7595 lines · cpp
1//===--- Compiler.cpp - Code generator for expressions ---*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Compiler.h"10#include "ByteCodeEmitter.h"11#include "Context.h"12#include "FixedPoint.h"13#include "Floating.h"14#include "Function.h"15#include "InterpShared.h"16#include "PrimType.h"17#include "Program.h"18#include "clang/AST/Attr.h"19#include "llvm/Support/SaveAndRestore.h"20 21using namespace clang;22using namespace clang::interp;23 24using APSInt = llvm::APSInt;25 26namespace clang {27namespace interp {28 29static std::optional<bool> getBoolValue(const Expr *E) {30 if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);31 CE && CE->hasAPValueResult() &&32 CE->getResultAPValueKind() == APValue::ValueKind::Int) {33 return CE->getResultAsAPSInt().getBoolValue();34 }35 36 return std::nullopt;37}38 39/// Scope used to handle temporaries in toplevel variable declarations.40template <class Emitter> class DeclScope final : public LocalScope<Emitter> {41public:42 DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)43 : LocalScope<Emitter>(Ctx, VD), Scope(Ctx->P),44 OldInitializingDecl(Ctx->InitializingDecl) {45 Ctx->InitializingDecl = VD;46 Ctx->InitStack.push_back(InitLink::Decl(VD));47 }48 49 ~DeclScope() {50 this->Ctx->InitializingDecl = OldInitializingDecl;51 this->Ctx->InitStack.pop_back();52 }53 54private:55 Program::DeclScope Scope;56 const ValueDecl *OldInitializingDecl;57};58 59/// Scope used to handle initialization methods.60template <class Emitter> class OptionScope final {61public:62 /// Root constructor, compiling or discarding primitives.63 OptionScope(Compiler<Emitter> *Ctx, bool NewDiscardResult,64 bool NewInitializing, bool NewToLValue)65 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),66 OldInitializing(Ctx->Initializing), OldToLValue(Ctx->ToLValue) {67 Ctx->DiscardResult = NewDiscardResult;68 Ctx->Initializing = NewInitializing;69 Ctx->ToLValue = NewToLValue;70 }71 72 ~OptionScope() {73 Ctx->DiscardResult = OldDiscardResult;74 Ctx->Initializing = OldInitializing;75 Ctx->ToLValue = OldToLValue;76 }77 78private:79 /// Parent context.80 Compiler<Emitter> *Ctx;81 /// Old discard flag to restore.82 bool OldDiscardResult;83 bool OldInitializing;84 bool OldToLValue;85};86 87template <class Emitter>88bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {89 switch (Kind) {90 case K_This:91 return Ctx->emitThis(E);92 case K_Field:93 // We're assuming there's a base pointer on the stack already.94 return Ctx->emitGetPtrFieldPop(Offset, E);95 case K_Temp:96 return Ctx->emitGetPtrLocal(Offset, E);97 case K_Decl:98 return Ctx->visitDeclRef(D, E);99 case K_Elem:100 if (!Ctx->emitConstUint32(Offset, E))101 return false;102 return Ctx->emitArrayElemPtrPopUint32(E);103 case K_RVO:104 return Ctx->emitRVOPtr(E);105 case K_InitList:106 return true;107 default:108 llvm_unreachable("Unhandled InitLink kind");109 }110 return true;111}112 113/// Sets the context for break/continue statements.114template <class Emitter> class LoopScope final {115public:116 using LabelTy = typename Compiler<Emitter>::LabelTy;117 using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;118 using LabelInfo = typename Compiler<Emitter>::LabelInfo;119 120 LoopScope(Compiler<Emitter> *Ctx, const Stmt *Name, LabelTy BreakLabel,121 LabelTy ContinueLabel)122 : Ctx(Ctx) {123#ifndef NDEBUG124 for (const LabelInfo &LI : Ctx->LabelInfoStack)125 assert(LI.Name != Name);126#endif127 128 this->Ctx->LabelInfoStack.emplace_back(Name, BreakLabel, ContinueLabel,129 /*DefaultLabel=*/std::nullopt,130 Ctx->VarScope);131 }132 133 ~LoopScope() { this->Ctx->LabelInfoStack.pop_back(); }134 135private:136 Compiler<Emitter> *Ctx;137};138 139// Sets the context for a switch scope, mapping labels.140template <class Emitter> class SwitchScope final {141public:142 using LabelTy = typename Compiler<Emitter>::LabelTy;143 using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;144 using CaseMap = typename Compiler<Emitter>::CaseMap;145 using LabelInfo = typename Compiler<Emitter>::LabelInfo;146 147 SwitchScope(Compiler<Emitter> *Ctx, const Stmt *Name, CaseMap &&CaseLabels,148 LabelTy BreakLabel, OptLabelTy DefaultLabel)149 : Ctx(Ctx), OldCaseLabels(std::move(this->Ctx->CaseLabels)) {150#ifndef NDEBUG151 for (const LabelInfo &LI : Ctx->LabelInfoStack)152 assert(LI.Name != Name);153#endif154 155 this->Ctx->CaseLabels = std::move(CaseLabels);156 this->Ctx->LabelInfoStack.emplace_back(Name, BreakLabel,157 /*ContinueLabel=*/std::nullopt,158 DefaultLabel, Ctx->VarScope);159 }160 161 ~SwitchScope() {162 this->Ctx->CaseLabels = std::move(OldCaseLabels);163 this->Ctx->LabelInfoStack.pop_back();164 }165 166private:167 Compiler<Emitter> *Ctx;168 CaseMap OldCaseLabels;169};170 171template <class Emitter> class StmtExprScope final {172public:173 StmtExprScope(Compiler<Emitter> *Ctx) : Ctx(Ctx), OldFlag(Ctx->InStmtExpr) {174 Ctx->InStmtExpr = true;175 }176 177 ~StmtExprScope() { Ctx->InStmtExpr = OldFlag; }178 179private:180 Compiler<Emitter> *Ctx;181 bool OldFlag;182};183 184/// When generating code for e.g. implicit field initializers in constructors,185/// we don't have anything to point to in case the initializer causes an error.186/// In that case, we need to disable location tracking for the initializer so187/// we later point to the call range instead.188template <class Emitter> class LocOverrideScope final {189public:190 LocOverrideScope(Compiler<Emitter> *Ctx, SourceInfo NewValue,191 bool Enabled = true)192 : Ctx(Ctx), OldFlag(Ctx->LocOverride), Enabled(Enabled) {193 194 if (Enabled)195 Ctx->LocOverride = NewValue;196 }197 198 ~LocOverrideScope() {199 if (Enabled)200 Ctx->LocOverride = OldFlag;201 }202 203private:204 Compiler<Emitter> *Ctx;205 std::optional<SourceInfo> OldFlag;206 bool Enabled;207};208 209} // namespace interp210} // namespace clang211 212template <class Emitter>213bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {214 const Expr *SubExpr = CE->getSubExpr();215 216 if (DiscardResult)217 return this->delegate(SubExpr);218 219 switch (CE->getCastKind()) {220 case CK_LValueToRValue: {221 if (ToLValue && CE->getType()->isPointerType())222 return this->delegate(SubExpr);223 224 if (SubExpr->getType().isVolatileQualified())225 return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);226 227 OptPrimType SubExprT = classify(SubExpr->getType());228 // Try to load the value directly. This is purely a performance229 // optimization.230 if (SubExprT) {231 if (const auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {232 const ValueDecl *D = DRE->getDecl();233 bool IsReference = D->getType()->isReferenceType();234 235 if (!IsReference) {236 if (Context::shouldBeGloballyIndexed(D)) {237 if (auto GlobalIndex = P.getGlobal(D))238 return this->emitGetGlobal(*SubExprT, *GlobalIndex, CE);239 } else if (auto It = Locals.find(D); It != Locals.end()) {240 return this->emitGetLocal(*SubExprT, It->second.Offset, CE);241 } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {242 if (auto It = this->Params.find(PVD); It != this->Params.end()) {243 return this->emitGetParam(*SubExprT, It->second.Offset, CE);244 }245 }246 }247 }248 }249 250 // Prepare storage for the result.251 if (!Initializing && !SubExprT) {252 UnsignedOrNone LocalIndex = allocateLocal(SubExpr);253 if (!LocalIndex)254 return false;255 if (!this->emitGetPtrLocal(*LocalIndex, CE))256 return false;257 }258 259 if (!this->visit(SubExpr))260 return false;261 262 if (SubExprT)263 return this->emitLoadPop(*SubExprT, CE);264 265 // If the subexpr type is not primitive, we need to perform a copy here.266 // This happens for example in C when dereferencing a pointer of struct267 // type.268 return this->emitMemcpy(CE);269 }270 271 case CK_DerivedToBaseMemberPointer: {272 assert(classifyPrim(CE->getType()) == PT_MemberPtr);273 assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr);274 const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();275 const auto *ToMP = CE->getType()->castAs<MemberPointerType>();276 277 unsigned DerivedOffset =278 Ctx.collectBaseOffset(ToMP->getMostRecentCXXRecordDecl(),279 FromMP->getMostRecentCXXRecordDecl());280 281 if (!this->delegate(SubExpr))282 return false;283 284 return this->emitGetMemberPtrBasePop(DerivedOffset, CE);285 }286 287 case CK_BaseToDerivedMemberPointer: {288 assert(classifyPrim(CE) == PT_MemberPtr);289 assert(classifyPrim(SubExpr) == PT_MemberPtr);290 const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();291 const auto *ToMP = CE->getType()->castAs<MemberPointerType>();292 293 unsigned DerivedOffset =294 Ctx.collectBaseOffset(FromMP->getMostRecentCXXRecordDecl(),295 ToMP->getMostRecentCXXRecordDecl());296 297 if (!this->delegate(SubExpr))298 return false;299 return this->emitGetMemberPtrBasePop(-DerivedOffset, CE);300 }301 302 case CK_UncheckedDerivedToBase:303 case CK_DerivedToBase: {304 if (!this->delegate(SubExpr))305 return false;306 307 const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {308 if (const auto *PT = dyn_cast<PointerType>(Ty))309 return PT->getPointeeType()->getAsCXXRecordDecl();310 return Ty->getAsCXXRecordDecl();311 };312 313 // FIXME: We can express a series of non-virtual casts as a single314 // GetPtrBasePop op.315 QualType CurType = SubExpr->getType();316 for (const CXXBaseSpecifier *B : CE->path()) {317 if (B->isVirtual()) {318 if (!this->emitGetPtrVirtBasePop(extractRecordDecl(B->getType()), CE))319 return false;320 CurType = B->getType();321 } else {322 unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType);323 if (!this->emitGetPtrBasePop(324 DerivedOffset, /*NullOK=*/CE->getType()->isPointerType(), CE))325 return false;326 CurType = B->getType();327 }328 }329 330 return true;331 }332 333 case CK_BaseToDerived: {334 if (!this->delegate(SubExpr))335 return false;336 unsigned DerivedOffset =337 collectBaseOffset(SubExpr->getType(), CE->getType());338 339 const Type *TargetType = CE->getType().getTypePtr();340 if (TargetType->isPointerOrReferenceType())341 TargetType = TargetType->getPointeeType().getTypePtr();342 return this->emitGetPtrDerivedPop(DerivedOffset,343 /*NullOK=*/CE->getType()->isPointerType(),344 TargetType, CE);345 }346 347 case CK_FloatingCast: {348 // HLSL uses CK_FloatingCast to cast between vectors.349 if (!SubExpr->getType()->isFloatingType() ||350 !CE->getType()->isFloatingType())351 return false;352 if (!this->visit(SubExpr))353 return false;354 const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());355 return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE);356 }357 358 case CK_IntegralToFloating: {359 if (!CE->getType()->isRealFloatingType())360 return false;361 if (!this->visit(SubExpr))362 return false;363 const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());364 return this->emitCastIntegralFloating(365 classifyPrim(SubExpr), TargetSemantics, getFPOptions(CE), CE);366 }367 368 case CK_FloatingToBoolean: {369 if (!SubExpr->getType()->isRealFloatingType() ||370 !CE->getType()->isBooleanType())371 return false;372 if (const auto *FL = dyn_cast<FloatingLiteral>(SubExpr))373 return this->emitConstBool(FL->getValue().isNonZero(), CE);374 if (!this->visit(SubExpr))375 return false;376 return this->emitCastFloatingIntegralBool(getFPOptions(CE), CE);377 }378 379 case CK_FloatingToIntegral: {380 if (!CE->getType()->isIntegralOrEnumerationType())381 return false;382 if (!this->visit(SubExpr))383 return false;384 PrimType ToT = classifyPrim(CE);385 if (ToT == PT_IntAP)386 return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()),387 getFPOptions(CE), CE);388 if (ToT == PT_IntAPS)389 return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()),390 getFPOptions(CE), CE);391 392 return this->emitCastFloatingIntegral(ToT, getFPOptions(CE), CE);393 }394 395 case CK_NullToPointer:396 case CK_NullToMemberPointer: {397 if (!this->discard(SubExpr))398 return false;399 const Descriptor *Desc = nullptr;400 const QualType PointeeType = CE->getType()->getPointeeType();401 if (!PointeeType.isNull()) {402 if (OptPrimType T = classify(PointeeType))403 Desc = P.createDescriptor(SubExpr, *T);404 else405 Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(),406 std::nullopt, /*IsConst=*/true);407 }408 409 uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(CE->getType());410 return this->emitNull(classifyPrim(CE->getType()), Val, Desc, CE);411 }412 413 case CK_PointerToIntegral: {414 if (!this->visit(SubExpr))415 return false;416 417 // If SubExpr doesn't result in a pointer, make it one.418 if (PrimType FromT = classifyPrim(SubExpr->getType()); FromT != PT_Ptr) {419 assert(isPtrType(FromT));420 if (!this->emitDecayPtr(FromT, PT_Ptr, CE))421 return false;422 }423 424 PrimType T = classifyPrim(CE->getType());425 if (T == PT_IntAP)426 return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()),427 CE);428 if (T == PT_IntAPS)429 return this->emitCastPointerIntegralAPS(Ctx.getBitWidth(CE->getType()),430 CE);431 return this->emitCastPointerIntegral(T, CE);432 }433 434 case CK_ArrayToPointerDecay: {435 if (!this->visit(SubExpr))436 return false;437 return this->emitArrayDecay(CE);438 }439 440 case CK_IntegralToPointer: {441 QualType IntType = SubExpr->getType();442 assert(IntType->isIntegralOrEnumerationType());443 if (!this->visit(SubExpr))444 return false;445 // FIXME: I think the discard is wrong since the int->ptr cast might cause a446 // diagnostic.447 PrimType T = classifyPrim(IntType);448 QualType PtrType = CE->getType();449 const Descriptor *Desc;450 if (OptPrimType T = classify(PtrType->getPointeeType()))451 Desc = P.createDescriptor(SubExpr, *T);452 else if (PtrType->getPointeeType()->isVoidType())453 Desc = nullptr;454 else455 Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),456 Descriptor::InlineDescMD, /*IsConst=*/true);457 458 if (!this->emitGetIntPtr(T, Desc, CE))459 return false;460 461 PrimType DestPtrT = classifyPrim(PtrType);462 if (DestPtrT == PT_Ptr)463 return true;464 465 // In case we're converting the integer to a non-Pointer.466 return this->emitDecayPtr(PT_Ptr, DestPtrT, CE);467 }468 469 case CK_AtomicToNonAtomic:470 case CK_ConstructorConversion:471 case CK_FunctionToPointerDecay:472 case CK_NonAtomicToAtomic:473 case CK_NoOp:474 case CK_UserDefinedConversion:475 case CK_AddressSpaceConversion:476 case CK_CPointerToObjCPointerCast:477 return this->delegate(SubExpr);478 479 case CK_BitCast: {480 QualType CETy = CE->getType();481 // Reject bitcasts to atomic types.482 if (CETy->isAtomicType()) {483 if (!this->discard(SubExpr))484 return false;485 return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE);486 }487 QualType SubExprTy = SubExpr->getType();488 OptPrimType FromT = classify(SubExprTy);489 // Casts from integer/vector to vector.490 if (CE->getType()->isVectorType())491 return this->emitBuiltinBitCast(CE);492 493 OptPrimType ToT = classify(CE->getType());494 if (!FromT || !ToT)495 return false;496 497 assert(isPtrType(*FromT));498 assert(isPtrType(*ToT));499 bool SrcIsVoidPtr = SubExprTy->isVoidPointerType();500 if (FromT == ToT) {501 if (CE->getType()->isVoidPointerType() &&502 !SubExprTy->isFunctionPointerType()) {503 return this->delegate(SubExpr);504 }505 506 if (!this->visit(SubExpr))507 return false;508 if (!this->emitCheckBitCast(CETy->getPointeeType().getTypePtr(),509 SrcIsVoidPtr, CE))510 return false;511 512 if (CE->getType()->isFunctionPointerType() ||513 SubExprTy->isFunctionPointerType()) {514 return this->emitFnPtrCast(CE);515 }516 if (FromT == PT_Ptr)517 return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE);518 return true;519 }520 521 if (!this->visit(SubExpr))522 return false;523 return this->emitDecayPtr(*FromT, *ToT, CE);524 }525 case CK_IntegralToBoolean:526 case CK_FixedPointToBoolean: {527 // HLSL uses this to cast to one-element vectors.528 OptPrimType FromT = classify(SubExpr->getType());529 if (!FromT)530 return false;531 532 if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))533 return this->emitConst(IL->getValue(), CE);534 if (!this->visit(SubExpr))535 return false;536 return this->emitCast(*FromT, classifyPrim(CE), CE);537 }538 539 case CK_BooleanToSignedIntegral:540 case CK_IntegralCast: {541 OptPrimType FromT = classify(SubExpr->getType());542 OptPrimType ToT = classify(CE->getType());543 if (!FromT || !ToT)544 return false;545 546 // Try to emit a casted known constant value directly.547 if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr)) {548 if (ToT != PT_IntAP && ToT != PT_IntAPS && FromT != PT_IntAP &&549 FromT != PT_IntAPS && !CE->getType()->isEnumeralType())550 return this->emitConst(APSInt(IL->getValue(), !isSignedType(*FromT)),551 CE);552 if (!this->emitConst(IL->getValue(), SubExpr))553 return false;554 } else {555 if (!this->visit(SubExpr))556 return false;557 }558 559 // Possibly diagnose casts to enum types if the target type does not560 // have a fixed size.561 if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {562 const auto *ED = CE->getType()->castAsEnumDecl();563 if (!ED->isFixed()) {564 if (!this->emitCheckEnumValue(*FromT, ED, CE))565 return false;566 }567 }568 569 if (ToT == PT_IntAP) {570 if (!this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE))571 return false;572 } else if (ToT == PT_IntAPS) {573 if (!this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE))574 return false;575 } else {576 if (FromT == ToT)577 return true;578 if (!this->emitCast(*FromT, *ToT, CE))579 return false;580 }581 if (CE->getCastKind() == CK_BooleanToSignedIntegral)582 return this->emitNeg(*ToT, CE);583 return true;584 }585 586 case CK_PointerToBoolean:587 case CK_MemberPointerToBoolean: {588 PrimType PtrT = classifyPrim(SubExpr->getType());589 590 if (!this->visit(SubExpr))591 return false;592 return this->emitIsNonNull(PtrT, CE);593 }594 595 case CK_IntegralComplexToBoolean:596 case CK_FloatingComplexToBoolean: {597 if (!this->visit(SubExpr))598 return false;599 return this->emitComplexBoolCast(SubExpr);600 }601 602 case CK_IntegralComplexToReal:603 case CK_FloatingComplexToReal:604 return this->emitComplexReal(SubExpr);605 606 case CK_IntegralRealToComplex:607 case CK_FloatingRealToComplex: {608 // We're creating a complex value here, so we need to609 // allocate storage for it.610 if (!Initializing) {611 UnsignedOrNone LocalIndex = allocateTemporary(CE);612 if (!LocalIndex)613 return false;614 if (!this->emitGetPtrLocal(*LocalIndex, CE))615 return false;616 }617 618 PrimType T = classifyPrim(SubExpr->getType());619 // Init the complex value to {SubExpr, 0}.620 if (!this->visitArrayElemInit(0, SubExpr, T))621 return false;622 // Zero-init the second element.623 if (!this->visitZeroInitializer(T, SubExpr->getType(), SubExpr))624 return false;625 return this->emitInitElem(T, 1, SubExpr);626 }627 628 case CK_IntegralComplexCast:629 case CK_FloatingComplexCast:630 case CK_IntegralComplexToFloatingComplex:631 case CK_FloatingComplexToIntegralComplex: {632 assert(CE->getType()->isAnyComplexType());633 assert(SubExpr->getType()->isAnyComplexType());634 if (!Initializing) {635 UnsignedOrNone LocalIndex = allocateLocal(CE);636 if (!LocalIndex)637 return false;638 if (!this->emitGetPtrLocal(*LocalIndex, CE))639 return false;640 }641 642 // Location for the SubExpr.643 // Since SubExpr is of complex type, visiting it results in a pointer644 // anyway, so we just create a temporary pointer variable.645 unsigned SubExprOffset =646 allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);647 if (!this->visit(SubExpr))648 return false;649 if (!this->emitSetLocal(PT_Ptr, SubExprOffset, CE))650 return false;651 652 PrimType SourceElemT = classifyComplexElementType(SubExpr->getType());653 QualType DestElemType =654 CE->getType()->getAs<ComplexType>()->getElementType();655 PrimType DestElemT = classifyPrim(DestElemType);656 // Cast both elements individually.657 for (unsigned I = 0; I != 2; ++I) {658 if (!this->emitGetLocal(PT_Ptr, SubExprOffset, CE))659 return false;660 if (!this->emitArrayElemPop(SourceElemT, I, CE))661 return false;662 663 // Do the cast.664 if (!this->emitPrimCast(SourceElemT, DestElemT, DestElemType, CE))665 return false;666 667 // Save the value.668 if (!this->emitInitElem(DestElemT, I, CE))669 return false;670 }671 return true;672 }673 674 case CK_VectorSplat: {675 assert(!canClassify(CE->getType()));676 assert(canClassify(SubExpr->getType()));677 assert(CE->getType()->isVectorType());678 679 if (!Initializing) {680 UnsignedOrNone LocalIndex = allocateLocal(CE);681 if (!LocalIndex)682 return false;683 if (!this->emitGetPtrLocal(*LocalIndex, CE))684 return false;685 }686 687 const auto *VT = CE->getType()->getAs<VectorType>();688 PrimType ElemT = classifyPrim(SubExpr->getType());689 unsigned ElemOffset =690 allocateLocalPrimitive(SubExpr, ElemT, /*IsConst=*/true);691 692 // Prepare a local variable for the scalar value.693 if (!this->visit(SubExpr))694 return false;695 if (classifyPrim(SubExpr) == PT_Ptr && !this->emitLoadPop(ElemT, CE))696 return false;697 698 if (!this->emitSetLocal(ElemT, ElemOffset, CE))699 return false;700 701 for (unsigned I = 0; I != VT->getNumElements(); ++I) {702 if (!this->emitGetLocal(ElemT, ElemOffset, CE))703 return false;704 if (!this->emitInitElem(ElemT, I, CE))705 return false;706 }707 708 return true;709 }710 711 case CK_HLSLVectorTruncation: {712 assert(SubExpr->getType()->isVectorType());713 if (OptPrimType ResultT = classify(CE)) {714 assert(!DiscardResult);715 // Result must be either a float or integer. Take the first element.716 if (!this->visit(SubExpr))717 return false;718 return this->emitArrayElemPop(*ResultT, 0, CE);719 }720 // Otherwise, this truncates from one vector type to another.721 assert(CE->getType()->isVectorType());722 723 if (!Initializing) {724 UnsignedOrNone LocalIndex = allocateTemporary(CE);725 if (!LocalIndex)726 return false;727 if (!this->emitGetPtrLocal(*LocalIndex, CE))728 return false;729 }730 unsigned ToSize = CE->getType()->getAs<VectorType>()->getNumElements();731 assert(SubExpr->getType()->getAs<VectorType>()->getNumElements() > ToSize);732 if (!this->visit(SubExpr))733 return false;734 return this->emitCopyArray(classifyVectorElementType(CE->getType()), 0, 0,735 ToSize, CE);736 };737 738 case CK_IntegralToFixedPoint: {739 if (!this->visit(SubExpr))740 return false;741 742 auto Sem =743 Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();744 return this->emitCastIntegralFixedPoint(classifyPrim(SubExpr->getType()),745 Sem, CE);746 }747 case CK_FloatingToFixedPoint: {748 if (!this->visit(SubExpr))749 return false;750 751 auto Sem =752 Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();753 return this->emitCastFloatingFixedPoint(Sem, CE);754 }755 case CK_FixedPointToFloating: {756 if (!this->visit(SubExpr))757 return false;758 const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());759 return this->emitCastFixedPointFloating(TargetSemantics, CE);760 }761 case CK_FixedPointToIntegral: {762 if (!this->visit(SubExpr))763 return false;764 return this->emitCastFixedPointIntegral(classifyPrim(CE->getType()), CE);765 }766 case CK_FixedPointCast: {767 if (!this->visit(SubExpr))768 return false;769 auto Sem =770 Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();771 return this->emitCastFixedPoint(Sem, CE);772 }773 774 case CK_ToVoid:775 return discard(SubExpr);776 777 case CK_Dynamic:778 // This initially goes through VisitCXXDynamicCastExpr, where we emit779 // a diagnostic if appropriate.780 return this->delegate(SubExpr);781 782 default:783 return this->emitInvalid(CE);784 }785 llvm_unreachable("Unhandled clang::CastKind enum");786}787 788template <class Emitter>789bool Compiler<Emitter>::VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E) {790 return this->emitBuiltinBitCast(E);791}792 793template <class Emitter>794bool Compiler<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {795 if (DiscardResult)796 return true;797 798 return this->emitConst(LE->getValue(), LE);799}800 801template <class Emitter>802bool Compiler<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {803 if (DiscardResult)804 return true;805 806 APFloat F = E->getValue();807 return this->emitFloat(F, E);808}809 810template <class Emitter>811bool Compiler<Emitter>::VisitImaginaryLiteral(const ImaginaryLiteral *E) {812 assert(E->getType()->isAnyComplexType());813 if (DiscardResult)814 return true;815 816 if (!Initializing) {817 UnsignedOrNone LocalIndex = allocateTemporary(E);818 if (!LocalIndex)819 return false;820 if (!this->emitGetPtrLocal(*LocalIndex, E))821 return false;822 }823 824 const Expr *SubExpr = E->getSubExpr();825 PrimType SubExprT = classifyPrim(SubExpr->getType());826 827 if (!this->visitZeroInitializer(SubExprT, SubExpr->getType(), SubExpr))828 return false;829 if (!this->emitInitElem(SubExprT, 0, SubExpr))830 return false;831 return this->visitArrayElemInit(1, SubExpr, SubExprT);832}833 834template <class Emitter>835bool Compiler<Emitter>::VisitFixedPointLiteral(const FixedPointLiteral *E) {836 assert(E->getType()->isFixedPointType());837 assert(classifyPrim(E) == PT_FixedPoint);838 839 if (DiscardResult)840 return true;841 842 auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());843 APInt Value = E->getValue();844 return this->emitConstFixedPoint(FixedPoint(Value, Sem), E);845}846 847template <class Emitter>848bool Compiler<Emitter>::VisitParenExpr(const ParenExpr *E) {849 return this->delegate(E->getSubExpr());850}851 852template <class Emitter>853bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {854 // Need short-circuiting for these.855 if (BO->isLogicalOp() && !BO->getType()->isVectorType())856 return this->VisitLogicalBinOp(BO);857 858 const Expr *LHS = BO->getLHS();859 const Expr *RHS = BO->getRHS();860 861 // Handle comma operators. Just discard the LHS862 // and delegate to RHS.863 if (BO->isCommaOp()) {864 if (!this->discard(LHS))865 return false;866 if (RHS->getType()->isVoidType())867 return this->discard(RHS);868 869 return this->delegate(RHS);870 }871 872 if (BO->getType()->isAnyComplexType())873 return this->VisitComplexBinOp(BO);874 if (BO->getType()->isVectorType())875 return this->VisitVectorBinOp(BO);876 if ((LHS->getType()->isAnyComplexType() ||877 RHS->getType()->isAnyComplexType()) &&878 BO->isComparisonOp())879 return this->emitComplexComparison(LHS, RHS, BO);880 if (LHS->getType()->isFixedPointType() || RHS->getType()->isFixedPointType())881 return this->VisitFixedPointBinOp(BO);882 883 if (BO->isPtrMemOp()) {884 if (!this->visit(LHS))885 return false;886 887 if (!this->visit(RHS))888 return false;889 890 if (!this->emitToMemberPtr(BO))891 return false;892 893 if (classifyPrim(BO) == PT_MemberPtr)894 return true;895 896 if (!this->emitCastMemberPtrPtr(BO))897 return false;898 return DiscardResult ? this->emitPopPtr(BO) : true;899 }900 901 // Typecheck the args.902 OptPrimType LT = classify(LHS);903 OptPrimType RT = classify(RHS);904 OptPrimType T = classify(BO->getType());905 906 // Special case for C++'s three-way/spaceship operator <=>, which907 // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't908 // have a PrimType).909 if (!T && BO->getOpcode() == BO_Cmp) {910 if (DiscardResult)911 return true;912 const ComparisonCategoryInfo *CmpInfo =913 Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());914 assert(CmpInfo);915 916 // We need a temporary variable holding our return value.917 if (!Initializing) {918 UnsignedOrNone ResultIndex = this->allocateLocal(BO);919 if (!this->emitGetPtrLocal(*ResultIndex, BO))920 return false;921 }922 923 if (!visit(LHS) || !visit(RHS))924 return false;925 926 return this->emitCMP3(*LT, CmpInfo, BO);927 }928 929 if (!LT || !RT || !T)930 return false;931 932 // Pointer arithmetic special case.933 if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {934 if (isPtrType(*T) || (isPtrType(*LT) && isPtrType(*RT)))935 return this->VisitPointerArithBinOp(BO);936 }937 938 if (BO->getOpcode() == BO_Assign)939 return this->visitAssignment(LHS, RHS, BO);940 941 if (!visit(LHS) || !visit(RHS))942 return false;943 944 // For languages such as C, cast the result of one945 // of our comparision opcodes to T (which is usually int).946 auto MaybeCastToBool = [this, T, BO](bool Result) {947 if (!Result)948 return false;949 if (DiscardResult)950 return this->emitPopBool(BO);951 if (T != PT_Bool)952 return this->emitCast(PT_Bool, *T, BO);953 return true;954 };955 956 auto Discard = [this, T, BO](bool Result) {957 if (!Result)958 return false;959 return DiscardResult ? this->emitPop(*T, BO) : true;960 };961 962 switch (BO->getOpcode()) {963 case BO_EQ:964 return MaybeCastToBool(this->emitEQ(*LT, BO));965 case BO_NE:966 return MaybeCastToBool(this->emitNE(*LT, BO));967 case BO_LT:968 return MaybeCastToBool(this->emitLT(*LT, BO));969 case BO_LE:970 return MaybeCastToBool(this->emitLE(*LT, BO));971 case BO_GT:972 return MaybeCastToBool(this->emitGT(*LT, BO));973 case BO_GE:974 return MaybeCastToBool(this->emitGE(*LT, BO));975 case BO_Sub:976 if (BO->getType()->isFloatingType())977 return Discard(this->emitSubf(getFPOptions(BO), BO));978 return Discard(this->emitSub(*T, BO));979 case BO_Add:980 if (BO->getType()->isFloatingType())981 return Discard(this->emitAddf(getFPOptions(BO), BO));982 return Discard(this->emitAdd(*T, BO));983 case BO_Mul:984 if (BO->getType()->isFloatingType())985 return Discard(this->emitMulf(getFPOptions(BO), BO));986 return Discard(this->emitMul(*T, BO));987 case BO_Rem:988 return Discard(this->emitRem(*T, BO));989 case BO_Div:990 if (BO->getType()->isFloatingType())991 return Discard(this->emitDivf(getFPOptions(BO), BO));992 return Discard(this->emitDiv(*T, BO));993 case BO_And:994 return Discard(this->emitBitAnd(*T, BO));995 case BO_Or:996 return Discard(this->emitBitOr(*T, BO));997 case BO_Shl:998 return Discard(this->emitShl(*LT, *RT, BO));999 case BO_Shr:1000 return Discard(this->emitShr(*LT, *RT, BO));1001 case BO_Xor:1002 return Discard(this->emitBitXor(*T, BO));1003 case BO_LOr:1004 case BO_LAnd:1005 llvm_unreachable("Already handled earlier");1006 default:1007 return false;1008 }1009 1010 llvm_unreachable("Unhandled binary op");1011}1012 1013/// Perform addition/subtraction of a pointer and an integer or1014/// subtraction of two pointers.1015template <class Emitter>1016bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {1017 BinaryOperatorKind Op = E->getOpcode();1018 const Expr *LHS = E->getLHS();1019 const Expr *RHS = E->getRHS();1020 1021 if ((Op != BO_Add && Op != BO_Sub) ||1022 (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))1023 return false;1024 1025 OptPrimType LT = classify(LHS);1026 OptPrimType RT = classify(RHS);1027 1028 if (!LT || !RT)1029 return false;1030 1031 // Visit the given pointer expression and optionally convert to a PT_Ptr.1032 auto visitAsPointer = [&](const Expr *E, PrimType T) -> bool {1033 if (!this->visit(E))1034 return false;1035 if (T != PT_Ptr)1036 return this->emitDecayPtr(T, PT_Ptr, E);1037 return true;1038 };1039 1040 if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {1041 if (Op != BO_Sub)1042 return false;1043 1044 assert(E->getType()->isIntegerType());1045 if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *LT))1046 return false;1047 1048 QualType ElemType = LHS->getType()->getPointeeType();1049 CharUnits ElemTypeSize;1050 if (ElemType->isVoidType() || ElemType->isFunctionType())1051 ElemTypeSize = CharUnits::One();1052 else1053 ElemTypeSize = Ctx.getASTContext().getTypeSizeInChars(ElemType);1054 1055 PrimType IntT = classifyPrim(E->getType());1056 if (!this->emitSubPtr(IntT, ElemTypeSize.isZero(), E))1057 return false;1058 return DiscardResult ? this->emitPop(IntT, E) : true;1059 }1060 1061 PrimType OffsetType;1062 if (LHS->getType()->isIntegerType()) {1063 if (!visitAsPointer(RHS, *RT))1064 return false;1065 if (!this->visit(LHS))1066 return false;1067 OffsetType = *LT;1068 } else if (RHS->getType()->isIntegerType()) {1069 if (!visitAsPointer(LHS, *LT))1070 return false;1071 if (!this->visit(RHS))1072 return false;1073 OffsetType = *RT;1074 } else {1075 return false;1076 }1077 1078 // Do the operation and optionally transform to1079 // result pointer type.1080 if (Op == BO_Add) {1081 if (!this->emitAddOffset(OffsetType, E))1082 return false;1083 1084 if (classifyPrim(E) != PT_Ptr)1085 return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);1086 return true;1087 }1088 if (Op == BO_Sub) {1089 if (!this->emitSubOffset(OffsetType, E))1090 return false;1091 1092 if (classifyPrim(E) != PT_Ptr)1093 return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);1094 return true;1095 }1096 1097 return false;1098}1099 1100template <class Emitter>1101bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {1102 assert(E->isLogicalOp());1103 BinaryOperatorKind Op = E->getOpcode();1104 const Expr *LHS = E->getLHS();1105 const Expr *RHS = E->getRHS();1106 OptPrimType T = classify(E->getType());1107 1108 if (Op == BO_LOr) {1109 // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.1110 LabelTy LabelTrue = this->getLabel();1111 LabelTy LabelEnd = this->getLabel();1112 1113 if (!this->visitBool(LHS))1114 return false;1115 if (!this->jumpTrue(LabelTrue))1116 return false;1117 1118 if (!this->visitBool(RHS))1119 return false;1120 if (!this->jump(LabelEnd))1121 return false;1122 1123 this->emitLabel(LabelTrue);1124 this->emitConstBool(true, E);1125 this->fallthrough(LabelEnd);1126 this->emitLabel(LabelEnd);1127 1128 } else {1129 assert(Op == BO_LAnd);1130 // Logical AND.1131 // Visit LHS. Only visit RHS if LHS was TRUE.1132 LabelTy LabelFalse = this->getLabel();1133 LabelTy LabelEnd = this->getLabel();1134 1135 if (!this->visitBool(LHS))1136 return false;1137 if (!this->jumpFalse(LabelFalse))1138 return false;1139 1140 if (!this->visitBool(RHS))1141 return false;1142 if (!this->jump(LabelEnd))1143 return false;1144 1145 this->emitLabel(LabelFalse);1146 this->emitConstBool(false, E);1147 this->fallthrough(LabelEnd);1148 this->emitLabel(LabelEnd);1149 }1150 1151 if (DiscardResult)1152 return this->emitPopBool(E);1153 1154 // For C, cast back to integer type.1155 assert(T);1156 if (T != PT_Bool)1157 return this->emitCast(PT_Bool, *T, E);1158 return true;1159}1160 1161template <class Emitter>1162bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {1163 // Prepare storage for result.1164 if (!Initializing) {1165 UnsignedOrNone LocalIndex = allocateTemporary(E);1166 if (!LocalIndex)1167 return false;1168 if (!this->emitGetPtrLocal(*LocalIndex, E))1169 return false;1170 }1171 1172 // Both LHS and RHS might _not_ be of complex type, but one of them1173 // needs to be.1174 const Expr *LHS = E->getLHS();1175 const Expr *RHS = E->getRHS();1176 1177 PrimType ResultElemT = this->classifyComplexElementType(E->getType());1178 unsigned ResultOffset = ~0u;1179 if (!DiscardResult)1180 ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, /*IsConst=*/true);1181 1182 // Save result pointer in ResultOffset1183 if (!this->DiscardResult) {1184 if (!this->emitDupPtr(E))1185 return false;1186 if (!this->emitSetLocal(PT_Ptr, ResultOffset, E))1187 return false;1188 }1189 QualType LHSType = LHS->getType();1190 if (const auto *AT = LHSType->getAs<AtomicType>())1191 LHSType = AT->getValueType();1192 QualType RHSType = RHS->getType();1193 if (const auto *AT = RHSType->getAs<AtomicType>())1194 RHSType = AT->getValueType();1195 1196 bool LHSIsComplex = LHSType->isAnyComplexType();1197 unsigned LHSOffset;1198 bool RHSIsComplex = RHSType->isAnyComplexType();1199 1200 // For ComplexComplex Mul, we have special ops to make their implementation1201 // easier.1202 BinaryOperatorKind Op = E->getOpcode();1203 if (Op == BO_Mul && LHSIsComplex && RHSIsComplex) {1204 assert(classifyPrim(LHSType->getAs<ComplexType>()->getElementType()) ==1205 classifyPrim(RHSType->getAs<ComplexType>()->getElementType()));1206 PrimType ElemT =1207 classifyPrim(LHSType->getAs<ComplexType>()->getElementType());1208 if (!this->visit(LHS))1209 return false;1210 if (!this->visit(RHS))1211 return false;1212 return this->emitMulc(ElemT, E);1213 }1214 1215 if (Op == BO_Div && RHSIsComplex) {1216 QualType ElemQT = RHSType->getAs<ComplexType>()->getElementType();1217 PrimType ElemT = classifyPrim(ElemQT);1218 // If the LHS is not complex, we still need to do the full complex1219 // division, so just stub create a complex value and stub it out with1220 // the LHS and a zero.1221 1222 if (!LHSIsComplex) {1223 // This is using the RHS type for the fake-complex LHS.1224 UnsignedOrNone LocalIndex = allocateTemporary(RHS);1225 if (!LocalIndex)1226 return false;1227 LHSOffset = *LocalIndex;1228 1229 if (!this->emitGetPtrLocal(LHSOffset, E))1230 return false;1231 1232 if (!this->visit(LHS))1233 return false;1234 // real is LHS1235 if (!this->emitInitElem(ElemT, 0, E))1236 return false;1237 // imag is zero1238 if (!this->visitZeroInitializer(ElemT, ElemQT, E))1239 return false;1240 if (!this->emitInitElem(ElemT, 1, E))1241 return false;1242 } else {1243 if (!this->visit(LHS))1244 return false;1245 }1246 1247 if (!this->visit(RHS))1248 return false;1249 return this->emitDivc(ElemT, E);1250 }1251 1252 // Evaluate LHS and save value to LHSOffset.1253 if (LHSType->isAnyComplexType()) {1254 LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);1255 if (!this->visit(LHS))1256 return false;1257 if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))1258 return false;1259 } else {1260 PrimType LHST = classifyPrim(LHSType);1261 LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);1262 if (!this->visit(LHS))1263 return false;1264 if (!this->emitSetLocal(LHST, LHSOffset, E))1265 return false;1266 }1267 1268 // Same with RHS.1269 unsigned RHSOffset;1270 if (RHSType->isAnyComplexType()) {1271 RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);1272 if (!this->visit(RHS))1273 return false;1274 if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))1275 return false;1276 } else {1277 PrimType RHST = classifyPrim(RHSType);1278 RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);1279 if (!this->visit(RHS))1280 return false;1281 if (!this->emitSetLocal(RHST, RHSOffset, E))1282 return false;1283 }1284 1285 // For both LHS and RHS, either load the value from the complex pointer, or1286 // directly from the local variable. For index 1 (i.e. the imaginary part),1287 // just load 0 and do the operation anyway.1288 auto loadComplexValue = [this](bool IsComplex, bool LoadZero,1289 unsigned ElemIndex, unsigned Offset,1290 const Expr *E) -> bool {1291 if (IsComplex) {1292 if (!this->emitGetLocal(PT_Ptr, Offset, E))1293 return false;1294 return this->emitArrayElemPop(classifyComplexElementType(E->getType()),1295 ElemIndex, E);1296 }1297 if (ElemIndex == 0 || !LoadZero)1298 return this->emitGetLocal(classifyPrim(E->getType()), Offset, E);1299 return this->visitZeroInitializer(classifyPrim(E->getType()), E->getType(),1300 E);1301 };1302 1303 // Now we can get pointers to the LHS and RHS from the offsets above.1304 for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) {1305 // Result pointer for the store later.1306 if (!this->DiscardResult) {1307 if (!this->emitGetLocal(PT_Ptr, ResultOffset, E))1308 return false;1309 }1310 1311 // The actual operation.1312 switch (Op) {1313 case BO_Add:1314 if (!loadComplexValue(LHSIsComplex, true, ElemIndex, LHSOffset, LHS))1315 return false;1316 1317 if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))1318 return false;1319 if (ResultElemT == PT_Float) {1320 if (!this->emitAddf(getFPOptions(E), E))1321 return false;1322 } else {1323 if (!this->emitAdd(ResultElemT, E))1324 return false;1325 }1326 break;1327 case BO_Sub:1328 if (!loadComplexValue(LHSIsComplex, true, ElemIndex, LHSOffset, LHS))1329 return false;1330 1331 if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))1332 return false;1333 if (ResultElemT == PT_Float) {1334 if (!this->emitSubf(getFPOptions(E), E))1335 return false;1336 } else {1337 if (!this->emitSub(ResultElemT, E))1338 return false;1339 }1340 break;1341 case BO_Mul:1342 if (!loadComplexValue(LHSIsComplex, false, ElemIndex, LHSOffset, LHS))1343 return false;1344 1345 if (!loadComplexValue(RHSIsComplex, false, ElemIndex, RHSOffset, RHS))1346 return false;1347 1348 if (ResultElemT == PT_Float) {1349 if (!this->emitMulf(getFPOptions(E), E))1350 return false;1351 } else {1352 if (!this->emitMul(ResultElemT, E))1353 return false;1354 }1355 break;1356 case BO_Div:1357 assert(!RHSIsComplex);1358 if (!loadComplexValue(LHSIsComplex, false, ElemIndex, LHSOffset, LHS))1359 return false;1360 1361 if (!loadComplexValue(RHSIsComplex, false, ElemIndex, RHSOffset, RHS))1362 return false;1363 1364 if (ResultElemT == PT_Float) {1365 if (!this->emitDivf(getFPOptions(E), E))1366 return false;1367 } else {1368 if (!this->emitDiv(ResultElemT, E))1369 return false;1370 }1371 break;1372 1373 default:1374 return false;1375 }1376 1377 if (!this->DiscardResult) {1378 // Initialize array element with the value we just computed.1379 if (!this->emitInitElemPop(ResultElemT, ElemIndex, E))1380 return false;1381 } else {1382 if (!this->emitPop(ResultElemT, E))1383 return false;1384 }1385 }1386 return true;1387}1388 1389template <class Emitter>1390bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {1391 const Expr *LHS = E->getLHS();1392 const Expr *RHS = E->getRHS();1393 assert(!E->isCommaOp() &&1394 "Comma op should be handled in VisitBinaryOperator");1395 assert(E->getType()->isVectorType());1396 assert(LHS->getType()->isVectorType());1397 assert(RHS->getType()->isVectorType());1398 1399 // We can only handle vectors with primitive element types.1400 if (!canClassify(LHS->getType()->castAs<VectorType>()->getElementType()))1401 return false;1402 1403 // Prepare storage for result.1404 if (!Initializing && !E->isCompoundAssignmentOp() && !E->isAssignmentOp()) {1405 UnsignedOrNone LocalIndex = allocateTemporary(E);1406 if (!LocalIndex)1407 return false;1408 if (!this->emitGetPtrLocal(*LocalIndex, E))1409 return false;1410 }1411 1412 const auto *VecTy = E->getType()->getAs<VectorType>();1413 auto Op = E->isCompoundAssignmentOp()1414 ? BinaryOperator::getOpForCompoundAssignment(E->getOpcode())1415 : E->getOpcode();1416 1417 PrimType ElemT = this->classifyVectorElementType(LHS->getType());1418 PrimType RHSElemT = this->classifyVectorElementType(RHS->getType());1419 PrimType ResultElemT = this->classifyVectorElementType(E->getType());1420 1421 if (E->getOpcode() == BO_Assign) {1422 assert(Ctx.getASTContext().hasSameUnqualifiedType(1423 LHS->getType()->castAs<VectorType>()->getElementType(),1424 RHS->getType()->castAs<VectorType>()->getElementType()));1425 if (!this->visit(LHS))1426 return false;1427 if (!this->visit(RHS))1428 return false;1429 if (!this->emitCopyArray(ElemT, 0, 0, VecTy->getNumElements(), E))1430 return false;1431 if (DiscardResult)1432 return this->emitPopPtr(E);1433 return true;1434 }1435 1436 // Evaluate LHS and save value to LHSOffset.1437 unsigned LHSOffset =1438 this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);1439 if (!this->visit(LHS))1440 return false;1441 if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))1442 return false;1443 1444 // Evaluate RHS and save value to RHSOffset.1445 unsigned RHSOffset =1446 this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);1447 if (!this->visit(RHS))1448 return false;1449 if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))1450 return false;1451 1452 if (E->isCompoundAssignmentOp() && !this->emitGetLocal(PT_Ptr, LHSOffset, E))1453 return false;1454 1455 // BitAdd/BitOr/BitXor/Shl/Shr doesn't support bool type, we need perform the1456 // integer promotion.1457 bool NeedIntPromot = ElemT == PT_Bool && (E->isBitwiseOp() || E->isShiftOp());1458 QualType PromotTy;1459 PrimType PromotT = PT_Bool;1460 PrimType OpT = ElemT;1461 if (NeedIntPromot) {1462 PromotTy =1463 Ctx.getASTContext().getPromotedIntegerType(Ctx.getASTContext().BoolTy);1464 PromotT = classifyPrim(PromotTy);1465 OpT = PromotT;1466 }1467 1468 auto getElem = [=](unsigned Offset, PrimType ElemT, unsigned Index) {1469 if (!this->emitGetLocal(PT_Ptr, Offset, E))1470 return false;1471 if (!this->emitArrayElemPop(ElemT, Index, E))1472 return false;1473 if (E->isLogicalOp()) {1474 if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))1475 return false;1476 if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))1477 return false;1478 } else if (NeedIntPromot) {1479 if (!this->emitPrimCast(ElemT, PromotT, PromotTy, E))1480 return false;1481 }1482 return true;1483 };1484 1485#define EMIT_ARITH_OP(OP) \1486 { \1487 if (ElemT == PT_Float) { \1488 if (!this->emit##OP##f(getFPOptions(E), E)) \1489 return false; \1490 } else { \1491 if (!this->emit##OP(ElemT, E)) \1492 return false; \1493 } \1494 break; \1495 }1496 1497 for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {1498 if (!getElem(LHSOffset, ElemT, I))1499 return false;1500 if (!getElem(RHSOffset, RHSElemT, I))1501 return false;1502 switch (Op) {1503 case BO_Add:1504 EMIT_ARITH_OP(Add)1505 case BO_Sub:1506 EMIT_ARITH_OP(Sub)1507 case BO_Mul:1508 EMIT_ARITH_OP(Mul)1509 case BO_Div:1510 EMIT_ARITH_OP(Div)1511 case BO_Rem:1512 if (!this->emitRem(ElemT, E))1513 return false;1514 break;1515 case BO_And:1516 if (!this->emitBitAnd(OpT, E))1517 return false;1518 break;1519 case BO_Or:1520 if (!this->emitBitOr(OpT, E))1521 return false;1522 break;1523 case BO_Xor:1524 if (!this->emitBitXor(OpT, E))1525 return false;1526 break;1527 case BO_Shl:1528 if (!this->emitShl(OpT, RHSElemT, E))1529 return false;1530 break;1531 case BO_Shr:1532 if (!this->emitShr(OpT, RHSElemT, E))1533 return false;1534 break;1535 case BO_EQ:1536 if (!this->emitEQ(ElemT, E))1537 return false;1538 break;1539 case BO_NE:1540 if (!this->emitNE(ElemT, E))1541 return false;1542 break;1543 case BO_LE:1544 if (!this->emitLE(ElemT, E))1545 return false;1546 break;1547 case BO_LT:1548 if (!this->emitLT(ElemT, E))1549 return false;1550 break;1551 case BO_GE:1552 if (!this->emitGE(ElemT, E))1553 return false;1554 break;1555 case BO_GT:1556 if (!this->emitGT(ElemT, E))1557 return false;1558 break;1559 case BO_LAnd:1560 // a && b is equivalent to a!=0 & b!=01561 if (!this->emitBitAnd(ResultElemT, E))1562 return false;1563 break;1564 case BO_LOr:1565 // a || b is equivalent to a!=0 | b!=01566 if (!this->emitBitOr(ResultElemT, E))1567 return false;1568 break;1569 default:1570 return this->emitInvalid(E);1571 }1572 1573 // The result of the comparison is a vector of the same width and number1574 // of elements as the comparison operands with a signed integral element1575 // type.1576 //1577 // https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html1578 if (E->isComparisonOp()) {1579 if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))1580 return false;1581 if (!this->emitNeg(ResultElemT, E))1582 return false;1583 }1584 1585 // If we performed an integer promotion, we need to cast the compute result1586 // into result vector element type.1587 if (NeedIntPromot &&1588 !this->emitPrimCast(PromotT, ResultElemT, VecTy->getElementType(), E))1589 return false;1590 1591 // Initialize array element with the value we just computed.1592 if (!this->emitInitElem(ResultElemT, I, E))1593 return false;1594 }1595 1596 if (DiscardResult && E->isCompoundAssignmentOp() && !this->emitPopPtr(E))1597 return false;1598 return true;1599}1600 1601template <class Emitter>1602bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {1603 const Expr *LHS = E->getLHS();1604 const Expr *RHS = E->getRHS();1605 const ASTContext &ASTCtx = Ctx.getASTContext();1606 1607 assert(LHS->getType()->isFixedPointType() ||1608 RHS->getType()->isFixedPointType());1609 1610 auto LHSSema = ASTCtx.getFixedPointSemantics(LHS->getType());1611 auto LHSSemaInt = LHSSema.toOpaqueInt();1612 auto RHSSema = ASTCtx.getFixedPointSemantics(RHS->getType());1613 auto RHSSemaInt = RHSSema.toOpaqueInt();1614 1615 if (!this->visit(LHS))1616 return false;1617 if (!LHS->getType()->isFixedPointType()) {1618 if (!this->emitCastIntegralFixedPoint(classifyPrim(LHS->getType()),1619 LHSSemaInt, E))1620 return false;1621 }1622 1623 if (!this->visit(RHS))1624 return false;1625 if (!RHS->getType()->isFixedPointType()) {1626 if (!this->emitCastIntegralFixedPoint(classifyPrim(RHS->getType()),1627 RHSSemaInt, E))1628 return false;1629 }1630 1631 // Convert the result to the target semantics.1632 auto ConvertResult = [&](bool R) -> bool {1633 if (!R)1634 return false;1635 auto ResultSema = ASTCtx.getFixedPointSemantics(E->getType()).toOpaqueInt();1636 auto CommonSema = LHSSema.getCommonSemantics(RHSSema).toOpaqueInt();1637 if (ResultSema != CommonSema)1638 return this->emitCastFixedPoint(ResultSema, E);1639 return true;1640 };1641 1642 auto MaybeCastToBool = [&](bool Result) {1643 if (!Result)1644 return false;1645 PrimType T = classifyPrim(E);1646 if (DiscardResult)1647 return this->emitPop(T, E);1648 if (T != PT_Bool)1649 return this->emitCast(PT_Bool, T, E);1650 return true;1651 };1652 1653 switch (E->getOpcode()) {1654 case BO_EQ:1655 return MaybeCastToBool(this->emitEQFixedPoint(E));1656 case BO_NE:1657 return MaybeCastToBool(this->emitNEFixedPoint(E));1658 case BO_LT:1659 return MaybeCastToBool(this->emitLTFixedPoint(E));1660 case BO_LE:1661 return MaybeCastToBool(this->emitLEFixedPoint(E));1662 case BO_GT:1663 return MaybeCastToBool(this->emitGTFixedPoint(E));1664 case BO_GE:1665 return MaybeCastToBool(this->emitGEFixedPoint(E));1666 case BO_Add:1667 return ConvertResult(this->emitAddFixedPoint(E));1668 case BO_Sub:1669 return ConvertResult(this->emitSubFixedPoint(E));1670 case BO_Mul:1671 return ConvertResult(this->emitMulFixedPoint(E));1672 case BO_Div:1673 return ConvertResult(this->emitDivFixedPoint(E));1674 case BO_Shl:1675 return ConvertResult(this->emitShiftFixedPoint(/*Left=*/true, E));1676 case BO_Shr:1677 return ConvertResult(this->emitShiftFixedPoint(/*Left=*/false, E));1678 1679 default:1680 return this->emitInvalid(E);1681 }1682 1683 llvm_unreachable("unhandled binop opcode");1684}1685 1686template <class Emitter>1687bool Compiler<Emitter>::VisitFixedPointUnaryOperator(const UnaryOperator *E) {1688 const Expr *SubExpr = E->getSubExpr();1689 assert(SubExpr->getType()->isFixedPointType());1690 1691 switch (E->getOpcode()) {1692 case UO_Plus:1693 return this->delegate(SubExpr);1694 case UO_Minus:1695 if (!this->visit(SubExpr))1696 return false;1697 return this->emitNegFixedPoint(E);1698 default:1699 return false;1700 }1701 1702 llvm_unreachable("Unhandled unary opcode");1703}1704 1705template <class Emitter>1706bool Compiler<Emitter>::VisitImplicitValueInitExpr(1707 const ImplicitValueInitExpr *E) {1708 if (DiscardResult)1709 return true;1710 1711 QualType QT = E->getType();1712 1713 if (OptPrimType T = classify(QT))1714 return this->visitZeroInitializer(*T, QT, E);1715 1716 if (QT->isRecordType()) {1717 const RecordDecl *RD = QT->getAsRecordDecl();1718 assert(RD);1719 if (RD->isInvalidDecl())1720 return false;1721 1722 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);1723 CXXRD && CXXRD->getNumVBases() > 0) {1724 // TODO: Diagnose.1725 return false;1726 }1727 1728 const Record *R = getRecord(QT);1729 if (!R)1730 return false;1731 1732 assert(Initializing);1733 return this->visitZeroRecordInitializer(R, E);1734 }1735 1736 if (QT->isIncompleteArrayType())1737 return true;1738 1739 if (QT->isArrayType())1740 return this->visitZeroArrayInitializer(QT, E);1741 1742 if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {1743 assert(Initializing);1744 QualType ElemQT = ComplexTy->getElementType();1745 PrimType ElemT = classifyPrim(ElemQT);1746 for (unsigned I = 0; I < 2; ++I) {1747 if (!this->visitZeroInitializer(ElemT, ElemQT, E))1748 return false;1749 if (!this->emitInitElem(ElemT, I, E))1750 return false;1751 }1752 return true;1753 }1754 1755 if (const auto *VecT = E->getType()->getAs<VectorType>()) {1756 unsigned NumVecElements = VecT->getNumElements();1757 QualType ElemQT = VecT->getElementType();1758 PrimType ElemT = classifyPrim(ElemQT);1759 1760 for (unsigned I = 0; I < NumVecElements; ++I) {1761 if (!this->visitZeroInitializer(ElemT, ElemQT, E))1762 return false;1763 if (!this->emitInitElem(ElemT, I, E))1764 return false;1765 }1766 return true;1767 }1768 1769 return false;1770}1771 1772template <class Emitter>1773bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {1774 const Expr *LHS = E->getLHS();1775 const Expr *RHS = E->getRHS();1776 const Expr *Index = E->getIdx();1777 const Expr *Base = E->getBase();1778 1779 // C++17's rules require us to evaluate the LHS first, regardless of which1780 // side is the base.1781 bool Success = true;1782 for (const Expr *SubExpr : {LHS, RHS}) {1783 if (!this->visit(SubExpr)) {1784 Success = false;1785 continue;1786 }1787 1788 // Expand the base if this is a subscript on a1789 // pointer expression.1790 if (SubExpr == Base && Base->getType()->isPointerType()) {1791 if (!this->emitExpandPtr(E))1792 Success = false;1793 }1794 }1795 1796 if (!Success)1797 return false;1798 1799 OptPrimType IndexT = classify(Index->getType());1800 // In error-recovery cases, the index expression has a dependent type.1801 if (!IndexT)1802 return this->emitError(E);1803 // If the index is first, we need to change that.1804 if (LHS == Index) {1805 if (!this->emitFlip(PT_Ptr, *IndexT, E))1806 return false;1807 }1808 1809 if (!this->emitArrayElemPtrPop(*IndexT, E))1810 return false;1811 if (DiscardResult)1812 return this->emitPopPtr(E);1813 1814 if (E->isGLValue())1815 return true;1816 1817 OptPrimType T = classifyPrim(E);1818 return this->emitLoadPop(*T, E);1819}1820 1821template <class Emitter>1822bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,1823 const Expr *ArrayFiller, const Expr *E) {1824 InitLinkScope<Emitter> ILS(this, InitLink::InitList());1825 1826 QualType QT = E->getType();1827 if (const auto *AT = QT->getAs<AtomicType>())1828 QT = AT->getValueType();1829 1830 if (QT->isVoidType()) {1831 if (Inits.size() == 0)1832 return true;1833 return this->emitInvalid(E);1834 }1835 1836 // Handle discarding first.1837 if (DiscardResult) {1838 for (const Expr *Init : Inits) {1839 if (!this->discard(Init))1840 return false;1841 }1842 return true;1843 }1844 1845 // Primitive values.1846 if (OptPrimType T = classify(QT)) {1847 assert(!DiscardResult);1848 if (Inits.size() == 0)1849 return this->visitZeroInitializer(*T, QT, E);1850 assert(Inits.size() == 1);1851 return this->delegate(Inits[0]);1852 }1853 1854 if (QT->isRecordType()) {1855 const Record *R = getRecord(QT);1856 1857 if (Inits.size() == 1 && E->getType() == Inits[0]->getType())1858 return this->delegate(Inits[0]);1859 1860 if (!R)1861 return false;1862 1863 auto initPrimitiveField = [=](const Record::Field *FieldToInit,1864 const Expr *Init, PrimType T,1865 bool Activate = false) -> bool {1866 InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));1867 if (!this->visit(Init))1868 return false;1869 1870 bool BitField = FieldToInit->isBitField();1871 if (BitField && Activate)1872 return this->emitInitBitFieldActivate(T, FieldToInit, E);1873 if (BitField)1874 return this->emitInitBitField(T, FieldToInit, E);1875 if (Activate)1876 return this->emitInitFieldActivate(T, FieldToInit->Offset, E);1877 return this->emitInitField(T, FieldToInit->Offset, E);1878 };1879 1880 auto initCompositeField = [=](const Record::Field *FieldToInit,1881 const Expr *Init,1882 bool Activate = false) -> bool {1883 InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));1884 InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));1885 1886 // Non-primitive case. Get a pointer to the field-to-initialize1887 // on the stack and recurse into visitInitializer().1888 if (!this->emitGetPtrField(FieldToInit->Offset, Init))1889 return false;1890 1891 if (Activate && !this->emitActivate(E))1892 return false;1893 1894 if (!this->visitInitializer(Init))1895 return false;1896 return this->emitPopPtr(E);1897 };1898 1899 if (R->isUnion()) {1900 if (Inits.size() == 0) {1901 if (!this->visitZeroRecordInitializer(R, E))1902 return false;1903 } else {1904 const Expr *Init = Inits[0];1905 const FieldDecl *FToInit = nullptr;1906 if (const auto *ILE = dyn_cast<InitListExpr>(E))1907 FToInit = ILE->getInitializedFieldInUnion();1908 else1909 FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion();1910 1911 const Record::Field *FieldToInit = R->getField(FToInit);1912 if (OptPrimType T = classify(Init)) {1913 if (!initPrimitiveField(FieldToInit, Init, *T, /*Activate=*/true))1914 return false;1915 } else {1916 if (!initCompositeField(FieldToInit, Init, /*Activate=*/true))1917 return false;1918 }1919 }1920 return this->emitFinishInit(E);1921 }1922 1923 assert(!R->isUnion());1924 unsigned InitIndex = 0;1925 for (const Expr *Init : Inits) {1926 // Skip unnamed bitfields.1927 while (InitIndex < R->getNumFields() &&1928 R->getField(InitIndex)->isUnnamedBitField())1929 ++InitIndex;1930 1931 if (OptPrimType T = classify(Init)) {1932 const Record::Field *FieldToInit = R->getField(InitIndex);1933 if (!initPrimitiveField(FieldToInit, Init, *T))1934 return false;1935 ++InitIndex;1936 } else {1937 // Initializer for a direct base class.1938 if (const Record::Base *B = R->getBase(Init->getType())) {1939 if (!this->emitGetPtrBase(B->Offset, Init))1940 return false;1941 1942 if (!this->visitInitializer(Init))1943 return false;1944 1945 if (!this->emitFinishInitPop(E))1946 return false;1947 // Base initializers don't increase InitIndex, since they don't count1948 // into the Record's fields.1949 } else {1950 const Record::Field *FieldToInit = R->getField(InitIndex);1951 if (!initCompositeField(FieldToInit, Init))1952 return false;1953 ++InitIndex;1954 }1955 }1956 }1957 return this->emitFinishInit(E);1958 }1959 1960 if (QT->isArrayType()) {1961 if (Inits.size() == 1 && QT == Inits[0]->getType())1962 return this->delegate(Inits[0]);1963 1964 const ConstantArrayType *CAT =1965 Ctx.getASTContext().getAsConstantArrayType(QT);1966 uint64_t NumElems = CAT->getZExtSize();1967 1968 if (!this->emitCheckArraySize(NumElems, E))1969 return false;1970 1971 OptPrimType InitT = classify(CAT->getElementType());1972 unsigned ElementIndex = 0;1973 for (const Expr *Init : Inits) {1974 if (const auto *EmbedS =1975 dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) {1976 PrimType TargetT = classifyPrim(Init->getType());1977 1978 auto Eval = [&](const IntegerLiteral *IL, unsigned ElemIndex) {1979 if (TargetT == PT_Float) {1980 if (!this->emitConst(IL->getValue(), classifyPrim(IL), Init))1981 return false;1982 const auto *Sem = &Ctx.getFloatSemantics(CAT->getElementType());1983 if (!this->emitCastIntegralFloating(classifyPrim(IL), Sem,1984 getFPOptions(E), E))1985 return false;1986 } else {1987 if (!this->emitConst(IL->getValue(), TargetT, Init))1988 return false;1989 }1990 return this->emitInitElem(TargetT, ElemIndex, IL);1991 };1992 if (!EmbedS->doForEachDataElement(Eval, ElementIndex))1993 return false;1994 } else {1995 if (!this->visitArrayElemInit(ElementIndex, Init, InitT))1996 return false;1997 ++ElementIndex;1998 }1999 }2000 2001 // Expand the filler expression.2002 // FIXME: This should go away.2003 if (ArrayFiller) {2004 for (; ElementIndex != NumElems; ++ElementIndex) {2005 if (!this->visitArrayElemInit(ElementIndex, ArrayFiller, InitT))2006 return false;2007 }2008 }2009 2010 return this->emitFinishInit(E);2011 }2012 2013 if (const auto *ComplexTy = QT->getAs<ComplexType>()) {2014 unsigned NumInits = Inits.size();2015 2016 if (NumInits == 1)2017 return this->delegate(Inits[0]);2018 2019 QualType ElemQT = ComplexTy->getElementType();2020 PrimType ElemT = classifyPrim(ElemQT);2021 if (NumInits == 0) {2022 // Zero-initialize both elements.2023 for (unsigned I = 0; I < 2; ++I) {2024 if (!this->visitZeroInitializer(ElemT, ElemQT, E))2025 return false;2026 if (!this->emitInitElem(ElemT, I, E))2027 return false;2028 }2029 } else if (NumInits == 2) {2030 unsigned InitIndex = 0;2031 for (const Expr *Init : Inits) {2032 if (!this->visit(Init))2033 return false;2034 2035 if (!this->emitInitElem(ElemT, InitIndex, E))2036 return false;2037 ++InitIndex;2038 }2039 }2040 return true;2041 }2042 2043 if (const auto *VecT = QT->getAs<VectorType>()) {2044 unsigned NumVecElements = VecT->getNumElements();2045 assert(NumVecElements >= Inits.size());2046 2047 QualType ElemQT = VecT->getElementType();2048 PrimType ElemT = classifyPrim(ElemQT);2049 2050 // All initializer elements.2051 unsigned InitIndex = 0;2052 for (const Expr *Init : Inits) {2053 if (!this->visit(Init))2054 return false;2055 2056 // If the initializer is of vector type itself, we have to deconstruct2057 // that and initialize all the target fields from the initializer fields.2058 if (const auto *InitVecT = Init->getType()->getAs<VectorType>()) {2059 if (!this->emitCopyArray(ElemT, 0, InitIndex,2060 InitVecT->getNumElements(), E))2061 return false;2062 InitIndex += InitVecT->getNumElements();2063 } else {2064 if (!this->emitInitElem(ElemT, InitIndex, E))2065 return false;2066 ++InitIndex;2067 }2068 }2069 2070 assert(InitIndex <= NumVecElements);2071 2072 // Fill the rest with zeroes.2073 for (; InitIndex != NumVecElements; ++InitIndex) {2074 if (!this->visitZeroInitializer(ElemT, ElemQT, E))2075 return false;2076 if (!this->emitInitElem(ElemT, InitIndex, E))2077 return false;2078 }2079 return true;2080 }2081 2082 return false;2083}2084 2085/// Pointer to the array(not the element!) must be on the stack when calling2086/// this.2087template <class Emitter>2088bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex, const Expr *Init,2089 OptPrimType InitT) {2090 if (InitT) {2091 // Visit the primitive element like normal.2092 if (!this->visit(Init))2093 return false;2094 return this->emitInitElem(*InitT, ElemIndex, Init);2095 }2096 2097 InitLinkScope<Emitter> ILS(this, InitLink::Elem(ElemIndex));2098 // Advance the pointer currently on the stack to the given2099 // dimension.2100 if (!this->emitConstUint32(ElemIndex, Init))2101 return false;2102 if (!this->emitArrayElemPtrUint32(Init))2103 return false;2104 if (!this->visitInitializer(Init))2105 return false;2106 return this->emitFinishInitPop(Init);2107}2108 2109template <class Emitter>2110bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,2111 const FunctionDecl *FuncDecl,2112 bool Activate, bool IsOperatorCall) {2113 assert(VarScope->getKind() == ScopeKind::Call);2114 llvm::BitVector NonNullArgs;2115 if (FuncDecl && FuncDecl->hasAttr<NonNullAttr>())2116 NonNullArgs = collectNonNullArgs(FuncDecl, Args);2117 2118 bool ExplicitMemberFn = false;2119 if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FuncDecl))2120 ExplicitMemberFn = MD->isExplicitObjectMemberFunction();2121 2122 unsigned ArgIndex = 0;2123 for (const Expr *Arg : Args) {2124 if (canClassify(Arg)) {2125 if (!this->visit(Arg))2126 return false;2127 } else {2128 2129 DeclTy Source = Arg;2130 if (FuncDecl) {2131 // Try to use the parameter declaration instead of the argument2132 // expression as a source.2133 unsigned DeclIndex = ArgIndex - IsOperatorCall + ExplicitMemberFn;2134 if (DeclIndex < FuncDecl->getNumParams())2135 Source = FuncDecl->getParamDecl(ArgIndex - IsOperatorCall +2136 ExplicitMemberFn);2137 }2138 2139 UnsignedOrNone LocalIndex =2140 allocateLocal(std::move(Source), Arg->getType(),2141 /*ExtendingDecl=*/nullptr, ScopeKind::Call);2142 if (!LocalIndex)2143 return false;2144 2145 if (!this->emitGetPtrLocal(*LocalIndex, Arg))2146 return false;2147 InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));2148 if (!this->visitInitializer(Arg))2149 return false;2150 }2151 2152 if (ArgIndex == 1 && Activate) {2153 if (!this->emitActivate(Arg))2154 return false;2155 }2156 2157 if (!NonNullArgs.empty() && NonNullArgs[ArgIndex]) {2158 PrimType ArgT = classify(Arg).value_or(PT_Ptr);2159 if (ArgT == PT_Ptr) {2160 if (!this->emitCheckNonNullArg(ArgT, Arg))2161 return false;2162 }2163 }2164 2165 ++ArgIndex;2166 }2167 2168 return true;2169}2170 2171template <class Emitter>2172bool Compiler<Emitter>::VisitInitListExpr(const InitListExpr *E) {2173 return this->visitInitList(E->inits(), E->getArrayFiller(), E);2174}2175 2176template <class Emitter>2177bool Compiler<Emitter>::VisitCXXParenListInitExpr(2178 const CXXParenListInitExpr *E) {2179 return this->visitInitList(E->getInitExprs(), E->getArrayFiller(), E);2180}2181 2182template <class Emitter>2183bool Compiler<Emitter>::VisitSubstNonTypeTemplateParmExpr(2184 const SubstNonTypeTemplateParmExpr *E) {2185 return this->delegate(E->getReplacement());2186}2187 2188template <class Emitter>2189bool Compiler<Emitter>::VisitConstantExpr(const ConstantExpr *E) {2190 OptPrimType T = classify(E->getType());2191 if (T && E->hasAPValueResult()) {2192 // Try to emit the APValue directly, without visiting the subexpr.2193 // This will only fail if we can't emit the APValue, so won't emit any2194 // diagnostics or any double values.2195 if (DiscardResult)2196 return true;2197 2198 if (this->visitAPValue(E->getAPValueResult(), *T, E))2199 return true;2200 }2201 return this->delegate(E->getSubExpr());2202}2203 2204template <class Emitter>2205bool Compiler<Emitter>::VisitEmbedExpr(const EmbedExpr *E) {2206 auto It = E->begin();2207 return this->visit(*It);2208}2209 2210static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,2211 UnaryExprOrTypeTrait Kind) {2212 bool AlignOfReturnsPreferred =2213 ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;2214 2215 // C++ [expr.alignof]p3:2216 // When alignof is applied to a reference type, the result is the2217 // alignment of the referenced type.2218 if (const auto *Ref = T->getAs<ReferenceType>())2219 T = Ref->getPointeeType();2220 2221 if (T.getQualifiers().hasUnaligned())2222 return CharUnits::One();2223 2224 // __alignof is defined to return the preferred alignment.2225 // Before 8, clang returned the preferred alignment for alignof and2226 // _Alignof as well.2227 if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)2228 return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));2229 2230 return ASTCtx.getTypeAlignInChars(T);2231}2232 2233template <class Emitter>2234bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(2235 const UnaryExprOrTypeTraitExpr *E) {2236 UnaryExprOrTypeTrait Kind = E->getKind();2237 const ASTContext &ASTCtx = Ctx.getASTContext();2238 2239 if (Kind == UETT_SizeOf || Kind == UETT_DataSizeOf) {2240 QualType ArgType = E->getTypeOfArgument();2241 2242 // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,2243 // the result is the size of the referenced type."2244 if (const auto *Ref = ArgType->getAs<ReferenceType>())2245 ArgType = Ref->getPointeeType();2246 2247 CharUnits Size;2248 if (ArgType->isVoidType() || ArgType->isFunctionType())2249 Size = CharUnits::One();2250 else {2251 if (ArgType->isDependentType() || !ArgType->isConstantSizeType())2252 return this->emitInvalid(E);2253 2254 if (Kind == UETT_SizeOf)2255 Size = ASTCtx.getTypeSizeInChars(ArgType);2256 else2257 Size = ASTCtx.getTypeInfoDataSizeInChars(ArgType).Width;2258 }2259 2260 if (DiscardResult)2261 return true;2262 2263 return this->emitConst(Size.getQuantity(), E);2264 }2265 2266 if (Kind == UETT_CountOf) {2267 QualType Ty = E->getTypeOfArgument();2268 assert(Ty->isArrayType());2269 2270 // We don't need to worry about array element qualifiers, so getting the2271 // unsafe array type is fine.2272 if (const auto *CAT =2273 dyn_cast<ConstantArrayType>(Ty->getAsArrayTypeUnsafe())) {2274 if (DiscardResult)2275 return true;2276 return this->emitConst(CAT->getSize(), E);2277 }2278 2279 assert(!Ty->isConstantSizeType());2280 2281 // If it's a variable-length array type, we need to check whether it is a2282 // multidimensional array. If so, we need to check the size expression of2283 // the VLA to see if it's a constant size. If so, we can return that value.2284 const auto *VAT = ASTCtx.getAsVariableArrayType(Ty);2285 assert(VAT);2286 if (VAT->getElementType()->isArrayType()) {2287 std::optional<APSInt> Res =2288 VAT->getSizeExpr()2289 ? VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx)2290 : std::nullopt;2291 if (Res) {2292 if (DiscardResult)2293 return true;2294 return this->emitConst(*Res, E);2295 }2296 }2297 }2298 2299 if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {2300 CharUnits Size;2301 2302 if (E->isArgumentType()) {2303 QualType ArgType = E->getTypeOfArgument();2304 2305 Size = AlignOfType(ArgType, ASTCtx, Kind);2306 } else {2307 // Argument is an expression, not a type.2308 const Expr *Arg = E->getArgumentExpr()->IgnoreParens();2309 2310 // The kinds of expressions that we have special-case logic here for2311 // should be kept up to date with the special checks for those2312 // expressions in Sema.2313 2314 // alignof decl is always accepted, even if it doesn't make sense: we2315 // default to 1 in those cases.2316 if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))2317 Size = ASTCtx.getDeclAlign(DRE->getDecl(),2318 /*RefAsPointee*/ true);2319 else if (const auto *ME = dyn_cast<MemberExpr>(Arg))2320 Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),2321 /*RefAsPointee*/ true);2322 else2323 Size = AlignOfType(Arg->getType(), ASTCtx, Kind);2324 }2325 2326 if (DiscardResult)2327 return true;2328 2329 return this->emitConst(Size.getQuantity(), E);2330 }2331 2332 if (Kind == UETT_VectorElements) {2333 if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>())2334 return this->emitConst(VT->getNumElements(), E);2335 assert(E->getTypeOfArgument()->isSizelessVectorType());2336 return this->emitSizelessVectorElementSize(E);2337 }2338 2339 if (Kind == UETT_VecStep) {2340 if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>()) {2341 unsigned N = VT->getNumElements();2342 2343 // The vec_step built-in functions that take a 3-component2344 // vector return 4. (OpenCL 1.1 spec 6.11.12)2345 if (N == 3)2346 N = 4;2347 2348 return this->emitConst(N, E);2349 }2350 return this->emitConst(1, E);2351 }2352 2353 if (Kind == UETT_OpenMPRequiredSimdAlign) {2354 assert(E->isArgumentType());2355 unsigned Bits = ASTCtx.getOpenMPDefaultSimdAlign(E->getArgumentType());2356 2357 return this->emitConst(ASTCtx.toCharUnitsFromBits(Bits).getQuantity(), E);2358 }2359 2360 if (Kind == UETT_PtrAuthTypeDiscriminator) {2361 if (E->getArgumentType()->isDependentType())2362 return this->emitInvalid(E);2363 2364 return this->emitConst(2365 const_cast<ASTContext &>(ASTCtx).getPointerAuthTypeDiscriminator(2366 E->getArgumentType()),2367 E);2368 }2369 2370 return false;2371}2372 2373template <class Emitter>2374bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {2375 // 'Base.Member'2376 const Expr *Base = E->getBase();2377 const ValueDecl *Member = E->getMemberDecl();2378 2379 if (DiscardResult)2380 return this->discard(Base);2381 2382 // MemberExprs are almost always lvalues, in which case we don't need to2383 // do the load. But sometimes they aren't.2384 const auto maybeLoadValue = [&]() -> bool {2385 if (E->isGLValue())2386 return true;2387 if (OptPrimType T = classify(E))2388 return this->emitLoadPop(*T, E);2389 return false;2390 };2391 2392 if (const auto *VD = dyn_cast<VarDecl>(Member)) {2393 // I am almost confident in saying that a var decl must be static2394 // and therefore registered as a global variable. But this will probably2395 // turn out to be wrong some time in the future, as always.2396 if (auto GlobalIndex = P.getGlobal(VD))2397 return this->emitGetPtrGlobal(*GlobalIndex, E) && maybeLoadValue();2398 return false;2399 }2400 2401 if (!isa<FieldDecl>(Member)) {2402 if (!this->discard(Base) && !this->emitSideEffect(E))2403 return false;2404 2405 return this->visitDeclRef(Member, E);2406 }2407 2408 if (!this->visit(Base))2409 return false;2410 2411 // Base above gives us a pointer on the stack.2412 const auto *FD = cast<FieldDecl>(Member);2413 const RecordDecl *RD = FD->getParent();2414 const Record *R = getRecord(RD);2415 if (!R)2416 return false;2417 const Record::Field *F = R->getField(FD);2418 // Leave a pointer to the field on the stack.2419 if (F->Decl->getType()->isReferenceType())2420 return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();2421 return this->emitGetPtrFieldPop(F->Offset, E) && maybeLoadValue();2422}2423 2424template <class Emitter>2425bool Compiler<Emitter>::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {2426 // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated2427 // stand-alone, e.g. via EvaluateAsInt().2428 if (!ArrayIndex)2429 return false;2430 return this->emitConst(*ArrayIndex, E);2431}2432 2433template <class Emitter>2434bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {2435 assert(Initializing);2436 assert(!DiscardResult);2437 2438 // We visit the common opaque expression here once so we have its value2439 // cached.2440 if (!this->discard(E->getCommonExpr()))2441 return false;2442 2443 // TODO: This compiles to quite a lot of bytecode if the array is larger.2444 // Investigate compiling this to a loop.2445 const Expr *SubExpr = E->getSubExpr();2446 size_t Size = E->getArraySize().getZExtValue();2447 OptPrimType SubExprT = classify(SubExpr);2448 2449 // So, every iteration, we execute an assignment here2450 // where the LHS is on the stack (the target array)2451 // and the RHS is our SubExpr.2452 for (size_t I = 0; I != Size; ++I) {2453 ArrayIndexScope<Emitter> IndexScope(this, I);2454 LocalScope<Emitter> BS(this);2455 2456 if (!this->visitArrayElemInit(I, SubExpr, SubExprT))2457 return false;2458 if (!BS.destroyLocals())2459 return false;2460 }2461 return true;2462}2463 2464template <class Emitter>2465bool Compiler<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {2466 const Expr *SourceExpr = E->getSourceExpr();2467 if (!SourceExpr)2468 return false;2469 2470 if (Initializing)2471 return this->visitInitializer(SourceExpr);2472 2473 PrimType SubExprT = classify(SourceExpr).value_or(PT_Ptr);2474 if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end())2475 return this->emitGetLocal(SubExprT, It->second, E);2476 2477 if (!this->visit(SourceExpr))2478 return false;2479 2480 // At this point we either have the evaluated source expression or a pointer2481 // to an object on the stack. We want to create a local variable that stores2482 // this value.2483 unsigned LocalIndex = allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true);2484 if (!this->emitSetLocal(SubExprT, LocalIndex, E))2485 return false;2486 2487 // Here the local variable is created but the value is removed from the stack,2488 // so we put it back if the caller needs it.2489 if (!DiscardResult) {2490 if (!this->emitGetLocal(SubExprT, LocalIndex, E))2491 return false;2492 }2493 2494 // This is cleaned up when the local variable is destroyed.2495 OpaqueExprs.insert({E, LocalIndex});2496 2497 return true;2498}2499 2500template <class Emitter>2501bool Compiler<Emitter>::VisitAbstractConditionalOperator(2502 const AbstractConditionalOperator *E) {2503 const Expr *Condition = E->getCond();2504 const Expr *TrueExpr = E->getTrueExpr();2505 const Expr *FalseExpr = E->getFalseExpr();2506 2507 // The TrueExpr and FalseExpr of a conditional operator do _not_ create a2508 // scope, which means the local variables created within them unconditionally2509 // always exist. However, we need to later differentiate which branch was2510 // taken and only destroy the varibles of the active branch. This is what the2511 // "enabled" flags on local variables are used for.2512 llvm::SaveAndRestore LAAA(this->VarScope->LocalsAlwaysEnabled,2513 /*NewValue=*/false);2514 2515 if (std::optional<bool> BoolValue = getBoolValue(Condition)) {2516 if (*BoolValue)2517 return this->delegate(TrueExpr);2518 return this->delegate(FalseExpr);2519 }2520 2521 bool IsBcpCall = false;2522 if (const auto *CE = dyn_cast<CallExpr>(Condition->IgnoreParenCasts());2523 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) {2524 IsBcpCall = true;2525 }2526 2527 LabelTy LabelEnd = this->getLabel(); // Label after the operator.2528 LabelTy LabelFalse = this->getLabel(); // Label for the false expr.2529 2530 if (IsBcpCall) {2531 if (!this->emitStartSpeculation(E))2532 return false;2533 }2534 2535 if (!this->visitBool(Condition)) {2536 // If the condition failed and we're checking for undefined behavior2537 // (which only happens with EvalEmitter) check the TrueExpr and FalseExpr2538 // as well.2539 if (this->checkingForUndefinedBehavior()) {2540 if (!this->discard(TrueExpr))2541 return false;2542 if (!this->discard(FalseExpr))2543 return false;2544 }2545 return false;2546 }2547 2548 if (!this->jumpFalse(LabelFalse))2549 return false;2550 if (!this->delegate(TrueExpr))2551 return false;2552 2553 if (!this->jump(LabelEnd))2554 return false;2555 this->emitLabel(LabelFalse);2556 if (!this->delegate(FalseExpr))2557 return false;2558 2559 this->fallthrough(LabelEnd);2560 this->emitLabel(LabelEnd);2561 2562 if (IsBcpCall)2563 return this->emitEndSpeculation(E);2564 return true;2565}2566 2567template <class Emitter>2568bool Compiler<Emitter>::VisitStringLiteral(const StringLiteral *E) {2569 if (DiscardResult)2570 return true;2571 2572 if (!Initializing) {2573 unsigned StringIndex = P.createGlobalString(E);2574 return this->emitGetPtrGlobal(StringIndex, E);2575 }2576 2577 // We are initializing an array on the stack.2578 const ConstantArrayType *CAT =2579 Ctx.getASTContext().getAsConstantArrayType(E->getType());2580 assert(CAT && "a string literal that's not a constant array?");2581 2582 // If the initializer string is too long, a diagnostic has already been2583 // emitted. Read only the array length from the string literal.2584 unsigned ArraySize = CAT->getZExtSize();2585 unsigned N = std::min(ArraySize, E->getLength());2586 unsigned CharWidth = E->getCharByteWidth();2587 2588 for (unsigned I = 0; I != N; ++I) {2589 uint32_t CodeUnit = E->getCodeUnit(I);2590 2591 if (CharWidth == 1) {2592 this->emitConstSint8(CodeUnit, E);2593 this->emitInitElemSint8(I, E);2594 } else if (CharWidth == 2) {2595 this->emitConstUint16(CodeUnit, E);2596 this->emitInitElemUint16(I, E);2597 } else if (CharWidth == 4) {2598 this->emitConstUint32(CodeUnit, E);2599 this->emitInitElemUint32(I, E);2600 } else {2601 llvm_unreachable("unsupported character width");2602 }2603 }2604 2605 // Fill up the rest of the char array with NUL bytes.2606 for (unsigned I = N; I != ArraySize; ++I) {2607 if (CharWidth == 1) {2608 this->emitConstSint8(0, E);2609 this->emitInitElemSint8(I, E);2610 } else if (CharWidth == 2) {2611 this->emitConstUint16(0, E);2612 this->emitInitElemUint16(I, E);2613 } else if (CharWidth == 4) {2614 this->emitConstUint32(0, E);2615 this->emitInitElemUint32(I, E);2616 } else {2617 llvm_unreachable("unsupported character width");2618 }2619 }2620 2621 return true;2622}2623 2624template <class Emitter>2625bool Compiler<Emitter>::VisitObjCStringLiteral(const ObjCStringLiteral *E) {2626 if (DiscardResult)2627 return true;2628 return this->emitDummyPtr(E, E);2629}2630 2631template <class Emitter>2632bool Compiler<Emitter>::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {2633 auto &A = Ctx.getASTContext();2634 std::string Str;2635 A.getObjCEncodingForType(E->getEncodedType(), Str);2636 StringLiteral *SL =2637 StringLiteral::Create(A, Str, StringLiteralKind::Ordinary,2638 /*Pascal=*/false, E->getType(), E->getAtLoc());2639 return this->delegate(SL);2640}2641 2642template <class Emitter>2643bool Compiler<Emitter>::VisitSYCLUniqueStableNameExpr(2644 const SYCLUniqueStableNameExpr *E) {2645 if (DiscardResult)2646 return true;2647 2648 assert(!Initializing);2649 2650 auto &A = Ctx.getASTContext();2651 std::string ResultStr = E->ComputeName(A);2652 2653 QualType CharTy = A.CharTy.withConst();2654 APInt Size(A.getTypeSize(A.getSizeType()), ResultStr.size() + 1);2655 QualType ArrayTy = A.getConstantArrayType(CharTy, Size, nullptr,2656 ArraySizeModifier::Normal, 0);2657 2658 StringLiteral *SL =2659 StringLiteral::Create(A, ResultStr, StringLiteralKind::Ordinary,2660 /*Pascal=*/false, ArrayTy, E->getLocation());2661 2662 unsigned StringIndex = P.createGlobalString(SL);2663 return this->emitGetPtrGlobal(StringIndex, E);2664}2665 2666template <class Emitter>2667bool Compiler<Emitter>::VisitCharacterLiteral(const CharacterLiteral *E) {2668 if (DiscardResult)2669 return true;2670 return this->emitConst(E->getValue(), E);2671}2672 2673template <class Emitter>2674bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(2675 const CompoundAssignOperator *E) {2676 2677 const Expr *LHS = E->getLHS();2678 const Expr *RHS = E->getRHS();2679 QualType LHSType = LHS->getType();2680 QualType LHSComputationType = E->getComputationLHSType();2681 QualType ResultType = E->getComputationResultType();2682 OptPrimType LT = classify(LHSComputationType);2683 OptPrimType RT = classify(ResultType);2684 2685 assert(ResultType->isFloatingType());2686 2687 if (!LT || !RT)2688 return false;2689 2690 PrimType LHST = classifyPrim(LHSType);2691 2692 // C++17 onwards require that we evaluate the RHS first.2693 // Compute RHS and save it in a temporary variable so we can2694 // load it again later.2695 if (!visit(RHS))2696 return false;2697 2698 unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);2699 if (!this->emitSetLocal(*RT, TempOffset, E))2700 return false;2701 2702 // First, visit LHS.2703 if (!visit(LHS))2704 return false;2705 if (!this->emitLoad(LHST, E))2706 return false;2707 2708 // If necessary, convert LHS to its computation type.2709 if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType),2710 LHSComputationType, E))2711 return false;2712 2713 // Now load RHS.2714 if (!this->emitGetLocal(*RT, TempOffset, E))2715 return false;2716 2717 switch (E->getOpcode()) {2718 case BO_AddAssign:2719 if (!this->emitAddf(getFPOptions(E), E))2720 return false;2721 break;2722 case BO_SubAssign:2723 if (!this->emitSubf(getFPOptions(E), E))2724 return false;2725 break;2726 case BO_MulAssign:2727 if (!this->emitMulf(getFPOptions(E), E))2728 return false;2729 break;2730 case BO_DivAssign:2731 if (!this->emitDivf(getFPOptions(E), E))2732 return false;2733 break;2734 default:2735 return false;2736 }2737 2738 if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->getType(), E))2739 return false;2740 2741 if (DiscardResult)2742 return this->emitStorePop(LHST, E);2743 return this->emitStore(LHST, E);2744}2745 2746template <class Emitter>2747bool Compiler<Emitter>::VisitPointerCompoundAssignOperator(2748 const CompoundAssignOperator *E) {2749 BinaryOperatorKind Op = E->getOpcode();2750 const Expr *LHS = E->getLHS();2751 const Expr *RHS = E->getRHS();2752 OptPrimType LT = classify(LHS->getType());2753 OptPrimType RT = classify(RHS->getType());2754 2755 if (Op != BO_AddAssign && Op != BO_SubAssign)2756 return false;2757 2758 if (!LT || !RT)2759 return false;2760 2761 if (!visit(LHS))2762 return false;2763 2764 if (!this->emitLoad(*LT, LHS))2765 return false;2766 2767 if (!visit(RHS))2768 return false;2769 2770 if (Op == BO_AddAssign) {2771 if (!this->emitAddOffset(*RT, E))2772 return false;2773 } else {2774 if (!this->emitSubOffset(*RT, E))2775 return false;2776 }2777 2778 if (DiscardResult)2779 return this->emitStorePopPtr(E);2780 return this->emitStorePtr(E);2781}2782 2783template <class Emitter>2784bool Compiler<Emitter>::VisitCompoundAssignOperator(2785 const CompoundAssignOperator *E) {2786 if (E->getType()->isVectorType())2787 return VisitVectorBinOp(E);2788 2789 const Expr *LHS = E->getLHS();2790 const Expr *RHS = E->getRHS();2791 OptPrimType LHSComputationT = classify(E->getComputationLHSType());2792 OptPrimType LT = classify(LHS->getType());2793 OptPrimType RT = classify(RHS->getType());2794 OptPrimType ResultT = classify(E->getType());2795 2796 if (!Ctx.getLangOpts().CPlusPlus14)2797 return this->visit(RHS) && this->visit(LHS) && this->emitError(E);2798 2799 if (!LT || !RT || !ResultT || !LHSComputationT)2800 return false;2801 2802 // Handle floating point operations separately here, since they2803 // require special care.2804 2805 if (ResultT == PT_Float || RT == PT_Float)2806 return VisitFloatCompoundAssignOperator(E);2807 2808 if (E->getType()->isPointerType())2809 return VisitPointerCompoundAssignOperator(E);2810 2811 assert(!E->getType()->isPointerType() && "Handled above");2812 assert(!E->getType()->isFloatingType() && "Handled above");2813 2814 // C++17 onwards require that we evaluate the RHS first.2815 // Compute RHS and save it in a temporary variable so we can2816 // load it again later.2817 // FIXME: Compound assignments are unsequenced in C, so we might2818 // have to figure out how to reject them.2819 if (!visit(RHS))2820 return false;2821 2822 unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);2823 2824 if (!this->emitSetLocal(*RT, TempOffset, E))2825 return false;2826 2827 // Get LHS pointer, load its value and cast it to the2828 // computation type if necessary.2829 if (!visit(LHS))2830 return false;2831 if (!this->emitLoad(*LT, E))2832 return false;2833 if (LT != LHSComputationT &&2834 !this->emitIntegralCast(*LT, *LHSComputationT, E->getComputationLHSType(),2835 E))2836 return false;2837 2838 // Get the RHS value on the stack.2839 if (!this->emitGetLocal(*RT, TempOffset, E))2840 return false;2841 2842 // Perform operation.2843 switch (E->getOpcode()) {2844 case BO_AddAssign:2845 if (!this->emitAdd(*LHSComputationT, E))2846 return false;2847 break;2848 case BO_SubAssign:2849 if (!this->emitSub(*LHSComputationT, E))2850 return false;2851 break;2852 case BO_MulAssign:2853 if (!this->emitMul(*LHSComputationT, E))2854 return false;2855 break;2856 case BO_DivAssign:2857 if (!this->emitDiv(*LHSComputationT, E))2858 return false;2859 break;2860 case BO_RemAssign:2861 if (!this->emitRem(*LHSComputationT, E))2862 return false;2863 break;2864 case BO_ShlAssign:2865 if (!this->emitShl(*LHSComputationT, *RT, E))2866 return false;2867 break;2868 case BO_ShrAssign:2869 if (!this->emitShr(*LHSComputationT, *RT, E))2870 return false;2871 break;2872 case BO_AndAssign:2873 if (!this->emitBitAnd(*LHSComputationT, E))2874 return false;2875 break;2876 case BO_XorAssign:2877 if (!this->emitBitXor(*LHSComputationT, E))2878 return false;2879 break;2880 case BO_OrAssign:2881 if (!this->emitBitOr(*LHSComputationT, E))2882 return false;2883 break;2884 default:2885 llvm_unreachable("Unimplemented compound assign operator");2886 }2887 2888 // And now cast from LHSComputationT to ResultT.2889 if (ResultT != LHSComputationT &&2890 !this->emitIntegralCast(*LHSComputationT, *ResultT, E->getType(), E))2891 return false;2892 2893 // And store the result in LHS.2894 if (DiscardResult) {2895 if (LHS->refersToBitField())2896 return this->emitStoreBitFieldPop(*ResultT, E);2897 return this->emitStorePop(*ResultT, E);2898 }2899 if (LHS->refersToBitField())2900 return this->emitStoreBitField(*ResultT, E);2901 return this->emitStore(*ResultT, E);2902}2903 2904template <class Emitter>2905bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) {2906 LocalScope<Emitter> ES(this);2907 const Expr *SubExpr = E->getSubExpr();2908 2909 return this->delegate(SubExpr) && ES.destroyLocals(E);2910}2911 2912template <class Emitter>2913bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(2914 const MaterializeTemporaryExpr *E) {2915 const Expr *SubExpr = E->getSubExpr();2916 2917 if (Initializing) {2918 // We already have a value, just initialize that.2919 return this->delegate(SubExpr);2920 }2921 // If we don't end up using the materialized temporary anyway, don't2922 // bother creating it.2923 if (DiscardResult)2924 return this->discard(SubExpr);2925 2926 // When we're initializing a global variable *or* the storage duration of2927 // the temporary is explicitly static, create a global variable.2928 OptPrimType SubExprT = classify(SubExpr);2929 bool IsStatic = E->getStorageDuration() == SD_Static;2930 if (IsStatic) {2931 2932 UnsignedOrNone GlobalIndex = P.createGlobal(E);2933 if (!GlobalIndex)2934 return false;2935 2936 const LifetimeExtendedTemporaryDecl *TempDecl =2937 E->getLifetimeExtendedTemporaryDecl();2938 assert(TempDecl);2939 2940 if (SubExprT) {2941 if (!this->visit(SubExpr))2942 return false;2943 if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))2944 return false;2945 return this->emitGetPtrGlobal(*GlobalIndex, E);2946 }2947 2948 if (!this->checkLiteralType(SubExpr))2949 return false;2950 // Non-primitive values.2951 if (!this->emitGetPtrGlobal(*GlobalIndex, E))2952 return false;2953 if (!this->visitInitializer(SubExpr))2954 return false;2955 return this->emitInitGlobalTempComp(TempDecl, E);2956 }2957 2958 // For everyhing else, use local variables.2959 if (SubExprT) {2960 bool IsConst = SubExpr->getType().isConstQualified();2961 bool IsVolatile = SubExpr->getType().isVolatileQualified();2962 unsigned LocalIndex = allocateLocalPrimitive(2963 E, *SubExprT, IsConst, IsVolatile, E->getExtendingDecl());2964 if (!this->VarScope->LocalsAlwaysEnabled &&2965 !this->emitEnableLocal(LocalIndex, E))2966 return false;2967 2968 if (!this->visit(SubExpr))2969 return false;2970 if (!this->emitSetLocal(*SubExprT, LocalIndex, E))2971 return false;2972 2973 return this->emitGetPtrLocal(LocalIndex, E);2974 }2975 2976 if (!this->checkLiteralType(SubExpr))2977 return false;2978 const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();2979 if (UnsignedOrNone LocalIndex =2980 allocateLocal(E, Inner->getType(), E->getExtendingDecl())) {2981 InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));2982 2983 if (!this->VarScope->LocalsAlwaysEnabled &&2984 !this->emitEnableLocal(*LocalIndex, E))2985 return false;2986 2987 if (!this->emitGetPtrLocal(*LocalIndex, E))2988 return false;2989 return this->visitInitializer(SubExpr) && this->emitFinishInit(E);2990 }2991 return false;2992}2993 2994template <class Emitter>2995bool Compiler<Emitter>::VisitCXXBindTemporaryExpr(2996 const CXXBindTemporaryExpr *E) {2997 const Expr *SubExpr = E->getSubExpr();2998 2999 if (Initializing)3000 return this->delegate(SubExpr);3001 3002 // Make sure we create a temporary even if we're discarding, since that will3003 // make sure we will also call the destructor.3004 3005 if (!this->visit(SubExpr))3006 return false;3007 3008 if (DiscardResult)3009 return this->emitPopPtr(E);3010 return true;3011}3012 3013template <class Emitter>3014bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {3015 const Expr *Init = E->getInitializer();3016 if (DiscardResult)3017 return this->discard(Init);3018 3019 if (Initializing) {3020 // We already have a value, just initialize that.3021 return this->visitInitializer(Init) && this->emitFinishInit(E);3022 }3023 3024 OptPrimType T = classify(E->getType());3025 if (E->isFileScope()) {3026 // Avoid creating a variable if this is a primitive RValue anyway.3027 if (T && !E->isLValue())3028 return this->delegate(Init);3029 3030 UnsignedOrNone GlobalIndex = P.createGlobal(E);3031 if (!GlobalIndex)3032 return false;3033 3034 if (!this->emitGetPtrGlobal(*GlobalIndex, E))3035 return false;3036 3037 // Since this is a global variable, we might've already seen,3038 // don't do it again.3039 if (P.isGlobalInitialized(*GlobalIndex))3040 return true;3041 3042 if (T) {3043 if (!this->visit(Init))3044 return false;3045 return this->emitInitGlobal(*T, *GlobalIndex, E);3046 }3047 3048 return this->visitInitializer(Init) && this->emitFinishInit(E);3049 }3050 3051 // Otherwise, use a local variable.3052 if (T && !E->isLValue()) {3053 // For primitive types, we just visit the initializer.3054 return this->delegate(Init);3055 }3056 3057 unsigned LocalIndex;3058 if (T)3059 LocalIndex = this->allocateLocalPrimitive(Init, *T, /*IsConst=*/false);3060 else if (UnsignedOrNone MaybeIndex = this->allocateLocal(Init))3061 LocalIndex = *MaybeIndex;3062 else3063 return false;3064 3065 if (!this->emitGetPtrLocal(LocalIndex, E))3066 return false;3067 3068 if (T)3069 return this->visit(Init) && this->emitInit(*T, E);3070 return this->visitInitializer(Init) && this->emitFinishInit(E);3071}3072 3073template <class Emitter>3074bool Compiler<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {3075 if (DiscardResult)3076 return true;3077 if (E->isStoredAsBoolean()) {3078 if (E->getType()->isBooleanType())3079 return this->emitConstBool(E->getBoolValue(), E);3080 return this->emitConst(E->getBoolValue(), E);3081 }3082 PrimType T = classifyPrim(E->getType());3083 return this->visitAPValue(E->getAPValue(), T, E);3084}3085 3086template <class Emitter>3087bool Compiler<Emitter>::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {3088 if (DiscardResult)3089 return true;3090 return this->emitConst(E->getValue(), E);3091}3092 3093template <class Emitter>3094bool Compiler<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {3095 if (DiscardResult)3096 return true;3097 3098 assert(Initializing);3099 const Record *R = P.getOrCreateRecord(E->getLambdaClass());3100 if (!R)3101 return false;3102 3103 auto *CaptureInitIt = E->capture_init_begin();3104 // Initialize all fields (which represent lambda captures) of the3105 // record with their initializers.3106 for (const Record::Field &F : R->fields()) {3107 const Expr *Init = *CaptureInitIt;3108 if (!Init || Init->containsErrors())3109 continue;3110 ++CaptureInitIt;3111 3112 if (OptPrimType T = classify(Init)) {3113 if (!this->visit(Init))3114 return false;3115 3116 if (!this->emitInitField(*T, F.Offset, E))3117 return false;3118 } else {3119 if (!this->emitGetPtrField(F.Offset, E))3120 return false;3121 3122 if (!this->visitInitializer(Init))3123 return false;3124 3125 if (!this->emitPopPtr(E))3126 return false;3127 }3128 }3129 3130 return true;3131}3132 3133template <class Emitter>3134bool Compiler<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {3135 if (DiscardResult)3136 return true;3137 3138 if (!Initializing) {3139 unsigned StringIndex = P.createGlobalString(E->getFunctionName(), E);3140 return this->emitGetPtrGlobal(StringIndex, E);3141 }3142 3143 return this->delegate(E->getFunctionName());3144}3145 3146template <class Emitter>3147bool Compiler<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {3148 if (E->getSubExpr() && !this->discard(E->getSubExpr()))3149 return false;3150 3151 return this->emitInvalid(E);3152}3153 3154template <class Emitter>3155bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(3156 const CXXReinterpretCastExpr *E) {3157 const Expr *SubExpr = E->getSubExpr();3158 3159 OptPrimType FromT = classify(SubExpr);3160 OptPrimType ToT = classify(E);3161 3162 if (!FromT || !ToT)3163 return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);3164 3165 if (FromT == PT_Ptr || ToT == PT_Ptr) {3166 // Both types could be PT_Ptr because their expressions are glvalues.3167 OptPrimType PointeeFromT;3168 if (SubExpr->getType()->isPointerOrReferenceType())3169 PointeeFromT = classify(SubExpr->getType()->getPointeeType());3170 else3171 PointeeFromT = classify(SubExpr->getType());3172 3173 OptPrimType PointeeToT;3174 if (E->getType()->isPointerOrReferenceType())3175 PointeeToT = classify(E->getType()->getPointeeType());3176 else3177 PointeeToT = classify(E->getType());3178 3179 bool Fatal = true;3180 if (PointeeToT && PointeeFromT) {3181 if (isIntegralType(*PointeeFromT) && isIntegralType(*PointeeToT))3182 Fatal = false;3183 } else {3184 Fatal = SubExpr->getType().getTypePtr() != E->getType().getTypePtr();3185 }3186 3187 if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))3188 return false;3189 3190 if (E->getCastKind() == CK_LValueBitCast)3191 return this->delegate(SubExpr);3192 return this->VisitCastExpr(E);3193 }3194 3195 // Try to actually do the cast.3196 bool Fatal = (ToT != FromT);3197 if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))3198 return false;3199 3200 return this->VisitCastExpr(E);3201}3202 3203template <class Emitter>3204bool Compiler<Emitter>::VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {3205 3206 if (!Ctx.getLangOpts().CPlusPlus20) {3207 if (!this->emitInvalidCast(CastKind::Dynamic, /*Fatal=*/false, E))3208 return false;3209 }3210 3211 return this->VisitCastExpr(E);3212}3213 3214template <class Emitter>3215bool Compiler<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {3216 assert(E->getType()->isBooleanType());3217 3218 if (DiscardResult)3219 return true;3220 return this->emitConstBool(E->getValue(), E);3221}3222 3223template <class Emitter>3224bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {3225 QualType T = E->getType();3226 assert(!canClassify(T));3227 3228 if (T->isRecordType()) {3229 const CXXConstructorDecl *Ctor = E->getConstructor();3230 3231 // If we're discarding a construct expression, we still need3232 // to allocate a variable and call the constructor and destructor.3233 if (DiscardResult) {3234 if (Ctor->isTrivial())3235 return true;3236 assert(!Initializing);3237 UnsignedOrNone LocalIndex = allocateLocal(E);3238 3239 if (!LocalIndex)3240 return false;3241 3242 if (!this->emitGetPtrLocal(*LocalIndex, E))3243 return false;3244 }3245 3246 // Trivial copy/move constructor. Avoid copy.3247 if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&3248 Ctor->isTrivial() &&3249 E->getArg(0)->isTemporaryObject(Ctx.getASTContext(),3250 T->getAsCXXRecordDecl()))3251 return this->visitInitializer(E->getArg(0));3252 3253 // Zero initialization.3254 bool ZeroInit = E->requiresZeroInitialization();3255 if (ZeroInit) {3256 const Record *R = getRecord(E->getType());3257 3258 if (!this->visitZeroRecordInitializer(R, E))3259 return false;3260 3261 // If the constructor is trivial anyway, we're done.3262 if (Ctor->isTrivial())3263 return true;3264 }3265 3266 // Avoid materializing a temporary for an elidable copy/move constructor.3267 if (!ZeroInit && E->isElidable()) {3268 const Expr *SrcObj = E->getArg(0);3269 assert(SrcObj->isTemporaryObject(Ctx.getASTContext(), Ctor->getParent()));3270 assert(Ctx.getASTContext().hasSameUnqualifiedType(E->getType(),3271 SrcObj->getType()));3272 if (const auto *ME = dyn_cast<MaterializeTemporaryExpr>(SrcObj)) {3273 if (!this->emitCheckFunctionDecl(Ctor, E))3274 return false;3275 return this->visitInitializer(ME->getSubExpr());3276 }3277 }3278 3279 const Function *Func = getFunction(Ctor);3280 3281 if (!Func)3282 return false;3283 3284 assert(Func->hasThisPointer());3285 assert(!Func->hasRVO());3286 3287 // The This pointer is already on the stack because this is an initializer,3288 // but we need to dup() so the call() below has its own copy.3289 if (!this->emitDupPtr(E))3290 return false;3291 3292 // Constructor arguments.3293 for (const auto *Arg : E->arguments()) {3294 if (!this->visit(Arg))3295 return false;3296 }3297 3298 if (Func->isVariadic()) {3299 uint32_t VarArgSize = 0;3300 unsigned NumParams = Func->getNumWrittenParams();3301 for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I) {3302 VarArgSize +=3303 align(primSize(classify(E->getArg(I)->getType()).value_or(PT_Ptr)));3304 }3305 if (!this->emitCallVar(Func, VarArgSize, E))3306 return false;3307 } else {3308 if (!this->emitCall(Func, 0, E)) {3309 // When discarding, we don't need the result anyway, so clean up3310 // the instance dup we did earlier in case surrounding code wants3311 // to keep evaluating.3312 if (DiscardResult)3313 (void)this->emitPopPtr(E);3314 return false;3315 }3316 }3317 3318 if (DiscardResult)3319 return this->emitPopPtr(E);3320 return this->emitFinishInit(E);3321 }3322 3323 if (T->isArrayType()) {3324 const Function *Func = getFunction(E->getConstructor());3325 if (!Func)3326 return false;3327 3328 if (!this->emitDupPtr(E))3329 return false;3330 3331 std::function<bool(QualType)> initArrayDimension;3332 initArrayDimension = [&](QualType T) -> bool {3333 if (!T->isArrayType()) {3334 // Constructor arguments.3335 for (const auto *Arg : E->arguments()) {3336 if (!this->visit(Arg))3337 return false;3338 }3339 3340 return this->emitCall(Func, 0, E);3341 }3342 3343 const ConstantArrayType *CAT =3344 Ctx.getASTContext().getAsConstantArrayType(T);3345 if (!CAT)3346 return false;3347 QualType ElemTy = CAT->getElementType();3348 unsigned NumElems = CAT->getZExtSize();3349 for (size_t I = 0; I != NumElems; ++I) {3350 if (!this->emitConstUint64(I, E))3351 return false;3352 if (!this->emitArrayElemPtrUint64(E))3353 return false;3354 if (!initArrayDimension(ElemTy))3355 return false;3356 }3357 return this->emitPopPtr(E);3358 };3359 3360 return initArrayDimension(E->getType());3361 }3362 3363 return false;3364}3365 3366template <class Emitter>3367bool Compiler<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {3368 if (DiscardResult)3369 return true;3370 3371 const APValue Val =3372 E->EvaluateInContext(Ctx.getASTContext(), SourceLocDefaultExpr);3373 3374 // Things like __builtin_LINE().3375 if (E->getType()->isIntegerType()) {3376 assert(Val.isInt());3377 const APSInt &I = Val.getInt();3378 return this->emitConst(I, E);3379 }3380 // Otherwise, the APValue is an LValue, with only one element.3381 // Theoretically, we don't need the APValue at all of course.3382 assert(E->getType()->isPointerType());3383 assert(Val.isLValue());3384 const APValue::LValueBase &Base = Val.getLValueBase();3385 if (const Expr *LValueExpr = Base.dyn_cast<const Expr *>())3386 return this->visit(LValueExpr);3387 3388 // Otherwise, we have a decl (which is the case for3389 // __builtin_source_location).3390 assert(Base.is<const ValueDecl *>());3391 assert(Val.getLValuePath().size() == 0);3392 const auto *BaseDecl = Base.dyn_cast<const ValueDecl *>();3393 assert(BaseDecl);3394 3395 auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl);3396 3397 UnsignedOrNone GlobalIndex = P.getOrCreateGlobal(UGCD);3398 if (!GlobalIndex)3399 return false;3400 3401 if (!this->emitGetPtrGlobal(*GlobalIndex, E))3402 return false;3403 3404 const Record *R = getRecord(E->getType());3405 const APValue &V = UGCD->getValue();3406 for (unsigned I = 0, N = R->getNumFields(); I != N; ++I) {3407 const Record::Field *F = R->getField(I);3408 const APValue &FieldValue = V.getStructField(I);3409 3410 PrimType FieldT = classifyPrim(F->Decl->getType());3411 3412 if (!this->visitAPValue(FieldValue, FieldT, E))3413 return false;3414 if (!this->emitInitField(FieldT, F->Offset, E))3415 return false;3416 }3417 3418 // Leave the pointer to the global on the stack.3419 return true;3420}3421 3422template <class Emitter>3423bool Compiler<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {3424 unsigned N = E->getNumComponents();3425 if (N == 0)3426 return false;3427 3428 for (unsigned I = 0; I != N; ++I) {3429 const OffsetOfNode &Node = E->getComponent(I);3430 if (Node.getKind() == OffsetOfNode::Array) {3431 const Expr *ArrayIndexExpr = E->getIndexExpr(Node.getArrayExprIndex());3432 PrimType IndexT = classifyPrim(ArrayIndexExpr->getType());3433 3434 if (DiscardResult) {3435 if (!this->discard(ArrayIndexExpr))3436 return false;3437 continue;3438 }3439 3440 if (!this->visit(ArrayIndexExpr))3441 return false;3442 // Cast to Sint64.3443 if (IndexT != PT_Sint64) {3444 if (!this->emitCast(IndexT, PT_Sint64, E))3445 return false;3446 }3447 }3448 }3449 3450 if (DiscardResult)3451 return true;3452 3453 PrimType T = classifyPrim(E->getType());3454 return this->emitOffsetOf(T, E, E);3455}3456 3457template <class Emitter>3458bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(3459 const CXXScalarValueInitExpr *E) {3460 QualType Ty = E->getType();3461 3462 if (DiscardResult || Ty->isVoidType())3463 return true;3464 3465 if (OptPrimType T = classify(Ty))3466 return this->visitZeroInitializer(*T, Ty, E);3467 3468 if (const auto *CT = Ty->getAs<ComplexType>()) {3469 if (!Initializing) {3470 UnsignedOrNone LocalIndex = allocateLocal(E);3471 if (!LocalIndex)3472 return false;3473 if (!this->emitGetPtrLocal(*LocalIndex, E))3474 return false;3475 }3476 3477 // Initialize both fields to 0.3478 QualType ElemQT = CT->getElementType();3479 PrimType ElemT = classifyPrim(ElemQT);3480 3481 for (unsigned I = 0; I != 2; ++I) {3482 if (!this->visitZeroInitializer(ElemT, ElemQT, E))3483 return false;3484 if (!this->emitInitElem(ElemT, I, E))3485 return false;3486 }3487 return true;3488 }3489 3490 if (const auto *VT = Ty->getAs<VectorType>()) {3491 // FIXME: Code duplication with the _Complex case above.3492 if (!Initializing) {3493 UnsignedOrNone LocalIndex = allocateLocal(E);3494 if (!LocalIndex)3495 return false;3496 if (!this->emitGetPtrLocal(*LocalIndex, E))3497 return false;3498 }3499 3500 // Initialize all fields to 0.3501 QualType ElemQT = VT->getElementType();3502 PrimType ElemT = classifyPrim(ElemQT);3503 3504 for (unsigned I = 0, N = VT->getNumElements(); I != N; ++I) {3505 if (!this->visitZeroInitializer(ElemT, ElemQT, E))3506 return false;3507 if (!this->emitInitElem(ElemT, I, E))3508 return false;3509 }3510 return true;3511 }3512 3513 return false;3514}3515 3516template <class Emitter>3517bool Compiler<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {3518 return this->emitConst(E->getPackLength(), E);3519}3520 3521template <class Emitter>3522bool Compiler<Emitter>::VisitGenericSelectionExpr(3523 const GenericSelectionExpr *E) {3524 return this->delegate(E->getResultExpr());3525}3526 3527template <class Emitter>3528bool Compiler<Emitter>::VisitChooseExpr(const ChooseExpr *E) {3529 return this->delegate(E->getChosenSubExpr());3530}3531 3532template <class Emitter>3533bool Compiler<Emitter>::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {3534 if (DiscardResult)3535 return true;3536 3537 return this->emitConst(E->getValue(), E);3538}3539 3540template <class Emitter>3541bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(3542 const CXXInheritedCtorInitExpr *E) {3543 const CXXConstructorDecl *Ctor = E->getConstructor();3544 assert(!Ctor->isTrivial() &&3545 "Trivial CXXInheritedCtorInitExpr, implement. (possible?)");3546 const Function *F = this->getFunction(Ctor);3547 assert(F);3548 assert(!F->hasRVO());3549 assert(F->hasThisPointer());3550 3551 if (!this->emitDupPtr(SourceInfo{}))3552 return false;3553 3554 // Forward all arguments of the current function (which should be a3555 // constructor itself) to the inherited ctor.3556 // This is necessary because the calling code has pushed the pointer3557 // of the correct base for us already, but the arguments need3558 // to come after.3559 unsigned Offset = align(primSize(PT_Ptr)); // instance pointer.3560 for (const ParmVarDecl *PD : Ctor->parameters()) {3561 PrimType PT = this->classify(PD->getType()).value_or(PT_Ptr);3562 3563 if (!this->emitGetParam(PT, Offset, E))3564 return false;3565 Offset += align(primSize(PT));3566 }3567 3568 return this->emitCall(F, 0, E);3569}3570 3571// FIXME: This function has become rather unwieldy, especially3572// the part where we initialize an array allocation of dynamic size.3573template <class Emitter>3574bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {3575 assert(classifyPrim(E->getType()) == PT_Ptr);3576 const Expr *Init = E->getInitializer();3577 QualType ElementType = E->getAllocatedType();3578 OptPrimType ElemT = classify(ElementType);3579 unsigned PlacementArgs = E->getNumPlacementArgs();3580 const FunctionDecl *OperatorNew = E->getOperatorNew();3581 const Expr *PlacementDest = nullptr;3582 bool IsNoThrow = false;3583 3584 if (PlacementArgs != 0) {3585 // FIXME: There is no restriction on this, but it's not clear that any3586 // other form makes any sense. We get here for cases such as:3587 //3588 // new (std::align_val_t{N}) X(int)3589 //3590 // (which should presumably be valid only if N is a multiple of3591 // alignof(int), and in any case can't be deallocated unless N is3592 // alignof(X) and X has new-extended alignment).3593 if (PlacementArgs == 1) {3594 const Expr *Arg1 = E->getPlacementArg(0);3595 if (Arg1->getType()->isNothrowT()) {3596 if (!this->discard(Arg1))3597 return false;3598 IsNoThrow = true;3599 } else {3600 // Invalid unless we have C++26 or are in a std:: function.3601 if (!this->emitInvalidNewDeleteExpr(E, E))3602 return false;3603 3604 // If we have a placement-new destination, we'll later use that instead3605 // of allocating.3606 if (OperatorNew->isReservedGlobalPlacementOperator())3607 PlacementDest = Arg1;3608 }3609 } else {3610 // Always invalid.3611 return this->emitInvalid(E);3612 }3613 } else if (!OperatorNew3614 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation())3615 return this->emitInvalidNewDeleteExpr(E, E);3616 3617 const Descriptor *Desc;3618 if (!PlacementDest) {3619 if (ElemT) {3620 if (E->isArray())3621 Desc = nullptr; // We're not going to use it in this case.3622 else3623 Desc = P.createDescriptor(E, *ElemT, /*SourceTy=*/nullptr,3624 Descriptor::InlineDescMD);3625 } else {3626 Desc = P.createDescriptor(3627 E, ElementType.getTypePtr(),3628 E->isArray() ? std::nullopt : Descriptor::InlineDescMD,3629 /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false,3630 /*IsVolatile=*/false, Init);3631 }3632 }3633 3634 if (E->isArray()) {3635 std::optional<const Expr *> ArraySizeExpr = E->getArraySize();3636 if (!ArraySizeExpr)3637 return false;3638 3639 const Expr *Stripped = *ArraySizeExpr;3640 for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped);3641 Stripped = ICE->getSubExpr())3642 if (ICE->getCastKind() != CK_NoOp &&3643 ICE->getCastKind() != CK_IntegralCast)3644 break;3645 3646 PrimType SizeT = classifyPrim(Stripped->getType());3647 3648 // Save evaluated array size to a variable.3649 unsigned ArrayLen =3650 allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);3651 if (!this->visit(Stripped))3652 return false;3653 if (!this->emitSetLocal(SizeT, ArrayLen, E))3654 return false;3655 3656 if (PlacementDest) {3657 if (!this->visit(PlacementDest))3658 return false;3659 if (!this->emitGetLocal(SizeT, ArrayLen, E))3660 return false;3661 if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))3662 return false;3663 } else {3664 if (!this->emitGetLocal(SizeT, ArrayLen, E))3665 return false;3666 3667 if (ElemT) {3668 // N primitive elements.3669 if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E))3670 return false;3671 } else {3672 // N Composite elements.3673 if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E))3674 return false;3675 }3676 }3677 3678 if (Init) {3679 QualType InitType = Init->getType();3680 size_t StaticInitElems = 0;3681 const Expr *DynamicInit = nullptr;3682 if (const ConstantArrayType *CAT =3683 Ctx.getASTContext().getAsConstantArrayType(InitType)) {3684 StaticInitElems = CAT->getZExtSize();3685 if (!this->visitInitializer(Init))3686 return false;3687 3688 if (const auto *ILE = dyn_cast<InitListExpr>(Init);3689 ILE && ILE->hasArrayFiller())3690 DynamicInit = ILE->getArrayFiller();3691 }3692 3693 // The initializer initializes a certain number of elements, S.3694 // However, the complete number of elements, N, might be larger than that.3695 // In this case, we need to get an initializer for the remaining elements.3696 // There are to cases:3697 // 1) For the form 'new Struct[n];', the initializer is a3698 // CXXConstructExpr and its type is an IncompleteArrayType.3699 // 2) For the form 'new Struct[n]{1,2,3}', the initializer is an3700 // InitListExpr and the initializer for the remaining elements3701 // is the array filler.3702 3703 if (DynamicInit || InitType->isIncompleteArrayType()) {3704 const Function *CtorFunc = nullptr;3705 if (const auto *CE = dyn_cast<CXXConstructExpr>(Init)) {3706 CtorFunc = getFunction(CE->getConstructor());3707 if (!CtorFunc)3708 return false;3709 } else if (!DynamicInit)3710 DynamicInit = Init;3711 3712 LabelTy EndLabel = this->getLabel();3713 LabelTy StartLabel = this->getLabel();3714 3715 // In the nothrow case, the alloc above might have returned nullptr.3716 // Don't call any constructors that case.3717 if (IsNoThrow) {3718 if (!this->emitDupPtr(E))3719 return false;3720 if (!this->emitNullPtr(0, nullptr, E))3721 return false;3722 if (!this->emitEQPtr(E))3723 return false;3724 if (!this->jumpTrue(EndLabel))3725 return false;3726 }3727 3728 // Create loop variables.3729 unsigned Iter =3730 allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);3731 if (!this->emitConst(StaticInitElems, SizeT, E))3732 return false;3733 if (!this->emitSetLocal(SizeT, Iter, E))3734 return false;3735 3736 this->fallthrough(StartLabel);3737 this->emitLabel(StartLabel);3738 // Condition. Iter < ArrayLen?3739 if (!this->emitGetLocal(SizeT, Iter, E))3740 return false;3741 if (!this->emitGetLocal(SizeT, ArrayLen, E))3742 return false;3743 if (!this->emitLT(SizeT, E))3744 return false;3745 if (!this->jumpFalse(EndLabel))3746 return false;3747 3748 // Pointer to the allocated array is already on the stack.3749 if (!this->emitGetLocal(SizeT, Iter, E))3750 return false;3751 if (!this->emitArrayElemPtr(SizeT, E))3752 return false;3753 3754 if (isa_and_nonnull<ImplicitValueInitExpr>(DynamicInit) &&3755 DynamicInit->getType()->isArrayType()) {3756 QualType ElemType =3757 DynamicInit->getType()->getAsArrayTypeUnsafe()->getElementType();3758 PrimType InitT = classifyPrim(ElemType);3759 if (!this->visitZeroInitializer(InitT, ElemType, E))3760 return false;3761 if (!this->emitStorePop(InitT, E))3762 return false;3763 } else if (DynamicInit) {3764 if (OptPrimType InitT = classify(DynamicInit)) {3765 if (!this->visit(DynamicInit))3766 return false;3767 if (!this->emitStorePop(*InitT, E))3768 return false;3769 } else {3770 if (!this->visitInitializer(DynamicInit))3771 return false;3772 if (!this->emitPopPtr(E))3773 return false;3774 }3775 } else {3776 assert(CtorFunc);3777 if (!this->emitCall(CtorFunc, 0, E))3778 return false;3779 }3780 3781 // ++Iter;3782 if (!this->emitGetPtrLocal(Iter, E))3783 return false;3784 if (!this->emitIncPop(SizeT, false, E))3785 return false;3786 3787 if (!this->jump(StartLabel))3788 return false;3789 3790 this->fallthrough(EndLabel);3791 this->emitLabel(EndLabel);3792 }3793 }3794 } else { // Non-array.3795 if (PlacementDest) {3796 if (!this->visit(PlacementDest))3797 return false;3798 if (!this->emitCheckNewTypeMismatch(E, E))3799 return false;3800 3801 } else {3802 // Allocate just one element.3803 if (!this->emitAlloc(Desc, E))3804 return false;3805 }3806 3807 if (Init) {3808 if (ElemT) {3809 if (!this->visit(Init))3810 return false;3811 3812 if (!this->emitInit(*ElemT, E))3813 return false;3814 } else {3815 // Composite.3816 if (!this->visitInitializer(Init))3817 return false;3818 }3819 }3820 }3821 3822 if (DiscardResult)3823 return this->emitPopPtr(E);3824 3825 return true;3826}3827 3828template <class Emitter>3829bool Compiler<Emitter>::VisitCXXDeleteExpr(const CXXDeleteExpr *E) {3830 const Expr *Arg = E->getArgument();3831 3832 const FunctionDecl *OperatorDelete = E->getOperatorDelete();3833 3834 if (!OperatorDelete->isUsableAsGlobalAllocationFunctionInConstantEvaluation())3835 return this->emitInvalidNewDeleteExpr(E, E);3836 3837 // Arg must be an lvalue.3838 if (!this->visit(Arg))3839 return false;3840 3841 return this->emitFree(E->isArrayForm(), E->isGlobalDelete(), E);3842}3843 3844template <class Emitter>3845bool Compiler<Emitter>::VisitBlockExpr(const BlockExpr *E) {3846 if (DiscardResult)3847 return true;3848 3849 const Function *Func = nullptr;3850 if (const Function *F = Ctx.getOrCreateObjCBlock(E))3851 Func = F;3852 3853 if (!Func)3854 return false;3855 return this->emitGetFnPtr(Func, E);3856}3857 3858template <class Emitter>3859bool Compiler<Emitter>::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {3860 const Type *TypeInfoType = E->getType().getTypePtr();3861 3862 auto canonType = [](const Type *T) {3863 return T->getCanonicalTypeUnqualified().getTypePtr();3864 };3865 3866 if (!E->isPotentiallyEvaluated()) {3867 if (DiscardResult)3868 return true;3869 3870 if (E->isTypeOperand())3871 return this->emitGetTypeid(3872 canonType(E->getTypeOperand(Ctx.getASTContext()).getTypePtr()),3873 TypeInfoType, E);3874 3875 return this->emitGetTypeid(3876 canonType(E->getExprOperand()->getType().getTypePtr()), TypeInfoType,3877 E);3878 }3879 3880 // Otherwise, we need to evaluate the expression operand.3881 assert(E->getExprOperand());3882 assert(E->getExprOperand()->isLValue());3883 3884 if (!Ctx.getLangOpts().CPlusPlus20 && !this->emitDiagTypeid(E))3885 return false;3886 3887 if (!this->visit(E->getExprOperand()))3888 return false;3889 3890 if (!this->emitGetTypeidPtr(TypeInfoType, E))3891 return false;3892 if (DiscardResult)3893 return this->emitPopPtr(E);3894 return true;3895}3896 3897template <class Emitter>3898bool Compiler<Emitter>::VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {3899 assert(Ctx.getLangOpts().CPlusPlus);3900 return this->emitConstBool(E->getValue(), E);3901}3902 3903template <class Emitter>3904bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {3905 if (DiscardResult)3906 return true;3907 assert(!Initializing);3908 3909 const MSGuidDecl *GuidDecl = E->getGuidDecl();3910 const RecordDecl *RD = GuidDecl->getType()->getAsRecordDecl();3911 assert(RD);3912 // If the definiton of the result type is incomplete, just return a dummy.3913 // If (and when) that is read from, we will fail, but not now.3914 if (!RD->isCompleteDefinition())3915 return this->emitDummyPtr(GuidDecl, E);3916 3917 UnsignedOrNone GlobalIndex = P.getOrCreateGlobal(GuidDecl);3918 if (!GlobalIndex)3919 return false;3920 if (!this->emitGetPtrGlobal(*GlobalIndex, E))3921 return false;3922 3923 assert(this->getRecord(E->getType()));3924 3925 const APValue &V = GuidDecl->getAsAPValue();3926 if (V.getKind() == APValue::None)3927 return true;3928 3929 assert(V.isStruct());3930 assert(V.getStructNumBases() == 0);3931 if (!this->visitAPValueInitializer(V, E, E->getType()))3932 return false;3933 3934 return this->emitFinishInit(E);3935}3936 3937template <class Emitter>3938bool Compiler<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {3939 assert(classifyPrim(E->getType()) == PT_Bool);3940 if (E->isValueDependent())3941 return false;3942 if (DiscardResult)3943 return true;3944 return this->emitConstBool(E->isSatisfied(), E);3945}3946 3947template <class Emitter>3948bool Compiler<Emitter>::VisitConceptSpecializationExpr(3949 const ConceptSpecializationExpr *E) {3950 assert(classifyPrim(E->getType()) == PT_Bool);3951 if (DiscardResult)3952 return true;3953 return this->emitConstBool(E->isSatisfied(), E);3954}3955 3956template <class Emitter>3957bool Compiler<Emitter>::VisitCXXRewrittenBinaryOperator(3958 const CXXRewrittenBinaryOperator *E) {3959 return this->delegate(E->getSemanticForm());3960}3961 3962template <class Emitter>3963bool Compiler<Emitter>::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {3964 3965 for (const Expr *SemE : E->semantics()) {3966 if (auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) {3967 if (SemE == E->getResultExpr())3968 return false;3969 3970 if (OVE->isUnique())3971 continue;3972 3973 if (!this->discard(OVE))3974 return false;3975 } else if (SemE == E->getResultExpr()) {3976 if (!this->delegate(SemE))3977 return false;3978 } else {3979 if (!this->discard(SemE))3980 return false;3981 }3982 }3983 return true;3984}3985 3986template <class Emitter>3987bool Compiler<Emitter>::VisitPackIndexingExpr(const PackIndexingExpr *E) {3988 return this->delegate(E->getSelectedExpr());3989}3990 3991template <class Emitter>3992bool Compiler<Emitter>::VisitRecoveryExpr(const RecoveryExpr *E) {3993 return this->emitError(E);3994}3995 3996template <class Emitter>3997bool Compiler<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {3998 assert(E->getType()->isVoidPointerType());3999 if (DiscardResult)4000 return true;4001 4002 return this->emitDummyPtr(E, E);4003}4004 4005template <class Emitter>4006bool Compiler<Emitter>::VisitConvertVectorExpr(const ConvertVectorExpr *E) {4007 assert(Initializing);4008 const auto *VT = E->getType()->castAs<VectorType>();4009 QualType ElemType = VT->getElementType();4010 PrimType ElemT = classifyPrim(ElemType);4011 const Expr *Src = E->getSrcExpr();4012 QualType SrcType = Src->getType();4013 PrimType SrcElemT = classifyVectorElementType(SrcType);4014 4015 unsigned SrcOffset =4016 this->allocateLocalPrimitive(Src, PT_Ptr, /*IsConst=*/true);4017 if (!this->visit(Src))4018 return false;4019 if (!this->emitSetLocal(PT_Ptr, SrcOffset, E))4020 return false;4021 4022 for (unsigned I = 0; I != VT->getNumElements(); ++I) {4023 if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))4024 return false;4025 if (!this->emitArrayElemPop(SrcElemT, I, E))4026 return false;4027 4028 // Cast to the desired result element type.4029 if (SrcElemT != ElemT) {4030 if (!this->emitPrimCast(SrcElemT, ElemT, ElemType, E))4031 return false;4032 } else if (ElemType->isFloatingType() && SrcType != ElemType) {4033 const auto *TargetSemantics = &Ctx.getFloatSemantics(ElemType);4034 if (!this->emitCastFP(TargetSemantics, getRoundingMode(E), E))4035 return false;4036 }4037 if (!this->emitInitElem(ElemT, I, E))4038 return false;4039 }4040 4041 return true;4042}4043 4044template <class Emitter>4045bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {4046 // FIXME: Unary shuffle with mask not currently supported.4047 if (E->getNumSubExprs() == 2)4048 return this->emitInvalid(E);4049 4050 assert(Initializing);4051 assert(E->getNumSubExprs() > 2);4052 4053 const Expr *Vecs[] = {E->getExpr(0), E->getExpr(1)};4054 const VectorType *VT = Vecs[0]->getType()->castAs<VectorType>();4055 PrimType ElemT = classifyPrim(VT->getElementType());4056 unsigned NumInputElems = VT->getNumElements();4057 unsigned NumOutputElems = E->getNumSubExprs() - 2;4058 assert(NumOutputElems > 0);4059 4060 // Save both input vectors to a local variable.4061 unsigned VectorOffsets[2];4062 for (unsigned I = 0; I != 2; ++I) {4063 VectorOffsets[I] =4064 this->allocateLocalPrimitive(Vecs[I], PT_Ptr, /*IsConst=*/true);4065 if (!this->visit(Vecs[I]))4066 return false;4067 if (!this->emitSetLocal(PT_Ptr, VectorOffsets[I], E))4068 return false;4069 }4070 for (unsigned I = 0; I != NumOutputElems; ++I) {4071 APSInt ShuffleIndex = E->getShuffleMaskIdx(I);4072 assert(ShuffleIndex >= -1);4073 if (ShuffleIndex == -1)4074 return this->emitInvalidShuffleVectorIndex(I, E);4075 4076 assert(ShuffleIndex < (NumInputElems * 2));4077 if (!this->emitGetLocal(PT_Ptr,4078 VectorOffsets[ShuffleIndex >= NumInputElems], E))4079 return false;4080 unsigned InputVectorIndex = ShuffleIndex.getZExtValue() % NumInputElems;4081 if (!this->emitArrayElemPop(ElemT, InputVectorIndex, E))4082 return false;4083 4084 if (!this->emitInitElem(ElemT, I, E))4085 return false;4086 }4087 4088 return true;4089}4090 4091template <class Emitter>4092bool Compiler<Emitter>::VisitExtVectorElementExpr(4093 const ExtVectorElementExpr *E) {4094 const Expr *Base = E->getBase();4095 assert(4096 Base->getType()->isVectorType() ||4097 Base->getType()->getAs<PointerType>()->getPointeeType()->isVectorType());4098 4099 SmallVector<uint32_t, 4> Indices;4100 E->getEncodedElementAccess(Indices);4101 4102 if (Indices.size() == 1) {4103 if (!this->visit(Base))4104 return false;4105 4106 if (E->isGLValue()) {4107 if (!this->emitConstUint32(Indices[0], E))4108 return false;4109 return this->emitArrayElemPtrPop(PT_Uint32, E);4110 }4111 // Else, also load the value.4112 return this->emitArrayElemPop(classifyPrim(E->getType()), Indices[0], E);4113 }4114 4115 // Create a local variable for the base.4116 unsigned BaseOffset = allocateLocalPrimitive(Base, PT_Ptr, /*IsConst=*/true);4117 if (!this->visit(Base))4118 return false;4119 if (!this->emitSetLocal(PT_Ptr, BaseOffset, E))4120 return false;4121 4122 // Now the vector variable for the return value.4123 if (!Initializing) {4124 UnsignedOrNone ResultIndex = allocateLocal(E);4125 if (!ResultIndex)4126 return false;4127 if (!this->emitGetPtrLocal(*ResultIndex, E))4128 return false;4129 }4130 4131 assert(Indices.size() == E->getType()->getAs<VectorType>()->getNumElements());4132 4133 PrimType ElemT =4134 classifyPrim(E->getType()->getAs<VectorType>()->getElementType());4135 uint32_t DstIndex = 0;4136 for (uint32_t I : Indices) {4137 if (!this->emitGetLocal(PT_Ptr, BaseOffset, E))4138 return false;4139 if (!this->emitArrayElemPop(ElemT, I, E))4140 return false;4141 if (!this->emitInitElem(ElemT, DstIndex, E))4142 return false;4143 ++DstIndex;4144 }4145 4146 // Leave the result pointer on the stack.4147 assert(!DiscardResult);4148 return true;4149}4150 4151template <class Emitter>4152bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {4153 const Expr *SubExpr = E->getSubExpr();4154 if (!E->isExpressibleAsConstantInitializer())4155 return this->discard(SubExpr) && this->emitInvalid(E);4156 4157 if (DiscardResult)4158 return true;4159 4160 assert(classifyPrim(E) == PT_Ptr);4161 return this->emitDummyPtr(E, E);4162}4163 4164template <class Emitter>4165bool Compiler<Emitter>::VisitCXXStdInitializerListExpr(4166 const CXXStdInitializerListExpr *E) {4167 const Expr *SubExpr = E->getSubExpr();4168 const ConstantArrayType *ArrayType =4169 Ctx.getASTContext().getAsConstantArrayType(SubExpr->getType());4170 const Record *R = getRecord(E->getType());4171 assert(Initializing);4172 assert(SubExpr->isGLValue());4173 4174 if (!this->visit(SubExpr))4175 return false;4176 if (!this->emitConstUint8(0, E))4177 return false;4178 if (!this->emitArrayElemPtrPopUint8(E))4179 return false;4180 if (!this->emitInitFieldPtr(R->getField(0u)->Offset, E))4181 return false;4182 4183 PrimType SecondFieldT = classifyPrim(R->getField(1u)->Decl->getType());4184 if (isIntegralType(SecondFieldT)) {4185 if (!this->emitConst(ArrayType->getSize(), SecondFieldT, E))4186 return false;4187 return this->emitInitField(SecondFieldT, R->getField(1u)->Offset, E);4188 }4189 assert(SecondFieldT == PT_Ptr);4190 4191 if (!this->emitGetFieldPtr(R->getField(0u)->Offset, E))4192 return false;4193 if (!this->emitExpandPtr(E))4194 return false;4195 if (!this->emitConst(ArrayType->getSize(), PT_Uint64, E))4196 return false;4197 if (!this->emitArrayElemPtrPop(PT_Uint64, E))4198 return false;4199 return this->emitInitFieldPtr(R->getField(1u)->Offset, E);4200}4201 4202template <class Emitter>4203bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {4204 LocalScope<Emitter> BS(this);4205 StmtExprScope<Emitter> SS(this);4206 4207 const CompoundStmt *CS = E->getSubStmt();4208 const Stmt *Result = CS->body_back();4209 for (const Stmt *S : CS->body()) {4210 if (S != Result) {4211 if (!this->visitStmt(S))4212 return false;4213 continue;4214 }4215 4216 assert(S == Result);4217 if (const Expr *ResultExpr = dyn_cast<Expr>(S))4218 return this->delegate(ResultExpr);4219 return this->emitUnsupported(E);4220 }4221 4222 return BS.destroyLocals();4223}4224 4225template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {4226 OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,4227 /*NewInitializing=*/false, /*ToLValue=*/false);4228 return this->Visit(E);4229}4230 4231template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {4232 // We're basically doing:4233 // OptionScope<Emitter> Scope(this, DicardResult, Initializing, ToLValue);4234 // but that's unnecessary of course.4235 return this->Visit(E);4236}4237 4238static const Expr *stripCheckedDerivedToBaseCasts(const Expr *E) {4239 if (const auto *PE = dyn_cast<ParenExpr>(E))4240 return stripCheckedDerivedToBaseCasts(PE->getSubExpr());4241 4242 if (const auto *CE = dyn_cast<CastExpr>(E);4243 CE &&4244 (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))4245 return stripCheckedDerivedToBaseCasts(CE->getSubExpr());4246 4247 return E;4248}4249 4250static const Expr *stripDerivedToBaseCasts(const Expr *E) {4251 if (const auto *PE = dyn_cast<ParenExpr>(E))4252 return stripDerivedToBaseCasts(PE->getSubExpr());4253 4254 if (const auto *CE = dyn_cast<CastExpr>(E);4255 CE && (CE->getCastKind() == CK_DerivedToBase ||4256 CE->getCastKind() == CK_UncheckedDerivedToBase ||4257 CE->getCastKind() == CK_NoOp))4258 return stripDerivedToBaseCasts(CE->getSubExpr());4259 4260 return E;4261}4262 4263template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {4264 if (E->getType().isNull())4265 return false;4266 4267 if (E->getType()->isVoidType())4268 return this->discard(E);4269 4270 // Create local variable to hold the return value.4271 if (!E->isGLValue() && !canClassify(E->getType())) {4272 UnsignedOrNone LocalIndex = allocateLocal(stripDerivedToBaseCasts(E));4273 if (!LocalIndex)4274 return false;4275 4276 if (!this->emitGetPtrLocal(*LocalIndex, E))4277 return false;4278 InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));4279 return this->visitInitializer(E);4280 }4281 4282 // Otherwise,we have a primitive return value, produce the value directly4283 // and push it on the stack.4284 OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,4285 /*NewInitializing=*/false, /*ToLValue=*/ToLValue);4286 return this->Visit(E);4287}4288 4289template <class Emitter>4290bool Compiler<Emitter>::visitInitializer(const Expr *E) {4291 assert(!canClassify(E->getType()));4292 4293 OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,4294 /*NewInitializing=*/true, /*ToLValue=*/false);4295 return this->Visit(E);4296}4297 4298template <class Emitter> bool Compiler<Emitter>::visitAsLValue(const Expr *E) {4299 OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,4300 /*NewInitializing=*/false, /*ToLValue=*/true);4301 return this->Visit(E);4302}4303 4304template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {4305 OptPrimType T = classify(E->getType());4306 if (!T) {4307 // Convert complex values to bool.4308 if (E->getType()->isAnyComplexType()) {4309 if (!this->visit(E))4310 return false;4311 return this->emitComplexBoolCast(E);4312 }4313 return false;4314 }4315 4316 if (!this->visit(E))4317 return false;4318 4319 if (T == PT_Bool)4320 return true;4321 4322 // Convert pointers to bool.4323 if (T == PT_Ptr)4324 return this->emitIsNonNullPtr(E);4325 4326 // Or Floats.4327 if (T == PT_Float)4328 return this->emitCastFloatingIntegralBool(getFPOptions(E), E);4329 4330 // Or anything else we can.4331 return this->emitCast(*T, PT_Bool, E);4332}4333 4334template <class Emitter>4335bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,4336 const Expr *E) {4337 if (const auto *AT = QT->getAs<AtomicType>())4338 QT = AT->getValueType();4339 4340 switch (T) {4341 case PT_Bool:4342 return this->emitZeroBool(E);4343 case PT_Sint8:4344 return this->emitZeroSint8(E);4345 case PT_Uint8:4346 return this->emitZeroUint8(E);4347 case PT_Sint16:4348 return this->emitZeroSint16(E);4349 case PT_Uint16:4350 return this->emitZeroUint16(E);4351 case PT_Sint32:4352 return this->emitZeroSint32(E);4353 case PT_Uint32:4354 return this->emitZeroUint32(E);4355 case PT_Sint64:4356 return this->emitZeroSint64(E);4357 case PT_Uint64:4358 return this->emitZeroUint64(E);4359 case PT_IntAP:4360 return this->emitZeroIntAP(Ctx.getBitWidth(QT), E);4361 case PT_IntAPS:4362 return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E);4363 case PT_Ptr:4364 return this->emitNullPtr(Ctx.getASTContext().getTargetNullPointerValue(QT),4365 nullptr, E);4366 case PT_MemberPtr:4367 return this->emitNullMemberPtr(0, nullptr, E);4368 case PT_Float: {4369 APFloat F = APFloat::getZero(Ctx.getFloatSemantics(QT));4370 return this->emitFloat(F, E);4371 }4372 case PT_FixedPoint: {4373 auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());4374 return this->emitConstFixedPoint(FixedPoint::zero(Sem), E);4375 }4376 }4377 llvm_unreachable("unknown primitive type");4378}4379 4380template <class Emitter>4381bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,4382 const Expr *E) {4383 assert(E);4384 assert(R);4385 // Fields4386 for (const Record::Field &Field : R->fields()) {4387 if (Field.isUnnamedBitField())4388 continue;4389 4390 const Descriptor *D = Field.Desc;4391 if (D->isPrimitive()) {4392 QualType QT = D->getType();4393 PrimType T = classifyPrim(D->getType());4394 if (!this->visitZeroInitializer(T, QT, E))4395 return false;4396 if (R->isUnion()) {4397 if (!this->emitInitFieldActivate(T, Field.Offset, E))4398 return false;4399 break;4400 }4401 if (!this->emitInitField(T, Field.Offset, E))4402 return false;4403 continue;4404 }4405 4406 if (!this->emitGetPtrField(Field.Offset, E))4407 return false;4408 4409 if (D->isPrimitiveArray()) {4410 QualType ET = D->getElemQualType();4411 PrimType T = classifyPrim(ET);4412 for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) {4413 if (!this->visitZeroInitializer(T, ET, E))4414 return false;4415 if (!this->emitInitElem(T, I, E))4416 return false;4417 }4418 } else if (D->isCompositeArray()) {4419 // Can't be a vector or complex field.4420 if (!this->visitZeroArrayInitializer(D->getType(), E))4421 return false;4422 } else if (D->isRecord()) {4423 if (!this->visitZeroRecordInitializer(D->ElemRecord, E))4424 return false;4425 } else4426 return false;4427 4428 // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the4429 // object's first non-static named data member is zero-initialized4430 if (R->isUnion()) {4431 if (!this->emitFinishInitActivatePop(E))4432 return false;4433 break;4434 }4435 if (!this->emitFinishInitPop(E))4436 return false;4437 }4438 4439 for (const Record::Base &B : R->bases()) {4440 if (!this->emitGetPtrBase(B.Offset, E))4441 return false;4442 if (!this->visitZeroRecordInitializer(B.R, E))4443 return false;4444 if (!this->emitFinishInitPop(E))4445 return false;4446 }4447 4448 // FIXME: Virtual bases.4449 4450 return true;4451}4452 4453template <class Emitter>4454bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {4455 assert(T->isArrayType() || T->isAnyComplexType() || T->isVectorType());4456 const ArrayType *AT = T->getAsArrayTypeUnsafe();4457 QualType ElemType = AT->getElementType();4458 size_t NumElems = cast<ConstantArrayType>(AT)->getZExtSize();4459 4460 if (OptPrimType ElemT = classify(ElemType)) {4461 for (size_t I = 0; I != NumElems; ++I) {4462 if (!this->visitZeroInitializer(*ElemT, ElemType, E))4463 return false;4464 if (!this->emitInitElem(*ElemT, I, E))4465 return false;4466 }4467 return true;4468 }4469 if (ElemType->isRecordType()) {4470 const Record *R = getRecord(ElemType);4471 4472 for (size_t I = 0; I != NumElems; ++I) {4473 if (!this->emitConstUint32(I, E))4474 return false;4475 if (!this->emitArrayElemPtr(PT_Uint32, E))4476 return false;4477 if (!this->visitZeroRecordInitializer(R, E))4478 return false;4479 if (!this->emitPopPtr(E))4480 return false;4481 }4482 return true;4483 }4484 if (ElemType->isArrayType()) {4485 for (size_t I = 0; I != NumElems; ++I) {4486 if (!this->emitConstUint32(I, E))4487 return false;4488 if (!this->emitArrayElemPtr(PT_Uint32, E))4489 return false;4490 if (!this->visitZeroArrayInitializer(ElemType, E))4491 return false;4492 if (!this->emitPopPtr(E))4493 return false;4494 }4495 return true;4496 }4497 4498 return false;4499}4500 4501template <class Emitter>4502bool Compiler<Emitter>::visitAssignment(const Expr *LHS, const Expr *RHS,4503 const Expr *E) {4504 if (!canClassify(E->getType()))4505 return false;4506 4507 if (!this->visit(RHS))4508 return false;4509 if (!this->visit(LHS))4510 return false;4511 4512 if (LHS->getType().isVolatileQualified())4513 return this->emitInvalidStore(LHS->getType().getTypePtr(), E);4514 4515 // We don't support assignments in C.4516 if (!Ctx.getLangOpts().CPlusPlus && !this->emitInvalid(E))4517 return false;4518 4519 PrimType RHT = classifyPrim(RHS);4520 bool Activates = refersToUnion(LHS);4521 bool BitField = LHS->refersToBitField();4522 4523 if (!this->emitFlip(PT_Ptr, RHT, E))4524 return false;4525 4526 if (DiscardResult) {4527 if (BitField && Activates)4528 return this->emitStoreBitFieldActivatePop(RHT, E);4529 if (BitField)4530 return this->emitStoreBitFieldPop(RHT, E);4531 if (Activates)4532 return this->emitStoreActivatePop(RHT, E);4533 // Otherwise, regular non-activating store.4534 return this->emitStorePop(RHT, E);4535 }4536 4537 auto maybeLoad = [&](bool Result) -> bool {4538 if (!Result)4539 return false;4540 // Assignments aren't necessarily lvalues in C.4541 // Load from them in that case.4542 if (!E->isLValue())4543 return this->emitLoadPop(RHT, E);4544 return true;4545 };4546 4547 if (BitField && Activates)4548 return maybeLoad(this->emitStoreBitFieldActivate(RHT, E));4549 if (BitField)4550 return maybeLoad(this->emitStoreBitField(RHT, E));4551 if (Activates)4552 return maybeLoad(this->emitStoreActivate(RHT, E));4553 // Otherwise, regular non-activating store.4554 return maybeLoad(this->emitStore(RHT, E));4555}4556 4557template <class Emitter>4558template <typename T>4559bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {4560 switch (Ty) {4561 case PT_Sint8:4562 return this->emitConstSint8(Value, E);4563 case PT_Uint8:4564 return this->emitConstUint8(Value, E);4565 case PT_Sint16:4566 return this->emitConstSint16(Value, E);4567 case PT_Uint16:4568 return this->emitConstUint16(Value, E);4569 case PT_Sint32:4570 return this->emitConstSint32(Value, E);4571 case PT_Uint32:4572 return this->emitConstUint32(Value, E);4573 case PT_Sint64:4574 return this->emitConstSint64(Value, E);4575 case PT_Uint64:4576 return this->emitConstUint64(Value, E);4577 case PT_Bool:4578 return this->emitConstBool(Value, E);4579 case PT_Ptr:4580 case PT_MemberPtr:4581 case PT_Float:4582 case PT_IntAP:4583 case PT_IntAPS:4584 case PT_FixedPoint:4585 llvm_unreachable("Invalid integral type");4586 break;4587 }4588 llvm_unreachable("unknown primitive type");4589}4590 4591template <class Emitter>4592template <typename T>4593bool Compiler<Emitter>::emitConst(T Value, const Expr *E) {4594 return this->emitConst(Value, classifyPrim(E->getType()), E);4595}4596 4597template <class Emitter>4598bool Compiler<Emitter>::emitConst(const APSInt &Value, PrimType Ty,4599 const Expr *E) {4600 if (Ty == PT_IntAPS)4601 return this->emitConstIntAPS(Value, E);4602 if (Ty == PT_IntAP)4603 return this->emitConstIntAP(Value, E);4604 4605 if (Value.isSigned())4606 return this->emitConst(Value.getSExtValue(), Ty, E);4607 return this->emitConst(Value.getZExtValue(), Ty, E);4608}4609 4610template <class Emitter>4611bool Compiler<Emitter>::emitConst(const APInt &Value, PrimType Ty,4612 const Expr *E) {4613 if (Ty == PT_IntAPS)4614 return this->emitConstIntAPS(Value, E);4615 if (Ty == PT_IntAP)4616 return this->emitConstIntAP(Value, E);4617 4618 if (isSignedType(Ty))4619 return this->emitConst(Value.getSExtValue(), Ty, E);4620 return this->emitConst(Value.getZExtValue(), Ty, E);4621}4622 4623template <class Emitter>4624bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) {4625 return this->emitConst(Value, classifyPrim(E->getType()), E);4626}4627 4628template <class Emitter>4629unsigned Compiler<Emitter>::allocateLocalPrimitive(4630 DeclTy &&Src, PrimType Ty, bool IsConst, bool IsVolatile,4631 const ValueDecl *ExtendingDecl, ScopeKind SC, bool IsConstexprUnknown) {4632 // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.4633 // (int){12} in C. Consider using Expr::isTemporaryObject() instead4634 // or isa<MaterializeTemporaryExpr>().4635 Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD,4636 IsConst, isa<const Expr *>(Src),4637 /*IsMutable=*/false, IsVolatile);4638 D->IsConstexprUnknown = IsConstexprUnknown;4639 Scope::Local Local = this->createLocal(D);4640 if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))4641 Locals.insert({VD, Local});4642 if (ExtendingDecl)4643 VarScope->addExtended(Local, ExtendingDecl);4644 else4645 VarScope->addForScopeKind(Local, SC);4646 return Local.Offset;4647}4648 4649template <class Emitter>4650UnsignedOrNone Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,4651 const ValueDecl *ExtendingDecl,4652 ScopeKind SC,4653 bool IsConstexprUnknown) {4654 const ValueDecl *Key = nullptr;4655 const Expr *Init = nullptr;4656 bool IsTemporary = false;4657 if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {4658 Key = VD;4659 4660 if (const auto *VarD = dyn_cast<VarDecl>(VD))4661 Init = VarD->getInit();4662 }4663 if (auto *E = Src.dyn_cast<const Expr *>()) {4664 IsTemporary = true;4665 if (Ty.isNull())4666 Ty = E->getType();4667 }4668 4669 Descriptor *D = P.createDescriptor(4670 Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),4671 IsTemporary, /*IsMutable=*/false, /*IsVolatile=*/false, Init);4672 if (!D)4673 return std::nullopt;4674 D->IsConstexprUnknown = IsConstexprUnknown;4675 4676 Scope::Local Local = this->createLocal(D);4677 if (Key)4678 Locals.insert({Key, Local});4679 if (ExtendingDecl)4680 VarScope->addExtended(Local, ExtendingDecl);4681 else4682 VarScope->addForScopeKind(Local, SC);4683 return Local.Offset;4684}4685 4686template <class Emitter>4687UnsignedOrNone Compiler<Emitter>::allocateTemporary(const Expr *E) {4688 QualType Ty = E->getType();4689 assert(!Ty->isRecordType());4690 4691 Descriptor *D = P.createDescriptor(4692 E, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),4693 /*IsTemporary=*/true);4694 4695 if (!D)4696 return std::nullopt;4697 4698 Scope::Local Local = this->createLocal(D);4699 VariableScope<Emitter> *S = VarScope;4700 assert(S);4701 // Attach to topmost scope.4702 while (S->getParent())4703 S = S->getParent();4704 assert(S && !S->getParent());4705 S->addLocal(Local);4706 return Local.Offset;4707}4708 4709template <class Emitter>4710const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) {4711 if (const PointerType *PT = dyn_cast<PointerType>(Ty))4712 return PT->getPointeeType()->getAsCanonical<RecordType>();4713 return Ty->getAsCanonical<RecordType>();4714}4715 4716template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) {4717 if (const auto *RecordTy = getRecordTy(Ty))4718 return getRecord(RecordTy->getDecl()->getDefinitionOrSelf());4719 return nullptr;4720}4721 4722template <class Emitter>4723Record *Compiler<Emitter>::getRecord(const RecordDecl *RD) {4724 return P.getOrCreateRecord(RD);4725}4726 4727template <class Emitter>4728const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) {4729 return Ctx.getOrCreateFunction(FD);4730}4731 4732template <class Emitter>4733bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) {4734 LocalScope<Emitter> RootScope(this);4735 4736 // If we won't destroy the toplevel scope, check for memory leaks first.4737 if (!DestroyToplevelScope) {4738 if (!this->emitCheckAllocations(E))4739 return false;4740 }4741 4742 auto maybeDestroyLocals = [&]() -> bool {4743 if (DestroyToplevelScope)4744 return RootScope.destroyLocals() && this->emitCheckAllocations(E);4745 return this->emitCheckAllocations(E);4746 };4747 4748 // Void expressions.4749 if (E->getType()->isVoidType()) {4750 if (!visit(E))4751 return false;4752 return this->emitRetVoid(E) && maybeDestroyLocals();4753 }4754 4755 // Expressions with a primitive return type.4756 if (OptPrimType T = classify(E)) {4757 if (!visit(E))4758 return false;4759 4760 return this->emitRet(*T, E) && maybeDestroyLocals();4761 }4762 4763 // Expressions with a composite return type.4764 // For us, that means everything we don't4765 // have a PrimType for.4766 if (UnsignedOrNone LocalOffset = this->allocateLocal(E)) {4767 InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalOffset));4768 if (!this->emitGetPtrLocal(*LocalOffset, E))4769 return false;4770 4771 if (!visitInitializer(E))4772 return false;4773 4774 if (!this->emitFinishInit(E))4775 return false;4776 // We are destroying the locals AFTER the Ret op.4777 // The Ret op needs to copy the (alive) values, but the4778 // destructors may still turn the entire expression invalid.4779 return this->emitRetValue(E) && maybeDestroyLocals();4780 }4781 4782 return maybeDestroyLocals() && this->emitCheckAllocations(E) && false;4783}4784 4785template <class Emitter>4786VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,4787 bool IsConstexprUnknown) {4788 4789 auto R = this->visitVarDecl(VD, VD->getInit(), /*Toplevel=*/true,4790 IsConstexprUnknown);4791 4792 if (R.notCreated())4793 return R;4794 4795 if (R)4796 return true;4797 4798 if (!R && Context::shouldBeGloballyIndexed(VD)) {4799 if (auto GlobalIndex = P.getGlobal(VD)) {4800 Block *GlobalBlock = P.getGlobal(*GlobalIndex);4801 GlobalInlineDescriptor &GD =4802 *reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());4803 4804 GD.InitState = GlobalInitState::InitializerFailed;4805 GlobalBlock->invokeDtor();4806 }4807 }4808 4809 return R;4810}4811 4812/// Toplevel visitDeclAndReturn().4813/// We get here from evaluateAsInitializer().4814/// We need to evaluate the initializer and return its value.4815template <class Emitter>4816bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, const Expr *Init,4817 bool ConstantContext) {4818 // We only create variables if we're evaluating in a constant context.4819 // Otherwise, just evaluate the initializer and return it.4820 if (!ConstantContext) {4821 DeclScope<Emitter> LS(this, VD);4822 if (!this->visit(Init))4823 return false;4824 return this->emitRet(classify(Init).value_or(PT_Ptr), VD) &&4825 LS.destroyLocals() && this->emitCheckAllocations(VD);4826 }4827 4828 LocalScope<Emitter> VDScope(this, VD);4829 if (!this->visitVarDecl(VD, Init, /*Toplevel=*/true))4830 return false;4831 4832 OptPrimType VarT = classify(VD->getType());4833 if (Context::shouldBeGloballyIndexed(VD)) {4834 auto GlobalIndex = P.getGlobal(VD);4835 assert(GlobalIndex); // visitVarDecl() didn't return false.4836 if (VarT) {4837 if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD))4838 return false;4839 } else {4840 if (!this->emitGetPtrGlobal(*GlobalIndex, VD))4841 return false;4842 }4843 } else {4844 auto Local = Locals.find(VD);4845 assert(Local != Locals.end()); // Same here.4846 if (VarT) {4847 if (!this->emitGetLocal(*VarT, Local->second.Offset, VD))4848 return false;4849 } else {4850 if (!this->emitGetPtrLocal(Local->second.Offset, VD))4851 return false;4852 }4853 }4854 4855 // Return the value.4856 if (!this->emitRet(VarT.value_or(PT_Ptr), VD)) {4857 // If the Ret above failed and this is a global variable, mark it as4858 // uninitialized, even everything else succeeded.4859 if (Context::shouldBeGloballyIndexed(VD)) {4860 auto GlobalIndex = P.getGlobal(VD);4861 assert(GlobalIndex);4862 Block *GlobalBlock = P.getGlobal(*GlobalIndex);4863 GlobalInlineDescriptor &GD =4864 *reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());4865 4866 GD.InitState = GlobalInitState::InitializerFailed;4867 GlobalBlock->invokeDtor();4868 }4869 return false;4870 }4871 4872 return VDScope.destroyLocals() && this->emitCheckAllocations(VD);4873}4874 4875template <class Emitter>4876VarCreationState4877Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init,4878 bool Toplevel, bool IsConstexprUnknown) {4879 // We don't know what to do with these, so just return false.4880 if (VD->getType().isNull())4881 return false;4882 4883 // This case is EvalEmitter-only. If we won't create any instructions for the4884 // initializer anyway, don't bother creating the variable in the first place.4885 if (!this->isActive())4886 return VarCreationState::NotCreated();4887 4888 OptPrimType VarT = classify(VD->getType());4889 4890 if (Init && Init->isValueDependent())4891 return false;4892 4893 if (Context::shouldBeGloballyIndexed(VD)) {4894 auto checkDecl = [&]() -> bool {4895 bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();4896 return !NeedsOp || this->emitCheckDecl(VD, VD);4897 };4898 4899 DeclScope<Emitter> LocalScope(this, VD);4900 4901 UnsignedOrNone GlobalIndex = P.getGlobal(VD);4902 if (GlobalIndex) {4903 // We've already seen and initialized this global.4904 if (P.getPtrGlobal(*GlobalIndex).isInitialized())4905 return checkDecl();4906 // The previous attempt at initialization might've been unsuccessful,4907 // so let's try this one.4908 } else if ((GlobalIndex = P.createGlobal(VD, Init))) {4909 } else {4910 return false;4911 }4912 if (!Init)4913 return true;4914 4915 if (!checkDecl())4916 return false;4917 4918 if (VarT) {4919 if (!this->visit(Init))4920 return false;4921 4922 return this->emitInitGlobal(*VarT, *GlobalIndex, VD);4923 }4924 4925 if (!this->emitGetPtrGlobal(*GlobalIndex, Init))4926 return false;4927 4928 if (!visitInitializer(Init))4929 return false;4930 4931 return this->emitFinishInitGlobal(Init);4932 }4933 // Local variables.4934 InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));4935 4936 if (VarT) {4937 unsigned Offset = this->allocateLocalPrimitive(4938 VD, *VarT, VD->getType().isConstQualified(),4939 VD->getType().isVolatileQualified(), nullptr, ScopeKind::Block,4940 IsConstexprUnknown);4941 4942 if (!Init)4943 return true;4944 4945 // If this is a toplevel declaration, create a scope for the4946 // initializer.4947 if (Toplevel) {4948 LocalScope<Emitter> Scope(this);4949 if (!this->visit(Init))4950 return false;4951 return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();4952 }4953 if (!this->visit(Init))4954 return false;4955 return this->emitSetLocal(*VarT, Offset, VD);4956 }4957 // Local composite variables.4958 if (UnsignedOrNone Offset = this->allocateLocal(4959 VD, VD->getType(), nullptr, ScopeKind::Block, IsConstexprUnknown)) {4960 if (!Init)4961 return true;4962 4963 if (!this->emitGetPtrLocal(*Offset, Init))4964 return false;4965 4966 if (!visitInitializer(Init))4967 return false;4968 4969 return this->emitFinishInitPop(Init);4970 }4971 return false;4972}4973 4974template <class Emitter>4975bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,4976 const Expr *E) {4977 assert(!DiscardResult);4978 if (Val.isInt())4979 return this->emitConst(Val.getInt(), ValType, E);4980 if (Val.isFloat()) {4981 APFloat F = Val.getFloat();4982 return this->emitFloat(F, E);4983 }4984 4985 if (Val.isLValue()) {4986 if (Val.isNullPointer())4987 return this->emitNull(ValType, 0, nullptr, E);4988 APValue::LValueBase Base = Val.getLValueBase();4989 if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())4990 return this->visit(BaseExpr);4991 if (const auto *VD = Base.dyn_cast<const ValueDecl *>())4992 return this->visitDeclRef(VD, E);4993 } else if (Val.isMemberPointer()) {4994 if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())4995 return this->emitGetMemberPtr(MemberDecl, E);4996 return this->emitNullMemberPtr(0, nullptr, E);4997 }4998 4999 return false;5000}5001 5002template <class Emitter>5003bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,5004 const Expr *E, QualType T) {5005 if (Val.isStruct()) {5006 const Record *R = this->getRecord(T);5007 assert(R);5008 for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) {5009 const APValue &F = Val.getStructField(I);5010 const Record::Field *RF = R->getField(I);5011 QualType FieldType = RF->Decl->getType();5012 5013 if (OptPrimType PT = classify(FieldType)) {5014 if (!this->visitAPValue(F, *PT, E))5015 return false;5016 if (!this->emitInitField(*PT, RF->Offset, E))5017 return false;5018 } else {5019 if (!this->emitGetPtrField(RF->Offset, E))5020 return false;5021 if (!this->visitAPValueInitializer(F, E, FieldType))5022 return false;5023 if (!this->emitPopPtr(E))5024 return false;5025 }5026 }5027 return true;5028 }5029 if (Val.isUnion()) {5030 const FieldDecl *UnionField = Val.getUnionField();5031 const Record *R = this->getRecord(UnionField->getParent());5032 assert(R);5033 const APValue &F = Val.getUnionValue();5034 const Record::Field *RF = R->getField(UnionField);5035 PrimType T = classifyPrim(RF->Decl->getType());5036 if (!this->visitAPValue(F, T, E))5037 return false;5038 return this->emitInitField(T, RF->Offset, E);5039 }5040 if (Val.isArray()) {5041 const auto *ArrType = T->getAsArrayTypeUnsafe();5042 QualType ElemType = ArrType->getElementType();5043 for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {5044 const APValue &Elem = Val.getArrayInitializedElt(A);5045 if (OptPrimType ElemT = classify(ElemType)) {5046 if (!this->visitAPValue(Elem, *ElemT, E))5047 return false;5048 if (!this->emitInitElem(*ElemT, A, E))5049 return false;5050 } else {5051 if (!this->emitConstUint32(A, E))5052 return false;5053 if (!this->emitArrayElemPtrUint32(E))5054 return false;5055 if (!this->visitAPValueInitializer(Elem, E, ElemType))5056 return false;5057 if (!this->emitPopPtr(E))5058 return false;5059 }5060 }5061 return true;5062 }5063 // TODO: Other types.5064 5065 return false;5066}5067 5068template <class Emitter>5069bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,5070 unsigned BuiltinID) {5071 if (BuiltinID == Builtin::BI__builtin_constant_p) {5072 // Void argument is always invalid and harder to handle later.5073 if (E->getArg(0)->getType()->isVoidType()) {5074 if (DiscardResult)5075 return true;5076 return this->emitConst(0, E);5077 }5078 5079 if (!this->emitStartSpeculation(E))5080 return false;5081 LabelTy EndLabel = this->getLabel();5082 if (!this->speculate(E, EndLabel))5083 return false;5084 this->fallthrough(EndLabel);5085 if (!this->emitEndSpeculation(E))5086 return false;5087 if (DiscardResult)5088 return this->emitPop(classifyPrim(E), E);5089 return true;5090 }5091 5092 // For these, we're expected to ultimately return an APValue pointing5093 // to the CallExpr. This is needed to get the correct codegen.5094 if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||5095 BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||5096 BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||5097 BuiltinID == Builtin::BI__builtin_function_start) {5098 if (DiscardResult)5099 return true;5100 return this->emitDummyPtr(E, E);5101 }5102 5103 QualType ReturnType = E->getType();5104 OptPrimType ReturnT = classify(E);5105 5106 // Non-primitive return type. Prepare storage.5107 if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {5108 UnsignedOrNone LocalIndex = allocateLocal(E);5109 if (!LocalIndex)5110 return false;5111 if (!this->emitGetPtrLocal(*LocalIndex, E))5112 return false;5113 }5114 5115 // Prepare function arguments including special cases.5116 switch (BuiltinID) {5117 case Builtin::BI__builtin_object_size:5118 case Builtin::BI__builtin_dynamic_object_size: {5119 assert(E->getNumArgs() == 2);5120 const Expr *Arg0 = E->getArg(0);5121 if (Arg0->isGLValue()) {5122 if (!this->visit(Arg0))5123 return false;5124 5125 } else {5126 if (!this->visitAsLValue(Arg0))5127 return false;5128 }5129 if (!this->visit(E->getArg(1)))5130 return false;5131 5132 } break;5133 default:5134 if (!Context::isUnevaluatedBuiltin(BuiltinID)) {5135 // Put arguments on the stack.5136 for (const auto *Arg : E->arguments()) {5137 if (!this->visit(Arg))5138 return false;5139 }5140 }5141 }5142 5143 if (!this->emitCallBI(E, BuiltinID, E))5144 return false;5145 5146 if (DiscardResult && !ReturnType->isVoidType()) {5147 assert(ReturnT);5148 return this->emitPop(*ReturnT, E);5149 }5150 5151 return true;5152}5153 5154template <class Emitter>5155bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {5156 const FunctionDecl *FuncDecl = E->getDirectCallee();5157 5158 if (FuncDecl) {5159 if (unsigned BuiltinID = FuncDecl->getBuiltinID())5160 return VisitBuiltinCallExpr(E, BuiltinID);5161 5162 // Calls to replaceable operator new/operator delete.5163 if (FuncDecl->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {5164 if (FuncDecl->getDeclName().isAnyOperatorNew())5165 return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new);5166 assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);5167 return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);5168 }5169 5170 // Explicit calls to trivial destructors5171 if (const auto *DD = dyn_cast<CXXDestructorDecl>(FuncDecl);5172 DD && DD->isTrivial()) {5173 const auto *MemberCall = cast<CXXMemberCallExpr>(E);5174 if (!this->visit(MemberCall->getImplicitObjectArgument()))5175 return false;5176 return this->emitCheckDestruction(E) && this->emitEndLifetime(E) &&5177 this->emitPopPtr(E);5178 }5179 }5180 5181 LocalScope<Emitter> CallScope(this, ScopeKind::Call);5182 5183 QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());5184 OptPrimType T = classify(ReturnType);5185 bool HasRVO = !ReturnType->isVoidType() && !T;5186 5187 if (HasRVO) {5188 if (DiscardResult) {5189 // If we need to discard the return value but the function returns its5190 // value via an RVO pointer, we need to create one such pointer just5191 // for this call.5192 if (UnsignedOrNone LocalIndex = allocateLocal(E)) {5193 if (!this->emitGetPtrLocal(*LocalIndex, E))5194 return false;5195 }5196 } else {5197 // We need the result. Prepare a pointer to return or5198 // dup the current one.5199 if (!Initializing) {5200 if (UnsignedOrNone LocalIndex = allocateLocal(E)) {5201 if (!this->emitGetPtrLocal(*LocalIndex, E))5202 return false;5203 }5204 }5205 if (!this->emitDupPtr(E))5206 return false;5207 }5208 }5209 5210 SmallVector<const Expr *, 8> Args(ArrayRef(E->getArgs(), E->getNumArgs()));5211 5212 bool IsAssignmentOperatorCall = false;5213 if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);5214 OCE && OCE->isAssignmentOp()) {5215 // Just like with regular assignments, we need to special-case assignment5216 // operators here and evaluate the RHS (the second arg) before the LHS (the5217 // first arg). We fix this by using a Flip op later.5218 assert(Args.size() == 2);5219 IsAssignmentOperatorCall = true;5220 std::reverse(Args.begin(), Args.end());5221 }5222 // Calling a static operator will still5223 // pass the instance, but we don't need it.5224 // Discard it here.5225 if (isa<CXXOperatorCallExpr>(E)) {5226 if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FuncDecl);5227 MD && MD->isStatic()) {5228 if (!this->discard(E->getArg(0)))5229 return false;5230 // Drop first arg.5231 Args.erase(Args.begin());5232 }5233 }5234 5235 bool Devirtualized = false;5236 UnsignedOrNone CalleeOffset = std::nullopt;5237 // Add the (optional, implicit) This pointer.5238 if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {5239 if (!FuncDecl && classifyPrim(E->getCallee()) == PT_MemberPtr) {5240 // If we end up creating a CallPtr op for this, we need the base of the5241 // member pointer as the instance pointer, and later extract the function5242 // decl as the function pointer.5243 const Expr *Callee = E->getCallee();5244 CalleeOffset =5245 this->allocateLocalPrimitive(Callee, PT_MemberPtr, /*IsConst=*/true);5246 if (!this->visit(Callee))5247 return false;5248 if (!this->emitSetLocal(PT_MemberPtr, *CalleeOffset, E))5249 return false;5250 if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))5251 return false;5252 if (!this->emitGetMemberPtrBase(E))5253 return false;5254 } else {5255 const auto *InstancePtr = MC->getImplicitObjectArgument();5256 if (isa_and_nonnull<CXXDestructorDecl>(CompilingFunction) ||5257 isa_and_nonnull<CXXConstructorDecl>(CompilingFunction)) {5258 const auto *Stripped = stripCheckedDerivedToBaseCasts(InstancePtr);5259 if (isa<CXXThisExpr>(Stripped)) {5260 FuncDecl =5261 cast<CXXMethodDecl>(FuncDecl)->getCorrespondingMethodInClass(5262 Stripped->getType()->getPointeeType()->getAsCXXRecordDecl());5263 Devirtualized = true;5264 if (!this->visit(Stripped))5265 return false;5266 } else {5267 if (!this->visit(InstancePtr))5268 return false;5269 }5270 } else {5271 if (!this->visit(InstancePtr))5272 return false;5273 }5274 }5275 } else if (const auto *PD =5276 dyn_cast<CXXPseudoDestructorExpr>(E->getCallee())) {5277 if (!this->emitCheckPseudoDtor(E))5278 return false;5279 const Expr *Base = PD->getBase();5280 // E.g. `using T = int; 0.~T();`.5281 if (OptPrimType BaseT = classify(Base); !BaseT || BaseT != PT_Ptr)5282 return this->discard(Base);5283 if (!this->visit(Base))5284 return false;5285 return this->emitEndLifetimePop(E);5286 } else if (!FuncDecl) {5287 const Expr *Callee = E->getCallee();5288 CalleeOffset =5289 this->allocateLocalPrimitive(Callee, PT_Ptr, /*IsConst=*/true);5290 if (!this->visit(Callee))5291 return false;5292 if (!this->emitSetLocal(PT_Ptr, *CalleeOffset, E))5293 return false;5294 }5295 5296 if (!this->visitCallArgs(Args, FuncDecl, IsAssignmentOperatorCall,5297 isa<CXXOperatorCallExpr>(E)))5298 return false;5299 5300 // Undo the argument reversal we did earlier.5301 if (IsAssignmentOperatorCall) {5302 assert(Args.size() == 2);5303 PrimType Arg1T = classify(Args[0]).value_or(PT_Ptr);5304 PrimType Arg2T = classify(Args[1]).value_or(PT_Ptr);5305 if (!this->emitFlip(Arg2T, Arg1T, E))5306 return false;5307 }5308 5309 if (FuncDecl) {5310 const Function *Func = getFunction(FuncDecl);5311 if (!Func)5312 return false;5313 5314 // In error cases, the function may be called with fewer arguments than5315 // parameters.5316 if (E->getNumArgs() < Func->getNumWrittenParams())5317 return false;5318 5319 assert(HasRVO == Func->hasRVO());5320 5321 bool HasQualifier = false;5322 if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee()))5323 HasQualifier = ME->hasQualifier();5324 5325 bool IsVirtual = false;5326 if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))5327 IsVirtual = !Devirtualized && MD->isVirtual();5328 5329 // In any case call the function. The return value will end up on the stack5330 // and if the function has RVO, we already have the pointer on the stack to5331 // write the result into.5332 if (IsVirtual && !HasQualifier) {5333 uint32_t VarArgSize = 0;5334 unsigned NumParams =5335 Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);5336 for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)5337 VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));5338 5339 if (!this->emitCallVirt(Func, VarArgSize, E))5340 return false;5341 } else if (Func->isVariadic()) {5342 uint32_t VarArgSize = 0;5343 unsigned NumParams =5344 Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);5345 for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)5346 VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));5347 if (!this->emitCallVar(Func, VarArgSize, E))5348 return false;5349 } else {5350 if (!this->emitCall(Func, 0, E))5351 return false;5352 }5353 } else {5354 // Indirect call. Visit the callee, which will leave a FunctionPointer on5355 // the stack. Cleanup of the returned value if necessary will be done after5356 // the function call completed.5357 5358 // Sum the size of all args from the call expr.5359 uint32_t ArgSize = 0;5360 for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)5361 ArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));5362 5363 // Get the callee, either from a member pointer or function pointer saved in5364 // CalleeOffset.5365 if (isa<CXXMemberCallExpr>(E) && CalleeOffset) {5366 if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))5367 return false;5368 if (!this->emitGetMemberPtrDecl(E))5369 return false;5370 } else {5371 if (!this->emitGetLocal(PT_Ptr, *CalleeOffset, E))5372 return false;5373 }5374 if (!this->emitCallPtr(ArgSize, E, E))5375 return false;5376 }5377 5378 // Cleanup for discarded return values.5379 if (DiscardResult && !ReturnType->isVoidType() && T)5380 return this->emitPop(*T, E) && CallScope.destroyLocals();5381 5382 return CallScope.destroyLocals();5383}5384 5385template <class Emitter>5386bool Compiler<Emitter>::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {5387 SourceLocScope<Emitter> SLS(this, E);5388 5389 return this->delegate(E->getExpr());5390}5391 5392template <class Emitter>5393bool Compiler<Emitter>::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {5394 SourceLocScope<Emitter> SLS(this, E);5395 5396 return this->delegate(E->getExpr());5397}5398 5399template <class Emitter>5400bool Compiler<Emitter>::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {5401 if (DiscardResult)5402 return true;5403 5404 return this->emitConstBool(E->getValue(), E);5405}5406 5407template <class Emitter>5408bool Compiler<Emitter>::VisitCXXNullPtrLiteralExpr(5409 const CXXNullPtrLiteralExpr *E) {5410 if (DiscardResult)5411 return true;5412 5413 uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());5414 return this->emitNullPtr(Val, nullptr, E);5415}5416 5417template <class Emitter>5418bool Compiler<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) {5419 if (DiscardResult)5420 return true;5421 5422 assert(E->getType()->isIntegerType());5423 5424 PrimType T = classifyPrim(E->getType());5425 return this->emitZero(T, E);5426}5427 5428template <class Emitter>5429bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {5430 if (DiscardResult)5431 return true;5432 5433 if (this->LambdaThisCapture.Offset > 0) {5434 if (this->LambdaThisCapture.IsPtr)5435 return this->emitGetThisFieldPtr(this->LambdaThisCapture.Offset, E);5436 return this->emitGetPtrThisField(this->LambdaThisCapture.Offset, E);5437 }5438 5439 // In some circumstances, the 'this' pointer does not actually refer to the5440 // instance pointer of the current function frame, but e.g. to the declaration5441 // currently being initialized. Here we emit the necessary instruction(s) for5442 // this scenario.5443 if (!InitStackActive || InitStack.empty())5444 return this->emitThis(E);5445 5446 // If our init stack is, for example:5447 // 0 Stack: 3 (decl)5448 // 1 Stack: 6 (init list)5449 // 2 Stack: 1 (field)5450 // 3 Stack: 6 (init list)5451 // 4 Stack: 1 (field)5452 //5453 // We want to find the LAST element in it that's an init list,5454 // which is marked with the K_InitList marker. The index right5455 // before that points to an init list. We need to find the5456 // elements before the K_InitList element that point to a base5457 // (e.g. a decl or This), optionally followed by field, elem, etc.5458 // In the example above, we want to emit elements [0..2].5459 unsigned StartIndex = 0;5460 unsigned EndIndex = 0;5461 // Find the init list.5462 for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {5463 if (InitStack[StartIndex].Kind == InitLink::K_DIE) {5464 EndIndex = StartIndex;5465 --StartIndex;5466 break;5467 }5468 }5469 5470 // Walk backwards to find the base.5471 for (; StartIndex > 0; --StartIndex) {5472 if (InitStack[StartIndex].Kind == InitLink::K_InitList)5473 continue;5474 5475 if (InitStack[StartIndex].Kind != InitLink::K_Field &&5476 InitStack[StartIndex].Kind != InitLink::K_Elem &&5477 InitStack[StartIndex].Kind != InitLink::K_DIE)5478 break;5479 }5480 5481 if (StartIndex == 0 && EndIndex == 0)5482 EndIndex = InitStack.size() - 1;5483 5484 assert(StartIndex < EndIndex);5485 5486 // Emit the instructions.5487 for (unsigned I = StartIndex; I != (EndIndex + 1); ++I) {5488 if (InitStack[I].Kind == InitLink::K_InitList ||5489 InitStack[I].Kind == InitLink::K_DIE)5490 continue;5491 if (!InitStack[I].template emit<Emitter>(this, E))5492 return false;5493 }5494 return true;5495}5496 5497template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) {5498 switch (S->getStmtClass()) {5499 case Stmt::CompoundStmtClass:5500 return visitCompoundStmt(cast<CompoundStmt>(S));5501 case Stmt::DeclStmtClass:5502 return visitDeclStmt(cast<DeclStmt>(S), /*EvaluateConditionDecl=*/true);5503 case Stmt::ReturnStmtClass:5504 return visitReturnStmt(cast<ReturnStmt>(S));5505 case Stmt::IfStmtClass:5506 return visitIfStmt(cast<IfStmt>(S));5507 case Stmt::WhileStmtClass:5508 return visitWhileStmt(cast<WhileStmt>(S));5509 case Stmt::DoStmtClass:5510 return visitDoStmt(cast<DoStmt>(S));5511 case Stmt::ForStmtClass:5512 return visitForStmt(cast<ForStmt>(S));5513 case Stmt::CXXForRangeStmtClass:5514 return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));5515 case Stmt::BreakStmtClass:5516 return visitBreakStmt(cast<BreakStmt>(S));5517 case Stmt::ContinueStmtClass:5518 return visitContinueStmt(cast<ContinueStmt>(S));5519 case Stmt::SwitchStmtClass:5520 return visitSwitchStmt(cast<SwitchStmt>(S));5521 case Stmt::CaseStmtClass:5522 return visitCaseStmt(cast<CaseStmt>(S));5523 case Stmt::DefaultStmtClass:5524 return visitDefaultStmt(cast<DefaultStmt>(S));5525 case Stmt::AttributedStmtClass:5526 return visitAttributedStmt(cast<AttributedStmt>(S));5527 case Stmt::CXXTryStmtClass:5528 return visitCXXTryStmt(cast<CXXTryStmt>(S));5529 case Stmt::NullStmtClass:5530 return true;5531 // Always invalid statements.5532 case Stmt::GCCAsmStmtClass:5533 case Stmt::MSAsmStmtClass:5534 case Stmt::GotoStmtClass:5535 return this->emitInvalid(S);5536 case Stmt::LabelStmtClass:5537 return this->visitStmt(cast<LabelStmt>(S)->getSubStmt());5538 default: {5539 if (const auto *E = dyn_cast<Expr>(S))5540 return this->discard(E);5541 return false;5542 }5543 }5544}5545 5546template <class Emitter>5547bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {5548 LocalScope<Emitter> Scope(this);5549 for (const auto *InnerStmt : S->body())5550 if (!visitStmt(InnerStmt))5551 return false;5552 return Scope.destroyLocals();5553}5554 5555template <class Emitter>5556bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {5557 if (auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) {5558 for (auto *BD : DD->flat_bindings())5559 if (auto *KD = BD->getHoldingVar();5560 KD && !this->visitVarDecl(KD, KD->getInit()))5561 return false;5562 }5563 return true;5564}5565 5566static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) {5567 assert(FD);5568 assert(FD->getParent()->isUnion());5569 const auto *CXXRD = dyn_cast<CXXRecordDecl>(FD->getParent());5570 return !CXXRD || CXXRD->hasTrivialDefaultConstructor();5571}5572 5573template <class Emitter> bool Compiler<Emitter>::refersToUnion(const Expr *E) {5574 for (;;) {5575 if (const auto *ME = dyn_cast<MemberExpr>(E)) {5576 if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());5577 FD && FD->getParent()->isUnion() && hasTrivialDefaultCtorParent(FD))5578 return true;5579 E = ME->getBase();5580 continue;5581 }5582 5583 if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {5584 E = ASE->getBase()->IgnoreImplicit();5585 continue;5586 }5587 5588 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);5589 ICE && (ICE->getCastKind() == CK_NoOp ||5590 ICE->getCastKind() == CK_DerivedToBase ||5591 ICE->getCastKind() == CK_UncheckedDerivedToBase)) {5592 E = ICE->getSubExpr();5593 continue;5594 }5595 5596 if (const auto *This = dyn_cast<CXXThisExpr>(E)) {5597 const auto *ThisRecord =5598 This->getType()->getPointeeType()->getAsRecordDecl();5599 if (!ThisRecord->isUnion())5600 return false;5601 // Otherwise, always activate if we're in the ctor.5602 if (const auto *Ctor =5603 dyn_cast_if_present<CXXConstructorDecl>(CompilingFunction))5604 return Ctor->getParent() == ThisRecord;5605 return false;5606 }5607 5608 break;5609 }5610 return false;5611}5612 5613template <class Emitter>5614bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,5615 bool EvaluateConditionDecl) {5616 for (const auto *D : DS->decls()) {5617 if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, BaseUsingDecl,5618 FunctionDecl, NamespaceAliasDecl, UsingDirectiveDecl>(D))5619 continue;5620 5621 const auto *VD = dyn_cast<VarDecl>(D);5622 if (!VD)5623 return false;5624 if (!this->visitVarDecl(VD, VD->getInit()))5625 return false;5626 5627 // Register decomposition decl holding vars.5628 if (EvaluateConditionDecl && !this->maybeEmitDeferredVarInit(VD))5629 return false;5630 }5631 5632 return true;5633}5634 5635template <class Emitter>5636bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {5637 if (this->InStmtExpr)5638 return this->emitUnsupported(RS);5639 5640 if (const Expr *RE = RS->getRetValue()) {5641 LocalScope<Emitter> RetScope(this);5642 if (ReturnType) {5643 // Primitive types are simply returned.5644 if (!this->visit(RE))5645 return false;5646 this->emitCleanup();5647 return this->emitRet(*ReturnType, RS);5648 }5649 5650 if (RE->getType()->isVoidType()) {5651 if (!this->visit(RE))5652 return false;5653 } else {5654 InitLinkScope<Emitter> ILS(this, InitLink::RVO());5655 // RVO - construct the value in the return location.5656 if (!this->emitRVOPtr(RE))5657 return false;5658 if (!this->visitInitializer(RE))5659 return false;5660 if (!this->emitPopPtr(RE))5661 return false;5662 5663 this->emitCleanup();5664 return this->emitRetVoid(RS);5665 }5666 }5667 5668 // Void return.5669 this->emitCleanup();5670 return this->emitRetVoid(RS);5671}5672 5673template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {5674 auto visitChildStmt = [&](const Stmt *S) -> bool {5675 LocalScope<Emitter> SScope(this);5676 if (!visitStmt(S))5677 return false;5678 return SScope.destroyLocals();5679 };5680 if (auto *CondInit = IS->getInit())5681 if (!visitStmt(CondInit))5682 return false;5683 5684 if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())5685 if (!visitDeclStmt(CondDecl))5686 return false;5687 5688 // Save ourselves compiling some code and the jumps, etc. if the condition is5689 // stataically known to be either true or false. We could look at more cases5690 // here, but I think all the ones that actually happen are using a5691 // ConstantExpr.5692 if (std::optional<bool> BoolValue = getBoolValue(IS->getCond())) {5693 if (*BoolValue)5694 return visitChildStmt(IS->getThen());5695 if (const Stmt *Else = IS->getElse())5696 return visitChildStmt(Else);5697 return true;5698 }5699 5700 // Otherwise, compile the condition.5701 if (IS->isNonNegatedConsteval()) {5702 if (!this->emitIsConstantContext(IS))5703 return false;5704 } else if (IS->isNegatedConsteval()) {5705 if (!this->emitIsConstantContext(IS))5706 return false;5707 if (!this->emitInv(IS))5708 return false;5709 } else {5710 if (!this->visitBool(IS->getCond()))5711 return false;5712 }5713 5714 if (!this->maybeEmitDeferredVarInit(IS->getConditionVariable()))5715 return false;5716 5717 if (const Stmt *Else = IS->getElse()) {5718 LabelTy LabelElse = this->getLabel();5719 LabelTy LabelEnd = this->getLabel();5720 if (!this->jumpFalse(LabelElse))5721 return false;5722 if (!visitChildStmt(IS->getThen()))5723 return false;5724 if (!this->jump(LabelEnd))5725 return false;5726 this->emitLabel(LabelElse);5727 if (!visitChildStmt(Else))5728 return false;5729 this->emitLabel(LabelEnd);5730 } else {5731 LabelTy LabelEnd = this->getLabel();5732 if (!this->jumpFalse(LabelEnd))5733 return false;5734 if (!visitChildStmt(IS->getThen()))5735 return false;5736 this->emitLabel(LabelEnd);5737 }5738 5739 return true;5740}5741 5742template <class Emitter>5743bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {5744 const Expr *Cond = S->getCond();5745 const Stmt *Body = S->getBody();5746 5747 LabelTy CondLabel = this->getLabel(); // Label before the condition.5748 LabelTy EndLabel = this->getLabel(); // Label after the loop.5749 LocalScope<Emitter> WholeLoopScope(this);5750 LoopScope<Emitter> LS(this, S, EndLabel, CondLabel);5751 5752 this->fallthrough(CondLabel);5753 this->emitLabel(CondLabel);5754 5755 {5756 LocalScope<Emitter> CondScope(this);5757 if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())5758 if (!visitDeclStmt(CondDecl))5759 return false;5760 5761 if (!this->visitBool(Cond))5762 return false;5763 5764 if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))5765 return false;5766 5767 if (!this->jumpFalse(EndLabel))5768 return false;5769 5770 if (!this->visitStmt(Body))5771 return false;5772 5773 if (!CondScope.destroyLocals())5774 return false;5775 }5776 if (!this->jump(CondLabel))5777 return false;5778 this->fallthrough(EndLabel);5779 this->emitLabel(EndLabel);5780 return WholeLoopScope.destroyLocals();5781}5782 5783template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {5784 const Expr *Cond = S->getCond();5785 const Stmt *Body = S->getBody();5786 5787 LabelTy StartLabel = this->getLabel();5788 LabelTy EndLabel = this->getLabel();5789 LabelTy CondLabel = this->getLabel();5790 LocalScope<Emitter> WholeLoopScope(this);5791 LoopScope<Emitter> LS(this, S, EndLabel, CondLabel);5792 5793 this->fallthrough(StartLabel);5794 this->emitLabel(StartLabel);5795 5796 {5797 LocalScope<Emitter> CondScope(this);5798 if (!this->visitStmt(Body))5799 return false;5800 this->fallthrough(CondLabel);5801 this->emitLabel(CondLabel);5802 if (!this->visitBool(Cond))5803 return false;5804 5805 if (!CondScope.destroyLocals())5806 return false;5807 }5808 if (!this->jumpTrue(StartLabel))5809 return false;5810 5811 this->fallthrough(EndLabel);5812 this->emitLabel(EndLabel);5813 return WholeLoopScope.destroyLocals();5814}5815 5816template <class Emitter>5817bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {5818 // for (Init; Cond; Inc) { Body }5819 const Stmt *Init = S->getInit();5820 const Expr *Cond = S->getCond();5821 const Expr *Inc = S->getInc();5822 const Stmt *Body = S->getBody();5823 5824 LabelTy EndLabel = this->getLabel();5825 LabelTy CondLabel = this->getLabel();5826 LabelTy IncLabel = this->getLabel();5827 5828 LocalScope<Emitter> WholeLoopScope(this);5829 if (Init && !this->visitStmt(Init))5830 return false;5831 5832 // Start of the loop body {5833 this->fallthrough(CondLabel);5834 this->emitLabel(CondLabel);5835 5836 LocalScope<Emitter> CondScope(this);5837 LoopScope<Emitter> LS(this, S, EndLabel, IncLabel);5838 if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt()) {5839 if (!visitDeclStmt(CondDecl))5840 return false;5841 }5842 5843 if (Cond) {5844 if (!this->visitBool(Cond))5845 return false;5846 if (!this->jumpFalse(EndLabel))5847 return false;5848 }5849 if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))5850 return false;5851 5852 if (Body && !this->visitStmt(Body))5853 return false;5854 5855 this->fallthrough(IncLabel);5856 this->emitLabel(IncLabel);5857 if (Inc && !this->discard(Inc))5858 return false;5859 5860 if (!CondScope.destroyLocals())5861 return false;5862 if (!this->jump(CondLabel))5863 return false;5864 // } End of loop body.5865 5866 this->emitLabel(EndLabel);5867 // If we jumped out of the loop above, we still need to clean up the condition5868 // scope.5869 return CondScope.destroyLocals() && WholeLoopScope.destroyLocals();5870}5871 5872template <class Emitter>5873bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {5874 const Stmt *Init = S->getInit();5875 const Expr *Cond = S->getCond();5876 const Expr *Inc = S->getInc();5877 const Stmt *Body = S->getBody();5878 const Stmt *BeginStmt = S->getBeginStmt();5879 const Stmt *RangeStmt = S->getRangeStmt();5880 const Stmt *EndStmt = S->getEndStmt();5881 5882 LabelTy EndLabel = this->getLabel();5883 LabelTy CondLabel = this->getLabel();5884 LabelTy IncLabel = this->getLabel();5885 LocalScope<Emitter> WholeLoopScope(this);5886 LoopScope<Emitter> LS(this, S, EndLabel, IncLabel);5887 5888 // Emit declarations needed in the loop.5889 if (Init && !this->visitStmt(Init))5890 return false;5891 if (!this->visitStmt(RangeStmt))5892 return false;5893 if (!this->visitStmt(BeginStmt))5894 return false;5895 if (!this->visitStmt(EndStmt))5896 return false;5897 5898 // Now the condition as well as the loop variable assignment.5899 this->fallthrough(CondLabel);5900 this->emitLabel(CondLabel);5901 if (!this->visitBool(Cond))5902 return false;5903 if (!this->jumpFalse(EndLabel))5904 return false;5905 5906 if (!this->visitDeclStmt(S->getLoopVarStmt(), /*EvaluateConditionDecl=*/true))5907 return false;5908 5909 // Body.5910 {5911 if (!this->visitStmt(Body))5912 return false;5913 5914 this->fallthrough(IncLabel);5915 this->emitLabel(IncLabel);5916 if (!this->discard(Inc))5917 return false;5918 }5919 5920 if (!this->jump(CondLabel))5921 return false;5922 5923 this->fallthrough(EndLabel);5924 this->emitLabel(EndLabel);5925 return WholeLoopScope.destroyLocals();5926}5927 5928template <class Emitter>5929bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {5930 if (LabelInfoStack.empty())5931 return false;5932 5933 OptLabelTy TargetLabel = std::nullopt;5934 const Stmt *TargetLoop = S->getNamedLoopOrSwitch();5935 const VariableScope<Emitter> *BreakScope = nullptr;5936 5937 if (!TargetLoop) {5938 for (const auto &LI : llvm::reverse(LabelInfoStack)) {5939 if (LI.BreakLabel) {5940 TargetLabel = *LI.BreakLabel;5941 BreakScope = LI.BreakOrContinueScope;5942 break;5943 }5944 }5945 } else {5946 for (auto LI : LabelInfoStack) {5947 if (LI.Name == TargetLoop) {5948 TargetLabel = *LI.BreakLabel;5949 BreakScope = LI.BreakOrContinueScope;5950 break;5951 }5952 }5953 }5954 5955 assert(TargetLabel);5956 5957 for (VariableScope<Emitter> *C = this->VarScope; C != BreakScope;5958 C = C->getParent()) {5959 if (!C->destroyLocals())5960 return false;5961 }5962 5963 return this->jump(*TargetLabel);5964}5965 5966template <class Emitter>5967bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {5968 if (LabelInfoStack.empty())5969 return false;5970 5971 OptLabelTy TargetLabel = std::nullopt;5972 const Stmt *TargetLoop = S->getNamedLoopOrSwitch();5973 const VariableScope<Emitter> *ContinueScope = nullptr;5974 5975 if (!TargetLoop) {5976 for (const auto &LI : llvm::reverse(LabelInfoStack)) {5977 if (LI.ContinueLabel) {5978 TargetLabel = *LI.ContinueLabel;5979 ContinueScope = LI.BreakOrContinueScope;5980 break;5981 }5982 }5983 } else {5984 for (auto LI : LabelInfoStack) {5985 if (LI.Name == TargetLoop) {5986 TargetLabel = *LI.ContinueLabel;5987 ContinueScope = LI.BreakOrContinueScope;5988 break;5989 }5990 }5991 }5992 assert(TargetLabel);5993 5994 for (VariableScope<Emitter> *C = VarScope; C != ContinueScope;5995 C = C->getParent()) {5996 if (!C->destroyLocals())5997 return false;5998 }5999 6000 return this->jump(*TargetLabel);6001}6002 6003template <class Emitter>6004bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {6005 const Expr *Cond = S->getCond();6006 if (Cond->containsErrors())6007 return false;6008 6009 PrimType CondT = this->classifyPrim(Cond->getType());6010 LocalScope<Emitter> LS(this);6011 6012 LabelTy EndLabel = this->getLabel();6013 UnsignedOrNone DefaultLabel = std::nullopt;6014 unsigned CondVar =6015 this->allocateLocalPrimitive(Cond, CondT, /*IsConst=*/true);6016 6017 if (const auto *CondInit = S->getInit())6018 if (!visitStmt(CondInit))6019 return false;6020 6021 if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())6022 if (!visitDeclStmt(CondDecl))6023 return false;6024 6025 // Initialize condition variable.6026 if (!this->visit(Cond))6027 return false;6028 if (!this->emitSetLocal(CondT, CondVar, S))6029 return false;6030 6031 if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))6032 return false;6033 6034 CaseMap CaseLabels;6035 // Create labels and comparison ops for all case statements.6036 for (const SwitchCase *SC = S->getSwitchCaseList(); SC;6037 SC = SC->getNextSwitchCase()) {6038 if (const auto *CS = dyn_cast<CaseStmt>(SC)) {6039 CaseLabels[SC] = this->getLabel();6040 6041 if (CS->caseStmtIsGNURange()) {6042 LabelTy EndOfRangeCheck = this->getLabel();6043 const Expr *Low = CS->getLHS();6044 const Expr *High = CS->getRHS();6045 if (Low->isValueDependent() || High->isValueDependent())6046 return false;6047 6048 if (!this->emitGetLocal(CondT, CondVar, CS))6049 return false;6050 if (!this->visit(Low))6051 return false;6052 PrimType LT = this->classifyPrim(Low->getType());6053 if (!this->emitGE(LT, S))6054 return false;6055 if (!this->jumpFalse(EndOfRangeCheck))6056 return false;6057 6058 if (!this->emitGetLocal(CondT, CondVar, CS))6059 return false;6060 if (!this->visit(High))6061 return false;6062 PrimType HT = this->classifyPrim(High->getType());6063 if (!this->emitLE(HT, S))6064 return false;6065 if (!this->jumpTrue(CaseLabels[CS]))6066 return false;6067 this->emitLabel(EndOfRangeCheck);6068 continue;6069 }6070 6071 const Expr *Value = CS->getLHS();6072 if (Value->isValueDependent())6073 return false;6074 PrimType ValueT = this->classifyPrim(Value->getType());6075 6076 // Compare the case statement's value to the switch condition.6077 if (!this->emitGetLocal(CondT, CondVar, CS))6078 return false;6079 if (!this->visit(Value))6080 return false;6081 6082 // Compare and jump to the case label.6083 if (!this->emitEQ(ValueT, S))6084 return false;6085 if (!this->jumpTrue(CaseLabels[CS]))6086 return false;6087 } else {6088 assert(!DefaultLabel);6089 DefaultLabel = this->getLabel();6090 }6091 }6092 6093 // If none of the conditions above were true, fall through to the default6094 // statement or jump after the switch statement.6095 if (DefaultLabel) {6096 if (!this->jump(*DefaultLabel))6097 return false;6098 } else {6099 if (!this->jump(EndLabel))6100 return false;6101 }6102 6103 SwitchScope<Emitter> SS(this, S, std::move(CaseLabels), EndLabel,6104 DefaultLabel);6105 if (!this->visitStmt(S->getBody()))6106 return false;6107 this->fallthrough(EndLabel);6108 this->emitLabel(EndLabel);6109 6110 return LS.destroyLocals();6111}6112 6113template <class Emitter>6114bool Compiler<Emitter>::visitCaseStmt(const CaseStmt *S) {6115 this->fallthrough(CaseLabels[S]);6116 this->emitLabel(CaseLabels[S]);6117 return this->visitStmt(S->getSubStmt());6118}6119 6120template <class Emitter>6121bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) {6122 if (LabelInfoStack.empty())6123 return false;6124 6125 LabelTy DefaultLabel;6126 for (const LabelInfo &LI : llvm::reverse(LabelInfoStack)) {6127 if (LI.DefaultLabel) {6128 DefaultLabel = *LI.DefaultLabel;6129 break;6130 }6131 }6132 6133 this->emitLabel(DefaultLabel);6134 return this->visitStmt(S->getSubStmt());6135}6136 6137template <class Emitter>6138bool Compiler<Emitter>::visitAttributedStmt(const AttributedStmt *S) {6139 if (this->Ctx.getLangOpts().CXXAssumptions &&6140 !this->Ctx.getLangOpts().MSVCCompat) {6141 for (const Attr *A : S->getAttrs()) {6142 auto *AA = dyn_cast<CXXAssumeAttr>(A);6143 if (!AA)6144 continue;6145 6146 assert(isa<NullStmt>(S->getSubStmt()));6147 6148 const Expr *Assumption = AA->getAssumption();6149 if (Assumption->isValueDependent())6150 return false;6151 6152 if (Assumption->HasSideEffects(this->Ctx.getASTContext()))6153 continue;6154 6155 // Evaluate assumption.6156 if (!this->visitBool(Assumption))6157 return false;6158 6159 if (!this->emitAssume(Assumption))6160 return false;6161 }6162 }6163 6164 // Ignore other attributes.6165 return this->visitStmt(S->getSubStmt());6166}6167 6168template <class Emitter>6169bool Compiler<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {6170 // Ignore all handlers.6171 return this->visitStmt(S->getTryBlock());6172}6173 6174template <class Emitter>6175bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {6176 assert(MD->isLambdaStaticInvoker());6177 assert(MD->hasBody());6178 assert(cast<CompoundStmt>(MD->getBody())->body_empty());6179 6180 const CXXRecordDecl *ClosureClass = MD->getParent();6181 const FunctionDecl *LambdaCallOp;6182 assert(ClosureClass->captures().empty());6183 if (ClosureClass->isGenericLambda()) {6184 LambdaCallOp = ClosureClass->getLambdaCallOperator();6185 assert(MD->isFunctionTemplateSpecialization() &&6186 "A generic lambda's static-invoker function must be a "6187 "template specialization");6188 const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();6189 FunctionTemplateDecl *CallOpTemplate =6190 LambdaCallOp->getDescribedFunctionTemplate();6191 void *InsertPos = nullptr;6192 const FunctionDecl *CorrespondingCallOpSpecialization =6193 CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);6194 assert(CorrespondingCallOpSpecialization);6195 LambdaCallOp = CorrespondingCallOpSpecialization;6196 } else {6197 LambdaCallOp = ClosureClass->getLambdaCallOperator();6198 }6199 assert(ClosureClass->captures().empty());6200 const Function *Func = this->getFunction(LambdaCallOp);6201 if (!Func)6202 return false;6203 assert(Func->hasThisPointer());6204 assert(Func->getNumParams() == (MD->getNumParams() + 1 + Func->hasRVO()));6205 6206 if (Func->hasRVO()) {6207 if (!this->emitRVOPtr(MD))6208 return false;6209 }6210 6211 // The lambda call operator needs an instance pointer, but we don't have6212 // one here, and we don't need one either because the lambda cannot have6213 // any captures, as verified above. Emit a null pointer. This is then6214 // special-cased when interpreting to not emit any misleading diagnostics.6215 if (!this->emitNullPtr(0, nullptr, MD))6216 return false;6217 6218 // Forward all arguments from the static invoker to the lambda call operator.6219 for (const ParmVarDecl *PVD : MD->parameters()) {6220 auto It = this->Params.find(PVD);6221 assert(It != this->Params.end());6222 6223 // We do the lvalue-to-rvalue conversion manually here, so no need6224 // to care about references.6225 PrimType ParamType = this->classify(PVD->getType()).value_or(PT_Ptr);6226 if (!this->emitGetParam(ParamType, It->second.Offset, MD))6227 return false;6228 }6229 6230 if (!this->emitCall(Func, 0, LambdaCallOp))6231 return false;6232 6233 this->emitCleanup();6234 if (ReturnType)6235 return this->emitRet(*ReturnType, MD);6236 6237 // Nothing to do, since we emitted the RVO pointer above.6238 return this->emitRetVoid(MD);6239}6240 6241template <class Emitter>6242bool Compiler<Emitter>::checkLiteralType(const Expr *E) {6243 if (Ctx.getLangOpts().CPlusPlus23)6244 return true;6245 6246 if (!E->isPRValue() || E->getType()->isLiteralType(Ctx.getASTContext()))6247 return true;6248 6249 return this->emitCheckLiteralType(E->getType().getTypePtr(), E);6250}6251 6252static bool initNeedsOverridenLoc(const CXXCtorInitializer *Init) {6253 const Expr *InitExpr = Init->getInit();6254 6255 if (!Init->isWritten() && !Init->isInClassMemberInitializer() &&6256 !isa<CXXConstructExpr>(InitExpr))6257 return true;6258 6259 if (const auto *CE = dyn_cast<CXXConstructExpr>(InitExpr)) {6260 const CXXConstructorDecl *Ctor = CE->getConstructor();6261 if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&6262 Ctor->isTrivial())6263 return true;6264 }6265 6266 return false;6267}6268 6269template <class Emitter>6270bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {6271 assert(!ReturnType);6272 6273 auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,6274 const Expr *InitExpr,6275 bool Activate = false) -> bool {6276 // We don't know what to do with these, so just return false.6277 if (InitExpr->getType().isNull())6278 return false;6279 6280 if (OptPrimType T = this->classify(InitExpr)) {6281 if (Activate && !this->emitActivateThisField(FieldOffset, InitExpr))6282 return false;6283 6284 if (!this->visit(InitExpr))6285 return false;6286 6287 bool BitField = F->isBitField();6288 if (BitField)6289 return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);6290 return this->emitInitThisField(*T, FieldOffset, InitExpr);6291 }6292 // Non-primitive case. Get a pointer to the field-to-initialize6293 // on the stack and call visitInitialzer() for it.6294 InitLinkScope<Emitter> FieldScope(this, InitLink::Field(F->Offset));6295 if (!this->emitGetPtrThisField(FieldOffset, InitExpr))6296 return false;6297 6298 if (Activate && !this->emitActivate(InitExpr))6299 return false;6300 6301 if (!this->visitInitializer(InitExpr))6302 return false;6303 6304 return this->emitFinishInitPop(InitExpr);6305 };6306 6307 const RecordDecl *RD = Ctor->getParent();6308 const Record *R = this->getRecord(RD);6309 if (!R)6310 return false;6311 bool IsUnion = R->isUnion();6312 6313 if (IsUnion && Ctor->isCopyOrMoveConstructor()) {6314 LocOverrideScope<Emitter> LOS(this, SourceInfo{});6315 6316 if (R->getNumFields() == 0)6317 return this->emitRetVoid(Ctor);6318 // union copy and move ctors are special.6319 assert(cast<CompoundStmt>(Ctor->getBody())->body_empty());6320 if (!this->emitThis(Ctor))6321 return false;6322 6323 const ParmVarDecl *PVD = Ctor->getParamDecl(0);6324 ParamOffset PO = this->Params[PVD]; // Must exist.6325 6326 if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor))6327 return false;6328 6329 return this->emitMemcpy(Ctor) && this->emitPopPtr(Ctor) &&6330 this->emitRetVoid(Ctor);6331 }6332 6333 InitLinkScope<Emitter> InitScope(this, InitLink::This());6334 for (const auto *Init : Ctor->inits()) {6335 // Scope needed for the initializers.6336 LocalScope<Emitter> Scope(this);6337 6338 const Expr *InitExpr = Init->getInit();6339 if (const FieldDecl *Member = Init->getMember()) {6340 const Record::Field *F = R->getField(Member);6341 6342 LocOverrideScope<Emitter> LOS(this, SourceInfo{},6343 initNeedsOverridenLoc(Init));6344 if (!emitFieldInitializer(F, F->Offset, InitExpr, IsUnion))6345 return false;6346 } else if (const Type *Base = Init->getBaseClass()) {6347 const auto *BaseDecl = Base->getAsCXXRecordDecl();6348 assert(BaseDecl);6349 6350 if (Init->isBaseVirtual()) {6351 assert(R->getVirtualBase(BaseDecl));6352 if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))6353 return false;6354 6355 } else {6356 // Base class initializer.6357 // Get This Base and call initializer on it.6358 const Record::Base *B = R->getBase(BaseDecl);6359 assert(B);6360 if (!this->emitGetPtrThisBase(B->Offset, InitExpr))6361 return false;6362 }6363 6364 if (IsUnion && !this->emitActivate(InitExpr))6365 return false;6366 6367 if (!this->visitInitializer(InitExpr))6368 return false;6369 if (!this->emitFinishInitPop(InitExpr))6370 return false;6371 } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {6372 LocOverrideScope<Emitter> LOS(this, SourceInfo{},6373 initNeedsOverridenLoc(Init));6374 assert(IFD->getChainingSize() >= 2);6375 6376 unsigned NestedFieldOffset = 0;6377 const Record::Field *NestedField = nullptr;6378 for (const NamedDecl *ND : IFD->chain()) {6379 const auto *FD = cast<FieldDecl>(ND);6380 const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());6381 assert(FieldRecord);6382 6383 NestedField = FieldRecord->getField(FD);6384 assert(NestedField);6385 IsUnion = IsUnion || FieldRecord->isUnion();6386 6387 NestedFieldOffset += NestedField->Offset;6388 }6389 assert(NestedField);6390 6391 unsigned FirstLinkOffset =6392 R->getField(cast<FieldDecl>(IFD->chain()[0]))->Offset;6393 InitLinkScope<Emitter> ILS(this, InitLink::Field(FirstLinkOffset));6394 InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(InitExpr));6395 if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr,6396 IsUnion))6397 return false;6398 6399 // Mark all chain links as initialized.6400 unsigned InitFieldOffset = 0;6401 for (const NamedDecl *ND : IFD->chain().drop_back()) {6402 const auto *FD = cast<FieldDecl>(ND);6403 const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());6404 assert(FieldRecord);6405 NestedField = FieldRecord->getField(FD);6406 InitFieldOffset += NestedField->Offset;6407 assert(NestedField);6408 if (!this->emitGetPtrThisField(InitFieldOffset, InitExpr))6409 return false;6410 if (!this->emitFinishInitPop(InitExpr))6411 return false;6412 }6413 6414 } else {6415 assert(Init->isDelegatingInitializer());6416 if (!this->emitThis(InitExpr))6417 return false;6418 if (!this->visitInitializer(Init->getInit()))6419 return false;6420 if (!this->emitPopPtr(InitExpr))6421 return false;6422 }6423 6424 if (!Scope.destroyLocals())6425 return false;6426 }6427 6428 if (const auto *Body = Ctor->getBody())6429 if (!visitStmt(Body))6430 return false;6431 6432 return this->emitRetVoid(SourceInfo{});6433}6434 6435template <class Emitter>6436bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {6437 const RecordDecl *RD = Dtor->getParent();6438 const Record *R = this->getRecord(RD);6439 if (!R)6440 return false;6441 6442 if (!Dtor->isTrivial() && Dtor->getBody()) {6443 if (!this->visitStmt(Dtor->getBody()))6444 return false;6445 }6446 6447 if (!this->emitThis(Dtor))6448 return false;6449 6450 if (!this->emitCheckDestruction(Dtor))6451 return false;6452 6453 assert(R);6454 if (!R->isUnion()) {6455 6456 LocOverrideScope<Emitter> LOS(this, SourceInfo{});6457 // First, destroy all fields.6458 for (const Record::Field &Field : llvm::reverse(R->fields())) {6459 const Descriptor *D = Field.Desc;6460 if (D->hasTrivialDtor())6461 continue;6462 if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))6463 return false;6464 if (!this->emitDestructionPop(D, SourceInfo{}))6465 return false;6466 }6467 }6468 6469 for (const Record::Base &Base : llvm::reverse(R->bases())) {6470 if (Base.R->hasTrivialDtor())6471 continue;6472 if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))6473 return false;6474 if (!this->emitRecordDestructionPop(Base.R, {}))6475 return false;6476 }6477 6478 // FIXME: Virtual bases.6479 return this->emitPopPtr(Dtor) && this->emitRetVoid(Dtor);6480}6481 6482template <class Emitter>6483bool Compiler<Emitter>::compileUnionAssignmentOperator(6484 const CXXMethodDecl *MD) {6485 if (!this->emitThis(MD))6486 return false;6487 6488 const ParmVarDecl *PVD = MD->getParamDecl(0);6489 ParamOffset PO = this->Params[PVD]; // Must exist.6490 6491 if (!this->emitGetParam(PT_Ptr, PO.Offset, MD))6492 return false;6493 6494 return this->emitMemcpy(MD) && this->emitRet(PT_Ptr, MD);6495}6496 6497template <class Emitter>6498bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {6499 // Classify the return type.6500 ReturnType = this->classify(F->getReturnType());6501 6502 this->CompilingFunction = F;6503 6504 if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F))6505 return this->compileConstructor(Ctor);6506 if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(F))6507 return this->compileDestructor(Dtor);6508 6509 // Emit custom code if this is a lambda static invoker.6510 if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {6511 const RecordDecl *RD = MD->getParent();6512 6513 if (RD->isUnion() &&6514 (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()))6515 return this->compileUnionAssignmentOperator(MD);6516 6517 if (MD->isLambdaStaticInvoker())6518 return this->emitLambdaStaticInvokerBody(MD);6519 }6520 6521 // Regular functions.6522 if (const auto *Body = F->getBody())6523 if (!visitStmt(Body))6524 return false;6525 6526 // Emit a guard return to protect against a code path missing one.6527 if (F->getReturnType()->isVoidType())6528 return this->emitRetVoid(SourceInfo{});6529 return this->emitNoRet(SourceInfo{});6530}6531 6532static uint32_t getBitWidth(const Expr *E) {6533 assert(E->refersToBitField());6534 const auto *ME = cast<MemberExpr>(E);6535 const auto *FD = cast<FieldDecl>(ME->getMemberDecl());6536 return FD->getBitWidthValue();6537}6538 6539template <class Emitter>6540bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {6541 const Expr *SubExpr = E->getSubExpr();6542 if (SubExpr->getType()->isAnyComplexType())6543 return this->VisitComplexUnaryOperator(E);6544 if (SubExpr->getType()->isVectorType())6545 return this->VisitVectorUnaryOperator(E);6546 if (SubExpr->getType()->isFixedPointType())6547 return this->VisitFixedPointUnaryOperator(E);6548 OptPrimType T = classify(SubExpr->getType());6549 6550 switch (E->getOpcode()) {6551 case UO_PostInc: { // x++6552 if (!Ctx.getLangOpts().CPlusPlus14)6553 return this->emitInvalid(E);6554 if (!T)6555 return this->emitError(E);6556 6557 if (!this->visit(SubExpr))6558 return false;6559 6560 if (T == PT_Ptr) {6561 if (!this->emitIncPtr(E))6562 return false;6563 6564 return DiscardResult ? this->emitPopPtr(E) : true;6565 }6566 6567 if (T == PT_Float)6568 return DiscardResult ? this->emitIncfPop(getFPOptions(E), E)6569 : this->emitIncf(getFPOptions(E), E);6570 6571 if (SubExpr->refersToBitField())6572 return DiscardResult ? this->emitIncPopBitfield(*T, E->canOverflow(),6573 getBitWidth(SubExpr), E)6574 : this->emitIncBitfield(*T, E->canOverflow(),6575 getBitWidth(SubExpr), E);6576 6577 return DiscardResult ? this->emitIncPop(*T, E->canOverflow(), E)6578 : this->emitInc(*T, E->canOverflow(), E);6579 }6580 case UO_PostDec: { // x--6581 if (!Ctx.getLangOpts().CPlusPlus14)6582 return this->emitInvalid(E);6583 if (!T)6584 return this->emitError(E);6585 6586 if (!this->visit(SubExpr))6587 return false;6588 6589 if (T == PT_Ptr) {6590 if (!this->emitDecPtr(E))6591 return false;6592 6593 return DiscardResult ? this->emitPopPtr(E) : true;6594 }6595 6596 if (T == PT_Float)6597 return DiscardResult ? this->emitDecfPop(getFPOptions(E), E)6598 : this->emitDecf(getFPOptions(E), E);6599 6600 if (SubExpr->refersToBitField()) {6601 return DiscardResult ? this->emitDecPopBitfield(*T, E->canOverflow(),6602 getBitWidth(SubExpr), E)6603 : this->emitDecBitfield(*T, E->canOverflow(),6604 getBitWidth(SubExpr), E);6605 }6606 6607 return DiscardResult ? this->emitDecPop(*T, E->canOverflow(), E)6608 : this->emitDec(*T, E->canOverflow(), E);6609 }6610 case UO_PreInc: { // ++x6611 if (!Ctx.getLangOpts().CPlusPlus14)6612 return this->emitInvalid(E);6613 if (!T)6614 return this->emitError(E);6615 6616 if (!this->visit(SubExpr))6617 return false;6618 6619 if (T == PT_Ptr) {6620 if (!this->emitLoadPtr(E))6621 return false;6622 if (!this->emitConstUint8(1, E))6623 return false;6624 if (!this->emitAddOffsetUint8(E))6625 return false;6626 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);6627 }6628 6629 // Post-inc and pre-inc are the same if the value is to be discarded.6630 if (DiscardResult) {6631 if (T == PT_Float)6632 return this->emitIncfPop(getFPOptions(E), E);6633 if (SubExpr->refersToBitField())6634 return DiscardResult ? this->emitIncPopBitfield(*T, E->canOverflow(),6635 getBitWidth(SubExpr), E)6636 : this->emitIncBitfield(*T, E->canOverflow(),6637 getBitWidth(SubExpr), E);6638 return this->emitIncPop(*T, E->canOverflow(), E);6639 }6640 6641 if (T == PT_Float) {6642 const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());6643 if (!this->emitLoadFloat(E))6644 return false;6645 APFloat F(TargetSemantics, 1);6646 if (!this->emitFloat(F, E))6647 return false;6648 6649 if (!this->emitAddf(getFPOptions(E), E))6650 return false;6651 if (!this->emitStoreFloat(E))6652 return false;6653 } else if (SubExpr->refersToBitField()) {6654 assert(isIntegralType(*T));6655 if (!this->emitPreIncBitfield(*T, E->canOverflow(), getBitWidth(SubExpr),6656 E))6657 return false;6658 } else {6659 assert(isIntegralType(*T));6660 if (!this->emitPreInc(*T, E->canOverflow(), E))6661 return false;6662 }6663 return E->isGLValue() || this->emitLoadPop(*T, E);6664 }6665 case UO_PreDec: { // --x6666 if (!Ctx.getLangOpts().CPlusPlus14)6667 return this->emitInvalid(E);6668 if (!T)6669 return this->emitError(E);6670 6671 if (!this->visit(SubExpr))6672 return false;6673 6674 if (T == PT_Ptr) {6675 if (!this->emitLoadPtr(E))6676 return false;6677 if (!this->emitConstUint8(1, E))6678 return false;6679 if (!this->emitSubOffsetUint8(E))6680 return false;6681 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);6682 }6683 6684 // Post-dec and pre-dec are the same if the value is to be discarded.6685 if (DiscardResult) {6686 if (T == PT_Float)6687 return this->emitDecfPop(getFPOptions(E), E);6688 if (SubExpr->refersToBitField())6689 return DiscardResult ? this->emitDecPopBitfield(*T, E->canOverflow(),6690 getBitWidth(SubExpr), E)6691 : this->emitDecBitfield(*T, E->canOverflow(),6692 getBitWidth(SubExpr), E);6693 return this->emitDecPop(*T, E->canOverflow(), E);6694 }6695 6696 if (T == PT_Float) {6697 const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());6698 if (!this->emitLoadFloat(E))6699 return false;6700 APFloat F(TargetSemantics, 1);6701 if (!this->emitFloat(F, E))6702 return false;6703 6704 if (!this->emitSubf(getFPOptions(E), E))6705 return false;6706 if (!this->emitStoreFloat(E))6707 return false;6708 } else if (SubExpr->refersToBitField()) {6709 assert(isIntegralType(*T));6710 if (!this->emitPreDecBitfield(*T, E->canOverflow(), getBitWidth(SubExpr),6711 E))6712 return false;6713 } else {6714 assert(isIntegralType(*T));6715 if (!this->emitPreDec(*T, E->canOverflow(), E))6716 return false;6717 }6718 return E->isGLValue() || this->emitLoadPop(*T, E);6719 }6720 case UO_LNot: // !x6721 if (!T)6722 return this->emitError(E);6723 6724 if (DiscardResult)6725 return this->discard(SubExpr);6726 6727 if (!this->visitBool(SubExpr))6728 return false;6729 6730 if (!this->emitInv(E))6731 return false;6732 6733 if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)6734 return this->emitCast(PT_Bool, ET, E);6735 return true;6736 case UO_Minus: // -x6737 if (!T)6738 return this->emitError(E);6739 6740 if (!this->visit(SubExpr))6741 return false;6742 return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);6743 case UO_Plus: // +x6744 if (!T)6745 return this->emitError(E);6746 6747 if (!this->visit(SubExpr)) // noop6748 return false;6749 return DiscardResult ? this->emitPop(*T, E) : true;6750 case UO_AddrOf: // &x6751 if (E->getType()->isMemberPointerType()) {6752 // C++11 [expr.unary.op]p3 has very strict rules on how the address of a6753 // member can be formed.6754 return this->emitGetMemberPtr(cast<DeclRefExpr>(SubExpr)->getDecl(), E);6755 }6756 // We should already have a pointer when we get here.6757 return this->delegate(SubExpr);6758 case UO_Deref: // *x6759 if (DiscardResult)6760 return this->discard(SubExpr);6761 6762 if (!this->visit(SubExpr))6763 return false;6764 6765 if (!SubExpr->getType()->isFunctionPointerType() && !this->emitCheckNull(E))6766 return false;6767 6768 if (classifyPrim(SubExpr) == PT_Ptr)6769 return this->emitNarrowPtr(E);6770 return true;6771 6772 case UO_Not: // ~x6773 if (!T)6774 return this->emitError(E);6775 6776 if (!this->visit(SubExpr))6777 return false;6778 return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);6779 case UO_Real: // __real x6780 assert(T);6781 return this->delegate(SubExpr);6782 case UO_Imag: { // __imag x6783 assert(T);6784 if (!this->discard(SubExpr))6785 return false;6786 return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);6787 }6788 case UO_Extension:6789 return this->delegate(SubExpr);6790 case UO_Coawait:6791 assert(false && "Unhandled opcode");6792 }6793 6794 return false;6795}6796 6797template <class Emitter>6798bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {6799 const Expr *SubExpr = E->getSubExpr();6800 assert(SubExpr->getType()->isAnyComplexType());6801 6802 if (DiscardResult)6803 return this->discard(SubExpr);6804 6805 OptPrimType ResT = classify(E);6806 auto prepareResult = [=]() -> bool {6807 if (!ResT && !Initializing) {6808 UnsignedOrNone LocalIndex = allocateLocal(SubExpr);6809 if (!LocalIndex)6810 return false;6811 return this->emitGetPtrLocal(*LocalIndex, E);6812 }6813 6814 return true;6815 };6816 6817 // The offset of the temporary, if we created one.6818 unsigned SubExprOffset = ~0u;6819 auto createTemp = [=, &SubExprOffset]() -> bool {6820 SubExprOffset =6821 this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);6822 if (!this->visit(SubExpr))6823 return false;6824 return this->emitSetLocal(PT_Ptr, SubExprOffset, E);6825 };6826 6827 PrimType ElemT = classifyComplexElementType(SubExpr->getType());6828 auto getElem = [=](unsigned Offset, unsigned Index) -> bool {6829 if (!this->emitGetLocal(PT_Ptr, Offset, E))6830 return false;6831 return this->emitArrayElemPop(ElemT, Index, E);6832 };6833 6834 switch (E->getOpcode()) {6835 case UO_Minus:6836 if (!prepareResult())6837 return false;6838 if (!createTemp())6839 return false;6840 for (unsigned I = 0; I != 2; ++I) {6841 if (!getElem(SubExprOffset, I))6842 return false;6843 if (!this->emitNeg(ElemT, E))6844 return false;6845 if (!this->emitInitElem(ElemT, I, E))6846 return false;6847 }6848 break;6849 6850 case UO_Plus: // +x6851 case UO_AddrOf: // &x6852 case UO_Deref: // *x6853 return this->delegate(SubExpr);6854 6855 case UO_LNot:6856 if (!this->visit(SubExpr))6857 return false;6858 if (!this->emitComplexBoolCast(SubExpr))6859 return false;6860 if (!this->emitInv(E))6861 return false;6862 if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)6863 return this->emitCast(PT_Bool, ET, E);6864 return true;6865 6866 case UO_Real:6867 return this->emitComplexReal(SubExpr);6868 6869 case UO_Imag:6870 if (!this->visit(SubExpr))6871 return false;6872 6873 if (SubExpr->isLValue()) {6874 if (!this->emitConstUint8(1, E))6875 return false;6876 return this->emitArrayElemPtrPopUint8(E);6877 }6878 6879 // Since our _Complex implementation does not map to a primitive type,6880 // we sometimes have to do the lvalue-to-rvalue conversion here manually.6881 return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);6882 6883 case UO_Not: // ~x6884 if (!this->visit(SubExpr))6885 return false;6886 // Negate the imaginary component.6887 if (!this->emitArrayElem(ElemT, 1, E))6888 return false;6889 if (!this->emitNeg(ElemT, E))6890 return false;6891 if (!this->emitInitElem(ElemT, 1, E))6892 return false;6893 return DiscardResult ? this->emitPopPtr(E) : true;6894 6895 case UO_Extension:6896 return this->delegate(SubExpr);6897 6898 default:6899 return this->emitInvalid(E);6900 }6901 6902 return true;6903}6904 6905template <class Emitter>6906bool Compiler<Emitter>::VisitVectorUnaryOperator(const UnaryOperator *E) {6907 const Expr *SubExpr = E->getSubExpr();6908 assert(SubExpr->getType()->isVectorType());6909 6910 if (DiscardResult)6911 return this->discard(SubExpr);6912 6913 auto UnaryOp = E->getOpcode();6914 if (UnaryOp == UO_Extension)6915 return this->delegate(SubExpr);6916 6917 if (UnaryOp != UO_Plus && UnaryOp != UO_Minus && UnaryOp != UO_LNot &&6918 UnaryOp != UO_Not && UnaryOp != UO_AddrOf)6919 return this->emitInvalid(E);6920 6921 // Nothing to do here.6922 if (UnaryOp == UO_Plus || UnaryOp == UO_AddrOf)6923 return this->delegate(SubExpr);6924 6925 if (!Initializing) {6926 UnsignedOrNone LocalIndex = allocateLocal(SubExpr);6927 if (!LocalIndex)6928 return false;6929 if (!this->emitGetPtrLocal(*LocalIndex, E))6930 return false;6931 }6932 6933 // The offset of the temporary, if we created one.6934 unsigned SubExprOffset =6935 this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);6936 if (!this->visit(SubExpr))6937 return false;6938 if (!this->emitSetLocal(PT_Ptr, SubExprOffset, E))6939 return false;6940 6941 const auto *VecTy = SubExpr->getType()->getAs<VectorType>();6942 PrimType ElemT = classifyVectorElementType(SubExpr->getType());6943 auto getElem = [=](unsigned Offset, unsigned Index) -> bool {6944 if (!this->emitGetLocal(PT_Ptr, Offset, E))6945 return false;6946 return this->emitArrayElemPop(ElemT, Index, E);6947 };6948 6949 switch (UnaryOp) {6950 case UO_Minus:6951 for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {6952 if (!getElem(SubExprOffset, I))6953 return false;6954 if (!this->emitNeg(ElemT, E))6955 return false;6956 if (!this->emitInitElem(ElemT, I, E))6957 return false;6958 }6959 break;6960 case UO_LNot: { // !x6961 // In C++, the logic operators !, &&, || are available for vectors. !v is6962 // equivalent to v == 0.6963 //6964 // The result of the comparison is a vector of the same width and number of6965 // elements as the comparison operands with a signed integral element type.6966 //6967 // https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html6968 QualType ResultVecTy = E->getType();6969 PrimType ResultVecElemT =6970 classifyPrim(ResultVecTy->getAs<VectorType>()->getElementType());6971 for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {6972 if (!getElem(SubExprOffset, I))6973 return false;6974 // operator ! on vectors returns -1 for 'truth', so negate it.6975 if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))6976 return false;6977 if (!this->emitInv(E))6978 return false;6979 if (!this->emitPrimCast(PT_Bool, ElemT, VecTy->getElementType(), E))6980 return false;6981 if (!this->emitNeg(ElemT, E))6982 return false;6983 if (ElemT != ResultVecElemT &&6984 !this->emitPrimCast(ElemT, ResultVecElemT, ResultVecTy, E))6985 return false;6986 if (!this->emitInitElem(ResultVecElemT, I, E))6987 return false;6988 }6989 break;6990 }6991 case UO_Not: // ~x6992 for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {6993 if (!getElem(SubExprOffset, I))6994 return false;6995 if (ElemT == PT_Bool) {6996 if (!this->emitInv(E))6997 return false;6998 } else {6999 if (!this->emitComp(ElemT, E))7000 return false;7001 }7002 if (!this->emitInitElem(ElemT, I, E))7003 return false;7004 }7005 break;7006 default:7007 llvm_unreachable("Unsupported unary operators should be handled up front");7008 }7009 return true;7010}7011 7012template <class Emitter>7013bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {7014 if (DiscardResult)7015 return true;7016 7017 if (const auto *ECD = dyn_cast<EnumConstantDecl>(D))7018 return this->emitConst(ECD->getInitVal(), E);7019 if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {7020 const Function *F = getFunction(FuncDecl);7021 return F && this->emitGetFnPtr(F, E);7022 }7023 if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) {7024 if (UnsignedOrNone Index = P.getOrCreateGlobal(D)) {7025 if (!this->emitGetPtrGlobal(*Index, E))7026 return false;7027 if (OptPrimType T = classify(E->getType())) {7028 if (!this->visitAPValue(TPOD->getValue(), *T, E))7029 return false;7030 return this->emitInitGlobal(*T, *Index, E);7031 }7032 return this->visitAPValueInitializer(TPOD->getValue(), E,7033 TPOD->getType());7034 }7035 return false;7036 }7037 7038 // References are implemented via pointers, so when we see a DeclRefExpr7039 // pointing to a reference, we need to get its value directly (i.e. the7040 // pointer to the actual value) instead of a pointer to the pointer to the7041 // value.7042 bool IsReference = D->getType()->isReferenceType();7043 7044 // Function parameters.7045 // Note that it's important to check them first since we might have a local7046 // variable created for a ParmVarDecl as well.7047 if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {7048 if (Ctx.getLangOpts().CPlusPlus && !Ctx.getLangOpts().CPlusPlus11 &&7049 !D->getType()->isIntegralOrEnumerationType()) {7050 return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),7051 /*InitializerFailed=*/false, E);7052 }7053 if (auto It = this->Params.find(PVD); It != this->Params.end()) {7054 if (IsReference || !It->second.IsPtr)7055 return this->emitGetParam(classifyPrim(E), It->second.Offset, E);7056 7057 return this->emitGetPtrParam(It->second.Offset, E);7058 }7059 }7060 // Local variables.7061 if (auto It = Locals.find(D); It != Locals.end()) {7062 const unsigned Offset = It->second.Offset;7063 if (IsReference)7064 return this->emitGetLocal(classifyPrim(E), Offset, E);7065 return this->emitGetPtrLocal(Offset, E);7066 }7067 // Global variables.7068 if (auto GlobalIndex = P.getGlobal(D)) {7069 if (IsReference) {7070 if (!Ctx.getLangOpts().CPlusPlus11)7071 return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);7072 return this->emitGetGlobalUnchecked(classifyPrim(E), *GlobalIndex, E);7073 }7074 7075 return this->emitGetPtrGlobal(*GlobalIndex, E);7076 }7077 7078 // In case we need to re-visit a declaration.7079 auto revisit = [&](const VarDecl *VD) -> bool {7080 if (!this->emitPushCC(VD->hasConstantInitialization(), E))7081 return false;7082 auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true);7083 7084 if (!this->emitPopCC(E))7085 return false;7086 7087 if (VarState.notCreated())7088 return true;7089 if (!VarState)7090 return false;7091 // Retry.7092 return this->visitDeclRef(D, E);7093 };7094 7095 // Lambda captures.7096 if (auto It = this->LambdaCaptures.find(D);7097 It != this->LambdaCaptures.end()) {7098 auto [Offset, IsPtr] = It->second;7099 7100 if (IsPtr)7101 return this->emitGetThisFieldPtr(Offset, E);7102 return this->emitGetPtrThisField(Offset, E);7103 }7104 7105 if (const auto *DRE = dyn_cast<DeclRefExpr>(E);7106 DRE && DRE->refersToEnclosingVariableOrCapture()) {7107 if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture())7108 return revisit(VD);7109 }7110 7111 if (const auto *BD = dyn_cast<BindingDecl>(D))7112 return this->visit(BD->getBinding());7113 7114 // Avoid infinite recursion.7115 if (D == InitializingDecl)7116 return this->emitDummyPtr(D, E);7117 7118 // Try to lazily visit (or emit dummy pointers for) declarations7119 // we haven't seen yet.7120 // For C.7121 if (!Ctx.getLangOpts().CPlusPlus) {7122 if (const auto *VD = dyn_cast<VarDecl>(D);7123 VD && VD->getAnyInitializer() &&7124 VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak())7125 return revisit(VD);7126 return this->emitDummyPtr(D, E);7127 }7128 7129 // ... and C++.7130 const auto *VD = dyn_cast<VarDecl>(D);7131 if (!VD)7132 return this->emitDummyPtr(D, E);7133 7134 const auto typeShouldBeVisited = [&](QualType T) -> bool {7135 if (T.isConstant(Ctx.getASTContext()))7136 return true;7137 return T->isReferenceType();7138 };7139 7140 if ((VD->hasGlobalStorage() || VD->isStaticDataMember()) &&7141 typeShouldBeVisited(VD->getType())) {7142 if (const Expr *Init = VD->getAnyInitializer();7143 Init && !Init->isValueDependent()) {7144 // Whether or not the evaluation is successul doesn't really matter7145 // here -- we will create a global variable in any case, and that7146 // will have the state of initializer evaluation attached.7147 APValue V;7148 SmallVector<PartialDiagnosticAt> Notes;7149 (void)Init->EvaluateAsInitializer(V, Ctx.getASTContext(), VD, Notes,7150 true);7151 return this->visitDeclRef(D, E);7152 }7153 return revisit(VD);7154 }7155 7156 // FIXME: The evaluateValue() check here is a little ridiculous, since7157 // it will ultimately call into Context::evaluateAsInitializer(). In7158 // other words, we're evaluating the initializer, just to know if we can7159 // evaluate the initializer.7160 if (VD->isLocalVarDecl() && typeShouldBeVisited(VD->getType()) &&7161 VD->getInit() && !VD->getInit()->isValueDependent()) {7162 7163 if (VD->evaluateValue())7164 return revisit(VD);7165 7166 if (!IsReference)7167 return this->emitDummyPtr(D, E);7168 7169 return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),7170 /*InitializerFailed=*/true, E);7171 }7172 7173 return this->emitDummyPtr(D, E);7174}7175 7176template <class Emitter>7177bool Compiler<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {7178 const auto *D = E->getDecl();7179 return this->visitDeclRef(D, E);7180}7181 7182template <class Emitter> bool Compiler<Emitter>::emitCleanup() {7183 for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) {7184 if (!C->destroyLocals())7185 return false;7186 }7187 return true;7188}7189 7190template <class Emitter>7191unsigned Compiler<Emitter>::collectBaseOffset(const QualType BaseType,7192 const QualType DerivedType) {7193 const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {7194 if (const auto *R = Ty->getPointeeCXXRecordDecl())7195 return R;7196 return Ty->getAsCXXRecordDecl();7197 };7198 const CXXRecordDecl *BaseDecl = extractRecordDecl(BaseType);7199 const CXXRecordDecl *DerivedDecl = extractRecordDecl(DerivedType);7200 7201 return Ctx.collectBaseOffset(BaseDecl, DerivedDecl);7202}7203 7204/// Emit casts from a PrimType to another PrimType.7205template <class Emitter>7206bool Compiler<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,7207 QualType ToQT, const Expr *E) {7208 7209 if (FromT == PT_Float) {7210 // Floating to floating.7211 if (ToT == PT_Float) {7212 const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);7213 return this->emitCastFP(ToSem, getRoundingMode(E), E);7214 }7215 7216 if (ToT == PT_IntAP)7217 return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(ToQT),7218 getFPOptions(E), E);7219 if (ToT == PT_IntAPS)7220 return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(ToQT),7221 getFPOptions(E), E);7222 7223 // Float to integral.7224 if (isIntegralType(ToT) || ToT == PT_Bool)7225 return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);7226 }7227 7228 if (isIntegralType(FromT) || FromT == PT_Bool) {7229 if (ToT == PT_IntAP)7230 return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E);7231 if (ToT == PT_IntAPS)7232 return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E);7233 7234 // Integral to integral.7235 if (isIntegralType(ToT) || ToT == PT_Bool)7236 return FromT != ToT ? this->emitCast(FromT, ToT, E) : true;7237 7238 if (ToT == PT_Float) {7239 // Integral to floating.7240 const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);7241 return this->emitCastIntegralFloating(FromT, ToSem, getFPOptions(E), E);7242 }7243 }7244 7245 return false;7246}7247 7248template <class Emitter>7249bool Compiler<Emitter>::emitIntegralCast(PrimType FromT, PrimType ToT,7250 QualType ToQT, const Expr *E) {7251 assert(FromT != ToT);7252 7253 if (ToT == PT_IntAP)7254 return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E);7255 if (ToT == PT_IntAPS)7256 return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E);7257 7258 return this->emitCast(FromT, ToT, E);7259}7260 7261/// Emits __real(SubExpr)7262template <class Emitter>7263bool Compiler<Emitter>::emitComplexReal(const Expr *SubExpr) {7264 assert(SubExpr->getType()->isAnyComplexType());7265 7266 if (DiscardResult)7267 return this->discard(SubExpr);7268 7269 if (!this->visit(SubExpr))7270 return false;7271 if (SubExpr->isLValue()) {7272 if (!this->emitConstUint8(0, SubExpr))7273 return false;7274 return this->emitArrayElemPtrPopUint8(SubExpr);7275 }7276 7277 // Rvalue, load the actual element.7278 return this->emitArrayElemPop(classifyComplexElementType(SubExpr->getType()),7279 0, SubExpr);7280}7281 7282template <class Emitter>7283bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {7284 assert(!DiscardResult);7285 PrimType ElemT = classifyComplexElementType(E->getType());7286 // We emit the expression (__real(E) != 0 || __imag(E) != 0)7287 // for us, that means (bool)E[0] || (bool)E[1]7288 if (!this->emitArrayElem(ElemT, 0, E))7289 return false;7290 if (ElemT == PT_Float) {7291 if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))7292 return false;7293 } else {7294 if (!this->emitCast(ElemT, PT_Bool, E))7295 return false;7296 }7297 7298 // We now have the bool value of E[0] on the stack.7299 LabelTy LabelTrue = this->getLabel();7300 if (!this->jumpTrue(LabelTrue))7301 return false;7302 7303 if (!this->emitArrayElemPop(ElemT, 1, E))7304 return false;7305 if (ElemT == PT_Float) {7306 if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))7307 return false;7308 } else {7309 if (!this->emitCast(ElemT, PT_Bool, E))7310 return false;7311 }7312 // Leave the boolean value of E[1] on the stack.7313 LabelTy EndLabel = this->getLabel();7314 this->jump(EndLabel);7315 7316 this->emitLabel(LabelTrue);7317 if (!this->emitPopPtr(E))7318 return false;7319 if (!this->emitConstBool(true, E))7320 return false;7321 7322 this->fallthrough(EndLabel);7323 this->emitLabel(EndLabel);7324 7325 return true;7326}7327 7328template <class Emitter>7329bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,7330 const BinaryOperator *E) {7331 assert(E->isComparisonOp());7332 assert(!Initializing);7333 assert(!DiscardResult);7334 7335 PrimType ElemT;7336 bool LHSIsComplex;7337 unsigned LHSOffset;7338 if (LHS->getType()->isAnyComplexType()) {7339 LHSIsComplex = true;7340 ElemT = classifyComplexElementType(LHS->getType());7341 LHSOffset = allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);7342 if (!this->visit(LHS))7343 return false;7344 if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))7345 return false;7346 } else {7347 LHSIsComplex = false;7348 PrimType LHST = classifyPrim(LHS->getType());7349 LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);7350 if (!this->visit(LHS))7351 return false;7352 if (!this->emitSetLocal(LHST, LHSOffset, E))7353 return false;7354 }7355 7356 bool RHSIsComplex;7357 unsigned RHSOffset;7358 if (RHS->getType()->isAnyComplexType()) {7359 RHSIsComplex = true;7360 ElemT = classifyComplexElementType(RHS->getType());7361 RHSOffset = allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);7362 if (!this->visit(RHS))7363 return false;7364 if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))7365 return false;7366 } else {7367 RHSIsComplex = false;7368 PrimType RHST = classifyPrim(RHS->getType());7369 RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);7370 if (!this->visit(RHS))7371 return false;7372 if (!this->emitSetLocal(RHST, RHSOffset, E))7373 return false;7374 }7375 7376 auto getElem = [&](unsigned LocalOffset, unsigned Index,7377 bool IsComplex) -> bool {7378 if (IsComplex) {7379 if (!this->emitGetLocal(PT_Ptr, LocalOffset, E))7380 return false;7381 return this->emitArrayElemPop(ElemT, Index, E);7382 }7383 return this->emitGetLocal(ElemT, LocalOffset, E);7384 };7385 7386 for (unsigned I = 0; I != 2; ++I) {7387 // Get both values.7388 if (!getElem(LHSOffset, I, LHSIsComplex))7389 return false;7390 if (!getElem(RHSOffset, I, RHSIsComplex))7391 return false;7392 // And compare them.7393 if (!this->emitEQ(ElemT, E))7394 return false;7395 7396 if (!this->emitCastBoolUint8(E))7397 return false;7398 }7399 7400 // We now have two bool values on the stack. Compare those.7401 if (!this->emitAddUint8(E))7402 return false;7403 if (!this->emitConstUint8(2, E))7404 return false;7405 7406 if (E->getOpcode() == BO_EQ) {7407 if (!this->emitEQUint8(E))7408 return false;7409 } else if (E->getOpcode() == BO_NE) {7410 if (!this->emitNEUint8(E))7411 return false;7412 } else7413 return false;7414 7415 // In C, this returns an int.7416 if (PrimType ResT = classifyPrim(E->getType()); ResT != PT_Bool)7417 return this->emitCast(PT_Bool, ResT, E);7418 return true;7419}7420 7421/// When calling this, we have a pointer of the local-to-destroy7422/// on the stack.7423/// Emit destruction of record types (or arrays of record types).7424template <class Emitter>7425bool Compiler<Emitter>::emitRecordDestructionPop(const Record *R,7426 SourceInfo Loc) {7427 assert(R);7428 assert(!R->hasTrivialDtor());7429 const CXXDestructorDecl *Dtor = R->getDestructor();7430 assert(Dtor);7431 const Function *DtorFunc = getFunction(Dtor);7432 if (!DtorFunc)7433 return false;7434 assert(DtorFunc->hasThisPointer());7435 assert(DtorFunc->getNumParams() == 1);7436 return this->emitCall(DtorFunc, 0, Loc);7437}7438/// When calling this, we have a pointer of the local-to-destroy7439/// on the stack.7440/// Emit destruction of record types (or arrays of record types).7441template <class Emitter>7442bool Compiler<Emitter>::emitDestructionPop(const Descriptor *Desc,7443 SourceInfo Loc) {7444 assert(Desc);7445 assert(!Desc->hasTrivialDtor());7446 7447 // Arrays.7448 if (Desc->isArray()) {7449 const Descriptor *ElemDesc = Desc->ElemDesc;7450 assert(ElemDesc);7451 7452 unsigned N = Desc->getNumElems();7453 if (N == 0)7454 return this->emitPopPtr(Loc);7455 7456 for (ssize_t I = N - 1; I >= 1; --I) {7457 if (!this->emitConstUint64(I, Loc))7458 return false;7459 if (!this->emitArrayElemPtrUint64(Loc))7460 return false;7461 if (!this->emitDestructionPop(ElemDesc, Loc))7462 return false;7463 }7464 // Last iteration, removes the instance pointer from the stack.7465 if (!this->emitConstUint64(0, Loc))7466 return false;7467 if (!this->emitArrayElemPtrPopUint64(Loc))7468 return false;7469 return this->emitDestructionPop(ElemDesc, Loc);7470 }7471 7472 assert(Desc->ElemRecord);7473 assert(!Desc->ElemRecord->hasTrivialDtor());7474 return this->emitRecordDestructionPop(Desc->ElemRecord, Loc);7475}7476 7477/// Create a dummy pointer for the given decl (or expr) and7478/// push a pointer to it on the stack.7479template <class Emitter>7480bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {7481 assert(!DiscardResult && "Should've been checked before");7482 7483 unsigned DummyID = P.getOrCreateDummy(D);7484 7485 if (!this->emitGetPtrGlobal(DummyID, E))7486 return false;7487 if (E->getType()->isVoidType())7488 return true;7489 7490 // Convert the dummy pointer to another pointer type if we have to.7491 if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {7492 if (isPtrType(PT))7493 return this->emitDecayPtr(PT_Ptr, PT, E);7494 return false;7495 }7496 return true;7497}7498 7499template <class Emitter>7500bool Compiler<Emitter>::emitFloat(const APFloat &F, const Expr *E) {7501 assert(!DiscardResult && "Should've been checked before");7502 7503 if (Floating::singleWord(F.getSemantics()))7504 return this->emitConstFloat(Floating(F), E);7505 7506 APInt I = F.bitcastToAPInt();7507 return this->emitConstFloat(7508 Floating(const_cast<uint64_t *>(I.getRawData()),7509 llvm::APFloatBase::SemanticsToEnum(F.getSemantics())),7510 E);7511}7512 7513// This function is constexpr if and only if To, From, and the types of7514// all subobjects of To and From are types T such that...7515// (3.1) - is_union_v<T> is false;7516// (3.2) - is_pointer_v<T> is false;7517// (3.3) - is_member_pointer_v<T> is false;7518// (3.4) - is_volatile_v<T> is false; and7519// (3.5) - T has no non-static data members of reference type7520template <class Emitter>7521bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {7522 const Expr *SubExpr = E->getSubExpr();7523 QualType FromType = SubExpr->getType();7524 QualType ToType = E->getType();7525 OptPrimType ToT = classify(ToType);7526 7527 assert(!ToType->isReferenceType());7528 7529 // Prepare storage for the result in case we discard.7530 if (DiscardResult && !Initializing && !ToT) {7531 UnsignedOrNone LocalIndex = allocateLocal(E);7532 if (!LocalIndex)7533 return false;7534 if (!this->emitGetPtrLocal(*LocalIndex, E))7535 return false;7536 }7537 7538 // Get a pointer to the value-to-cast on the stack.7539 // For CK_LValueToRValueBitCast, this is always an lvalue and7540 // we later assume it to be one (i.e. a PT_Ptr). However,7541 // we call this function for other utility methods where7542 // a bitcast might be useful, so convert it to a PT_Ptr in that case.7543 if (SubExpr->isGLValue() || FromType->isVectorType()) {7544 if (!this->visit(SubExpr))7545 return false;7546 } else if (OptPrimType FromT = classify(SubExpr)) {7547 unsigned TempOffset =7548 allocateLocalPrimitive(SubExpr, *FromT, /*IsConst=*/true);7549 if (!this->visit(SubExpr))7550 return false;7551 if (!this->emitSetLocal(*FromT, TempOffset, E))7552 return false;7553 if (!this->emitGetPtrLocal(TempOffset, E))7554 return false;7555 } else {7556 return false;7557 }7558 7559 if (!ToT) {7560 if (!this->emitBitCast(E))7561 return false;7562 return DiscardResult ? this->emitPopPtr(E) : true;7563 }7564 assert(ToT);7565 7566 const llvm::fltSemantics *TargetSemantics = nullptr;7567 if (ToT == PT_Float)7568 TargetSemantics = &Ctx.getFloatSemantics(ToType);7569 7570 // Conversion to a primitive type. FromType can be another7571 // primitive type, or a record/array.7572 bool ToTypeIsUChar = (ToType->isSpecificBuiltinType(BuiltinType::UChar) ||7573 ToType->isSpecificBuiltinType(BuiltinType::Char_U));7574 uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);7575 7576 if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->isStdByteType(),7577 ResultBitWidth, TargetSemantics,7578 ToType.getTypePtr(), E))7579 return false;7580 7581 if (DiscardResult)7582 return this->emitPop(*ToT, E);7583 7584 return true;7585}7586 7587namespace clang {7588namespace interp {7589 7590template class Compiler<ByteCodeEmitter>;7591template class Compiler<EvalEmitter>;7592 7593} // namespace interp7594} // namespace clang7595