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" 14a7dea167SDimitry Andric #include "Function.h" 15a7dea167SDimitry Andric #include "PrimType.h" 16a7dea167SDimitry Andric #include "Program.h" 17a7dea167SDimitry Andric #include "State.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. 28a7dea167SDimitry Andric template <class Emitter> class DeclScope final : public LocalScope<Emitter> { 29a7dea167SDimitry Andric public: 30a7dea167SDimitry Andric DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD) 31a7dea167SDimitry Andric : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {} 32a7dea167SDimitry Andric 33a7dea167SDimitry Andric void addExtended(const Scope::Local &Local) override { 34a7dea167SDimitry Andric return this->addLocal(Local); 35a7dea167SDimitry Andric } 36a7dea167SDimitry Andric 37a7dea167SDimitry Andric private: 38a7dea167SDimitry Andric Program::DeclScope Scope; 39a7dea167SDimitry Andric }; 40a7dea167SDimitry Andric 41a7dea167SDimitry Andric /// Scope used to handle initialization methods. 42a7dea167SDimitry Andric template <class Emitter> class OptionScope { 43a7dea167SDimitry Andric public: 44a7dea167SDimitry Andric /// Root constructor, compiling or discarding primitives. 45a7dea167SDimitry Andric OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult) 46bdd1243dSDimitry Andric : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult) { 47a7dea167SDimitry Andric Ctx->DiscardResult = NewDiscardResult; 48a7dea167SDimitry Andric } 49a7dea167SDimitry Andric 50bdd1243dSDimitry Andric ~OptionScope() { Ctx->DiscardResult = OldDiscardResult; } 51a7dea167SDimitry Andric 52a7dea167SDimitry Andric private: 53a7dea167SDimitry Andric /// Parent context. 54a7dea167SDimitry Andric ByteCodeExprGen<Emitter> *Ctx; 55a7dea167SDimitry Andric /// Old discard flag to restore. 56a7dea167SDimitry Andric bool OldDiscardResult; 57a7dea167SDimitry Andric }; 58a7dea167SDimitry Andric 59a7dea167SDimitry Andric } // namespace interp 60a7dea167SDimitry Andric } // namespace clang 61a7dea167SDimitry Andric 62a7dea167SDimitry Andric template <class Emitter> 63a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { 64a7dea167SDimitry Andric auto *SubExpr = CE->getSubExpr(); 65a7dea167SDimitry Andric switch (CE->getCastKind()) { 66a7dea167SDimitry Andric 67a7dea167SDimitry Andric case CK_LValueToRValue: { 68a7dea167SDimitry Andric return dereference( 69a7dea167SDimitry Andric CE->getSubExpr(), DerefKind::Read, 70a7dea167SDimitry Andric [](PrimType) { 71a7dea167SDimitry Andric // Value loaded - nothing to do here. 72a7dea167SDimitry Andric return true; 73a7dea167SDimitry Andric }, 74a7dea167SDimitry Andric [this, CE](PrimType T) { 75a7dea167SDimitry Andric // Pointer on stack - dereference it. 76a7dea167SDimitry Andric if (!this->emitLoadPop(T, CE)) 77a7dea167SDimitry Andric return false; 78a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, CE) : true; 79a7dea167SDimitry Andric }); 80a7dea167SDimitry Andric } 81a7dea167SDimitry Andric 82bdd1243dSDimitry Andric case CK_UncheckedDerivedToBase: 83bdd1243dSDimitry Andric case CK_DerivedToBase: { 84bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 85bdd1243dSDimitry Andric return false; 86bdd1243dSDimitry Andric 87bdd1243dSDimitry Andric const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr); 88bdd1243dSDimitry Andric assert(FromDecl); 89bdd1243dSDimitry Andric const CXXRecordDecl *ToDecl = getRecordDecl(CE); 90bdd1243dSDimitry Andric assert(ToDecl); 91bdd1243dSDimitry Andric const Record *R = getRecord(FromDecl); 92bdd1243dSDimitry Andric const Record::Base *ToBase = R->getBase(ToDecl); 93bdd1243dSDimitry Andric assert(ToBase); 94bdd1243dSDimitry Andric 95bdd1243dSDimitry Andric return this->emitGetPtrBase(ToBase->Offset, CE); 96bdd1243dSDimitry Andric } 97bdd1243dSDimitry Andric 98a7dea167SDimitry Andric case CK_ArrayToPointerDecay: 99a7dea167SDimitry Andric case CK_AtomicToNonAtomic: 100a7dea167SDimitry Andric case CK_ConstructorConversion: 101a7dea167SDimitry Andric case CK_FunctionToPointerDecay: 102a7dea167SDimitry Andric case CK_NonAtomicToAtomic: 103a7dea167SDimitry Andric case CK_NoOp: 104a7dea167SDimitry Andric case CK_UserDefinedConversion: 105bdd1243dSDimitry Andric case CK_NullToPointer: 106bdd1243dSDimitry Andric return this->visit(SubExpr); 107bdd1243dSDimitry Andric 108bdd1243dSDimitry Andric case CK_IntegralToBoolean: 109bdd1243dSDimitry Andric case CK_IntegralCast: { 110bdd1243dSDimitry Andric std::optional<PrimType> FromT = classify(SubExpr->getType()); 111bdd1243dSDimitry Andric std::optional<PrimType> ToT = classify(CE->getType()); 112bdd1243dSDimitry Andric if (!FromT || !ToT) 113bdd1243dSDimitry Andric return false; 114bdd1243dSDimitry Andric 115bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 116bdd1243dSDimitry Andric return false; 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric // TODO: Emit this only if FromT != ToT. 119bdd1243dSDimitry Andric return this->emitCast(*FromT, *ToT, CE); 120bdd1243dSDimitry Andric } 121a7dea167SDimitry Andric 122a7dea167SDimitry Andric case CK_ToVoid: 123a7dea167SDimitry Andric return discard(SubExpr); 124a7dea167SDimitry Andric 125bdd1243dSDimitry Andric default: 126bdd1243dSDimitry Andric assert(false && "Cast not implemented"); 127a7dea167SDimitry Andric } 128bdd1243dSDimitry Andric llvm_unreachable("Unhandled clang::CastKind enum"); 129a7dea167SDimitry Andric } 130a7dea167SDimitry Andric 131a7dea167SDimitry Andric template <class Emitter> 132a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) { 133a7dea167SDimitry Andric if (DiscardResult) 134a7dea167SDimitry Andric return true; 135a7dea167SDimitry Andric 136bdd1243dSDimitry Andric return this->emitConst(LE->getValue(), LE); 137a7dea167SDimitry Andric } 138a7dea167SDimitry Andric 139a7dea167SDimitry Andric template <class Emitter> 140a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) { 141bdd1243dSDimitry Andric return this->visit(PE->getSubExpr()); 142a7dea167SDimitry Andric } 143a7dea167SDimitry Andric 144a7dea167SDimitry Andric template <class Emitter> 145a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { 146a7dea167SDimitry Andric const Expr *LHS = BO->getLHS(); 147a7dea167SDimitry Andric const Expr *RHS = BO->getRHS(); 148a7dea167SDimitry Andric 149a7dea167SDimitry Andric // Deal with operations which have composite or void types. 150a7dea167SDimitry Andric switch (BO->getOpcode()) { 151a7dea167SDimitry Andric case BO_Comma: 152a7dea167SDimitry Andric if (!discard(LHS)) 153a7dea167SDimitry Andric return false; 154bdd1243dSDimitry Andric if (!this->visit(RHS)) 155a7dea167SDimitry Andric return false; 156a7dea167SDimitry Andric return true; 157a7dea167SDimitry Andric default: 158a7dea167SDimitry Andric break; 159a7dea167SDimitry Andric } 160a7dea167SDimitry Andric 161a7dea167SDimitry Andric // Typecheck the args. 162bdd1243dSDimitry Andric std::optional<PrimType> LT = classify(LHS->getType()); 163bdd1243dSDimitry Andric std::optional<PrimType> RT = classify(RHS->getType()); 164bdd1243dSDimitry Andric std::optional<PrimType> T = classify(BO->getType()); 165bdd1243dSDimitry Andric if (!LT || !RT || !T) { 166a7dea167SDimitry Andric return this->bail(BO); 167a7dea167SDimitry Andric } 168a7dea167SDimitry Andric 169a7dea167SDimitry Andric auto Discard = [this, T, BO](bool Result) { 170a7dea167SDimitry Andric if (!Result) 171a7dea167SDimitry Andric return false; 172a7dea167SDimitry Andric return DiscardResult ? this->emitPop(*T, BO) : true; 173a7dea167SDimitry Andric }; 174a7dea167SDimitry Andric 175bdd1243dSDimitry Andric // Pointer arithmetic special case. 176bdd1243dSDimitry Andric if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) { 177bdd1243dSDimitry Andric if (*T == PT_Ptr || (*LT == PT_Ptr && *RT == PT_Ptr)) 178bdd1243dSDimitry Andric return this->VisitPointerArithBinOp(BO); 179bdd1243dSDimitry Andric } 180bdd1243dSDimitry Andric 181bdd1243dSDimitry Andric if (!visit(LHS) || !visit(RHS)) 182bdd1243dSDimitry Andric return false; 183bdd1243dSDimitry Andric 184a7dea167SDimitry Andric switch (BO->getOpcode()) { 185a7dea167SDimitry Andric case BO_EQ: 186a7dea167SDimitry Andric return Discard(this->emitEQ(*LT, BO)); 187a7dea167SDimitry Andric case BO_NE: 188a7dea167SDimitry Andric return Discard(this->emitNE(*LT, BO)); 189a7dea167SDimitry Andric case BO_LT: 190a7dea167SDimitry Andric return Discard(this->emitLT(*LT, BO)); 191a7dea167SDimitry Andric case BO_LE: 192a7dea167SDimitry Andric return Discard(this->emitLE(*LT, BO)); 193a7dea167SDimitry Andric case BO_GT: 194a7dea167SDimitry Andric return Discard(this->emitGT(*LT, BO)); 195a7dea167SDimitry Andric case BO_GE: 196a7dea167SDimitry Andric return Discard(this->emitGE(*LT, BO)); 197a7dea167SDimitry Andric case BO_Sub: 198a7dea167SDimitry Andric return Discard(this->emitSub(*T, BO)); 199a7dea167SDimitry Andric case BO_Add: 200a7dea167SDimitry Andric return Discard(this->emitAdd(*T, BO)); 201a7dea167SDimitry Andric case BO_Mul: 202a7dea167SDimitry Andric return Discard(this->emitMul(*T, BO)); 203bdd1243dSDimitry Andric case BO_Rem: 204bdd1243dSDimitry Andric return Discard(this->emitRem(*T, BO)); 205bdd1243dSDimitry Andric case BO_Div: 206bdd1243dSDimitry Andric return Discard(this->emitDiv(*T, BO)); 207bdd1243dSDimitry Andric case BO_Assign: 208bdd1243dSDimitry Andric if (DiscardResult) 209bdd1243dSDimitry Andric return this->emitStorePop(*T, BO); 210bdd1243dSDimitry Andric return this->emitStore(*T, BO); 211bdd1243dSDimitry Andric case BO_And: 212bdd1243dSDimitry Andric return Discard(this->emitBitAnd(*T, BO)); 213bdd1243dSDimitry Andric case BO_Or: 214bdd1243dSDimitry Andric return Discard(this->emitBitOr(*T, BO)); 215bdd1243dSDimitry Andric case BO_Shl: 216bdd1243dSDimitry Andric return Discard(this->emitShl(*LT, *RT, BO)); 217bdd1243dSDimitry Andric case BO_Shr: 218bdd1243dSDimitry Andric return Discard(this->emitShr(*LT, *RT, BO)); 219bdd1243dSDimitry Andric case BO_Xor: 220bdd1243dSDimitry Andric return Discard(this->emitBitXor(*T, BO)); 221bdd1243dSDimitry Andric case BO_LAnd: 222bdd1243dSDimitry Andric case BO_LOr: 223a7dea167SDimitry Andric default: 224a7dea167SDimitry Andric return this->bail(BO); 225a7dea167SDimitry Andric } 226bdd1243dSDimitry Andric 227bdd1243dSDimitry Andric llvm_unreachable("Unhandled binary op"); 228a7dea167SDimitry Andric } 229a7dea167SDimitry Andric 230bdd1243dSDimitry Andric /// Perform addition/subtraction of a pointer and an integer or 231bdd1243dSDimitry Andric /// subtraction of two pointers. 232bdd1243dSDimitry Andric template <class Emitter> 233bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) { 234bdd1243dSDimitry Andric BinaryOperatorKind Op = E->getOpcode(); 235bdd1243dSDimitry Andric const Expr *LHS = E->getLHS(); 236bdd1243dSDimitry Andric const Expr *RHS = E->getRHS(); 237bdd1243dSDimitry Andric 238bdd1243dSDimitry Andric if ((Op != BO_Add && Op != BO_Sub) || 239bdd1243dSDimitry Andric (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType())) 240bdd1243dSDimitry Andric return false; 241bdd1243dSDimitry Andric 242bdd1243dSDimitry Andric std::optional<PrimType> LT = classify(LHS); 243bdd1243dSDimitry Andric std::optional<PrimType> RT = classify(RHS); 244bdd1243dSDimitry Andric 245bdd1243dSDimitry Andric if (!LT || !RT) 246bdd1243dSDimitry Andric return false; 247bdd1243dSDimitry Andric 248bdd1243dSDimitry Andric if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) { 249bdd1243dSDimitry Andric if (Op != BO_Sub) 250bdd1243dSDimitry Andric return false; 251bdd1243dSDimitry Andric 252bdd1243dSDimitry Andric assert(E->getType()->isIntegerType()); 253bdd1243dSDimitry Andric if (!visit(RHS) || !visit(LHS)) 254bdd1243dSDimitry Andric return false; 255bdd1243dSDimitry Andric 256bdd1243dSDimitry Andric return this->emitSubPtr(classifyPrim(E->getType()), E); 257bdd1243dSDimitry Andric } 258bdd1243dSDimitry Andric 259bdd1243dSDimitry Andric PrimType OffsetType; 260bdd1243dSDimitry Andric if (LHS->getType()->isIntegerType()) { 261bdd1243dSDimitry Andric if (!visit(RHS) || !visit(LHS)) 262bdd1243dSDimitry Andric return false; 263bdd1243dSDimitry Andric OffsetType = *LT; 264bdd1243dSDimitry Andric } else if (RHS->getType()->isIntegerType()) { 265bdd1243dSDimitry Andric if (!visit(LHS) || !visit(RHS)) 266bdd1243dSDimitry Andric return false; 267bdd1243dSDimitry Andric OffsetType = *RT; 268bdd1243dSDimitry Andric } else { 269bdd1243dSDimitry Andric return false; 270bdd1243dSDimitry Andric } 271bdd1243dSDimitry Andric 272bdd1243dSDimitry Andric if (Op == BO_Add) 273bdd1243dSDimitry Andric return this->emitAddOffset(OffsetType, E); 274bdd1243dSDimitry Andric else if (Op == BO_Sub) 275bdd1243dSDimitry Andric return this->emitSubOffset(OffsetType, E); 276bdd1243dSDimitry Andric 277bdd1243dSDimitry Andric return this->bail(E); 278a7dea167SDimitry Andric } 279a7dea167SDimitry Andric 280a7dea167SDimitry Andric template <class Emitter> 281bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { 282bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(E)) 283bdd1243dSDimitry Andric return this->emitZero(*T, E); 284bdd1243dSDimitry Andric 285bdd1243dSDimitry Andric return false; 286bdd1243dSDimitry Andric } 287bdd1243dSDimitry Andric 288bdd1243dSDimitry Andric template <class Emitter> 289bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr( 290bdd1243dSDimitry Andric const ArraySubscriptExpr *E) { 291bdd1243dSDimitry Andric const Expr *Base = E->getBase(); 292bdd1243dSDimitry Andric const Expr *Index = E->getIdx(); 293bdd1243dSDimitry Andric PrimType IndexT = classifyPrim(Index->getType()); 294bdd1243dSDimitry Andric 295bdd1243dSDimitry Andric // Take pointer of LHS, add offset from RHS, narrow result. 296bdd1243dSDimitry Andric // What's left on the stack after this is a pointer. 297bdd1243dSDimitry Andric if (!this->visit(Base)) 298bdd1243dSDimitry Andric return false; 299bdd1243dSDimitry Andric 300bdd1243dSDimitry Andric if (!this->visit(Index)) 301bdd1243dSDimitry Andric return false; 302bdd1243dSDimitry Andric 303bdd1243dSDimitry Andric if (!this->emitAddOffset(IndexT, E)) 304bdd1243dSDimitry Andric return false; 305bdd1243dSDimitry Andric 306bdd1243dSDimitry Andric if (!this->emitNarrowPtr(E)) 307bdd1243dSDimitry Andric return false; 308bdd1243dSDimitry Andric 309bdd1243dSDimitry Andric if (DiscardResult) 310bdd1243dSDimitry Andric return this->emitPopPtr(E); 311bdd1243dSDimitry Andric 312bdd1243dSDimitry Andric return true; 313bdd1243dSDimitry Andric } 314bdd1243dSDimitry Andric 315bdd1243dSDimitry Andric template <class Emitter> 316bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) { 317bdd1243dSDimitry Andric for (const Expr *Init : E->inits()) { 318bdd1243dSDimitry Andric if (!this->visit(Init)) 319bdd1243dSDimitry Andric return false; 320bdd1243dSDimitry Andric } 321bdd1243dSDimitry Andric return true; 322bdd1243dSDimitry Andric } 323bdd1243dSDimitry Andric 324bdd1243dSDimitry Andric template <class Emitter> 325bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr( 326bdd1243dSDimitry Andric const SubstNonTypeTemplateParmExpr *E) { 327bdd1243dSDimitry Andric return this->visit(E->getReplacement()); 328bdd1243dSDimitry Andric } 329bdd1243dSDimitry Andric 330bdd1243dSDimitry Andric template <class Emitter> 331bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) { 332bdd1243dSDimitry Andric // TODO: Check if the ConstantExpr already has a value set and if so, 333bdd1243dSDimitry Andric // use that instead of evaluating it again. 334bdd1243dSDimitry Andric return this->visit(E->getSubExpr()); 335bdd1243dSDimitry Andric } 336bdd1243dSDimitry Andric 337bdd1243dSDimitry Andric static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, 338bdd1243dSDimitry Andric UnaryExprOrTypeTrait Kind) { 339bdd1243dSDimitry Andric bool AlignOfReturnsPreferred = 340bdd1243dSDimitry Andric ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; 341bdd1243dSDimitry Andric 342bdd1243dSDimitry Andric // C++ [expr.alignof]p3: 343bdd1243dSDimitry Andric // When alignof is applied to a reference type, the result is the 344bdd1243dSDimitry Andric // alignment of the referenced type. 345bdd1243dSDimitry Andric if (const auto *Ref = T->getAs<ReferenceType>()) 346bdd1243dSDimitry Andric T = Ref->getPointeeType(); 347bdd1243dSDimitry Andric 348bdd1243dSDimitry Andric // __alignof is defined to return the preferred alignment. 349bdd1243dSDimitry Andric // Before 8, clang returned the preferred alignment for alignof and 350bdd1243dSDimitry Andric // _Alignof as well. 351bdd1243dSDimitry Andric if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred) 352bdd1243dSDimitry Andric return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T)); 353bdd1243dSDimitry Andric 354bdd1243dSDimitry Andric return ASTCtx.getTypeAlignInChars(T); 355bdd1243dSDimitry Andric } 356bdd1243dSDimitry Andric 357bdd1243dSDimitry Andric template <class Emitter> 358bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr( 359bdd1243dSDimitry Andric const UnaryExprOrTypeTraitExpr *E) { 360bdd1243dSDimitry Andric UnaryExprOrTypeTrait Kind = E->getKind(); 361bdd1243dSDimitry Andric ASTContext &ASTCtx = Ctx.getASTContext(); 362bdd1243dSDimitry Andric 363bdd1243dSDimitry Andric if (Kind == UETT_SizeOf) { 364bdd1243dSDimitry Andric QualType ArgType = E->getTypeOfArgument(); 365bdd1243dSDimitry Andric CharUnits Size; 366bdd1243dSDimitry Andric if (ArgType->isVoidType() || ArgType->isFunctionType()) 367bdd1243dSDimitry Andric Size = CharUnits::One(); 368bdd1243dSDimitry Andric else { 369bdd1243dSDimitry Andric if (ArgType->isDependentType() || !ArgType->isConstantSizeType()) 370bdd1243dSDimitry Andric return false; 371bdd1243dSDimitry Andric 372bdd1243dSDimitry Andric Size = ASTCtx.getTypeSizeInChars(ArgType); 373bdd1243dSDimitry Andric } 374bdd1243dSDimitry Andric 375bdd1243dSDimitry Andric return this->emitConst(Size.getQuantity(), E); 376bdd1243dSDimitry Andric } 377bdd1243dSDimitry Andric 378bdd1243dSDimitry Andric if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) { 379bdd1243dSDimitry Andric CharUnits Size; 380bdd1243dSDimitry Andric 381bdd1243dSDimitry Andric if (E->isArgumentType()) { 382bdd1243dSDimitry Andric QualType ArgType = E->getTypeOfArgument(); 383bdd1243dSDimitry Andric 384bdd1243dSDimitry Andric Size = AlignOfType(ArgType, ASTCtx, Kind); 385bdd1243dSDimitry Andric } else { 386bdd1243dSDimitry Andric // Argument is an expression, not a type. 387bdd1243dSDimitry Andric const Expr *Arg = E->getArgumentExpr()->IgnoreParens(); 388bdd1243dSDimitry Andric 389bdd1243dSDimitry Andric // The kinds of expressions that we have special-case logic here for 390bdd1243dSDimitry Andric // should be kept up to date with the special checks for those 391bdd1243dSDimitry Andric // expressions in Sema. 392bdd1243dSDimitry Andric 393bdd1243dSDimitry Andric // alignof decl is always accepted, even if it doesn't make sense: we 394bdd1243dSDimitry Andric // default to 1 in those cases. 395bdd1243dSDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg)) 396bdd1243dSDimitry Andric Size = ASTCtx.getDeclAlign(DRE->getDecl(), 397bdd1243dSDimitry Andric /*RefAsPointee*/ true); 398bdd1243dSDimitry Andric else if (const auto *ME = dyn_cast<MemberExpr>(Arg)) 399bdd1243dSDimitry Andric Size = ASTCtx.getDeclAlign(ME->getMemberDecl(), 400bdd1243dSDimitry Andric /*RefAsPointee*/ true); 401bdd1243dSDimitry Andric else 402bdd1243dSDimitry Andric Size = AlignOfType(Arg->getType(), ASTCtx, Kind); 403bdd1243dSDimitry Andric } 404bdd1243dSDimitry Andric 405bdd1243dSDimitry Andric return this->emitConst(Size.getQuantity(), E); 406bdd1243dSDimitry Andric } 407bdd1243dSDimitry Andric 408bdd1243dSDimitry Andric return false; 409bdd1243dSDimitry Andric } 410bdd1243dSDimitry Andric 411bdd1243dSDimitry Andric template <class Emitter> 412bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) { 413bdd1243dSDimitry Andric if (DiscardResult) 414bdd1243dSDimitry Andric return true; 415bdd1243dSDimitry Andric 416bdd1243dSDimitry Andric // 'Base.Member' 417bdd1243dSDimitry Andric const Expr *Base = E->getBase(); 418bdd1243dSDimitry Andric const ValueDecl *Member = E->getMemberDecl(); 419bdd1243dSDimitry Andric 420bdd1243dSDimitry Andric if (!this->visit(Base)) 421bdd1243dSDimitry Andric return false; 422bdd1243dSDimitry Andric 423bdd1243dSDimitry Andric // Base above gives us a pointer on the stack. 424bdd1243dSDimitry Andric // TODO: Implement non-FieldDecl members. 425bdd1243dSDimitry Andric if (const auto *FD = dyn_cast<FieldDecl>(Member)) { 426bdd1243dSDimitry Andric const RecordDecl *RD = FD->getParent(); 427bdd1243dSDimitry Andric const Record *R = getRecord(RD); 428bdd1243dSDimitry Andric const Record::Field *F = R->getField(FD); 429bdd1243dSDimitry Andric // Leave a pointer to the field on the stack. 430bdd1243dSDimitry Andric if (F->Decl->getType()->isReferenceType()) 431bdd1243dSDimitry Andric return this->emitGetFieldPop(PT_Ptr, F->Offset, E); 432bdd1243dSDimitry Andric return this->emitGetPtrField(F->Offset, E); 433bdd1243dSDimitry Andric } 434bdd1243dSDimitry Andric 435bdd1243dSDimitry Andric return false; 436bdd1243dSDimitry Andric } 437bdd1243dSDimitry Andric 438bdd1243dSDimitry Andric template <class Emitter> 439bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr( 440bdd1243dSDimitry Andric const ArrayInitIndexExpr *E) { 441bdd1243dSDimitry Andric // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated 442bdd1243dSDimitry Andric // stand-alone, e.g. via EvaluateAsInt(). 443bdd1243dSDimitry Andric if (!ArrayIndex) 444bdd1243dSDimitry Andric return false; 445bdd1243dSDimitry Andric return this->emitConst(*ArrayIndex, E); 446bdd1243dSDimitry Andric } 447bdd1243dSDimitry Andric 448bdd1243dSDimitry Andric template <class Emitter> 449bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) { 450bdd1243dSDimitry Andric return this->visit(E->getSourceExpr()); 451bdd1243dSDimitry Andric } 452bdd1243dSDimitry Andric 453bdd1243dSDimitry Andric template <class Emitter> 454bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator( 455bdd1243dSDimitry Andric const AbstractConditionalOperator *E) { 456bdd1243dSDimitry Andric const Expr *Condition = E->getCond(); 457bdd1243dSDimitry Andric const Expr *TrueExpr = E->getTrueExpr(); 458bdd1243dSDimitry Andric const Expr *FalseExpr = E->getFalseExpr(); 459bdd1243dSDimitry Andric 460bdd1243dSDimitry Andric LabelTy LabelEnd = this->getLabel(); // Label after the operator. 461bdd1243dSDimitry Andric LabelTy LabelFalse = this->getLabel(); // Label for the false expr. 462bdd1243dSDimitry Andric 463bdd1243dSDimitry Andric if (!this->visit(Condition)) 464bdd1243dSDimitry Andric return false; 465bdd1243dSDimitry Andric if (!this->jumpFalse(LabelFalse)) 466bdd1243dSDimitry Andric return false; 467bdd1243dSDimitry Andric 468bdd1243dSDimitry Andric if (!this->visit(TrueExpr)) 469bdd1243dSDimitry Andric return false; 470bdd1243dSDimitry Andric if (!this->jump(LabelEnd)) 471bdd1243dSDimitry Andric return false; 472bdd1243dSDimitry Andric 473bdd1243dSDimitry Andric this->emitLabel(LabelFalse); 474bdd1243dSDimitry Andric 475bdd1243dSDimitry Andric if (!this->visit(FalseExpr)) 476bdd1243dSDimitry Andric return false; 477bdd1243dSDimitry Andric 478bdd1243dSDimitry Andric this->fallthrough(LabelEnd); 479bdd1243dSDimitry Andric this->emitLabel(LabelEnd); 480bdd1243dSDimitry Andric 481bdd1243dSDimitry Andric return true; 482bdd1243dSDimitry Andric } 483bdd1243dSDimitry Andric 484bdd1243dSDimitry Andric template <class Emitter> 485bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) { 486bdd1243dSDimitry Andric unsigned StringIndex = P.createGlobalString(E); 487bdd1243dSDimitry Andric return this->emitGetPtrGlobal(StringIndex, E); 488bdd1243dSDimitry Andric } 489bdd1243dSDimitry Andric 490bdd1243dSDimitry Andric template <class Emitter> 491bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral( 492bdd1243dSDimitry Andric const CharacterLiteral *E) { 493bdd1243dSDimitry Andric return this->emitConst(E->getValue(), E); 494bdd1243dSDimitry Andric } 495bdd1243dSDimitry Andric 496bdd1243dSDimitry Andric template <class Emitter> 497bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( 498bdd1243dSDimitry Andric const CompoundAssignOperator *E) { 499bdd1243dSDimitry Andric const Expr *LHS = E->getLHS(); 500bdd1243dSDimitry Andric const Expr *RHS = E->getRHS(); 501bdd1243dSDimitry Andric std::optional<PrimType> LT = classify(E->getLHS()->getType()); 502bdd1243dSDimitry Andric std::optional<PrimType> RT = classify(E->getRHS()->getType()); 503bdd1243dSDimitry Andric 504bdd1243dSDimitry Andric if (!LT || !RT) 505bdd1243dSDimitry Andric return false; 506bdd1243dSDimitry Andric 507bdd1243dSDimitry Andric assert(!E->getType()->isPointerType() && 508bdd1243dSDimitry Andric "Support pointer arithmethic in compound assignment operators"); 509bdd1243dSDimitry Andric 510bdd1243dSDimitry Andric // Get LHS pointer, load its value and get RHS value. 511bdd1243dSDimitry Andric if (!visit(LHS)) 512bdd1243dSDimitry Andric return false; 513bdd1243dSDimitry Andric if (!this->emitLoad(*LT, E)) 514bdd1243dSDimitry Andric return false; 515bdd1243dSDimitry Andric if (!visit(RHS)) 516bdd1243dSDimitry Andric return false; 517bdd1243dSDimitry Andric 518bdd1243dSDimitry Andric // Perform operation. 519bdd1243dSDimitry Andric switch (E->getOpcode()) { 520bdd1243dSDimitry Andric case BO_AddAssign: 521bdd1243dSDimitry Andric if (!this->emitAdd(*LT, E)) 522bdd1243dSDimitry Andric return false; 523bdd1243dSDimitry Andric break; 524bdd1243dSDimitry Andric case BO_SubAssign: 525bdd1243dSDimitry Andric if (!this->emitSub(*LT, E)) 526bdd1243dSDimitry Andric return false; 527bdd1243dSDimitry Andric break; 528bdd1243dSDimitry Andric 529bdd1243dSDimitry Andric case BO_MulAssign: 530bdd1243dSDimitry Andric case BO_DivAssign: 531bdd1243dSDimitry Andric case BO_RemAssign: 532bdd1243dSDimitry Andric case BO_ShlAssign: 533bdd1243dSDimitry Andric if (!this->emitShl(*LT, *RT, E)) 534bdd1243dSDimitry Andric return false; 535bdd1243dSDimitry Andric break; 536bdd1243dSDimitry Andric case BO_ShrAssign: 537bdd1243dSDimitry Andric if (!this->emitShr(*LT, *RT, E)) 538bdd1243dSDimitry Andric return false; 539bdd1243dSDimitry Andric break; 540bdd1243dSDimitry Andric case BO_AndAssign: 541bdd1243dSDimitry Andric case BO_XorAssign: 542bdd1243dSDimitry Andric case BO_OrAssign: 543bdd1243dSDimitry Andric default: 544bdd1243dSDimitry Andric llvm_unreachable("Unimplemented compound assign operator"); 545bdd1243dSDimitry Andric } 546bdd1243dSDimitry Andric 547bdd1243dSDimitry Andric // And store the result in LHS. 548bdd1243dSDimitry Andric if (DiscardResult) 549bdd1243dSDimitry Andric return this->emitStorePop(*LT, E); 550bdd1243dSDimitry Andric return this->emitStore(*LT, E); 551bdd1243dSDimitry Andric } 552bdd1243dSDimitry Andric 553bdd1243dSDimitry Andric template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) { 55404eeddc0SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true); 555a7dea167SDimitry Andric return this->Visit(E); 556a7dea167SDimitry Andric } 557a7dea167SDimitry Andric 558a7dea167SDimitry Andric template <class Emitter> 559a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visit(const Expr *E) { 56004eeddc0SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false); 561a7dea167SDimitry Andric return this->Visit(E); 562a7dea167SDimitry Andric } 563a7dea167SDimitry Andric 564a7dea167SDimitry Andric template <class Emitter> 565a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) { 566bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(E->getType())) { 567a7dea167SDimitry Andric return visit(E); 568a7dea167SDimitry Andric } else { 569a7dea167SDimitry Andric return this->bail(E); 570a7dea167SDimitry Andric } 571a7dea167SDimitry Andric } 572a7dea167SDimitry Andric 573a7dea167SDimitry Andric template <class Emitter> 574a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, const Expr *E) { 575a7dea167SDimitry Andric switch (T) { 576a7dea167SDimitry Andric case PT_Bool: 577a7dea167SDimitry Andric return this->emitZeroBool(E); 578a7dea167SDimitry Andric case PT_Sint8: 579a7dea167SDimitry Andric return this->emitZeroSint8(E); 580a7dea167SDimitry Andric case PT_Uint8: 581a7dea167SDimitry Andric return this->emitZeroUint8(E); 582a7dea167SDimitry Andric case PT_Sint16: 583a7dea167SDimitry Andric return this->emitZeroSint16(E); 584a7dea167SDimitry Andric case PT_Uint16: 585a7dea167SDimitry Andric return this->emitZeroUint16(E); 586a7dea167SDimitry Andric case PT_Sint32: 587a7dea167SDimitry Andric return this->emitZeroSint32(E); 588a7dea167SDimitry Andric case PT_Uint32: 589a7dea167SDimitry Andric return this->emitZeroUint32(E); 590a7dea167SDimitry Andric case PT_Sint64: 591a7dea167SDimitry Andric return this->emitZeroSint64(E); 592a7dea167SDimitry Andric case PT_Uint64: 593a7dea167SDimitry Andric return this->emitZeroUint64(E); 594a7dea167SDimitry Andric case PT_Ptr: 595a7dea167SDimitry Andric return this->emitNullPtr(E); 596a7dea167SDimitry Andric } 597a7dea167SDimitry Andric llvm_unreachable("unknown primitive type"); 598a7dea167SDimitry Andric } 599a7dea167SDimitry Andric 600a7dea167SDimitry Andric template <class Emitter> 601a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereference( 602a7dea167SDimitry Andric const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, 603a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 604bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(LV->getType())) { 605a7dea167SDimitry Andric if (!LV->refersToBitField()) { 606a7dea167SDimitry Andric // Only primitive, non bit-field types can be dereferenced directly. 607a7dea167SDimitry Andric if (auto *DE = dyn_cast<DeclRefExpr>(LV)) { 608a7dea167SDimitry Andric if (!DE->getDecl()->getType()->isReferenceType()) { 609a7dea167SDimitry Andric if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) 610a7dea167SDimitry Andric return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); 611a7dea167SDimitry Andric if (auto *VD = dyn_cast<VarDecl>(DE->getDecl())) 612a7dea167SDimitry Andric return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); 613a7dea167SDimitry Andric } 614a7dea167SDimitry Andric } 615a7dea167SDimitry Andric } 616a7dea167SDimitry Andric 617a7dea167SDimitry Andric if (!visit(LV)) 618a7dea167SDimitry Andric return false; 619a7dea167SDimitry Andric return Indirect(*T); 620a7dea167SDimitry Andric } 621a7dea167SDimitry Andric 622a7dea167SDimitry Andric return false; 623a7dea167SDimitry Andric } 624a7dea167SDimitry Andric 625a7dea167SDimitry Andric template <class Emitter> 626a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceParam( 627a7dea167SDimitry Andric const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, 628a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Direct, 629a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 630a7dea167SDimitry Andric auto It = this->Params.find(PD); 631a7dea167SDimitry Andric if (It != this->Params.end()) { 632a7dea167SDimitry Andric unsigned Idx = It->second; 633a7dea167SDimitry Andric switch (AK) { 634a7dea167SDimitry Andric case DerefKind::Read: 635a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetParam(T, Idx, LV); 636a7dea167SDimitry Andric 637a7dea167SDimitry Andric case DerefKind::Write: 638a7dea167SDimitry Andric if (!Direct(T)) 639a7dea167SDimitry Andric return false; 640a7dea167SDimitry Andric if (!this->emitSetParam(T, Idx, LV)) 641a7dea167SDimitry Andric return false; 642a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 643a7dea167SDimitry Andric 644a7dea167SDimitry Andric case DerefKind::ReadWrite: 645a7dea167SDimitry Andric if (!this->emitGetParam(T, Idx, LV)) 646a7dea167SDimitry Andric return false; 647a7dea167SDimitry Andric if (!Direct(T)) 648a7dea167SDimitry Andric return false; 649a7dea167SDimitry Andric if (!this->emitSetParam(T, Idx, LV)) 650a7dea167SDimitry Andric return false; 651a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 652a7dea167SDimitry Andric } 653a7dea167SDimitry Andric return true; 654a7dea167SDimitry Andric } 655a7dea167SDimitry Andric 656a7dea167SDimitry Andric // If the param is a pointer, we can dereference a dummy value. 657a7dea167SDimitry Andric if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) { 658a7dea167SDimitry Andric if (auto Idx = P.getOrCreateDummy(PD)) 659a7dea167SDimitry Andric return this->emitGetPtrGlobal(*Idx, PD); 660a7dea167SDimitry Andric return false; 661a7dea167SDimitry Andric } 662a7dea167SDimitry Andric 663a7dea167SDimitry Andric // Value cannot be produced - try to emit pointer and do stuff with it. 664a7dea167SDimitry Andric return visit(LV) && Indirect(T); 665a7dea167SDimitry Andric } 666a7dea167SDimitry Andric 667a7dea167SDimitry Andric template <class Emitter> 668a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceVar( 669a7dea167SDimitry Andric const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK, 670a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Direct, 671a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 672a7dea167SDimitry Andric auto It = Locals.find(VD); 673a7dea167SDimitry Andric if (It != Locals.end()) { 674a7dea167SDimitry Andric const auto &L = It->second; 675a7dea167SDimitry Andric switch (AK) { 676a7dea167SDimitry Andric case DerefKind::Read: 677a7dea167SDimitry Andric if (!this->emitGetLocal(T, L.Offset, LV)) 678a7dea167SDimitry Andric return false; 679a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, LV) : true; 680a7dea167SDimitry Andric 681a7dea167SDimitry Andric case DerefKind::Write: 682a7dea167SDimitry Andric if (!Direct(T)) 683a7dea167SDimitry Andric return false; 684a7dea167SDimitry Andric if (!this->emitSetLocal(T, L.Offset, LV)) 685a7dea167SDimitry Andric return false; 686a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 687a7dea167SDimitry Andric 688a7dea167SDimitry Andric case DerefKind::ReadWrite: 689a7dea167SDimitry Andric if (!this->emitGetLocal(T, L.Offset, LV)) 690a7dea167SDimitry Andric return false; 691a7dea167SDimitry Andric if (!Direct(T)) 692a7dea167SDimitry Andric return false; 693a7dea167SDimitry Andric if (!this->emitSetLocal(T, L.Offset, LV)) 694a7dea167SDimitry Andric return false; 695a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 696a7dea167SDimitry Andric } 697bdd1243dSDimitry Andric } else if (auto Idx = P.getGlobal(VD)) { 698a7dea167SDimitry Andric switch (AK) { 699a7dea167SDimitry Andric case DerefKind::Read: 700a7dea167SDimitry Andric if (!this->emitGetGlobal(T, *Idx, LV)) 701a7dea167SDimitry Andric return false; 702a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, LV) : true; 703a7dea167SDimitry Andric 704a7dea167SDimitry Andric case DerefKind::Write: 705a7dea167SDimitry Andric if (!Direct(T)) 706a7dea167SDimitry Andric return false; 707a7dea167SDimitry Andric if (!this->emitSetGlobal(T, *Idx, LV)) 708a7dea167SDimitry Andric return false; 709a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 710a7dea167SDimitry Andric 711a7dea167SDimitry Andric case DerefKind::ReadWrite: 712a7dea167SDimitry Andric if (!this->emitGetGlobal(T, *Idx, LV)) 713a7dea167SDimitry Andric return false; 714a7dea167SDimitry Andric if (!Direct(T)) 715a7dea167SDimitry Andric return false; 716a7dea167SDimitry Andric if (!this->emitSetGlobal(T, *Idx, LV)) 717a7dea167SDimitry Andric return false; 718a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 719a7dea167SDimitry Andric } 720a7dea167SDimitry Andric } 721a7dea167SDimitry Andric 722a7dea167SDimitry Andric // If the declaration is a constant value, emit it here even 723a7dea167SDimitry Andric // though the declaration was not evaluated in the current scope. 724a7dea167SDimitry Andric // The access mode can only be read in this case. 725a7dea167SDimitry Andric if (!DiscardResult && AK == DerefKind::Read) { 726a7dea167SDimitry Andric if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) { 727a7dea167SDimitry Andric QualType VT = VD->getType(); 728a7dea167SDimitry Andric if (VT.isConstQualified() && VT->isFundamentalType()) 729bdd1243dSDimitry Andric return this->visit(VD->getInit()); 730a7dea167SDimitry Andric } 731a7dea167SDimitry Andric } 732a7dea167SDimitry Andric 733a7dea167SDimitry Andric // Value cannot be produced - try to emit pointer. 734a7dea167SDimitry Andric return visit(LV) && Indirect(T); 735a7dea167SDimitry Andric } 736a7dea167SDimitry Andric 737a7dea167SDimitry Andric template <class Emitter> 738bdd1243dSDimitry Andric template <typename T> 739bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) { 740bdd1243dSDimitry Andric switch (classifyPrim(E->getType())) { 741a7dea167SDimitry Andric case PT_Sint8: 742bdd1243dSDimitry Andric return this->emitConstSint8(Value, E); 743a7dea167SDimitry Andric case PT_Uint8: 744bdd1243dSDimitry Andric return this->emitConstUint8(Value, E); 745a7dea167SDimitry Andric case PT_Sint16: 746bdd1243dSDimitry Andric return this->emitConstSint16(Value, E); 747a7dea167SDimitry Andric case PT_Uint16: 748bdd1243dSDimitry Andric return this->emitConstUint16(Value, E); 749a7dea167SDimitry Andric case PT_Sint32: 750bdd1243dSDimitry Andric return this->emitConstSint32(Value, E); 751a7dea167SDimitry Andric case PT_Uint32: 752bdd1243dSDimitry Andric return this->emitConstUint32(Value, E); 753a7dea167SDimitry Andric case PT_Sint64: 754bdd1243dSDimitry Andric return this->emitConstSint64(Value, E); 755a7dea167SDimitry Andric case PT_Uint64: 756bdd1243dSDimitry Andric return this->emitConstUint64(Value, E); 757a7dea167SDimitry Andric case PT_Bool: 758bdd1243dSDimitry Andric return this->emitConstBool(Value, E); 759a7dea167SDimitry Andric case PT_Ptr: 760a7dea167SDimitry Andric llvm_unreachable("Invalid integral type"); 761a7dea167SDimitry Andric break; 762a7dea167SDimitry Andric } 763a7dea167SDimitry Andric llvm_unreachable("unknown primitive type"); 764a7dea167SDimitry Andric } 765a7dea167SDimitry Andric 766a7dea167SDimitry Andric template <class Emitter> 767bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) { 768bdd1243dSDimitry Andric if (Value.isSigned()) 769bdd1243dSDimitry Andric return this->emitConst(Value.getSExtValue(), E); 770bdd1243dSDimitry Andric return this->emitConst(Value.getZExtValue(), E); 771bdd1243dSDimitry Andric } 772bdd1243dSDimitry Andric 773bdd1243dSDimitry Andric template <class Emitter> 774a7dea167SDimitry Andric unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src, 775a7dea167SDimitry Andric PrimType Ty, 776a7dea167SDimitry Andric bool IsConst, 777a7dea167SDimitry Andric bool IsExtended) { 778bdd1243dSDimitry Andric // Make sure we don't accidentally register the same decl twice. 779bdd1243dSDimitry Andric if (const auto *VD = 780bdd1243dSDimitry Andric dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 781bdd1243dSDimitry Andric assert(!P.getGlobal(VD)); 782bdd1243dSDimitry Andric assert(Locals.find(VD) == Locals.end()); 783bdd1243dSDimitry Andric } 784bdd1243dSDimitry Andric 785bdd1243dSDimitry Andric // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g. 786bdd1243dSDimitry Andric // (int){12} in C. Consider using Expr::isTemporaryObject() instead 787bdd1243dSDimitry Andric // or isa<MaterializeTemporaryExpr>(). 788bdd1243dSDimitry Andric Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst, 789bdd1243dSDimitry Andric Src.is<const Expr *>()); 790a7dea167SDimitry Andric Scope::Local Local = this->createLocal(D); 791a7dea167SDimitry Andric if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) 792a7dea167SDimitry Andric Locals.insert({VD, Local}); 793a7dea167SDimitry Andric VarScope->add(Local, IsExtended); 794a7dea167SDimitry Andric return Local.Offset; 795a7dea167SDimitry Andric } 796a7dea167SDimitry Andric 797a7dea167SDimitry Andric template <class Emitter> 798bdd1243dSDimitry Andric std::optional<unsigned> 799a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) { 800bdd1243dSDimitry Andric // Make sure we don't accidentally register the same decl twice. 801bdd1243dSDimitry Andric if (const auto *VD = 802bdd1243dSDimitry Andric dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 803bdd1243dSDimitry Andric assert(!P.getGlobal(VD)); 804bdd1243dSDimitry Andric assert(Locals.find(VD) == Locals.end()); 805bdd1243dSDimitry Andric } 806a7dea167SDimitry Andric 807bdd1243dSDimitry Andric QualType Ty; 808a7dea167SDimitry Andric const ValueDecl *Key = nullptr; 809bdd1243dSDimitry Andric const Expr *Init = nullptr; 810a7dea167SDimitry Andric bool IsTemporary = false; 811bdd1243dSDimitry Andric if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 812a7dea167SDimitry Andric Key = VD; 813a7dea167SDimitry Andric Ty = VD->getType(); 814bdd1243dSDimitry Andric 815bdd1243dSDimitry Andric if (const auto *VarD = dyn_cast<VarDecl>(VD)) 816bdd1243dSDimitry Andric Init = VarD->getInit(); 817a7dea167SDimitry Andric } 818a7dea167SDimitry Andric if (auto *E = Src.dyn_cast<const Expr *>()) { 819a7dea167SDimitry Andric IsTemporary = true; 820a7dea167SDimitry Andric Ty = E->getType(); 821a7dea167SDimitry Andric } 822a7dea167SDimitry Andric 823bdd1243dSDimitry Andric Descriptor *D = P.createDescriptor( 824bdd1243dSDimitry Andric Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(), 825bdd1243dSDimitry Andric IsTemporary, /*IsMutable=*/false, Init); 826a7dea167SDimitry Andric if (!D) 827a7dea167SDimitry Andric return {}; 828a7dea167SDimitry Andric 829a7dea167SDimitry Andric Scope::Local Local = this->createLocal(D); 830a7dea167SDimitry Andric if (Key) 831a7dea167SDimitry Andric Locals.insert({Key, Local}); 832a7dea167SDimitry Andric VarScope->add(Local, IsExtended); 833a7dea167SDimitry Andric return Local.Offset; 834a7dea167SDimitry Andric } 835a7dea167SDimitry Andric 836bdd1243dSDimitry Andric // NB: When calling this function, we have a pointer to the 837bdd1243dSDimitry Andric // array-to-initialize on the stack. 838a7dea167SDimitry Andric template <class Emitter> 839bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitArrayInitializer(const Expr *Initializer) { 840bdd1243dSDimitry Andric assert(Initializer->getType()->isArrayType()); 841bdd1243dSDimitry Andric 842bdd1243dSDimitry Andric // TODO: Fillers? 843bdd1243dSDimitry Andric if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) { 844bdd1243dSDimitry Andric unsigned ElementIndex = 0; 845bdd1243dSDimitry Andric for (const Expr *Init : InitList->inits()) { 846bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(Init->getType())) { 847bdd1243dSDimitry Andric // Visit the primitive element like normal. 848bdd1243dSDimitry Andric if (!this->emitDupPtr(Init)) 849bdd1243dSDimitry Andric return false; 850bdd1243dSDimitry Andric if (!this->visit(Init)) 851bdd1243dSDimitry Andric return false; 852bdd1243dSDimitry Andric if (!this->emitInitElem(*T, ElementIndex, Init)) 853bdd1243dSDimitry Andric return false; 854bdd1243dSDimitry Andric } else { 855bdd1243dSDimitry Andric // Advance the pointer currently on the stack to the given 856bdd1243dSDimitry Andric // dimension and narrow(). 857bdd1243dSDimitry Andric if (!this->emitDupPtr(Init)) 858bdd1243dSDimitry Andric return false; 859bdd1243dSDimitry Andric if (!this->emitConstUint32(ElementIndex, Init)) 860bdd1243dSDimitry Andric return false; 861bdd1243dSDimitry Andric if (!this->emitAddOffsetUint32(Init)) 862bdd1243dSDimitry Andric return false; 863bdd1243dSDimitry Andric if (!this->emitNarrowPtr(Init)) 864bdd1243dSDimitry Andric return false; 865bdd1243dSDimitry Andric 866bdd1243dSDimitry Andric if (!visitInitializer(Init)) 867bdd1243dSDimitry Andric return false; 868bdd1243dSDimitry Andric } 869bdd1243dSDimitry Andric if (!this->emitPopPtr(Init)) 870bdd1243dSDimitry Andric return false; 871bdd1243dSDimitry Andric 872bdd1243dSDimitry Andric ++ElementIndex; 873bdd1243dSDimitry Andric } 874bdd1243dSDimitry Andric return true; 875bdd1243dSDimitry Andric } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) { 876bdd1243dSDimitry Andric return this->visitInitializer(DIE->getExpr()); 877bdd1243dSDimitry Andric } else if (const auto *AILE = dyn_cast<ArrayInitLoopExpr>(Initializer)) { 878bdd1243dSDimitry Andric // TODO: This compiles to quite a lot of bytecode if the array is larger. 879bdd1243dSDimitry Andric // Investigate compiling this to a loop, or at least try to use 880bdd1243dSDimitry Andric // the AILE's Common expr. 881bdd1243dSDimitry Andric const Expr *SubExpr = AILE->getSubExpr(); 882bdd1243dSDimitry Andric size_t Size = AILE->getArraySize().getZExtValue(); 883bdd1243dSDimitry Andric std::optional<PrimType> ElemT = classify(SubExpr->getType()); 884bdd1243dSDimitry Andric 885bdd1243dSDimitry Andric // So, every iteration, we execute an assignment here 886bdd1243dSDimitry Andric // where the LHS is on the stack (the target array) 887bdd1243dSDimitry Andric // and the RHS is our SubExpr. 888bdd1243dSDimitry Andric for (size_t I = 0; I != Size; ++I) { 889bdd1243dSDimitry Andric ArrayIndexScope<Emitter> IndexScope(this, I); 890bdd1243dSDimitry Andric 891bdd1243dSDimitry Andric if (!this->emitDupPtr(SubExpr)) // LHS 892bdd1243dSDimitry Andric return false; 893bdd1243dSDimitry Andric 894bdd1243dSDimitry Andric if (ElemT) { 895bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 896bdd1243dSDimitry Andric return false; 897bdd1243dSDimitry Andric if (!this->emitInitElem(*ElemT, I, Initializer)) 898bdd1243dSDimitry Andric return false; 899bdd1243dSDimitry Andric } else { 900bdd1243dSDimitry Andric // Narrow to our array element and recurse into visitInitializer() 901bdd1243dSDimitry Andric if (!this->emitConstUint64(I, SubExpr)) 902bdd1243dSDimitry Andric return false; 903bdd1243dSDimitry Andric 904bdd1243dSDimitry Andric if (!this->emitAddOffsetUint64(SubExpr)) 905bdd1243dSDimitry Andric return false; 906bdd1243dSDimitry Andric 907bdd1243dSDimitry Andric if (!this->emitNarrowPtr(SubExpr)) 908bdd1243dSDimitry Andric return false; 909bdd1243dSDimitry Andric 910bdd1243dSDimitry Andric if (!visitInitializer(SubExpr)) 911bdd1243dSDimitry Andric return false; 912bdd1243dSDimitry Andric } 913bdd1243dSDimitry Andric 914bdd1243dSDimitry Andric if (!this->emitPopPtr(Initializer)) 915bdd1243dSDimitry Andric return false; 916bdd1243dSDimitry Andric } 917bdd1243dSDimitry Andric return true; 918bdd1243dSDimitry Andric } else if (const auto *IVIE = dyn_cast<ImplicitValueInitExpr>(Initializer)) { 919bdd1243dSDimitry Andric const ArrayType *AT = IVIE->getType()->getAsArrayTypeUnsafe(); 920bdd1243dSDimitry Andric assert(AT); 921bdd1243dSDimitry Andric const auto *CAT = cast<ConstantArrayType>(AT); 922bdd1243dSDimitry Andric size_t NumElems = CAT->getSize().getZExtValue(); 923bdd1243dSDimitry Andric 924bdd1243dSDimitry Andric if (std::optional<PrimType> ElemT = classify(CAT->getElementType())) { 925bdd1243dSDimitry Andric // TODO(perf): For int and bool types, we can probably just skip this 926bdd1243dSDimitry Andric // since we memset our Block*s to 0 and so we have the desired value 927bdd1243dSDimitry Andric // without this. 928bdd1243dSDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 929bdd1243dSDimitry Andric if (!this->emitZero(*ElemT, Initializer)) 930bdd1243dSDimitry Andric return false; 931bdd1243dSDimitry Andric if (!this->emitInitElem(*ElemT, I, Initializer)) 932bdd1243dSDimitry Andric return false; 933bdd1243dSDimitry Andric } 934bdd1243dSDimitry Andric } else { 935bdd1243dSDimitry Andric assert(false && "default initializer for non-primitive type"); 936bdd1243dSDimitry Andric } 937bdd1243dSDimitry Andric 938bdd1243dSDimitry Andric return true; 939bdd1243dSDimitry Andric } else if (const auto *Ctor = dyn_cast<CXXConstructExpr>(Initializer)) { 940bdd1243dSDimitry Andric const ConstantArrayType *CAT = 941bdd1243dSDimitry Andric Ctx.getASTContext().getAsConstantArrayType(Ctor->getType()); 942bdd1243dSDimitry Andric assert(CAT); 943bdd1243dSDimitry Andric size_t NumElems = CAT->getSize().getZExtValue(); 944bdd1243dSDimitry Andric const Function *Func = getFunction(Ctor->getConstructor()); 945bdd1243dSDimitry Andric if (!Func || !Func->isConstexpr()) 946bdd1243dSDimitry Andric return false; 947bdd1243dSDimitry Andric 948bdd1243dSDimitry Andric // FIXME(perf): We're calling the constructor once per array element here, 949bdd1243dSDimitry Andric // in the old intepreter we had a special-case for trivial constructors. 950bdd1243dSDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 951bdd1243dSDimitry Andric if (!this->emitDupPtr(Initializer)) 952bdd1243dSDimitry Andric return false; 953bdd1243dSDimitry Andric if (!this->emitConstUint64(I, Initializer)) 954bdd1243dSDimitry Andric return false; 955bdd1243dSDimitry Andric if (!this->emitAddOffsetUint64(Initializer)) 956bdd1243dSDimitry Andric return false; 957bdd1243dSDimitry Andric if (!this->emitNarrowPtr(Initializer)) 958bdd1243dSDimitry Andric return false; 959bdd1243dSDimitry Andric 960bdd1243dSDimitry Andric // Constructor arguments. 961bdd1243dSDimitry Andric for (const auto *Arg : Ctor->arguments()) { 962bdd1243dSDimitry Andric if (!this->visit(Arg)) 963bdd1243dSDimitry Andric return false; 964bdd1243dSDimitry Andric } 965bdd1243dSDimitry Andric 966bdd1243dSDimitry Andric if (!this->emitCall(Func, Initializer)) 967bdd1243dSDimitry Andric return false; 968bdd1243dSDimitry Andric } 969bdd1243dSDimitry Andric return true; 970bdd1243dSDimitry Andric } 971bdd1243dSDimitry Andric 972bdd1243dSDimitry Andric assert(false && "Unknown expression for array initialization"); 973bdd1243dSDimitry Andric return false; 974a7dea167SDimitry Andric } 975a7dea167SDimitry Andric 976a7dea167SDimitry Andric template <class Emitter> 977bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitRecordInitializer(const Expr *Initializer) { 978bdd1243dSDimitry Andric Initializer = Initializer->IgnoreParenImpCasts(); 979bdd1243dSDimitry Andric assert(Initializer->getType()->isRecordType()); 980bdd1243dSDimitry Andric 981bdd1243dSDimitry Andric if (const auto CtorExpr = dyn_cast<CXXConstructExpr>(Initializer)) { 982bdd1243dSDimitry Andric const Function *Func = getFunction(CtorExpr->getConstructor()); 983bdd1243dSDimitry Andric 984bdd1243dSDimitry Andric if (!Func || !Func->isConstexpr()) 985bdd1243dSDimitry Andric return false; 986bdd1243dSDimitry Andric 987bdd1243dSDimitry Andric // The This pointer is already on the stack because this is an initializer, 988bdd1243dSDimitry Andric // but we need to dup() so the call() below has its own copy. 989bdd1243dSDimitry Andric if (!this->emitDupPtr(Initializer)) 990bdd1243dSDimitry Andric return false; 991bdd1243dSDimitry Andric 992bdd1243dSDimitry Andric // Constructor arguments. 993bdd1243dSDimitry Andric for (const auto *Arg : CtorExpr->arguments()) { 994bdd1243dSDimitry Andric if (!this->visit(Arg)) 995bdd1243dSDimitry Andric return false; 996a7dea167SDimitry Andric } 997bdd1243dSDimitry Andric 998bdd1243dSDimitry Andric return this->emitCall(Func, Initializer); 999bdd1243dSDimitry Andric } else if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) { 1000bdd1243dSDimitry Andric const Record *R = getRecord(InitList->getType()); 1001bdd1243dSDimitry Andric 1002bdd1243dSDimitry Andric unsigned InitIndex = 0; 1003bdd1243dSDimitry Andric for (const Expr *Init : InitList->inits()) { 1004bdd1243dSDimitry Andric const Record::Field *FieldToInit = R->getField(InitIndex); 1005bdd1243dSDimitry Andric 1006bdd1243dSDimitry Andric if (!this->emitDupPtr(Initializer)) 1007bdd1243dSDimitry Andric return false; 1008bdd1243dSDimitry Andric 1009bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(Init)) { 1010bdd1243dSDimitry Andric if (!this->visit(Init)) 1011bdd1243dSDimitry Andric return false; 1012bdd1243dSDimitry Andric 1013bdd1243dSDimitry Andric if (!this->emitInitField(*T, FieldToInit->Offset, Initializer)) 1014bdd1243dSDimitry Andric return false; 1015bdd1243dSDimitry Andric 1016bdd1243dSDimitry Andric if (!this->emitPopPtr(Initializer)) 1017bdd1243dSDimitry Andric return false; 1018bdd1243dSDimitry Andric } else { 1019bdd1243dSDimitry Andric // Non-primitive case. Get a pointer to the field-to-initialize 1020bdd1243dSDimitry Andric // on the stack and recurse into visitInitializer(). 1021bdd1243dSDimitry Andric if (!this->emitGetPtrField(FieldToInit->Offset, Init)) 1022bdd1243dSDimitry Andric return false; 1023bdd1243dSDimitry Andric 1024bdd1243dSDimitry Andric if (!this->visitInitializer(Init)) 1025bdd1243dSDimitry Andric return false; 1026bdd1243dSDimitry Andric 1027bdd1243dSDimitry Andric if (!this->emitPopPtr(Initializer)) 1028bdd1243dSDimitry Andric return false; 1029bdd1243dSDimitry Andric } 1030bdd1243dSDimitry Andric ++InitIndex; 1031bdd1243dSDimitry Andric } 1032bdd1243dSDimitry Andric 1033bdd1243dSDimitry Andric return true; 1034bdd1243dSDimitry Andric } else if (const CallExpr *CE = dyn_cast<CallExpr>(Initializer)) { 1035bdd1243dSDimitry Andric // RVO functions expect a pointer to initialize on the stack. 1036bdd1243dSDimitry Andric // Dup our existing pointer so it has its own copy to use. 1037bdd1243dSDimitry Andric if (!this->emitDupPtr(Initializer)) 1038bdd1243dSDimitry Andric return false; 1039bdd1243dSDimitry Andric 1040bdd1243dSDimitry Andric return this->VisitCallExpr(CE); 1041bdd1243dSDimitry Andric } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) { 1042bdd1243dSDimitry Andric return this->visitInitializer(DIE->getExpr()); 1043bdd1243dSDimitry Andric } 1044bdd1243dSDimitry Andric 1045bdd1243dSDimitry Andric return false; 1046a7dea167SDimitry Andric } 1047a7dea167SDimitry Andric 1048a7dea167SDimitry Andric template <class Emitter> 1049bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *Initializer) { 1050bdd1243dSDimitry Andric QualType InitializerType = Initializer->getType(); 1051bdd1243dSDimitry Andric 1052bdd1243dSDimitry Andric if (InitializerType->isArrayType()) 1053bdd1243dSDimitry Andric return visitArrayInitializer(Initializer); 1054bdd1243dSDimitry Andric 1055bdd1243dSDimitry Andric if (InitializerType->isRecordType()) 1056bdd1243dSDimitry Andric return visitRecordInitializer(Initializer); 1057bdd1243dSDimitry Andric 1058bdd1243dSDimitry Andric // Otherwise, visit the expression like normal. 1059bdd1243dSDimitry Andric return this->visit(Initializer); 1060a7dea167SDimitry Andric } 1061a7dea167SDimitry Andric 1062a7dea167SDimitry Andric template <class Emitter> 1063a7dea167SDimitry Andric const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) { 1064753f127fSDimitry Andric if (const PointerType *PT = dyn_cast<PointerType>(Ty)) 1065a7dea167SDimitry Andric return PT->getPointeeType()->getAs<RecordType>(); 1066a7dea167SDimitry Andric else 1067a7dea167SDimitry Andric return Ty->getAs<RecordType>(); 1068a7dea167SDimitry Andric } 1069a7dea167SDimitry Andric 1070a7dea167SDimitry Andric template <class Emitter> 1071a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) { 1072a7dea167SDimitry Andric if (auto *RecordTy = getRecordTy(Ty)) { 1073a7dea167SDimitry Andric return getRecord(RecordTy->getDecl()); 1074a7dea167SDimitry Andric } 1075a7dea167SDimitry Andric return nullptr; 1076a7dea167SDimitry Andric } 1077a7dea167SDimitry Andric 1078a7dea167SDimitry Andric template <class Emitter> 1079a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) { 1080a7dea167SDimitry Andric return P.getOrCreateRecord(RD); 1081a7dea167SDimitry Andric } 1082a7dea167SDimitry Andric 1083a7dea167SDimitry Andric template <class Emitter> 1084bdd1243dSDimitry Andric const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) { 1085bdd1243dSDimitry Andric assert(FD); 1086bdd1243dSDimitry Andric const Function *Func = P.getFunction(FD); 1087bdd1243dSDimitry Andric bool IsBeingCompiled = Func && !Func->isFullyCompiled(); 1088bdd1243dSDimitry Andric bool WasNotDefined = Func && !Func->hasBody(); 1089bdd1243dSDimitry Andric 1090bdd1243dSDimitry Andric if (IsBeingCompiled) 1091bdd1243dSDimitry Andric return Func; 1092bdd1243dSDimitry Andric 1093bdd1243dSDimitry Andric if (!Func || WasNotDefined) { 1094bdd1243dSDimitry Andric if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(Ctx, P).compileFunc(FD)) 1095bdd1243dSDimitry Andric Func = *R; 1096bdd1243dSDimitry Andric else { 1097bdd1243dSDimitry Andric llvm::consumeError(R.takeError()); 1098bdd1243dSDimitry Andric return nullptr; 1099bdd1243dSDimitry Andric } 1100bdd1243dSDimitry Andric } 1101bdd1243dSDimitry Andric 1102bdd1243dSDimitry Andric return Func; 1103bdd1243dSDimitry Andric } 1104bdd1243dSDimitry Andric 1105bdd1243dSDimitry Andric template <class Emitter> 1106a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) { 1107a7dea167SDimitry Andric ExprScope<Emitter> RootScope(this); 1108a7dea167SDimitry Andric if (!visit(Exp)) 1109a7dea167SDimitry Andric return false; 1110a7dea167SDimitry Andric 1111bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(Exp)) 1112a7dea167SDimitry Andric return this->emitRet(*T, Exp); 1113a7dea167SDimitry Andric else 1114a7dea167SDimitry Andric return this->emitRetValue(Exp); 1115a7dea167SDimitry Andric } 1116a7dea167SDimitry Andric 1117bdd1243dSDimitry Andric /// Toplevel visitDecl(). 1118bdd1243dSDimitry Andric /// We get here from evaluateAsInitializer(). 1119bdd1243dSDimitry Andric /// We need to evaluate the initializer and return its value. 1120a7dea167SDimitry Andric template <class Emitter> 1121a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { 1122bdd1243dSDimitry Andric std::optional<PrimType> VarT = classify(VD->getType()); 1123a7dea167SDimitry Andric 1124bdd1243dSDimitry Andric // Create and initialize the variable. 1125bdd1243dSDimitry Andric if (!this->visitVarDecl(VD)) 1126a7dea167SDimitry Andric return false; 1127a7dea167SDimitry Andric 1128bdd1243dSDimitry Andric // Get a pointer to the variable 1129bdd1243dSDimitry Andric if (shouldBeGloballyIndexed(VD)) { 1130bdd1243dSDimitry Andric auto GlobalIndex = P.getGlobal(VD); 1131bdd1243dSDimitry Andric assert(GlobalIndex); // visitVarDecl() didn't return false. 1132bdd1243dSDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, VD)) 1133a7dea167SDimitry Andric return false; 1134a7dea167SDimitry Andric } else { 1135bdd1243dSDimitry Andric auto Local = Locals.find(VD); 1136bdd1243dSDimitry Andric assert(Local != Locals.end()); // Same here. 1137bdd1243dSDimitry Andric if (!this->emitGetPtrLocal(Local->second.Offset, VD)) 1138a7dea167SDimitry Andric return false; 1139a7dea167SDimitry Andric } 1140a7dea167SDimitry Andric 1141bdd1243dSDimitry Andric // Return the value 1142bdd1243dSDimitry Andric if (VarT) { 1143bdd1243dSDimitry Andric if (!this->emitLoadPop(*VarT, VD)) 1144a7dea167SDimitry Andric return false; 1145bdd1243dSDimitry Andric 1146bdd1243dSDimitry Andric return this->emitRet(*VarT, VD); 1147bdd1243dSDimitry Andric } 1148bdd1243dSDimitry Andric 1149a7dea167SDimitry Andric return this->emitRetValue(VD); 1150a7dea167SDimitry Andric } 1151bdd1243dSDimitry Andric 1152bdd1243dSDimitry Andric template <class Emitter> 1153bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) { 1154bdd1243dSDimitry Andric const Expr *Init = VD->getInit(); 1155bdd1243dSDimitry Andric std::optional<PrimType> VarT = classify(VD->getType()); 1156bdd1243dSDimitry Andric 1157bdd1243dSDimitry Andric if (shouldBeGloballyIndexed(VD)) { 1158bdd1243dSDimitry Andric std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(VD, Init); 1159bdd1243dSDimitry Andric 1160bdd1243dSDimitry Andric if (!GlobalIndex) 1161bdd1243dSDimitry Andric return this->bail(VD); 1162bdd1243dSDimitry Andric 1163bdd1243dSDimitry Andric assert(Init); 1164bdd1243dSDimitry Andric { 1165bdd1243dSDimitry Andric DeclScope<Emitter> LocalScope(this, VD); 1166bdd1243dSDimitry Andric 1167bdd1243dSDimitry Andric if (VarT) { 1168bdd1243dSDimitry Andric if (!this->visit(Init)) 1169bdd1243dSDimitry Andric return false; 1170bdd1243dSDimitry Andric return this->emitInitGlobal(*VarT, *GlobalIndex, VD); 1171bdd1243dSDimitry Andric } 1172bdd1243dSDimitry Andric return this->visitGlobalInitializer(Init, *GlobalIndex); 1173bdd1243dSDimitry Andric } 1174bdd1243dSDimitry Andric } else { 1175bdd1243dSDimitry Andric VariableScope<Emitter> LocalScope(this); 1176bdd1243dSDimitry Andric if (VarT) { 1177bdd1243dSDimitry Andric unsigned Offset = this->allocateLocalPrimitive( 1178bdd1243dSDimitry Andric VD, *VarT, VD->getType().isConstQualified()); 1179bdd1243dSDimitry Andric if (Init) { 1180bdd1243dSDimitry Andric // Compile the initializer in its own scope. 1181bdd1243dSDimitry Andric ExprScope<Emitter> Scope(this); 1182bdd1243dSDimitry Andric if (!this->visit(Init)) 1183bdd1243dSDimitry Andric return false; 1184bdd1243dSDimitry Andric 1185bdd1243dSDimitry Andric return this->emitSetLocal(*VarT, Offset, VD); 1186bdd1243dSDimitry Andric } 1187bdd1243dSDimitry Andric } else { 1188bdd1243dSDimitry Andric if (std::optional<unsigned> Offset = this->allocateLocal(VD)) { 1189bdd1243dSDimitry Andric if (Init) 1190bdd1243dSDimitry Andric return this->visitLocalInitializer(Init, *Offset); 1191bdd1243dSDimitry Andric } 1192bdd1243dSDimitry Andric } 1193bdd1243dSDimitry Andric return true; 1194a7dea167SDimitry Andric } 1195a7dea167SDimitry Andric 1196bdd1243dSDimitry Andric return false; 1197bdd1243dSDimitry Andric } 1198bdd1243dSDimitry Andric 1199bdd1243dSDimitry Andric template <class Emitter> 1200bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) { 1201bdd1243dSDimitry Andric assert(!E->getBuiltinCallee() && "Builtin functions aren't supported yet"); 1202bdd1243dSDimitry Andric 1203bdd1243dSDimitry Andric const Decl *Callee = E->getCalleeDecl(); 1204bdd1243dSDimitry Andric if (const auto *FuncDecl = dyn_cast_or_null<FunctionDecl>(Callee)) { 1205bdd1243dSDimitry Andric const Function *Func = getFunction(FuncDecl); 1206bdd1243dSDimitry Andric if (!Func) 1207bdd1243dSDimitry Andric return false; 1208bdd1243dSDimitry Andric // If the function is being compiled right now, this is a recursive call. 1209bdd1243dSDimitry Andric // In that case, the function can't be valid yet, even though it will be 1210bdd1243dSDimitry Andric // later. 1211bdd1243dSDimitry Andric // If the function is already fully compiled but not constexpr, it was 1212bdd1243dSDimitry Andric // found to be faulty earlier on, so bail out. 1213bdd1243dSDimitry Andric if (Func->isFullyCompiled() && !Func->isConstexpr()) 1214bdd1243dSDimitry Andric return false; 1215bdd1243dSDimitry Andric 1216bdd1243dSDimitry Andric QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); 1217bdd1243dSDimitry Andric std::optional<PrimType> T = classify(ReturnType); 1218bdd1243dSDimitry Andric 1219bdd1243dSDimitry Andric if (Func->hasRVO() && DiscardResult) { 1220bdd1243dSDimitry Andric // If we need to discard the return value but the function returns its 1221bdd1243dSDimitry Andric // value via an RVO pointer, we need to create one such pointer just 1222bdd1243dSDimitry Andric // for this call. 1223bdd1243dSDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocal(E)) { 1224bdd1243dSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 1225bdd1243dSDimitry Andric return false; 1226bdd1243dSDimitry Andric } 1227bdd1243dSDimitry Andric } 1228bdd1243dSDimitry Andric 1229bdd1243dSDimitry Andric // Put arguments on the stack. 1230bdd1243dSDimitry Andric for (const auto *Arg : E->arguments()) { 1231bdd1243dSDimitry Andric if (!this->visit(Arg)) 1232bdd1243dSDimitry Andric return false; 1233bdd1243dSDimitry Andric } 1234bdd1243dSDimitry Andric 1235bdd1243dSDimitry Andric // In any case call the function. The return value will end up on the stack and 1236bdd1243dSDimitry Andric // if the function has RVO, we already have the pointer on the stack to write 1237bdd1243dSDimitry Andric // the result into. 1238bdd1243dSDimitry Andric if (!this->emitCall(Func, E)) 1239bdd1243dSDimitry Andric return false; 1240bdd1243dSDimitry Andric 1241bdd1243dSDimitry Andric if (DiscardResult && !ReturnType->isVoidType() && T) 1242bdd1243dSDimitry Andric return this->emitPop(*T, E); 1243bdd1243dSDimitry Andric 1244bdd1243dSDimitry Andric return true; 1245bdd1243dSDimitry Andric } else { 1246bdd1243dSDimitry Andric assert(false && "We don't support non-FunctionDecl callees right now."); 1247bdd1243dSDimitry Andric } 1248bdd1243dSDimitry Andric 1249bdd1243dSDimitry Andric return false; 1250bdd1243dSDimitry Andric } 1251bdd1243dSDimitry Andric 1252bdd1243dSDimitry Andric template <class Emitter> 1253bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXMemberCallExpr( 1254bdd1243dSDimitry Andric const CXXMemberCallExpr *E) { 1255bdd1243dSDimitry Andric // Get a This pointer on the stack. 1256bdd1243dSDimitry Andric if (!this->visit(E->getImplicitObjectArgument())) 1257bdd1243dSDimitry Andric return false; 1258bdd1243dSDimitry Andric 1259bdd1243dSDimitry Andric return VisitCallExpr(E); 1260bdd1243dSDimitry Andric } 1261bdd1243dSDimitry Andric 1262bdd1243dSDimitry Andric template <class Emitter> 1263bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr( 1264bdd1243dSDimitry Andric const CXXDefaultInitExpr *E) { 1265bdd1243dSDimitry Andric return this->visit(E->getExpr()); 1266bdd1243dSDimitry Andric } 1267bdd1243dSDimitry Andric 1268bdd1243dSDimitry Andric template <class Emitter> 1269bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr( 1270bdd1243dSDimitry Andric const CXXDefaultArgExpr *E) { 1271bdd1243dSDimitry Andric return this->visit(E->getExpr()); 1272bdd1243dSDimitry Andric } 1273bdd1243dSDimitry Andric 1274bdd1243dSDimitry Andric template <class Emitter> 1275bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr( 1276bdd1243dSDimitry Andric const CXXBoolLiteralExpr *E) { 1277bdd1243dSDimitry Andric if (DiscardResult) 1278bdd1243dSDimitry Andric return true; 1279bdd1243dSDimitry Andric 1280bdd1243dSDimitry Andric return this->emitConstBool(E->getValue(), E); 1281bdd1243dSDimitry Andric } 1282bdd1243dSDimitry Andric 1283bdd1243dSDimitry Andric template <class Emitter> 1284bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr( 1285bdd1243dSDimitry Andric const CXXNullPtrLiteralExpr *E) { 1286bdd1243dSDimitry Andric if (DiscardResult) 1287bdd1243dSDimitry Andric return true; 1288bdd1243dSDimitry Andric 1289bdd1243dSDimitry Andric return this->emitNullPtr(E); 1290bdd1243dSDimitry Andric } 1291bdd1243dSDimitry Andric 1292bdd1243dSDimitry Andric template <class Emitter> 1293bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) { 1294bdd1243dSDimitry Andric if (DiscardResult) 1295bdd1243dSDimitry Andric return true; 1296bdd1243dSDimitry Andric return this->emitThis(E); 1297bdd1243dSDimitry Andric } 1298bdd1243dSDimitry Andric 1299bdd1243dSDimitry Andric template <class Emitter> 1300bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) { 1301bdd1243dSDimitry Andric const Expr *SubExpr = E->getSubExpr(); 1302bdd1243dSDimitry Andric std::optional<PrimType> T = classify(SubExpr->getType()); 1303bdd1243dSDimitry Andric 1304bdd1243dSDimitry Andric // TODO: Support pointers for inc/dec operators. 1305bdd1243dSDimitry Andric switch (E->getOpcode()) { 1306bdd1243dSDimitry Andric case UO_PostInc: { // x++ 1307bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1308bdd1243dSDimitry Andric return false; 1309bdd1243dSDimitry Andric 1310bdd1243dSDimitry Andric return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E); 1311bdd1243dSDimitry Andric } 1312bdd1243dSDimitry Andric case UO_PostDec: { // x-- 1313bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1314bdd1243dSDimitry Andric return false; 1315bdd1243dSDimitry Andric 1316bdd1243dSDimitry Andric return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E); 1317bdd1243dSDimitry Andric } 1318bdd1243dSDimitry Andric case UO_PreInc: { // ++x 1319bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1320bdd1243dSDimitry Andric return false; 1321bdd1243dSDimitry Andric 1322bdd1243dSDimitry Andric // Post-inc and pre-inc are the same if the value is to be discarded. 1323bdd1243dSDimitry Andric if (DiscardResult) 1324bdd1243dSDimitry Andric return this->emitIncPop(*T, E); 1325bdd1243dSDimitry Andric 1326bdd1243dSDimitry Andric this->emitLoad(*T, E); 1327bdd1243dSDimitry Andric this->emitConst(1, E); 1328bdd1243dSDimitry Andric this->emitAdd(*T, E); 1329bdd1243dSDimitry Andric return this->emitStore(*T, E); 1330bdd1243dSDimitry Andric } 1331bdd1243dSDimitry Andric case UO_PreDec: { // --x 1332bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1333bdd1243dSDimitry Andric return false; 1334bdd1243dSDimitry Andric 1335bdd1243dSDimitry Andric // Post-dec and pre-dec are the same if the value is to be discarded. 1336bdd1243dSDimitry Andric if (DiscardResult) 1337bdd1243dSDimitry Andric return this->emitDecPop(*T, E); 1338bdd1243dSDimitry Andric 1339bdd1243dSDimitry Andric this->emitLoad(*T, E); 1340bdd1243dSDimitry Andric this->emitConst(1, E); 1341bdd1243dSDimitry Andric this->emitSub(*T, E); 1342bdd1243dSDimitry Andric return this->emitStore(*T, E); 1343bdd1243dSDimitry Andric } 1344bdd1243dSDimitry Andric case UO_LNot: // !x 1345bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1346bdd1243dSDimitry Andric return false; 1347bdd1243dSDimitry Andric // The Inv doesn't change anything, so skip it if we don't need the result. 1348bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E); 1349bdd1243dSDimitry Andric case UO_Minus: // -x 1350bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1351bdd1243dSDimitry Andric return false; 1352bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E); 1353bdd1243dSDimitry Andric case UO_Plus: // +x 1354bdd1243dSDimitry Andric if (!this->visit(SubExpr)) // noop 1355bdd1243dSDimitry Andric return false; 1356bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : true; 1357bdd1243dSDimitry Andric case UO_AddrOf: // &x 1358bdd1243dSDimitry Andric // We should already have a pointer when we get here. 1359bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1360bdd1243dSDimitry Andric return false; 1361bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : true; 1362bdd1243dSDimitry Andric case UO_Deref: // *x 1363bdd1243dSDimitry Andric return dereference( 1364bdd1243dSDimitry Andric SubExpr, DerefKind::Read, 1365bdd1243dSDimitry Andric [](PrimType) { 1366bdd1243dSDimitry Andric llvm_unreachable("Dereferencing requires a pointer"); 1367bdd1243dSDimitry Andric return false; 1368bdd1243dSDimitry Andric }, 1369bdd1243dSDimitry Andric [this, E](PrimType T) { 1370bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(T, E) : true; 1371bdd1243dSDimitry Andric }); 1372bdd1243dSDimitry Andric case UO_Not: // ~x 1373bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1374bdd1243dSDimitry Andric return false; 1375bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E); 1376bdd1243dSDimitry Andric case UO_Real: // __real x 1377bdd1243dSDimitry Andric case UO_Imag: // __imag x 1378bdd1243dSDimitry Andric case UO_Extension: 1379bdd1243dSDimitry Andric case UO_Coawait: 1380bdd1243dSDimitry Andric assert(false && "Unhandled opcode"); 1381bdd1243dSDimitry Andric } 1382bdd1243dSDimitry Andric 1383bdd1243dSDimitry Andric return false; 1384bdd1243dSDimitry Andric } 1385bdd1243dSDimitry Andric 1386bdd1243dSDimitry Andric template <class Emitter> 1387bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { 1388bdd1243dSDimitry Andric const auto *Decl = E->getDecl(); 1389bdd1243dSDimitry Andric // References are implemented via pointers, so when we see a DeclRefExpr 1390bdd1243dSDimitry Andric // pointing to a reference, we need to get its value directly (i.e. the 1391bdd1243dSDimitry Andric // pointer to the actual value) instead of a pointer to the pointer to the 1392bdd1243dSDimitry Andric // value. 1393bdd1243dSDimitry Andric bool IsReference = Decl->getType()->isReferenceType(); 1394bdd1243dSDimitry Andric 1395bdd1243dSDimitry Andric if (auto It = Locals.find(Decl); It != Locals.end()) { 1396bdd1243dSDimitry Andric const unsigned Offset = It->second.Offset; 1397bdd1243dSDimitry Andric 1398bdd1243dSDimitry Andric if (IsReference) 1399bdd1243dSDimitry Andric return this->emitGetLocal(PT_Ptr, Offset, E); 1400bdd1243dSDimitry Andric return this->emitGetPtrLocal(Offset, E); 1401bdd1243dSDimitry Andric } else if (auto GlobalIndex = P.getGlobal(Decl)) { 1402bdd1243dSDimitry Andric if (IsReference) 1403bdd1243dSDimitry Andric return this->emitGetGlobal(PT_Ptr, *GlobalIndex, E); 1404bdd1243dSDimitry Andric 1405bdd1243dSDimitry Andric return this->emitGetPtrGlobal(*GlobalIndex, E); 1406bdd1243dSDimitry Andric } else if (const auto *PVD = dyn_cast<ParmVarDecl>(Decl)) { 1407bdd1243dSDimitry Andric if (auto It = this->Params.find(PVD); It != this->Params.end()) { 1408bdd1243dSDimitry Andric if (IsReference) 1409bdd1243dSDimitry Andric return this->emitGetParam(PT_Ptr, It->second, E); 1410bdd1243dSDimitry Andric return this->emitGetPtrParam(It->second, E); 1411bdd1243dSDimitry Andric } 1412bdd1243dSDimitry Andric } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(Decl)) { 1413bdd1243dSDimitry Andric return this->emitConst(ECD->getInitVal(), E); 1414bdd1243dSDimitry Andric } 1415bdd1243dSDimitry Andric 1416bdd1243dSDimitry Andric return false; 1417a7dea167SDimitry Andric } 1418a7dea167SDimitry Andric 1419a7dea167SDimitry Andric template <class Emitter> 1420a7dea167SDimitry Andric void ByteCodeExprGen<Emitter>::emitCleanup() { 1421a7dea167SDimitry Andric for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) 1422a7dea167SDimitry Andric C->emitDestruction(); 1423a7dea167SDimitry Andric } 1424a7dea167SDimitry Andric 1425a7dea167SDimitry Andric namespace clang { 1426a7dea167SDimitry Andric namespace interp { 1427a7dea167SDimitry Andric 1428a7dea167SDimitry Andric template class ByteCodeExprGen<ByteCodeEmitter>; 1429a7dea167SDimitry Andric template class ByteCodeExprGen<EvalEmitter>; 1430a7dea167SDimitry Andric 1431a7dea167SDimitry Andric } // namespace interp 1432a7dea167SDimitry Andric } // namespace clang 1433