48 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
49 OldInitializing(Ctx->Initializing) {
55 Ctx->DiscardResult = OldDiscardResult;
56 Ctx->Initializing = OldInitializing;
63 bool OldDiscardResult;
70template <
class Emitter>
75 case CK_LValueToRValue: {
77 SubExpr, DerefKind::Read,
84 if (!this->emitLoadPop(T, CE))
86 return DiscardResult ? this->emitPop(T, CE) :
true;
90 case CK_UncheckedDerivedToBase:
91 case CK_DerivedToBase: {
92 if (!this->visit(SubExpr))
95 unsigned DerivedOffset = collectBaseOffset(getRecordTy(CE->
getType()),
96 getRecordTy(SubExpr->getType()));
98 return this->emitGetPtrBasePop(DerivedOffset, CE);
101 case CK_BaseToDerived: {
102 if (!this->visit(SubExpr))
105 unsigned DerivedOffset = collectBaseOffset(getRecordTy(SubExpr->getType()),
108 return this->emitGetPtrDerivedPop(DerivedOffset, CE);
111 case CK_FloatingCast: {
112 if (!this->visit(SubExpr))
114 const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->
getType());
115 return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE);
118 case CK_IntegralToFloating: {
119 std::optional<PrimType> FromT = classify(SubExpr->getType());
123 if (!this->visit(SubExpr))
126 const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->
getType());
127 llvm::RoundingMode RM = getRoundingMode(CE);
128 return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE);
131 case CK_FloatingToBoolean:
132 case CK_FloatingToIntegral: {
133 std::optional<PrimType> ToT = classify(CE->
getType());
138 if (!this->visit(SubExpr))
141 return this->emitCastFloatingIntegral(*ToT, CE);
144 case CK_NullToPointer:
147 return this->emitNull(classifyPrim(CE->
getType()), CE);
149 case CK_PointerToIntegral: {
151 if (!this->visit(SubExpr))
155 return this->emitCastPointerIntegral(T, CE);
158 case CK_ArrayToPointerDecay:
159 case CK_AtomicToNonAtomic:
160 case CK_ConstructorConversion:
161 case CK_FunctionToPointerDecay:
162 case CK_NonAtomicToAtomic:
164 case CK_UserDefinedConversion:
166 return this->delegate(SubExpr);
168 case CK_IntegralToBoolean:
169 case CK_IntegralCast: {
171 return this->discard(SubExpr);
172 std::optional<PrimType> FromT = classify(SubExpr->getType());
173 std::optional<PrimType> ToT = classify(CE->
getType());
177 if (!this->visit(SubExpr))
183 return this->emitCast(*FromT, *ToT, CE);
186 case CK_PointerToBoolean: {
187 PrimType PtrT = classifyPrim(SubExpr->getType());
190 if (!this->visit(SubExpr))
193 if (!this->emitNull(PtrT, CE))
196 return this->emitNE(PtrT, CE);
200 return discard(SubExpr);
203 assert(
false &&
"Cast not implemented");
205 llvm_unreachable(
"Unhandled clang::CastKind enum");
208template <
class Emitter>
213 return this->emitConst(
LE->getValue(),
LE);
216template <
class Emitter>
221 return this->emitConstFloat(E->
getValue(), E);
224template <
class Emitter>
229template <
class Emitter>
233 return this->VisitLogicalBinOp(BO);
239 return this->visit(RHS);
242 std::optional<PrimType>
LT = classify(LHS->
getType());
243 std::optional<PrimType> RT = classify(RHS->
getType());
244 std::optional<PrimType> T = classify(BO->
getType());
248 if (!this->discard(LHS))
251 return this->discard(RHS);
253 return this->delegate(RHS);
256 if (!
LT || !RT || !T)
257 return this->bail(BO);
262 return this->VisitPointerArithBinOp(BO);
265 if (!visit(LHS) || !visit(RHS))
270 auto MaybeCastToBool = [
this, T, BO](
bool Result) {
274 return this->emitPop(*T, BO);
276 return this->emitCast(
PT_Bool, *T, BO);
280 auto Discard = [
this, T, BO](
bool Result) {
283 return DiscardResult ? this->emitPop(*T, BO) :
true;
288 return MaybeCastToBool(this->emitEQ(*
LT, BO));
290 return MaybeCastToBool(this->emitNE(*
LT, BO));
292 return MaybeCastToBool(this->emitLT(*
LT, BO));
294 return MaybeCastToBool(this->emitLE(*
LT, BO));
296 return MaybeCastToBool(this->emitGT(*
LT, BO));
298 return MaybeCastToBool(this->emitGE(*
LT, BO));
301 return Discard(this->emitSubf(getRoundingMode(BO), BO));
302 return Discard(this->emitSub(*T, BO));
305 return Discard(this->emitAddf(getRoundingMode(BO), BO));
306 return Discard(this->emitAdd(*T, BO));
309 return Discard(this->emitMulf(getRoundingMode(BO), BO));
310 return Discard(this->emitMul(*T, BO));
312 return Discard(this->emitRem(*T, BO));
315 return Discard(this->emitDivf(getRoundingMode(BO), BO));
316 return Discard(this->emitDiv(*T, BO));
319 return this->emitStorePop(*T, BO);
320 return this->emitStore(*T, BO);
322 return Discard(this->emitBitAnd(*T, BO));
324 return Discard(this->emitBitOr(*T, BO));
326 return Discard(this->emitShl(*
LT, *RT, BO));
328 return Discard(this->emitShr(*
LT, *RT, BO));
330 return Discard(this->emitBitXor(*T, BO));
333 llvm_unreachable(
"Already handled earlier");
335 return this->bail(BO);
338 llvm_unreachable(
"Unhandled binary op");
343template <
class Emitter>
349 if ((Op != BO_Add && Op != BO_Sub) ||
353 std::optional<PrimType>
LT = classify(LHS);
354 std::optional<PrimType> RT = classify(RHS);
364 if (!visit(RHS) || !visit(LHS))
367 return this->emitSubPtr(classifyPrim(E->
getType()), E);
372 if (!visit(RHS) || !visit(LHS))
376 if (!visit(LHS) || !visit(RHS))
384 return this->emitAddOffset(OffsetType, E);
385 else if (Op == BO_Sub)
386 return this->emitSubOffset(OffsetType, E);
388 return this->bail(E);
391template <
class Emitter>
397 std::optional<PrimType> T = classify(E->
getType());
401 LabelTy LabelTrue = this->getLabel();
402 LabelTy LabelEnd = this->getLabel();
404 if (!this->visitBool(LHS))
406 if (!this->jumpTrue(LabelTrue))
409 if (!this->visitBool(RHS))
411 if (!this->jump(LabelEnd))
414 this->emitLabel(LabelTrue);
415 this->emitConstBool(
true, E);
416 this->fallthrough(LabelEnd);
417 this->emitLabel(LabelEnd);
420 assert(Op == BO_LAnd);
423 LabelTy LabelFalse = this->getLabel();
424 LabelTy LabelEnd = this->getLabel();
426 if (!this->visitBool(LHS))
428 if (!this->jumpFalse(LabelFalse))
431 if (!this->visitBool(RHS))
433 if (!this->jump(LabelEnd))
436 this->emitLabel(LabelFalse);
437 this->emitConstBool(
false, E);
438 this->fallthrough(LabelEnd);
439 this->emitLabel(LabelEnd);
443 return this->emitPopBool(E);
448 return this->emitCast(
PT_Bool, *T, E);
452template <
class Emitter>
457 return this->visitZeroInitializer(QT, E);
465 const auto *CAT = cast<ConstantArrayType>(AT);
466 size_t NumElems = CAT->getSize().getZExtValue();
468 if (std::optional<PrimType> ElemT = classify(CAT->getElementType())) {
472 for (
size_t I = 0; I != NumElems; ++I) {
473 if (!this->visitZeroInitializer(CAT->getElementType(), E))
475 if (!this->emitInitElem(*ElemT, I, E))
479 assert(
false &&
"default initializer for non-primitive type");
488template <
class Emitter>
495 return this->discard(
Base) && this->discard(Index);
499 if (!this->visit(
Base))
502 if (!this->visit(Index))
505 PrimType IndexT = classifyPrim(Index->getType());
506 return this->emitArrayElemPtrPop(IndexT, E);
509template <
class Emitter>
515 unsigned InitIndex = 0;
516 for (
const Expr *Init : Inits) {
517 if (!this->emitDupPtr(E))
520 if (std::optional<PrimType> T = classify(Init)) {
522 if (!this->visit(Init))
524 if (!this->emitInitField(*T, FieldToInit->
Offset, E))
526 if (!this->emitPopPtr(E))
532 if (!this->emitGetPtrBasePop(B->Offset, Init))
535 if (!this->visitInitializer(Init))
538 if (!this->emitPopPtr(E))
546 if (!this->emitGetPtrField(FieldToInit->
Offset, Init))
549 if (!this->visitInitializer(Init))
552 if (!this->emitPopPtr(E))
561template <
class Emitter>
566 if (!this->discard(Init))
573 if (std::optional<PrimType> T = classify(E->
getType())) {
574 assert(!DiscardResult);
576 return this->visitZeroInitializer(E->
getType(), E);
578 return this->delegate(E->
inits()[0]);
583 return this->visitInitList(E->
inits(), E);
587 unsigned ElementIndex = 0;
589 if (std::optional<PrimType> T = classify(Init->getType())) {
591 if (!this->visit(Init))
593 if (!this->emitInitElem(*T, ElementIndex, Init))
598 if (!this->emitConstUint32(ElementIndex, Init))
600 if (!this->emitArrayElemPtrUint32(Init))
602 if (!this->visitInitializer(Init))
604 if (!this->emitPopPtr(Init))
616template <
class Emitter>
621 if (!this->discard(Init))
631template <
class Emitter>
637template <
class Emitter>
642 std::optional<PrimType> T = classify(E->
getType());
652 bool AlignOfReturnsPreferred =
653 ASTCtx.
getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
664 if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
670template <
class Emitter>
676 if (Kind == UETT_SizeOf) {
691 return this->emitConst(Size.getQuantity(), E);
694 if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
711 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
714 else if (
const auto *ME = dyn_cast<MemberExpr>(Arg))
724 return this->emitConst(Size.getQuantity(), E);
730template <
class Emitter>
736 return this->discard(
Base);
738 if (!this->visit(
Base))
744 if (
const auto *FD = dyn_cast<FieldDecl>(
Member)) {
746 const Record *R = getRecord(RD);
751 return this->emitGetPtrField(F->
Offset, E);
757template <
class Emitter>
764 return this->emitConst(*ArrayIndex, E);
767template <
class Emitter>
770 assert(Initializing);
771 assert(!DiscardResult);
777 std::optional<PrimType> ElemT = classify(SubExpr->
getType());
782 for (
size_t I = 0; I != Size; ++I) {
786 if (!this->visit(SubExpr))
788 if (!this->emitInitElem(*ElemT, I, E))
792 if (!this->emitConstUint64(I, SubExpr))
794 if (!this->emitArrayElemPtrUint64(SubExpr))
796 if (!visitInitializer(SubExpr))
798 if (!this->emitPopPtr(E))
805template <
class Emitter>
812template <
class Emitter>
819 LabelTy LabelEnd = this->getLabel();
820 LabelTy LabelFalse = this->getLabel();
825 if (!this->jumpFalse(LabelFalse))
828 if (!this->delegate(TrueExpr))
830 if (!this->jump(LabelEnd))
833 this->emitLabel(LabelFalse);
835 if (!this->delegate(FalseExpr))
838 this->fallthrough(LabelEnd);
839 this->emitLabel(LabelEnd);
844template <
class Emitter>
850 unsigned StringIndex =
P.createGlobalString(E);
851 return this->emitGetPtrGlobal(StringIndex, E);
856 Ctx.getASTContext().getAsConstantArrayType(E->
getType());
857 assert(CAT &&
"a string literal that's not a constant array?");
865 for (
unsigned I = 0; I != N; ++I) {
868 if (CharWidth == 1) {
869 this->emitConstSint8(CodeUnit, E);
870 this->emitInitElemSint8(I, E);
871 }
else if (CharWidth == 2) {
872 this->emitConstUint16(CodeUnit, E);
873 this->emitInitElemUint16(I, E);
874 }
else if (CharWidth == 4) {
875 this->emitConstUint32(CodeUnit, E);
876 this->emitInitElemUint32(I, E);
878 llvm_unreachable(
"unsupported character width");
884template <
class Emitter>
889 return this->emitConst(E->
getValue(), E);
892template <
class Emitter>
901 std::optional<PrimType>
LT = classify(LHSComputationType);
902 std::optional<PrimType> RT = classify(ResultType);
909 PrimType LHST = classifyPrim(LHSType);
917 unsigned TempOffset = this->allocateLocalPrimitive(E, *RT,
true);
918 if (!this->emitSetLocal(*RT, TempOffset, E))
924 if (!this->emitLoad(LHST, E))
928 if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType),
929 LHSComputationType, E))
933 if (!this->emitGetLocal(*RT, TempOffset, E))
936 llvm::RoundingMode RM = getRoundingMode(E);
939 if (!this->emitAddf(RM, E))
943 if (!this->emitSubf(RM, E))
947 if (!this->emitMulf(RM, E))
951 if (!this->emitDivf(RM, E))
958 if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->
getType(), E))
962 return this->emitStorePop(LHST, E);
963 return this->emitStore(LHST, E);
966template <
class Emitter>
972 std::optional<PrimType>
LT = classify(LHS->
getType());
973 std::optional<PrimType> RT = classify(RHS->
getType());
975 if (Op != BO_AddAssign && Op != BO_SubAssign)
985 if (!this->emitLoadPtr(LHS))
991 if (Op == BO_AddAssign)
992 this->emitAddOffset(*RT, E);
994 this->emitSubOffset(*RT, E);
997 return this->emitStorePopPtr(E);
998 return this->emitStorePtr(E);
1001template <
class Emitter>
1007 std::optional<PrimType> LHSComputationT =
1009 std::optional<PrimType>
LT = classify(LHS->
getType());
1011 std::optional<PrimType> ResultT = classify(E->
getType());
1013 if (!
LT || !RT || !ResultT || !LHSComputationT)
1020 return VisitFloatCompoundAssignOperator(E);
1023 return VisitPointerCompoundAssignOperator(E);
1036 unsigned TempOffset = this->allocateLocalPrimitive(E, *RT,
true);
1038 if (!this->emitSetLocal(*RT, TempOffset, E))
1045 if (!this->emitLoad(*
LT, E))
1047 if (*
LT != *LHSComputationT) {
1048 if (!this->emitCast(*
LT, *LHSComputationT, E))
1053 if (!this->emitGetLocal(*RT, TempOffset, E))
1059 if (!this->emitAdd(*LHSComputationT, E))
1063 if (!this->emitSub(*LHSComputationT, E))
1067 if (!this->emitMul(*LHSComputationT, E))
1071 if (!this->emitDiv(*LHSComputationT, E))
1075 if (!this->emitRem(*LHSComputationT, E))
1079 if (!this->emitShl(*LHSComputationT, *RT, E))
1083 if (!this->emitShr(*LHSComputationT, *RT, E))
1087 if (!this->emitBitAnd(*LHSComputationT, E))
1091 if (!this->emitBitXor(*LHSComputationT, E))
1095 if (!this->emitBitOr(*LHSComputationT, E))
1099 llvm_unreachable(
"Unimplemented compound assign operator");
1103 if (*ResultT != *LHSComputationT) {
1104 if (!this->emitCast(*LHSComputationT, *ResultT, E))
1110 return this->emitStorePop(*ResultT, E);
1111 return this->emitStore(*ResultT, E);
1114template <
class Emitter>
1119 assert(E->
getNumObjects() == 0 &&
"TODO: Implement cleanups");
1121 return this->delegate(SubExpr);
1124template <
class Emitter>
1131 return this->visitInitializer(SubExpr);
1136 return this->discard(SubExpr);
1138 std::optional<PrimType> SubExprT = classify(SubExpr);
1140 std::optional<unsigned> GlobalIndex =
P.createGlobal(E);
1149 if (!this->visit(SubExpr))
1151 if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
1153 return this->emitGetPtrGlobal(*GlobalIndex, E);
1157 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
1159 if (!this->visitInitializer(SubExpr))
1161 return this->emitInitGlobalTempComp(TempDecl, E);
1166 if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive(
1167 SubExpr, *SubExprT,
true,
true)) {
1168 if (!this->visit(SubExpr))
1170 this->emitSetLocal(*SubExprT, *LocalIndex, E);
1171 return this->emitGetPtrLocal(*LocalIndex, E);
1174 if (std::optional<unsigned> LocalIndex =
1175 allocateLocal(SubExpr,
true)) {
1176 if (!this->emitGetPtrLocal(*LocalIndex, E))
1178 return this->visitInitializer(SubExpr);
1184template <
class Emitter>
1188 return this->visitInitializer(E->
getSubExpr());
1192template <
class Emitter>
1198 return this->visitInitializer(Init);
1201 std::optional<PrimType> T = classify(E->
getType());
1203 if (std::optional<unsigned> GlobalIndex =
P.createGlobal(E)) {
1205 return this->visit(Init);
1206 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
1208 return this->visitInitializer(Init);
1215 return this->delegate(Init);
1217 if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) {
1218 if (!this->emitGetPtrLocal(*LocalIndex, E))
1220 if (!this->visitInitializer(Init))
1223 return this->emitPopPtr(E);
1231template <
class Emitter>
1235 return this->emitConstBool(E->
getValue(), E);
1238template <
class Emitter>
1240 assert(Initializing);
1247 const Expr *Init = *CaptureInitIt;
1250 if (std::optional<PrimType> T = classify(Init)) {
1251 if (!this->visit(Init))
1254 if (!this->emitSetField(*T, F.Offset, E))
1257 if (!this->emitDupPtr(E))
1260 if (!this->emitGetPtrField(F.Offset, E))
1263 if (!this->visitInitializer(Init))
1266 if (!this->emitPopPtr(E))
1274template <
class Emitter>
1279 assert(!Initializing);
1283template <
class Emitter>
1288 return this->emitInvalid(E);
1291template <
class Emitter>
1297 return this->emitInvalidCast(CastKind::Reinterpret, E);
1300template <
class Emitter>
1306 return this->emitConstBool(E->
getValue(), E);
1309template <
class Emitter>
1313 assert(!classify(T));
1321 return this->visitZeroRecordInitializer(R, E);
1324 const Function *Func = getFunction(Ctor);
1334 if (DiscardResult) {
1335 assert(!Initializing);
1336 std::optional<unsigned> LocalIndex =
1337 allocateLocal(E,
true);
1342 if (!this->emitGetPtrLocal(*LocalIndex, E))
1348 if (!this->emitDupPtr(E))
1352 for (
const auto *Arg : E->
arguments()) {
1353 if (!this->visit(Arg))
1357 if (!this->emitCall(Func, E))
1361 if (DiscardResult) {
1362 if (!this->emitPopPtr(E))
1370 Ctx.getASTContext().getAsConstantArrayType(E->
getType());
1372 size_t NumElems = CAT->
getSize().getZExtValue();
1379 for (
size_t I = 0; I != NumElems; ++I) {
1380 if (!this->emitConstUint64(I, E))
1382 if (!this->emitArrayElemPtrUint64(E))
1386 for (
const auto *Arg : E->
arguments()) {
1387 if (!this->visit(Arg))
1391 if (!this->emitCall(Func, E))
1400template <
class Emitter>
1410 assert(Val.
isInt());
1412 return this->emitConst(I, E);
1419 if (
const Expr *LValueExpr =
Base.dyn_cast<
const Expr *>())
1420 return this->visit(LValueExpr);
1429 auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl);
1431 std::optional<unsigned> GlobalIndex =
P.getOrCreateGlobal(UGCD);
1435 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
1439 const APValue &
V = UGCD->getValue();
1440 for (
unsigned I = 0, N = R->
getNumFields(); I != N; ++I) {
1442 const APValue &FieldValue =
V.getStructField(I);
1446 if (!this->visitAPValue(FieldValue, FieldT, E))
1448 if (!this->emitInitField(FieldT, F->
Offset, E))
1456template <
class Emitter>
1462 for (
unsigned I = 0; I != N; ++I) {
1468 if (DiscardResult) {
1469 if (!this->discard(ArrayIndexExpr))
1474 if (!this->visit(ArrayIndexExpr))
1478 if (!this->emitCast(IndexT,
PT_Sint64, E))
1488 return this->emitOffsetOf(T, E, E);
1497 return this->Visit(E);
1500template <
class Emitter>
1508 return this->Visit(E);
1516 return this->discard(E);
1520 std::optional<unsigned> LocalIndex = allocateLocal(E,
true);
1524 if (!this->emitGetPtrLocal(*LocalIndex, E))
1526 return this->visitInitializer(E);
1533 return this->Visit(E);
1536template <
class Emitter>
1538 assert(!classify(E->
getType()));
1545 return this->Visit(E);
1548template <
class Emitter>
1550 std::optional<PrimType> T = classify(E->
getType());
1554 if (!this->visit(E))
1562 if (!this->emitNull(*T, E))
1564 return this->emitNE(*T, E);
1569 return this->emitCastFloatingIntegralBool(E);
1572 return this->emitCast(*T,
PT_Bool, E);
1575template <
class Emitter>
1584 return this->emitZeroBool(E);
1586 return this->emitZeroSint8(E);
1588 return this->emitZeroUint8(E);
1590 return this->emitZeroSint16(E);
1592 return this->emitZeroUint16(E);
1594 return this->emitZeroSint32(E);
1596 return this->emitZeroUint32(E);
1598 return this->emitZeroSint64(E);
1600 return this->emitZeroUint64(E);
1602 return this->emitNullPtr(E);
1604 return this->emitNullFnPtr(E);
1606 return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
1609 llvm_unreachable(
"unknown primitive type");
1612template <
class Emitter>
1623 if (!this->visitZeroInitializer(QT, E))
1625 if (!this->emitInitField(T,
Field.Offset, E))
1631 if (!this->emitDupPtr(E))
1633 if (!this->emitGetPtrField(
Field.Offset, E))
1639 for (uint32_t I = 0, N = D->
getNumElems(); I != N; ++I) {
1640 if (!this->visitZeroInitializer(ET, E))
1642 if (!this->emitInitElem(T, I, E))
1648 for (uint32_t I = 0, N = D->
getNumElems(); I != N; ++I) {
1649 if (!this->emitConstUint32(I, E))
1651 if (!this->emitArrayElemPtr(
PT_Uint32, E))
1653 if (!this->visitZeroRecordInitializer(ElemRecord, E))
1655 if (!this->emitPopPtr(E))
1659 if (!this->visitZeroRecordInitializer(D->
ElemRecord, E))
1665 if (!this->emitPopPtr(E))
1670 if (!this->emitGetPtrBase(B.Offset, E))
1672 if (!this->visitZeroRecordInitializer(B.R, E))
1674 if (!this->emitPopPtr(E))
1683template <
class Emitter>
1685 const Expr *LV, DerefKind AK, llvm::function_ref<
bool(
PrimType)> Direct,
1686 llvm::function_ref<
bool(
PrimType)> Indirect) {
1687 if (std::optional<PrimType> T = classify(LV->
getType())) {
1690 if (
const auto *DE = dyn_cast<DeclRefExpr>(LV)) {
1691 if (!DE->getDecl()->getType()->isReferenceType()) {
1692 if (
const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
1693 return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
1694 if (
const auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
1695 return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
1702 return Indirect(*T);
1708template <
class Emitter>
1711 llvm::function_ref<
bool(
PrimType)> Direct,
1712 llvm::function_ref<
bool(
PrimType)> Indirect) {
1713 auto It = this->Params.find(PD);
1714 if (It != this->Params.end()) {
1715 unsigned Idx = It->second.Offset;
1717 case DerefKind::Read:
1718 return DiscardResult ?
true : this->emitGetParam(T, Idx, LV);
1720 case DerefKind::Write:
1723 if (!this->emitSetParam(T, Idx, LV))
1725 return DiscardResult ?
true : this->emitGetPtrParam(Idx, LV);
1727 case DerefKind::ReadWrite:
1728 if (!this->emitGetParam(T, Idx, LV))
1732 if (!this->emitSetParam(T, Idx, LV))
1734 return DiscardResult ?
true : this->emitGetPtrParam(Idx, LV);
1740 if (!DiscardResult && T ==
PT_Ptr && AK == DerefKind::Read) {
1741 if (
auto Idx =
P.getOrCreateDummy(PD))
1742 return this->emitGetPtrGlobal(*Idx, PD);
1747 return visit(LV) && Indirect(T);
1750template <
class Emitter>
1753 llvm::function_ref<
bool(
PrimType)> Direct,
1754 llvm::function_ref<
bool(
PrimType)> Indirect) {
1755 auto It = Locals.find(VD);
1756 if (It != Locals.end()) {
1757 const auto &L = It->second;
1759 case DerefKind::Read:
1760 if (!this->emitGetLocal(T, L.Offset, LV))
1762 return DiscardResult ? this->emitPop(T, LV) :
true;
1764 case DerefKind::Write:
1767 if (!this->emitSetLocal(T, L.Offset, LV))
1769 return DiscardResult ?
true : this->emitGetPtrLocal(L.Offset, LV);
1771 case DerefKind::ReadWrite:
1772 if (!this->emitGetLocal(T, L.Offset, LV))
1776 if (!this->emitSetLocal(T, L.Offset, LV))
1778 return DiscardResult ?
true : this->emitGetPtrLocal(L.Offset, LV);
1780 }
else if (
auto Idx =
P.getGlobal(VD)) {
1782 case DerefKind::Read:
1783 if (!this->emitGetGlobal(T, *Idx, LV))
1785 return DiscardResult ? this->emitPop(T, LV) :
true;
1787 case DerefKind::Write:
1790 if (!this->emitSetGlobal(T, *Idx, LV))
1792 return DiscardResult ?
true : this->emitGetPtrGlobal(*Idx, LV);
1794 case DerefKind::ReadWrite:
1795 if (!this->emitGetGlobal(T, *Idx, LV))
1799 if (!this->emitSetGlobal(T, *Idx, LV))
1801 return DiscardResult ?
true : this->emitGetPtrGlobal(*Idx, LV);
1808 if (!DiscardResult && AK == DerefKind::Read) {
1812 return this->visit(VD->
getInit());
1817 return visit(LV) && Indirect(T);
1820template <
class Emitter>
1821template <
typename T>
1825 return this->emitConstSint8(
Value, E);
1827 return this->emitConstUint8(
Value, E);
1829 return this->emitConstSint16(
Value, E);
1831 return this->emitConstUint16(
Value, E);
1833 return this->emitConstSint32(
Value, E);
1835 return this->emitConstUint32(
Value, E);
1837 return this->emitConstSint64(
Value, E);
1839 return this->emitConstUint64(
Value, E);
1841 return this->emitConstBool(
Value, E);
1845 llvm_unreachable(
"Invalid integral type");
1848 llvm_unreachable(
"unknown primitive type");
1851template <
class Emitter>
1852template <
typename T>
1854 return this->emitConst(
Value, classifyPrim(E->
getType()), E);
1857template <
class Emitter>
1860 if (
Value.isSigned())
1861 return this->emitConst(
Value.getSExtValue(), Ty, E);
1862 return this->emitConst(
Value.getZExtValue(), Ty, E);
1865template <
class Emitter>
1867 return this->emitConst(
Value, classifyPrim(E->
getType()), E);
1870template <
class Emitter>
1876 if (
const auto *VD =
1877 dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>())) {
1878 assert(!
P.getGlobal(VD));
1879 assert(!Locals.contains(VD));
1886 Src.is<
const Expr *>());
1888 if (
auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>()))
1889 Locals.insert({VD, Local});
1890 VarScope->add(Local, IsExtended);
1891 return Local.Offset;
1894template <
class Emitter>
1895std::optional<unsigned>
1898 if ([[maybe_unused]]
const auto *VD =
1899 dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>())) {
1900 assert(!
P.getGlobal(VD));
1901 assert(!Locals.contains(VD));
1906 const Expr *Init =
nullptr;
1907 bool IsTemporary =
false;
1908 if (
auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>())) {
1912 if (
const auto *VarD = dyn_cast<VarDecl>(VD))
1913 Init = VarD->getInit();
1915 if (
auto *E = Src.dyn_cast<
const Expr *>()) {
1922 IsTemporary,
false, Init);
1928 Locals.insert({Key, Local});
1929 VarScope->add(Local, IsExtended);
1930 return Local.Offset;
1933template <
class Emitter>
1935 if (
const PointerType *PT = dyn_cast<PointerType>(Ty))
1940template <
class Emitter>
1942 if (
const auto *RecordTy = getRecordTy(Ty))
1943 return getRecord(RecordTy->getDecl());
1947template <
class Emitter>
1949 return P.getOrCreateRecord(RD);
1952template <
class Emitter>
1954 return Ctx.getOrCreateFunction(FD);
1957template <
class Emitter>
1964 return this->emitRetVoid(E);
1966 if (std::optional<PrimType> T = classify(E))
1967 return this->emitRet(*T, E);
1968 return this->emitRetValue(E);
1974template <
class Emitter>
1976 assert(!VD->
isInvalidDecl() &&
"Trying to constant evaluate an invalid decl");
1979 if (!this->visitVarDecl(VD))
1984 auto GlobalIndex =
P.getGlobal(VD);
1985 assert(GlobalIndex);
1986 if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
1989 auto Local = Locals.find(VD);
1990 assert(Local != Locals.end());
1991 if (!this->emitGetPtrLocal(Local->second.Offset, VD))
1996 if (std::optional<PrimType> VarT = classify(VD->
getType())) {
1997 if (!this->emitLoadPop(*VarT, VD))
2000 return this->emitRet(*VarT, VD);
2003 return this->emitRetValue(VD);
2006template <
class Emitter>
2013 std::optional<PrimType> VarT = classify(VD->
getType());
2017 if (
P.getGlobal(VD))
2020 std::optional<unsigned> GlobalIndex =
P.createGlobal(VD, Init);
2023 return this->bail(VD);
2030 if (!this->visit(Init))
2032 return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
2034 return this->visitGlobalInitializer(Init, *GlobalIndex);
2039 unsigned Offset = this->allocateLocalPrimitive(
2044 if (!this->visit(Init))
2047 return this->emitSetLocal(*VarT, Offset, VD);
2050 if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
2052 return this->visitLocalInitializer(Init, *Offset);
2061template <
class Emitter>
2064 assert(!DiscardResult);
2066 return this->emitConst(Val.
getInt(), ValType, E);
2070 if (
const Expr *BaseExpr =
Base.dyn_cast<
const Expr *>())
2071 return this->visit(BaseExpr);
2077template <
class Emitter>
2084 for (
const auto *Arg : E->
arguments()) {
2085 if (!this->visit(Arg))
2089 if (!this->emitCallBI(Func, E, E))
2093 if (DiscardResult && !ReturnType->
isVoidType()) {
2094 PrimType T = classifyPrim(ReturnType);
2095 return this->emitPop(T, E);
2101template <
class Emitter>
2104 return VisitBuiltinCallExpr(E);
2107 std::optional<PrimType> T = classify(ReturnType);
2108 bool HasRVO = !ReturnType->
isVoidType() && !T;
2111 if (DiscardResult) {
2115 if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {
2116 if (!this->emitGetPtrLocal(*LocalIndex, E))
2120 assert(Initializing);
2121 if (!isa<CXXMemberCallExpr>(E)) {
2122 if (!this->emitDupPtr(E))
2129 for (
const auto *Arg : E->
arguments()) {
2130 if (!this->visit(Arg))
2135 const Function *Func = getFunction(FuncDecl);
2146 assert(HasRVO == Func->
hasRVO());
2148 bool HasQualifier =
false;
2149 if (
const auto *ME = dyn_cast<MemberExpr>(E->
getCallee()))
2150 HasQualifier = ME->hasQualifier();
2152 bool IsVirtual =
false;
2153 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))
2154 IsVirtual = MD->isVirtual();
2159 if (IsVirtual && !HasQualifier) {
2160 if (!this->emitCallVirt(Func, E))
2163 if (!this->emitCall(Func, E))
2173 if (!this->emitCallPtr(E))
2178 if (DiscardResult && !ReturnType->
isVoidType() && T)
2179 return this->emitPop(*T, E);
2184template <
class Emitter>
2190 if (!this->emitDupPtr(E))
2197 return VisitCallExpr(E);
2200template <
class Emitter>
2205 return this->visitInitializer(E->
getExpr());
2207 assert(classify(E->
getType()));
2208 return this->visit(E->
getExpr());
2211template <
class Emitter>
2217 if (std::optional<PrimType> T = classify(E->
getExpr()))
2218 return this->visit(SubExpr);
2220 assert(Initializing);
2221 return this->visitInitializer(SubExpr);
2224template <
class Emitter>
2230 return this->emitConstBool(E->
getValue(), E);
2233template <
class Emitter>
2239 return this->emitNullPtr(E);
2242template <
class Emitter>
2250 return this->emitZero(T, E);
2253template <
class Emitter>
2257 return this->emitThis(E);
2260template <
class Emitter>
2263 std::optional<PrimType> T = classify(SubExpr->
getType());
2267 if (!this->visit(SubExpr))
2271 if (!this->emitIncPtr(E))
2274 return DiscardResult ? this->emitPopPtr(E) :
true;
2278 return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E)
2279 : this->emitIncf(getRoundingMode(E), E);
2282 return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
2285 if (!this->visit(SubExpr))
2289 if (!this->emitDecPtr(E))
2292 return DiscardResult ? this->emitPopPtr(E) :
true;
2296 return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E)
2297 : this->emitDecf(getRoundingMode(E), E);
2300 return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
2303 if (!this->visit(SubExpr))
2307 if (!this->emitLoadPtr(E))
2309 if (!this->emitConstUint8(1, E))
2311 if (!this->emitAddOffsetUint8(E))
2313 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
2317 if (DiscardResult) {
2319 return this->emitIncfPop(getRoundingMode(E), E);
2320 return this->emitIncPop(*T, E);
2324 const auto &TargetSemantics = Ctx.getFloatSemantics(E->
getType());
2325 if (!this->emitLoadFloat(E))
2327 if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
2329 if (!this->emitAddf(getRoundingMode(E), E))
2331 return this->emitStoreFloat(E);
2333 if (!this->emitLoad(*T, E))
2335 if (!this->emitConst(1, E))
2337 if (!this->emitAdd(*T, E))
2339 return this->emitStore(*T, E);
2342 if (!this->visit(SubExpr))
2346 if (!this->emitLoadPtr(E))
2348 if (!this->emitConstUint8(1, E))
2350 if (!this->emitSubOffsetUint8(E))
2352 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
2356 if (DiscardResult) {
2358 return this->emitDecfPop(getRoundingMode(E), E);
2359 return this->emitDecPop(*T, E);
2363 const auto &TargetSemantics = Ctx.getFloatSemantics(E->
getType());
2364 if (!this->emitLoadFloat(E))
2366 if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
2368 if (!this->emitSubf(getRoundingMode(E), E))
2370 return this->emitStoreFloat(E);
2372 if (!this->emitLoad(*T, E))
2374 if (!this->emitConst(1, E))
2376 if (!this->emitSub(*T, E))
2378 return this->emitStore(*T, E);
2382 return this->discard(SubExpr);
2384 if (!this->visitBool(SubExpr))
2387 if (!this->emitInvBool(E))
2391 return this->emitCast(
PT_Bool, ET, E);
2394 if (!this->visit(SubExpr))
2396 return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
2398 if (!this->visit(SubExpr))
2400 return DiscardResult ? this->emitPop(*T, E) :
true;
2403 if (!this->visit(SubExpr))
2405 return DiscardResult ? this->emitPop(*T, E) :
true;
2408 SubExpr, DerefKind::Read,
2410 llvm_unreachable(
"Dereferencing requires a pointer");
2414 return DiscardResult ? this->emitPop(T, E) :
true;
2417 if (!this->visit(SubExpr))
2419 return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
2423 return this->delegate(SubExpr);
2425 assert(
false &&
"Unhandled opcode");
2431template <
class Emitter>
2438 if (
const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
2439 return this->emitConst(ECD->getInitVal(), E);
2440 }
else if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
2441 return this->visit(BD->getBinding());
2442 }
else if (
const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
2443 const Function *F = getFunction(FuncDecl);
2444 return F && this->emitGetFnPtr(F, E);
2454 if (
auto It = Locals.find(D); It != Locals.end()) {
2455 const unsigned Offset = It->second.Offset;
2458 return this->emitGetLocal(
PT_Ptr, Offset, E);
2459 return this->emitGetPtrLocal(Offset, E);
2460 }
else if (
auto GlobalIndex =
P.getGlobal(D)) {
2462 return this->emitGetGlobalPtr(*GlobalIndex, E);
2464 return this->emitGetPtrGlobal(*GlobalIndex, E);
2465 }
else if (
const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
2466 if (
auto It = this->Params.find(PVD); It != this->Params.end()) {
2467 if (IsReference || !It->second.IsPtr)
2468 return this->emitGetParamPtr(It->second.Offset, E);
2470 return this->emitGetPtrParam(It->second.Offset, E);
2475 if (
auto It = this->LambdaCaptures.find(D);
2476 It != this->LambdaCaptures.end()) {
2477 auto [Offset, IsPtr] = It->second;
2480 return this->emitGetThisFieldPtr(Offset, E);
2481 return this->emitGetPtrThisField(Offset, E);
2486 if (!Ctx.getLangOpts().CPlusPlus) {
2487 if (
const auto *VD = dyn_cast<VarDecl>(D);
2489 if (!this->visitVarDecl(VD))
2492 return this->VisitDeclRefExpr(E);
2496 return this->emitInvalidDeclRef(E, E);
2499template <
class Emitter>
2502 C->emitDestruction();
2505template <
class Emitter>
2509 const auto *FinalDecl = cast<CXXRecordDecl>(BaseType->
getDecl());
2511 const Record *CurRecord = getRecord(CurDecl);
2512 assert(CurDecl && FinalDecl);
2514 unsigned OffsetSum = 0;
2519 const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
2521 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
2522 OffsetSum += B.Offset;
2528 if (CurDecl == FinalDecl)
2532 assert(OffsetSum > 0);
2537template <
class Emitter>
2544 const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
2545 return this->emitCastFP(ToSem, getRoundingMode(E), E);
2550 return this->emitCastFloatingIntegral(ToT, E);
2556 return FromT != ToT ? this->emitCast(FromT, ToT, E) :
true;
2560 const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
2561 return this->emitCastIntegralFloating(FromT, ToSem, getRoundingMode(E),
2573template <
class Emitter>
2587 for (ssize_t I = Desc->
getNumElems() - 1; I >= 0; --I) {
2590 if (!this->emitArrayElemPtrUint64(
SourceInfo{}))
2592 if (!this->emitRecordDestruction(Desc->
ElemDesc))
2609 if (!this->emitRecordDestruction(D))
2620 if (
const Function *DtorFunc = getFunction(Dtor)) {
2621 assert(DtorFunc->hasThisPointer());
2622 assert(DtorFunc->getNumParams() == 1);
2633 if (!this->emitRecordDestruction(
Base.Desc))
ASTImporterLookupTable & LT
static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, UnaryExprOrTypeTrait Kind)
static std::optional< DereferenceInfo > dereference(ProgramStateRef State, const FieldRegion *FR)
Dereferences FR and returns with the pointee's region, and whether it needs to be casted back to it's...
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
const LValueBase getLValueBase() const
ArrayRef< LValuePathEntry > getLValuePath() const
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
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
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 ?: operator.
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...
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
Expr * getSubExpr() const
Get the initializer to use for each array element.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isLogicalOp(Opcode Opc)
static bool isCommaOp(Opcode Opc)
static bool isPtrMemOp(Opcode Opc)
predicates to categorize the respective opcodes.
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 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.
Represents a C++ constructor within a class.
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 C++ destructor within a class.
Represents a call to a member function that may be written either with member call syntax (e....
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
The null pointer literal (C++11 [lex.nullptr])
Represents a list-initialization with parenthesis.
ArrayRef< Expr * > getInitExprs()
A C++ reinterpret_cast expression (C++ [expr.reinterpret.cast]).
Represents the this expression in C++.
A C++ throw-expression (C++ [except.throw]).
const Expr * getSubExpr() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
static CharUnits One()
One - Construct a CharUnits quantity of one.
unsigned getValue() const
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
CompoundLiteralExpr - [C99 6.5.2.5].
const Expr * getInitializer() const
Represents the canonical version of C arrays with a specified constant size.
const llvm::APInt & getSize() const
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
APValue getAPValueResult() const
bool hasAPValueResult() const
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
bool isInvalidDecl() const
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
unsigned getNumObjects() const
This represents one expression.
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool refersToBitField() const
Returns true if this expression is a gl-value that potentially refers to a bit-field.
llvm::APFloat getValue() const
const Expr * getSubExpr() const
Represents a function declaration or definition.
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
GNUNullExpr - Implements the GNU __null extension, which is a name for a null pointer constant that h...
Represents an implicitly-generated value initialization of an object of a given type.
Describes an C or C++ initializer list.
unsigned getNumInits() const
ArrayRef< Expr * > inits()
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.
Implicit declaration of a temporary that was materialized by a MaterializeTemporaryExpr and lifetime-...
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.
LifetimeExtendedTemporaryDecl * getLifetimeExtendedTemporaryDecl()
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
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.
@ Array
An index into an array.
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 ...
ParenExpr - This represents a parethesized expression, e.g.
const Expr * getSubExpr() const
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
[C99 6.4.2.2] - A predefined identifier such as func.
StringLiteral * getFunctionName()
A (possibly-)qualified type.
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 isConstQualified() const
Determine whether this type is const-qualified.
Represents a struct/union/class.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
Base for LValueReferenceType and RValueReferenceType.
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...
StringLiteral - This represents a string literal expression, e.g.
unsigned getLength() const
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
A type trait used in the implementation of various C++11 and Library TR1 trait templates.
bool isBooleanType() const
bool isFundamentalType() const
Tests whether the type is categorized as a fundamental type.
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFunctionType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
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
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Compilation context for expressions.
bool visitExpr(const Expr *E) override
std::optional< unsigned > allocateLocal(DeclTy &&Decl, bool IsExtended=false)
Allocates a space storing a local given its type.
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, bool IsExtended=false)
Creates a local primitive value.
bool VisitIntegerLiteral(const IntegerLiteral *E)
bool VisitCharacterLiteral(const CharacterLiteral *E)
bool VisitDeclRefExpr(const DeclRefExpr *E)
bool VisitExprWithCleanups(const ExprWithCleanups *E)
bool VisitCXXThrowExpr(const CXXThrowExpr *E)
bool VisitMemberExpr(const MemberExpr *E)
bool VisitOffsetOfExpr(const OffsetOfExpr *E)
bool discard(const Expr *E)
Evaluates an expression for side effects and discards the result.
bool visitDecl(const VarDecl *VD) override
Toplevel visitDecl().
bool visitInitializer(const Expr *E)
Compiles an initializer.
bool VisitParenExpr(const ParenExpr *E)
bool Initializing
Flag inidicating if we're initializing an already created variable.
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E)
bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E)
bool VisitLambdaExpr(const LambdaExpr *E)
bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E)
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E)
bool VisitBuiltinCallExpr(const CallExpr *E)
bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E)
bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *E)
void emitCleanup()
Emits scope cleanup instructions.
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E)
bool visitBool(const Expr *E)
Visits an expression and converts it to a boolean.
bool VisitPredefinedExpr(const PredefinedExpr *E)
bool VisitBinaryOperator(const BinaryOperator *E)
bool VisitTypeTraitExpr(const TypeTraitExpr *E)
bool visit(const Expr *E)
Evaluates an expression and places the result on the stack.
bool VisitInitListExpr(const InitListExpr *E)
bool VisitFloatingLiteral(const FloatingLiteral *E)
bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E)
bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E)
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E)
bool visitInitList(ArrayRef< const Expr * > Inits, const Expr *E)
bool VisitUnaryOperator(const UnaryOperator *E)
bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E)
bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E)
bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E)
bool DiscardResult
Flag indicating if return value is to be discarded.
bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E)
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E)
const Function * getFunction(const FunctionDecl *FD)
bool VisitLogicalBinOp(const BinaryOperator *E)
bool visitVarDecl(const VarDecl *VD)
Creates and initializes a variable from the given decl.
bool VisitStringLiteral(const StringLiteral *E)
bool VisitCXXConstructExpr(const CXXConstructExpr *E)
bool VisitGNUNullExpr(const GNUNullExpr *E)
Record * getRecord(QualType Ty)
Returns a record from a record or pointer type.
bool VisitSourceLocExpr(const SourceLocExpr *E)
bool VisitOpaqueValueExpr(const OpaqueValueExpr *E)
bool VisitCXXThisExpr(const CXXThisExpr *E)
typename Emitter::LabelTy LabelTy
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E)
Visit an APValue.
bool VisitPointerArithBinOp(const BinaryOperator *E)
Perform addition/subtraction of a pointer and an integer or subtraction of two pointers.
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
bool VisitCompoundAssignOperator(const CompoundAssignOperator *E)
bool VisitCallExpr(const CallExpr *E)
const RecordType * getRecordTy(QualType Ty)
Returns a record type from a record or pointer type.
bool delegate(const Expr *E)
Just pass evaluation on to E.
bool VisitConstantExpr(const ConstantExpr *E)
bool VisitCastExpr(const CastExpr *E)
bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E)
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E)
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.
void addExtended(const Scope::Local &Local) override
DeclScope(ByteCodeExprGen< Emitter > *Ctx, const ValueDecl *VD)
Expression scope which tracks potentially lifetime extended temporaries which are hoisted to the pare...
bool isFullyCompiled() const
Checks if the function is fully done compiling.
bool hasThisPointer() const
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
bool hasRVO() const
Checks if the first argument is a RVO pointer.
Generic scope for local variables.
Scope used to handle initialization methods.
OptionScope(ByteCodeExprGen< Emitter > *Ctx, bool NewDiscardResult, bool NewInitializing)
Root constructor, compiling or discarding primitives.
Context to manage declaration lifetimes.
Structure/Class descriptor.
unsigned getNumBases() const
const CXXDestructorDecl * getDestructor() const
Returns the destructor of the record, if any.
const Field * getField(const FieldDecl *FD) const
Returns a field.
llvm::iterator_range< const_base_iter > bases() const
unsigned getNumFields() const
llvm::iterator_range< const_field_iter > fields() const
const Base * getBase(const RecordDecl *FD) const
Returns a base descriptor.
Describes the statement/declaration an opcode was generated from.
Scope chain managing the variable lifetimes.
virtual void addLocal(const Scope::Local &Local)
ByteCodeExprGen< Emitter > * Ctx
ByteCodeExprGen instance.
bool LE(InterpState &S, CodePtr OpPC)
PrimType
Enumeration of the primitive types of the VM.
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
constexpr bool isIntegralType(PrimType T)
UnaryExprOrTypeTrait
Names for the "expression or type" traits.
@ C
Languages that the frontend can parse and compile.
@ SD_Static
Static storage duration.
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 isCompositeArray() const
Checks if the descriptor is of an array of composites.
static constexpr MetadataSize InlineDescMD
Descriptor *const ElemDesc
Descriptor of the array element.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
bool isRecord() const
Checks if the descriptor is of a record.
Record *const ElemRecord
Pointer to the record, if block contains records.
bool isArray() const
Checks if the descriptor is of an array.
Describes a record field.
Information about a local's storage.