19#include "llvm/Support/SaveAndRestore.h"
30 if (
const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
31 CE && CE->hasAPValueResult() &&
33 return CE->getResultAsAPSInt().getBoolValue();
44 OldInitializingDecl(
Ctx->InitializingDecl) {
45 Ctx->InitializingDecl = VD;
50 this->
Ctx->InitializingDecl = OldInitializingDecl;
51 this->
Ctx->InitStack.pop_back();
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;
73 Ctx->DiscardResult = OldDiscardResult;
74 Ctx->Initializing = OldInitializing;
75 Ctx->ToLValue = OldToLValue;
82 bool OldDiscardResult;
87template <
class Emitter>
91 return Ctx->emitThis(E);
94 return Ctx->emitGetPtrFieldPop(
Offset, E);
96 return Ctx->emitGetPtrLocal(
Offset, E);
100 if (!Ctx->emitConstUint32(
Offset, E))
102 return Ctx->emitArrayElemPtrPopUint32(E);
104 return Ctx->emitRVOPtr(E);
108 llvm_unreachable(
"Unhandled InitLink kind");
124 for (
const LabelInfo &LI : Ctx->LabelInfoStack)
125 assert(LI.Name != Name);
128 this->Ctx->LabelInfoStack.emplace_back(Name, BreakLabel, ContinueLabel,
149 : Ctx(Ctx), OldCaseLabels(
std::move(this->Ctx->CaseLabels)) {
151 for (
const LabelInfo &LI : Ctx->LabelInfoStack)
152 assert(LI.Name != Name);
155 this->Ctx->CaseLabels = std::move(CaseLabels);
156 this->Ctx->LabelInfoStack.emplace_back(Name, BreakLabel,
158 DefaultLabel, Ctx->VarScope);
162 this->Ctx->CaseLabels = std::move(OldCaseLabels);
163 this->Ctx->LabelInfoStack.pop_back();
168 CaseMap OldCaseLabels;
179 : Ctx(Ctx), OldFlag(Ctx->LocOverride), Enabled(Enabled) {
182 Ctx->LocOverride = NewValue;
187 Ctx->LocOverride = OldFlag;
192 std::optional<SourceInfo> OldFlag;
199template <
class Emitter>
207 case CK_LValueToRValue: {
218 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
224 if (
auto GlobalIndex =
P.getGlobal(D))
225 return this->emitGetGlobal(*SubExprT, *GlobalIndex, E);
226 }
else if (
auto It =
Locals.find(D); It !=
Locals.end()) {
227 return this->emitGetLocal(*SubExprT, It->second.Offset, E);
228 }
else if (
const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
229 if (
auto It = this->Params.find(PVD); It != this->Params.end()) {
230 return this->emitGetParam(*SubExprT, It->second.Index, E);
242 if (!this->emitGetPtrLocal(*LocalIndex, E))
246 if (!this->
visit(SubExpr))
250 return this->emitLoadPop(*SubExprT, E);
255 return this->emitMemcpy(E);
258 case CK_DerivedToBaseMemberPointer: {
269 ->getMostRecentCXXRecordDecl();
271 const CXXRecordDecl *ToDecl = B->getType()->getAsCXXRecordDecl();
272 unsigned DerivedOffset =
Ctx.collectBaseOffset(ToDecl, CurDecl);
274 if (!this->emitCastMemberPtrBasePop(DerivedOffset, ToDecl, E))
282 case CK_BaseToDerivedMemberPointer: {
293 ->getMostRecentCXXRecordDecl();
297 typedef std::reverse_iterator<CastExpr::path_const_iterator> ReverseIter;
299 PathI != PathE; ++PathI) {
300 const CXXRecordDecl *ToDecl = (*PathI)->getType()->getAsCXXRecordDecl();
301 unsigned DerivedOffset =
Ctx.collectBaseOffset(CurDecl, ToDecl);
303 if (!this->emitCastMemberPtrDerivedPop(-DerivedOffset, ToDecl, E))
310 assert(ToDecl != CurDecl);
311 unsigned DerivedOffset =
Ctx.collectBaseOffset(CurDecl, ToDecl);
313 if (!this->emitCastMemberPtrDerivedPop(-DerivedOffset, ToDecl, E))
319 case CK_UncheckedDerivedToBase:
320 case CK_DerivedToBase: {
325 if (
const auto *PT = dyn_cast<PointerType>(Ty))
326 return PT->getPointeeType()->getAsCXXRecordDecl();
327 return Ty->getAsCXXRecordDecl();
334 if (B->isVirtual()) {
335 if (!this->emitGetPtrVirtBasePop(extractRecordDecl(B->getType()), E))
337 CurType = B->getType();
339 unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType);
340 if (!this->emitGetPtrBasePop(
343 CurType = B->getType();
350 case CK_BaseToDerived: {
353 unsigned DerivedOffset =
359 return this->emitGetPtrDerivedPop(DerivedOffset,
364 case CK_FloatingCast: {
367 return this->emitVectorConversion(E->
getSubExpr(), E);
371 if (!this->
visit(SubExpr))
373 const auto *TargetSemantics = &
Ctx.getFloatSemantics(E->
getType());
377 case CK_IntegralToFloating: {
379 return this->emitVectorConversion(E->
getSubExpr(), E);
382 if (!this->
visit(SubExpr))
384 const auto *TargetSemantics = &
Ctx.getFloatSemantics(E->
getType());
385 return this->emitCastIntegralFloating(
classifyPrim(SubExpr),
386 TargetSemantics, getFPOptions(E), E);
389 case CK_FloatingToBoolean: {
391 return this->emitVectorConversion(E->
getSubExpr(), E);
395 if (
const auto *FL = dyn_cast<FloatingLiteral>(SubExpr))
396 return this->emitConstBool(FL->getValue().isNonZero(), E);
397 if (!this->
visit(SubExpr))
399 return this->emitCastFloatingIntegralBool(getFPOptions(E), E);
402 case CK_FloatingToIntegral: {
404 return this->emitVectorConversion(E->
getSubExpr(), E);
407 if (!this->
visit(SubExpr))
411 return this->emitCastFloatingIntegralAP(
Ctx.getBitWidth(E->
getType()),
414 return this->emitCastFloatingIntegralAPS(
Ctx.getBitWidth(E->
getType()),
417 return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);
420 case CK_NullToPointer:
421 case CK_NullToMemberPointer: {
424 uint64_t Val =
Ctx.getASTContext().getTargetNullPointerValue(E->
getType());
429 case CK_PointerToIntegral: {
430 if (!this->
visit(SubExpr))
436 if (!this->emitDecayPtr(FromT,
PT_Ptr, E))
442 return this->emitCastPointerIntegralAP(
Ctx.getBitWidth(E->
getType()), E);
444 return this->emitCastPointerIntegralAPS(
Ctx.getBitWidth(E->
getType()), E);
445 return this->emitCastPointerIntegral(T, E);
448 case CK_ArrayToPointerDecay: {
449 if (!this->
visit(SubExpr))
451 return this->emitArrayDecay(E);
454 case CK_IntegralToPointer: {
456 assert(IntType->isIntegralOrEnumerationType());
457 if (!this->
visit(SubExpr))
471 return this->emitDecayPtr(
PT_Ptr, DestPtrT, E);
474 case CK_AtomicToNonAtomic:
475 case CK_ConstructorConversion:
476 case CK_FunctionToPointerDecay:
477 case CK_NonAtomicToAtomic:
479 case CK_UserDefinedConversion:
480 case CK_AddressSpaceConversion:
481 case CK_CPointerToObjCPointerCast:
498 return this->emitBuiltinBitCast(E);
513 if (!this->
visit(SubExpr))
521 return this->emitFnPtrCast(E);
528 if (!this->
visit(SubExpr))
530 return this->emitDecayPtr(*FromT, *ToT, E);
532 case CK_IntegralToBoolean:
533 case CK_FixedPointToBoolean: {
535 return this->emitVectorConversion(E->
getSubExpr(), E);
541 if (
const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))
542 return this->emitConst(IL->getValue(), E);
543 if (!this->
visit(SubExpr))
548 case CK_IntegralCast:
550 return this->emitVectorConversion(E->
getSubExpr(), E);
552 case CK_BooleanToSignedIntegral: {
559 if (
const auto *IL = dyn_cast<IntegerLiteral>(SubExpr)) {
564 if (!this->emitConst(IL->getValue(), SubExpr))
567 if (!this->
visit(SubExpr))
575 if (!ED->isFixed()) {
576 if (!this->emitCheckEnumValue(*FromT, ED, E))
582 if (!this->emitCastAP(*FromT,
Ctx.getBitWidth(E->
getType()), E))
585 if (!this->emitCastAPS(*FromT,
Ctx.getBitWidth(E->
getType()), E))
590 if (!this->emitCast(*FromT, *ToT, E))
593 if (E->
getCastKind() == CK_BooleanToSignedIntegral)
594 return this->emitNeg(*ToT, E);
598 case CK_PointerToBoolean:
599 case CK_MemberPointerToBoolean: {
602 if (!this->
visit(SubExpr))
604 return this->emitIsNonNull(PtrT, E);
607 case CK_IntegralComplexToBoolean:
608 case CK_FloatingComplexToBoolean: {
609 if (!this->
visit(SubExpr))
611 return this->emitComplexBoolCast(SubExpr);
614 case CK_IntegralComplexToReal:
615 case CK_FloatingComplexToReal:
616 return this->emitComplexReal(SubExpr);
618 case CK_IntegralRealToComplex:
619 case CK_FloatingRealToComplex: {
626 if (!this->emitGetPtrLocal(*LocalIndex, E))
635 if (!this->visitZeroInitializer(T, SubExpr->
getType(), SubExpr))
637 return this->emitInitElem(T, 1, SubExpr);
640 case CK_IntegralComplexCast:
641 case CK_FloatingComplexCast:
642 case CK_IntegralComplexToFloatingComplex:
643 case CK_FloatingComplexToIntegralComplex: {
650 if (!this->emitGetPtrLocal(*LocalIndex, E))
657 unsigned SubExprOffset =
659 if (!this->
visit(SubExpr))
661 if (!this->emitSetLocal(
PT_Ptr, SubExprOffset, E))
669 for (
unsigned I = 0; I != 2; ++I) {
670 if (!this->emitGetLocal(
PT_Ptr, SubExprOffset, E))
672 if (!this->emitArrayElemPop(SourceElemT, I, E))
676 if (!this->emitPrimCast(SourceElemT, DestElemT, DestElemType, E))
680 if (!this->emitInitElem(DestElemT, I, E))
686 case CK_VectorSplat: {
697 if (!this->emitGetPtrLocal(*LocalIndex, E))
703 unsigned ElemOffset =
707 if (!this->
visit(SubExpr))
712 if (!this->emitSetLocal(ElemT, ElemOffset, E))
715 for (
unsigned I = 0; I != VT->getNumElements(); ++I) {
716 if (!this->emitGetLocal(ElemT, ElemOffset, E))
718 if (!this->emitInitElem(ElemT, I, E))
725 case CK_HLSLVectorTruncation: {
730 if (!this->
visit(SubExpr))
732 return this->emitArrayElemPop(*ResultT, 0, E);
741 if (!this->emitGetPtrLocal(*LocalIndex, E))
746 if (!this->
visit(SubExpr))
748 return this->emitCopyArray(classifyVectorElementType(E->
getType()), 0, 0,
752 case CK_IntegralToFixedPoint: {
753 if (!this->
visit(SubExpr))
757 Ctx.getASTContext().getFixedPointSemantics(E->
getType()).toOpaqueInt();
762 return this->emitPopFixedPoint(E);
765 case CK_FloatingToFixedPoint: {
766 if (!this->
visit(SubExpr))
770 Ctx.getASTContext().getFixedPointSemantics(E->
getType()).toOpaqueInt();
771 if (!this->emitCastFloatingFixedPoint(Sem, E))
774 return this->emitPopFixedPoint(E);
777 case CK_FixedPointToFloating: {
778 if (!this->
visit(SubExpr))
780 const auto *TargetSemantics = &
Ctx.getFloatSemantics(E->
getType());
781 if (!this->emitCastFixedPointFloating(TargetSemantics, E))
784 return this->emitPopFloat(E);
787 case CK_FixedPointToIntegral: {
788 if (!this->
visit(SubExpr))
791 if (!this->emitCastFixedPointIntegral(IntegralT, E))
794 return this->emitPop(IntegralT, E);
797 case CK_FixedPointCast: {
798 if (!this->
visit(SubExpr))
801 Ctx.getASTContext().getFixedPointSemantics(E->
getType()).toOpaqueInt();
802 if (!this->emitCastFixedPoint(Sem, E))
805 return this->emitPopFixedPoint(E);
813 llvm_unreachable(
"CXXDynamicCastExpr has its own function");
815 case CK_LValueBitCast:
820 case CK_HLSLArrayRValue: {
827 if (!this->emitGetPtrLocal(*LocalIndex, E))
830 if (!this->
visit(SubExpr))
832 return this->emitMemcpy(E);
835 case CK_HLSLMatrixTruncation: {
840 if (!this->
visit(SubExpr))
842 return this->emitArrayElemPop(*ResultT, 0, E);
851 if (!this->emitGetPtrLocal(*LocalIndex, E))
856 if (!this->
visit(SubExpr))
858 return this->emitCopyArray(classifyMatrixElementType(SubExpr->
getType()), 0,
862 case CK_HLSLAggregateSplatCast: {
872 if (!this->emitGetPtrLocal(*LocalIndex, E))
882 if (!this->
visit(SubExpr))
884 if (!this->emitSetLocal(SrcElemT, SrcOffset, E))
888 return emitHLSLAggregateSplat(SrcElemT, SrcOffset, E->
getType(), E);
891 case CK_HLSLElementwiseCast: {
902 unsigned SrcPtrOffset =
904 if (!this->
visit(SubExpr))
906 if (!this->emitSetLocal(
PT_Ptr, SrcPtrOffset, E))
910 if (!emitHLSLFlattenAggregate(SrcType, SrcPtrOffset, Elements, 1, E))
912 if (Elements.empty())
915 const HLSLFlatElement &Src = Elements[0];
916 if (!this->emitGetLocal(Src.Type, Src.LocalOffset, E))
918 return this->emitPrimCast(Src.Type, *DestT, DestType, E);
925 if (!this->emitGetPtrLocal(*LocalIndex, E))
931 if (!this->
visit(SubExpr))
933 if (!this->emitSetLocal(
PT_Ptr, SrcOffset, E))
937 unsigned ElemCount = countHLSLFlatElements(DestType);
940 Elements.reserve(ElemCount);
941 if (!emitHLSLFlattenAggregate(SrcType, SrcOffset, Elements, ElemCount, E))
946 assert(Elements.size() == ElemCount &&
947 "Source type has fewer scalar elements than the destination type");
949 return emitHLSLConstructAggregate(DestType, Elements, E);
956 const Record::Field *RF = R->getField(UnionField);
957 QualType FieldType = RF->Decl->getType();
960 if (!this->
visit(SubExpr))
962 if (RF->isBitField())
963 return this->emitInitBitFieldActivate(*PT, RF->Offset, RF->bitWidth(),
965 return this->emitInitFieldActivate(*PT, RF->Offset, E);
968 if (!this->emitGetPtrField(RF->Offset, E))
970 if (!this->emitActivate(E))
976 return this->emitInvalid(E);
978 llvm_unreachable(
"Unhandled clang::CastKind enum");
981template <
class Emitter>
983 return this->emitBuiltinBitCast(E);
986template <
class Emitter>
991 return this->emitConst(
LE->getValue(),
LE);
994template <
class Emitter>
1000 return this->emitFloat(F, E);
1003template <
class Emitter>
1013 if (!this->emitGetPtrLocal(*LocalIndex, E))
1020 if (!this->visitZeroInitializer(SubExprT, SubExpr->
getType(), SubExpr))
1022 if (!this->emitInitElem(SubExprT, 0, SubExpr))
1027template <
class Emitter>
1035 auto Sem =
Ctx.getASTContext().getFixedPointSemantics(E->
getType());
1040template <
class Emitter>
1045template <
class Emitter>
1072 return this->emitComplexComparison(LHS, RHS, E);
1080 if (!this->
visit(LHS))
1083 if (!this->
visit(RHS))
1086 if (!this->emitToMemberPtr(E))
1092 if (!this->emitCastMemberPtrPtr(E))
1109 Ctx.getASTContext().CompCategories.lookupInfoForType(E->
getType());
1115 if (!this->emitGetPtrLocal(*ResultIndex, E))
1122 return this->emitCMP3(*
LT, CmpInfo, E);
1125 if (!
LT || !RT || !T)
1135 return this->visitAssignment(LHS, RHS, E);
1142 auto MaybeCastToBool = [
this, T, E](
bool Result) {
1146 return this->emitPopBool(E);
1148 return this->emitCast(
PT_Bool, *T, E);
1152 auto Discard = [
this, T, E](
bool Result) {
1160 return MaybeCastToBool(this->emitEQ(*
LT, E));
1162 return MaybeCastToBool(this->emitNE(*
LT, E));
1164 return MaybeCastToBool(this->emitLT(*
LT, E));
1166 return MaybeCastToBool(this->emitLE(*
LT, E));
1168 return MaybeCastToBool(this->emitGT(*
LT, E));
1170 return MaybeCastToBool(this->emitGE(*
LT, E));
1173 return Discard(this->emitSubf(getFPOptions(E), E));
1174 return Discard(this->emitSub(*T, E));
1177 return Discard(this->emitAddf(getFPOptions(E), E));
1178 return Discard(this->emitAdd(*T, E));
1181 return Discard(this->emitMulf(getFPOptions(E), E));
1182 return Discard(this->emitMul(*T, E));
1184 return Discard(this->emitRem(*T, E));
1187 return Discard(this->emitDivf(getFPOptions(E), E));
1188 return Discard(this->emitDiv(*T, E));
1190 return Discard(this->emitBitAnd(*T, E));
1192 return Discard(this->emitBitOr(*T, E));
1194 return Discard(this->emitShl(*
LT, *RT, E));
1196 return Discard(this->emitShr(*
LT, *RT, E));
1198 return Discard(this->emitBitXor(*T, E));
1201 llvm_unreachable(
"Already handled earlier");
1206 llvm_unreachable(
"Unhandled binary op");
1211template <
class Emitter>
1217 if ((Op != BO_Add && Op != BO_Sub) ||
1228 auto visitAsPointer = [&](
const Expr *E,
PrimType T) ->
bool {
1229 if (!this->
visit(E))
1232 return this->emitDecayPtr(T,
PT_Ptr, E);
1241 if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *
LT))
1249 ElemTypeSize =
Ctx.getASTContext().getTypeSizeInChars(ElemType);
1252 if (!this->emitSubPtr(IntT, ElemTypeSize.
isZero(), E))
1259 if (!visitAsPointer(RHS, *RT))
1261 if (!this->
visit(LHS))
1265 if (!visitAsPointer(LHS, *
LT))
1267 if (!this->
visit(RHS))
1278 if (!this->emitAddOffset(OffsetType, E))
1282 if (!this->emitSubOffset(OffsetType, E))
1299template <
class Emitter>
1309 LabelTy LabelTrue = this->getLabel();
1310 LabelTy LabelEnd = this->getLabel();
1314 if (!this->jumpTrue(LabelTrue, E))
1319 if (!this->jump(LabelEnd, E))
1322 this->emitLabel(LabelTrue);
1323 this->emitConstBool(
true, E);
1324 this->fallthrough(LabelEnd);
1325 this->emitLabel(LabelEnd);
1328 assert(Op == BO_LAnd);
1331 LabelTy LabelFalse = this->getLabel();
1332 LabelTy LabelEnd = this->getLabel();
1336 if (!this->jumpFalse(LabelFalse, E))
1341 if (!this->jump(LabelEnd, E))
1344 this->emitLabel(LabelFalse);
1345 this->emitConstBool(
false, E);
1346 this->fallthrough(LabelEnd);
1347 this->emitLabel(LabelEnd);
1351 return this->emitPopBool(E);
1356 return this->emitCast(
PT_Bool, *T, E);
1360template <
class Emitter>
1367 if (!this->emitGetPtrLocal(*LocalIndex, E))
1376 PrimType ResultElemT = this->classifyComplexElementType(E->
getType());
1377 unsigned ResultOffset = ~0u;
1383 if (!this->emitDupPtr(E))
1385 if (!this->emitSetLocal(
PT_Ptr, ResultOffset, E))
1390 LHSType = AT->getValueType();
1393 RHSType = AT->getValueType();
1402 if (Op == BO_Mul && LHSIsComplex && RHSIsComplex) {
1407 if (!this->
visit(LHS))
1409 if (!this->
visit(RHS))
1411 if (!this->emitMulc(ElemT, E))
1414 return this->emitPopPtr(E);
1418 if (Op == BO_Div && RHSIsComplex) {
1425 if (!LHSIsComplex) {
1430 LHSOffset = *LocalIndex;
1432 if (!this->emitGetPtrLocal(LHSOffset, E))
1435 if (!this->
visit(LHS))
1438 if (!this->emitInitElem(ElemT, 0, E))
1441 if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1443 if (!this->emitInitElem(ElemT, 1, E))
1446 if (!this->
visit(LHS))
1450 if (!this->
visit(RHS))
1452 if (!this->emitDivc(ElemT, E))
1455 return this->emitPopPtr(E);
1462 if (!this->
visit(LHS))
1464 if (!this->emitSetLocal(
PT_Ptr, LHSOffset, E))
1469 if (!this->
visit(LHS))
1471 if (!this->emitSetLocal(LHST, LHSOffset, E))
1479 if (!this->
visit(RHS))
1481 if (!this->emitSetLocal(
PT_Ptr, RHSOffset, E))
1486 if (!this->
visit(RHS))
1488 if (!this->emitSetLocal(RHST, RHSOffset, E))
1495 auto loadComplexValue = [
this](
bool IsComplex,
bool LoadZero,
1496 unsigned ElemIndex,
unsigned Offset,
1497 const Expr *E) ->
bool {
1499 if (!this->emitGetLocal(
PT_Ptr, Offset, E))
1501 return this->emitArrayElemPop(classifyComplexElementType(E->
getType()),
1504 if (ElemIndex == 0 || !LoadZero)
1511 for (
unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) {
1514 if (!this->emitGetLocal(
PT_Ptr, ResultOffset, E))
1521 if (!loadComplexValue(LHSIsComplex,
true, ElemIndex, LHSOffset, LHS))
1524 if (!loadComplexValue(RHSIsComplex,
true, ElemIndex, RHSOffset, RHS))
1527 if (!this->emitAddf(getFPOptions(E), E))
1530 if (!this->emitAdd(ResultElemT, E))
1535 if (!loadComplexValue(LHSIsComplex,
true, ElemIndex, LHSOffset, LHS))
1538 if (!loadComplexValue(RHSIsComplex,
true, ElemIndex, RHSOffset, RHS))
1541 if (!this->emitSubf(getFPOptions(E), E))
1544 if (!this->emitSub(ResultElemT, E))
1549 if (!loadComplexValue(LHSIsComplex,
false, ElemIndex, LHSOffset, LHS))
1552 if (!loadComplexValue(RHSIsComplex,
false, ElemIndex, RHSOffset, RHS))
1556 if (!this->emitMulf(getFPOptions(E), E))
1559 if (!this->emitMul(ResultElemT, E))
1564 assert(!RHSIsComplex);
1565 if (!loadComplexValue(LHSIsComplex,
false, ElemIndex, LHSOffset, LHS))
1568 if (!loadComplexValue(RHSIsComplex,
false, ElemIndex, RHSOffset, RHS))
1572 if (!this->emitDivf(getFPOptions(E), E))
1575 if (!this->emitDiv(ResultElemT, E))
1586 if (!this->emitInitElemPop(ResultElemT, ElemIndex, E))
1589 if (!this->emitPop(ResultElemT, E))
1594 return this->emitPopPtr(E);
1600template <
class Emitter>
1605 "Comma op should be handled in VisitBinaryOperator");
1619 if (!this->emitGetPtrLocal(*LocalIndex, E))
1633 assert(
Ctx.getASTContext().hasSameUnqualifiedType(
1636 if (!this->
visit(LHS))
1638 if (!this->
visit(RHS))
1640 if (!this->emitCopyArray(ElemT, 0, 0, VecTy->getNumElements(), E))
1643 return this->emitPopPtr(E);
1648 unsigned LHSOffset =
1650 if (!this->
visit(LHS))
1652 if (!this->emitSetLocal(
PT_Ptr, LHSOffset, E))
1656 unsigned RHSOffset =
1658 if (!this->
visit(RHS))
1660 if (!this->emitSetLocal(
PT_Ptr, RHSOffset, E))
1672 if (NeedIntPromot) {
1674 Ctx.getASTContext().getPromotedIntegerType(
Ctx.getASTContext().BoolTy);
1679 auto getElem = [=](
unsigned Offset,
PrimType ElemT,
unsigned Index) {
1680 if (!this->emitGetLocal(
PT_Ptr, Offset, E))
1682 if (!this->emitArrayElemPop(ElemT, Index, E))
1685 if (!this->emitPrimCast(ElemT,
PT_Bool,
Ctx.getASTContext().BoolTy, E))
1687 if (!this->emitPrimCast(
PT_Bool, ResultElemT, VecTy->getElementType(), E))
1689 }
else if (NeedIntPromot) {
1690 if (!this->emitPrimCast(ElemT, PromotT, PromotTy, E))
1696#define EMIT_ARITH_OP(OP) \
1698 if (ElemT == PT_Float) { \
1699 if (!this->emit##OP##f(getFPOptions(E), E)) \
1702 if (!this->emit##OP(ElemT, E)) \
1708 for (
unsigned I = 0; I != VecTy->getNumElements(); ++I) {
1709 if (!getElem(LHSOffset, ElemT, I))
1711 if (!getElem(RHSOffset, RHSElemT, I))
1723 if (!this->emitRem(ElemT, E))
1727 if (!this->emitBitAnd(OpT, E))
1731 if (!this->emitBitOr(OpT, E))
1735 if (!this->emitBitXor(OpT, E))
1739 if (!this->emitShl(OpT, RHSElemT, E))
1743 if (!this->emitShr(OpT, RHSElemT, E))
1747 if (!this->emitEQ(ElemT, E))
1751 if (!this->emitNE(ElemT, E))
1755 if (!this->emitLE(ElemT, E))
1759 if (!this->emitLT(ElemT, E))
1763 if (!this->emitGE(ElemT, E))
1767 if (!this->emitGT(ElemT, E))
1772 if (!this->emitBitAnd(ResultElemT, E))
1777 if (!this->emitBitOr(ResultElemT, E))
1781 return this->emitInvalid(E);
1790 if (!this->emitPrimCast(
PT_Bool, ResultElemT, VecTy->getElementType(), E))
1792 if (!this->emitNeg(ResultElemT, E))
1798 if (NeedIntPromot &&
1799 !this->emitPrimCast(PromotT, ResultElemT, VecTy->getElementType(), E))
1803 if (!this->emitInitElem(ResultElemT, I, E))
1812template <
class Emitter>
1822 auto LHSSemaInt = LHSSema.toOpaqueInt();
1824 auto RHSSemaInt = RHSSema.toOpaqueInt();
1826 if (!this->
visit(LHS))
1834 if (!this->
visit(RHS))
1843 auto ConvertResult = [&](
bool R) ->
bool {
1847 auto CommonSema = LHSSema.getCommonSemantics(RHSSema).toOpaqueInt();
1848 if (ResultSema != CommonSema)
1849 return this->emitCastFixedPoint(ResultSema, E);
1853 auto MaybeCastToBool = [&](
bool Result) {
1858 return this->emitPop(T, E);
1860 return this->emitCast(
PT_Bool, T, E);
1866 return MaybeCastToBool(this->emitEQFixedPoint(E));
1868 return MaybeCastToBool(this->emitNEFixedPoint(E));
1870 return MaybeCastToBool(this->emitLTFixedPoint(E));
1872 return MaybeCastToBool(this->emitLEFixedPoint(E));
1874 return MaybeCastToBool(this->emitGTFixedPoint(E));
1876 return MaybeCastToBool(this->emitGEFixedPoint(E));
1878 return ConvertResult(this->emitAddFixedPoint(E));
1880 return ConvertResult(this->emitSubFixedPoint(E));
1882 return ConvertResult(this->emitMulFixedPoint(E));
1884 return ConvertResult(this->emitDivFixedPoint(E));
1886 return ConvertResult(this->emitShiftFixedPoint(
true, E));
1888 return ConvertResult(this->emitShiftFixedPoint(
false, E));
1891 return this->emitInvalid(E);
1894 llvm_unreachable(
"unhandled binop opcode");
1897template <
class Emitter>
1906 if (!this->
visit(SubExpr))
1908 if (!this->emitNegFixedPoint(E))
1911 return this->emitPopFixedPoint(E);
1917 llvm_unreachable(
"Unhandled unary opcode");
1920template <
class Emitter>
1929 return this->visitZeroInitializer(*T, QT, E);
1937 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
1938 CXXRD && CXXRD->getNumVBases() > 0) {
1948 return this->visitZeroRecordInitializer(R, E);
1955 return this->visitZeroArrayInitializer(QT, E);
1959 QualType ElemQT = ComplexTy->getElementType();
1961 for (
unsigned I = 0; I < 2; ++I) {
1962 if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1964 if (!this->emitInitElem(ElemT, I, E))
1971 unsigned NumVecElements = VecT->getNumElements();
1972 QualType ElemQT = VecT->getElementType();
1975 for (
unsigned I = 0; I < NumVecElements; ++I) {
1976 if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1978 if (!this->emitInitElem(ElemT, I, E))
1985 unsigned NumElems = MT->getNumElementsFlattened();
1986 QualType ElemQT = MT->getElementType();
1989 for (
unsigned I = 0; I != NumElems; ++I) {
1990 if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1992 if (!this->emitInitElem(ElemT, I, E))
2001template <
class Emitter>
2014 for (
const Expr *SubExpr : {LHS, RHS}) {
2015 if (!this->
visit(SubExpr)) {
2022 if (SubExpr ==
Base &&
Base->getType()->isPointerType()) {
2023 if (!this->emitExpandPtr(E))
2034 return this->emitError(E);
2037 if (!this->emitFlip(
PT_Ptr, *IndexT, E))
2041 if (!this->emitArrayElemPtrPop(*IndexT, E))
2044 return this->emitPopPtr(E);
2050 return this->emitLoadPop(*T, E);
2053template <
class Emitter>
2055 const Expr *ArrayFiller,
const Expr *E) {
2060 QT = AT->getValueType();
2063 if (
Inits.size() == 0)
2065 return this->emitInvalid(E);
2080 if (
Inits.size() == 0)
2081 return this->visitZeroInitializer(*T, QT, E);
2082 assert(
Inits.size() == 1);
2095 auto initPrimitiveField = [=](
const Record::Field *FieldToInit,
2102 bool BitField = FieldToInit->isBitField();
2104 return this->emitInitBitFieldActivate(T, FieldToInit->Offset,
2105 FieldToInit->bitWidth(), E);
2107 return this->emitInitBitField(T, FieldToInit->Offset,
2108 FieldToInit->bitWidth(), E);
2110 return this->emitInitFieldActivate(T, FieldToInit->Offset, E);
2111 return this->emitInitField(T, FieldToInit->Offset, E);
2114 auto initCompositeField = [=](
const Record::Field *FieldToInit,
2122 if (!this->emitGetPtrField(FieldToInit->Offset,
Init))
2125 if (
Activate && !this->emitActivate(E))
2132 if (
Inits.size() == 0) {
2133 if (!this->visitZeroRecordInitializer(R, E))
2138 if (
const auto *ILE = dyn_cast<InitListExpr>(E))
2139 FToInit = ILE->getInitializedFieldInUnion();
2143 const Record::Field *FieldToInit = R->getField(FToInit);
2145 if (!initPrimitiveField(FieldToInit,
Init, *T,
true))
2148 if (!initCompositeField(FieldToInit,
Init,
true))
2152 return this->emitFinishInit(E);
2155 assert(!R->isUnion());
2156 for (
unsigned BI = 0; BI != R->getNumBases(); ++BI) {
2158 const Record::Base *B = R->getBase(BI);
2159 if (!this->emitGetPtrBase(B->Offset,
Init))
2165 unsigned FieldIndex = 0;
2166 for (
unsigned FI = R->getNumBases(); FI !=
Inits.size();) {
2167 const Record::Field *FieldToInit = R->getField(FieldIndex);
2168 if (FieldToInit->isUnnamedBitField()) {
2183 if (!initPrimitiveField(FieldToInit,
Init, *T))
2185 }
else if (!initCompositeField(FieldToInit,
Init)) {
2193 assert(R->getNumVirtualBases() == 0);
2195 return this->emitFinishInit(E);
2200 Ctx.getASTContext().getAsConstantArrayType(QT);
2203 if (
Initializing && !this->emitCheckArrayDestSize(NumElems, E))
2206 if (
Inits.size() == 1 && QT ==
Inits[0]->getType())
2210 unsigned ElementIndex = 0;
2212 if (
const auto *EmbedS =
2213 dyn_cast<EmbedExpr>(
Init->IgnoreParenImpCasts())) {
2221 if (!this->emitCastIntegralFloating(
classifyPrim(IL), Sem,
2222 getFPOptions(E), E))
2228 return this->emitInitElem(TargetT, ElemIndex, IL);
2230 if (!EmbedS->doForEachDataElement(Eval, ElementIndex))
2246 for (; ElementIndex != NumElems; ++ElementIndex) {
2252 return this->emitFinishInit(E);
2256 unsigned NumInits =
Inits.size();
2261 QualType ElemQT = ComplexTy->getElementType();
2263 if (NumInits == 0) {
2265 for (
unsigned I = 0; I < 2; ++I) {
2266 if (!this->visitZeroInitializer(ElemT, ElemQT, E))
2268 if (!this->emitInitElem(ElemT, I, E))
2271 }
else if (NumInits == 2) {
2272 unsigned InitIndex = 0;
2277 if (!this->emitInitElem(ElemT, InitIndex, E))
2286 unsigned NumVecElements = VecT->getNumElements();
2287 assert(NumVecElements >=
Inits.size());
2289 QualType ElemQT = VecT->getElementType();
2293 unsigned InitIndex = 0;
2300 if (
const auto *InitVecT =
Init->getType()->getAs<
VectorType>()) {
2301 if (!this->emitCopyArray(ElemT, 0, InitIndex,
2302 InitVecT->getNumElements(), E))
2304 InitIndex += InitVecT->getNumElements();
2306 if (!this->emitInitElem(ElemT, InitIndex, E))
2312 assert(InitIndex <= NumVecElements);
2315 for (; InitIndex != NumVecElements; ++InitIndex) {
2316 if (!this->visitZeroInitializer(ElemT, ElemQT, E))
2318 if (!this->emitInitElem(ElemT, InitIndex, E))
2325 unsigned NumElems = MT->getNumElementsFlattened();
2326 assert(
Inits.size() == NumElems);
2328 QualType ElemQT = MT->getElementType();
2334 for (
unsigned I = 0; I != NumElems; ++I) {
2337 if (!this->emitInitElem(ElemT, I, E))
2348template <
class Emitter>
2355 return this->emitInitElem(*InitT, ElemIndex,
Init);
2361 if (!this->emitConstUint32(ElemIndex,
Init))
2363 if (!this->emitArrayElemPtrUint32(
Init))
2368template <
class Emitter>
2371 bool Activate,
bool IsOperatorCall) {
2373 llvm::BitVector NonNullArgs;
2374 if (FuncDecl && FuncDecl->
hasAttr<NonNullAttr>())
2377 bool ExplicitMemberFn =
false;
2378 if (
const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FuncDecl))
2379 ExplicitMemberFn = MD->isExplicitObjectMemberFunction();
2381 unsigned ArgIndex = 0;
2382 for (
const Expr *Arg : Args) {
2384 if (!this->
visit(Arg))
2392 unsigned DeclIndex = ArgIndex - IsOperatorCall + ExplicitMemberFn;
2393 if (DeclIndex < FuncDecl->getNumParams())
2394 Source = FuncDecl->
getParamDecl(ArgIndex - IsOperatorCall +
2403 if (!this->emitGetPtrLocal(*LocalIndex, Arg))
2411 if (!this->emitActivate(Arg))
2415 if (!NonNullArgs.empty() && NonNullArgs[ArgIndex]) {
2418 if (!this->emitCheckNonNullArg(ArgT, Arg))
2429template <
class Emitter>
2434template <
class Emitter>
2440template <
class Emitter>
2446template <
class Emitter>
2464template <
class Emitter>
2466 auto It = E->
begin();
2467 return this->
visit(*It);
2472 bool AlignOfReturnsPreferred =
2479 T = Ref->getPointeeType();
2481 if (T.getQualifiers().hasUnaligned())
2487 if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
2493template <
class Emitter>
2500 if (Kind == UETT_SizeOf || Kind == UETT_DataSizeOf) {
2506 ArgType = Ref->getPointeeType();
2512 if (
ArgType->isDependentType() || !
ArgType->isConstantSizeType())
2513 return this->emitInvalid(E);
2515 if (Kind == UETT_SizeOf)
2524 return this->emitConst(Size.getQuantity(), E);
2527 if (Kind == UETT_CountOf) {
2533 if (
const auto *CAT =
2537 return this->emitConst(CAT->getSize(), E);
2547 if (VAT->getElementType()->isArrayType()) {
2548 std::optional<APSInt> Res =
2550 ? VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx)
2555 return this->emitConst(*Res, E);
2560 if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
2580 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
2583 else if (
const auto *ME = dyn_cast<MemberExpr>(Arg))
2593 return this->emitConst(Size.getQuantity(), E);
2596 if (Kind == UETT_VectorElements) {
2601 return this->emitConst(VT->getNumElements(), E);
2603 return this->emitSizelessVectorElementSize(E);
2606 if (Kind == UETT_VecStep) {
2608 unsigned N = VT->getNumElements();
2615 return this->emitConst(N, E);
2617 return this->emitConst(1, E);
2620 if (Kind == UETT_OpenMPRequiredSimdAlign) {
2629 if (Kind == UETT_PtrAuthTypeDiscriminator) {
2631 return this->emitInvalid(E);
2633 return this->emitConst(
2634 const_cast<ASTContext &
>(ASTCtx).getPointerAuthTypeDiscriminator(
2642template <
class Emitter>
2651 if (
const auto *VD = dyn_cast<VarDecl>(
Member)) {
2654 if (
auto GlobalIndex =
P.getGlobal(VD)) {
2655 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
2657 if (
Member->getType()->isReferenceType())
2658 return this->emitLoadPopPtr(E);
2667 if (
const auto *MD = dyn_cast<CXXMethodDecl>(
Member);
2668 MD && !MD->isStatic()) {
2672 if (!this->
discard(Base) && !this->emitSideEffect(E))
2687 const Record::Field *F = R->getField(FD);
2691 const auto maybeLoadValue = [&]() ->
bool {
2695 return this->emitLoadPop(*T, E);
2700 if (F->Decl->getType()->isReferenceType())
2701 return this->emitGetFieldPop(
PT_Ptr, F->Offset, E) && maybeLoadValue();
2702 return this->emitGetPtrFieldPop(F->Offset, E) && maybeLoadValue();
2705template <
class Emitter>
2715template <
class Emitter>
2729 if (!this->
visit(Common))
2731 return this->emitCopyArray(*SubExprT, 0, 0, Size, E);
2745 for (
size_t I = 0; I != Size; ++I) {
2757template <
class Emitter>
2772 return this->emitGetLocal(SubExprT, It->second, E);
2775 if (!this->
visit(SourceExpr))
2782 if (!this->emitSetLocal(SubExprT, LocalIndex, E))
2791 return this->emitGetLocal(SubExprT, LocalIndex, E);
2795template <
class Emitter>
2808 bool IsBcpCall =
false;
2809 if (
const auto *CE = dyn_cast<CallExpr>(
Condition->IgnoreParenCasts());
2810 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) {
2814 LabelTy LabelEnd = this->getLabel();
2815 LabelTy LabelFalse = this->getLabel();
2818 if (!this->emitPushIgnoreDiags(E))
2826 if (this->checkingForUndefinedBehavior()) {
2829 if (!this->
discard(FalseExpr))
2846 if (!this->jumpFalse(LabelFalse, E))
2851 if (!this->jump(LabelEnd, E))
2853 this->emitLabel(LabelFalse);
2857 this->fallthrough(LabelEnd);
2858 this->emitLabel(LabelEnd);
2861 return this->emitPopIgnoreDiags(E);
2865template <
class Emitter>
2871 unsigned StringIndex =
P.createGlobalString(E);
2872 return this->emitGetPtrGlobal(StringIndex, E);
2877 Ctx.getASTContext().getAsConstantArrayType(E->
getType());
2878 assert(CAT &&
"a string literal that's not a constant array?");
2883 unsigned N = std::min(ArraySize, E->
getLength());
2886 for (
unsigned I = 0; I != N; ++I) {
2889 if (CharWidth == 1) {
2890 this->emitConstSint8(CodeUnit, E);
2891 this->emitInitElemSint8(I, E);
2892 }
else if (CharWidth == 2) {
2893 this->emitConstUint16(CodeUnit, E);
2894 this->emitInitElemUint16(I, E);
2895 }
else if (CharWidth == 4) {
2896 this->emitConstUint32(CodeUnit, E);
2897 this->emitInitElemUint32(I, E);
2899 llvm_unreachable(
"unsupported character width");
2904 for (
unsigned I = N; I != ArraySize; ++I) {
2905 if (CharWidth == 1) {
2906 this->emitConstSint8(0, E);
2907 this->emitInitElemSint8(I, E);
2908 }
else if (CharWidth == 2) {
2909 this->emitConstUint16(0, E);
2910 this->emitInitElemUint16(I, E);
2911 }
else if (CharWidth == 4) {
2912 this->emitConstUint32(0, E);
2913 this->emitInitElemUint32(I, E);
2915 llvm_unreachable(
"unsupported character width");
2922template <
class Emitter>
2926 return this->emitDummyPtr(E, E);
2929template <
class Emitter>
2931 auto &A =
Ctx.getASTContext();
2940template <
class Emitter>
2948 auto &A =
Ctx.getASTContext();
2952 APInt Size(A.getTypeSize(A.getSizeType()), ResultStr.size() + 1);
2953 QualType ArrayTy = A.getConstantArrayType(CharTy, Size,
nullptr,
2960 unsigned StringIndex =
P.createGlobalString(SL);
2961 return this->emitGetPtrGlobal(StringIndex, E);
2964template <
class Emitter>
2968 return this->emitConst(E->
getValue(), E);
2971template <
class Emitter>
2997 if (!this->emitSetLocal(*RT, TempOffset, E))
3003 if (!this->emitLoad(LHST, E))
3007 if (!this->emitPrimCast(LHST,
classifyPrim(LHSComputationType),
3008 LHSComputationType, E))
3012 if (!this->emitGetLocal(*RT, TempOffset, E))
3017 if (!this->emitAddf(getFPOptions(E), E))
3021 if (!this->emitSubf(getFPOptions(E), E))
3025 if (!this->emitMulf(getFPOptions(E), E))
3029 if (!this->emitDivf(getFPOptions(E), E))
3040 return this->emitStorePop(LHST, E);
3041 return this->emitStore(LHST, E);
3044template <
class Emitter>
3053 if (Op != BO_AddAssign && Op != BO_SubAssign)
3062 if (!this->emitLoad(*
LT, LHS))
3068 if (Op == BO_AddAssign) {
3069 if (!this->emitAddOffset(*RT, E))
3072 if (!this->emitSubOffset(*RT, E))
3077 return this->emitStorePopPtr(E);
3078 return this->emitStorePtr(E);
3081template <
class Emitter>
3094 if (!
Ctx.getLangOpts().CPlusPlus14)
3095 return this->
visit(RHS) && this->
visit(LHS) && this->emitError(E);
3097 if (!
LT || !RT || !ResultT || !LHSComputationT)
3122 if (!this->emitSetLocal(*RT, TempOffset, E))
3129 if (!this->emitLoad(*
LT, E))
3131 if (
LT != LHSComputationT &&
3137 if (!this->emitGetLocal(*RT, TempOffset, E))
3143 if (!this->emitAdd(*LHSComputationT, E))
3147 if (!this->emitSub(*LHSComputationT, E))
3151 if (!this->emitMul(*LHSComputationT, E))
3155 if (!this->emitDiv(*LHSComputationT, E))
3159 if (!this->emitRem(*LHSComputationT, E))
3163 if (!this->emitShl(*LHSComputationT, *RT, E))
3167 if (!this->emitShr(*LHSComputationT, *RT, E))
3171 if (!this->emitBitAnd(*LHSComputationT, E))
3175 if (!this->emitBitXor(*LHSComputationT, E))
3179 if (!this->emitBitOr(*LHSComputationT, E))
3183 llvm_unreachable(
"Unimplemented compound assign operator");
3187 if (ResultT != LHSComputationT &&
3188 !this->emitIntegralCast(*LHSComputationT, *ResultT, E->
getType(), E))
3194 return this->emitStoreBitFieldPop(*ResultT, E);
3195 return this->emitStorePop(*ResultT, E);
3198 return this->emitStoreBitField(*ResultT, E);
3199 return this->emitStore(*ResultT, E);
3202template <
class Emitter>
3210template <
class Emitter>
3225 if (!
Ctx.getLangOpts().CPlusPlus11)
3232 for (
const Expr *LHS : CommaLHSs) {
3254 if (!this->
visit(Inner))
3259 if (!this->emitInitGlobalTemp(*InnerT, *GlobalIndex, TempDecl, E))
3262 if (!this->emitInitGlobal(*InnerT, *GlobalIndex, E))
3265 return this->emitGetPtrGlobal(*GlobalIndex, E);
3268 if (!this->checkLiteralType(Inner))
3271 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
3277 return this->emitInitGlobalTempComp(TempDecl, E);
3290 unsigned LocalIndex =
3292 if (!this->VarScope->LocalsAlwaysEnabled &&
3293 !this->emitEnableLocal(LocalIndex, E))
3296 if (!this->
visit(Inner))
3298 if (!this->emitSetLocal(*InnerT, LocalIndex, E))
3301 return this->emitGetPtrLocal(LocalIndex, E);
3304 if (!this->checkLiteralType(Inner))
3311 if (!this->VarScope->LocalsAlwaysEnabled &&
3312 !this->emitEnableLocal(*LocalIndex, E))
3315 if (!this->emitGetPtrLocal(*LocalIndex, E))
3322template <
class Emitter>
3333 if (!this->
visit(SubExpr))
3337 return this->emitPopPtr(E);
3341template <
class Emitter>
3362 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
3367 if (
P.isGlobalInitialized(*GlobalIndex))
3373 return this->emitInitGlobal(*T, *GlobalIndex, E);
3385 unsigned LocalIndex;
3389 LocalIndex = *MaybeIndex;
3393 if (!this->emitGetPtrLocal(LocalIndex, E))
3397 return this->
visit(
Init) && this->emitInit(*T, E);
3401template <
class Emitter>
3414template <
class Emitter>
3418 return this->emitConst(E->
getValue(), E);
3421template <
class Emitter>
3434 for (
const Record::Field &F : R->fields()) {
3436 if (!
Init ||
Init->containsErrors())
3444 if (!this->emitInitField(*T, F.Offset, E))
3447 if (!this->emitGetPtrField(F.Offset, E))
3458template <
class Emitter>
3465 return this->emitGetPtrGlobal(StringIndex, E);
3471template <
class Emitter>
3476 return this->emitInvalid(E);
3479template <
class Emitter>
3499 bool Fatal = (ToT != FromT);
3506template <
class Emitter>
3508 if (!
Ctx.getLangOpts().CPlusPlus20) {
3529 if (!this->emitDynamicCast(DestType.
getTypePtr(),
3534 return this->emitPopPtr(E);
3538template <
class Emitter>
3544 return this->emitConstBool(E->
getValue(), E);
3547template <
class Emitter>
3552 if (T->isRecordType()) {
3566 if (!this->emitGetPtrLocal(*LocalIndex, E))
3574 T->getAsCXXRecordDecl()))
3584 if (!this->visitZeroRecordInitializer(R, E))
3596 assert(
Ctx.getASTContext().hasSameUnqualifiedType(E->
getType(),
3598 if (
const auto *ME = dyn_cast<MaterializeTemporaryExpr>(SrcObj)) {
3599 if (!this->emitCheckFunctionDecl(Ctor, E))
3610 assert(
Func->hasThisPointer());
3611 assert(!
Func->hasRVO());
3615 if (!this->emitDupPtr(E))
3619 for (
const auto *Arg : E->
arguments()) {
3620 if (!this->
visit(Arg))
3624 if (
Func->isVariadic()) {
3625 uint32_t VarArgSize = 0;
3626 unsigned NumParams =
Func->getNumWrittenParams();
3627 for (
unsigned I = NumParams, N = E->
getNumArgs(); I != N; ++I) {
3631 if (!this->emitCallVar(
Func, VarArgSize, E))
3634 if (!this->emitCall(
Func, 0, E)) {
3639 (void)this->emitPopPtr(E);
3645 return this->emitPopPtr(E);
3649 if (T->isArrayType()) {
3654 if (!this->emitDupPtr(E))
3658 initArrayDimension = [&](
QualType T) ->
bool {
3659 if (!T->isArrayType()) {
3661 for (
const auto *Arg : E->
arguments()) {
3662 if (!this->
visit(Arg))
3666 return this->emitCall(
Func, 0, E);
3670 Ctx.getASTContext().getAsConstantArrayType(T);
3675 for (
size_t I = 0; I != NumElems; ++I) {
3676 if (!this->emitConstUint64(I, E))
3678 if (!this->emitArrayElemPtrUint64(E))
3680 if (!initArrayDimension(ElemTy))
3683 return this->emitPopPtr(E);
3686 return initArrayDimension(E->
getType());
3692template <
class Emitter>
3702 assert(Val.
isInt());
3704 return this->emitConst(I, E);
3711 if (
const Expr *LValueExpr =
Base.dyn_cast<
const Expr *>())
3712 return this->
visit(LValueExpr);
3727 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
3731 const APValue &
V = UGCD->getValue();
3732 for (
unsigned I = 0, N = R->getNumFields(); I != N; ++I) {
3733 const Record::Field *F = R->getField(I);
3734 const APValue &FieldValue =
V.getStructField(I);
3740 if (!this->emitInitField(FieldT, F->Offset, E))
3748template <
class Emitter>
3754 for (
unsigned I = 0; I != N; ++I) {
3761 if (!this->
discard(ArrayIndexExpr))
3766 if (!this->
visit(ArrayIndexExpr))
3770 if (!this->emitCast(IndexT,
PT_Sint64, E))
3780 return this->emitOffsetOf(T, E, E);
3783template <
class Emitter>
3792 return this->visitZeroInitializer(*T, Ty, E);
3799 if (!this->emitGetPtrLocal(*LocalIndex, E))
3807 ElemQT = CT->getElementType();
3810 NumElems = VT->getNumElements();
3811 ElemQT = VT->getElementType();
3817 for (
unsigned I = 0, N = NumElems; I != N; ++I) {
3818 if (!this->visitZeroInitializer(ElemT, ElemQT, E))
3820 if (!this->emitInitElem(ElemT, I, E))
3829template <
class Emitter>
3834template <
class Emitter>
3840template <
class Emitter>
3845template <
class Emitter>
3850 return this->emitConst(E->
getValue(), E);
3853template <
class Emitter>
3858 "Trivial CXXInheritedCtorInitExpr, implement. (possible?)");
3872 unsigned ParamIndex = 0;
3876 if (!this->emitGetParam(PT, ParamIndex, E))
3881 return this->emitCall(F, 0, E);
3886template <
class Emitter>
3894 const Expr *PlacementDest =
nullptr;
3895 bool IsNoThrow =
false;
3900 if (PlacementArgs != 0) {
3909 if (PlacementArgs == 1) {
3917 if (!this->emitInvalidNewDeleteExpr(E, E))
3922 if (OperatorNew->isReservedGlobalPlacementOperator())
3923 PlacementDest = Arg1;
3927 return this->emitInvalid(E);
3929 }
else if (!OperatorNew
3930 ->isUsableAsGlobalAllocationFunctionInConstantEvaluation())
3931 return this->emitInvalidNewDeleteExpr(E, E);
3934 if (!PlacementDest) {
3939 Desc =
P.createDescriptor(E, *ElemT,
nullptr,
3942 Desc =
P.createDescriptor(
3945 false,
false,
false,
3951 std::optional<const Expr *> ArraySizeExpr = E->
getArraySize();
3955 const Expr *Stripped = *ArraySizeExpr;
3956 for (;
auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped);
3957 Stripped = ICE->getSubExpr())
3958 if (ICE->getCastKind() != CK_NoOp &&
3959 ICE->getCastKind() != CK_IntegralCast)
3967 if (!this->
visit(Stripped))
3969 if (!this->emitSetLocal(
SizeT, ArrayLen, E))
3972 if (PlacementDest) {
3973 if (!this->
visit(PlacementDest))
3975 if (!this->emitGetLocal(
SizeT, ArrayLen, E))
3977 if (!this->emitCheckNewTypeMismatchArray(
SizeT, E, E))
3980 if (!this->emitGetLocal(
SizeT, ArrayLen, E))
3985 if (!this->emitAllocN(
SizeT, *ElemT, E, IsNoThrow, E))
3989 if (!this->emitAllocCN(
SizeT, Desc, IsNoThrow, E))
3996 size_t StaticInitElems = 0;
3997 const Expr *DynamicInit =
nullptr;
4001 Ctx.getASTContext().getAsConstantArrayType(InitType)) {
4002 StaticInitElems = CAT->getZExtSize();
4007 if (
const auto *ILE = dyn_cast<InitListExpr>(
Init)) {
4008 if (ILE->hasArrayFiller())
4009 DynamicInit = ILE->getArrayFiller();
4028 const Function *CtorFunc =
nullptr;
4029 if (
const auto *CE = dyn_cast<CXXConstructExpr>(
Init)) {
4033 }
else if (!DynamicInit && !ElemT)
4036 LabelTy EndLabel = this->getLabel();
4037 LabelTy StartLabel = this->getLabel();
4042 if (!this->emitDupPtr(E))
4044 if (!this->emitNullPtr(0,
nullptr, E))
4046 if (!this->emitEQPtr(E))
4048 if (!this->jumpTrue(EndLabel, E))
4055 if (!this->emitConst(StaticInitElems,
SizeT, E))
4057 if (!this->emitSetLocal(
SizeT, Iter, E))
4060 this->fallthrough(StartLabel);
4061 this->emitLabel(StartLabel);
4063 if (!this->emitGetLocal(
SizeT, Iter, E))
4065 if (!this->emitGetLocal(
SizeT, ArrayLen, E))
4067 if (!this->emitLT(
SizeT, E))
4069 if (!this->jumpFalse(EndLabel, E))
4073 if (!this->emitGetLocal(
SizeT, Iter, E))
4075 if (!this->emitArrayElemPtr(
SizeT, E))
4078 if (isa_and_nonnull<ImplicitValueInitExpr>(DynamicInit) &&
4083 if (!this->visitZeroInitializer(*InitT, ElemType, E))
4085 if (!this->emitStorePop(*InitT, E))
4089 if (!this->visitZeroArrayInitializer(ElemType, E))
4092 }
else if (DynamicInit) {
4094 if (!this->
visit(DynamicInit))
4096 if (!this->emitStorePop(*InitT, E))
4103 if (!this->visitZeroInitializer(
4107 if (!this->emitStorePop(*ElemT, E))
4111 if (!this->emitCall(CtorFunc, 0, E))
4116 if (!this->emitGetPtrLocal(Iter, E))
4118 if (!this->emitIncPop(
SizeT,
false, E))
4121 if (!this->jump(StartLabel, E))
4124 this->fallthrough(EndLabel);
4125 this->emitLabel(EndLabel);
4129 if (PlacementDest) {
4130 if (!this->
visit(PlacementDest))
4132 if (!this->emitCheckNewTypeMismatch(E, E))
4137 if (!this->emitAlloc(Desc, E))
4146 if (!this->emitInit(*ElemT, E))
4157 return this->emitPopPtr(E);
4162template <
class Emitter>
4168 if (!OperatorDelete->isUsableAsGlobalAllocationFunctionInConstantEvaluation())
4169 return this->emitInvalidNewDeleteExpr(E, E);
4178template <
class Emitter>
4184 if (
const Function *F =
Ctx.getOrCreateObjCBlock(E))
4189 return this->emitGetFnPtr(
Func, E);
4192template <
class Emitter>
4196 auto canonType = [](
const Type *T) {
4197 return T->getCanonicalTypeUnqualified().getTypePtr();
4205 return this->emitGetTypeid(
4209 return this->emitGetTypeid(
4218 if (!
Ctx.getLangOpts().CPlusPlus20 && !this->emitDiagTypeid(E))
4224 if (!this->emitGetTypeidPtr(TypeInfoType, E))
4227 return this->emitPopPtr(E);
4231template <
class Emitter>
4235 return this->emitDummyPtr(E, E);
4236 return this->emitError(E);
4239template <
class Emitter>
4242 return this->emitDummyPtr(E, E);
4243 return this->emitError(E);
4246template <
class Emitter>
4248 assert(
Ctx.getLangOpts().CPlusPlus);
4249 return this->emitConstBool(E->
getValue(), E);
4252template <
class Emitter>
4264 return this->emitDummyPtr(GuidDecl, E);
4269 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
4278 assert(
V.isStruct());
4279 assert(
V.getStructNumBases() == 0);
4283 return this->emitFinishInit(E);
4286template <
class Emitter>
4296template <
class Emitter>
4305template <
class Emitter>
4311template <
class Emitter>
4315 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) {
4319 if (OVE->isUnique())
4335template <
class Emitter>
4340template <
class Emitter>
4342 return this->emitError(E);
4345template <
class Emitter>
4351 return this->emitDummyPtr(E, E);
4354template <
class Emitter>
4355bool Compiler<Emitter>::emitVectorConversion(
const Expr *Src,
const Expr *E) {
4360 QualType ElemType = VT->getElementType();
4361 PrimType ElemT = classifyPrim(ElemType);
4363 PrimType SrcElemT = classifyVectorElementType(SrcType);
4369 if (!this->emitGetPtrLocal(*LocalIndex, E))
4373 unsigned SrcOffset =
4374 this->allocateLocalPrimitive(Src,
PT_Ptr,
true);
4375 if (!this->visit(Src))
4377 if (!this->emitSetLocal(
PT_Ptr, SrcOffset, E))
4380 for (
unsigned I = 0; I != VT->getNumElements(); ++I) {
4381 if (!this->emitGetLocal(
PT_Ptr, SrcOffset, E))
4383 if (!this->emitArrayElemPop(SrcElemT, I, E))
4387 if (SrcElemT != ElemT) {
4388 if (!this->emitPrimCast(SrcElemT, ElemT, ElemType, E))
4390 }
else if (ElemType->isFloatingType() && SrcType != ElemType) {
4391 const auto *TargetSemantics = &Ctx.getFloatSemantics(ElemType);
4395 if (!this->emitInitElem(ElemT, I, E))
4401template <
class Emitter>
4403 return emitVectorConversion(E->
getSrcExpr(), E);
4406template <
class Emitter>
4410 return this->emitInvalid(E);
4419 assert(NumOutputElems > 0);
4425 if (!this->emitGetPtrLocal(*LocalIndex, E))
4430 unsigned VectorOffsets[2];
4431 for (
unsigned I = 0; I != 2; ++I) {
4434 if (!this->
visit(Vecs[I]))
4436 if (!this->emitSetLocal(
PT_Ptr, VectorOffsets[I], E))
4439 for (
unsigned I = 0; I != NumOutputElems; ++I) {
4441 assert(ShuffleIndex >= -1);
4442 if (ShuffleIndex == -1)
4443 return this->emitInvalidShuffleVectorIndex(I, E);
4445 assert(ShuffleIndex < (NumInputElems * 2));
4446 if (!this->emitGetLocal(
PT_Ptr,
4447 VectorOffsets[ShuffleIndex >= NumInputElems], E))
4449 unsigned InputVectorIndex = ShuffleIndex.getZExtValue() % NumInputElems;
4450 if (!this->emitArrayElemPop(ElemT, InputVectorIndex, E))
4453 if (!this->emitInitElem(ElemT, I, E))
4458 return this->emitPopPtr(E);
4463template <
class Emitter>
4468 Base->getType()->isVectorType() ||
4474 if (Indices.size() == 1) {
4479 if (!this->emitConstUint32(Indices[0], E))
4481 return this->emitArrayElemPtrPop(
PT_Uint32, E);
4491 if (!this->emitSetLocal(
PT_Ptr, BaseOffset, E))
4499 if (!this->emitGetPtrLocal(*ResultIndex, E))
4507 uint32_t DstIndex = 0;
4508 for (uint32_t I : Indices) {
4509 if (!this->emitGetLocal(
PT_Ptr, BaseOffset, E))
4511 if (!this->emitArrayElemPop(ElemT, I, E))
4513 if (!this->emitInitElem(ElemT, DstIndex, E))
4523template <
class Emitter>
4527 return this->
discard(SubExpr) && this->emitInvalid(E);
4533 return this->emitDummyPtr(E, E);
4536template <
class Emitter>
4541 Ctx.getASTContext().getAsConstantArrayType(SubExpr->
getType());
4546 if (!this->
visit(SubExpr))
4548 if (!this->emitConstUint8(0, E))
4550 if (!this->emitArrayElemPtrPopUint8(E))
4552 if (!this->emitInitFieldPtr(R->getField(0u)->Offset, E))
4557 if (!this->emitConst(
ArrayType->getSize(), SecondFieldT, E))
4559 return this->emitInitField(SecondFieldT, R->getField(1u)->Offset, E);
4561 assert(SecondFieldT ==
PT_Ptr);
4563 if (!this->emitGetFieldPtr(R->getField(0u)->Offset, E))
4565 if (!this->emitExpandPtr(E))
4569 if (!this->emitArrayElemPtrPop(
PT_Uint64, E))
4571 return this->emitInitFieldPtr(R->getField(1u)->Offset, E);
4574template <
class Emitter>
4589 if (
const Expr *ResultExpr = dyn_cast<Expr>(S))
4593 return this->emitUnsupported(E);
4602 return this->
Visit(E);
4609 return this->
Visit(E);
4613 if (
const auto *PE = dyn_cast<ParenExpr>(E))
4616 if (
const auto *CE = dyn_cast<CastExpr>(E);
4618 (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))
4625 if (
const auto *PE = dyn_cast<ParenExpr>(E))
4628 if (
const auto *CE = dyn_cast<CastExpr>(E);
4629 CE && (CE->getCastKind() == CK_DerivedToBase ||
4630 CE->getCastKind() == CK_UncheckedDerivedToBase ||
4631 CE->getCastKind() == CK_NoOp))
4651 if (!this->emitGetPtrLocal(*LocalIndex, E))
4661 return this->
Visit(E);
4664template <
class Emitter>
4670 return this->
Visit(E) && this->emitFinishInit(E);
4673template <
class Emitter>
4679 return this->
Visit(E) && this->emitFinishInitPop(E);
4685 return this->
Visit(E);
4696 if (!this->
visit(E))
4698 return this->emitComplexBoolCast(E);
4703 if (!this->
visit(E))
4711 return this->emitIsNonNullPtr(E);
4715 return this->emitCastFloatingIntegralBool(getFPOptions(E), E);
4718 return this->emitCast(*T,
PT_Bool, E);
4721template <
class Emitter>
4725 QT = AT->getValueType();
4729 return this->emitZeroBool(E);
4731 return this->emitZeroSint8(E);
4733 return this->emitZeroUint8(E);
4735 return this->emitZeroSint16(E);
4737 return this->emitZeroUint16(E);
4739 return this->emitZeroSint32(E);
4741 return this->emitZeroUint32(E);
4743 return this->emitZeroSint64(E);
4745 return this->emitZeroUint64(E);
4747 return this->emitZeroIntAP(Ctx.getBitWidth(QT), E);
4749 return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E);
4751 return this->emitNullPtr(Ctx.getASTContext().getTargetNullPointerValue(QT),
4754 return this->emitNullMemberPtr(0,
nullptr, E);
4756 APFloat F = APFloat::getZero(Ctx.getFloatSemantics(QT));
4757 return this->emitFloat(F, E);
4760 auto Sem = Ctx.getASTContext().getFixedPointSemantics(QT);
4764 llvm_unreachable(
"unknown primitive type");
4767template <
class Emitter>
4768bool Compiler<Emitter>::visitZeroRecordInitializer(
const Record *R,
4773 for (
const Record::Field &Field :
R->fields()) {
4774 if (Field.isUnnamedBitField())
4781 if (!this->visitZeroInitializer(T, QT, E))
4784 if (!this->emitInitFieldActivate(T, Field.Offset, E))
4788 if (!this->emitInitField(T, Field.Offset, E))
4793 if (!this->emitGetPtrField(Field.Offset, E))
4800 if (!this->visitZeroInitializer(T, ET, E))
4802 if (!this->emitInitElem(T, I, E))
4807 if (!this->visitZeroArrayInitializer(D->
getType(), E))
4810 if (!this->visitZeroRecordInitializer(D->
ElemRecord, E))
4818 if (!this->emitFinishInitActivatePop(E))
4822 if (!this->emitFinishInitPop(E))
4826 for (
const Record::Base &B :
R->bases()) {
4827 if (!this->emitGetPtrBase(B.Offset, E))
4829 if (!this->visitZeroRecordInitializer(B.R, E))
4831 if (!this->emitFinishInitPop(E))
4840template <
class Emitter>
4841bool Compiler<Emitter>::visitZeroArrayInitializer(
QualType T,
const Expr *E) {
4842 assert(T->isArrayType() || T->isAnyComplexType() || T->isVectorType());
4848 for (
size_t I = 0; I != NumElems; ++I) {
4849 if (!this->visitZeroInitializer(*ElemT, ElemType, E))
4851 if (!this->emitInitElem(*ElemT, I, E))
4857 const Record *
R = getRecord(ElemType);
4861 for (
size_t I = 0; I != NumElems; ++I) {
4862 if (!this->emitConstUint32(I, E))
4864 if (!this->emitArrayElemPtr(
PT_Uint32, E))
4866 if (!this->visitZeroRecordInitializer(R, E))
4868 if (!this->emitPopPtr(E))
4874 for (
size_t I = 0; I != NumElems; ++I) {
4875 if (!this->emitConstUint32(I, E))
4877 if (!this->emitArrayElemPtr(
PT_Uint32, E))
4879 if (!this->visitZeroArrayInitializer(ElemType, E))
4881 if (!this->emitPopPtr(E))
4890template <
class Emitter>
4891bool Compiler<Emitter>::visitAssignment(
const Expr *LHS,
const Expr *RHS,
4893 if (!canClassify(E->
getType()))
4896 if (!this->visit(RHS))
4898 if (!this->visit(LHS))
4905 if (!Ctx.getLangOpts().CPlusPlus && !this->emitInvalid(E))
4909 bool Activates = refersToUnion(LHS);
4912 if (!this->emitFlip(
PT_Ptr, RHT, E))
4915 if (DiscardResult) {
4916 if (BitField && Activates)
4917 return this->emitStoreBitFieldActivatePop(RHT, E);
4919 return this->emitStoreBitFieldPop(RHT, E);
4921 return this->emitStoreActivatePop(RHT, E);
4923 return this->emitStorePop(RHT, E);
4926 auto maybeLoad = [&](
bool Result) ->
bool {
4932 return this->emitLoadPop(RHT, E);
4936 if (BitField && Activates)
4937 return maybeLoad(this->emitStoreBitFieldActivate(RHT, E));
4939 return maybeLoad(this->emitStoreBitField(RHT, E));
4941 return maybeLoad(this->emitStoreActivate(RHT, E));
4943 return maybeLoad(this->emitStore(RHT, E));
4946template <
class Emitter>
4947template <
typename T>
4951 return this->emitConstSint8(
Value, Info);
4953 return this->emitConstUint8(
Value, Info);
4955 return this->emitConstSint16(
Value, Info);
4957 return this->emitConstUint16(
Value, Info);
4959 return this->emitConstSint32(
Value, Info);
4961 return this->emitConstUint32(
Value, Info);
4963 return this->emitConstSint64(
Value, Info);
4965 return this->emitConstUint64(
Value, Info);
4967 return this->emitConstBool(
Value, Info);
4974 llvm_unreachable(
"Invalid integral type");
4977 llvm_unreachable(
"unknown primitive type");
4980template <
class Emitter>
4981template <
typename T>
4982bool Compiler<Emitter>::emitConst(T
Value,
const Expr *E) {
4983 return this->emitConst(
Value, classifyPrim(E->
getType()), E);
4986template <
class Emitter>
4990 return this->emitConstIntAPS(
Value, Info);
4992 return this->emitConstIntAP(
Value, Info);
4994 if (
Value.isSigned())
4995 return this->emitConst(
Value.getSExtValue(), Ty, Info);
4996 return this->emitConst(
Value.getZExtValue(), Ty, Info);
4999template <
class Emitter>
5003 return this->emitConstIntAPS(
Value, Info);
5005 return this->emitConstIntAP(
Value, Info);
5008 return this->emitConst(
Value.getSExtValue(), Ty, Info);
5009 return this->emitConst(
Value.getZExtValue(), Ty, Info);
5012template <
class Emitter>
5013bool Compiler<Emitter>::emitConst(
const APSInt &
Value,
const Expr *E) {
5014 return this->emitConst(
Value, classifyPrim(E->
getType()), E);
5017template <
class Emitter>
5030 if (
auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>()))
5031 Locals.insert({VD, Local});
5032 VarScope->addForScopeKind(Local, SC);
5033 return Local.Offset;
5036template <
class Emitter>
5041 bool IsTemporary =
false;
5042 if (
auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>())) {
5045 if (
const auto *VarD = dyn_cast<VarDecl>(VD))
5046 Init = VarD->getInit();
5048 if (
auto *E = Src.dyn_cast<
const Expr *>()) {
5059 return std::nullopt;
5064 Locals.insert({Key, Local});
5065 VarScope->addForScopeKind(Local, SC);
5066 return Local.Offset;
5069template <
class Emitter>
5079 return std::nullopt;
5089 return Local.Offset;
5092template <
class Emitter>
5094 if (
const PointerType *PT = dyn_cast<PointerType>(Ty))
5095 return PT->getPointeeType()->getAsCanonical<RecordType>();
5101 return getRecord(RecordTy->getDecl()->getDefinitionOrSelf());
5105template <
class Emitter>
5107 return P.getOrCreateRecord(RD);
5110template <
class Emitter>
5112 return Ctx.getOrCreateFunction(FD);
5115template <
class Emitter>
5119 auto maybeDestroyLocals = [&]() ->
bool {
5120 if (DestroyToplevelScope)
5121 return RootScope.
destroyLocals() && this->emitCheckAllocations(E);
5122 return this->emitCheckAllocations(E);
5129 return this->emitRetVoid(E) && maybeDestroyLocals();
5137 return this->emitRet(*T, E) && maybeDestroyLocals();
5145 if (!this->emitGetPtrLocal(*LocalOffset, E))
5153 return this->emitRetValue(E) && maybeDestroyLocals();
5156 return maybeDestroyLocals() &&
false;
5159template <
class Emitter>
5161 bool DestroyToplevelScope) {
5165 return this->
visitExpr(E, DestroyToplevelScope);
5168template <
class Emitter>
5180 if (
auto GlobalIndex =
P.getGlobal(VD)) {
5181 Block *GlobalBlock =
P.getGlobal(*GlobalIndex);
5195template <
class Emitter>
5197 bool ConstantContext) {
5200 if (!ConstantContext) {
5214 auto GlobalIndex =
P.getGlobal(VD);
5215 assert(GlobalIndex);
5217 if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD))
5220 if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
5224 auto Local =
Locals.find(VD);
5225 assert(Local !=
Locals.end());
5227 if (!this->emitGetLocal(*VarT, Local->second.Offset, VD))
5230 if (!this->emitGetPtrLocal(Local->second.Offset, VD))
5240 auto GlobalIndex =
P.getGlobal(VD);
5241 assert(GlobalIndex);
5242 Block *GlobalBlock =
P.getGlobal(*GlobalIndex);
5251 return VDScope.
destroyLocals() && this->emitCheckAllocations(VD);
5254template <
class Emitter>
5265 if (!this->isActive())
5270 if (
Init &&
Init->isValueDependent())
5274 auto checkDecl = [&]() ->
bool {
5276 return !NeedsOp || this->emitCheckDecl(VD, VD);
5283 if (!
P.getGlobal(*GlobalIndex)->isInitialized())
5286 if (
P.isGlobalInitialized(*GlobalIndex))
5290 }
else if ((GlobalIndex =
5305 return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
5308 if (!this->emitGetPtrGlobal(*GlobalIndex,
Init))
5311 if (!this->emitStartInit(
Init))
5317 if (!this->emitEndInit(
Init))
5320 return this->emitFinishInitGlobal(
Init);
5330 if (!
Init ||
Init->getType()->isVoidType())
5339 return this->emitSetLocal(*VarT, Offset, VD) &&
Scope.destroyLocals();
5351 if (!this->emitCheckRefInit(
Init))
5355 return this->emitSetLocal(*VarT, Offset, VD);
5363 if (!this->emitGetPtrLocal(*Offset,
Init))
5371template <
class Emitter>
5392 Locals.insert({VD, Local});
5395 if (!this->emitGetPtrLocal(Local.Offset, VD))
5401 return this->emitDestructionPop(D, VD);
5404template <
class Emitter>
5410 return this->emitConst(Val.
getInt(), ValType, Info);
5413 return this->emitFloat(F, Info);
5418 if (!this->emitGetMemberPtr(MemberDecl, Info))
5424 if (!this->emitCopyMemberPtrPath(PathEntry, IsDerived, Info))
5430 return this->emitNullMemberPtr(0,
nullptr, Info);
5435 return this->emitNull(ValType, 0,
nullptr, Info);
5440 if (
const Expr *BaseExpr =
Base.dyn_cast<
const Expr *>())
5441 return this->
visit(BaseExpr);
5446 QualType EntryType = VD->getType();
5447 for (
auto &Entry : Path) {
5449 uint64_t Index = Entry.getAsArrayIndex();
5452 if (!this->emitConst(Index,
PT_Uint64, Info))
5454 if (!this->emitArrayElemPtrPop(
PT_Uint64, Info))
5456 EntryType = ElemType;
5466 const Decl *BaseOrMember = Entry.getAsBaseOrMember().getPointer();
5467 if (
const auto *FD = dyn_cast<FieldDecl>(BaseOrMember)) {
5469 if (!this->emitGetPtrFieldPop(EntryOffset, Info))
5471 EntryType = FD->getType();
5475 if (!this->emitGetPtrBasePop(BaseOffset,
false, Info))
5477 EntryType =
Ctx.getASTContext().getCanonicalTagType(
Base);
5489template <
class Emitter>
5499 const Record::Field *RF = R->getField(I);
5500 QualType FieldType = RF->Decl->getType();
5506 if (!this->emitInitField(*PT, RF->Offset, Info))
5509 if (!this->emitGetPtrField(RF->Offset, Info))
5513 if (!this->emitFinishInitPop(Info))
5523 if (I >= R->getNumBases())
5528 const Record::Base *RB = R->getBase(I);
5529 QualType BaseType =
Ctx.getASTContext().getCanonicalTagType(RB->Decl);
5531 if (!this->emitGetPtrBase(RB->Offset, Info))
5535 if (!this->emitFinishInitPop(Info))
5550 const Record::Field *RF = R->getField(UnionField);
5551 QualType FieldType = RF->Decl->getType();
5556 if (RF->isBitField())
5557 return this->emitInitBitFieldActivate(*PT, RF->Offset, RF->bitWidth(),
5559 return this->emitInitFieldActivate(*PT, RF->Offset, Info);
5562 if (!this->emitGetPtrField(RF->Offset, Info))
5564 if (!this->emitActivate(Info))
5568 return this->emitPopPtr(Info);
5572 const auto *ArrType = T->getAsArrayTypeUnsafe();
5573 QualType ElemType = ArrType->getElementType();
5576 for (
unsigned A = 0, AN = Val.
getArraySize(); A != AN; ++A) {
5577 const APValue &Elem = A >= InitializedElems
5586 if (!this->emitInitElem(*ElemT, A, Info))
5589 if (!this->emitConstUint32(A, Info))
5591 if (!this->emitArrayElemPtrUint32(Info))
5595 if (!this->emitPopPtr(Info))
5606template <
class Emitter>
5608 unsigned BuiltinID) {
5609 if (BuiltinID == Builtin::BI__builtin_constant_p) {
5614 return this->emitConst(0, E);
5617 if (!this->emitStartSpeculation(E))
5619 LabelTy EndLabel = this->getLabel();
5620 if (!this->speculate(E, EndLabel))
5622 if (!this->emitEndSpeculation(E))
5624 this->fallthrough(EndLabel);
5632 if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
5633 BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||
5634 BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||
5635 BuiltinID == Builtin::BI__builtin_function_start) {
5638 return this->emitDummyPtr(E, E);
5649 if (!this->emitGetPtrLocal(*LocalIndex, E))
5654 switch (BuiltinID) {
5655 case Builtin::BI__builtin_object_size:
5656 case Builtin::BI__builtin_dynamic_object_size: {
5660 if (!this->
visit(Arg0))
5671 case Builtin::BI__assume:
5672 case Builtin::BI__builtin_assume:
5675 case Builtin::BI__atomic_is_lock_free:
5676 case Builtin::BI__atomic_always_lock_free: {
5687 for (
const auto *Arg : E->
arguments()) {
5688 if (!this->
visit(Arg))
5694 if (!this->emitCallBI(E, BuiltinID, E))
5703template <
class Emitter>
5724 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(FuncDecl);
5725 DD && DD->isTrivial()) {
5727 if (!this->
visit(MemberCall->getImplicitObjectArgument()))
5729 return this->emitCheckDestruction(E) && this->emitEndLifetime(E) &&
5730 this->emitPopPtr(E);
5738 bool HasRVO = !
ReturnType->isVoidType() && !T;
5746 if (!this->emitGetPtrLocal(*LocalIndex, E))
5754 if (!this->emitGetPtrLocal(*LocalIndex, E))
5758 if (!this->emitDupPtr(E))
5765 bool IsAssignmentOperatorCall =
false;
5766 bool ActivateLHS =
false;
5767 if (
const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
5768 OCE && OCE->isAssignmentOp()) {
5772 assert(Args.size() == 2);
5773 const CXXRecordDecl *LHSRecord = Args[0]->getType()->getAsCXXRecordDecl();
5775 IsAssignmentOperatorCall =
true;
5776 std::reverse(Args.begin(), Args.end());
5782 if (
const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FuncDecl);
5783 MD && MD->isStatic()) {
5787 Args.erase(Args.begin());
5791 bool Devirtualized =
false;
5794 if (
const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {
5802 if (!this->
visit(Callee))
5804 if (!this->emitSetLocal(
PT_MemberPtr, *CalleeOffset, E))
5806 if (!this->emitGetLocal(
PT_MemberPtr, *CalleeOffset, E))
5808 if (!this->emitGetMemberPtrBase(E))
5811 const auto *InstancePtr = MC->getImplicitObjectArgument();
5818 Stripped->getType()->getPointeeType()->getAsCXXRecordDecl());
5819 Devirtualized =
true;
5820 if (!this->
visit(Stripped))
5823 if (!this->
visit(InstancePtr))
5827 if (!this->
visit(InstancePtr))
5831 }
else if (
const auto *PD =
5832 dyn_cast<CXXPseudoDestructorExpr>(E->
getCallee())) {
5833 if (!this->emitCheckPseudoDtor(E))
5841 return this->emitEndLifetimePop(E);
5842 }
else if (!FuncDecl) {
5846 if (!this->
visit(Callee))
5848 if (!this->emitSetLocal(
PT_Ptr, *CalleeOffset, E))
5857 if (IsAssignmentOperatorCall) {
5858 assert(Args.size() == 2);
5861 if (!this->emitFlip(Arg2T, Arg1T, E))
5875 assert(HasRVO ==
Func->hasRVO());
5877 bool HasQualifier =
false;
5878 if (
const auto *ME = dyn_cast<MemberExpr>(E->
getCallee()))
5879 HasQualifier = ME->hasQualifier();
5881 bool IsVirtual =
false;
5882 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))
5883 IsVirtual = !Devirtualized && MD->isVirtual();
5888 if (IsVirtual && !HasQualifier) {
5889 uint32_t VarArgSize = 0;
5890 unsigned NumParams =
5891 Func->getNumWrittenParams() +
5893 for (
unsigned I = NumParams, N = E->
getNumArgs(); I != N; ++I)
5896 if (!this->emitCallVirt(
Func, VarArgSize, E))
5898 }
else if (
Func->isVariadic()) {
5899 uint32_t VarArgSize = 0;
5900 unsigned NumParams =
5901 Func->getNumWrittenParams() +
5903 for (
unsigned I = NumParams, N = E->
getNumArgs(); I != N; ++I)
5905 if (!this->emitCallVar(
Func, VarArgSize, E))
5908 if (!this->emitCall(
Func, 0, E))
5917 uint32_t ArgSize = 0;
5918 for (
unsigned I = 0, N = E->
getNumArgs(); I != N; ++I)
5924 if (!this->emitGetLocal(
PT_MemberPtr, *CalleeOffset, E))
5926 if (!this->emitGetMemberPtrDecl(E))
5929 if (!this->emitGetLocal(
PT_Ptr, *CalleeOffset, E))
5932 if (!this->emitCallPtr(ArgSize, E, E))
5943template <
class Emitter>
5950template <
class Emitter>
5957template <
class Emitter>
5962 return this->emitConstBool(E->
getValue(), E);
5965template <
class Emitter>
5971 uint64_t Val =
Ctx.getASTContext().getTargetNullPointerValue(E->
getType());
5972 return this->emitNullPtr(Val,
nullptr, E);
5975template <
class Emitter>
5983 return this->emitZero(T, E);
5986template <
class Emitter>
5991 if constexpr (!std::is_same_v<Emitter, EvalEmitter>) {
5992 if (this->LambdaThisCapture.Offset > 0) {
5993 if (this->LambdaThisCapture.IsPtr)
5994 return this->emitGetThisFieldPtr(this->LambdaThisCapture.Offset, E);
5995 return this->emitGetPtrThisField(this->LambdaThisCapture.Offset, E);
6004 return this->emitThis(E);
6019 unsigned StartIndex = 0;
6020 unsigned EndIndex = 0;
6022 for (StartIndex =
InitStack.size() - 1; StartIndex > 0; --StartIndex) {
6024 EndIndex = StartIndex;
6031 for (; StartIndex > 0; --StartIndex) {
6041 if (StartIndex == 0 && EndIndex == 0)
6044 assert(StartIndex < EndIndex);
6047 for (
unsigned I = StartIndex; I != (EndIndex + 1); ++I) {
6059 case Stmt::CompoundStmtClass:
6061 case Stmt::DeclStmtClass:
6063 case Stmt::ReturnStmtClass:
6065 case Stmt::IfStmtClass:
6067 case Stmt::WhileStmtClass:
6069 case Stmt::DoStmtClass:
6071 case Stmt::ForStmtClass:
6073 case Stmt::CXXForRangeStmtClass:
6075 case Stmt::BreakStmtClass:
6077 case Stmt::ContinueStmtClass:
6079 case Stmt::SwitchStmtClass:
6081 case Stmt::CaseStmtClass:
6083 case Stmt::DefaultStmtClass:
6085 case Stmt::AttributedStmtClass:
6087 case Stmt::CXXTryStmtClass:
6089 case Stmt::NullStmtClass:
6092 case Stmt::GCCAsmStmtClass:
6093 case Stmt::MSAsmStmtClass:
6094 case Stmt::GotoStmtClass:
6095 return this->emitInvalid(S);
6096 case Stmt::LabelStmtClass:
6099 if (
const auto *E = dyn_cast<Expr>(S))
6106template <
class Emitter>
6109 for (
const auto *InnerStmt : S->
body())
6112 return Scope.destroyLocals();
6115template <
class Emitter>
6116bool Compiler<Emitter>::maybeEmitDeferredVarInit(
const VarDecl *VD) {
6117 if (
auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) {
6118 for (
auto *BD : DD->flat_bindings())
6119 if (
auto *KD = BD->getHoldingVar();
6120 KD && !this->visitVarDecl(KD, KD->getInit()))
6134template <
class Emitter>
bool Compiler<Emitter>::refersToUnion(
const Expr *E) {
6136 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
6137 if (
const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
6144 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
6149 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
6150 ICE && (ICE->getCastKind() == CK_NoOp ||
6151 ICE->getCastKind() == CK_DerivedToBase ||
6152 ICE->getCastKind() == CK_UncheckedDerivedToBase)) {
6153 E = ICE->getSubExpr();
6157 if (
const auto *
This = dyn_cast<CXXThisExpr>(E)) {
6158 const auto *ThisRecord =
6159 This->getType()->getPointeeType()->getAsRecordDecl();
6160 if (!ThisRecord->isUnion())
6163 if (
const auto *Ctor =
6164 dyn_cast_if_present<CXXConstructorDecl>(CompilingFunction))
6165 return Ctor->getParent() == ThisRecord;
6174template <
class Emitter>
6176 bool EvaluateConditionDecl) {
6177 for (
const auto *D : DS->
decls()) {
6182 const auto *VD = dyn_cast<VarDecl>(D);
6189 if (EvaluateConditionDecl && !this->maybeEmitDeferredVarInit(VD))
6196template <
class Emitter>
6199 return this->emitUnsupported(RS);
6205 if (!this->
visit(RE))
6211 if (RE->getType()->isVoidType()) {
6212 if (!this->
visit(RE))
6215 if (RE->containsErrors())
6220 if (!this->emitRVOPtr(RE))
6226 return this->emitRetVoid(RS);
6232 return this->emitRetVoid(RS);
6238 auto visitChildStmt = [&](
const Stmt *S) ->
bool {
6245 if (
auto *CondInit = IS->
getInit()) {
6261 return visitChildStmt(IS->
getThen());
6263 return visitChildStmt(Else);
6269 if (!this->emitIsConstantContext(IS))
6272 if (!this->emitIsConstantContext(IS))
6274 if (!this->emitInv(IS))
6288 LabelTy LabelElse = this->getLabel();
6289 LabelTy LabelEnd = this->getLabel();
6290 if (!this->jumpFalse(LabelElse, IS))
6292 if (!visitChildStmt(IS->
getThen()))
6294 if (!this->jump(LabelEnd, IS))
6296 this->emitLabel(LabelElse);
6297 if (!visitChildStmt(Else))
6299 this->emitLabel(LabelEnd);
6301 LabelTy LabelEnd = this->getLabel();
6302 if (!this->jumpFalse(LabelEnd, IS))
6304 if (!visitChildStmt(IS->
getThen()))
6306 this->emitLabel(LabelEnd);
6315template <
class Emitter>
6320 LabelTy CondLabel = this->getLabel();
6321 LabelTy EndLabel = this->getLabel();
6325 this->fallthrough(CondLabel);
6326 this->emitLabel(CondLabel);
6342 if (!this->jumpFalse(EndLabel, S))
6352 if (!this->jump(CondLabel, S))
6354 this->fallthrough(EndLabel);
6355 this->emitLabel(EndLabel);
6364 LabelTy StartLabel = this->getLabel();
6365 LabelTy EndLabel = this->getLabel();
6366 LabelTy CondLabel = this->getLabel();
6370 this->fallthrough(StartLabel);
6371 this->emitLabel(StartLabel);
6377 this->fallthrough(CondLabel);
6378 this->emitLabel(CondLabel);
6385 if (!this->jumpTrue(StartLabel, S))
6388 this->fallthrough(EndLabel);
6389 this->emitLabel(EndLabel);
6393template <
class Emitter>
6401 LabelTy EndLabel = this->getLabel();
6402 LabelTy CondLabel = this->getLabel();
6403 LabelTy IncLabel = this->getLabel();
6410 this->fallthrough(CondLabel);
6411 this->emitLabel(CondLabel);
6423 if (!this->jumpFalse(EndLabel, S))
6432 this->fallthrough(IncLabel);
6433 this->emitLabel(IncLabel);
6439 if (!this->jump(CondLabel, S))
6443 this->emitLabel(EndLabel);
6449template <
class Emitter>
6459 LabelTy EndLabel = this->getLabel();
6460 LabelTy CondLabel = this->getLabel();
6461 LabelTy IncLabel = this->getLabel();
6476 this->fallthrough(CondLabel);
6477 this->emitLabel(CondLabel);
6480 if (!this->jumpFalse(EndLabel, S))
6491 this->fallthrough(IncLabel);
6492 this->emitLabel(IncLabel);
6497 if (!this->jump(CondLabel, S))
6500 this->fallthrough(EndLabel);
6501 this->emitLabel(EndLabel);
6505template <
class Emitter>
6516 if (LI.BreakLabel) {
6517 TargetLabel = *LI.BreakLabel;
6518 BreakScope = LI.BreakOrContinueScope;
6524 if (LI.Name == TargetLoop) {
6525 TargetLabel = *LI.BreakLabel;
6526 BreakScope = LI.BreakOrContinueScope;
6537 C =
C->getParent()) {
6538 if (!
C->destroyLocals())
6542 return this->jump(*TargetLabel, S);
6545template <
class Emitter>
6556 if (LI.ContinueLabel) {
6557 TargetLabel = *LI.ContinueLabel;
6558 ContinueScope = LI.BreakOrContinueScope;
6564 if (LI.Name == TargetLoop) {
6565 TargetLabel = *LI.ContinueLabel;
6566 ContinueScope = LI.BreakOrContinueScope;
6571 assert(TargetLabel);
6574 C =
C->getParent()) {
6575 if (!
C->destroyLocals())
6579 return this->jump(*TargetLabel, S);
6582template <
class Emitter>
6585 if (
Cond->containsErrors())
6592 LabelTy EndLabel = this->getLabel();
6597 if (
const auto *CondInit = S->
getInit())
6608 if (!this->emitSetLocal(CondT, CondVar, S))
6618 if (
const auto *CS = dyn_cast<CaseStmt>(SC)) {
6621 if (CS->caseStmtIsGNURange()) {
6622 LabelTy EndOfRangeCheck = this->getLabel();
6623 const Expr *Low = CS->getLHS();
6624 const Expr *High = CS->getRHS();
6628 if (!this->emitGetLocal(CondT, CondVar, CS))
6630 if (!this->
visit(Low))
6633 if (!this->emitGE(
LT, S))
6635 if (!this->jumpFalse(EndOfRangeCheck, S))
6638 if (!this->emitGetLocal(CondT, CondVar, CS))
6640 if (!this->
visit(High))
6643 if (!this->emitLE(HT, S))
6647 this->emitLabel(EndOfRangeCheck);
6652 if (
Value->isValueDependent())
6657 if (!this->emitGetLocal(CondT, CondVar, CS))
6663 if (!this->emitEQ(ValueT, S))
6668 assert(!DefaultLabel);
6669 DefaultLabel = this->getLabel();
6676 if (!this->jump(*DefaultLabel, S))
6679 if (!this->jump(EndLabel, S))
6687 this->fallthrough(EndLabel);
6688 this->emitLabel(EndLabel);
6693template <
class Emitter>
6701 return this->emitUnsupported(S);
6706template <
class Emitter>
6713 if (LI.DefaultLabel) {
6714 DefaultLabel = *LI.DefaultLabel;
6719 this->emitLabel(DefaultLabel);
6723template <
class Emitter>
6730 if (IsMSVCConstexprAttr && !this->emitPushMSVCCE(S))
6733 if (this->
Ctx.getLangOpts().CXXAssumptions &&
6734 !this->Ctx.getLangOpts().MSVCCompat) {
6736 auto *AA = dyn_cast<CXXAssumeAttr>(A);
6742 const Expr *Assumption = AA->getAssumption();
6753 if (!this->emitAssume(Assumption))
6762 if (IsMSVCConstexprAttr)
6763 return this->emitPopMSVCCE(S);
6767template <
class Emitter>
6773template <
class Emitter>
6774bool Compiler<Emitter>::emitLambdaStaticInvokerBody(
const CXXMethodDecl *MD) {
6781 assert(ClosureClass->
captures().empty());
6785 "A generic lambda's static-invoker function must be a "
6786 "template specialization");
6790 void *InsertPos =
nullptr;
6791 const FunctionDecl *CorrespondingCallOpSpecialization =
6793 assert(CorrespondingCallOpSpecialization);
6794 LambdaCallOp = CorrespondingCallOpSpecialization;
6798 assert(ClosureClass->
captures().empty());
6799 const Function *
Func = this->getFunction(LambdaCallOp);
6802 assert(
Func->hasThisPointer());
6805 if (
Func->hasRVO()) {
6806 if (!this->emitRVOPtr(MD))
6814 if (!this->emitNullPtr(0,
nullptr, MD))
6819 auto It = this->Params.find(PVD);
6820 assert(It != this->Params.end());
6824 PrimType ParamType = this->classify(PVD->getType()).value_or(
PT_Ptr);
6825 if (!this->emitGetParam(ParamType, It->second.Index, MD))
6829 if (!this->emitCall(
Func, 0, LambdaCallOp))
6834 return this->emitRet(*ReturnType, MD);
6837 return this->emitRetVoid(MD);
6840template <
class Emitter>
6841bool Compiler<Emitter>::checkLiteralType(
const Expr *E) {
6842 if (Ctx.getLangOpts().CPlusPlus23)
6852 const Expr *InitExpr =
Init->getInit();
6854 if (!
Init->isWritten() && !
Init->isInClassMemberInitializer() &&
6858 if (
const auto *CE = dyn_cast<CXXConstructExpr>(InitExpr)) {
6868template <
class Emitter>
6870 assert(!ReturnType);
6873 if (!this->emitStartThisLifetime1(Ctor))
6876 auto emitFieldInitializer = [&](
const Record::Field *F,
unsigned FieldOffset,
6877 const Expr *InitExpr,
6880 if (InitExpr->getType().isNull())
6884 if (
Activate && !this->emitActivateThisField(FieldOffset, InitExpr))
6887 if (!this->visit(InitExpr))
6890 if (F->isBitField())
6891 return this->emitInitThisBitField(*T, FieldOffset, F->bitWidth(),
6893 return this->emitInitThisField(*T, FieldOffset, InitExpr);
6898 if (!this->emitGetPtrThisField(FieldOffset, InitExpr))
6901 if (
Activate && !this->emitActivate(InitExpr))
6904 return this->visitInitializerPop(InitExpr);
6908 const Record *
R = this->getRecord(RD);
6911 bool IsUnion =
R->isUnion();
6921 if (!this->emitThis(Ctor))
6924 if (!this->emitGetParam(
PT_Ptr, 0, Ctor))
6927 return this->emitMemcpy(Ctor) && this->emitPopPtr(Ctor) &&
6928 this->emitRetVoid(Ctor);
6931 unsigned FieldInits = 0;
6933 for (
const auto *
Init : Ctor->
inits()) {
6937 const Expr *InitExpr =
Init->getInit();
6939 const Record::Field *F =
R->getField(
Member);
6943 if (!emitFieldInitializer(F, F->Offset, InitExpr, IsUnion))
6947 const auto *BaseDecl =
Base->getAsCXXRecordDecl();
6950 if (
Init->isBaseVirtual()) {
6951 assert(
R->getVirtualBase(BaseDecl));
6952 if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
6958 const Record::Base *B =
R->getBase(BaseDecl);
6960 if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
6964 if (!this->visitInitializerPop(InitExpr))
6969 unsigned ChainSize = IFD->getChainingSize();
6970 assert(ChainSize >= 2);
6972 unsigned NestedFieldOffset = 0;
6973 const Record::Field *NestedField =
nullptr;
6974 for (
unsigned I = 0; I != ChainSize; ++I) {
6976 const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
6977 assert(FieldRecord);
6979 NestedField = FieldRecord->
getField(FD);
6980 assert(NestedField);
6981 IsUnion = IsUnion || FieldRecord->
isUnion();
6983 NestedFieldOffset += NestedField->Offset;
6986 if (I != ChainSize - 1)
6989 assert(NestedField);
6992 if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr,
6997 unsigned InitFieldOffset = 0;
6998 for (
const NamedDecl *ND : IFD->chain().drop_back()) {
7000 const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
7001 assert(FieldRecord);
7002 NestedField = FieldRecord->
getField(FD);
7003 InitFieldOffset += NestedField->Offset;
7004 assert(NestedField);
7005 if (!this->emitGetPtrThisField(InitFieldOffset, InitExpr))
7007 if (!this->emitFinishInitPop(InitExpr))
7011 InitStack.pop_back_n(ChainSize - 1);
7014 assert(
Init->isDelegatingInitializer());
7015 if (!this->emitThis(InitExpr))
7017 if (!this->visitInitializerPop(
Init->getInit()))
7021 if (!
Scope.destroyLocals())
7025 if (FieldInits !=
R->getNumFields()) {
7026 assert(FieldInits < R->getNumFields());
7028 if (!this->emitStartThisLifetime(Ctor))
7035 if (
const auto *CS = dyn_cast<CompoundStmt>(Body)) {
7036 if (!CS->body_empty() && !this->emitCtorCheck(
SourceInfo{}))
7043 if (!visitStmt(Body))
7050template <
class Emitter>
7053 const Record *
R = this->getRecord(RD);
7057 if (!
Dtor->isTrivial() &&
Dtor->getBody()) {
7058 if (!this->visitStmt(
Dtor->getBody()))
7062 if (!this->emitThis(
Dtor))
7065 if (!this->emitCheckDestruction(
Dtor))
7069 if (!
R->isUnion()) {
7073 for (
const Record::Field &Field : llvm::reverse(
R->fields())) {
7077 if (!this->emitGetPtrField(Field.Offset,
SourceInfo{}))
7079 if (!this->emitDestructionPop(D,
SourceInfo{}))
7084 for (
const Record::Base &
Base : llvm::reverse(
R->bases())) {
7085 if (
Base.R->hasTrivialDtor())
7089 if (!this->emitRecordDestructionPop(
Base.R, {}))
7093 if (!this->emitMarkDestroyed(
Dtor))
7097 return this->emitPopPtr(
Dtor) && this->emitRetVoid(
Dtor);
7100template <
class Emitter>
7101bool Compiler<Emitter>::compileUnionAssignmentOperator(
7103 if (!this->emitThis(MD))
7106 if (!this->emitGetParam(
PT_Ptr, 0, MD))
7109 return this->emitMemcpy(MD) && this->emitRet(
PT_Ptr, MD);
7112template <
class Emitter>
7122 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(F))
7123 return this->compileConstructor(Ctor);
7124 if (
const auto *
Dtor = dyn_cast<CXXDestructorDecl>(F))
7125 return this->compileDestructor(
Dtor);
7128 if (
const auto *MD = dyn_cast<CXXMethodDecl>(F)) {
7133 return this->compileUnionAssignmentOperator(MD);
7136 return this->emitLambdaStaticInvokerBody(MD);
7140 if (
const auto *Body = F->
getBody())
7154 return FD->getBitWidthValue();
7157template <
class Emitter>
7173 if (!
Ctx.getLangOpts().CPlusPlus14)
7174 return this->emitInvalid(E);
7176 return this->emitError(E);
7178 if (!this->
visit(SubExpr))
7182 if (!this->emitIncPtr(E))
7189 return DiscardResult ? this->emitIncfPop(getFPOptions(E), E)
7190 : this->emitIncf(getFPOptions(E), E);
7202 if (!
Ctx.getLangOpts().CPlusPlus14)
7203 return this->emitInvalid(E);
7205 return this->emitError(E);
7207 if (!this->
visit(SubExpr))
7211 if (!this->emitDecPtr(E))
7218 return DiscardResult ? this->emitDecfPop(getFPOptions(E), E)
7219 : this->emitDecf(getFPOptions(E), E);
7232 if (!
Ctx.getLangOpts().CPlusPlus14)
7233 return this->emitInvalid(E);
7235 return this->emitError(E);
7237 if (!this->
visit(SubExpr))
7241 if (!this->emitLoadPtr(E))
7243 if (!this->emitConstUint8(1, E))
7245 if (!this->emitAddOffsetUint8(E))
7247 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
7253 return this->emitIncfPop(getFPOptions(E), E);
7263 const auto &TargetSemantics =
Ctx.getFloatSemantics(E->
getType());
7264 if (!this->emitLoadFloat(E))
7266 APFloat F(TargetSemantics, 1);
7267 if (!this->emitFloat(F, E))
7270 if (!this->emitAddf(getFPOptions(E), E))
7272 if (!this->emitStoreFloat(E))
7284 return E->
isGLValue() || this->emitLoadPop(*T, E);
7287 if (!
Ctx.getLangOpts().CPlusPlus14)
7288 return this->emitInvalid(E);
7290 return this->emitError(E);
7292 if (!this->
visit(SubExpr))
7296 if (!this->emitLoadPtr(E))
7298 if (!this->emitConstUint8(1, E))
7300 if (!this->emitSubOffsetUint8(E))
7302 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
7308 return this->emitDecfPop(getFPOptions(E), E);
7318 const auto &TargetSemantics =
Ctx.getFloatSemantics(E->
getType());
7319 if (!this->emitLoadFloat(E))
7321 APFloat F(TargetSemantics, 1);
7322 if (!this->emitFloat(F, E))
7325 if (!this->emitSubf(getFPOptions(E), E))
7327 if (!this->emitStoreFloat(E))
7339 return E->
isGLValue() || this->emitLoadPop(*T, E);
7343 return this->emitError(E);
7346 return this->
discard(SubExpr);
7351 if (!this->emitInv(E))
7355 return this->emitCast(
PT_Bool, ET, E);
7359 return this->emitError(E);
7361 if (!this->
visit(SubExpr))
7363 return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
7366 return this->emitError(E);
7368 if (!this->
visit(SubExpr))
7384 if (!
Ctx.getLangOpts().CPlusPlus) {
7386 if (
const auto *Deref = dyn_cast<UnaryOperator>(
Sub);
7387 Deref && Deref->getOpcode() == UO_Deref)
7388 return this->
delegate(Deref->getSubExpr());
7394 return this->
discard(SubExpr);
7396 if (!this->
visit(SubExpr))
7403 return this->emitNarrowPtr(E);
7408 return this->emitError(E);
7410 if (!this->
visit(SubExpr))
7412 return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
7424 : this->visitZeroInitializer(*T, SubExpr->
getType(), SubExpr);
7429 assert(
false &&
"Unhandled opcode");
7435template <
class Emitter>
7441 return this->
discard(SubExpr);
7444 auto prepareResult = [=]() ->
bool {
7449 return this->emitGetPtrLocal(*LocalIndex, E);
7456 unsigned SubExprOffset = ~0u;
7457 auto createTemp = [=, &SubExprOffset]() ->
bool {
7460 if (!this->
visit(SubExpr))
7462 return this->emitSetLocal(
PT_Ptr, SubExprOffset, E);
7466 auto getElem = [=](
unsigned Offset,
unsigned Index) ->
bool {
7467 if (!this->emitGetLocal(
PT_Ptr, Offset, E))
7469 return this->emitArrayElemPop(ElemT, Index, E);
7474 if (!prepareResult())
7478 for (
unsigned I = 0; I != 2; ++I) {
7479 if (!getElem(SubExprOffset, I))
7481 if (!this->emitNeg(ElemT, E))
7483 if (!this->emitInitElem(ElemT, I, E))
7494 if (!this->
visit(SubExpr))
7496 if (!this->emitComplexBoolCast(SubExpr))
7498 if (!this->emitInv(E))
7501 return this->emitCast(
PT_Bool, ET, E);
7505 return this->emitComplexReal(SubExpr);
7508 if (!this->
visit(SubExpr))
7512 if (!this->emitConstUint8(1, E))
7514 return this->emitArrayElemPtrPopUint8(E);
7525 if (!this->emitArrayElem(ElemT, 1, E))
7527 if (!this->emitNeg(ElemT, E))
7529 if (!this->emitInitElem(ElemT, 1, E))
7537 return this->emitInvalid(E);
7543template <
class Emitter>
7549 return this->
discard(SubExpr);
7552 if (UnaryOp == UO_Extension)
7555 if (UnaryOp != UO_Plus && UnaryOp != UO_Minus && UnaryOp != UO_LNot &&
7556 UnaryOp != UO_Not && UnaryOp != UO_AddrOf)
7557 return this->emitInvalid(E);
7560 if (UnaryOp == UO_Plus || UnaryOp == UO_AddrOf)
7567 if (!this->emitGetPtrLocal(*LocalIndex, E))
7572 unsigned SubExprOffset =
7574 if (!this->
visit(SubExpr))
7576 if (!this->emitSetLocal(
PT_Ptr, SubExprOffset, E))
7581 auto getElem = [=](
unsigned Offset,
unsigned Index) ->
bool {
7582 if (!this->emitGetLocal(
PT_Ptr, Offset, E))
7584 return this->emitArrayElemPop(ElemT, Index, E);
7589 for (
unsigned I = 0; I != VecTy->getNumElements(); ++I) {
7590 if (!getElem(SubExprOffset, I))
7592 if (!this->emitNeg(ElemT, E))
7594 if (!this->emitInitElem(ElemT, I, E))
7609 for (
unsigned I = 0; I != VecTy->getNumElements(); ++I) {
7610 if (!getElem(SubExprOffset, I))
7613 if (!this->emitPrimCast(ElemT,
PT_Bool,
Ctx.getASTContext().BoolTy, E))
7615 if (!this->emitInv(E))
7617 if (!this->emitPrimCast(
PT_Bool, ElemT, VecTy->getElementType(), E))
7619 if (!this->emitNeg(ElemT, E))
7621 if (ElemT != ResultVecElemT &&
7622 !this->emitPrimCast(ElemT, ResultVecElemT, ResultVecTy, E))
7624 if (!this->emitInitElem(ResultVecElemT, I, E))
7630 for (
unsigned I = 0; I != VecTy->getNumElements(); ++I) {
7631 if (!getElem(SubExprOffset, I))
7634 if (!this->emitInv(E))
7637 if (!this->emitComp(ElemT, E))
7640 if (!this->emitInitElem(ElemT, I, E))
7645 llvm_unreachable(
"Unsupported unary operators should be handled up front");
7650template <
class Emitter>
7652 if (
const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
7655 return this->emitConst(ECD->getInitVal(), E);
7657 if (
const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
7661 return F && this->emitGetFnPtr(F, E);
7663 if (
const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) {
7671 return this->emitInitGlobal(*T, *Index, E);
7674 if (!this->emitGetPtrGlobal(*Index, E))
7678 return this->emitFinishInit(E);
7690 auto maybePopPtr = [&]() ->
bool {
7692 return this->emitPopPtr(E);
7699 if (
const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
7703 if (
Ctx.getLangOpts().CPlusPlus && !
Ctx.getLangOpts().CPlusPlus11 &&
7708 if (
auto It = this->Params.find(PVD); It != this->Params.end()) {
7709 if (IsReference || !It->second.IsPtr)
7710 return this->emitGetParam(
classifyPrim(E), It->second.Index, E);
7712 return this->emitGetPtrParam(It->second.Index, E);
7715 if (!
Ctx.getLangOpts().CPlusPlus23 && IsReference)
7721 const unsigned Offset = It->second.Offset;
7724 return this->emitGetRefLocal(Offset, E) && maybePopPtr();
7726 return this->emitGetPtrLocal(Offset, E) && maybePopPtr();
7729 if (
auto GlobalIndex =
P.getGlobal(D)) {
7731 if (!
Ctx.getLangOpts().CPlusPlus11)
7732 return this->emitGetGlobal(
classifyPrim(E), *GlobalIndex, E);
7733 if (!
Ctx.getLangOpts().CPlusPlus23)
7734 return this->emitGetGlobalUnchecked(
classifyPrim(E), *GlobalIndex, E);
7736 return this->emitGetRefGlobal(*GlobalIndex, E) && maybePopPtr();
7739 return this->emitGetPtrGlobal(*GlobalIndex, E) && maybePopPtr();
7743 auto revisit = [&](
const VarDecl *VD,
7744 bool IsConstexprUnknown =
true) ->
bool {
7746 IsConstexprUnknown);
7751 if (!this->emitPopCC(E))
7754 if (VarState.notCreated())
7762 if constexpr (!std::is_same_v<Emitter, EvalEmitter>) {
7764 if (
auto It = this->LambdaCaptures.find(D);
7765 It != this->LambdaCaptures.end()) {
7766 auto [Offset, IsPtr] = It->second;
7769 return this->emitGetThisFieldPtr(Offset, E) && maybePopPtr();
7770 return this->emitGetPtrThisField(Offset, E) && maybePopPtr();
7774 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E);
7775 DRE && DRE->refersToEnclosingVariableOrCapture()) {
7776 if (
const auto *VD = dyn_cast<VarDecl>(D); VD && VD->
isInitCapture())
7780 if (
const auto *BD = dyn_cast<BindingDecl>(D))
7781 return this->
delegate(BD->getBinding());
7787 return this->emitDummyPtr(D, E);
7792 const auto *VD = dyn_cast<VarDecl>(D);
7794 return this->emitError(E);
7797 if (!
Ctx.getLangOpts().CPlusPlus) {
7801 return revisit(VD,
false);
7805 return this->emitDummyPtr(D, E);
7809 const auto typeShouldBeVisited = [&](
QualType T) ->
bool {
7810 if (T.isConstant(
Ctx.getASTContext()))
7812 return T->isReferenceType();
7816 typeShouldBeVisited(DeclType)) {
7818 Init && !
Init->isValueDependent()) {
7823 (void)
Init->EvaluateAsInitializer(
Ctx.getASTContext(), VD,
Result,
true);
7836 bool IsConstexprUnknown = !DeclType.
isConstant(
Ctx.getASTContext()) &&
7841 return revisit(VD, IsConstexprUnknown);
7842 }
else if (
Ctx.getLangOpts().CPlusPlus23 && IsReference)
7843 return revisit(VD,
true);
7852 return this->emitDummyPtr(
7856template <
class Emitter>
7862template <
class Emitter>
7872 if (!
C->destroyLocals())
7878template <
class Emitter>
7879unsigned Compiler<Emitter>::collectBaseOffset(
const QualType BaseType,
7882 if (
const auto *R = Ty->getPointeeCXXRecordDecl())
7884 return Ty->getAsCXXRecordDecl();
7886 const CXXRecordDecl *BaseDecl = extractRecordDecl(BaseType);
7887 const CXXRecordDecl *DerivedDecl = extractRecordDecl(DerivedType);
7889 return Ctx.collectBaseOffset(BaseDecl, DerivedDecl);
7893template <
class Emitter>
7900 const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
7905 return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(ToQT),
7906 getFPOptions(E), E);
7908 return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(ToQT),
7909 getFPOptions(E), E);
7913 return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);
7918 return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E);
7920 return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E);
7924 return FromT != ToT ? this->emitCast(FromT, ToT, E) :
true;
7928 const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
7929 return this->emitCastIntegralFloating(FromT, ToSem, getFPOptions(E), E);
7936template <
class Emitter>
7939 assert(FromT != ToT);
7942 return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E);
7944 return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E);
7946 return this->emitCast(FromT, ToT, E);
7950template <
class Emitter>
7951bool Compiler<Emitter>::emitComplexReal(
const Expr *SubExpr) {
7955 return this->
discard(SubExpr);
7957 if (!this->visit(SubExpr))
7960 if (!this->emitConstUint8(0, SubExpr))
7962 return this->emitArrayElemPtrPopUint8(SubExpr);
7966 return this->emitArrayElemPop(classifyComplexElementType(SubExpr->
getType()),
7970template <
class Emitter>
7971bool Compiler<Emitter>::emitComplexBoolCast(
const Expr *E) {
7972 assert(!DiscardResult);
7976 if (!this->emitArrayElem(ElemT, 0, E))
7979 if (!this->emitCastFloatingIntegral(
PT_Bool, getFPOptions(E), E))
7982 if (!this->emitCast(ElemT,
PT_Bool, E))
7987 LabelTy LabelTrue = this->getLabel();
7988 if (!this->jumpTrue(LabelTrue, E))
7991 if (!this->emitArrayElemPop(ElemT, 1, E))
7994 if (!this->emitCastFloatingIntegral(
PT_Bool, getFPOptions(E), E))
7997 if (!this->emitCast(ElemT,
PT_Bool, E))
8001 LabelTy EndLabel = this->getLabel();
8002 this->jump(EndLabel, E);
8004 this->emitLabel(LabelTrue);
8005 if (!this->emitPopPtr(E))
8007 if (!this->emitConstBool(
true, E))
8010 this->fallthrough(EndLabel);
8011 this->emitLabel(EndLabel);
8016template <
class Emitter>
8017bool Compiler<Emitter>::emitComplexComparison(
const Expr *LHS,
const Expr *RHS,
8028 LHSIsComplex =
true;
8029 ElemT = classifyComplexElementType(LHS->
getType());
8030 LHSOffset = allocateLocalPrimitive(LHS,
PT_Ptr,
true);
8031 if (!this->visit(LHS))
8033 if (!this->emitSetLocal(
PT_Ptr, LHSOffset, E))
8036 LHSIsComplex =
false;
8038 LHSOffset = this->allocateLocalPrimitive(LHS, LHST,
true);
8039 if (!this->visit(LHS))
8041 if (!this->emitSetLocal(LHST, LHSOffset, E))
8048 RHSIsComplex =
true;
8049 ElemT = classifyComplexElementType(RHS->
getType());
8050 RHSOffset = allocateLocalPrimitive(RHS,
PT_Ptr,
true);
8051 if (!this->visit(RHS))
8053 if (!this->emitSetLocal(
PT_Ptr, RHSOffset, E))
8056 RHSIsComplex =
false;
8058 RHSOffset = this->allocateLocalPrimitive(RHS, RHST,
true);
8059 if (!this->visit(RHS))
8061 if (!this->emitSetLocal(RHST, RHSOffset, E))
8065 auto getElem = [&](
unsigned LocalOffset,
unsigned Index,
8066 bool IsComplex) ->
bool {
8068 if (!this->emitGetLocal(
PT_Ptr, LocalOffset, E))
8070 return this->emitArrayElemPop(ElemT, Index, E);
8072 return this->emitGetLocal(ElemT, LocalOffset, E);
8075 for (
unsigned I = 0; I != 2; ++I) {
8077 if (!getElem(LHSOffset, I, LHSIsComplex))
8079 if (!getElem(RHSOffset, I, RHSIsComplex))
8082 if (!this->emitEQ(ElemT, E))
8085 if (!this->emitCastBoolUint8(E))
8090 if (!this->emitAddUint8(E))
8092 if (!this->emitConstUint8(2, E))
8096 if (!this->emitEQUint8(E))
8099 if (!this->emitNEUint8(E))
8106 return this->emitCast(
PT_Bool, ResT, E);
8113template <
class Emitter>
8114bool Compiler<Emitter>::emitRecordDestructionPop(
const Record *R,
8117 assert(!
R->hasTrivialDtor());
8120 const Function *DtorFunc = getFunction(
Dtor);
8123 assert(DtorFunc->hasThisPointer());
8124 assert(DtorFunc->getNumParams() == 1);
8125 return this->emitCall(DtorFunc, 0, Loc);
8130template <
class Emitter>
8131bool Compiler<Emitter>::emitDestructionPop(
const Descriptor *Desc,
8143 return this->emitPopPtr(Loc);
8145 for (ssize_t I = N - 1; I >= 1; --I) {
8146 if (!this->emitConstUint64(I, Loc))
8148 if (!this->emitArrayElemPtrUint64(Loc))
8150 if (!this->emitDestructionPop(ElemDesc, Loc))
8154 if (!this->emitConstUint64(0, Loc))
8156 if (!this->emitArrayElemPtrPopUint64(Loc))
8158 return this->emitDestructionPop(ElemDesc, Loc);
8163 return this->emitRecordDestructionPop(Desc->
ElemRecord, Loc);
8168template <
class Emitter>
8169bool Compiler<Emitter>::emitDummyPtr(
const DeclTy &D,
const Expr *E,
bool CU) {
8170 assert(!DiscardResult &&
"Should've been checked before");
8171 unsigned DummyID = P.getOrCreateDummy(D, CU);
8173 if (!this->emitGetPtrGlobal(DummyID, E))
8181 return this->emitDecayPtr(
PT_Ptr, PT, E);
8187template <
class Emitter>
8190 return this->emitConstFloat(
Floating(F), Info);
8192 APInt I = F.bitcastToAPInt();
8193 return this->emitConstFloat(
8194 Floating(
const_cast<uint64_t *
>(I.getRawData()),
8195 llvm::APFloatBase::SemanticsToEnum(F.getSemantics())),
8206template <
class Emitter>
8207bool Compiler<Emitter>::emitBuiltinBitCast(
const CastExpr *E) {
8220 if (!this->emitGetPtrLocal(*LocalIndex, E))
8230 if (!this->visit(SubExpr))
8232 }
else if (
OptPrimType FromT = classify(SubExpr)) {
8233 unsigned TempOffset =
8234 allocateLocalPrimitive(SubExpr, *FromT,
true);
8235 if (!this->visit(SubExpr))
8237 if (!this->emitSetLocal(*FromT, TempOffset, E))
8239 if (!this->emitGetPtrLocal(TempOffset, E))
8246 if (!this->emitBitCast(E))
8248 return DiscardResult ? this->emitPopPtr(E) :
true;
8252 const llvm::fltSemantics *TargetSemantics =
nullptr;
8254 TargetSemantics = &Ctx.getFloatSemantics(ToType);
8260 uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);
8262 if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->
isStdByteType(),
8263 ResultBitWidth, TargetSemantics,
8268 return this->emitPop(*ToT, E);
8277template <
class Emitter>
8278bool Compiler<Emitter>::emitHLSLAggregateSplat(
PrimType SrcT,
8283 unsigned NumElems = 0;
8286 NumElems = VT->getNumElements();
8287 ElemType = VT->getElementType();
8289 NumElems = MT->getNumElementsFlattened();
8290 ElemType = MT->getElementType();
8293 PrimType ElemT = classifyPrim(ElemType);
8294 for (
unsigned I = 0; I != NumElems; ++I) {
8295 if (!this->emitGetLocal(SrcT, SrcOffset, E))
8297 if (!this->emitPrimCast(SrcT, ElemT, ElemType, E))
8299 if (!this->emitInitElem(ElemT, I, E))
8309 QualType ArrElemType = CAT->getElementType();
8310 unsigned ArrSize = CAT->getZExtSize();
8313 for (
unsigned I = 0; I != ArrSize; ++I) {
8314 if (!this->emitGetLocal(SrcT, SrcOffset, E))
8316 if (!this->emitPrimCast(SrcT, *ElemT, ArrElemType, E))
8318 if (!this->emitInitElem(*ElemT, I, E))
8322 for (
unsigned I = 0; I != ArrSize; ++I) {
8323 if (!this->emitConstUint32(I, E))
8325 if (!this->emitArrayElemPtrUint32(E))
8327 if (!emitHLSLAggregateSplat(SrcT, SrcOffset, ArrElemType, E))
8329 if (!this->emitFinishInitPop(E))
8339 const Record *
R = getRecord(DestType);
8343 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(
R->getDecl())) {
8345 const Record::Base *B =
R->getBase(BS.getType());
8347 if (!this->emitGetPtrBase(B->Offset, E))
8349 if (!emitHLSLAggregateSplat(SrcT, SrcOffset, BS.getType(), E))
8351 if (!this->emitFinishInitPop(E))
8356 for (
const Record::Field &F :
R->fields()) {
8357 if (F.isUnnamedBitField())
8360 QualType FieldType = F.Decl->getType();
8362 if (!this->emitGetLocal(SrcT, SrcOffset, E))
8364 if (!this->emitPrimCast(SrcT, *FieldT, FieldType, E))
8366 if (F.isBitField()) {
8367 if (!this->emitInitBitField(*FieldT, F.Offset, F.bitWidth(), E))
8370 if (!this->emitInitField(*FieldT, F.Offset, E))
8374 if (!this->emitGetPtrField(F.Offset, E))
8376 if (!emitHLSLAggregateSplat(SrcT, SrcOffset, FieldType, E))
8378 if (!this->emitPopPtr(E))
8391template <
class Emitter>
8392unsigned Compiler<Emitter>::countHLSLFlatElements(
QualType Ty) {
8395 return VT->getNumElements();
8397 return MT->getNumElementsFlattened();
8401 return CAT->getZExtSize() * countHLSLFlatElements(CAT->getElementType());
8405 const Record *
R = getRecord(Ty);
8409 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(
R->getDecl())) {
8411 Count += countHLSLFlatElements(BS.getType());
8413 for (
const Record::Field &F :
R->fields()) {
8414 if (F.isUnnamedBitField())
8416 Count += countHLSLFlatElements(F.Decl->getType());
8421 if (canClassify(Ty))
8430template <
class Emitter>
8431bool Compiler<Emitter>::emitHLSLFlattenAggregate(
8432 QualType SrcType,
unsigned SrcOffset,
8437 auto saveToLocal = [&](
PrimType T) ->
bool {
8438 unsigned Offset = allocateLocalPrimitive(E, T,
true);
8439 if (!this->emitSetLocal(T, Offset, E))
8441 Elements.push_back({Offset, T});
8447 unsigned Offset = allocateLocalPrimitive(E,
PT_Ptr,
true);
8448 if (!this->emitSetLocal(
PT_Ptr, Offset, E))
8449 return std::nullopt;
8454 unsigned NumElems = 0;
8457 NumElems = VT->getNumElements();
8458 ElemType = VT->getElementType();
8460 NumElems = MT->getNumElementsFlattened();
8461 ElemType = MT->getElementType();
8464 PrimType ElemT = classifyPrim(ElemType);
8465 for (
unsigned I = 0; I != NumElems && Elements.size() < MaxElements; ++I) {
8466 if (!this->emitGetLocal(
PT_Ptr, SrcOffset, E))
8468 if (!this->emitArrayElemPop(ElemT, I, E))
8470 if (!saveToLocal(ElemT))
8480 QualType ArrElemType = CAT->getElementType();
8481 unsigned ArrSize = CAT->getZExtSize();
8484 for (
unsigned I = 0; I != ArrSize && Elements.size() < MaxElements; ++I) {
8485 if (!this->emitGetLocal(
PT_Ptr, SrcOffset, E))
8487 if (!this->emitArrayElemPop(*ElemT, I, E))
8489 if (!saveToLocal(*ElemT))
8493 for (
unsigned I = 0; I != ArrSize && Elements.size() < MaxElements; ++I) {
8494 if (!this->emitGetLocal(
PT_Ptr, SrcOffset, E))
8496 if (!this->emitConstUint32(I, E))
8498 if (!this->emitArrayElemPtrPopUint32(E))
8503 if (!emitHLSLFlattenAggregate(ArrElemType, *ElemPtrOffset, Elements,
8514 const Record *
R = getRecord(SrcType);
8518 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(
R->getDecl())) {
8520 if (Elements.size() >= MaxElements)
8522 const Record::Base *B =
R->getBase(BS.getType());
8524 if (!this->emitGetLocal(
PT_Ptr, SrcOffset, E))
8526 if (!this->emitGetPtrBasePop(B->Offset,
false, E))
8531 if (!emitHLSLFlattenAggregate(BS.getType(), *BasePtrOffset, Elements,
8537 for (
const Record::Field &F :
R->fields()) {
8538 if (Elements.size() >= MaxElements)
8540 if (F.isUnnamedBitField())
8543 QualType FieldType = F.Decl->getType();
8544 if (!this->emitGetLocal(
PT_Ptr, SrcOffset, E))
8546 if (!this->emitGetPtrFieldPop(F.Offset, E))
8550 if (!this->emitLoadPop(*FieldT, E))
8552 if (!saveToLocal(*FieldT))
8556 if (!FieldPtrOffset)
8558 if (!emitHLSLFlattenAggregate(FieldType, *FieldPtrOffset, Elements,
8574template <
class Emitter>
8575bool Compiler<Emitter>::emitHLSLConstructAggregate(
8581 const auto &Src = Elements[ElemIdx++];
8582 if (!this->emitGetLocal(Src.Type, Src.LocalOffset, E))
8584 return this->emitPrimCast(Src.Type, DestT, DestQT, E);
8588 unsigned NumElems = 0;
8591 NumElems = VT->getNumElements();
8592 ElemType = VT->getElementType();
8594 NumElems = MT->getNumElementsFlattened();
8595 ElemType = MT->getElementType();
8598 PrimType DestElemT = classifyPrim(ElemType);
8599 for (
unsigned I = 0; I != NumElems; ++I) {
8600 if (!loadAndCast(DestElemT, ElemType))
8602 if (!this->emitInitElem(DestElemT, I, E))
8612 QualType ArrElemType = CAT->getElementType();
8613 unsigned ArrSize = CAT->getZExtSize();
8616 for (
unsigned I = 0; I != ArrSize; ++I) {
8617 if (!loadAndCast(*ElemT, ArrElemType))
8619 if (!this->emitInitElem(*ElemT, I, E))
8623 for (
unsigned I = 0; I != ArrSize; ++I) {
8624 if (!this->emitConstUint32(I, E))
8626 if (!this->emitArrayElemPtrUint32(E))
8628 if (!emitHLSLConstructAggregate(ArrElemType, Elements, ElemIdx, E))
8630 if (!this->emitFinishInitPop(E))
8640 const Record *
R = getRecord(DestType);
8644 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(
R->getDecl())) {
8646 const Record::Base *B =
R->getBase(BS.getType());
8648 if (!this->emitGetPtrBase(B->Offset, E))
8650 if (!emitHLSLConstructAggregate(BS.getType(), Elements, ElemIdx, E))
8652 if (!this->emitFinishInitPop(E))
8657 for (
const Record::Field &F :
R->fields()) {
8658 if (F.isUnnamedBitField())
8661 QualType FieldType = F.Decl->getType();
8663 if (!loadAndCast(*FieldT, FieldType))
8665 if (F.isBitField()) {
8666 if (!this->emitInitBitField(*FieldT, F.Offset, F.bitWidth(), E))
8669 if (!this->emitInitField(*FieldT, F.Offset, E))
8673 if (!this->emitGetPtrField(F.Offset, E))
8675 if (!emitHLSLConstructAggregate(FieldType, Elements, ElemIdx, E))
8677 if (!this->emitPopPtr(E))
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static void emitCleanup(CIRGenFunction &cgf, cir::CleanupScopeOp cleanupScope, EHScopeStack::Cleanup *cleanup, EHScopeStack::Cleanup::Flags flags, Address activeFlag)
static uint32_t getBitWidth(const Expr *E)
#define EMIT_ARITH_OP(OP)
static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, UnaryExprOrTypeTrait Kind)
static const Expr * stripDerivedToBaseCasts(const Expr *E)
static const Expr * stripCheckedDerivedToBaseCasts(const Expr *E)
static bool hasTrivialDefaultCtorParent(const FieldDecl *FD)
static bool initNeedsOverridenLoc(const CXXCtorInitializer *Init)
Result
Implement __builtin_bit_cast and related operations.
a trap message and trap category.
llvm::APInt getValue() const
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
const LValueBase getLValueBase() const
APValue & getArrayInitializedElt(unsigned I)
ArrayRef< LValuePathEntry > getLValuePath() const
APValue & getStructField(unsigned i)
const FieldDecl * getUnionField() const
unsigned getStructNumFields() const
bool isMemberPointerToDerivedMember() const
unsigned getArrayInitializedElts() const
unsigned getStructNumBases() const
const ValueDecl * getMemberPointerDecl() const
APValue & getUnionValue()
APValue & getArrayFiller()
bool isIndeterminate() const
ArrayRef< const CXXRecordDecl * > getMemberPointerPath() const
bool isMemberPointer() const
unsigned getArraySize() const
@ None
There is no such object (it's outside its lifetime).
bool isNullPointer() const
APValue & getStructBase(unsigned i)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getPreferredTypeAlign(QualType T) const
Return the "preferred" alignment of the specified type T for the current target, in bits.
const LangOptions & getLangOpts() const
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
TypeInfoChars getTypeInfoDataSizeInChars(QualType T) const
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
AddrLabelExpr - The GNU address of label extension, representing &&label.
Represents the index of the current element of an array being initialized by an ArrayInitLoopExpr.
Represents a loop initializing the elements of an array.
llvm::APInt getArraySize() const
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Expr * getSubExpr() const
Get the initializer to use for each array element.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Expr * getLHS()
An array access can be written A[4] or 4[A] (both are equivalent).
An Embarcadero array type trait, as used in the implementation of __array_rank and __array_extent.
uint64_t getValue() const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
Represents a C++ declaration that introduces decls from somewhere else.
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isLogicalOp(Opcode Opc)
static bool isComparisonOp(Opcode Opc)
static bool isShiftOp(Opcode Opc)
static bool isCommaOp(Opcode Opc)
static Opcode getOpForCompoundAssignment(Opcode Opc)
static bool isPtrMemOp(Opcode Opc)
predicates to categorize the respective opcodes.
static bool isAssignmentOp(Opcode Opc)
static bool isCompoundAssignmentOp(Opcode Opc)
static bool isBitwiseOp(Opcode Opc)
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
BreakStmt - This represents a break.
Represents a C++2a __builtin_bit_cast(T, v) expression.
Represents a base class of a C++ class.
Represents binding an expression to a temporary.
const Expr * getSubExpr() const
A boolean literal, per ([C++ lex.bool] Boolean literals).
Represents a call to a C++ constructor.
bool isElidable() const
Whether this construction is elidable.
Expr * getArg(unsigned Arg)
Return the specified argument.
bool requiresZeroInitialization() const
Whether this construction first requires zero-initialization before the initializer is called.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ constructor within a class.
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Represents a C++ base or member initializer.
A default argument (C++ [dcl.fct.default]).
A use of a default initializer in a constructor or in aggregate initialization.
Expr * getExpr()
Get the initialization expression that will be used.
Represents a delete expression for memory deallocation and destructor calls, e.g.
FunctionDecl * getOperatorDelete() const
bool isGlobalDelete() const
Represents a C++ destructor within a class.
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
DeclStmt * getBeginStmt()
DeclStmt * getLoopVarStmt()
DeclStmt * getRangeStmt()
Represents a call to an inherited base class constructor from an inheriting constructor.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will call.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
bool isLambdaStaticInvoker() const
Determine whether this is a lambda closure type's static member function that is used for the result ...
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
QualType getAllocatedType() const
std::optional< Expr * > getArraySize()
This might return std::nullopt even if isArray() returns true, since there might not be an array size...
Expr * getPlacementArg(unsigned I)
unsigned getNumPlacementArgs() const
FunctionDecl * getOperatorNew() const
Expr * getInitializer()
The initializer of this new-expression.
Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
The null pointer literal (C++11 [lex.nullptr])
Represents a list-initialization with parenthesis.
MutableArrayRef< Expr * > getInitExprs()
Represents a C++ struct/union/class.
bool hasTrivialDefaultConstructor() const
Determine whether this class has a trivial default constructor (C++11 [class.ctor]p5).
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
capture_const_range captures() const
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
A C++ reinterpret_cast expression (C++ [expr.reinterpret.cast]).
A rewritten comparison expression that was originally written using operator syntax.
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
An expression "T()" which creates an rvalue of a non-class type T.
Implicit construction of a std::initializer_list<T> object from an array temporary within list-initia...
Represents the this expression in C++.
A C++ throw-expression (C++ [except.throw]).
const Expr * getSubExpr() const
CXXTryStmt - A C++ try block, including all handlers.
CompoundStmt * getTryBlock()
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
bool isTypeOperand() const
QualType getTypeOperand(const ASTContext &Context) const
Retrieves the type operand of this typeid() expression after various required adjustments (removing r...
Expr * getExprOperand() const
bool isPotentiallyEvaluated() const
Determine whether this typeid has a type operand which is potentially evaluated, per C++11 [expr....
A Microsoft C++ __uuidof expression, which gets the _GUID that corresponds to the supplied type or ex...
MSGuidDecl * getGuidDecl() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CaseStmt - Represent a case statement.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
path_iterator path_begin()
CastKind getCastKind() const
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
const FieldDecl * getTargetUnionField() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
unsigned getValue() const
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Complex values, per C99 6.2.5p11.
QualType getElementType() const
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
CompoundLiteralExpr - [C99 6.5.2.5].
const Expr * getInitializer() const
CompoundStmt - This represents a group of statements like { stmt stmt }.
Represents the specialization of a concept - evaluates to a prvalue of type bool.
bool isSatisfied() const
Whether or not the concept with the given arguments was satisfied when the expression was created.
Represents the canonical version of C arrays with a specified constant size.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
APValue getAPValueResult() const
bool hasAPValueResult() const
Represents a concrete matrix type with constant number of rows and columns.
ContinueStmt - This represents a continue.
ConvertVectorExpr - Clang builtin function __builtin_convertvector This AST node provides support for...
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
bool isInvalidDecl() const
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isAnyOperatorNew() const
InitListExpr * getUpdater() const
DoStmt - This represents a 'do/while' stmt.
const Expr * getBase() const
Represents a reference to emded data.
ChildElementIter< false > begin()
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
This represents one expression.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
bool isValueDependent() const
Determines whether the value of this expression depends on.
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const
Determine whether the result of this expression is a temporary object of the given class type.
bool refersToBitField() const
Returns true if this expression is a gl-value that potentially refers to a bit-field.
An expression trait intrinsic.
ExtVectorElementExpr - This represents access to specific elements of a vector, and may occur on the ...
void getEncodedElementAccess(SmallVectorImpl< uint32_t > &Elts) const
getEncodedElementAccess - Encode the elements accessed into an llvm aggregate Constant of ConstantInt...
Represents a member of a struct/union/class.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
llvm::APInt getValue() const
Returns an internal integer representation of the literal.
llvm::APFloat getValue() const
ForStmt - This represents a 'for (init;cond;inc)' stmt.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
DeclStmt * getConditionVariableDeclStmt()
If this ForStmt has a condition variable, return the faux DeclStmt associated with the creation of th...
const Expr * getSubExpr() const
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
bool isUsableAsGlobalAllocationFunctionInConstantEvaluation(UnsignedOrNone *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const
Determines whether this function is one of the replaceable global allocation functions described in i...
bool isDefaulted() const
Whether this function is defaulted.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Declaration of a template function.
FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, void *&InsertPos)
Return the specialization with the provided arguments if it exists, otherwise return the insertion po...
GNUNullExpr - Implements the GNU __null extension, which is a name for a null pointer constant that h...
Represents a C11 generic selection.
Expr * getResultExpr()
Return the result expression of this controlling expression.
IfStmt - This represents an if/then/else.
bool isNonNegatedConsteval() const
bool isNegatedConsteval() const
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
const Expr * getSubExpr() const
Represents an implicitly-generated value initialization of an object of a given type.
Represents a field injected from an anonymous union/struct into the parent scope.
Describes an C or C++ initializer list.
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
ArrayRef< Expr * > inits() const
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
CXXRecordDecl * getLambdaClass() const
Retrieve the class that corresponds to the lambda.
bool isCompatibleWith(ClangABI Version) const
Implicit declaration of a temporary that was materialized by a MaterializeTemporaryExpr and lifetime-...
const Stmt * getNamedLoopOrSwitch() const
If this is a named break/continue, get the loop or switch statement that this targets.
APValue & getAsAPValue() const
Get the value of this MSGuidDecl as an APValue.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
LifetimeExtendedTemporaryDecl * getLifetimeExtendedTemporaryDecl()
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
A pointer to member type per C++ 8.3.3 - Pointers to members.
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a C++ namespace alias.
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp,...
ObjCBoolLiteralExpr - Objective-C Boolean Literal.
ObjCBoxedExpr - used for generalized expression boxing.
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
ObjCEncodeExpr, used for @encode in Objective-C.
QualType getEncodedType() const
SourceLocation getAtLoc() const
bool isExpressibleAsConstantInitializer() const
ObjCStringLiteral, used for Objective-C string literals i.e.
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Expr * getIndexExpr(unsigned Idx)
const OffsetOfNode & getComponent(unsigned Idx) const
unsigned getNumComponents() const
Helper class for OffsetOfExpr.
unsigned getArrayExprIndex() const
For an array element node, returns the index into the array of expressions.
@ Array
An index into an array.
Kind getKind() const
Determine what kind of offsetof node this is.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Expr * getSelectedExpr() const
ParenExpr - This represents a parenthesized expression, e.g.
const Expr * getSubExpr() const
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
[C99 6.4.2.2] - A predefined identifier such as func.
StringLiteral * getFunctionName()
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Expr * getResultExpr()
Return the result-bearing expression, or null if there is none.
ArrayRef< Expr * > semantics()
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
QualType withConst() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
bool isConstant(const ASTContext &Ctx) const
bool isConstQualified() const
Determine whether this type is const-qualified.
Represents a struct/union/class.
Frontend produces RecoveryExprs on semantic errors that prevent creating other well-formed expression...
Base for LValueReferenceType and RValueReferenceType.
C++2a [expr.prim.req]: A requires-expression provides a concise way to express requirements on templa...
bool isSatisfied() const
Whether or not the requires clause is satisfied.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
SourceLocation getLocation() const
std::string ComputeName(ASTContext &Context) const
Scope - A scope is a transient data structure that is used while parsing the program.
ShuffleVectorExpr - clang-specific builtin-in function __builtin_shufflevector.
llvm::APSInt getShuffleMaskIdx(unsigned N) const
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
Represents an expression that computes the length of a parameter pack.
unsigned getPackLength() const
Retrieve the length of the parameter pack.
Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(), __builtin_FUNCTION(),...
APValue EvaluateInContext(const ASTContext &Ctx, const Expr *DefaultExpr) const
Return the result of evaluating this SourceLocExpr in the specified (and possibly null) default argum...
Represents a C++11 static_assert declaration.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
CompoundStmt * getSubStmt()
bool Visit(PTR(Stmt) S, ParamTys... P)
Stmt - This represents one statement.
StmtClass getStmtClass() const
StringLiteral - This represents a string literal expression, e.g.
unsigned getLength() const
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
uint32_t getCodeUnit(size_t i) const
unsigned getCharByteWidth() const
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Expr * getReplacement() const
const SwitchCase * getNextSwitchCase() const
SwitchStmt - This represents a 'switch' stmt.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
SwitchCase * getSwitchCaseList()
DeclStmt * getConditionVariableDeclStmt()
If this SwitchStmt has a condition variable, return the faux DeclStmt associated with the creation of...
Represents the declaration of a struct/union/class/enum.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
A template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
A type trait used in the implementation of various C++11 and Library TR1 trait templates.
bool getBoolValue() const
const APValue & getAPValue() const
bool isStoredAsBoolean() const
The base class of the type hierarchy.
bool isBooleanType() const
bool isLiteralType(const ASTContext &Ctx) const
Return true if this is a literal type (C++11 [basic.types]p10)
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isVoidPointerType() const
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
bool isFunctionPointerType() const
bool isConstantMatrixType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAnyComplexType() const
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isMemberPointerType() const
bool isAtomicType() const
EnumDecl * castAsEnumDecl() const
bool isStdByteType() const
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isPointerOrReferenceType() const
bool isFunctionType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool isSizelessVectorType() const
Returns true for all scalable vector types.
Base class for declarations which introduce a typedef-name.
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
QualType getArgumentType() const
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
bool isArgumentType() const
UnaryExprOrTypeTrait getKind() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Represents C++ using-directive.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isWeak() const
Determine whether this symbol is weakly-imported, or declared with the weak or weak-ref attr.
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
const APValue * evaluateValue() const
Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
WhileStmt - This represents a 'while' stmt.
DeclStmt * getConditionVariableDeclStmt()
If this WhileStmt has a condition variable, return the faux DeclStmt associated with the creation of ...
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
A memory block, either on the stack or in the heap.
void invokeDtor()
Invokes the Destructor.
Compilation context for expressions.
llvm::SmallVector< InitLink > InitStack
bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E)
bool VisitCXXDeleteExpr(const CXXDeleteExpr *E)
bool VisitOffsetOfExpr(const OffsetOfExpr *E)
bool visitContinueStmt(const ContinueStmt *S)
bool VisitCharacterLiteral(const CharacterLiteral *E)
bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init, OptPrimType InitT)
Pointer to the array(not the element!) must be on the stack when calling this.
UnsignedOrNone allocateLocal(DeclTy &&Decl, QualType Ty=QualType(), ScopeKind=ScopeKind::Block)
Allocates a space storing a local given its type.
bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E)
bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E)
bool visitInitializerPop(const Expr *E)
Similar, but will also pop the pointer.
bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E)
bool visitBool(const Expr *E)
Visits an expression and converts it to a boolean.
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E)
PrimType classifyPrim(QualType Ty) const
Classifies a known primitive type.
bool VisitTypeTraitExpr(const TypeTraitExpr *E)
bool VisitLambdaExpr(const LambdaExpr *E)
bool VisitMemberExpr(const MemberExpr *E)
llvm::DenseMap< const OpaqueValueExpr *, unsigned > OpaqueExprs
OpaqueValueExpr to location mapping.
bool VisitBinaryOperator(const BinaryOperator *E)
bool visitAttributedStmt(const AttributedStmt *S)
bool VisitPackIndexingExpr(const PackIndexingExpr *E)
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E)
bool VisitCallExpr(const CallExpr *E)
std::optional< uint64_t > ArrayIndex
Current argument index. Needed to emit ArrayInitIndexExpr.
bool VisitPseudoObjectExpr(const PseudoObjectExpr *E)
bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E)
const Function * getFunction(const FunctionDecl *FD)
Returns a function for the given FunctionDecl.
bool VisitFixedPointBinOp(const BinaryOperator *E)
bool VisitCastExpr(const CastExpr *E)
bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E)
bool VisitFixedPointUnaryOperator(const UnaryOperator *E)
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, bool IsVolatile=false, ScopeKind SC=ScopeKind::Block)
Creates a local primitive value.
bool VisitComplexUnaryOperator(const UnaryOperator *E)
llvm::DenseMap< const SwitchCase *, LabelTy > CaseMap
bool VisitBlockExpr(const BlockExpr *E)
bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E)
bool VisitLogicalBinOp(const BinaryOperator *E)
bool visitCompoundStmt(const CompoundStmt *S)
Context & Ctx
Current compilation context.
bool visitDeclRef(const ValueDecl *D, const Expr *E)
Visit the given decl as if we have a reference to it.
bool visitBreakStmt(const BreakStmt *S)
bool visitExpr(const Expr *E, bool DestroyToplevelScope) override
bool visitForStmt(const ForStmt *S)
bool VisitDeclRefExpr(const DeclRefExpr *E)
bool VisitOpaqueValueExpr(const OpaqueValueExpr *E)
bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E)
bool visitAPValue(const APValue &Val, PrimType ValType, SourceInfo Info)
Visit an APValue.
bool VisitStmtExpr(const StmtExpr *E)
bool VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E)
bool VisitFixedPointLiteral(const FixedPointLiteral *E)
const FunctionDecl * CompilingFunction
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E)
VarCreationState visitVarDecl(const VarDecl *VD, const Expr *Init, bool Toplevel=false)
Creates and initializes a variable from the given decl.
VariableScope< Emitter > * VarScope
Current scope.
bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init, bool ConstantContext) override
Toplevel visitDeclAndReturn().
bool VisitCXXNewExpr(const CXXNewExpr *E)
const ValueDecl * InitializingDecl
bool VisitCompoundAssignOperator(const CompoundAssignOperator *E)
bool visit(const Expr *E) override
Evaluates an expression and places the result on the stack.
bool delegate(const Expr *E)
Just pass evaluation on to E.
bool visitLValueExpr(const Expr *E, bool DestroyToplevelScope) override
bool discard(const Expr *E)
Evaluates an expression for side effects and discards the result.
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
CaseMap CaseLabels
Switch case mapping.
bool visitAPValueInitializer(const APValue &Val, SourceInfo Info, QualType T)
Record * getRecord(QualType Ty)
Returns a record from a record or pointer type.
const RecordType * getRecordTy(QualType Ty)
Returns a record type from a record or pointer type.
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E)
bool visitInitList(ArrayRef< const Expr * > Inits, const Expr *ArrayFiller, const Expr *E)
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E)
bool VisitPredefinedExpr(const PredefinedExpr *E)
bool VisitSourceLocExpr(const SourceLocExpr *E)
bool visitDeclStmt(const DeclStmt *DS, bool EvaluateConditionDecl=false)
bool emitCleanup()
Emits scope cleanup instructions.
bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E)
bool VisitObjCStringLiteral(const ObjCStringLiteral *E)
bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E)
bool visitInitializer(const Expr *E)
Compiles an initializer.
bool visitDtorCall(const VarDecl *VD, const APValue &Value) override
const Expr * SourceLocDefaultExpr
DefaultInit- or DefaultArgExpr, needed for SourceLocExpr.
bool VisitObjCArrayLiteral(const ObjCArrayLiteral *E)
UnsignedOrNone OptLabelTy
bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E)
bool VisitPointerArithBinOp(const BinaryOperator *E)
Perform addition/subtraction of a pointer and an integer or subtraction of two pointers.
bool visitCallArgs(ArrayRef< const Expr * > Args, const FunctionDecl *FuncDecl, bool Activate, bool IsOperatorCall)
bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E)
bool visitDefaultStmt(const DefaultStmt *S)
bool VisitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E)
typename Emitter::LabelTy LabelTy
VarCreationState visitDecl(const VarDecl *VD)
bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E)
bool visitStmt(const Stmt *S)
bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E)
bool VisitVectorUnaryOperator(const UnaryOperator *E)
bool VisitCXXConstructExpr(const CXXConstructExpr *E)
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E)
bool VisitDesignatedInitUpdateExpr(const DesignatedInitUpdateExpr *E)
bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E)
bool VisitRecoveryExpr(const RecoveryExpr *E)
bool VisitRequiresExpr(const RequiresExpr *E)
bool Initializing
Flag inidicating if we're initializing an already created variable.
bool visitReturnStmt(const ReturnStmt *RS)
bool VisitCXXThrowExpr(const CXXThrowExpr *E)
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
bool VisitChooseExpr(const ChooseExpr *E)
bool visitFunc(const FunctionDecl *F) override
bool visitCXXForRangeStmt(const CXXForRangeStmt *S)
bool visitCaseStmt(const CaseStmt *S)
bool VisitComplexBinOp(const BinaryOperator *E)
llvm::DenseMap< const ValueDecl *, Scope::Local > Locals
Variable to storage mapping.
bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E)
bool VisitCXXTypeidExpr(const CXXTypeidExpr *E)
UnsignedOrNone allocateTemporary(const Expr *E)
bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinID)
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E)
bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E)
OptPrimType ReturnType
Type of the expression returned by the function.
bool VisitUnaryOperator(const UnaryOperator *E)
bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E)
OptPrimType classify(const Expr *E) const
llvm::SmallVector< LabelInfo > LabelInfoStack
Stack of label information for loops and switch statements.
bool VisitGenericSelectionExpr(const GenericSelectionExpr *E)
bool visitDoStmt(const DoStmt *S)
bool VisitIntegerLiteral(const IntegerLiteral *E)
bool VisitInitListExpr(const InitListExpr *E)
bool VisitVectorBinOp(const BinaryOperator *E)
bool VisitStringLiteral(const StringLiteral *E)
bool VisitParenExpr(const ParenExpr *E)
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E)
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E)
bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E)
bool DiscardResult
Flag indicating if return value is to be discarded.
bool VisitEmbedExpr(const EmbedExpr *E)
bool VisitConvertVectorExpr(const ConvertVectorExpr *E)
bool VisitCXXThisExpr(const CXXThisExpr *E)
bool VisitConstantExpr(const ConstantExpr *E)
bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E)
bool visitSwitchStmt(const SwitchStmt *S)
bool VisitCXXUuidofExpr(const CXXUuidofExpr *E)
bool VisitExprWithCleanups(const ExprWithCleanups *E)
bool visitAsLValue(const Expr *E)
bool visitWhileStmt(const WhileStmt *S)
bool visitIfStmt(const IfStmt *IS)
bool VisitAddrLabelExpr(const AddrLabelExpr *E)
bool canClassify(const Expr *E) const
bool VisitFloatingLiteral(const FloatingLiteral *E)
Program & P
Program to link to.
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E)
bool VariablesAreConstexprUnknown
bool VisitGNUNullExpr(const GNUNullExpr *E)
bool VisitImaginaryLiteral(const ImaginaryLiteral *E)
bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E)
bool visitCXXTryStmt(const CXXTryStmt *S)
static bool isUnevaluatedBuiltin(unsigned ID)
Unevaluated builtins don't get their arguments put on the stack automatically.
static bool shouldBeGloballyIndexed(const ValueDecl *VD)
Returns whether we should create a global variable for the given ValueDecl.
Scope used to handle temporaries in toplevel variable declarations.
DeclScope(Compiler< Emitter > *Ctx, const ValueDecl *VD)
Wrapper around fixed point types.
static FixedPoint zero(llvm::FixedPointSemantics Sem)
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
bool hasThisPointer() const
bool hasRVO() const
Checks if the first argument is a RVO pointer.
When generating code for e.g.
LocOverrideScope(Compiler< Emitter > *Ctx, SourceInfo NewValue, bool Enabled=true)
Generic scope for local variables.
bool destroyLocals(const Expr *E=nullptr) override
Explicit destruction of local variables.
LocalScope(Compiler< Emitter > *Ctx, ScopeKind Kind=ScopeKind::Block)
Sets the context for break/continue statements.
typename Compiler< Emitter >::LabelTy LabelTy
typename Compiler< Emitter >::OptLabelTy OptLabelTy
typename Compiler< Emitter >::LabelInfo LabelInfo
LoopScope(Compiler< Emitter > *Ctx, const Stmt *Name, LabelTy BreakLabel, LabelTy ContinueLabel)
PrimType value_or(PrimType PT) const
Scope used to handle initialization methods.
OptionScope(Compiler< Emitter > *Ctx, bool NewDiscardResult, bool NewInitializing, bool NewToLValue)
Root constructor, compiling or discarding primitives.
Context to manage declaration lifetimes.
Structure/Class descriptor.
bool isUnion() const
Checks if the record is a union.
const Field * getField(unsigned I) const
const Base * getBase(unsigned I) const
bool hasTrivialDtor() const
Returns true for anonymous unions and records with no destructor or for those with a trivial destruct...
Describes the statement/declaration an opcode was generated from.
const Expr * asExpr() const
typename Compiler< Emitter >::LabelTy LabelTy
typename Compiler< Emitter >::OptLabelTy OptLabelTy
typename Compiler< Emitter >::LabelInfo LabelInfo
typename Compiler< Emitter >::CaseMap CaseMap
SwitchScope(Compiler< Emitter > *Ctx, const Stmt *Name, CaseMap &&CaseLabels, LabelTy BreakLabel, OptLabelTy DefaultLabel)
Scope chain managing the variable lifetimes.
Compiler< Emitter > * Ctx
Compiler instance.
virtual void addLocal(Scope::Local Local)
VariableScope * getParent() const
bool Sub(InterpState &S, CodePtr OpPC)
bool LT(InterpState &S, CodePtr OpPC)
static llvm::RoundingMode getRoundingMode(FPOptions FPO)
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
constexpr bool isSignedType(PrimType T)
bool Div(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
static bool Activate(InterpState &S, CodePtr OpPC)
constexpr bool isPtrType(PrimType T)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool InitScope(InterpState &S, CodePtr OpPC, uint32_t I)
constexpr bool isIntegerOrBoolType(PrimType T)
static void discard(InterpStack &Stk, PrimType T)
bool LE(InterpState &S, CodePtr OpPC)
PrimType
Enumeration of the primitive types of the VM.
static std::optional< bool > getBoolValue(const Expr *E)
bool Init(InterpState &S, CodePtr OpPC)
bool Mul(InterpState &S, CodePtr OpPC)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
bool Add(InterpState &S, CodePtr OpPC)
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, ArrayRef< const Expr * > Args)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
bool hasSpecificAttr(const Container &container)
@ Success
Annotation was successful.
UnaryExprOrTypeTrait
Names for the "expression or type" traits.
@ SD_Static
Static storage duration.
@ SD_FullExpression
Full-expression storage duration (for temporaries).
@ Result
The result type of a method or function.
OptionalUnsigned< unsigned > UnsignedOrNone
U cast(CodeGen::Address addr)
int const char * function
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
EvalResult is a struct with detailed info about an evaluated expression.
Describes a memory block created by an allocation site.
unsigned getNumElems() const
Returns the number of elements stored in the block.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
QualType getElemQualType() const
bool hasTrivialDtor() const
Whether variables of this descriptor need their destructor called or not.
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
const Descriptor *const ElemDesc
Descriptor of the array element.
static constexpr MetadataSize InlineDescMD
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
PrimType getPrimType() const
bool isRecord() const
Checks if the descriptor is of a record.
const Record *const ElemRecord
Pointer to the record, if block contains records.
bool isArray() const
Checks if the descriptor is of an array.
Descriptor used for global variables.
GlobalInitState InitState
static InitLink InitList()
static InitLink Elem(unsigned Index)
bool emit(Compiler< Emitter > *Ctx, const Expr *E) const
static InitLink Field(unsigned Offset)
static InitLink Decl(const ValueDecl *D)
static InitLink Temp(unsigned Offset)
Information about a local's storage.
State encapsulating if a the variable creation has been successful, unsuccessful, or no variable has ...
static VarCreationState NotCreated()