Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/Compiler.cpp
213799 views
//===--- Compiler.cpp - Code generator for expressions ---*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Compiler.h"9#include "ByteCodeEmitter.h"10#include "Context.h"11#include "FixedPoint.h"12#include "Floating.h"13#include "Function.h"14#include "InterpShared.h"15#include "PrimType.h"16#include "Program.h"17#include "clang/AST/Attr.h"1819using namespace clang;20using namespace clang::interp;2122using APSInt = llvm::APSInt;2324namespace clang {25namespace interp {2627static std::optional<bool> getBoolValue(const Expr *E) {28if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);29CE && CE->hasAPValueResult() &&30CE->getResultAPValueKind() == APValue::ValueKind::Int) {31return CE->getResultAsAPSInt().getBoolValue();32}3334return std::nullopt;35}3637/// Scope used to handle temporaries in toplevel variable declarations.38template <class Emitter> class DeclScope final : public LocalScope<Emitter> {39public:40DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)41: LocalScope<Emitter>(Ctx, VD), Scope(Ctx->P),42OldInitializingDecl(Ctx->InitializingDecl) {43Ctx->InitializingDecl = VD;44Ctx->InitStack.push_back(InitLink::Decl(VD));45}4647~DeclScope() {48this->Ctx->InitializingDecl = OldInitializingDecl;49this->Ctx->InitStack.pop_back();50}5152private:53Program::DeclScope Scope;54const ValueDecl *OldInitializingDecl;55};5657/// Scope used to handle initialization methods.58template <class Emitter> class OptionScope final {59public:60/// Root constructor, compiling or discarding primitives.61OptionScope(Compiler<Emitter> *Ctx, bool NewDiscardResult,62bool NewInitializing)63: Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),64OldInitializing(Ctx->Initializing) {65Ctx->DiscardResult = NewDiscardResult;66Ctx->Initializing = NewInitializing;67}6869~OptionScope() {70Ctx->DiscardResult = OldDiscardResult;71Ctx->Initializing = OldInitializing;72}7374private:75/// Parent context.76Compiler<Emitter> *Ctx;77/// Old discard flag to restore.78bool OldDiscardResult;79bool OldInitializing;80};8182template <class Emitter>83bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {84switch (Kind) {85case K_This:86return Ctx->emitThis(E);87case K_Field:88// We're assuming there's a base pointer on the stack already.89return Ctx->emitGetPtrFieldPop(Offset, E);90case K_Temp:91return Ctx->emitGetPtrLocal(Offset, E);92case K_Decl:93return Ctx->visitDeclRef(D, E);94case K_Elem:95if (!Ctx->emitConstUint32(Offset, E))96return false;97return Ctx->emitArrayElemPtrPopUint32(E);98case K_RVO:99return Ctx->emitRVOPtr(E);100case K_InitList:101return true;102default:103llvm_unreachable("Unhandled InitLink kind");104}105return true;106}107108/// Scope managing label targets.109template <class Emitter> class LabelScope {110public:111virtual ~LabelScope() {}112113protected:114LabelScope(Compiler<Emitter> *Ctx) : Ctx(Ctx) {}115/// Compiler instance.116Compiler<Emitter> *Ctx;117};118119/// Sets the context for break/continue statements.120template <class Emitter> class LoopScope final : public LabelScope<Emitter> {121public:122using LabelTy = typename Compiler<Emitter>::LabelTy;123using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;124125LoopScope(Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)126: LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),127OldContinueLabel(Ctx->ContinueLabel),128OldBreakVarScope(Ctx->BreakVarScope),129OldContinueVarScope(Ctx->ContinueVarScope) {130this->Ctx->BreakLabel = BreakLabel;131this->Ctx->ContinueLabel = ContinueLabel;132this->Ctx->BreakVarScope = this->Ctx->VarScope;133this->Ctx->ContinueVarScope = this->Ctx->VarScope;134}135136~LoopScope() {137this->Ctx->BreakLabel = OldBreakLabel;138this->Ctx->ContinueLabel = OldContinueLabel;139this->Ctx->ContinueVarScope = OldContinueVarScope;140this->Ctx->BreakVarScope = OldBreakVarScope;141}142143private:144OptLabelTy OldBreakLabel;145OptLabelTy OldContinueLabel;146VariableScope<Emitter> *OldBreakVarScope;147VariableScope<Emitter> *OldContinueVarScope;148};149150// Sets the context for a switch scope, mapping labels.151template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {152public:153using LabelTy = typename Compiler<Emitter>::LabelTy;154using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;155using CaseMap = typename Compiler<Emitter>::CaseMap;156157SwitchScope(Compiler<Emitter> *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel,158OptLabelTy DefaultLabel)159: LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),160OldDefaultLabel(this->Ctx->DefaultLabel),161OldCaseLabels(std::move(this->Ctx->CaseLabels)),162OldLabelVarScope(Ctx->BreakVarScope) {163this->Ctx->BreakLabel = BreakLabel;164this->Ctx->DefaultLabel = DefaultLabel;165this->Ctx->CaseLabels = std::move(CaseLabels);166this->Ctx->BreakVarScope = this->Ctx->VarScope;167}168169~SwitchScope() {170this->Ctx->BreakLabel = OldBreakLabel;171this->Ctx->DefaultLabel = OldDefaultLabel;172this->Ctx->CaseLabels = std::move(OldCaseLabels);173this->Ctx->BreakVarScope = OldLabelVarScope;174}175176private:177OptLabelTy OldBreakLabel;178OptLabelTy OldDefaultLabel;179CaseMap OldCaseLabels;180VariableScope<Emitter> *OldLabelVarScope;181};182183template <class Emitter> class StmtExprScope final {184public:185StmtExprScope(Compiler<Emitter> *Ctx) : Ctx(Ctx), OldFlag(Ctx->InStmtExpr) {186Ctx->InStmtExpr = true;187}188189~StmtExprScope() { Ctx->InStmtExpr = OldFlag; }190191private:192Compiler<Emitter> *Ctx;193bool OldFlag;194};195196} // namespace interp197} // namespace clang198199template <class Emitter>200bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {201const Expr *SubExpr = CE->getSubExpr();202203if (DiscardResult)204return this->delegate(SubExpr);205206switch (CE->getCastKind()) {207case CK_LValueToRValue: {208if (SubExpr->getType().isVolatileQualified())209return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);210211std::optional<PrimType> SubExprT = classify(SubExpr->getType());212// Prepare storage for the result.213if (!Initializing && !SubExprT) {214std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);215if (!LocalIndex)216return false;217if (!this->emitGetPtrLocal(*LocalIndex, CE))218return false;219}220221if (!this->visit(SubExpr))222return false;223224if (SubExprT)225return this->emitLoadPop(*SubExprT, CE);226227// If the subexpr type is not primitive, we need to perform a copy here.228// This happens for example in C when dereferencing a pointer of struct229// type.230return this->emitMemcpy(CE);231}232233case CK_DerivedToBaseMemberPointer: {234assert(classifyPrim(CE->getType()) == PT_MemberPtr);235assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr);236const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();237const auto *ToMP = CE->getType()->castAs<MemberPointerType>();238239unsigned DerivedOffset =240Ctx.collectBaseOffset(ToMP->getMostRecentCXXRecordDecl(),241FromMP->getMostRecentCXXRecordDecl());242243if (!this->delegate(SubExpr))244return false;245246return this->emitGetMemberPtrBasePop(DerivedOffset, CE);247}248249case CK_BaseToDerivedMemberPointer: {250assert(classifyPrim(CE) == PT_MemberPtr);251assert(classifyPrim(SubExpr) == PT_MemberPtr);252const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();253const auto *ToMP = CE->getType()->castAs<MemberPointerType>();254255unsigned DerivedOffset =256Ctx.collectBaseOffset(FromMP->getMostRecentCXXRecordDecl(),257ToMP->getMostRecentCXXRecordDecl());258259if (!this->delegate(SubExpr))260return false;261return this->emitGetMemberPtrBasePop(-DerivedOffset, CE);262}263264case CK_UncheckedDerivedToBase:265case CK_DerivedToBase: {266if (!this->delegate(SubExpr))267return false;268269const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {270if (const auto *PT = dyn_cast<PointerType>(Ty))271return PT->getPointeeType()->getAsCXXRecordDecl();272return Ty->getAsCXXRecordDecl();273};274275// FIXME: We can express a series of non-virtual casts as a single276// GetPtrBasePop op.277QualType CurType = SubExpr->getType();278for (const CXXBaseSpecifier *B : CE->path()) {279if (B->isVirtual()) {280if (!this->emitGetPtrVirtBasePop(extractRecordDecl(B->getType()), CE))281return false;282CurType = B->getType();283} else {284unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType);285if (!this->emitGetPtrBasePop(286DerivedOffset, /*NullOK=*/CE->getType()->isPointerType(), CE))287return false;288CurType = B->getType();289}290}291292return true;293}294295case CK_BaseToDerived: {296if (!this->delegate(SubExpr))297return false;298unsigned DerivedOffset =299collectBaseOffset(SubExpr->getType(), CE->getType());300301const Type *TargetType = CE->getType().getTypePtr();302if (TargetType->isPointerOrReferenceType())303TargetType = TargetType->getPointeeType().getTypePtr();304return this->emitGetPtrDerivedPop(DerivedOffset,305/*NullOK=*/CE->getType()->isPointerType(),306TargetType, CE);307}308309case CK_FloatingCast: {310// HLSL uses CK_FloatingCast to cast between vectors.311if (!SubExpr->getType()->isFloatingType() ||312!CE->getType()->isFloatingType())313return false;314if (!this->visit(SubExpr))315return false;316const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());317return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE);318}319320case CK_IntegralToFloating: {321if (!CE->getType()->isRealFloatingType())322return false;323if (!this->visit(SubExpr))324return false;325const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());326return this->emitCastIntegralFloating(327classifyPrim(SubExpr), TargetSemantics, getFPOptions(CE), CE);328}329330case CK_FloatingToBoolean: {331if (!SubExpr->getType()->isRealFloatingType() ||332!CE->getType()->isBooleanType())333return false;334if (const auto *FL = dyn_cast<FloatingLiteral>(SubExpr))335return this->emitConstBool(FL->getValue().isNonZero(), CE);336if (!this->visit(SubExpr))337return false;338return this->emitCastFloatingIntegralBool(getFPOptions(CE), CE);339}340341case CK_FloatingToIntegral: {342if (!this->visit(SubExpr))343return false;344PrimType ToT = classifyPrim(CE);345if (ToT == PT_IntAP)346return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()),347getFPOptions(CE), CE);348if (ToT == PT_IntAPS)349return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()),350getFPOptions(CE), CE);351352return this->emitCastFloatingIntegral(ToT, getFPOptions(CE), CE);353}354355case CK_NullToPointer:356case CK_NullToMemberPointer: {357if (!this->discard(SubExpr))358return false;359const Descriptor *Desc = nullptr;360const QualType PointeeType = CE->getType()->getPointeeType();361if (!PointeeType.isNull()) {362if (std::optional<PrimType> T = classify(PointeeType))363Desc = P.createDescriptor(SubExpr, *T);364else365Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(),366std::nullopt, /*IsConst=*/true);367}368369uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(CE->getType());370return this->emitNull(classifyPrim(CE->getType()), Val, Desc, CE);371}372373case CK_PointerToIntegral: {374if (!this->visit(SubExpr))375return false;376377// If SubExpr doesn't result in a pointer, make it one.378if (PrimType FromT = classifyPrim(SubExpr->getType()); FromT != PT_Ptr) {379assert(isPtrType(FromT));380if (!this->emitDecayPtr(FromT, PT_Ptr, CE))381return false;382}383384PrimType T = classifyPrim(CE->getType());385if (T == PT_IntAP)386return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()),387CE);388if (T == PT_IntAPS)389return this->emitCastPointerIntegralAPS(Ctx.getBitWidth(CE->getType()),390CE);391return this->emitCastPointerIntegral(T, CE);392}393394case CK_ArrayToPointerDecay: {395if (!this->visit(SubExpr))396return false;397return this->emitArrayDecay(CE);398}399400case CK_IntegralToPointer: {401QualType IntType = SubExpr->getType();402assert(IntType->isIntegralOrEnumerationType());403if (!this->visit(SubExpr))404return false;405// FIXME: I think the discard is wrong since the int->ptr cast might cause a406// diagnostic.407PrimType T = classifyPrim(IntType);408QualType PtrType = CE->getType();409const Descriptor *Desc;410if (std::optional<PrimType> T = classify(PtrType->getPointeeType()))411Desc = P.createDescriptor(SubExpr, *T);412else if (PtrType->getPointeeType()->isVoidType())413Desc = nullptr;414else415Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),416Descriptor::InlineDescMD, /*IsConst=*/true);417418if (!this->emitGetIntPtr(T, Desc, CE))419return false;420421PrimType DestPtrT = classifyPrim(PtrType);422if (DestPtrT == PT_Ptr)423return true;424425// In case we're converting the integer to a non-Pointer.426return this->emitDecayPtr(PT_Ptr, DestPtrT, CE);427}428429case CK_AtomicToNonAtomic:430case CK_ConstructorConversion:431case CK_FunctionToPointerDecay:432case CK_NonAtomicToAtomic:433case CK_NoOp:434case CK_UserDefinedConversion:435case CK_AddressSpaceConversion:436case CK_CPointerToObjCPointerCast:437return this->delegate(SubExpr);438439case CK_BitCast: {440// Reject bitcasts to atomic types.441if (CE->getType()->isAtomicType()) {442if (!this->discard(SubExpr))443return false;444return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE);445}446QualType SubExprTy = SubExpr->getType();447std::optional<PrimType> FromT = classify(SubExprTy);448// Casts from integer/vector to vector.449if (CE->getType()->isVectorType())450return this->emitBuiltinBitCast(CE);451452std::optional<PrimType> ToT = classify(CE->getType());453if (!FromT || !ToT)454return false;455456assert(isPtrType(*FromT));457assert(isPtrType(*ToT));458if (FromT == ToT) {459if (CE->getType()->isVoidPointerType())460return this->delegate(SubExpr);461462if (!this->visit(SubExpr))463return false;464if (CE->getType()->isFunctionPointerType())465return true;466if (FromT == PT_Ptr)467return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE);468return true;469}470471if (!this->visit(SubExpr))472return false;473return this->emitDecayPtr(*FromT, *ToT, CE);474}475case CK_IntegralToBoolean:476case CK_FixedPointToBoolean: {477// HLSL uses this to cast to one-element vectors.478std::optional<PrimType> FromT = classify(SubExpr->getType());479if (!FromT)480return false;481482if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))483return this->emitConst(IL->getValue(), CE);484if (!this->visit(SubExpr))485return false;486return this->emitCast(*FromT, classifyPrim(CE), CE);487}488489case CK_BooleanToSignedIntegral:490case CK_IntegralCast: {491std::optional<PrimType> FromT = classify(SubExpr->getType());492std::optional<PrimType> ToT = classify(CE->getType());493if (!FromT || !ToT)494return false;495496// Try to emit a casted known constant value directly.497if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr)) {498if (ToT != PT_IntAP && ToT != PT_IntAPS && FromT != PT_IntAP &&499FromT != PT_IntAPS && !CE->getType()->isEnumeralType())500return this->emitConst(IL->getValue(), CE);501if (!this->emitConst(IL->getValue(), SubExpr))502return false;503} else {504if (!this->visit(SubExpr))505return false;506}507508// Possibly diagnose casts to enum types if the target type does not509// have a fixed size.510if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {511if (const auto *ET = CE->getType().getCanonicalType()->castAs<EnumType>();512!ET->getDecl()->isFixed()) {513if (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE))514return false;515}516}517518if (ToT == PT_IntAP) {519if (!this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE))520return false;521} else if (ToT == PT_IntAPS) {522if (!this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE))523return false;524} else {525if (FromT == ToT)526return true;527if (!this->emitCast(*FromT, *ToT, CE))528return false;529}530if (CE->getCastKind() == CK_BooleanToSignedIntegral)531return this->emitNeg(*ToT, CE);532return true;533}534535case CK_PointerToBoolean:536case CK_MemberPointerToBoolean: {537PrimType PtrT = classifyPrim(SubExpr->getType());538539if (!this->visit(SubExpr))540return false;541return this->emitIsNonNull(PtrT, CE);542}543544case CK_IntegralComplexToBoolean:545case CK_FloatingComplexToBoolean: {546if (!this->visit(SubExpr))547return false;548return this->emitComplexBoolCast(SubExpr);549}550551case CK_IntegralComplexToReal:552case CK_FloatingComplexToReal:553return this->emitComplexReal(SubExpr);554555case CK_IntegralRealToComplex:556case CK_FloatingRealToComplex: {557// We're creating a complex value here, so we need to558// allocate storage for it.559if (!Initializing) {560std::optional<unsigned> LocalIndex = allocateTemporary(CE);561if (!LocalIndex)562return false;563if (!this->emitGetPtrLocal(*LocalIndex, CE))564return false;565}566567PrimType T = classifyPrim(SubExpr->getType());568// Init the complex value to {SubExpr, 0}.569if (!this->visitArrayElemInit(0, SubExpr, T))570return false;571// Zero-init the second element.572if (!this->visitZeroInitializer(T, SubExpr->getType(), SubExpr))573return false;574return this->emitInitElem(T, 1, SubExpr);575}576577case CK_IntegralComplexCast:578case CK_FloatingComplexCast:579case CK_IntegralComplexToFloatingComplex:580case CK_FloatingComplexToIntegralComplex: {581assert(CE->getType()->isAnyComplexType());582assert(SubExpr->getType()->isAnyComplexType());583if (!Initializing) {584std::optional<unsigned> LocalIndex = allocateLocal(CE);585if (!LocalIndex)586return false;587if (!this->emitGetPtrLocal(*LocalIndex, CE))588return false;589}590591// Location for the SubExpr.592// Since SubExpr is of complex type, visiting it results in a pointer593// anyway, so we just create a temporary pointer variable.594unsigned SubExprOffset =595allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);596if (!this->visit(SubExpr))597return false;598if (!this->emitSetLocal(PT_Ptr, SubExprOffset, CE))599return false;600601PrimType SourceElemT = classifyComplexElementType(SubExpr->getType());602QualType DestElemType =603CE->getType()->getAs<ComplexType>()->getElementType();604PrimType DestElemT = classifyPrim(DestElemType);605// Cast both elements individually.606for (unsigned I = 0; I != 2; ++I) {607if (!this->emitGetLocal(PT_Ptr, SubExprOffset, CE))608return false;609if (!this->emitArrayElemPop(SourceElemT, I, CE))610return false;611612// Do the cast.613if (!this->emitPrimCast(SourceElemT, DestElemT, DestElemType, CE))614return false;615616// Save the value.617if (!this->emitInitElem(DestElemT, I, CE))618return false;619}620return true;621}622623case CK_VectorSplat: {624assert(!classify(CE->getType()));625assert(classify(SubExpr->getType()));626assert(CE->getType()->isVectorType());627628if (!Initializing) {629std::optional<unsigned> LocalIndex = allocateLocal(CE);630if (!LocalIndex)631return false;632if (!this->emitGetPtrLocal(*LocalIndex, CE))633return false;634}635636const auto *VT = CE->getType()->getAs<VectorType>();637PrimType ElemT = classifyPrim(SubExpr->getType());638unsigned ElemOffset =639allocateLocalPrimitive(SubExpr, ElemT, /*IsConst=*/true);640641// Prepare a local variable for the scalar value.642if (!this->visit(SubExpr))643return false;644if (classifyPrim(SubExpr) == PT_Ptr && !this->emitLoadPop(ElemT, CE))645return false;646647if (!this->emitSetLocal(ElemT, ElemOffset, CE))648return false;649650for (unsigned I = 0; I != VT->getNumElements(); ++I) {651if (!this->emitGetLocal(ElemT, ElemOffset, CE))652return false;653if (!this->emitInitElem(ElemT, I, CE))654return false;655}656657return true;658}659660case CK_HLSLVectorTruncation: {661assert(SubExpr->getType()->isVectorType());662if (std::optional<PrimType> ResultT = classify(CE)) {663assert(!DiscardResult);664// Result must be either a float or integer. Take the first element.665if (!this->visit(SubExpr))666return false;667return this->emitArrayElemPop(*ResultT, 0, CE);668}669// Otherwise, this truncates from one vector type to another.670assert(CE->getType()->isVectorType());671672if (!Initializing) {673std::optional<unsigned> LocalIndex = allocateTemporary(CE);674if (!LocalIndex)675return false;676if (!this->emitGetPtrLocal(*LocalIndex, CE))677return false;678}679unsigned ToSize = CE->getType()->getAs<VectorType>()->getNumElements();680assert(SubExpr->getType()->getAs<VectorType>()->getNumElements() > ToSize);681if (!this->visit(SubExpr))682return false;683return this->emitCopyArray(classifyVectorElementType(CE->getType()), 0, 0,684ToSize, CE);685};686687case CK_IntegralToFixedPoint: {688if (!this->visit(SubExpr))689return false;690691auto Sem =692Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();693return this->emitCastIntegralFixedPoint(classifyPrim(SubExpr->getType()),694Sem, CE);695}696case CK_FloatingToFixedPoint: {697if (!this->visit(SubExpr))698return false;699700auto Sem =701Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();702return this->emitCastFloatingFixedPoint(Sem, CE);703}704case CK_FixedPointToFloating: {705if (!this->visit(SubExpr))706return false;707const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());708return this->emitCastFixedPointFloating(TargetSemantics, CE);709}710case CK_FixedPointToIntegral: {711if (!this->visit(SubExpr))712return false;713return this->emitCastFixedPointIntegral(classifyPrim(CE->getType()), CE);714}715case CK_FixedPointCast: {716if (!this->visit(SubExpr))717return false;718auto Sem =719Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();720return this->emitCastFixedPoint(Sem, CE);721}722723case CK_ToVoid:724return discard(SubExpr);725726default:727return this->emitInvalid(CE);728}729llvm_unreachable("Unhandled clang::CastKind enum");730}731732template <class Emitter>733bool Compiler<Emitter>::VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E) {734return this->emitBuiltinBitCast(E);735}736737template <class Emitter>738bool Compiler<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {739if (DiscardResult)740return true;741742return this->emitConst(LE->getValue(), LE);743}744745template <class Emitter>746bool Compiler<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {747if (DiscardResult)748return true;749750APFloat F = E->getValue();751return this->emitFloat(F, E);752}753754template <class Emitter>755bool Compiler<Emitter>::VisitImaginaryLiteral(const ImaginaryLiteral *E) {756assert(E->getType()->isAnyComplexType());757if (DiscardResult)758return true;759760if (!Initializing) {761std::optional<unsigned> LocalIndex = allocateTemporary(E);762if (!LocalIndex)763return false;764if (!this->emitGetPtrLocal(*LocalIndex, E))765return false;766}767768const Expr *SubExpr = E->getSubExpr();769PrimType SubExprT = classifyPrim(SubExpr->getType());770771if (!this->visitZeroInitializer(SubExprT, SubExpr->getType(), SubExpr))772return false;773if (!this->emitInitElem(SubExprT, 0, SubExpr))774return false;775return this->visitArrayElemInit(1, SubExpr, SubExprT);776}777778template <class Emitter>779bool Compiler<Emitter>::VisitFixedPointLiteral(const FixedPointLiteral *E) {780assert(E->getType()->isFixedPointType());781assert(classifyPrim(E) == PT_FixedPoint);782783if (DiscardResult)784return true;785786auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());787APInt Value = E->getValue();788return this->emitConstFixedPoint(FixedPoint(Value, Sem), E);789}790791template <class Emitter>792bool Compiler<Emitter>::VisitParenExpr(const ParenExpr *E) {793return this->delegate(E->getSubExpr());794}795796template <class Emitter>797bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {798// Need short-circuiting for these.799if (BO->isLogicalOp() && !BO->getType()->isVectorType())800return this->VisitLogicalBinOp(BO);801802const Expr *LHS = BO->getLHS();803const Expr *RHS = BO->getRHS();804805// Handle comma operators. Just discard the LHS806// and delegate to RHS.807if (BO->isCommaOp()) {808if (!this->discard(LHS))809return false;810if (RHS->getType()->isVoidType())811return this->discard(RHS);812813return this->delegate(RHS);814}815816if (BO->getType()->isAnyComplexType())817return this->VisitComplexBinOp(BO);818if (BO->getType()->isVectorType())819return this->VisitVectorBinOp(BO);820if ((LHS->getType()->isAnyComplexType() ||821RHS->getType()->isAnyComplexType()) &&822BO->isComparisonOp())823return this->emitComplexComparison(LHS, RHS, BO);824if (LHS->getType()->isFixedPointType() || RHS->getType()->isFixedPointType())825return this->VisitFixedPointBinOp(BO);826827if (BO->isPtrMemOp()) {828if (!this->visit(LHS))829return false;830831if (!this->visit(RHS))832return false;833834if (!this->emitToMemberPtr(BO))835return false;836837if (classifyPrim(BO) == PT_MemberPtr)838return true;839840if (!this->emitCastMemberPtrPtr(BO))841return false;842return DiscardResult ? this->emitPopPtr(BO) : true;843}844845// Typecheck the args.846std::optional<PrimType> LT = classify(LHS);847std::optional<PrimType> RT = classify(RHS);848std::optional<PrimType> T = classify(BO->getType());849850// Special case for C++'s three-way/spaceship operator <=>, which851// returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't852// have a PrimType).853if (!T && BO->getOpcode() == BO_Cmp) {854if (DiscardResult)855return true;856const ComparisonCategoryInfo *CmpInfo =857Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());858assert(CmpInfo);859860// We need a temporary variable holding our return value.861if (!Initializing) {862std::optional<unsigned> ResultIndex = this->allocateLocal(BO);863if (!this->emitGetPtrLocal(*ResultIndex, BO))864return false;865}866867if (!visit(LHS) || !visit(RHS))868return false;869870return this->emitCMP3(*LT, CmpInfo, BO);871}872873if (!LT || !RT || !T)874return false;875876// Pointer arithmetic special case.877if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {878if (isPtrType(*T) || (isPtrType(*LT) && isPtrType(*RT)))879return this->VisitPointerArithBinOp(BO);880}881882// Assignments require us to evalute the RHS first.883if (BO->getOpcode() == BO_Assign) {884885if (!visit(RHS) || !visit(LHS))886return false;887888// We don't support assignments in C.889if (!Ctx.getLangOpts().CPlusPlus && !this->emitInvalid(BO))890return false;891892if (!this->emitFlip(*LT, *RT, BO))893return false;894} else {895if (!visit(LHS) || !visit(RHS))896return false;897}898899// For languages such as C, cast the result of one900// of our comparision opcodes to T (which is usually int).901auto MaybeCastToBool = [this, T, BO](bool Result) {902if (!Result)903return false;904if (DiscardResult)905return this->emitPop(*T, BO);906if (T != PT_Bool)907return this->emitCast(PT_Bool, *T, BO);908return true;909};910911auto Discard = [this, T, BO](bool Result) {912if (!Result)913return false;914return DiscardResult ? this->emitPop(*T, BO) : true;915};916917switch (BO->getOpcode()) {918case BO_EQ:919return MaybeCastToBool(this->emitEQ(*LT, BO));920case BO_NE:921return MaybeCastToBool(this->emitNE(*LT, BO));922case BO_LT:923return MaybeCastToBool(this->emitLT(*LT, BO));924case BO_LE:925return MaybeCastToBool(this->emitLE(*LT, BO));926case BO_GT:927return MaybeCastToBool(this->emitGT(*LT, BO));928case BO_GE:929return MaybeCastToBool(this->emitGE(*LT, BO));930case BO_Sub:931if (BO->getType()->isFloatingType())932return Discard(this->emitSubf(getFPOptions(BO), BO));933return Discard(this->emitSub(*T, BO));934case BO_Add:935if (BO->getType()->isFloatingType())936return Discard(this->emitAddf(getFPOptions(BO), BO));937return Discard(this->emitAdd(*T, BO));938case BO_Mul:939if (BO->getType()->isFloatingType())940return Discard(this->emitMulf(getFPOptions(BO), BO));941return Discard(this->emitMul(*T, BO));942case BO_Rem:943return Discard(this->emitRem(*T, BO));944case BO_Div:945if (BO->getType()->isFloatingType())946return Discard(this->emitDivf(getFPOptions(BO), BO));947return Discard(this->emitDiv(*T, BO));948case BO_Assign:949if (DiscardResult)950return LHS->refersToBitField() ? this->emitStoreBitFieldPop(*T, BO)951: this->emitStorePop(*T, BO);952if (LHS->refersToBitField()) {953if (!this->emitStoreBitField(*T, BO))954return false;955} else {956if (!this->emitStore(*T, BO))957return false;958}959// Assignments aren't necessarily lvalues in C.960// Load from them in that case.961if (!BO->isLValue())962return this->emitLoadPop(*T, BO);963return true;964case BO_And:965return Discard(this->emitBitAnd(*T, BO));966case BO_Or:967return Discard(this->emitBitOr(*T, BO));968case BO_Shl:969return Discard(this->emitShl(*LT, *RT, BO));970case BO_Shr:971return Discard(this->emitShr(*LT, *RT, BO));972case BO_Xor:973return Discard(this->emitBitXor(*T, BO));974case BO_LOr:975case BO_LAnd:976llvm_unreachable("Already handled earlier");977default:978return false;979}980981llvm_unreachable("Unhandled binary op");982}983984/// Perform addition/subtraction of a pointer and an integer or985/// subtraction of two pointers.986template <class Emitter>987bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {988BinaryOperatorKind Op = E->getOpcode();989const Expr *LHS = E->getLHS();990const Expr *RHS = E->getRHS();991992if ((Op != BO_Add && Op != BO_Sub) ||993(!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))994return false;995996std::optional<PrimType> LT = classify(LHS);997std::optional<PrimType> RT = classify(RHS);998999if (!LT || !RT)1000return false;10011002// Visit the given pointer expression and optionally convert to a PT_Ptr.1003auto visitAsPointer = [&](const Expr *E, PrimType T) -> bool {1004if (!this->visit(E))1005return false;1006if (T != PT_Ptr)1007return this->emitDecayPtr(T, PT_Ptr, E);1008return true;1009};10101011if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {1012if (Op != BO_Sub)1013return false;10141015assert(E->getType()->isIntegerType());1016if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *LT))1017return false;10181019PrimType IntT = classifyPrim(E->getType());1020if (!this->emitSubPtr(IntT, E))1021return false;1022return DiscardResult ? this->emitPop(IntT, E) : true;1023}10241025PrimType OffsetType;1026if (LHS->getType()->isIntegerType()) {1027if (!visitAsPointer(RHS, *RT))1028return false;1029if (!this->visit(LHS))1030return false;1031OffsetType = *LT;1032} else if (RHS->getType()->isIntegerType()) {1033if (!visitAsPointer(LHS, *LT))1034return false;1035if (!this->visit(RHS))1036return false;1037OffsetType = *RT;1038} else {1039return false;1040}10411042// Do the operation and optionally transform to1043// result pointer type.1044if (Op == BO_Add) {1045if (!this->emitAddOffset(OffsetType, E))1046return false;10471048if (classifyPrim(E) != PT_Ptr)1049return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);1050return true;1051} else if (Op == BO_Sub) {1052if (!this->emitSubOffset(OffsetType, E))1053return false;10541055if (classifyPrim(E) != PT_Ptr)1056return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);1057return true;1058}10591060return false;1061}10621063template <class Emitter>1064bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {1065assert(E->isLogicalOp());1066BinaryOperatorKind Op = E->getOpcode();1067const Expr *LHS = E->getLHS();1068const Expr *RHS = E->getRHS();1069std::optional<PrimType> T = classify(E->getType());10701071if (Op == BO_LOr) {1072// Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.1073LabelTy LabelTrue = this->getLabel();1074LabelTy LabelEnd = this->getLabel();10751076if (!this->visitBool(LHS))1077return false;1078if (!this->jumpTrue(LabelTrue))1079return false;10801081if (!this->visitBool(RHS))1082return false;1083if (!this->jump(LabelEnd))1084return false;10851086this->emitLabel(LabelTrue);1087this->emitConstBool(true, E);1088this->fallthrough(LabelEnd);1089this->emitLabel(LabelEnd);10901091} else {1092assert(Op == BO_LAnd);1093// Logical AND.1094// Visit LHS. Only visit RHS if LHS was TRUE.1095LabelTy LabelFalse = this->getLabel();1096LabelTy LabelEnd = this->getLabel();10971098if (!this->visitBool(LHS))1099return false;1100if (!this->jumpFalse(LabelFalse))1101return false;11021103if (!this->visitBool(RHS))1104return false;1105if (!this->jump(LabelEnd))1106return false;11071108this->emitLabel(LabelFalse);1109this->emitConstBool(false, E);1110this->fallthrough(LabelEnd);1111this->emitLabel(LabelEnd);1112}11131114if (DiscardResult)1115return this->emitPopBool(E);11161117// For C, cast back to integer type.1118assert(T);1119if (T != PT_Bool)1120return this->emitCast(PT_Bool, *T, E);1121return true;1122}11231124template <class Emitter>1125bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {1126// Prepare storage for result.1127if (!Initializing) {1128std::optional<unsigned> LocalIndex = allocateTemporary(E);1129if (!LocalIndex)1130return false;1131if (!this->emitGetPtrLocal(*LocalIndex, E))1132return false;1133}11341135// Both LHS and RHS might _not_ be of complex type, but one of them1136// needs to be.1137const Expr *LHS = E->getLHS();1138const Expr *RHS = E->getRHS();11391140PrimType ResultElemT = this->classifyComplexElementType(E->getType());1141unsigned ResultOffset = ~0u;1142if (!DiscardResult)1143ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, /*IsConst=*/true);11441145// Save result pointer in ResultOffset1146if (!this->DiscardResult) {1147if (!this->emitDupPtr(E))1148return false;1149if (!this->emitSetLocal(PT_Ptr, ResultOffset, E))1150return false;1151}1152QualType LHSType = LHS->getType();1153if (const auto *AT = LHSType->getAs<AtomicType>())1154LHSType = AT->getValueType();1155QualType RHSType = RHS->getType();1156if (const auto *AT = RHSType->getAs<AtomicType>())1157RHSType = AT->getValueType();11581159bool LHSIsComplex = LHSType->isAnyComplexType();1160unsigned LHSOffset;1161bool RHSIsComplex = RHSType->isAnyComplexType();11621163// For ComplexComplex Mul, we have special ops to make their implementation1164// easier.1165BinaryOperatorKind Op = E->getOpcode();1166if (Op == BO_Mul && LHSIsComplex && RHSIsComplex) {1167assert(classifyPrim(LHSType->getAs<ComplexType>()->getElementType()) ==1168classifyPrim(RHSType->getAs<ComplexType>()->getElementType()));1169PrimType ElemT =1170classifyPrim(LHSType->getAs<ComplexType>()->getElementType());1171if (!this->visit(LHS))1172return false;1173if (!this->visit(RHS))1174return false;1175return this->emitMulc(ElemT, E);1176}11771178if (Op == BO_Div && RHSIsComplex) {1179QualType ElemQT = RHSType->getAs<ComplexType>()->getElementType();1180PrimType ElemT = classifyPrim(ElemQT);1181// If the LHS is not complex, we still need to do the full complex1182// division, so just stub create a complex value and stub it out with1183// the LHS and a zero.11841185if (!LHSIsComplex) {1186// This is using the RHS type for the fake-complex LHS.1187std::optional<unsigned> LocalIndex = allocateTemporary(RHS);1188if (!LocalIndex)1189return false;1190LHSOffset = *LocalIndex;11911192if (!this->emitGetPtrLocal(LHSOffset, E))1193return false;11941195if (!this->visit(LHS))1196return false;1197// real is LHS1198if (!this->emitInitElem(ElemT, 0, E))1199return false;1200// imag is zero1201if (!this->visitZeroInitializer(ElemT, ElemQT, E))1202return false;1203if (!this->emitInitElem(ElemT, 1, E))1204return false;1205} else {1206if (!this->visit(LHS))1207return false;1208}12091210if (!this->visit(RHS))1211return false;1212return this->emitDivc(ElemT, E);1213}12141215// Evaluate LHS and save value to LHSOffset.1216if (LHSType->isAnyComplexType()) {1217LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);1218if (!this->visit(LHS))1219return false;1220if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))1221return false;1222} else {1223PrimType LHST = classifyPrim(LHSType);1224LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);1225if (!this->visit(LHS))1226return false;1227if (!this->emitSetLocal(LHST, LHSOffset, E))1228return false;1229}12301231// Same with RHS.1232unsigned RHSOffset;1233if (RHSType->isAnyComplexType()) {1234RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);1235if (!this->visit(RHS))1236return false;1237if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))1238return false;1239} else {1240PrimType RHST = classifyPrim(RHSType);1241RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);1242if (!this->visit(RHS))1243return false;1244if (!this->emitSetLocal(RHST, RHSOffset, E))1245return false;1246}12471248// For both LHS and RHS, either load the value from the complex pointer, or1249// directly from the local variable. For index 1 (i.e. the imaginary part),1250// just load 0 and do the operation anyway.1251auto loadComplexValue = [this](bool IsComplex, bool LoadZero,1252unsigned ElemIndex, unsigned Offset,1253const Expr *E) -> bool {1254if (IsComplex) {1255if (!this->emitGetLocal(PT_Ptr, Offset, E))1256return false;1257return this->emitArrayElemPop(classifyComplexElementType(E->getType()),1258ElemIndex, E);1259}1260if (ElemIndex == 0 || !LoadZero)1261return this->emitGetLocal(classifyPrim(E->getType()), Offset, E);1262return this->visitZeroInitializer(classifyPrim(E->getType()), E->getType(),1263E);1264};12651266// Now we can get pointers to the LHS and RHS from the offsets above.1267for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) {1268// Result pointer for the store later.1269if (!this->DiscardResult) {1270if (!this->emitGetLocal(PT_Ptr, ResultOffset, E))1271return false;1272}12731274// The actual operation.1275switch (Op) {1276case BO_Add:1277if (!loadComplexValue(LHSIsComplex, true, ElemIndex, LHSOffset, LHS))1278return false;12791280if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))1281return false;1282if (ResultElemT == PT_Float) {1283if (!this->emitAddf(getFPOptions(E), E))1284return false;1285} else {1286if (!this->emitAdd(ResultElemT, E))1287return false;1288}1289break;1290case BO_Sub:1291if (!loadComplexValue(LHSIsComplex, true, ElemIndex, LHSOffset, LHS))1292return false;12931294if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))1295return false;1296if (ResultElemT == PT_Float) {1297if (!this->emitSubf(getFPOptions(E), E))1298return false;1299} else {1300if (!this->emitSub(ResultElemT, E))1301return false;1302}1303break;1304case BO_Mul:1305if (!loadComplexValue(LHSIsComplex, false, ElemIndex, LHSOffset, LHS))1306return false;13071308if (!loadComplexValue(RHSIsComplex, false, ElemIndex, RHSOffset, RHS))1309return false;13101311if (ResultElemT == PT_Float) {1312if (!this->emitMulf(getFPOptions(E), E))1313return false;1314} else {1315if (!this->emitMul(ResultElemT, E))1316return false;1317}1318break;1319case BO_Div:1320assert(!RHSIsComplex);1321if (!loadComplexValue(LHSIsComplex, false, ElemIndex, LHSOffset, LHS))1322return false;13231324if (!loadComplexValue(RHSIsComplex, false, ElemIndex, RHSOffset, RHS))1325return false;13261327if (ResultElemT == PT_Float) {1328if (!this->emitDivf(getFPOptions(E), E))1329return false;1330} else {1331if (!this->emitDiv(ResultElemT, E))1332return false;1333}1334break;13351336default:1337return false;1338}13391340if (!this->DiscardResult) {1341// Initialize array element with the value we just computed.1342if (!this->emitInitElemPop(ResultElemT, ElemIndex, E))1343return false;1344} else {1345if (!this->emitPop(ResultElemT, E))1346return false;1347}1348}1349return true;1350}13511352template <class Emitter>1353bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {1354assert(!E->isCommaOp() &&1355"Comma op should be handled in VisitBinaryOperator");1356assert(E->getType()->isVectorType());1357assert(E->getLHS()->getType()->isVectorType());1358assert(E->getRHS()->getType()->isVectorType());13591360// Prepare storage for result.1361if (!Initializing && !E->isCompoundAssignmentOp()) {1362std::optional<unsigned> LocalIndex = allocateTemporary(E);1363if (!LocalIndex)1364return false;1365if (!this->emitGetPtrLocal(*LocalIndex, E))1366return false;1367}13681369const Expr *LHS = E->getLHS();1370const Expr *RHS = E->getRHS();1371const auto *VecTy = E->getType()->getAs<VectorType>();1372auto Op = E->isCompoundAssignmentOp()1373? BinaryOperator::getOpForCompoundAssignment(E->getOpcode())1374: E->getOpcode();13751376PrimType ElemT = this->classifyVectorElementType(LHS->getType());1377PrimType RHSElemT = this->classifyVectorElementType(RHS->getType());1378PrimType ResultElemT = this->classifyVectorElementType(E->getType());13791380// Evaluate LHS and save value to LHSOffset.1381unsigned LHSOffset =1382this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);1383if (!this->visit(LHS))1384return false;1385if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))1386return false;13871388// Evaluate RHS and save value to RHSOffset.1389unsigned RHSOffset =1390this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);1391if (!this->visit(RHS))1392return false;1393if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))1394return false;13951396if (E->isCompoundAssignmentOp() && !this->emitGetLocal(PT_Ptr, LHSOffset, E))1397return false;13981399// BitAdd/BitOr/BitXor/Shl/Shr doesn't support bool type, we need perform the1400// integer promotion.1401bool NeedIntPromot = ElemT == PT_Bool && (E->isBitwiseOp() || E->isShiftOp());1402QualType PromotTy =1403Ctx.getASTContext().getPromotedIntegerType(Ctx.getASTContext().BoolTy);1404PrimType PromotT = classifyPrim(PromotTy);1405PrimType OpT = NeedIntPromot ? PromotT : ElemT;14061407auto getElem = [=](unsigned Offset, PrimType ElemT, unsigned Index) {1408if (!this->emitGetLocal(PT_Ptr, Offset, E))1409return false;1410if (!this->emitArrayElemPop(ElemT, Index, E))1411return false;1412if (E->isLogicalOp()) {1413if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))1414return false;1415if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))1416return false;1417} else if (NeedIntPromot) {1418if (!this->emitPrimCast(ElemT, PromotT, PromotTy, E))1419return false;1420}1421return true;1422};14231424#define EMIT_ARITH_OP(OP) \1425{ \1426if (ElemT == PT_Float) { \1427if (!this->emit##OP##f(getFPOptions(E), E)) \1428return false; \1429} else { \1430if (!this->emit##OP(ElemT, E)) \1431return false; \1432} \1433break; \1434}14351436for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {1437if (!getElem(LHSOffset, ElemT, I))1438return false;1439if (!getElem(RHSOffset, RHSElemT, I))1440return false;1441switch (Op) {1442case BO_Add:1443EMIT_ARITH_OP(Add)1444case BO_Sub:1445EMIT_ARITH_OP(Sub)1446case BO_Mul:1447EMIT_ARITH_OP(Mul)1448case BO_Div:1449EMIT_ARITH_OP(Div)1450case BO_Rem:1451if (!this->emitRem(ElemT, E))1452return false;1453break;1454case BO_And:1455if (!this->emitBitAnd(OpT, E))1456return false;1457break;1458case BO_Or:1459if (!this->emitBitOr(OpT, E))1460return false;1461break;1462case BO_Xor:1463if (!this->emitBitXor(OpT, E))1464return false;1465break;1466case BO_Shl:1467if (!this->emitShl(OpT, RHSElemT, E))1468return false;1469break;1470case BO_Shr:1471if (!this->emitShr(OpT, RHSElemT, E))1472return false;1473break;1474case BO_EQ:1475if (!this->emitEQ(ElemT, E))1476return false;1477break;1478case BO_NE:1479if (!this->emitNE(ElemT, E))1480return false;1481break;1482case BO_LE:1483if (!this->emitLE(ElemT, E))1484return false;1485break;1486case BO_LT:1487if (!this->emitLT(ElemT, E))1488return false;1489break;1490case BO_GE:1491if (!this->emitGE(ElemT, E))1492return false;1493break;1494case BO_GT:1495if (!this->emitGT(ElemT, E))1496return false;1497break;1498case BO_LAnd:1499// a && b is equivalent to a!=0 & b!=01500if (!this->emitBitAnd(ResultElemT, E))1501return false;1502break;1503case BO_LOr:1504// a || b is equivalent to a!=0 | b!=01505if (!this->emitBitOr(ResultElemT, E))1506return false;1507break;1508default:1509return this->emitInvalid(E);1510}15111512// The result of the comparison is a vector of the same width and number1513// of elements as the comparison operands with a signed integral element1514// type.1515//1516// https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html1517if (E->isComparisonOp()) {1518if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))1519return false;1520if (!this->emitNeg(ResultElemT, E))1521return false;1522}15231524// If we performed an integer promotion, we need to cast the compute result1525// into result vector element type.1526if (NeedIntPromot &&1527!this->emitPrimCast(PromotT, ResultElemT, VecTy->getElementType(), E))1528return false;15291530// Initialize array element with the value we just computed.1531if (!this->emitInitElem(ResultElemT, I, E))1532return false;1533}15341535if (DiscardResult && E->isCompoundAssignmentOp() && !this->emitPopPtr(E))1536return false;1537return true;1538}15391540template <class Emitter>1541bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {1542const Expr *LHS = E->getLHS();1543const Expr *RHS = E->getRHS();1544const ASTContext &ASTCtx = Ctx.getASTContext();15451546assert(LHS->getType()->isFixedPointType() ||1547RHS->getType()->isFixedPointType());15481549auto LHSSema = ASTCtx.getFixedPointSemantics(LHS->getType());1550auto LHSSemaInt = LHSSema.toOpaqueInt();1551auto RHSSema = ASTCtx.getFixedPointSemantics(RHS->getType());1552auto RHSSemaInt = RHSSema.toOpaqueInt();15531554if (!this->visit(LHS))1555return false;1556if (!LHS->getType()->isFixedPointType()) {1557if (!this->emitCastIntegralFixedPoint(classifyPrim(LHS->getType()),1558LHSSemaInt, E))1559return false;1560}15611562if (!this->visit(RHS))1563return false;1564if (!RHS->getType()->isFixedPointType()) {1565if (!this->emitCastIntegralFixedPoint(classifyPrim(RHS->getType()),1566RHSSemaInt, E))1567return false;1568}15691570// Convert the result to the target semantics.1571auto ConvertResult = [&](bool R) -> bool {1572if (!R)1573return false;1574auto ResultSema = ASTCtx.getFixedPointSemantics(E->getType()).toOpaqueInt();1575auto CommonSema = LHSSema.getCommonSemantics(RHSSema).toOpaqueInt();1576if (ResultSema != CommonSema)1577return this->emitCastFixedPoint(ResultSema, E);1578return true;1579};15801581auto MaybeCastToBool = [&](bool Result) {1582if (!Result)1583return false;1584PrimType T = classifyPrim(E);1585if (DiscardResult)1586return this->emitPop(T, E);1587if (T != PT_Bool)1588return this->emitCast(PT_Bool, T, E);1589return true;1590};15911592switch (E->getOpcode()) {1593case BO_EQ:1594return MaybeCastToBool(this->emitEQFixedPoint(E));1595case BO_NE:1596return MaybeCastToBool(this->emitNEFixedPoint(E));1597case BO_LT:1598return MaybeCastToBool(this->emitLTFixedPoint(E));1599case BO_LE:1600return MaybeCastToBool(this->emitLEFixedPoint(E));1601case BO_GT:1602return MaybeCastToBool(this->emitGTFixedPoint(E));1603case BO_GE:1604return MaybeCastToBool(this->emitGEFixedPoint(E));1605case BO_Add:1606return ConvertResult(this->emitAddFixedPoint(E));1607case BO_Sub:1608return ConvertResult(this->emitSubFixedPoint(E));1609case BO_Mul:1610return ConvertResult(this->emitMulFixedPoint(E));1611case BO_Div:1612return ConvertResult(this->emitDivFixedPoint(E));1613case BO_Shl:1614return ConvertResult(this->emitShiftFixedPoint(/*Left=*/true, E));1615case BO_Shr:1616return ConvertResult(this->emitShiftFixedPoint(/*Left=*/false, E));16171618default:1619return this->emitInvalid(E);1620}16211622llvm_unreachable("unhandled binop opcode");1623}16241625template <class Emitter>1626bool Compiler<Emitter>::VisitFixedPointUnaryOperator(const UnaryOperator *E) {1627const Expr *SubExpr = E->getSubExpr();1628assert(SubExpr->getType()->isFixedPointType());16291630switch (E->getOpcode()) {1631case UO_Plus:1632return this->delegate(SubExpr);1633case UO_Minus:1634if (!this->visit(SubExpr))1635return false;1636return this->emitNegFixedPoint(E);1637default:1638return false;1639}16401641llvm_unreachable("Unhandled unary opcode");1642}16431644template <class Emitter>1645bool Compiler<Emitter>::VisitImplicitValueInitExpr(1646const ImplicitValueInitExpr *E) {1647QualType QT = E->getType();16481649if (std::optional<PrimType> T = classify(QT))1650return this->visitZeroInitializer(*T, QT, E);16511652if (QT->isRecordType()) {1653const RecordDecl *RD = QT->getAsRecordDecl();1654assert(RD);1655if (RD->isInvalidDecl())1656return false;16571658if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);1659CXXRD && CXXRD->getNumVBases() > 0) {1660// TODO: Diagnose.1661return false;1662}16631664const Record *R = getRecord(QT);1665if (!R)1666return false;16671668assert(Initializing);1669return this->visitZeroRecordInitializer(R, E);1670}16711672if (QT->isIncompleteArrayType())1673return true;16741675if (QT->isArrayType())1676return this->visitZeroArrayInitializer(QT, E);16771678if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {1679assert(Initializing);1680QualType ElemQT = ComplexTy->getElementType();1681PrimType ElemT = classifyPrim(ElemQT);1682for (unsigned I = 0; I < 2; ++I) {1683if (!this->visitZeroInitializer(ElemT, ElemQT, E))1684return false;1685if (!this->emitInitElem(ElemT, I, E))1686return false;1687}1688return true;1689}16901691if (const auto *VecT = E->getType()->getAs<VectorType>()) {1692unsigned NumVecElements = VecT->getNumElements();1693QualType ElemQT = VecT->getElementType();1694PrimType ElemT = classifyPrim(ElemQT);16951696for (unsigned I = 0; I < NumVecElements; ++I) {1697if (!this->visitZeroInitializer(ElemT, ElemQT, E))1698return false;1699if (!this->emitInitElem(ElemT, I, E))1700return false;1701}1702return true;1703}17041705return false;1706}17071708template <class Emitter>1709bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {1710const Expr *LHS = E->getLHS();1711const Expr *RHS = E->getRHS();1712const Expr *Index = E->getIdx();1713const Expr *Base = E->getBase();17141715// C++17's rules require us to evaluate the LHS first, regardless of which1716// side is the base.1717bool Success = true;1718for (const Expr *SubExpr : {LHS, RHS}) {1719if (!this->visit(SubExpr)) {1720Success = false;1721continue;1722}17231724// Expand the base if this is a subscript on a1725// pointer expression.1726if (SubExpr == Base && Base->getType()->isPointerType()) {1727if (!this->emitExpandPtr(E))1728Success = false;1729}1730}17311732if (!Success)1733return false;17341735std::optional<PrimType> IndexT = classify(Index->getType());1736// In error-recovery cases, the index expression has a dependent type.1737if (!IndexT)1738return this->emitError(E);1739// If the index is first, we need to change that.1740if (LHS == Index) {1741if (!this->emitFlip(PT_Ptr, *IndexT, E))1742return false;1743}17441745if (!this->emitArrayElemPtrPop(*IndexT, E))1746return false;1747if (DiscardResult)1748return this->emitPopPtr(E);1749return true;1750}17511752template <class Emitter>1753bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,1754const Expr *ArrayFiller, const Expr *E) {1755InitLinkScope<Emitter> ILS(this, InitLink::InitList());17561757QualType QT = E->getType();1758if (const auto *AT = QT->getAs<AtomicType>())1759QT = AT->getValueType();17601761if (QT->isVoidType()) {1762if (Inits.size() == 0)1763return true;1764return this->emitInvalid(E);1765}17661767// Handle discarding first.1768if (DiscardResult) {1769for (const Expr *Init : Inits) {1770if (!this->discard(Init))1771return false;1772}1773return true;1774}17751776// Primitive values.1777if (std::optional<PrimType> T = classify(QT)) {1778assert(!DiscardResult);1779if (Inits.size() == 0)1780return this->visitZeroInitializer(*T, QT, E);1781assert(Inits.size() == 1);1782return this->delegate(Inits[0]);1783}17841785if (QT->isRecordType()) {1786const Record *R = getRecord(QT);17871788if (Inits.size() == 1 && E->getType() == Inits[0]->getType())1789return this->delegate(Inits[0]);17901791auto initPrimitiveField = [=](const Record::Field *FieldToInit,1792const Expr *Init, PrimType T) -> bool {1793InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));1794InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));1795if (!this->visit(Init))1796return false;17971798if (FieldToInit->isBitField())1799return this->emitInitBitField(T, FieldToInit, E);1800return this->emitInitField(T, FieldToInit->Offset, E);1801};18021803auto initCompositeField = [=](const Record::Field *FieldToInit,1804const Expr *Init) -> bool {1805InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));1806InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));18071808// Non-primitive case. Get a pointer to the field-to-initialize1809// on the stack and recurse into visitInitializer().1810if (!this->emitGetPtrField(FieldToInit->Offset, Init))1811return false;1812if (!this->visitInitializer(Init))1813return false;1814return this->emitPopPtr(E);1815};18161817if (R->isUnion()) {1818if (Inits.size() == 0) {1819if (!this->visitZeroRecordInitializer(R, E))1820return false;1821} else {1822const Expr *Init = Inits[0];1823const FieldDecl *FToInit = nullptr;1824if (const auto *ILE = dyn_cast<InitListExpr>(E))1825FToInit = ILE->getInitializedFieldInUnion();1826else1827FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion();18281829const Record::Field *FieldToInit = R->getField(FToInit);1830if (std::optional<PrimType> T = classify(Init)) {1831if (!initPrimitiveField(FieldToInit, Init, *T))1832return false;1833} else {1834if (!initCompositeField(FieldToInit, Init))1835return false;1836}1837}1838return this->emitFinishInit(E);1839}18401841assert(!R->isUnion());1842unsigned InitIndex = 0;1843for (const Expr *Init : Inits) {1844// Skip unnamed bitfields.1845while (InitIndex < R->getNumFields() &&1846R->getField(InitIndex)->isUnnamedBitField())1847++InitIndex;18481849if (std::optional<PrimType> T = classify(Init)) {1850const Record::Field *FieldToInit = R->getField(InitIndex);1851if (!initPrimitiveField(FieldToInit, Init, *T))1852return false;1853++InitIndex;1854} else {1855// Initializer for a direct base class.1856if (const Record::Base *B = R->getBase(Init->getType())) {1857if (!this->emitGetPtrBase(B->Offset, Init))1858return false;18591860if (!this->visitInitializer(Init))1861return false;18621863if (!this->emitFinishInitPop(E))1864return false;1865// Base initializers don't increase InitIndex, since they don't count1866// into the Record's fields.1867} else {1868const Record::Field *FieldToInit = R->getField(InitIndex);1869if (!initCompositeField(FieldToInit, Init))1870return false;1871++InitIndex;1872}1873}1874}1875return this->emitFinishInit(E);1876}18771878if (QT->isArrayType()) {1879if (Inits.size() == 1 && QT == Inits[0]->getType())1880return this->delegate(Inits[0]);18811882const ConstantArrayType *CAT =1883Ctx.getASTContext().getAsConstantArrayType(QT);1884uint64_t NumElems = CAT->getZExtSize();18851886if (!this->emitCheckArraySize(NumElems, E))1887return false;18881889std::optional<PrimType> InitT = classify(CAT->getElementType());1890unsigned ElementIndex = 0;1891for (const Expr *Init : Inits) {1892if (const auto *EmbedS =1893dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) {1894PrimType TargetT = classifyPrim(Init->getType());18951896auto Eval = [&](const Expr *Init, unsigned ElemIndex) {1897PrimType InitT = classifyPrim(Init->getType());1898if (!this->visit(Init))1899return false;1900if (InitT != TargetT) {1901if (!this->emitCast(InitT, TargetT, E))1902return false;1903}1904return this->emitInitElem(TargetT, ElemIndex, Init);1905};1906if (!EmbedS->doForEachDataElement(Eval, ElementIndex))1907return false;1908} else {1909if (!this->visitArrayElemInit(ElementIndex, Init, InitT))1910return false;1911++ElementIndex;1912}1913}19141915// Expand the filler expression.1916// FIXME: This should go away.1917if (ArrayFiller) {1918for (; ElementIndex != NumElems; ++ElementIndex) {1919if (!this->visitArrayElemInit(ElementIndex, ArrayFiller, InitT))1920return false;1921}1922}19231924return this->emitFinishInit(E);1925}19261927if (const auto *ComplexTy = QT->getAs<ComplexType>()) {1928unsigned NumInits = Inits.size();19291930if (NumInits == 1)1931return this->delegate(Inits[0]);19321933QualType ElemQT = ComplexTy->getElementType();1934PrimType ElemT = classifyPrim(ElemQT);1935if (NumInits == 0) {1936// Zero-initialize both elements.1937for (unsigned I = 0; I < 2; ++I) {1938if (!this->visitZeroInitializer(ElemT, ElemQT, E))1939return false;1940if (!this->emitInitElem(ElemT, I, E))1941return false;1942}1943} else if (NumInits == 2) {1944unsigned InitIndex = 0;1945for (const Expr *Init : Inits) {1946if (!this->visit(Init))1947return false;19481949if (!this->emitInitElem(ElemT, InitIndex, E))1950return false;1951++InitIndex;1952}1953}1954return true;1955}19561957if (const auto *VecT = QT->getAs<VectorType>()) {1958unsigned NumVecElements = VecT->getNumElements();1959assert(NumVecElements >= Inits.size());19601961QualType ElemQT = VecT->getElementType();1962PrimType ElemT = classifyPrim(ElemQT);19631964// All initializer elements.1965unsigned InitIndex = 0;1966for (const Expr *Init : Inits) {1967if (!this->visit(Init))1968return false;19691970// If the initializer is of vector type itself, we have to deconstruct1971// that and initialize all the target fields from the initializer fields.1972if (const auto *InitVecT = Init->getType()->getAs<VectorType>()) {1973if (!this->emitCopyArray(ElemT, 0, InitIndex,1974InitVecT->getNumElements(), E))1975return false;1976InitIndex += InitVecT->getNumElements();1977} else {1978if (!this->emitInitElem(ElemT, InitIndex, E))1979return false;1980++InitIndex;1981}1982}19831984assert(InitIndex <= NumVecElements);19851986// Fill the rest with zeroes.1987for (; InitIndex != NumVecElements; ++InitIndex) {1988if (!this->visitZeroInitializer(ElemT, ElemQT, E))1989return false;1990if (!this->emitInitElem(ElemT, InitIndex, E))1991return false;1992}1993return true;1994}19951996return false;1997}19981999/// Pointer to the array(not the element!) must be on the stack when calling2000/// this.2001template <class Emitter>2002bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex, const Expr *Init,2003std::optional<PrimType> InitT) {2004if (InitT) {2005// Visit the primitive element like normal.2006if (!this->visit(Init))2007return false;2008return this->emitInitElem(*InitT, ElemIndex, Init);2009}20102011InitLinkScope<Emitter> ILS(this, InitLink::Elem(ElemIndex));2012// Advance the pointer currently on the stack to the given2013// dimension.2014if (!this->emitConstUint32(ElemIndex, Init))2015return false;2016if (!this->emitArrayElemPtrUint32(Init))2017return false;2018if (!this->visitInitializer(Init))2019return false;2020return this->emitFinishInitPop(Init);2021}20222023template <class Emitter>2024bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,2025const FunctionDecl *FuncDecl) {2026assert(VarScope->getKind() == ScopeKind::Call);2027llvm::BitVector NonNullArgs = collectNonNullArgs(FuncDecl, Args);20282029unsigned ArgIndex = 0;2030for (const Expr *Arg : Args) {2031if (std::optional<PrimType> T = classify(Arg)) {2032if (!this->visit(Arg))2033return false;2034} else {20352036std::optional<unsigned> LocalIndex = allocateLocal(2037Arg, Arg->getType(), /*ExtendingDecl=*/nullptr, ScopeKind::Call);2038if (!LocalIndex)2039return false;20402041if (!this->emitGetPtrLocal(*LocalIndex, Arg))2042return false;2043InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));2044if (!this->visitInitializer(Arg))2045return false;2046}20472048if (FuncDecl && NonNullArgs[ArgIndex]) {2049PrimType ArgT = classify(Arg).value_or(PT_Ptr);2050if (ArgT == PT_Ptr) {2051if (!this->emitCheckNonNullArg(ArgT, Arg))2052return false;2053}2054}20552056++ArgIndex;2057}20582059return true;2060}20612062template <class Emitter>2063bool Compiler<Emitter>::VisitInitListExpr(const InitListExpr *E) {2064return this->visitInitList(E->inits(), E->getArrayFiller(), E);2065}20662067template <class Emitter>2068bool Compiler<Emitter>::VisitCXXParenListInitExpr(2069const CXXParenListInitExpr *E) {2070return this->visitInitList(E->getInitExprs(), E->getArrayFiller(), E);2071}20722073template <class Emitter>2074bool Compiler<Emitter>::VisitSubstNonTypeTemplateParmExpr(2075const SubstNonTypeTemplateParmExpr *E) {2076return this->delegate(E->getReplacement());2077}20782079template <class Emitter>2080bool Compiler<Emitter>::VisitConstantExpr(const ConstantExpr *E) {2081std::optional<PrimType> T = classify(E->getType());2082if (T && E->hasAPValueResult()) {2083// Try to emit the APValue directly, without visiting the subexpr.2084// This will only fail if we can't emit the APValue, so won't emit any2085// diagnostics or any double values.2086if (DiscardResult)2087return true;20882089if (this->visitAPValue(E->getAPValueResult(), *T, E))2090return true;2091}2092return this->delegate(E->getSubExpr());2093}20942095template <class Emitter>2096bool Compiler<Emitter>::VisitEmbedExpr(const EmbedExpr *E) {2097auto It = E->begin();2098return this->visit(*It);2099}21002101static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,2102UnaryExprOrTypeTrait Kind) {2103bool AlignOfReturnsPreferred =2104ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;21052106// C++ [expr.alignof]p3:2107// When alignof is applied to a reference type, the result is the2108// alignment of the referenced type.2109if (const auto *Ref = T->getAs<ReferenceType>())2110T = Ref->getPointeeType();21112112if (T.getQualifiers().hasUnaligned())2113return CharUnits::One();21142115// __alignof is defined to return the preferred alignment.2116// Before 8, clang returned the preferred alignment for alignof and2117// _Alignof as well.2118if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)2119return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));21202121return ASTCtx.getTypeAlignInChars(T);2122}21232124template <class Emitter>2125bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(2126const UnaryExprOrTypeTraitExpr *E) {2127UnaryExprOrTypeTrait Kind = E->getKind();2128const ASTContext &ASTCtx = Ctx.getASTContext();21292130if (Kind == UETT_SizeOf || Kind == UETT_DataSizeOf) {2131QualType ArgType = E->getTypeOfArgument();21322133// C++ [expr.sizeof]p2: "When applied to a reference or a reference type,2134// the result is the size of the referenced type."2135if (const auto *Ref = ArgType->getAs<ReferenceType>())2136ArgType = Ref->getPointeeType();21372138CharUnits Size;2139if (ArgType->isVoidType() || ArgType->isFunctionType())2140Size = CharUnits::One();2141else {2142if (ArgType->isDependentType() || !ArgType->isConstantSizeType())2143return this->emitInvalid(E);21442145if (Kind == UETT_SizeOf)2146Size = ASTCtx.getTypeSizeInChars(ArgType);2147else2148Size = ASTCtx.getTypeInfoDataSizeInChars(ArgType).Width;2149}21502151if (DiscardResult)2152return true;21532154return this->emitConst(Size.getQuantity(), E);2155}21562157if (Kind == UETT_CountOf) {2158QualType Ty = E->getTypeOfArgument();2159assert(Ty->isArrayType());21602161// We don't need to worry about array element qualifiers, so getting the2162// unsafe array type is fine.2163if (const auto *CAT =2164dyn_cast<ConstantArrayType>(Ty->getAsArrayTypeUnsafe())) {2165if (DiscardResult)2166return true;2167return this->emitConst(CAT->getSize(), E);2168}21692170assert(!Ty->isConstantSizeType());21712172// If it's a variable-length array type, we need to check whether it is a2173// multidimensional array. If so, we need to check the size expression of2174// the VLA to see if it's a constant size. If so, we can return that value.2175const auto *VAT = ASTCtx.getAsVariableArrayType(Ty);2176assert(VAT);2177if (VAT->getElementType()->isArrayType()) {2178std::optional<APSInt> Res =2179VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx);2180if (Res) {2181if (DiscardResult)2182return true;2183return this->emitConst(*Res, E);2184}2185}2186}21872188if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {2189CharUnits Size;21902191if (E->isArgumentType()) {2192QualType ArgType = E->getTypeOfArgument();21932194Size = AlignOfType(ArgType, ASTCtx, Kind);2195} else {2196// Argument is an expression, not a type.2197const Expr *Arg = E->getArgumentExpr()->IgnoreParens();21982199// The kinds of expressions that we have special-case logic here for2200// should be kept up to date with the special checks for those2201// expressions in Sema.22022203// alignof decl is always accepted, even if it doesn't make sense: we2204// default to 1 in those cases.2205if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))2206Size = ASTCtx.getDeclAlign(DRE->getDecl(),2207/*RefAsPointee*/ true);2208else if (const auto *ME = dyn_cast<MemberExpr>(Arg))2209Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),2210/*RefAsPointee*/ true);2211else2212Size = AlignOfType(Arg->getType(), ASTCtx, Kind);2213}22142215if (DiscardResult)2216return true;22172218return this->emitConst(Size.getQuantity(), E);2219}22202221if (Kind == UETT_VectorElements) {2222if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>())2223return this->emitConst(VT->getNumElements(), E);2224assert(E->getTypeOfArgument()->isSizelessVectorType());2225return this->emitSizelessVectorElementSize(E);2226}22272228if (Kind == UETT_VecStep) {2229if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>()) {2230unsigned N = VT->getNumElements();22312232// The vec_step built-in functions that take a 3-component2233// vector return 4. (OpenCL 1.1 spec 6.11.12)2234if (N == 3)2235N = 4;22362237return this->emitConst(N, E);2238}2239return this->emitConst(1, E);2240}22412242if (Kind == UETT_OpenMPRequiredSimdAlign) {2243assert(E->isArgumentType());2244unsigned Bits = ASTCtx.getOpenMPDefaultSimdAlign(E->getArgumentType());22452246return this->emitConst(ASTCtx.toCharUnitsFromBits(Bits).getQuantity(), E);2247}22482249if (Kind == UETT_PtrAuthTypeDiscriminator) {2250if (E->getArgumentType()->isDependentType())2251return this->emitInvalid(E);22522253return this->emitConst(2254const_cast<ASTContext &>(ASTCtx).getPointerAuthTypeDiscriminator(2255E->getArgumentType()),2256E);2257}22582259return false;2260}22612262template <class Emitter>2263bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {2264// 'Base.Member'2265const Expr *Base = E->getBase();2266const ValueDecl *Member = E->getMemberDecl();22672268if (DiscardResult)2269return this->discard(Base);22702271// MemberExprs are almost always lvalues, in which case we don't need to2272// do the load. But sometimes they aren't.2273const auto maybeLoadValue = [&]() -> bool {2274if (E->isGLValue())2275return true;2276if (std::optional<PrimType> T = classify(E))2277return this->emitLoadPop(*T, E);2278return false;2279};22802281if (const auto *VD = dyn_cast<VarDecl>(Member)) {2282// I am almost confident in saying that a var decl must be static2283// and therefore registered as a global variable. But this will probably2284// turn out to be wrong some time in the future, as always.2285if (auto GlobalIndex = P.getGlobal(VD))2286return this->emitGetPtrGlobal(*GlobalIndex, E) && maybeLoadValue();2287return false;2288}22892290if (!isa<FieldDecl>(Member)) {2291if (!this->discard(Base) && !this->emitSideEffect(E))2292return false;22932294return this->visitDeclRef(Member, E);2295}22962297if (Initializing) {2298if (!this->delegate(Base))2299return false;2300} else {2301if (!this->visit(Base))2302return false;2303}23042305// Base above gives us a pointer on the stack.2306const auto *FD = cast<FieldDecl>(Member);2307const RecordDecl *RD = FD->getParent();2308const Record *R = getRecord(RD);2309if (!R)2310return false;2311const Record::Field *F = R->getField(FD);2312// Leave a pointer to the field on the stack.2313if (F->Decl->getType()->isReferenceType())2314return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();2315return this->emitGetPtrFieldPop(F->Offset, E) && maybeLoadValue();2316}23172318template <class Emitter>2319bool Compiler<Emitter>::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {2320// ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated2321// stand-alone, e.g. via EvaluateAsInt().2322if (!ArrayIndex)2323return false;2324return this->emitConst(*ArrayIndex, E);2325}23262327template <class Emitter>2328bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {2329assert(Initializing);2330assert(!DiscardResult);23312332// We visit the common opaque expression here once so we have its value2333// cached.2334if (!this->discard(E->getCommonExpr()))2335return false;23362337// TODO: This compiles to quite a lot of bytecode if the array is larger.2338// Investigate compiling this to a loop.2339const Expr *SubExpr = E->getSubExpr();2340size_t Size = E->getArraySize().getZExtValue();2341std::optional<PrimType> SubExprT = classify(SubExpr);23422343// So, every iteration, we execute an assignment here2344// where the LHS is on the stack (the target array)2345// and the RHS is our SubExpr.2346for (size_t I = 0; I != Size; ++I) {2347ArrayIndexScope<Emitter> IndexScope(this, I);2348BlockScope<Emitter> BS(this);23492350if (!this->visitArrayElemInit(I, SubExpr, SubExprT))2351return false;2352if (!BS.destroyLocals())2353return false;2354}2355return true;2356}23572358template <class Emitter>2359bool Compiler<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {2360const Expr *SourceExpr = E->getSourceExpr();2361if (!SourceExpr)2362return false;23632364if (Initializing)2365return this->visitInitializer(SourceExpr);23662367PrimType SubExprT = classify(SourceExpr).value_or(PT_Ptr);2368if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end())2369return this->emitGetLocal(SubExprT, It->second, E);23702371if (!this->visit(SourceExpr))2372return false;23732374// At this point we either have the evaluated source expression or a pointer2375// to an object on the stack. We want to create a local variable that stores2376// this value.2377unsigned LocalIndex = allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true);2378if (!this->emitSetLocal(SubExprT, LocalIndex, E))2379return false;23802381// Here the local variable is created but the value is removed from the stack,2382// so we put it back if the caller needs it.2383if (!DiscardResult) {2384if (!this->emitGetLocal(SubExprT, LocalIndex, E))2385return false;2386}23872388// This is cleaned up when the local variable is destroyed.2389OpaqueExprs.insert({E, LocalIndex});23902391return true;2392}23932394template <class Emitter>2395bool Compiler<Emitter>::VisitAbstractConditionalOperator(2396const AbstractConditionalOperator *E) {2397const Expr *Condition = E->getCond();2398const Expr *TrueExpr = E->getTrueExpr();2399const Expr *FalseExpr = E->getFalseExpr();24002401auto visitChildExpr = [&](const Expr *E) -> bool {2402LocalScope<Emitter> S(this);2403if (!this->delegate(E))2404return false;2405return S.destroyLocals();2406};24072408if (std::optional<bool> BoolValue = getBoolValue(Condition)) {2409if (BoolValue)2410return visitChildExpr(TrueExpr);2411return visitChildExpr(FalseExpr);2412}24132414bool IsBcpCall = false;2415if (const auto *CE = dyn_cast<CallExpr>(Condition->IgnoreParenCasts());2416CE && CE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) {2417IsBcpCall = true;2418}24192420LabelTy LabelEnd = this->getLabel(); // Label after the operator.2421LabelTy LabelFalse = this->getLabel(); // Label for the false expr.24222423if (IsBcpCall) {2424if (!this->emitStartSpeculation(E))2425return false;2426}24272428if (!this->visitBool(Condition)) {2429// If the condition failed and we're checking for undefined behavior2430// (which only happens with EvalEmitter) check the TrueExpr and FalseExpr2431// as well.2432if (this->checkingForUndefinedBehavior()) {2433if (!this->discard(TrueExpr))2434return false;2435if (!this->discard(FalseExpr))2436return false;2437}2438return false;2439}24402441if (!this->jumpFalse(LabelFalse))2442return false;2443if (!visitChildExpr(TrueExpr))2444return false;2445if (!this->jump(LabelEnd))2446return false;2447this->emitLabel(LabelFalse);2448if (!visitChildExpr(FalseExpr))2449return false;2450this->fallthrough(LabelEnd);2451this->emitLabel(LabelEnd);24522453if (IsBcpCall)2454return this->emitEndSpeculation(E);2455return true;2456}24572458template <class Emitter>2459bool Compiler<Emitter>::VisitStringLiteral(const StringLiteral *E) {2460if (DiscardResult)2461return true;24622463if (!Initializing) {2464unsigned StringIndex = P.createGlobalString(E);2465return this->emitGetPtrGlobal(StringIndex, E);2466}24672468// We are initializing an array on the stack.2469const ConstantArrayType *CAT =2470Ctx.getASTContext().getAsConstantArrayType(E->getType());2471assert(CAT && "a string literal that's not a constant array?");24722473// If the initializer string is too long, a diagnostic has already been2474// emitted. Read only the array length from the string literal.2475unsigned ArraySize = CAT->getZExtSize();2476unsigned N = std::min(ArraySize, E->getLength());2477unsigned CharWidth = E->getCharByteWidth();24782479for (unsigned I = 0; I != N; ++I) {2480uint32_t CodeUnit = E->getCodeUnit(I);24812482if (CharWidth == 1) {2483this->emitConstSint8(CodeUnit, E);2484this->emitInitElemSint8(I, E);2485} else if (CharWidth == 2) {2486this->emitConstUint16(CodeUnit, E);2487this->emitInitElemUint16(I, E);2488} else if (CharWidth == 4) {2489this->emitConstUint32(CodeUnit, E);2490this->emitInitElemUint32(I, E);2491} else {2492llvm_unreachable("unsupported character width");2493}2494}24952496// Fill up the rest of the char array with NUL bytes.2497for (unsigned I = N; I != ArraySize; ++I) {2498if (CharWidth == 1) {2499this->emitConstSint8(0, E);2500this->emitInitElemSint8(I, E);2501} else if (CharWidth == 2) {2502this->emitConstUint16(0, E);2503this->emitInitElemUint16(I, E);2504} else if (CharWidth == 4) {2505this->emitConstUint32(0, E);2506this->emitInitElemUint32(I, E);2507} else {2508llvm_unreachable("unsupported character width");2509}2510}25112512return true;2513}25142515template <class Emitter>2516bool Compiler<Emitter>::VisitObjCStringLiteral(const ObjCStringLiteral *E) {2517if (DiscardResult)2518return true;2519return this->emitDummyPtr(E, E);2520}25212522template <class Emitter>2523bool Compiler<Emitter>::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {2524auto &A = Ctx.getASTContext();2525std::string Str;2526A.getObjCEncodingForType(E->getEncodedType(), Str);2527StringLiteral *SL =2528StringLiteral::Create(A, Str, StringLiteralKind::Ordinary,2529/*Pascal=*/false, E->getType(), E->getAtLoc());2530return this->delegate(SL);2531}25322533template <class Emitter>2534bool Compiler<Emitter>::VisitSYCLUniqueStableNameExpr(2535const SYCLUniqueStableNameExpr *E) {2536if (DiscardResult)2537return true;25382539assert(!Initializing);25402541auto &A = Ctx.getASTContext();2542std::string ResultStr = E->ComputeName(A);25432544QualType CharTy = A.CharTy.withConst();2545APInt Size(A.getTypeSize(A.getSizeType()), ResultStr.size() + 1);2546QualType ArrayTy = A.getConstantArrayType(CharTy, Size, nullptr,2547ArraySizeModifier::Normal, 0);25482549StringLiteral *SL =2550StringLiteral::Create(A, ResultStr, StringLiteralKind::Ordinary,2551/*Pascal=*/false, ArrayTy, E->getLocation());25522553unsigned StringIndex = P.createGlobalString(SL);2554return this->emitGetPtrGlobal(StringIndex, E);2555}25562557template <class Emitter>2558bool Compiler<Emitter>::VisitCharacterLiteral(const CharacterLiteral *E) {2559if (DiscardResult)2560return true;2561return this->emitConst(E->getValue(), E);2562}25632564template <class Emitter>2565bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(2566const CompoundAssignOperator *E) {25672568const Expr *LHS = E->getLHS();2569const Expr *RHS = E->getRHS();2570QualType LHSType = LHS->getType();2571QualType LHSComputationType = E->getComputationLHSType();2572QualType ResultType = E->getComputationResultType();2573std::optional<PrimType> LT = classify(LHSComputationType);2574std::optional<PrimType> RT = classify(ResultType);25752576assert(ResultType->isFloatingType());25772578if (!LT || !RT)2579return false;25802581PrimType LHST = classifyPrim(LHSType);25822583// C++17 onwards require that we evaluate the RHS first.2584// Compute RHS and save it in a temporary variable so we can2585// load it again later.2586if (!visit(RHS))2587return false;25882589unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);2590if (!this->emitSetLocal(*RT, TempOffset, E))2591return false;25922593// First, visit LHS.2594if (!visit(LHS))2595return false;2596if (!this->emitLoad(LHST, E))2597return false;25982599// If necessary, convert LHS to its computation type.2600if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType),2601LHSComputationType, E))2602return false;26032604// Now load RHS.2605if (!this->emitGetLocal(*RT, TempOffset, E))2606return false;26072608switch (E->getOpcode()) {2609case BO_AddAssign:2610if (!this->emitAddf(getFPOptions(E), E))2611return false;2612break;2613case BO_SubAssign:2614if (!this->emitSubf(getFPOptions(E), E))2615return false;2616break;2617case BO_MulAssign:2618if (!this->emitMulf(getFPOptions(E), E))2619return false;2620break;2621case BO_DivAssign:2622if (!this->emitDivf(getFPOptions(E), E))2623return false;2624break;2625default:2626return false;2627}26282629if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->getType(), E))2630return false;26312632if (DiscardResult)2633return this->emitStorePop(LHST, E);2634return this->emitStore(LHST, E);2635}26362637template <class Emitter>2638bool Compiler<Emitter>::VisitPointerCompoundAssignOperator(2639const CompoundAssignOperator *E) {2640BinaryOperatorKind Op = E->getOpcode();2641const Expr *LHS = E->getLHS();2642const Expr *RHS = E->getRHS();2643std::optional<PrimType> LT = classify(LHS->getType());2644std::optional<PrimType> RT = classify(RHS->getType());26452646if (Op != BO_AddAssign && Op != BO_SubAssign)2647return false;26482649if (!LT || !RT)2650return false;26512652if (!visit(LHS))2653return false;26542655if (!this->emitLoad(*LT, LHS))2656return false;26572658if (!visit(RHS))2659return false;26602661if (Op == BO_AddAssign) {2662if (!this->emitAddOffset(*RT, E))2663return false;2664} else {2665if (!this->emitSubOffset(*RT, E))2666return false;2667}26682669if (DiscardResult)2670return this->emitStorePopPtr(E);2671return this->emitStorePtr(E);2672}26732674template <class Emitter>2675bool Compiler<Emitter>::VisitCompoundAssignOperator(2676const CompoundAssignOperator *E) {2677if (E->getType()->isVectorType())2678return VisitVectorBinOp(E);26792680const Expr *LHS = E->getLHS();2681const Expr *RHS = E->getRHS();2682std::optional<PrimType> LHSComputationT =2683classify(E->getComputationLHSType());2684std::optional<PrimType> LT = classify(LHS->getType());2685std::optional<PrimType> RT = classify(RHS->getType());2686std::optional<PrimType> ResultT = classify(E->getType());26872688if (!Ctx.getLangOpts().CPlusPlus14)2689return this->visit(RHS) && this->visit(LHS) && this->emitError(E);26902691if (!LT || !RT || !ResultT || !LHSComputationT)2692return false;26932694// Handle floating point operations separately here, since they2695// require special care.26962697if (ResultT == PT_Float || RT == PT_Float)2698return VisitFloatCompoundAssignOperator(E);26992700if (E->getType()->isPointerType())2701return VisitPointerCompoundAssignOperator(E);27022703assert(!E->getType()->isPointerType() && "Handled above");2704assert(!E->getType()->isFloatingType() && "Handled above");27052706// C++17 onwards require that we evaluate the RHS first.2707// Compute RHS and save it in a temporary variable so we can2708// load it again later.2709// FIXME: Compound assignments are unsequenced in C, so we might2710// have to figure out how to reject them.2711if (!visit(RHS))2712return false;27132714unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);27152716if (!this->emitSetLocal(*RT, TempOffset, E))2717return false;27182719// Get LHS pointer, load its value and cast it to the2720// computation type if necessary.2721if (!visit(LHS))2722return false;2723if (!this->emitLoad(*LT, E))2724return false;2725if (LT != LHSComputationT) {2726if (!this->emitCast(*LT, *LHSComputationT, E))2727return false;2728}27292730// Get the RHS value on the stack.2731if (!this->emitGetLocal(*RT, TempOffset, E))2732return false;27332734// Perform operation.2735switch (E->getOpcode()) {2736case BO_AddAssign:2737if (!this->emitAdd(*LHSComputationT, E))2738return false;2739break;2740case BO_SubAssign:2741if (!this->emitSub(*LHSComputationT, E))2742return false;2743break;2744case BO_MulAssign:2745if (!this->emitMul(*LHSComputationT, E))2746return false;2747break;2748case BO_DivAssign:2749if (!this->emitDiv(*LHSComputationT, E))2750return false;2751break;2752case BO_RemAssign:2753if (!this->emitRem(*LHSComputationT, E))2754return false;2755break;2756case BO_ShlAssign:2757if (!this->emitShl(*LHSComputationT, *RT, E))2758return false;2759break;2760case BO_ShrAssign:2761if (!this->emitShr(*LHSComputationT, *RT, E))2762return false;2763break;2764case BO_AndAssign:2765if (!this->emitBitAnd(*LHSComputationT, E))2766return false;2767break;2768case BO_XorAssign:2769if (!this->emitBitXor(*LHSComputationT, E))2770return false;2771break;2772case BO_OrAssign:2773if (!this->emitBitOr(*LHSComputationT, E))2774return false;2775break;2776default:2777llvm_unreachable("Unimplemented compound assign operator");2778}27792780// And now cast from LHSComputationT to ResultT.2781if (ResultT != LHSComputationT) {2782if (!this->emitCast(*LHSComputationT, *ResultT, E))2783return false;2784}27852786// And store the result in LHS.2787if (DiscardResult) {2788if (LHS->refersToBitField())2789return this->emitStoreBitFieldPop(*ResultT, E);2790return this->emitStorePop(*ResultT, E);2791}2792if (LHS->refersToBitField())2793return this->emitStoreBitField(*ResultT, E);2794return this->emitStore(*ResultT, E);2795}27962797template <class Emitter>2798bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) {2799LocalScope<Emitter> ES(this);2800const Expr *SubExpr = E->getSubExpr();28012802return this->delegate(SubExpr) && ES.destroyLocals(E);2803}28042805template <class Emitter>2806bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(2807const MaterializeTemporaryExpr *E) {2808const Expr *SubExpr = E->getSubExpr();28092810if (Initializing) {2811// We already have a value, just initialize that.2812return this->delegate(SubExpr);2813}2814// If we don't end up using the materialized temporary anyway, don't2815// bother creating it.2816if (DiscardResult)2817return this->discard(SubExpr);28182819// When we're initializing a global variable *or* the storage duration of2820// the temporary is explicitly static, create a global variable.2821std::optional<PrimType> SubExprT = classify(SubExpr);2822bool IsStatic = E->getStorageDuration() == SD_Static;2823if (IsStatic) {2824std::optional<unsigned> GlobalIndex = P.createGlobal(E);2825if (!GlobalIndex)2826return false;28272828const LifetimeExtendedTemporaryDecl *TempDecl =2829E->getLifetimeExtendedTemporaryDecl();2830if (IsStatic)2831assert(TempDecl);28322833if (SubExprT) {2834if (!this->visit(SubExpr))2835return false;2836if (IsStatic) {2837if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))2838return false;2839} else {2840if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E))2841return false;2842}2843return this->emitGetPtrGlobal(*GlobalIndex, E);2844}28452846if (!this->checkLiteralType(SubExpr))2847return false;2848// Non-primitive values.2849if (!this->emitGetPtrGlobal(*GlobalIndex, E))2850return false;2851if (!this->visitInitializer(SubExpr))2852return false;2853if (IsStatic)2854return this->emitInitGlobalTempComp(TempDecl, E);2855return true;2856}28572858// For everyhing else, use local variables.2859if (SubExprT) {2860bool IsConst = SubExpr->getType().isConstQualified();2861unsigned LocalIndex =2862allocateLocalPrimitive(E, *SubExprT, IsConst, E->getExtendingDecl());2863if (!this->visit(SubExpr))2864return false;2865if (!this->emitSetLocal(*SubExprT, LocalIndex, E))2866return false;2867return this->emitGetPtrLocal(LocalIndex, E);2868} else {28692870if (!this->checkLiteralType(SubExpr))2871return false;28722873const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();2874if (std::optional<unsigned> LocalIndex =2875allocateLocal(E, Inner->getType(), E->getExtendingDecl())) {2876InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));2877if (!this->emitGetPtrLocal(*LocalIndex, E))2878return false;2879return this->visitInitializer(SubExpr) && this->emitFinishInit(E);2880}2881}2882return false;2883}28842885template <class Emitter>2886bool Compiler<Emitter>::VisitCXXBindTemporaryExpr(2887const CXXBindTemporaryExpr *E) {2888const Expr *SubExpr = E->getSubExpr();28892890if (Initializing)2891return this->delegate(SubExpr);28922893// Make sure we create a temporary even if we're discarding, since that will2894// make sure we will also call the destructor.28952896if (!this->visit(SubExpr))2897return false;28982899if (DiscardResult)2900return this->emitPopPtr(E);2901return true;2902}29032904template <class Emitter>2905bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {2906const Expr *Init = E->getInitializer();2907if (DiscardResult)2908return this->discard(Init);29092910if (Initializing) {2911// We already have a value, just initialize that.2912return this->visitInitializer(Init) && this->emitFinishInit(E);2913}29142915std::optional<PrimType> T = classify(E->getType());2916if (E->isFileScope()) {2917// Avoid creating a variable if this is a primitive RValue anyway.2918if (T && !E->isLValue())2919return this->delegate(Init);29202921if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {2922if (!this->emitGetPtrGlobal(*GlobalIndex, E))2923return false;29242925if (T) {2926if (!this->visit(Init))2927return false;2928return this->emitInitGlobal(*T, *GlobalIndex, E);2929}29302931return this->visitInitializer(Init) && this->emitFinishInit(E);2932}29332934return false;2935}29362937// Otherwise, use a local variable.2938if (T && !E->isLValue()) {2939// For primitive types, we just visit the initializer.2940return this->delegate(Init);2941}29422943unsigned LocalIndex;2944if (T)2945LocalIndex = this->allocateLocalPrimitive(Init, *T, /*IsConst=*/false);2946else if (std::optional<unsigned> MaybeIndex = this->allocateLocal(Init))2947LocalIndex = *MaybeIndex;2948else2949return false;29502951if (!this->emitGetPtrLocal(LocalIndex, E))2952return false;29532954if (T)2955return this->visit(Init) && this->emitInit(*T, E);2956return this->visitInitializer(Init) && this->emitFinishInit(E);2957}29582959template <class Emitter>2960bool Compiler<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {2961if (DiscardResult)2962return true;2963if (E->isStoredAsBoolean()) {2964if (E->getType()->isBooleanType())2965return this->emitConstBool(E->getBoolValue(), E);2966return this->emitConst(E->getBoolValue(), E);2967}2968PrimType T = classifyPrim(E->getType());2969return this->visitAPValue(E->getAPValue(), T, E);2970}29712972template <class Emitter>2973bool Compiler<Emitter>::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {2974if (DiscardResult)2975return true;2976return this->emitConst(E->getValue(), E);2977}29782979template <class Emitter>2980bool Compiler<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {2981if (DiscardResult)2982return true;29832984assert(Initializing);2985const Record *R = P.getOrCreateRecord(E->getLambdaClass());2986if (!R)2987return false;29882989auto *CaptureInitIt = E->capture_init_begin();2990// Initialize all fields (which represent lambda captures) of the2991// record with their initializers.2992for (const Record::Field &F : R->fields()) {2993const Expr *Init = *CaptureInitIt;2994if (!Init || Init->containsErrors())2995continue;2996++CaptureInitIt;29972998if (std::optional<PrimType> T = classify(Init)) {2999if (!this->visit(Init))3000return false;30013002if (!this->emitInitField(*T, F.Offset, E))3003return false;3004} else {3005if (!this->emitGetPtrField(F.Offset, E))3006return false;30073008if (!this->visitInitializer(Init))3009return false;30103011if (!this->emitPopPtr(E))3012return false;3013}3014}30153016return true;3017}30183019template <class Emitter>3020bool Compiler<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {3021if (DiscardResult)3022return true;30233024if (!Initializing) {3025unsigned StringIndex = P.createGlobalString(E->getFunctionName(), E);3026return this->emitGetPtrGlobal(StringIndex, E);3027}30283029return this->delegate(E->getFunctionName());3030}30313032template <class Emitter>3033bool Compiler<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {3034if (E->getSubExpr() && !this->discard(E->getSubExpr()))3035return false;30363037return this->emitInvalid(E);3038}30393040template <class Emitter>3041bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(3042const CXXReinterpretCastExpr *E) {3043const Expr *SubExpr = E->getSubExpr();30443045std::optional<PrimType> FromT = classify(SubExpr);3046std::optional<PrimType> ToT = classify(E);30473048if (!FromT || !ToT)3049return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);30503051if (FromT == PT_Ptr || ToT == PT_Ptr) {3052// Both types could be PT_Ptr because their expressions are glvalues.3053std::optional<PrimType> PointeeFromT;3054if (SubExpr->getType()->isPointerOrReferenceType())3055PointeeFromT = classify(SubExpr->getType()->getPointeeType());3056else3057PointeeFromT = classify(SubExpr->getType());30583059std::optional<PrimType> PointeeToT;3060if (E->getType()->isPointerOrReferenceType())3061PointeeToT = classify(E->getType()->getPointeeType());3062else3063PointeeToT = classify(E->getType());30643065bool Fatal = true;3066if (PointeeToT && PointeeFromT) {3067if (isIntegralType(*PointeeFromT) && isIntegralType(*PointeeToT))3068Fatal = false;3069} else {3070Fatal = SubExpr->getType().getTypePtr() != E->getType().getTypePtr();3071}30723073if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))3074return false;30753076if (E->getCastKind() == CK_LValueBitCast)3077return this->delegate(SubExpr);3078return this->VisitCastExpr(E);3079}30803081// Try to actually do the cast.3082bool Fatal = (ToT != FromT);3083if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))3084return false;30853086return this->VisitCastExpr(E);3087}30883089template <class Emitter>3090bool Compiler<Emitter>::VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {30913092if (!Ctx.getLangOpts().CPlusPlus20) {3093if (!this->emitInvalidCast(CastKind::Dynamic, /*Fatal=*/false, E))3094return false;3095}30963097return this->VisitCastExpr(E);3098}30993100template <class Emitter>3101bool Compiler<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {3102assert(E->getType()->isBooleanType());31033104if (DiscardResult)3105return true;3106return this->emitConstBool(E->getValue(), E);3107}31083109template <class Emitter>3110bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {3111QualType T = E->getType();3112assert(!classify(T));31133114if (T->isRecordType()) {3115const CXXConstructorDecl *Ctor = E->getConstructor();31163117// Trivial copy/move constructor. Avoid copy.3118if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&3119Ctor->isTrivial() &&3120E->getArg(0)->isTemporaryObject(Ctx.getASTContext(),3121T->getAsCXXRecordDecl()))3122return this->visitInitializer(E->getArg(0));31233124// If we're discarding a construct expression, we still need3125// to allocate a variable and call the constructor and destructor.3126if (DiscardResult) {3127if (Ctor->isTrivial())3128return true;3129assert(!Initializing);3130std::optional<unsigned> LocalIndex = allocateLocal(E);31313132if (!LocalIndex)3133return false;31343135if (!this->emitGetPtrLocal(*LocalIndex, E))3136return false;3137}31383139// Zero initialization.3140if (E->requiresZeroInitialization()) {3141const Record *R = getRecord(E->getType());31423143if (!this->visitZeroRecordInitializer(R, E))3144return false;31453146// If the constructor is trivial anyway, we're done.3147if (Ctor->isTrivial())3148return true;3149}31503151const Function *Func = getFunction(Ctor);31523153if (!Func)3154return false;31553156assert(Func->hasThisPointer());3157assert(!Func->hasRVO());31583159// The This pointer is already on the stack because this is an initializer,3160// but we need to dup() so the call() below has its own copy.3161if (!this->emitDupPtr(E))3162return false;31633164// Constructor arguments.3165for (const auto *Arg : E->arguments()) {3166if (!this->visit(Arg))3167return false;3168}31693170if (Func->isVariadic()) {3171uint32_t VarArgSize = 0;3172unsigned NumParams = Func->getNumWrittenParams();3173for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I) {3174VarArgSize +=3175align(primSize(classify(E->getArg(I)->getType()).value_or(PT_Ptr)));3176}3177if (!this->emitCallVar(Func, VarArgSize, E))3178return false;3179} else {3180if (!this->emitCall(Func, 0, E)) {3181// When discarding, we don't need the result anyway, so clean up3182// the instance dup we did earlier in case surrounding code wants3183// to keep evaluating.3184if (DiscardResult)3185(void)this->emitPopPtr(E);3186return false;3187}3188}31893190if (DiscardResult)3191return this->emitPopPtr(E);3192return this->emitFinishInit(E);3193}31943195if (T->isArrayType()) {3196const ConstantArrayType *CAT =3197Ctx.getASTContext().getAsConstantArrayType(E->getType());3198if (!CAT)3199return false;32003201size_t NumElems = CAT->getZExtSize();3202const Function *Func = getFunction(E->getConstructor());3203if (!Func)3204return false;32053206// FIXME(perf): We're calling the constructor once per array element here,3207// in the old intepreter we had a special-case for trivial constructors.3208for (size_t I = 0; I != NumElems; ++I) {3209if (!this->emitConstUint64(I, E))3210return false;3211if (!this->emitArrayElemPtrUint64(E))3212return false;32133214// Constructor arguments.3215for (const auto *Arg : E->arguments()) {3216if (!this->visit(Arg))3217return false;3218}32193220if (!this->emitCall(Func, 0, E))3221return false;3222}3223return true;3224}32253226return false;3227}32283229template <class Emitter>3230bool Compiler<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {3231if (DiscardResult)3232return true;32333234const APValue Val =3235E->EvaluateInContext(Ctx.getASTContext(), SourceLocDefaultExpr);32363237// Things like __builtin_LINE().3238if (E->getType()->isIntegerType()) {3239assert(Val.isInt());3240const APSInt &I = Val.getInt();3241return this->emitConst(I, E);3242}3243// Otherwise, the APValue is an LValue, with only one element.3244// Theoretically, we don't need the APValue at all of course.3245assert(E->getType()->isPointerType());3246assert(Val.isLValue());3247const APValue::LValueBase &Base = Val.getLValueBase();3248if (const Expr *LValueExpr = Base.dyn_cast<const Expr *>())3249return this->visit(LValueExpr);32503251// Otherwise, we have a decl (which is the case for3252// __builtin_source_location).3253assert(Base.is<const ValueDecl *>());3254assert(Val.getLValuePath().size() == 0);3255const auto *BaseDecl = Base.dyn_cast<const ValueDecl *>();3256assert(BaseDecl);32573258auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl);32593260std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(UGCD);3261if (!GlobalIndex)3262return false;32633264if (!this->emitGetPtrGlobal(*GlobalIndex, E))3265return false;32663267const Record *R = getRecord(E->getType());3268const APValue &V = UGCD->getValue();3269for (unsigned I = 0, N = R->getNumFields(); I != N; ++I) {3270const Record::Field *F = R->getField(I);3271const APValue &FieldValue = V.getStructField(I);32723273PrimType FieldT = classifyPrim(F->Decl->getType());32743275if (!this->visitAPValue(FieldValue, FieldT, E))3276return false;3277if (!this->emitInitField(FieldT, F->Offset, E))3278return false;3279}32803281// Leave the pointer to the global on the stack.3282return true;3283}32843285template <class Emitter>3286bool Compiler<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {3287unsigned N = E->getNumComponents();3288if (N == 0)3289return false;32903291for (unsigned I = 0; I != N; ++I) {3292const OffsetOfNode &Node = E->getComponent(I);3293if (Node.getKind() == OffsetOfNode::Array) {3294const Expr *ArrayIndexExpr = E->getIndexExpr(Node.getArrayExprIndex());3295PrimType IndexT = classifyPrim(ArrayIndexExpr->getType());32963297if (DiscardResult) {3298if (!this->discard(ArrayIndexExpr))3299return false;3300continue;3301}33023303if (!this->visit(ArrayIndexExpr))3304return false;3305// Cast to Sint64.3306if (IndexT != PT_Sint64) {3307if (!this->emitCast(IndexT, PT_Sint64, E))3308return false;3309}3310}3311}33123313if (DiscardResult)3314return true;33153316PrimType T = classifyPrim(E->getType());3317return this->emitOffsetOf(T, E, E);3318}33193320template <class Emitter>3321bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(3322const CXXScalarValueInitExpr *E) {3323QualType Ty = E->getType();33243325if (DiscardResult || Ty->isVoidType())3326return true;33273328if (std::optional<PrimType> T = classify(Ty))3329return this->visitZeroInitializer(*T, Ty, E);33303331if (const auto *CT = Ty->getAs<ComplexType>()) {3332if (!Initializing) {3333std::optional<unsigned> LocalIndex = allocateLocal(E);3334if (!LocalIndex)3335return false;3336if (!this->emitGetPtrLocal(*LocalIndex, E))3337return false;3338}33393340// Initialize both fields to 0.3341QualType ElemQT = CT->getElementType();3342PrimType ElemT = classifyPrim(ElemQT);33433344for (unsigned I = 0; I != 2; ++I) {3345if (!this->visitZeroInitializer(ElemT, ElemQT, E))3346return false;3347if (!this->emitInitElem(ElemT, I, E))3348return false;3349}3350return true;3351}33523353if (const auto *VT = Ty->getAs<VectorType>()) {3354// FIXME: Code duplication with the _Complex case above.3355if (!Initializing) {3356std::optional<unsigned> LocalIndex = allocateLocal(E);3357if (!LocalIndex)3358return false;3359if (!this->emitGetPtrLocal(*LocalIndex, E))3360return false;3361}33623363// Initialize all fields to 0.3364QualType ElemQT = VT->getElementType();3365PrimType ElemT = classifyPrim(ElemQT);33663367for (unsigned I = 0, N = VT->getNumElements(); I != N; ++I) {3368if (!this->visitZeroInitializer(ElemT, ElemQT, E))3369return false;3370if (!this->emitInitElem(ElemT, I, E))3371return false;3372}3373return true;3374}33753376return false;3377}33783379template <class Emitter>3380bool Compiler<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {3381return this->emitConst(E->getPackLength(), E);3382}33833384template <class Emitter>3385bool Compiler<Emitter>::VisitGenericSelectionExpr(3386const GenericSelectionExpr *E) {3387return this->delegate(E->getResultExpr());3388}33893390template <class Emitter>3391bool Compiler<Emitter>::VisitChooseExpr(const ChooseExpr *E) {3392return this->delegate(E->getChosenSubExpr());3393}33943395template <class Emitter>3396bool Compiler<Emitter>::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {3397if (DiscardResult)3398return true;33993400return this->emitConst(E->getValue(), E);3401}34023403template <class Emitter>3404bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(3405const CXXInheritedCtorInitExpr *E) {3406const CXXConstructorDecl *Ctor = E->getConstructor();3407assert(!Ctor->isTrivial() &&3408"Trivial CXXInheritedCtorInitExpr, implement. (possible?)");3409const Function *F = this->getFunction(Ctor);3410assert(F);3411assert(!F->hasRVO());3412assert(F->hasThisPointer());34133414if (!this->emitDupPtr(SourceInfo{}))3415return false;34163417// Forward all arguments of the current function (which should be a3418// constructor itself) to the inherited ctor.3419// This is necessary because the calling code has pushed the pointer3420// of the correct base for us already, but the arguments need3421// to come after.3422unsigned Offset = align(primSize(PT_Ptr)); // instance pointer.3423for (const ParmVarDecl *PD : Ctor->parameters()) {3424PrimType PT = this->classify(PD->getType()).value_or(PT_Ptr);34253426if (!this->emitGetParam(PT, Offset, E))3427return false;3428Offset += align(primSize(PT));3429}34303431return this->emitCall(F, 0, E);3432}34333434// FIXME: This function has become rather unwieldy, especially3435// the part where we initialize an array allocation of dynamic size.3436template <class Emitter>3437bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {3438assert(classifyPrim(E->getType()) == PT_Ptr);3439const Expr *Init = E->getInitializer();3440QualType ElementType = E->getAllocatedType();3441std::optional<PrimType> ElemT = classify(ElementType);3442unsigned PlacementArgs = E->getNumPlacementArgs();3443const FunctionDecl *OperatorNew = E->getOperatorNew();3444const Expr *PlacementDest = nullptr;3445bool IsNoThrow = false;34463447if (PlacementArgs != 0) {3448// FIXME: There is no restriction on this, but it's not clear that any3449// other form makes any sense. We get here for cases such as:3450//3451// new (std::align_val_t{N}) X(int)3452//3453// (which should presumably be valid only if N is a multiple of3454// alignof(int), and in any case can't be deallocated unless N is3455// alignof(X) and X has new-extended alignment).3456if (PlacementArgs == 1) {3457const Expr *Arg1 = E->getPlacementArg(0);3458if (Arg1->getType()->isNothrowT()) {3459if (!this->discard(Arg1))3460return false;3461IsNoThrow = true;3462} else {3463// Invalid unless we have C++26 or are in a std:: function.3464if (!this->emitInvalidNewDeleteExpr(E, E))3465return false;34663467// If we have a placement-new destination, we'll later use that instead3468// of allocating.3469if (OperatorNew->isReservedGlobalPlacementOperator())3470PlacementDest = Arg1;3471}3472} else {3473// Always invalid.3474return this->emitInvalid(E);3475}3476} else if (!OperatorNew3477->isUsableAsGlobalAllocationFunctionInConstantEvaluation())3478return this->emitInvalidNewDeleteExpr(E, E);34793480const Descriptor *Desc;3481if (!PlacementDest) {3482if (ElemT) {3483if (E->isArray())3484Desc = nullptr; // We're not going to use it in this case.3485else3486Desc = P.createDescriptor(E, *ElemT, /*SourceTy=*/nullptr,3487Descriptor::InlineDescMD);3488} else {3489Desc = P.createDescriptor(3490E, ElementType.getTypePtr(),3491E->isArray() ? std::nullopt : Descriptor::InlineDescMD,3492/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false,3493/*IsVolatile=*/false, Init);3494}3495}34963497if (E->isArray()) {3498std::optional<const Expr *> ArraySizeExpr = E->getArraySize();3499if (!ArraySizeExpr)3500return false;35013502const Expr *Stripped = *ArraySizeExpr;3503for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped);3504Stripped = ICE->getSubExpr())3505if (ICE->getCastKind() != CK_NoOp &&3506ICE->getCastKind() != CK_IntegralCast)3507break;35083509PrimType SizeT = classifyPrim(Stripped->getType());35103511// Save evaluated array size to a variable.3512unsigned ArrayLen =3513allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);3514if (!this->visit(Stripped))3515return false;3516if (!this->emitSetLocal(SizeT, ArrayLen, E))3517return false;35183519if (PlacementDest) {3520if (!this->visit(PlacementDest))3521return false;3522if (!this->emitStartLifetime(E))3523return false;3524if (!this->emitGetLocal(SizeT, ArrayLen, E))3525return false;3526if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))3527return false;3528} else {3529if (!this->emitGetLocal(SizeT, ArrayLen, E))3530return false;35313532if (ElemT) {3533// N primitive elements.3534if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E))3535return false;3536} else {3537// N Composite elements.3538if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E))3539return false;3540}3541}35423543if (Init) {3544QualType InitType = Init->getType();3545size_t StaticInitElems = 0;3546const Expr *DynamicInit = nullptr;3547if (const ConstantArrayType *CAT =3548Ctx.getASTContext().getAsConstantArrayType(InitType)) {3549StaticInitElems = CAT->getZExtSize();3550if (!this->visitInitializer(Init))3551return false;35523553if (const auto *ILE = dyn_cast<InitListExpr>(Init);3554ILE && ILE->hasArrayFiller())3555DynamicInit = ILE->getArrayFiller();3556}35573558// The initializer initializes a certain number of elements, S.3559// However, the complete number of elements, N, might be larger than that.3560// In this case, we need to get an initializer for the remaining elements.3561// There are to cases:3562// 1) For the form 'new Struct[n];', the initializer is a3563// CXXConstructExpr and its type is an IncompleteArrayType.3564// 2) For the form 'new Struct[n]{1,2,3}', the initializer is an3565// InitListExpr and the initializer for the remaining elements3566// is the array filler.35673568if (DynamicInit || InitType->isIncompleteArrayType()) {3569const Function *CtorFunc = nullptr;3570if (const auto *CE = dyn_cast<CXXConstructExpr>(Init)) {3571CtorFunc = getFunction(CE->getConstructor());3572if (!CtorFunc)3573return false;3574} else if (!DynamicInit)3575DynamicInit = Init;35763577LabelTy EndLabel = this->getLabel();3578LabelTy StartLabel = this->getLabel();35793580// In the nothrow case, the alloc above might have returned nullptr.3581// Don't call any constructors that case.3582if (IsNoThrow) {3583if (!this->emitDupPtr(E))3584return false;3585if (!this->emitNullPtr(0, nullptr, E))3586return false;3587if (!this->emitEQPtr(E))3588return false;3589if (!this->jumpTrue(EndLabel))3590return false;3591}35923593// Create loop variables.3594unsigned Iter =3595allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);3596if (!this->emitConst(StaticInitElems, SizeT, E))3597return false;3598if (!this->emitSetLocal(SizeT, Iter, E))3599return false;36003601this->fallthrough(StartLabel);3602this->emitLabel(StartLabel);3603// Condition. Iter < ArrayLen?3604if (!this->emitGetLocal(SizeT, Iter, E))3605return false;3606if (!this->emitGetLocal(SizeT, ArrayLen, E))3607return false;3608if (!this->emitLT(SizeT, E))3609return false;3610if (!this->jumpFalse(EndLabel))3611return false;36123613// Pointer to the allocated array is already on the stack.3614if (!this->emitGetLocal(SizeT, Iter, E))3615return false;3616if (!this->emitArrayElemPtr(SizeT, E))3617return false;36183619if (isa_and_nonnull<ImplicitValueInitExpr>(DynamicInit) &&3620DynamicInit->getType()->isArrayType()) {3621QualType ElemType =3622DynamicInit->getType()->getAsArrayTypeUnsafe()->getElementType();3623PrimType InitT = classifyPrim(ElemType);3624if (!this->visitZeroInitializer(InitT, ElemType, E))3625return false;3626if (!this->emitStorePop(InitT, E))3627return false;3628} else if (DynamicInit) {3629if (std::optional<PrimType> InitT = classify(DynamicInit)) {3630if (!this->visit(DynamicInit))3631return false;3632if (!this->emitStorePop(*InitT, E))3633return false;3634} else {3635if (!this->visitInitializer(DynamicInit))3636return false;3637if (!this->emitPopPtr(E))3638return false;3639}3640} else {3641assert(CtorFunc);3642if (!this->emitCall(CtorFunc, 0, E))3643return false;3644}36453646// ++Iter;3647if (!this->emitGetPtrLocal(Iter, E))3648return false;3649if (!this->emitIncPop(SizeT, false, E))3650return false;36513652if (!this->jump(StartLabel))3653return false;36543655this->fallthrough(EndLabel);3656this->emitLabel(EndLabel);3657}3658}3659} else { // Non-array.3660if (PlacementDest) {3661if (!this->visit(PlacementDest))3662return false;3663if (!this->emitStartLifetime(E))3664return false;3665if (!this->emitCheckNewTypeMismatch(E, E))3666return false;3667} else {3668// Allocate just one element.3669if (!this->emitAlloc(Desc, E))3670return false;3671}36723673if (Init) {3674if (ElemT) {3675if (!this->visit(Init))3676return false;36773678if (!this->emitInit(*ElemT, E))3679return false;3680} else {3681// Composite.3682if (!this->visitInitializer(Init))3683return false;3684}3685}3686}36873688if (DiscardResult)3689return this->emitPopPtr(E);36903691return true;3692}36933694template <class Emitter>3695bool Compiler<Emitter>::VisitCXXDeleteExpr(const CXXDeleteExpr *E) {3696const Expr *Arg = E->getArgument();36973698const FunctionDecl *OperatorDelete = E->getOperatorDelete();36993700if (!OperatorDelete->isUsableAsGlobalAllocationFunctionInConstantEvaluation())3701return this->emitInvalidNewDeleteExpr(E, E);37023703// Arg must be an lvalue.3704if (!this->visit(Arg))3705return false;37063707return this->emitFree(E->isArrayForm(), E->isGlobalDelete(), E);3708}37093710template <class Emitter>3711bool Compiler<Emitter>::VisitBlockExpr(const BlockExpr *E) {3712if (DiscardResult)3713return true;37143715const Function *Func = nullptr;3716if (auto F = Ctx.getOrCreateObjCBlock(E))3717Func = F;37183719if (!Func)3720return false;3721return this->emitGetFnPtr(Func, E);3722}37233724template <class Emitter>3725bool Compiler<Emitter>::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {3726const Type *TypeInfoType = E->getType().getTypePtr();37273728auto canonType = [](const Type *T) {3729return T->getCanonicalTypeUnqualified().getTypePtr();3730};37313732if (!E->isPotentiallyEvaluated()) {3733if (DiscardResult)3734return true;37353736if (E->isTypeOperand())3737return this->emitGetTypeid(3738canonType(E->getTypeOperand(Ctx.getASTContext()).getTypePtr()),3739TypeInfoType, E);37403741return this->emitGetTypeid(3742canonType(E->getExprOperand()->getType().getTypePtr()), TypeInfoType,3743E);3744}37453746// Otherwise, we need to evaluate the expression operand.3747assert(E->getExprOperand());3748assert(E->getExprOperand()->isLValue());37493750if (!Ctx.getLangOpts().CPlusPlus20 && !this->emitDiagTypeid(E))3751return false;37523753if (!this->visit(E->getExprOperand()))3754return false;37553756if (!this->emitGetTypeidPtr(TypeInfoType, E))3757return false;3758if (DiscardResult)3759return this->emitPopPtr(E);3760return true;3761}37623763template <class Emitter>3764bool Compiler<Emitter>::VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {3765assert(Ctx.getLangOpts().CPlusPlus);3766return this->emitConstBool(E->getValue(), E);3767}37683769template <class Emitter>3770bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {3771if (DiscardResult)3772return true;3773assert(!Initializing);37743775const MSGuidDecl *GuidDecl = E->getGuidDecl();3776const RecordDecl *RD = GuidDecl->getType()->getAsRecordDecl();3777assert(RD);3778// If the definiton of the result type is incomplete, just return a dummy.3779// If (and when) that is read from, we will fail, but not now.3780if (!RD->isCompleteDefinition())3781return this->emitDummyPtr(GuidDecl, E);37823783std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(GuidDecl);3784if (!GlobalIndex)3785return false;3786if (!this->emitGetPtrGlobal(*GlobalIndex, E))3787return false;37883789assert(this->getRecord(E->getType()));37903791const APValue &V = GuidDecl->getAsAPValue();3792if (V.getKind() == APValue::None)3793return true;37943795assert(V.isStruct());3796assert(V.getStructNumBases() == 0);3797if (!this->visitAPValueInitializer(V, E, E->getType()))3798return false;37993800return this->emitFinishInit(E);3801}38023803template <class Emitter>3804bool Compiler<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {3805assert(classifyPrim(E->getType()) == PT_Bool);3806if (DiscardResult)3807return true;3808return this->emitConstBool(E->isSatisfied(), E);3809}38103811template <class Emitter>3812bool Compiler<Emitter>::VisitConceptSpecializationExpr(3813const ConceptSpecializationExpr *E) {3814assert(classifyPrim(E->getType()) == PT_Bool);3815if (DiscardResult)3816return true;3817return this->emitConstBool(E->isSatisfied(), E);3818}38193820template <class Emitter>3821bool Compiler<Emitter>::VisitCXXRewrittenBinaryOperator(3822const CXXRewrittenBinaryOperator *E) {3823return this->delegate(E->getSemanticForm());3824}38253826template <class Emitter>3827bool Compiler<Emitter>::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {38283829for (const Expr *SemE : E->semantics()) {3830if (auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) {3831if (SemE == E->getResultExpr())3832return false;38333834if (OVE->isUnique())3835continue;38363837if (!this->discard(OVE))3838return false;3839} else if (SemE == E->getResultExpr()) {3840if (!this->delegate(SemE))3841return false;3842} else {3843if (!this->discard(SemE))3844return false;3845}3846}3847return true;3848}38493850template <class Emitter>3851bool Compiler<Emitter>::VisitPackIndexingExpr(const PackIndexingExpr *E) {3852return this->delegate(E->getSelectedExpr());3853}38543855template <class Emitter>3856bool Compiler<Emitter>::VisitRecoveryExpr(const RecoveryExpr *E) {3857return this->emitError(E);3858}38593860template <class Emitter>3861bool Compiler<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {3862assert(E->getType()->isVoidPointerType());38633864unsigned Offset =3865allocateLocalPrimitive(E->getLabel(), PT_Ptr, /*IsConst=*/true);38663867return this->emitGetLocal(PT_Ptr, Offset, E);3868}38693870template <class Emitter>3871bool Compiler<Emitter>::VisitConvertVectorExpr(const ConvertVectorExpr *E) {3872assert(Initializing);3873const auto *VT = E->getType()->castAs<VectorType>();3874QualType ElemType = VT->getElementType();3875PrimType ElemT = classifyPrim(ElemType);3876const Expr *Src = E->getSrcExpr();3877QualType SrcType = Src->getType();3878PrimType SrcElemT = classifyVectorElementType(SrcType);38793880unsigned SrcOffset =3881this->allocateLocalPrimitive(Src, PT_Ptr, /*IsConst=*/true);3882if (!this->visit(Src))3883return false;3884if (!this->emitSetLocal(PT_Ptr, SrcOffset, E))3885return false;38863887for (unsigned I = 0; I != VT->getNumElements(); ++I) {3888if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))3889return false;3890if (!this->emitArrayElemPop(SrcElemT, I, E))3891return false;38923893// Cast to the desired result element type.3894if (SrcElemT != ElemT) {3895if (!this->emitPrimCast(SrcElemT, ElemT, ElemType, E))3896return false;3897} else if (ElemType->isFloatingType() && SrcType != ElemType) {3898const auto *TargetSemantics = &Ctx.getFloatSemantics(ElemType);3899if (!this->emitCastFP(TargetSemantics, getRoundingMode(E), E))3900return false;3901}3902if (!this->emitInitElem(ElemT, I, E))3903return false;3904}39053906return true;3907}39083909template <class Emitter>3910bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {3911assert(Initializing);3912assert(E->getNumSubExprs() > 2);39133914const Expr *Vecs[] = {E->getExpr(0), E->getExpr(1)};3915const VectorType *VT = Vecs[0]->getType()->castAs<VectorType>();3916PrimType ElemT = classifyPrim(VT->getElementType());3917unsigned NumInputElems = VT->getNumElements();3918unsigned NumOutputElems = E->getNumSubExprs() - 2;3919assert(NumOutputElems > 0);39203921// Save both input vectors to a local variable.3922unsigned VectorOffsets[2];3923for (unsigned I = 0; I != 2; ++I) {3924VectorOffsets[I] =3925this->allocateLocalPrimitive(Vecs[I], PT_Ptr, /*IsConst=*/true);3926if (!this->visit(Vecs[I]))3927return false;3928if (!this->emitSetLocal(PT_Ptr, VectorOffsets[I], E))3929return false;3930}3931for (unsigned I = 0; I != NumOutputElems; ++I) {3932APSInt ShuffleIndex = E->getShuffleMaskIdx(I);3933assert(ShuffleIndex >= -1);3934if (ShuffleIndex == -1)3935return this->emitInvalidShuffleVectorIndex(I, E);39363937assert(ShuffleIndex < (NumInputElems * 2));3938if (!this->emitGetLocal(PT_Ptr,3939VectorOffsets[ShuffleIndex >= NumInputElems], E))3940return false;3941unsigned InputVectorIndex = ShuffleIndex.getZExtValue() % NumInputElems;3942if (!this->emitArrayElemPop(ElemT, InputVectorIndex, E))3943return false;39443945if (!this->emitInitElem(ElemT, I, E))3946return false;3947}39483949return true;3950}39513952template <class Emitter>3953bool Compiler<Emitter>::VisitExtVectorElementExpr(3954const ExtVectorElementExpr *E) {3955const Expr *Base = E->getBase();3956assert(3957Base->getType()->isVectorType() ||3958Base->getType()->getAs<PointerType>()->getPointeeType()->isVectorType());39593960SmallVector<uint32_t, 4> Indices;3961E->getEncodedElementAccess(Indices);39623963if (Indices.size() == 1) {3964if (!this->visit(Base))3965return false;39663967if (E->isGLValue()) {3968if (!this->emitConstUint32(Indices[0], E))3969return false;3970return this->emitArrayElemPtrPop(PT_Uint32, E);3971}3972// Else, also load the value.3973return this->emitArrayElemPop(classifyPrim(E->getType()), Indices[0], E);3974}39753976// Create a local variable for the base.3977unsigned BaseOffset = allocateLocalPrimitive(Base, PT_Ptr, /*IsConst=*/true);3978if (!this->visit(Base))3979return false;3980if (!this->emitSetLocal(PT_Ptr, BaseOffset, E))3981return false;39823983// Now the vector variable for the return value.3984if (!Initializing) {3985std::optional<unsigned> ResultIndex;3986ResultIndex = allocateLocal(E);3987if (!ResultIndex)3988return false;3989if (!this->emitGetPtrLocal(*ResultIndex, E))3990return false;3991}39923993assert(Indices.size() == E->getType()->getAs<VectorType>()->getNumElements());39943995PrimType ElemT =3996classifyPrim(E->getType()->getAs<VectorType>()->getElementType());3997uint32_t DstIndex = 0;3998for (uint32_t I : Indices) {3999if (!this->emitGetLocal(PT_Ptr, BaseOffset, E))4000return false;4001if (!this->emitArrayElemPop(ElemT, I, E))4002return false;4003if (!this->emitInitElem(ElemT, DstIndex, E))4004return false;4005++DstIndex;4006}40074008// Leave the result pointer on the stack.4009assert(!DiscardResult);4010return true;4011}40124013template <class Emitter>4014bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {4015const Expr *SubExpr = E->getSubExpr();4016if (!E->isExpressibleAsConstantInitializer())4017return this->discard(SubExpr) && this->emitInvalid(E);40184019if (DiscardResult)4020return true;40214022assert(classifyPrim(E) == PT_Ptr);4023return this->emitDummyPtr(E, E);4024}40254026template <class Emitter>4027bool Compiler<Emitter>::VisitCXXStdInitializerListExpr(4028const CXXStdInitializerListExpr *E) {4029const Expr *SubExpr = E->getSubExpr();4030const ConstantArrayType *ArrayType =4031Ctx.getASTContext().getAsConstantArrayType(SubExpr->getType());4032const Record *R = getRecord(E->getType());4033assert(Initializing);4034assert(SubExpr->isGLValue());40354036if (!this->visit(SubExpr))4037return false;4038if (!this->emitConstUint8(0, E))4039return false;4040if (!this->emitArrayElemPtrPopUint8(E))4041return false;4042if (!this->emitInitFieldPtr(R->getField(0u)->Offset, E))4043return false;40444045PrimType SecondFieldT = classifyPrim(R->getField(1u)->Decl->getType());4046if (isIntegralType(SecondFieldT)) {4047if (!this->emitConst(static_cast<APSInt>(ArrayType->getSize()),4048SecondFieldT, E))4049return false;4050return this->emitInitField(SecondFieldT, R->getField(1u)->Offset, E);4051}4052assert(SecondFieldT == PT_Ptr);40534054if (!this->emitGetFieldPtr(R->getField(0u)->Offset, E))4055return false;4056if (!this->emitExpandPtr(E))4057return false;4058if (!this->emitConst(static_cast<APSInt>(ArrayType->getSize()), PT_Uint64, E))4059return false;4060if (!this->emitArrayElemPtrPop(PT_Uint64, E))4061return false;4062return this->emitInitFieldPtr(R->getField(1u)->Offset, E);4063}40644065template <class Emitter>4066bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {4067BlockScope<Emitter> BS(this);4068StmtExprScope<Emitter> SS(this);40694070const CompoundStmt *CS = E->getSubStmt();4071const Stmt *Result = CS->getStmtExprResult();4072for (const Stmt *S : CS->body()) {4073if (S != Result) {4074if (!this->visitStmt(S))4075return false;4076continue;4077}40784079assert(S == Result);4080if (const Expr *ResultExpr = dyn_cast<Expr>(S))4081return this->delegate(ResultExpr);4082return this->emitUnsupported(E);4083}40844085return BS.destroyLocals();4086}40874088template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {4089OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,4090/*NewInitializing=*/false);4091return this->Visit(E);4092}40934094template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {4095// We're basically doing:4096// OptionScope<Emitter> Scope(this, DicardResult, Initializing);4097// but that's unnecessary of course.4098return this->Visit(E);4099}41004101template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {4102if (E->getType().isNull())4103return false;41044105if (E->getType()->isVoidType())4106return this->discard(E);41074108// Create local variable to hold the return value.4109if (!E->isGLValue() && !E->getType()->isAnyComplexType() &&4110!classify(E->getType())) {4111std::optional<unsigned> LocalIndex = allocateLocal(E);4112if (!LocalIndex)4113return false;41144115if (!this->emitGetPtrLocal(*LocalIndex, E))4116return false;4117InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));4118return this->visitInitializer(E);4119}41204121// Otherwise,we have a primitive return value, produce the value directly4122// and push it on the stack.4123OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,4124/*NewInitializing=*/false);4125return this->Visit(E);4126}41274128template <class Emitter>4129bool Compiler<Emitter>::visitInitializer(const Expr *E) {4130assert(!classify(E->getType()));41314132OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,4133/*NewInitializing=*/true);4134return this->Visit(E);4135}41364137template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {4138std::optional<PrimType> T = classify(E->getType());4139if (!T) {4140// Convert complex values to bool.4141if (E->getType()->isAnyComplexType()) {4142if (!this->visit(E))4143return false;4144return this->emitComplexBoolCast(E);4145}4146return false;4147}41484149if (!this->visit(E))4150return false;41514152if (T == PT_Bool)4153return true;41544155// Convert pointers to bool.4156if (T == PT_Ptr)4157return this->emitIsNonNullPtr(E);41584159// Or Floats.4160if (T == PT_Float)4161return this->emitCastFloatingIntegralBool(getFPOptions(E), E);41624163// Or anything else we can.4164return this->emitCast(*T, PT_Bool, E);4165}41664167template <class Emitter>4168bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,4169const Expr *E) {4170if (const auto *AT = QT->getAs<AtomicType>())4171QT = AT->getValueType();41724173switch (T) {4174case PT_Bool:4175return this->emitZeroBool(E);4176case PT_Sint8:4177return this->emitZeroSint8(E);4178case PT_Uint8:4179return this->emitZeroUint8(E);4180case PT_Sint16:4181return this->emitZeroSint16(E);4182case PT_Uint16:4183return this->emitZeroUint16(E);4184case PT_Sint32:4185return this->emitZeroSint32(E);4186case PT_Uint32:4187return this->emitZeroUint32(E);4188case PT_Sint64:4189return this->emitZeroSint64(E);4190case PT_Uint64:4191return this->emitZeroUint64(E);4192case PT_IntAP:4193return this->emitZeroIntAP(Ctx.getBitWidth(QT), E);4194case PT_IntAPS:4195return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E);4196case PT_Ptr:4197return this->emitNullPtr(Ctx.getASTContext().getTargetNullPointerValue(QT),4198nullptr, E);4199case PT_MemberPtr:4200return this->emitNullMemberPtr(0, nullptr, E);4201case PT_Float: {4202APFloat F = APFloat::getZero(Ctx.getFloatSemantics(QT));4203return this->emitFloat(F, E);4204}4205case PT_FixedPoint: {4206auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());4207return this->emitConstFixedPoint(FixedPoint::zero(Sem), E);4208}4209}4210llvm_unreachable("unknown primitive type");4211}42124213template <class Emitter>4214bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,4215const Expr *E) {4216assert(E);4217assert(R);4218// Fields4219for (const Record::Field &Field : R->fields()) {4220if (Field.isUnnamedBitField())4221continue;42224223const Descriptor *D = Field.Desc;4224if (D->isPrimitive()) {4225QualType QT = D->getType();4226PrimType T = classifyPrim(D->getType());4227if (!this->visitZeroInitializer(T, QT, E))4228return false;4229if (!this->emitInitField(T, Field.Offset, E))4230return false;4231if (R->isUnion())4232break;4233continue;4234}42354236if (!this->emitGetPtrField(Field.Offset, E))4237return false;42384239if (D->isPrimitiveArray()) {4240QualType ET = D->getElemQualType();4241PrimType T = classifyPrim(ET);4242for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) {4243if (!this->visitZeroInitializer(T, ET, E))4244return false;4245if (!this->emitInitElem(T, I, E))4246return false;4247}4248} else if (D->isCompositeArray()) {4249// Can't be a vector or complex field.4250if (!this->visitZeroArrayInitializer(D->getType(), E))4251return false;4252} else if (D->isRecord()) {4253if (!this->visitZeroRecordInitializer(D->ElemRecord, E))4254return false;4255} else4256return false;42574258if (!this->emitFinishInitPop(E))4259return false;42604261// C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the4262// object's first non-static named data member is zero-initialized4263if (R->isUnion())4264break;4265}42664267for (const Record::Base &B : R->bases()) {4268if (!this->emitGetPtrBase(B.Offset, E))4269return false;4270if (!this->visitZeroRecordInitializer(B.R, E))4271return false;4272if (!this->emitFinishInitPop(E))4273return false;4274}42754276// FIXME: Virtual bases.42774278return true;4279}42804281template <class Emitter>4282bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {4283assert(T->isArrayType() || T->isAnyComplexType() || T->isVectorType());4284const ArrayType *AT = T->getAsArrayTypeUnsafe();4285QualType ElemType = AT->getElementType();4286size_t NumElems = cast<ConstantArrayType>(AT)->getZExtSize();42874288if (std::optional<PrimType> ElemT = classify(ElemType)) {4289for (size_t I = 0; I != NumElems; ++I) {4290if (!this->visitZeroInitializer(*ElemT, ElemType, E))4291return false;4292if (!this->emitInitElem(*ElemT, I, E))4293return false;4294}4295return true;4296} else if (ElemType->isRecordType()) {4297const Record *R = getRecord(ElemType);42984299for (size_t I = 0; I != NumElems; ++I) {4300if (!this->emitConstUint32(I, E))4301return false;4302if (!this->emitArrayElemPtr(PT_Uint32, E))4303return false;4304if (!this->visitZeroRecordInitializer(R, E))4305return false;4306if (!this->emitPopPtr(E))4307return false;4308}4309return true;4310} else if (ElemType->isArrayType()) {4311for (size_t I = 0; I != NumElems; ++I) {4312if (!this->emitConstUint32(I, E))4313return false;4314if (!this->emitArrayElemPtr(PT_Uint32, E))4315return false;4316if (!this->visitZeroArrayInitializer(ElemType, E))4317return false;4318if (!this->emitPopPtr(E))4319return false;4320}4321return true;4322}43234324return false;4325}43264327template <class Emitter>4328template <typename T>4329bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {4330switch (Ty) {4331case PT_Sint8:4332return this->emitConstSint8(Value, E);4333case PT_Uint8:4334return this->emitConstUint8(Value, E);4335case PT_Sint16:4336return this->emitConstSint16(Value, E);4337case PT_Uint16:4338return this->emitConstUint16(Value, E);4339case PT_Sint32:4340return this->emitConstSint32(Value, E);4341case PT_Uint32:4342return this->emitConstUint32(Value, E);4343case PT_Sint64:4344return this->emitConstSint64(Value, E);4345case PT_Uint64:4346return this->emitConstUint64(Value, E);4347case PT_Bool:4348return this->emitConstBool(Value, E);4349case PT_Ptr:4350case PT_MemberPtr:4351case PT_Float:4352case PT_IntAP:4353case PT_IntAPS:4354case PT_FixedPoint:4355llvm_unreachable("Invalid integral type");4356break;4357}4358llvm_unreachable("unknown primitive type");4359}43604361template <class Emitter>4362template <typename T>4363bool Compiler<Emitter>::emitConst(T Value, const Expr *E) {4364return this->emitConst(Value, classifyPrim(E->getType()), E);4365}43664367template <class Emitter>4368bool Compiler<Emitter>::emitConst(const APSInt &Value, PrimType Ty,4369const Expr *E) {4370if (Ty == PT_IntAPS)4371return this->emitConstIntAPS(Value, E);4372if (Ty == PT_IntAP)4373return this->emitConstIntAP(Value, E);43744375if (Value.isSigned())4376return this->emitConst(Value.getSExtValue(), Ty, E);4377return this->emitConst(Value.getZExtValue(), Ty, E);4378}43794380template <class Emitter>4381bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) {4382return this->emitConst(Value, classifyPrim(E->getType()), E);4383}43844385template <class Emitter>4386unsigned Compiler<Emitter>::allocateLocalPrimitive(4387DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl,4388ScopeKind SC, bool IsConstexprUnknown) {4389// Make sure we don't accidentally register the same decl twice.4390if (const auto *VD =4391dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {4392assert(!P.getGlobal(VD));4393assert(!Locals.contains(VD));4394(void)VD;4395}43964397// FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.4398// (int){12} in C. Consider using Expr::isTemporaryObject() instead4399// or isa<MaterializeTemporaryExpr>().4400Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD,4401IsConst, isa<const Expr *>(Src));4402D->IsConstexprUnknown = IsConstexprUnknown;4403Scope::Local Local = this->createLocal(D);4404if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))4405Locals.insert({VD, Local});4406if (ExtendingDecl)4407VarScope->addExtended(Local, ExtendingDecl);4408else4409VarScope->addForScopeKind(Local, SC);4410return Local.Offset;4411}44124413template <class Emitter>4414std::optional<unsigned>4415Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,4416const ValueDecl *ExtendingDecl, ScopeKind SC,4417bool IsConstexprUnknown) {4418// Make sure we don't accidentally register the same decl twice.4419if ([[maybe_unused]] const auto *VD =4420dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {4421assert(!P.getGlobal(VD));4422assert(!Locals.contains(VD));4423}44244425const ValueDecl *Key = nullptr;4426const Expr *Init = nullptr;4427bool IsTemporary = false;4428if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {4429Key = VD;4430Ty = VD->getType();44314432if (const auto *VarD = dyn_cast<VarDecl>(VD))4433Init = VarD->getInit();4434}4435if (auto *E = Src.dyn_cast<const Expr *>()) {4436IsTemporary = true;4437if (Ty.isNull())4438Ty = E->getType();4439}44404441Descriptor *D = P.createDescriptor(4442Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),4443IsTemporary, /*IsMutable=*/false, /*IsVolatile=*/false, Init);4444if (!D)4445return std::nullopt;4446D->IsConstexprUnknown = IsConstexprUnknown;44474448Scope::Local Local = this->createLocal(D);4449if (Key)4450Locals.insert({Key, Local});4451if (ExtendingDecl)4452VarScope->addExtended(Local, ExtendingDecl);4453else4454VarScope->addForScopeKind(Local, SC);4455return Local.Offset;4456}44574458template <class Emitter>4459std::optional<unsigned> Compiler<Emitter>::allocateTemporary(const Expr *E) {4460QualType Ty = E->getType();4461assert(!Ty->isRecordType());44624463Descriptor *D = P.createDescriptor(4464E, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),4465/*IsTemporary=*/true);44664467if (!D)4468return std::nullopt;44694470Scope::Local Local = this->createLocal(D);4471VariableScope<Emitter> *S = VarScope;4472assert(S);4473// Attach to topmost scope.4474while (S->getParent())4475S = S->getParent();4476assert(S && !S->getParent());4477S->addLocal(Local);4478return Local.Offset;4479}44804481template <class Emitter>4482const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) {4483if (const PointerType *PT = dyn_cast<PointerType>(Ty))4484return PT->getPointeeType()->getAs<RecordType>();4485return Ty->getAs<RecordType>();4486}44874488template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) {4489if (const auto *RecordTy = getRecordTy(Ty))4490return getRecord(RecordTy->getDecl());4491return nullptr;4492}44934494template <class Emitter>4495Record *Compiler<Emitter>::getRecord(const RecordDecl *RD) {4496return P.getOrCreateRecord(RD);4497}44984499template <class Emitter>4500const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) {4501return Ctx.getOrCreateFunction(FD);4502}45034504template <class Emitter>4505bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) {4506LocalScope<Emitter> RootScope(this);45074508// If we won't destroy the toplevel scope, check for memory leaks first.4509if (!DestroyToplevelScope) {4510if (!this->emitCheckAllocations(E))4511return false;4512}45134514auto maybeDestroyLocals = [&]() -> bool {4515if (DestroyToplevelScope)4516return RootScope.destroyLocals() && this->emitCheckAllocations(E);4517return this->emitCheckAllocations(E);4518};45194520// Void expressions.4521if (E->getType()->isVoidType()) {4522if (!visit(E))4523return false;4524return this->emitRetVoid(E) && maybeDestroyLocals();4525}45264527// Expressions with a primitive return type.4528if (std::optional<PrimType> T = classify(E)) {4529if (!visit(E))4530return false;45314532return this->emitRet(*T, E) && maybeDestroyLocals();4533}45344535// Expressions with a composite return type.4536// For us, that means everything we don't4537// have a PrimType for.4538if (std::optional<unsigned> LocalOffset = this->allocateLocal(E)) {4539InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalOffset));4540if (!this->emitGetPtrLocal(*LocalOffset, E))4541return false;45424543if (!visitInitializer(E))4544return false;45454546if (!this->emitFinishInit(E))4547return false;4548// We are destroying the locals AFTER the Ret op.4549// The Ret op needs to copy the (alive) values, but the4550// destructors may still turn the entire expression invalid.4551return this->emitRetValue(E) && maybeDestroyLocals();4552}45534554return maybeDestroyLocals() && this->emitCheckAllocations(E) && false;4555}45564557template <class Emitter>4558VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,4559bool IsConstexprUnknown) {45604561auto R = this->visitVarDecl(VD, /*Toplevel=*/true, IsConstexprUnknown);45624563if (R.notCreated())4564return R;45654566if (R)4567return true;45684569if (!R && Context::shouldBeGloballyIndexed(VD)) {4570if (auto GlobalIndex = P.getGlobal(VD)) {4571Block *GlobalBlock = P.getGlobal(*GlobalIndex);4572GlobalInlineDescriptor &GD =4573*reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());45744575GD.InitState = GlobalInitState::InitializerFailed;4576GlobalBlock->invokeDtor();4577}4578}45794580return R;4581}45824583/// Toplevel visitDeclAndReturn().4584/// We get here from evaluateAsInitializer().4585/// We need to evaluate the initializer and return its value.4586template <class Emitter>4587bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,4588bool ConstantContext) {45894590// We only create variables if we're evaluating in a constant context.4591// Otherwise, just evaluate the initializer and return it.4592if (!ConstantContext) {4593DeclScope<Emitter> LS(this, VD);4594const Expr *Init = VD->getInit();4595if (!this->visit(Init))4596return false;4597return this->emitRet(classify(Init).value_or(PT_Ptr), VD) &&4598LS.destroyLocals() && this->emitCheckAllocations(VD);4599}46004601LocalScope<Emitter> VDScope(this, VD);4602if (!this->visitVarDecl(VD, /*Toplevel=*/true))4603return false;46044605std::optional<PrimType> VarT = classify(VD->getType());4606if (Context::shouldBeGloballyIndexed(VD)) {4607auto GlobalIndex = P.getGlobal(VD);4608assert(GlobalIndex); // visitVarDecl() didn't return false.4609if (VarT) {4610if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD))4611return false;4612} else {4613if (!this->emitGetPtrGlobal(*GlobalIndex, VD))4614return false;4615}4616} else {4617auto Local = Locals.find(VD);4618assert(Local != Locals.end()); // Same here.4619if (VarT) {4620if (!this->emitGetLocal(*VarT, Local->second.Offset, VD))4621return false;4622} else {4623if (!this->emitGetPtrLocal(Local->second.Offset, VD))4624return false;4625}4626}46274628// Return the value.4629if (!this->emitRet(VarT.value_or(PT_Ptr), VD)) {4630// If the Ret above failed and this is a global variable, mark it as4631// uninitialized, even everything else succeeded.4632if (Context::shouldBeGloballyIndexed(VD)) {4633auto GlobalIndex = P.getGlobal(VD);4634assert(GlobalIndex);4635Block *GlobalBlock = P.getGlobal(*GlobalIndex);4636GlobalInlineDescriptor &GD =4637*reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());46384639GD.InitState = GlobalInitState::InitializerFailed;4640GlobalBlock->invokeDtor();4641}4642return false;4643}46444645return VDScope.destroyLocals() && this->emitCheckAllocations(VD);4646}46474648template <class Emitter>4649VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,4650bool Toplevel,4651bool IsConstexprUnknown) {4652// We don't know what to do with these, so just return false.4653if (VD->getType().isNull())4654return false;46554656// This case is EvalEmitter-only. If we won't create any instructions for the4657// initializer anyway, don't bother creating the variable in the first place.4658if (!this->isActive())4659return VarCreationState::NotCreated();46604661const Expr *Init = VD->getInit();4662std::optional<PrimType> VarT = classify(VD->getType());46634664if (Init && Init->isValueDependent())4665return false;46664667if (Context::shouldBeGloballyIndexed(VD)) {4668auto checkDecl = [&]() -> bool {4669bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();4670return !NeedsOp || this->emitCheckDecl(VD, VD);4671};46724673auto initGlobal = [&](unsigned GlobalIndex) -> bool {4674assert(Init);46754676if (VarT) {4677if (!this->visit(Init))4678return checkDecl() && false;46794680return checkDecl() && this->emitInitGlobal(*VarT, GlobalIndex, VD);4681}46824683if (!checkDecl())4684return false;46854686if (!this->emitGetPtrGlobal(GlobalIndex, Init))4687return false;46884689if (!visitInitializer(Init))4690return false;46914692return this->emitFinishInitGlobal(Init);4693};46944695DeclScope<Emitter> LocalScope(this, VD);46964697// We've already seen and initialized this global.4698if (std::optional<unsigned> GlobalIndex = P.getGlobal(VD)) {4699if (P.getPtrGlobal(*GlobalIndex).isInitialized())4700return checkDecl();47014702// The previous attempt at initialization might've been unsuccessful,4703// so let's try this one.4704return Init && checkDecl() && initGlobal(*GlobalIndex);4705}47064707std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);47084709if (!GlobalIndex)4710return false;47114712return !Init || (checkDecl() && initGlobal(*GlobalIndex));4713}4714// Local variables.4715InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));47164717if (VarT) {4718unsigned Offset = this->allocateLocalPrimitive(4719VD, *VarT, VD->getType().isConstQualified(), nullptr, ScopeKind::Block,4720IsConstexprUnknown);4721if (Init) {4722// If this is a toplevel declaration, create a scope for the4723// initializer.4724if (Toplevel) {4725LocalScope<Emitter> Scope(this);4726if (!this->visit(Init))4727return false;4728return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();4729} else {4730if (!this->visit(Init))4731return false;4732return this->emitSetLocal(*VarT, Offset, VD);4733}4734}4735} else {4736if (std::optional<unsigned> Offset = this->allocateLocal(4737VD, VD->getType(), nullptr, ScopeKind::Block, IsConstexprUnknown)) {4738if (!Init)4739return true;47404741if (!this->emitGetPtrLocal(*Offset, Init))4742return false;47434744if (!visitInitializer(Init))4745return false;47464747return this->emitFinishInitPop(Init);4748}4749return false;4750}4751return true;4752}47534754template <class Emitter>4755bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,4756const Expr *E) {4757assert(!DiscardResult);4758if (Val.isInt())4759return this->emitConst(Val.getInt(), ValType, E);4760else if (Val.isFloat()) {4761APFloat F = Val.getFloat();4762return this->emitFloat(F, E);4763}47644765if (Val.isLValue()) {4766if (Val.isNullPointer())4767return this->emitNull(ValType, 0, nullptr, E);4768APValue::LValueBase Base = Val.getLValueBase();4769if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())4770return this->visit(BaseExpr);4771else if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) {4772return this->visitDeclRef(VD, E);4773}4774} else if (Val.isMemberPointer()) {4775if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())4776return this->emitGetMemberPtr(MemberDecl, E);4777return this->emitNullMemberPtr(0, nullptr, E);4778}47794780return false;4781}47824783template <class Emitter>4784bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,4785const Expr *E, QualType T) {4786if (Val.isStruct()) {4787const Record *R = this->getRecord(T);4788assert(R);4789for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) {4790const APValue &F = Val.getStructField(I);4791const Record::Field *RF = R->getField(I);4792QualType FieldType = RF->Decl->getType();47934794if (std::optional<PrimType> PT = classify(FieldType)) {4795if (!this->visitAPValue(F, *PT, E))4796return false;4797if (!this->emitInitField(*PT, RF->Offset, E))4798return false;4799} else {4800if (!this->emitGetPtrField(RF->Offset, E))4801return false;4802if (!this->visitAPValueInitializer(F, E, FieldType))4803return false;4804if (!this->emitPopPtr(E))4805return false;4806}4807}4808return true;4809} else if (Val.isUnion()) {4810const FieldDecl *UnionField = Val.getUnionField();4811const Record *R = this->getRecord(UnionField->getParent());4812assert(R);4813const APValue &F = Val.getUnionValue();4814const Record::Field *RF = R->getField(UnionField);4815PrimType T = classifyPrim(RF->Decl->getType());4816if (!this->visitAPValue(F, T, E))4817return false;4818return this->emitInitField(T, RF->Offset, E);4819} else if (Val.isArray()) {4820const auto *ArrType = T->getAsArrayTypeUnsafe();4821QualType ElemType = ArrType->getElementType();4822for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {4823const APValue &Elem = Val.getArrayInitializedElt(A);4824if (std::optional<PrimType> ElemT = classify(ElemType)) {4825if (!this->visitAPValue(Elem, *ElemT, E))4826return false;4827if (!this->emitInitElem(*ElemT, A, E))4828return false;4829} else {4830if (!this->emitConstUint32(A, E))4831return false;4832if (!this->emitArrayElemPtrUint32(E))4833return false;4834if (!this->visitAPValueInitializer(Elem, E, ElemType))4835return false;4836if (!this->emitPopPtr(E))4837return false;4838}4839}4840return true;4841}4842// TODO: Other types.48434844return false;4845}48464847template <class Emitter>4848bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,4849unsigned BuiltinID) {48504851if (BuiltinID == Builtin::BI__builtin_constant_p) {4852// Void argument is always invalid and harder to handle later.4853if (E->getArg(0)->getType()->isVoidType()) {4854if (DiscardResult)4855return true;4856return this->emitConst(0, E);4857}48584859if (!this->emitStartSpeculation(E))4860return false;4861LabelTy EndLabel = this->getLabel();4862if (!this->speculate(E, EndLabel))4863return false;4864this->fallthrough(EndLabel);4865if (!this->emitEndSpeculation(E))4866return false;4867if (DiscardResult)4868return this->emitPop(classifyPrim(E), E);4869return true;4870}48714872// For these, we're expected to ultimately return an APValue pointing4873// to the CallExpr. This is needed to get the correct codegen.4874if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||4875BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||4876BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||4877BuiltinID == Builtin::BI__builtin_function_start) {4878if (DiscardResult)4879return true;4880return this->emitDummyPtr(E, E);4881}48824883QualType ReturnType = E->getType();4884std::optional<PrimType> ReturnT = classify(E);48854886// Non-primitive return type. Prepare storage.4887if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {4888std::optional<unsigned> LocalIndex = allocateLocal(E);4889if (!LocalIndex)4890return false;4891if (!this->emitGetPtrLocal(*LocalIndex, E))4892return false;4893}48944895if (!Context::isUnevaluatedBuiltin(BuiltinID)) {4896// Put arguments on the stack.4897for (const auto *Arg : E->arguments()) {4898if (!this->visit(Arg))4899return false;4900}4901}49024903if (!this->emitCallBI(E, BuiltinID, E))4904return false;49054906if (DiscardResult && !ReturnType->isVoidType()) {4907assert(ReturnT);4908return this->emitPop(*ReturnT, E);4909}49104911return true;4912}49134914static const Expr *stripDerivedToBaseCasts(const Expr *E) {4915if (const auto *PE = dyn_cast<ParenExpr>(E))4916return stripDerivedToBaseCasts(PE->getSubExpr());49174918if (const auto *CE = dyn_cast<CastExpr>(E);4919CE &&4920(CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))4921return stripDerivedToBaseCasts(CE->getSubExpr());49224923return E;4924}49254926template <class Emitter>4927bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {4928const FunctionDecl *FuncDecl = E->getDirectCallee();49294930if (FuncDecl) {4931if (unsigned BuiltinID = FuncDecl->getBuiltinID())4932return VisitBuiltinCallExpr(E, BuiltinID);49334934// Calls to replaceable operator new/operator delete.4935if (FuncDecl->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {4936if (FuncDecl->getDeclName().isAnyOperatorNew()) {4937return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new);4938} else {4939assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);4940return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);4941}4942}49434944// Explicit calls to trivial destructors4945if (const auto *DD = dyn_cast<CXXDestructorDecl>(FuncDecl);4946DD && DD->isTrivial()) {4947const auto *MemberCall = cast<CXXMemberCallExpr>(E);4948if (!this->visit(MemberCall->getImplicitObjectArgument()))4949return false;4950return this->emitCheckDestruction(E) && this->emitEndLifetime(E) &&4951this->emitPopPtr(E);4952}4953}49544955BlockScope<Emitter> CallScope(this, ScopeKind::Call);49564957QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());4958std::optional<PrimType> T = classify(ReturnType);4959bool HasRVO = !ReturnType->isVoidType() && !T;49604961if (HasRVO) {4962if (DiscardResult) {4963// If we need to discard the return value but the function returns its4964// value via an RVO pointer, we need to create one such pointer just4965// for this call.4966if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {4967if (!this->emitGetPtrLocal(*LocalIndex, E))4968return false;4969}4970} else {4971// We need the result. Prepare a pointer to return or4972// dup the current one.4973if (!Initializing) {4974if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {4975if (!this->emitGetPtrLocal(*LocalIndex, E))4976return false;4977}4978}4979if (!this->emitDupPtr(E))4980return false;4981}4982}49834984SmallVector<const Expr *, 8> Args(ArrayRef(E->getArgs(), E->getNumArgs()));49854986bool IsAssignmentOperatorCall = false;4987if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);4988OCE && OCE->isAssignmentOp()) {4989// Just like with regular assignments, we need to special-case assignment4990// operators here and evaluate the RHS (the second arg) before the LHS (the4991// first arg). We fix this by using a Flip op later.4992assert(Args.size() == 2);4993IsAssignmentOperatorCall = true;4994std::reverse(Args.begin(), Args.end());4995}4996// Calling a static operator will still4997// pass the instance, but we don't need it.4998// Discard it here.4999if (isa<CXXOperatorCallExpr>(E)) {5000if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FuncDecl);5001MD && MD->isStatic()) {5002if (!this->discard(E->getArg(0)))5003return false;5004// Drop first arg.5005Args.erase(Args.begin());5006}5007}50085009bool Devirtualized = false;5010std::optional<unsigned> CalleeOffset;5011// Add the (optional, implicit) This pointer.5012if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {5013if (!FuncDecl && classifyPrim(E->getCallee()) == PT_MemberPtr) {5014// If we end up creating a CallPtr op for this, we need the base of the5015// member pointer as the instance pointer, and later extract the function5016// decl as the function pointer.5017const Expr *Callee = E->getCallee();5018CalleeOffset =5019this->allocateLocalPrimitive(Callee, PT_MemberPtr, /*IsConst=*/true);5020if (!this->visit(Callee))5021return false;5022if (!this->emitSetLocal(PT_MemberPtr, *CalleeOffset, E))5023return false;5024if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))5025return false;5026if (!this->emitGetMemberPtrBase(E))5027return false;5028} else {5029const auto *InstancePtr = MC->getImplicitObjectArgument();5030if (isa_and_nonnull<CXXDestructorDecl>(CompilingFunction) ||5031isa_and_nonnull<CXXConstructorDecl>(CompilingFunction)) {5032const auto *Stripped = stripDerivedToBaseCasts(InstancePtr);5033if (isa<CXXThisExpr>(Stripped)) {5034FuncDecl =5035cast<CXXMethodDecl>(FuncDecl)->getCorrespondingMethodInClass(5036Stripped->getType()->getPointeeType()->getAsCXXRecordDecl());5037Devirtualized = true;5038if (!this->visit(Stripped))5039return false;5040} else {5041if (!this->visit(InstancePtr))5042return false;5043}5044} else {5045if (!this->visit(InstancePtr))5046return false;5047}5048}5049} else if (const auto *PD =5050dyn_cast<CXXPseudoDestructorExpr>(E->getCallee())) {5051if (!this->emitCheckPseudoDtor(E))5052return false;5053const Expr *Base = PD->getBase();5054if (!Base->isGLValue())5055return this->discard(Base);5056if (!this->visit(Base))5057return false;5058return this->emitEndLifetimePop(E);5059} else if (!FuncDecl) {5060const Expr *Callee = E->getCallee();5061CalleeOffset =5062this->allocateLocalPrimitive(Callee, PT_Ptr, /*IsConst=*/true);5063if (!this->visit(Callee))5064return false;5065if (!this->emitSetLocal(PT_Ptr, *CalleeOffset, E))5066return false;5067}50685069if (!this->visitCallArgs(Args, FuncDecl))5070return false;50715072// Undo the argument reversal we did earlier.5073if (IsAssignmentOperatorCall) {5074assert(Args.size() == 2);5075PrimType Arg1T = classify(Args[0]).value_or(PT_Ptr);5076PrimType Arg2T = classify(Args[1]).value_or(PT_Ptr);5077if (!this->emitFlip(Arg2T, Arg1T, E))5078return false;5079}50805081if (FuncDecl) {5082const Function *Func = getFunction(FuncDecl);5083if (!Func)5084return false;5085assert(HasRVO == Func->hasRVO());50865087bool HasQualifier = false;5088if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee()))5089HasQualifier = ME->hasQualifier();50905091bool IsVirtual = false;5092if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))5093IsVirtual = !Devirtualized && MD->isVirtual();50945095// In any case call the function. The return value will end up on the stack5096// and if the function has RVO, we already have the pointer on the stack to5097// write the result into.5098if (IsVirtual && !HasQualifier) {5099uint32_t VarArgSize = 0;5100unsigned NumParams =5101Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);5102for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)5103VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));51045105if (!this->emitCallVirt(Func, VarArgSize, E))5106return false;5107} else if (Func->isVariadic()) {5108uint32_t VarArgSize = 0;5109unsigned NumParams =5110Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);5111for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)5112VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));5113if (!this->emitCallVar(Func, VarArgSize, E))5114return false;5115} else {5116if (!this->emitCall(Func, 0, E))5117return false;5118}5119} else {5120// Indirect call. Visit the callee, which will leave a FunctionPointer on5121// the stack. Cleanup of the returned value if necessary will be done after5122// the function call completed.51235124// Sum the size of all args from the call expr.5125uint32_t ArgSize = 0;5126for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)5127ArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));51285129// Get the callee, either from a member pointer or function pointer saved in5130// CalleeOffset.5131if (isa<CXXMemberCallExpr>(E) && CalleeOffset) {5132if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))5133return false;5134if (!this->emitGetMemberPtrDecl(E))5135return false;5136} else {5137if (!this->emitGetLocal(PT_Ptr, *CalleeOffset, E))5138return false;5139}5140if (!this->emitCallPtr(ArgSize, E, E))5141return false;5142}51435144// Cleanup for discarded return values.5145if (DiscardResult && !ReturnType->isVoidType() && T)5146return this->emitPop(*T, E) && CallScope.destroyLocals();51475148return CallScope.destroyLocals();5149}51505151template <class Emitter>5152bool Compiler<Emitter>::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {5153SourceLocScope<Emitter> SLS(this, E);51545155return this->delegate(E->getExpr());5156}51575158template <class Emitter>5159bool Compiler<Emitter>::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {5160SourceLocScope<Emitter> SLS(this, E);51615162return this->delegate(E->getExpr());5163}51645165template <class Emitter>5166bool Compiler<Emitter>::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {5167if (DiscardResult)5168return true;51695170return this->emitConstBool(E->getValue(), E);5171}51725173template <class Emitter>5174bool Compiler<Emitter>::VisitCXXNullPtrLiteralExpr(5175const CXXNullPtrLiteralExpr *E) {5176if (DiscardResult)5177return true;51785179uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());5180return this->emitNullPtr(Val, nullptr, E);5181}51825183template <class Emitter>5184bool Compiler<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) {5185if (DiscardResult)5186return true;51875188assert(E->getType()->isIntegerType());51895190PrimType T = classifyPrim(E->getType());5191return this->emitZero(T, E);5192}51935194template <class Emitter>5195bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {5196if (DiscardResult)5197return true;51985199if (this->LambdaThisCapture.Offset > 0) {5200if (this->LambdaThisCapture.IsPtr)5201return this->emitGetThisFieldPtr(this->LambdaThisCapture.Offset, E);5202return this->emitGetPtrThisField(this->LambdaThisCapture.Offset, E);5203}52045205// In some circumstances, the 'this' pointer does not actually refer to the5206// instance pointer of the current function frame, but e.g. to the declaration5207// currently being initialized. Here we emit the necessary instruction(s) for5208// this scenario.5209if (!InitStackActive)5210return this->emitThis(E);52115212if (!InitStack.empty()) {5213// If our init stack is, for example:5214// 0 Stack: 3 (decl)5215// 1 Stack: 6 (init list)5216// 2 Stack: 1 (field)5217// 3 Stack: 6 (init list)5218// 4 Stack: 1 (field)5219//5220// We want to find the LAST element in it that's an init list,5221// which is marked with the K_InitList marker. The index right5222// before that points to an init list. We need to find the5223// elements before the K_InitList element that point to a base5224// (e.g. a decl or This), optionally followed by field, elem, etc.5225// In the example above, we want to emit elements [0..2].5226unsigned StartIndex = 0;5227unsigned EndIndex = 0;5228// Find the init list.5229for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {5230if (InitStack[StartIndex].Kind == InitLink::K_InitList ||5231InitStack[StartIndex].Kind == InitLink::K_This) {5232EndIndex = StartIndex;5233--StartIndex;5234break;5235}5236}52375238// Walk backwards to find the base.5239for (; StartIndex > 0; --StartIndex) {5240if (InitStack[StartIndex].Kind == InitLink::K_InitList)5241continue;52425243if (InitStack[StartIndex].Kind != InitLink::K_Field &&5244InitStack[StartIndex].Kind != InitLink::K_Elem)5245break;5246}52475248// Emit the instructions.5249for (unsigned I = StartIndex; I != EndIndex; ++I) {5250if (InitStack[I].Kind == InitLink::K_InitList)5251continue;5252if (!InitStack[I].template emit<Emitter>(this, E))5253return false;5254}5255return true;5256}5257return this->emitThis(E);5258}52595260template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) {5261switch (S->getStmtClass()) {5262case Stmt::CompoundStmtClass:5263return visitCompoundStmt(cast<CompoundStmt>(S));5264case Stmt::DeclStmtClass:5265return visitDeclStmt(cast<DeclStmt>(S), /*EvaluateConditionDecl=*/true);5266case Stmt::ReturnStmtClass:5267return visitReturnStmt(cast<ReturnStmt>(S));5268case Stmt::IfStmtClass:5269return visitIfStmt(cast<IfStmt>(S));5270case Stmt::WhileStmtClass:5271return visitWhileStmt(cast<WhileStmt>(S));5272case Stmt::DoStmtClass:5273return visitDoStmt(cast<DoStmt>(S));5274case Stmt::ForStmtClass:5275return visitForStmt(cast<ForStmt>(S));5276case Stmt::CXXForRangeStmtClass:5277return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));5278case Stmt::BreakStmtClass:5279return visitBreakStmt(cast<BreakStmt>(S));5280case Stmt::ContinueStmtClass:5281return visitContinueStmt(cast<ContinueStmt>(S));5282case Stmt::SwitchStmtClass:5283return visitSwitchStmt(cast<SwitchStmt>(S));5284case Stmt::CaseStmtClass:5285return visitCaseStmt(cast<CaseStmt>(S));5286case Stmt::DefaultStmtClass:5287return visitDefaultStmt(cast<DefaultStmt>(S));5288case Stmt::AttributedStmtClass:5289return visitAttributedStmt(cast<AttributedStmt>(S));5290case Stmt::CXXTryStmtClass:5291return visitCXXTryStmt(cast<CXXTryStmt>(S));5292case Stmt::NullStmtClass:5293return true;5294// Always invalid statements.5295case Stmt::GCCAsmStmtClass:5296case Stmt::MSAsmStmtClass:5297case Stmt::GotoStmtClass:5298return this->emitInvalid(S);5299case Stmt::LabelStmtClass:5300return this->visitStmt(cast<LabelStmt>(S)->getSubStmt());5301default: {5302if (const auto *E = dyn_cast<Expr>(S))5303return this->discard(E);5304return false;5305}5306}5307}53085309template <class Emitter>5310bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {5311BlockScope<Emitter> Scope(this);5312for (const auto *InnerStmt : S->body())5313if (!visitStmt(InnerStmt))5314return false;5315return Scope.destroyLocals();5316}53175318template <class Emitter>5319bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {5320if (auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) {5321for (auto *BD : DD->flat_bindings())5322if (auto *KD = BD->getHoldingVar(); KD && !this->visitVarDecl(KD))5323return false;5324}5325return true;5326}53275328template <class Emitter>5329bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,5330bool EvaluateConditionDecl) {5331for (const auto *D : DS->decls()) {5332if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, BaseUsingDecl,5333FunctionDecl, NamespaceAliasDecl, UsingDirectiveDecl>(D))5334continue;53355336const auto *VD = dyn_cast<VarDecl>(D);5337if (!VD)5338return false;5339if (!this->visitVarDecl(VD))5340return false;53415342// Register decomposition decl holding vars.5343if (EvaluateConditionDecl && !this->maybeEmitDeferredVarInit(VD))5344return false;5345}53465347return true;5348}53495350template <class Emitter>5351bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {5352if (this->InStmtExpr)5353return this->emitUnsupported(RS);53545355if (const Expr *RE = RS->getRetValue()) {5356LocalScope<Emitter> RetScope(this);5357if (ReturnType) {5358// Primitive types are simply returned.5359if (!this->visit(RE))5360return false;5361this->emitCleanup();5362return this->emitRet(*ReturnType, RS);5363} else if (RE->getType()->isVoidType()) {5364if (!this->visit(RE))5365return false;5366} else {5367InitLinkScope<Emitter> ILS(this, InitLink::RVO());5368// RVO - construct the value in the return location.5369if (!this->emitRVOPtr(RE))5370return false;5371if (!this->visitInitializer(RE))5372return false;5373if (!this->emitPopPtr(RE))5374return false;53755376this->emitCleanup();5377return this->emitRetVoid(RS);5378}5379}53805381// Void return.5382this->emitCleanup();5383return this->emitRetVoid(RS);5384}53855386template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {5387auto visitChildStmt = [&](const Stmt *S) -> bool {5388LocalScope<Emitter> SScope(this);5389if (!visitStmt(S))5390return false;5391return SScope.destroyLocals();5392};5393if (auto *CondInit = IS->getInit())5394if (!visitStmt(CondInit))5395return false;53965397if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())5398if (!visitDeclStmt(CondDecl))5399return false;54005401// Save ourselves compiling some code and the jumps, etc. if the condition is5402// stataically known to be either true or false. We could look at more cases5403// here, but I think all the ones that actually happen are using a5404// ConstantExpr.5405if (std::optional<bool> BoolValue = getBoolValue(IS->getCond())) {5406if (*BoolValue)5407return visitChildStmt(IS->getThen());5408else if (const Stmt *Else = IS->getElse())5409return visitChildStmt(Else);5410return true;5411}54125413// Otherwise, compile the condition.5414if (IS->isNonNegatedConsteval()) {5415if (!this->emitIsConstantContext(IS))5416return false;5417} else if (IS->isNegatedConsteval()) {5418if (!this->emitIsConstantContext(IS))5419return false;5420if (!this->emitInv(IS))5421return false;5422} else {5423if (!this->visitBool(IS->getCond()))5424return false;5425}54265427if (!this->maybeEmitDeferredVarInit(IS->getConditionVariable()))5428return false;54295430if (const Stmt *Else = IS->getElse()) {5431LabelTy LabelElse = this->getLabel();5432LabelTy LabelEnd = this->getLabel();5433if (!this->jumpFalse(LabelElse))5434return false;5435if (!visitChildStmt(IS->getThen()))5436return false;5437if (!this->jump(LabelEnd))5438return false;5439this->emitLabel(LabelElse);5440if (!visitChildStmt(Else))5441return false;5442this->emitLabel(LabelEnd);5443} else {5444LabelTy LabelEnd = this->getLabel();5445if (!this->jumpFalse(LabelEnd))5446return false;5447if (!visitChildStmt(IS->getThen()))5448return false;5449this->emitLabel(LabelEnd);5450}54515452return true;5453}54545455template <class Emitter>5456bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {5457const Expr *Cond = S->getCond();5458const Stmt *Body = S->getBody();54595460LabelTy CondLabel = this->getLabel(); // Label before the condition.5461LabelTy EndLabel = this->getLabel(); // Label after the loop.5462LoopScope<Emitter> LS(this, EndLabel, CondLabel);54635464this->fallthrough(CondLabel);5465this->emitLabel(CondLabel);54665467{5468LocalScope<Emitter> CondScope(this);5469if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())5470if (!visitDeclStmt(CondDecl))5471return false;54725473if (!this->visitBool(Cond))5474return false;54755476if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))5477return false;54785479if (!this->jumpFalse(EndLabel))5480return false;54815482if (!this->visitStmt(Body))5483return false;54845485if (!CondScope.destroyLocals())5486return false;5487}5488if (!this->jump(CondLabel))5489return false;5490this->fallthrough(EndLabel);5491this->emitLabel(EndLabel);54925493return true;5494}54955496template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {5497const Expr *Cond = S->getCond();5498const Stmt *Body = S->getBody();54995500LabelTy StartLabel = this->getLabel();5501LabelTy EndLabel = this->getLabel();5502LabelTy CondLabel = this->getLabel();5503LoopScope<Emitter> LS(this, EndLabel, CondLabel);55045505this->fallthrough(StartLabel);5506this->emitLabel(StartLabel);55075508{5509LocalScope<Emitter> CondScope(this);5510if (!this->visitStmt(Body))5511return false;5512this->fallthrough(CondLabel);5513this->emitLabel(CondLabel);5514if (!this->visitBool(Cond))5515return false;55165517if (!CondScope.destroyLocals())5518return false;5519}5520if (!this->jumpTrue(StartLabel))5521return false;55225523this->fallthrough(EndLabel);5524this->emitLabel(EndLabel);5525return true;5526}55275528template <class Emitter>5529bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {5530// for (Init; Cond; Inc) { Body }5531const Stmt *Init = S->getInit();5532const Expr *Cond = S->getCond();5533const Expr *Inc = S->getInc();5534const Stmt *Body = S->getBody();55355536LabelTy EndLabel = this->getLabel();5537LabelTy CondLabel = this->getLabel();5538LabelTy IncLabel = this->getLabel();5539LoopScope<Emitter> LS(this, EndLabel, IncLabel);55405541if (Init && !this->visitStmt(Init))5542return false;55435544this->fallthrough(CondLabel);5545this->emitLabel(CondLabel);55465547// Start of loop body.5548LocalScope<Emitter> CondScope(this);5549if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())5550if (!visitDeclStmt(CondDecl))5551return false;55525553if (Cond) {5554if (!this->visitBool(Cond))5555return false;5556if (!this->jumpFalse(EndLabel))5557return false;5558}5559if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))5560return false;55615562if (Body && !this->visitStmt(Body))5563return false;55645565this->fallthrough(IncLabel);5566this->emitLabel(IncLabel);5567if (Inc && !this->discard(Inc))5568return false;55695570if (!CondScope.destroyLocals())5571return false;5572if (!this->jump(CondLabel))5573return false;5574// End of loop body.55755576this->emitLabel(EndLabel);5577// If we jumped out of the loop above, we still need to clean up the condition5578// scope.5579return CondScope.destroyLocals();5580}55815582template <class Emitter>5583bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {5584const Stmt *Init = S->getInit();5585const Expr *Cond = S->getCond();5586const Expr *Inc = S->getInc();5587const Stmt *Body = S->getBody();5588const Stmt *BeginStmt = S->getBeginStmt();5589const Stmt *RangeStmt = S->getRangeStmt();5590const Stmt *EndStmt = S->getEndStmt();55915592LabelTy EndLabel = this->getLabel();5593LabelTy CondLabel = this->getLabel();5594LabelTy IncLabel = this->getLabel();5595LoopScope<Emitter> LS(this, EndLabel, IncLabel);55965597// Emit declarations needed in the loop.5598if (Init && !this->visitStmt(Init))5599return false;5600if (!this->visitStmt(RangeStmt))5601return false;5602if (!this->visitStmt(BeginStmt))5603return false;5604if (!this->visitStmt(EndStmt))5605return false;56065607// Now the condition as well as the loop variable assignment.5608this->fallthrough(CondLabel);5609this->emitLabel(CondLabel);5610if (!this->visitBool(Cond))5611return false;5612if (!this->jumpFalse(EndLabel))5613return false;56145615if (!this->visitDeclStmt(S->getLoopVarStmt(), /*EvaluateConditionDecl=*/true))5616return false;56175618// Body.5619{5620if (!this->visitStmt(Body))5621return false;56225623this->fallthrough(IncLabel);5624this->emitLabel(IncLabel);5625if (!this->discard(Inc))5626return false;5627}56285629if (!this->jump(CondLabel))5630return false;56315632this->fallthrough(EndLabel);5633this->emitLabel(EndLabel);5634return true;5635}56365637template <class Emitter>5638bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {5639if (!BreakLabel)5640return false;56415642for (VariableScope<Emitter> *C = VarScope; C != BreakVarScope;5643C = C->getParent())5644C->emitDestruction();5645return this->jump(*BreakLabel);5646}56475648template <class Emitter>5649bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {5650if (!ContinueLabel)5651return false;56525653for (VariableScope<Emitter> *C = VarScope;5654C && C->getParent() != ContinueVarScope; C = C->getParent())5655C->emitDestruction();5656return this->jump(*ContinueLabel);5657}56585659template <class Emitter>5660bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {5661const Expr *Cond = S->getCond();5662if (Cond->containsErrors())5663return false;56645665PrimType CondT = this->classifyPrim(Cond->getType());5666LocalScope<Emitter> LS(this);56675668LabelTy EndLabel = this->getLabel();5669OptLabelTy DefaultLabel = std::nullopt;5670unsigned CondVar =5671this->allocateLocalPrimitive(Cond, CondT, /*IsConst=*/true);56725673if (const auto *CondInit = S->getInit())5674if (!visitStmt(CondInit))5675return false;56765677if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())5678if (!visitDeclStmt(CondDecl))5679return false;56805681// Initialize condition variable.5682if (!this->visit(Cond))5683return false;5684if (!this->emitSetLocal(CondT, CondVar, S))5685return false;56865687if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))5688return false;56895690CaseMap CaseLabels;5691// Create labels and comparison ops for all case statements.5692for (const SwitchCase *SC = S->getSwitchCaseList(); SC;5693SC = SC->getNextSwitchCase()) {5694if (const auto *CS = dyn_cast<CaseStmt>(SC)) {5695// FIXME: Implement ranges.5696if (CS->caseStmtIsGNURange())5697return false;5698CaseLabels[SC] = this->getLabel();56995700const Expr *Value = CS->getLHS();5701PrimType ValueT = this->classifyPrim(Value->getType());57025703// Compare the case statement's value to the switch condition.5704if (!this->emitGetLocal(CondT, CondVar, CS))5705return false;5706if (!this->visit(Value))5707return false;57085709// Compare and jump to the case label.5710if (!this->emitEQ(ValueT, S))5711return false;5712if (!this->jumpTrue(CaseLabels[CS]))5713return false;5714} else {5715assert(!DefaultLabel);5716DefaultLabel = this->getLabel();5717}5718}57195720// If none of the conditions above were true, fall through to the default5721// statement or jump after the switch statement.5722if (DefaultLabel) {5723if (!this->jump(*DefaultLabel))5724return false;5725} else {5726if (!this->jump(EndLabel))5727return false;5728}57295730SwitchScope<Emitter> SS(this, std::move(CaseLabels), EndLabel, DefaultLabel);5731if (!this->visitStmt(S->getBody()))5732return false;5733this->emitLabel(EndLabel);57345735return LS.destroyLocals();5736}57375738template <class Emitter>5739bool Compiler<Emitter>::visitCaseStmt(const CaseStmt *S) {5740this->emitLabel(CaseLabels[S]);5741return this->visitStmt(S->getSubStmt());5742}57435744template <class Emitter>5745bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) {5746this->emitLabel(*DefaultLabel);5747return this->visitStmt(S->getSubStmt());5748}57495750template <class Emitter>5751bool Compiler<Emitter>::visitAttributedStmt(const AttributedStmt *S) {5752if (this->Ctx.getLangOpts().CXXAssumptions &&5753!this->Ctx.getLangOpts().MSVCCompat) {5754for (const Attr *A : S->getAttrs()) {5755auto *AA = dyn_cast<CXXAssumeAttr>(A);5756if (!AA)5757continue;57585759assert(isa<NullStmt>(S->getSubStmt()));57605761const Expr *Assumption = AA->getAssumption();5762if (Assumption->isValueDependent())5763return false;57645765if (Assumption->HasSideEffects(this->Ctx.getASTContext()))5766continue;57675768// Evaluate assumption.5769if (!this->visitBool(Assumption))5770return false;57715772if (!this->emitAssume(Assumption))5773return false;5774}5775}57765777// Ignore other attributes.5778return this->visitStmt(S->getSubStmt());5779}57805781template <class Emitter>5782bool Compiler<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {5783// Ignore all handlers.5784return this->visitStmt(S->getTryBlock());5785}57865787template <class Emitter>5788bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {5789assert(MD->isLambdaStaticInvoker());5790assert(MD->hasBody());5791assert(cast<CompoundStmt>(MD->getBody())->body_empty());57925793const CXXRecordDecl *ClosureClass = MD->getParent();5794const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();5795assert(ClosureClass->captures_begin() == ClosureClass->captures_end());5796const Function *Func = this->getFunction(LambdaCallOp);5797if (!Func)5798return false;5799assert(Func->hasThisPointer());5800assert(Func->getNumParams() == (MD->getNumParams() + 1 + Func->hasRVO()));58015802if (Func->hasRVO()) {5803if (!this->emitRVOPtr(MD))5804return false;5805}58065807// The lambda call operator needs an instance pointer, but we don't have5808// one here, and we don't need one either because the lambda cannot have5809// any captures, as verified above. Emit a null pointer. This is then5810// special-cased when interpreting to not emit any misleading diagnostics.5811if (!this->emitNullPtr(0, nullptr, MD))5812return false;58135814// Forward all arguments from the static invoker to the lambda call operator.5815for (const ParmVarDecl *PVD : MD->parameters()) {5816auto It = this->Params.find(PVD);5817assert(It != this->Params.end());58185819// We do the lvalue-to-rvalue conversion manually here, so no need5820// to care about references.5821PrimType ParamType = this->classify(PVD->getType()).value_or(PT_Ptr);5822if (!this->emitGetParam(ParamType, It->second.Offset, MD))5823return false;5824}58255826if (!this->emitCall(Func, 0, LambdaCallOp))5827return false;58285829this->emitCleanup();5830if (ReturnType)5831return this->emitRet(*ReturnType, MD);58325833// Nothing to do, since we emitted the RVO pointer above.5834return this->emitRetVoid(MD);5835}58365837template <class Emitter>5838bool Compiler<Emitter>::checkLiteralType(const Expr *E) {5839if (Ctx.getLangOpts().CPlusPlus23)5840return true;58415842if (!E->isPRValue() || E->getType()->isLiteralType(Ctx.getASTContext()))5843return true;58445845return this->emitCheckLiteralType(E->getType().getTypePtr(), E);5846}58475848template <class Emitter>5849bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {5850assert(!ReturnType);58515852auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,5853const Expr *InitExpr) -> bool {5854// We don't know what to do with these, so just return false.5855if (InitExpr->getType().isNull())5856return false;58575858if (std::optional<PrimType> T = this->classify(InitExpr)) {5859if (!this->visit(InitExpr))5860return false;58615862if (F->isBitField())5863return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);5864return this->emitInitThisField(*T, FieldOffset, InitExpr);5865}5866// Non-primitive case. Get a pointer to the field-to-initialize5867// on the stack and call visitInitialzer() for it.5868InitLinkScope<Emitter> FieldScope(this, InitLink::Field(F->Offset));5869if (!this->emitGetPtrThisField(FieldOffset, InitExpr))5870return false;58715872if (!this->visitInitializer(InitExpr))5873return false;58745875return this->emitFinishInitPop(InitExpr);5876};58775878const RecordDecl *RD = Ctor->getParent();5879const Record *R = this->getRecord(RD);5880if (!R)5881return false;58825883if (R->isUnion() && Ctor->isCopyOrMoveConstructor()) {5884if (R->getNumFields() == 0)5885return this->emitRetVoid(Ctor);5886// union copy and move ctors are special.5887assert(cast<CompoundStmt>(Ctor->getBody())->body_empty());5888if (!this->emitThis(Ctor))5889return false;58905891auto PVD = Ctor->getParamDecl(0);5892ParamOffset PO = this->Params[PVD]; // Must exist.58935894if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor))5895return false;58965897return this->emitMemcpy(Ctor) && this->emitPopPtr(Ctor) &&5898this->emitRetVoid(Ctor);5899}59005901InitLinkScope<Emitter> InitScope(this, InitLink::This());5902for (const auto *Init : Ctor->inits()) {5903// Scope needed for the initializers.5904BlockScope<Emitter> Scope(this);59055906const Expr *InitExpr = Init->getInit();5907if (const FieldDecl *Member = Init->getMember()) {5908const Record::Field *F = R->getField(Member);59095910if (!emitFieldInitializer(F, F->Offset, InitExpr))5911return false;5912} else if (const Type *Base = Init->getBaseClass()) {5913const auto *BaseDecl = Base->getAsCXXRecordDecl();5914assert(BaseDecl);59155916if (Init->isBaseVirtual()) {5917assert(R->getVirtualBase(BaseDecl));5918if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))5919return false;59205921} else {5922// Base class initializer.5923// Get This Base and call initializer on it.5924const Record::Base *B = R->getBase(BaseDecl);5925assert(B);5926if (!this->emitGetPtrThisBase(B->Offset, InitExpr))5927return false;5928}59295930if (!this->visitInitializer(InitExpr))5931return false;5932if (!this->emitFinishInitPop(InitExpr))5933return false;5934} else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {5935assert(IFD->getChainingSize() >= 2);59365937unsigned NestedFieldOffset = 0;5938const Record::Field *NestedField = nullptr;5939for (const NamedDecl *ND : IFD->chain()) {5940const auto *FD = cast<FieldDecl>(ND);5941const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());5942assert(FieldRecord);59435944NestedField = FieldRecord->getField(FD);5945assert(NestedField);59465947NestedFieldOffset += NestedField->Offset;5948}5949assert(NestedField);59505951if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))5952return false;59535954// Mark all chain links as initialized.5955unsigned InitFieldOffset = 0;5956for (const NamedDecl *ND : IFD->chain().drop_back()) {5957const auto *FD = cast<FieldDecl>(ND);5958const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());5959assert(FieldRecord);5960NestedField = FieldRecord->getField(FD);5961InitFieldOffset += NestedField->Offset;5962assert(NestedField);5963if (!this->emitGetPtrThisField(InitFieldOffset, InitExpr))5964return false;5965if (!this->emitFinishInitPop(InitExpr))5966return false;5967}59685969} else {5970assert(Init->isDelegatingInitializer());5971if (!this->emitThis(InitExpr))5972return false;5973if (!this->visitInitializer(Init->getInit()))5974return false;5975if (!this->emitPopPtr(InitExpr))5976return false;5977}59785979if (!Scope.destroyLocals())5980return false;5981}59825983if (const auto *Body = Ctor->getBody())5984if (!visitStmt(Body))5985return false;59865987return this->emitRetVoid(SourceInfo{});5988}59895990template <class Emitter>5991bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {5992const RecordDecl *RD = Dtor->getParent();5993const Record *R = this->getRecord(RD);5994if (!R)5995return false;59965997if (!Dtor->isTrivial() && Dtor->getBody()) {5998if (!this->visitStmt(Dtor->getBody()))5999return false;6000}60016002if (!this->emitThis(Dtor))6003return false;60046005if (!this->emitCheckDestruction(Dtor))6006return false;60076008assert(R);6009if (!R->isUnion()) {6010// First, destroy all fields.6011for (const Record::Field &Field : llvm::reverse(R->fields())) {6012const Descriptor *D = Field.Desc;6013if (!D->isPrimitive() && !D->isPrimitiveArray()) {6014if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))6015return false;6016if (!this->emitDestruction(D, SourceInfo{}))6017return false;6018if (!this->emitPopPtr(SourceInfo{}))6019return false;6020}6021}6022}60236024for (const Record::Base &Base : llvm::reverse(R->bases())) {6025if (Base.R->isAnonymousUnion())6026continue;60276028if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))6029return false;6030if (!this->emitRecordDestruction(Base.R, {}))6031return false;6032if (!this->emitPopPtr(SourceInfo{}))6033return false;6034}60356036// FIXME: Virtual bases.6037return this->emitPopPtr(Dtor) && this->emitRetVoid(Dtor);6038}60396040template <class Emitter>6041bool Compiler<Emitter>::compileUnionAssignmentOperator(6042const CXXMethodDecl *MD) {6043if (!this->emitThis(MD))6044return false;60456046auto PVD = MD->getParamDecl(0);6047ParamOffset PO = this->Params[PVD]; // Must exist.60486049if (!this->emitGetParam(PT_Ptr, PO.Offset, MD))6050return false;60516052return this->emitMemcpy(MD) && this->emitRet(PT_Ptr, MD);6053}60546055template <class Emitter>6056bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {6057// Classify the return type.6058ReturnType = this->classify(F->getReturnType());60596060this->CompilingFunction = F;60616062if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F))6063return this->compileConstructor(Ctor);6064if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(F))6065return this->compileDestructor(Dtor);60666067// Emit custom code if this is a lambda static invoker.6068if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {6069const RecordDecl *RD = MD->getParent();60706071if (RD->isUnion() &&6072(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()))6073return this->compileUnionAssignmentOperator(MD);60746075if (MD->isLambdaStaticInvoker())6076return this->emitLambdaStaticInvokerBody(MD);6077}60786079// Regular functions.6080if (const auto *Body = F->getBody())6081if (!visitStmt(Body))6082return false;60836084// Emit a guard return to protect against a code path missing one.6085if (F->getReturnType()->isVoidType())6086return this->emitRetVoid(SourceInfo{});6087return this->emitNoRet(SourceInfo{});6088}60896090template <class Emitter>6091bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {6092const Expr *SubExpr = E->getSubExpr();6093if (SubExpr->getType()->isAnyComplexType())6094return this->VisitComplexUnaryOperator(E);6095if (SubExpr->getType()->isVectorType())6096return this->VisitVectorUnaryOperator(E);6097if (SubExpr->getType()->isFixedPointType())6098return this->VisitFixedPointUnaryOperator(E);6099std::optional<PrimType> T = classify(SubExpr->getType());61006101switch (E->getOpcode()) {6102case UO_PostInc: { // x++6103if (!Ctx.getLangOpts().CPlusPlus14)6104return this->emitInvalid(E);6105if (!T)6106return this->emitError(E);61076108if (!this->visit(SubExpr))6109return false;61106111if (T == PT_Ptr) {6112if (!this->emitIncPtr(E))6113return false;61146115return DiscardResult ? this->emitPopPtr(E) : true;6116}61176118if (T == PT_Float) {6119return DiscardResult ? this->emitIncfPop(getFPOptions(E), E)6120: this->emitIncf(getFPOptions(E), E);6121}61226123return DiscardResult ? this->emitIncPop(*T, E->canOverflow(), E)6124: this->emitInc(*T, E->canOverflow(), E);6125}6126case UO_PostDec: { // x--6127if (!Ctx.getLangOpts().CPlusPlus14)6128return this->emitInvalid(E);6129if (!T)6130return this->emitError(E);61316132if (!this->visit(SubExpr))6133return false;61346135if (T == PT_Ptr) {6136if (!this->emitDecPtr(E))6137return false;61386139return DiscardResult ? this->emitPopPtr(E) : true;6140}61416142if (T == PT_Float) {6143return DiscardResult ? this->emitDecfPop(getFPOptions(E), E)6144: this->emitDecf(getFPOptions(E), E);6145}61466147return DiscardResult ? this->emitDecPop(*T, E->canOverflow(), E)6148: this->emitDec(*T, E->canOverflow(), E);6149}6150case UO_PreInc: { // ++x6151if (!Ctx.getLangOpts().CPlusPlus14)6152return this->emitInvalid(E);6153if (!T)6154return this->emitError(E);61556156if (!this->visit(SubExpr))6157return false;61586159if (T == PT_Ptr) {6160if (!this->emitLoadPtr(E))6161return false;6162if (!this->emitConstUint8(1, E))6163return false;6164if (!this->emitAddOffsetUint8(E))6165return false;6166return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);6167}61686169// Post-inc and pre-inc are the same if the value is to be discarded.6170if (DiscardResult) {6171if (T == PT_Float)6172return this->emitIncfPop(getFPOptions(E), E);6173return this->emitIncPop(*T, E->canOverflow(), E);6174}61756176if (T == PT_Float) {6177const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());6178if (!this->emitLoadFloat(E))6179return false;6180APFloat F(TargetSemantics, 1);6181if (!this->emitFloat(F, E))6182return false;61836184if (!this->emitAddf(getFPOptions(E), E))6185return false;6186if (!this->emitStoreFloat(E))6187return false;6188} else {6189assert(isIntegralType(*T));6190if (!this->emitPreInc(*T, E->canOverflow(), E))6191return false;6192}6193return E->isGLValue() || this->emitLoadPop(*T, E);6194}6195case UO_PreDec: { // --x6196if (!Ctx.getLangOpts().CPlusPlus14)6197return this->emitInvalid(E);6198if (!T)6199return this->emitError(E);62006201if (!this->visit(SubExpr))6202return false;62036204if (T == PT_Ptr) {6205if (!this->emitLoadPtr(E))6206return false;6207if (!this->emitConstUint8(1, E))6208return false;6209if (!this->emitSubOffsetUint8(E))6210return false;6211return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);6212}62136214// Post-dec and pre-dec are the same if the value is to be discarded.6215if (DiscardResult) {6216if (T == PT_Float)6217return this->emitDecfPop(getFPOptions(E), E);6218return this->emitDecPop(*T, E->canOverflow(), E);6219}62206221if (T == PT_Float) {6222const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());6223if (!this->emitLoadFloat(E))6224return false;6225APFloat F(TargetSemantics, 1);6226if (!this->emitFloat(F, E))6227return false;62286229if (!this->emitSubf(getFPOptions(E), E))6230return false;6231if (!this->emitStoreFloat(E))6232return false;6233} else {6234assert(isIntegralType(*T));6235if (!this->emitPreDec(*T, E->canOverflow(), E))6236return false;6237}6238return E->isGLValue() || this->emitLoadPop(*T, E);6239}6240case UO_LNot: // !x6241if (!T)6242return this->emitError(E);62436244if (DiscardResult)6245return this->discard(SubExpr);62466247if (!this->visitBool(SubExpr))6248return false;62496250if (!this->emitInv(E))6251return false;62526253if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)6254return this->emitCast(PT_Bool, ET, E);6255return true;6256case UO_Minus: // -x6257if (!T)6258return this->emitError(E);62596260if (!this->visit(SubExpr))6261return false;6262return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);6263case UO_Plus: // +x6264if (!T)6265return this->emitError(E);62666267if (!this->visit(SubExpr)) // noop6268return false;6269return DiscardResult ? this->emitPop(*T, E) : true;6270case UO_AddrOf: // &x6271if (E->getType()->isMemberPointerType()) {6272// C++11 [expr.unary.op]p3 has very strict rules on how the address of a6273// member can be formed.6274return this->emitGetMemberPtr(cast<DeclRefExpr>(SubExpr)->getDecl(), E);6275}6276// We should already have a pointer when we get here.6277return this->delegate(SubExpr);6278case UO_Deref: // *x6279if (DiscardResult)6280return this->discard(SubExpr);62816282if (!this->visit(SubExpr))6283return false;62846285if (classifyPrim(SubExpr) == PT_Ptr)6286return this->emitNarrowPtr(E);6287return true;62886289case UO_Not: // ~x6290if (!T)6291return this->emitError(E);62926293if (!this->visit(SubExpr))6294return false;6295return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);6296case UO_Real: // __real x6297assert(T);6298return this->delegate(SubExpr);6299case UO_Imag: { // __imag x6300assert(T);6301if (!this->discard(SubExpr))6302return false;6303return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);6304}6305case UO_Extension:6306return this->delegate(SubExpr);6307case UO_Coawait:6308assert(false && "Unhandled opcode");6309}63106311return false;6312}63136314template <class Emitter>6315bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {6316const Expr *SubExpr = E->getSubExpr();6317assert(SubExpr->getType()->isAnyComplexType());63186319if (DiscardResult)6320return this->discard(SubExpr);63216322std::optional<PrimType> ResT = classify(E);6323auto prepareResult = [=]() -> bool {6324if (!ResT && !Initializing) {6325std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);6326if (!LocalIndex)6327return false;6328return this->emitGetPtrLocal(*LocalIndex, E);6329}63306331return true;6332};63336334// The offset of the temporary, if we created one.6335unsigned SubExprOffset = ~0u;6336auto createTemp = [=, &SubExprOffset]() -> bool {6337SubExprOffset =6338this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);6339if (!this->visit(SubExpr))6340return false;6341return this->emitSetLocal(PT_Ptr, SubExprOffset, E);6342};63436344PrimType ElemT = classifyComplexElementType(SubExpr->getType());6345auto getElem = [=](unsigned Offset, unsigned Index) -> bool {6346if (!this->emitGetLocal(PT_Ptr, Offset, E))6347return false;6348return this->emitArrayElemPop(ElemT, Index, E);6349};63506351switch (E->getOpcode()) {6352case UO_Minus:6353if (!prepareResult())6354return false;6355if (!createTemp())6356return false;6357for (unsigned I = 0; I != 2; ++I) {6358if (!getElem(SubExprOffset, I))6359return false;6360if (!this->emitNeg(ElemT, E))6361return false;6362if (!this->emitInitElem(ElemT, I, E))6363return false;6364}6365break;63666367case UO_Plus: // +x6368case UO_AddrOf: // &x6369case UO_Deref: // *x6370return this->delegate(SubExpr);63716372case UO_LNot:6373if (!this->visit(SubExpr))6374return false;6375if (!this->emitComplexBoolCast(SubExpr))6376return false;6377if (!this->emitInv(E))6378return false;6379if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)6380return this->emitCast(PT_Bool, ET, E);6381return true;63826383case UO_Real:6384return this->emitComplexReal(SubExpr);63856386case UO_Imag:6387if (!this->visit(SubExpr))6388return false;63896390if (SubExpr->isLValue()) {6391if (!this->emitConstUint8(1, E))6392return false;6393return this->emitArrayElemPtrPopUint8(E);6394}63956396// Since our _Complex implementation does not map to a primitive type,6397// we sometimes have to do the lvalue-to-rvalue conversion here manually.6398return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);63996400case UO_Not: // ~x6401if (!this->visit(SubExpr))6402return false;6403// Negate the imaginary component.6404if (!this->emitArrayElem(ElemT, 1, E))6405return false;6406if (!this->emitNeg(ElemT, E))6407return false;6408if (!this->emitInitElem(ElemT, 1, E))6409return false;6410return DiscardResult ? this->emitPopPtr(E) : true;64116412case UO_Extension:6413return this->delegate(SubExpr);64146415default:6416return this->emitInvalid(E);6417}64186419return true;6420}64216422template <class Emitter>6423bool Compiler<Emitter>::VisitVectorUnaryOperator(const UnaryOperator *E) {6424const Expr *SubExpr = E->getSubExpr();6425assert(SubExpr->getType()->isVectorType());64266427if (DiscardResult)6428return this->discard(SubExpr);64296430auto UnaryOp = E->getOpcode();6431if (UnaryOp == UO_Extension)6432return this->delegate(SubExpr);64336434if (UnaryOp != UO_Plus && UnaryOp != UO_Minus && UnaryOp != UO_LNot &&6435UnaryOp != UO_Not && UnaryOp != UO_AddrOf)6436return this->emitInvalid(E);64376438// Nothing to do here.6439if (UnaryOp == UO_Plus || UnaryOp == UO_AddrOf)6440return this->delegate(SubExpr);64416442if (!Initializing) {6443std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);6444if (!LocalIndex)6445return false;6446if (!this->emitGetPtrLocal(*LocalIndex, E))6447return false;6448}64496450// The offset of the temporary, if we created one.6451unsigned SubExprOffset =6452this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);6453if (!this->visit(SubExpr))6454return false;6455if (!this->emitSetLocal(PT_Ptr, SubExprOffset, E))6456return false;64576458const auto *VecTy = SubExpr->getType()->getAs<VectorType>();6459PrimType ElemT = classifyVectorElementType(SubExpr->getType());6460auto getElem = [=](unsigned Offset, unsigned Index) -> bool {6461if (!this->emitGetLocal(PT_Ptr, Offset, E))6462return false;6463return this->emitArrayElemPop(ElemT, Index, E);6464};64656466switch (UnaryOp) {6467case UO_Minus:6468for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {6469if (!getElem(SubExprOffset, I))6470return false;6471if (!this->emitNeg(ElemT, E))6472return false;6473if (!this->emitInitElem(ElemT, I, E))6474return false;6475}6476break;6477case UO_LNot: { // !x6478// In C++, the logic operators !, &&, || are available for vectors. !v is6479// equivalent to v == 0.6480//6481// The result of the comparison is a vector of the same width and number of6482// elements as the comparison operands with a signed integral element type.6483//6484// https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html6485QualType ResultVecTy = E->getType();6486PrimType ResultVecElemT =6487classifyPrim(ResultVecTy->getAs<VectorType>()->getElementType());6488for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {6489if (!getElem(SubExprOffset, I))6490return false;6491// operator ! on vectors returns -1 for 'truth', so negate it.6492if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))6493return false;6494if (!this->emitInv(E))6495return false;6496if (!this->emitPrimCast(PT_Bool, ElemT, VecTy->getElementType(), E))6497return false;6498if (!this->emitNeg(ElemT, E))6499return false;6500if (ElemT != ResultVecElemT &&6501!this->emitPrimCast(ElemT, ResultVecElemT, ResultVecTy, E))6502return false;6503if (!this->emitInitElem(ResultVecElemT, I, E))6504return false;6505}6506break;6507}6508case UO_Not: // ~x6509for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {6510if (!getElem(SubExprOffset, I))6511return false;6512if (ElemT == PT_Bool) {6513if (!this->emitInv(E))6514return false;6515} else {6516if (!this->emitComp(ElemT, E))6517return false;6518}6519if (!this->emitInitElem(ElemT, I, E))6520return false;6521}6522break;6523default:6524llvm_unreachable("Unsupported unary operators should be handled up front");6525}6526return true;6527}65286529template <class Emitter>6530bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {6531if (DiscardResult)6532return true;65336534if (const auto *ECD = dyn_cast<EnumConstantDecl>(D))6535return this->emitConst(ECD->getInitVal(), E);6536if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {6537const Function *F = getFunction(FuncDecl);6538return F && this->emitGetFnPtr(F, E);6539}6540if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) {6541if (std::optional<unsigned> Index = P.getOrCreateGlobal(D)) {6542if (!this->emitGetPtrGlobal(*Index, E))6543return false;6544if (std::optional<PrimType> T = classify(E->getType())) {6545if (!this->visitAPValue(TPOD->getValue(), *T, E))6546return false;6547return this->emitInitGlobal(*T, *Index, E);6548}6549return this->visitAPValueInitializer(TPOD->getValue(), E,6550TPOD->getType());6551}6552return false;6553}65546555// References are implemented via pointers, so when we see a DeclRefExpr6556// pointing to a reference, we need to get its value directly (i.e. the6557// pointer to the actual value) instead of a pointer to the pointer to the6558// value.6559bool IsReference = D->getType()->isReferenceType();65606561// Local variables.6562if (auto It = Locals.find(D); It != Locals.end()) {6563const unsigned Offset = It->second.Offset;6564if (IsReference)6565return this->emitGetLocal(classifyPrim(E), Offset, E);6566return this->emitGetPtrLocal(Offset, E);6567}6568// Global variables.6569if (auto GlobalIndex = P.getGlobal(D)) {6570if (IsReference) {6571if (!Ctx.getLangOpts().CPlusPlus11)6572return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);6573return this->emitGetGlobalUnchecked(classifyPrim(E), *GlobalIndex, E);6574}65756576return this->emitGetPtrGlobal(*GlobalIndex, E);6577}6578// Function parameters.6579if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {6580if (auto It = this->Params.find(PVD); It != this->Params.end()) {6581if (IsReference || !It->second.IsPtr)6582return this->emitGetParam(classifyPrim(E), It->second.Offset, E);65836584return this->emitGetPtrParam(It->second.Offset, E);6585}6586}65876588// In case we need to re-visit a declaration.6589auto revisit = [&](const VarDecl *VD) -> bool {6590if (!this->emitPushCC(VD->hasConstantInitialization(), E))6591return false;6592auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true);65936594if (!this->emitPopCC(E))6595return false;65966597if (VarState.notCreated())6598return true;6599if (!VarState)6600return false;6601// Retry.6602return this->visitDeclRef(D, E);6603};66046605// Lambda captures.6606if (auto It = this->LambdaCaptures.find(D);6607It != this->LambdaCaptures.end()) {6608auto [Offset, IsPtr] = It->second;66096610if (IsPtr)6611return this->emitGetThisFieldPtr(Offset, E);6612return this->emitGetPtrThisField(Offset, E);6613}66146615if (const auto *DRE = dyn_cast<DeclRefExpr>(E);6616DRE && DRE->refersToEnclosingVariableOrCapture()) {6617if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture())6618return revisit(VD);6619}66206621if (const auto *BD = dyn_cast<BindingDecl>(D))6622return this->visit(BD->getBinding());66236624// Avoid infinite recursion.6625if (D == InitializingDecl)6626return this->emitDummyPtr(D, E);66276628// Try to lazily visit (or emit dummy pointers for) declarations6629// we haven't seen yet.6630// For C.6631if (!Ctx.getLangOpts().CPlusPlus) {6632if (const auto *VD = dyn_cast<VarDecl>(D);6633VD && VD->getAnyInitializer() &&6634VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak())6635return revisit(VD);6636return this->emitDummyPtr(D, E);6637}66386639// ... and C++.6640const auto *VD = dyn_cast<VarDecl>(D);6641if (!VD)6642return this->emitDummyPtr(D, E);66436644const auto typeShouldBeVisited = [&](QualType T) -> bool {6645if (T.isConstant(Ctx.getASTContext()))6646return true;6647return T->isReferenceType();6648};66496650if ((VD->hasGlobalStorage() || VD->isStaticDataMember()) &&6651typeShouldBeVisited(VD->getType())) {6652if (const Expr *Init = VD->getAnyInitializer();6653Init && !Init->isValueDependent()) {6654// Whether or not the evaluation is successul doesn't really matter6655// here -- we will create a global variable in any case, and that6656// will have the state of initializer evaluation attached.6657APValue V;6658SmallVector<PartialDiagnosticAt> Notes;6659(void)Init->EvaluateAsInitializer(V, Ctx.getASTContext(), VD, Notes,6660true);6661return this->visitDeclRef(D, E);6662}6663return revisit(VD);6664}66656666// FIXME: The evaluateValue() check here is a little ridiculous, since6667// it will ultimately call into Context::evaluateAsInitializer(). In6668// other words, we're evaluating the initializer, just to know if we can6669// evaluate the initializer.6670if (VD->isLocalVarDecl() && typeShouldBeVisited(VD->getType()) &&6671VD->getInit() && !VD->getInit()->isValueDependent()) {66726673if (VD->evaluateValue())6674return revisit(VD);66756676if (!IsReference)6677return this->emitDummyPtr(D, E);66786679return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),6680/*InitializerFailed=*/true, E);6681}66826683return this->emitDummyPtr(D, E);6684}66856686template <class Emitter>6687bool Compiler<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {6688const auto *D = E->getDecl();6689return this->visitDeclRef(D, E);6690}66916692template <class Emitter> void Compiler<Emitter>::emitCleanup() {6693for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())6694C->emitDestruction();6695}66966697template <class Emitter>6698unsigned Compiler<Emitter>::collectBaseOffset(const QualType BaseType,6699const QualType DerivedType) {6700const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {6701if (const auto *R = Ty->getPointeeCXXRecordDecl())6702return R;6703return Ty->getAsCXXRecordDecl();6704};6705const CXXRecordDecl *BaseDecl = extractRecordDecl(BaseType);6706const CXXRecordDecl *DerivedDecl = extractRecordDecl(DerivedType);67076708return Ctx.collectBaseOffset(BaseDecl, DerivedDecl);6709}67106711/// Emit casts from a PrimType to another PrimType.6712template <class Emitter>6713bool Compiler<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,6714QualType ToQT, const Expr *E) {67156716if (FromT == PT_Float) {6717// Floating to floating.6718if (ToT == PT_Float) {6719const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);6720return this->emitCastFP(ToSem, getRoundingMode(E), E);6721}67226723if (ToT == PT_IntAP)6724return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(ToQT),6725getFPOptions(E), E);6726if (ToT == PT_IntAPS)6727return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(ToQT),6728getFPOptions(E), E);67296730// Float to integral.6731if (isIntegralType(ToT) || ToT == PT_Bool)6732return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);6733}67346735if (isIntegralType(FromT) || FromT == PT_Bool) {6736if (ToT == PT_IntAP)6737return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E);6738if (ToT == PT_IntAPS)6739return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E);67406741// Integral to integral.6742if (isIntegralType(ToT) || ToT == PT_Bool)6743return FromT != ToT ? this->emitCast(FromT, ToT, E) : true;67446745if (ToT == PT_Float) {6746// Integral to floating.6747const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);6748return this->emitCastIntegralFloating(FromT, ToSem, getFPOptions(E), E);6749}6750}67516752return false;6753}67546755/// Emits __real(SubExpr)6756template <class Emitter>6757bool Compiler<Emitter>::emitComplexReal(const Expr *SubExpr) {6758assert(SubExpr->getType()->isAnyComplexType());67596760if (DiscardResult)6761return this->discard(SubExpr);67626763if (!this->visit(SubExpr))6764return false;6765if (SubExpr->isLValue()) {6766if (!this->emitConstUint8(0, SubExpr))6767return false;6768return this->emitArrayElemPtrPopUint8(SubExpr);6769}67706771// Rvalue, load the actual element.6772return this->emitArrayElemPop(classifyComplexElementType(SubExpr->getType()),67730, SubExpr);6774}67756776template <class Emitter>6777bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {6778assert(!DiscardResult);6779PrimType ElemT = classifyComplexElementType(E->getType());6780// We emit the expression (__real(E) != 0 || __imag(E) != 0)6781// for us, that means (bool)E[0] || (bool)E[1]6782if (!this->emitArrayElem(ElemT, 0, E))6783return false;6784if (ElemT == PT_Float) {6785if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))6786return false;6787} else {6788if (!this->emitCast(ElemT, PT_Bool, E))6789return false;6790}67916792// We now have the bool value of E[0] on the stack.6793LabelTy LabelTrue = this->getLabel();6794if (!this->jumpTrue(LabelTrue))6795return false;67966797if (!this->emitArrayElemPop(ElemT, 1, E))6798return false;6799if (ElemT == PT_Float) {6800if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))6801return false;6802} else {6803if (!this->emitCast(ElemT, PT_Bool, E))6804return false;6805}6806// Leave the boolean value of E[1] on the stack.6807LabelTy EndLabel = this->getLabel();6808this->jump(EndLabel);68096810this->emitLabel(LabelTrue);6811if (!this->emitPopPtr(E))6812return false;6813if (!this->emitConstBool(true, E))6814return false;68156816this->fallthrough(EndLabel);6817this->emitLabel(EndLabel);68186819return true;6820}68216822template <class Emitter>6823bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,6824const BinaryOperator *E) {6825assert(E->isComparisonOp());6826assert(!Initializing);6827assert(!DiscardResult);68286829PrimType ElemT;6830bool LHSIsComplex;6831unsigned LHSOffset;6832if (LHS->getType()->isAnyComplexType()) {6833LHSIsComplex = true;6834ElemT = classifyComplexElementType(LHS->getType());6835LHSOffset = allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);6836if (!this->visit(LHS))6837return false;6838if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))6839return false;6840} else {6841LHSIsComplex = false;6842PrimType LHST = classifyPrim(LHS->getType());6843LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);6844if (!this->visit(LHS))6845return false;6846if (!this->emitSetLocal(LHST, LHSOffset, E))6847return false;6848}68496850bool RHSIsComplex;6851unsigned RHSOffset;6852if (RHS->getType()->isAnyComplexType()) {6853RHSIsComplex = true;6854ElemT = classifyComplexElementType(RHS->getType());6855RHSOffset = allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);6856if (!this->visit(RHS))6857return false;6858if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))6859return false;6860} else {6861RHSIsComplex = false;6862PrimType RHST = classifyPrim(RHS->getType());6863RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);6864if (!this->visit(RHS))6865return false;6866if (!this->emitSetLocal(RHST, RHSOffset, E))6867return false;6868}68696870auto getElem = [&](unsigned LocalOffset, unsigned Index,6871bool IsComplex) -> bool {6872if (IsComplex) {6873if (!this->emitGetLocal(PT_Ptr, LocalOffset, E))6874return false;6875return this->emitArrayElemPop(ElemT, Index, E);6876}6877return this->emitGetLocal(ElemT, LocalOffset, E);6878};68796880for (unsigned I = 0; I != 2; ++I) {6881// Get both values.6882if (!getElem(LHSOffset, I, LHSIsComplex))6883return false;6884if (!getElem(RHSOffset, I, RHSIsComplex))6885return false;6886// And compare them.6887if (!this->emitEQ(ElemT, E))6888return false;68896890if (!this->emitCastBoolUint8(E))6891return false;6892}68936894// We now have two bool values on the stack. Compare those.6895if (!this->emitAddUint8(E))6896return false;6897if (!this->emitConstUint8(2, E))6898return false;68996900if (E->getOpcode() == BO_EQ) {6901if (!this->emitEQUint8(E))6902return false;6903} else if (E->getOpcode() == BO_NE) {6904if (!this->emitNEUint8(E))6905return false;6906} else6907return false;69086909// In C, this returns an int.6910if (PrimType ResT = classifyPrim(E->getType()); ResT != PT_Bool)6911return this->emitCast(PT_Bool, ResT, E);6912return true;6913}69146915/// When calling this, we have a pointer of the local-to-destroy6916/// on the stack.6917/// Emit destruction of record types (or arrays of record types).6918template <class Emitter>6919bool Compiler<Emitter>::emitRecordDestruction(const Record *R, SourceInfo Loc) {6920assert(R);6921assert(!R->isAnonymousUnion());6922const CXXDestructorDecl *Dtor = R->getDestructor();6923if (!Dtor || Dtor->isTrivial())6924return true;69256926assert(Dtor);6927const Function *DtorFunc = getFunction(Dtor);6928if (!DtorFunc)6929return false;6930assert(DtorFunc->hasThisPointer());6931assert(DtorFunc->getNumParams() == 1);6932if (!this->emitDupPtr(Loc))6933return false;6934return this->emitCall(DtorFunc, 0, Loc);6935}6936/// When calling this, we have a pointer of the local-to-destroy6937/// on the stack.6938/// Emit destruction of record types (or arrays of record types).6939template <class Emitter>6940bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,6941SourceInfo Loc) {6942assert(Desc);6943assert(!Desc->isPrimitive());6944assert(!Desc->isPrimitiveArray());69456946// Can happen if the decl is invalid.6947if (Desc->isDummy())6948return true;69496950// Arrays.6951if (Desc->isArray()) {6952const Descriptor *ElemDesc = Desc->ElemDesc;6953assert(ElemDesc);69546955// Don't need to do anything for these.6956if (ElemDesc->isPrimitiveArray())6957return true;69586959// If this is an array of record types, check if we need6960// to call the element destructors at all. If not, try6961// to save the work.6962if (const Record *ElemRecord = ElemDesc->ElemRecord) {6963if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();6964!Dtor || Dtor->isTrivial())6965return true;6966}69676968if (unsigned N = Desc->getNumElems()) {6969for (ssize_t I = N - 1; I >= 0; --I) {6970if (!this->emitConstUint64(I, Loc))6971return false;6972if (!this->emitArrayElemPtrUint64(Loc))6973return false;6974if (!this->emitDestruction(ElemDesc, Loc))6975return false;6976if (!this->emitPopPtr(Loc))6977return false;6978}6979}6980return true;6981}69826983assert(Desc->ElemRecord);6984if (Desc->ElemRecord->isAnonymousUnion())6985return true;69866987return this->emitRecordDestruction(Desc->ElemRecord, Loc);6988}69896990/// Create a dummy pointer for the given decl (or expr) and6991/// push a pointer to it on the stack.6992template <class Emitter>6993bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {6994assert(!DiscardResult && "Should've been checked before");69956996unsigned DummyID = P.getOrCreateDummy(D);69976998if (!this->emitGetPtrGlobal(DummyID, E))6999return false;7000if (E->getType()->isVoidType())7001return true;70027003// Convert the dummy pointer to another pointer type if we have to.7004if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {7005if (isPtrType(PT))7006return this->emitDecayPtr(PT_Ptr, PT, E);7007return false;7008}7009return true;7010}70117012template <class Emitter>7013bool Compiler<Emitter>::emitFloat(const APFloat &F, const Expr *E) {7014assert(!DiscardResult && "Should've been checked before");70157016if (Floating::singleWord(F.getSemantics()))7017return this->emitConstFloat(Floating(F), E);70187019APInt I = F.bitcastToAPInt();7020return this->emitConstFloat(7021Floating(const_cast<uint64_t *>(I.getRawData()),7022llvm::APFloatBase::SemanticsToEnum(F.getSemantics())),7023E);7024}70257026// This function is constexpr if and only if To, From, and the types of7027// all subobjects of To and From are types T such that...7028// (3.1) - is_union_v<T> is false;7029// (3.2) - is_pointer_v<T> is false;7030// (3.3) - is_member_pointer_v<T> is false;7031// (3.4) - is_volatile_v<T> is false; and7032// (3.5) - T has no non-static data members of reference type7033template <class Emitter>7034bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {7035const Expr *SubExpr = E->getSubExpr();7036QualType FromType = SubExpr->getType();7037QualType ToType = E->getType();7038std::optional<PrimType> ToT = classify(ToType);70397040assert(!ToType->isReferenceType());70417042// Prepare storage for the result in case we discard.7043if (DiscardResult && !Initializing && !ToT) {7044std::optional<unsigned> LocalIndex = allocateLocal(E);7045if (!LocalIndex)7046return false;7047if (!this->emitGetPtrLocal(*LocalIndex, E))7048return false;7049}70507051// Get a pointer to the value-to-cast on the stack.7052// For CK_LValueToRValueBitCast, this is always an lvalue and7053// we later assume it to be one (i.e. a PT_Ptr). However,7054// we call this function for other utility methods where7055// a bitcast might be useful, so convert it to a PT_Ptr in that case.7056if (SubExpr->isGLValue() || FromType->isVectorType()) {7057if (!this->visit(SubExpr))7058return false;7059} else if (std::optional<PrimType> FromT = classify(SubExpr)) {7060unsigned TempOffset =7061allocateLocalPrimitive(SubExpr, *FromT, /*IsConst=*/true);7062if (!this->visit(SubExpr))7063return false;7064if (!this->emitSetLocal(*FromT, TempOffset, E))7065return false;7066if (!this->emitGetPtrLocal(TempOffset, E))7067return false;7068} else {7069return false;7070}70717072if (!ToT) {7073if (!this->emitBitCast(E))7074return false;7075return DiscardResult ? this->emitPopPtr(E) : true;7076}7077assert(ToT);70787079const llvm::fltSemantics *TargetSemantics = nullptr;7080if (ToT == PT_Float)7081TargetSemantics = &Ctx.getFloatSemantics(ToType);70827083// Conversion to a primitive type. FromType can be another7084// primitive type, or a record/array.7085bool ToTypeIsUChar = (ToType->isSpecificBuiltinType(BuiltinType::UChar) ||7086ToType->isSpecificBuiltinType(BuiltinType::Char_U));7087uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);70887089if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->isStdByteType(),7090ResultBitWidth, TargetSemantics, E))7091return false;70927093if (DiscardResult)7094return this->emitPop(*ToT, E);70957096return true;7097}70987099namespace clang {7100namespace interp {71017102template class Compiler<ByteCodeEmitter>;7103template class Compiler<EvalEmitter>;71047105} // namespace interp7106} // namespace clang710771087109