47 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult) {
57 bool OldDiscardResult;
63template <
class Emitter>
68 case CK_LValueToRValue: {
77 if (!this->emitLoadPop(T, CE))
79 return DiscardResult ? this->emitPop(T, CE) : true;
83 case CK_UncheckedDerivedToBase:
84 case CK_DerivedToBase: {
85 if (!this->visit(SubExpr))
96 return this->emitGetPtrBasePop(ToBase->
Offset, CE);
99 case CK_FloatingCast: {
100 if (!this->visit(SubExpr))
102 const auto *TargetSemantics =
103 &Ctx.getASTContext().getFloatTypeSemantics(CE->
getType());
104 return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE);
107 case CK_IntegralToFloating: {
108 std::optional<PrimType> FromT = classify(SubExpr->getType());
112 if (!this->visit(SubExpr))
115 const auto *TargetSemantics =
116 &Ctx.getASTContext().getFloatTypeSemantics(CE->
getType());
117 llvm::RoundingMode RM = getRoundingMode(CE);
118 return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE);
121 case CK_FloatingToBoolean:
122 case CK_FloatingToIntegral: {
123 std::optional<PrimType> ToT = classify(CE->
getType());
128 if (!this->visit(SubExpr))
131 return this->emitCastFloatingIntegral(*ToT, CE);
134 case CK_ArrayToPointerDecay:
135 case CK_AtomicToNonAtomic:
136 case CK_ConstructorConversion:
137 case CK_FunctionToPointerDecay:
138 case CK_NonAtomicToAtomic:
140 case CK_UserDefinedConversion:
141 case CK_NullToPointer:
142 return this->visit(SubExpr);
144 case CK_IntegralToBoolean:
145 case CK_IntegralCast: {
146 std::optional<PrimType> FromT = classify(SubExpr->getType());
147 std::optional<PrimType> ToT = classify(CE->
getType());
151 if (!this->visit(SubExpr))
155 return this->emitCast(*FromT, *ToT, CE);
159 return discard(SubExpr);
162 assert(
false &&
"Cast not implemented");
164 llvm_unreachable(
"Unhandled clang::CastKind enum");
167template <
class Emitter>
172 return this->emitConst(
LE->getValue(),
LE);
175template <
class Emitter>
180 return this->emitConstFloat(E->
getValue(), E);
183template <
class Emitter>
188template <
class Emitter>
192 return this->VisitLogicalBinOp(BO);
202 if (!this->visit(RHS))
210 std::optional<PrimType>
LT = classify(LHS->
getType());
211 std::optional<PrimType> RT = classify(RHS->
getType());
212 std::optional<PrimType> T = classify(BO->
getType());
213 if (!
LT || !RT || !T) {
214 return this->bail(BO);
217 auto Discard = [
this, T, BO](
bool Result) {
220 return DiscardResult ? this->emitPop(*T, BO) :
true;
226 return this->VisitPointerArithBinOp(BO);
229 if (!visit(LHS) || !visit(RHS))
234 return Discard(this->emitEQ(*
LT, BO));
236 return Discard(this->emitNE(*
LT, BO));
238 return Discard(this->emitLT(*
LT, BO));
240 return Discard(this->emitLE(*
LT, BO));
242 return Discard(this->emitGT(*
LT, BO));
244 return Discard(this->emitGE(*
LT, BO));
247 return Discard(this->emitSubf(getRoundingMode(BO), BO));
248 return Discard(this->emitSub(*T, BO));
251 return Discard(this->emitAddf(getRoundingMode(BO), BO));
252 return Discard(this->emitAdd(*T, BO));
255 return Discard(this->emitMulf(getRoundingMode(BO), BO));
256 return Discard(this->emitMul(*T, BO));
258 return Discard(this->emitRem(*T, BO));
261 return Discard(this->emitDivf(getRoundingMode(BO), BO));
262 return Discard(this->emitDiv(*T, BO));
265 return this->emitStorePop(*T, BO);
266 return this->emitStore(*T, BO);
268 return Discard(this->emitBitAnd(*T, BO));
270 return Discard(this->emitBitOr(*T, BO));
272 return Discard(this->emitShl(*
LT, *RT, BO));
274 return Discard(this->emitShr(*
LT, *RT, BO));
276 return Discard(this->emitBitXor(*T, BO));
279 llvm_unreachable(
"Already handled earlier");
281 return this->bail(BO);
284 llvm_unreachable(
"Unhandled binary op");
289template <
class Emitter>
295 if ((Op != BO_Add && Op != BO_Sub) ||
299 std::optional<PrimType>
LT = classify(LHS);
300 std::optional<PrimType> RT = classify(RHS);
310 if (!visit(RHS) || !visit(LHS))
313 return this->emitSubPtr(classifyPrim(E->
getType()), E);
318 if (!visit(RHS) || !visit(LHS))
322 if (!visit(LHS) || !visit(RHS))
330 return this->emitAddOffset(OffsetType, E);
331 else if (Op == BO_Sub)
332 return this->emitSubOffset(OffsetType, E);
334 return this->bail(E);
337template <
class Emitter>
346 LabelTy LabelTrue = this->getLabel();
347 LabelTy LabelEnd = this->getLabel();
349 if (!this->visit(LHS))
351 if (!this->jumpTrue(LabelTrue))
354 if (!this->visit(RHS))
356 if (!this->jump(LabelEnd))
359 this->emitLabel(LabelTrue);
360 this->emitConstBool(
true, E);
361 this->fallthrough(LabelEnd);
362 this->emitLabel(LabelEnd);
365 return this->emitPopBool(E);
372 LabelTy LabelFalse = this->getLabel();
373 LabelTy LabelEnd = this->getLabel();
375 if (!this->visit(LHS))
377 if (!this->jumpFalse(LabelFalse))
380 if (!this->visit(RHS))
382 if (!this->jump(LabelEnd))
385 this->emitLabel(LabelFalse);
386 this->emitConstBool(
false, E);
387 this->fallthrough(LabelEnd);
388 this->emitLabel(LabelEnd);
391 return this->emitPopBool(E);
396template <
class Emitter>
398 std::optional<PrimType> T = classify(E);
404 return this->emitNullPtr(E);
406 return this->emitZero(*T, E);
409template <
class Emitter>
414 PrimType IndexT = classifyPrim(Index->getType());
418 if (!this->visit(
Base))
421 if (!this->visit(Index))
424 if (!this->emitArrayElemPtrPop(IndexT, E))
428 return this->emitPopPtr(E);
433template <
class Emitter>
436 if (!this->visit(Init))
442template <
class Emitter>
448template <
class Emitter>
457 bool AlignOfReturnsPreferred =
458 ASTCtx.
getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
469 if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
475template <
class Emitter>
481 if (Kind == UETT_SizeOf) {
493 return this->emitConst(Size.getQuantity(), E);
496 if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
513 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
516 else if (
const auto *ME = dyn_cast<MemberExpr>(Arg))
523 return this->emitConst(Size.getQuantity(), E);
529template <
class Emitter>
538 if (!this->visit(
Base))
543 if (
const auto *FD = dyn_cast<FieldDecl>(
Member)) {
545 const Record *R = getRecord(RD);
550 return this->emitGetPtrField(F->
Offset, E);
556template <
class Emitter>
563 return this->emitConst(*ArrayIndex, E);
566template <
class Emitter>
571template <
class Emitter>
578 LabelTy LabelEnd = this->getLabel();
579 LabelTy LabelFalse = this->getLabel();
583 if (!this->jumpFalse(LabelFalse))
586 if (!this->visit(TrueExpr))
588 if (!this->jump(LabelEnd))
591 this->emitLabel(LabelFalse);
593 if (!this->visit(FalseExpr))
596 this->fallthrough(LabelEnd);
597 this->emitLabel(LabelEnd);
602template <
class Emitter>
604 unsigned StringIndex =
P.createGlobalString(E);
605 return this->emitGetPtrGlobal(StringIndex, E);
608template <
class Emitter>
611 return this->emitConst(E->
getValue(), E);
614template <
class Emitter>
621 llvm::RoundingMode RM = getRoundingMode(E);
624 std::optional<PrimType>
LT = classify(LHSComputationType);
625 std::optional<PrimType> RT = classify(ResultType);
634 if (!this->emitLoad(*
LT, E))
638 if (LHS->
getType() != LHSComputationType) {
639 const auto *TargetSemantics =
640 &Ctx.getASTContext().getFloatTypeSemantics(LHSComputationType);
642 if (!this->emitCastFP(TargetSemantics, RM, E))
652 if (!this->emitAddf(RM, E))
656 if (!this->emitSubf(RM, E))
660 if (!this->emitMulf(RM, E))
664 if (!this->emitDivf(RM, E))
672 if (LHS->
getType() != ResultType) {
673 const auto *TargetSemantics =
674 &Ctx.getASTContext().getFloatTypeSemantics(LHS->
getType());
676 if (!this->emitCastFP(TargetSemantics, RM, E))
681 return this->emitStorePop(*
LT, E);
682 return this->emitStore(*
LT, E);
685template <
class Emitter>
691 std::optional<PrimType>
LT = classify(LHS->
getType());
692 std::optional<PrimType> RT = classify(RHS->
getType());
694 if (Op != BO_AddAssign && Op != BO_SubAssign)
704 if (!this->emitLoadPtr(LHS))
710 if (Op == BO_AddAssign)
711 this->emitAddOffset(*RT, E);
713 this->emitSubOffset(*RT, E);
716 return this->emitStorePopPtr(E);
717 return this->emitStorePtr(E);
720template <
class Emitter>
727 return VisitFloatCompoundAssignOperator(E);
730 return VisitPointerCompoundAssignOperator(E);
734 std::optional<PrimType> LHSComputationT =
736 std::optional<PrimType>
LT = classify(LHS->
getType());
738 std::optional<PrimType> ResultT = classify(E->
getType());
740 if (!
LT || !RT || !ResultT || !LHSComputationT)
749 if (!this->emitLoad(*
LT, E))
752 if (*
LT != *LHSComputationT) {
753 if (!this->emitCast(*
LT, *LHSComputationT, E))
763 if (!this->emitAdd(*LHSComputationT, E))
767 if (!this->emitSub(*LHSComputationT, E))
771 if (!this->emitMul(*LHSComputationT, E))
775 if (!this->emitDiv(*LHSComputationT, E))
779 if (!this->emitRem(*LHSComputationT, E))
783 if (!this->emitShl(*LHSComputationT, *RT, E))
787 if (!this->emitShr(*LHSComputationT, *RT, E))
791 if (!this->emitBitAnd(*LHSComputationT, E))
795 if (!this->emitBitXor(*LHSComputationT, E))
799 if (!this->emitBitOr(*LHSComputationT, E))
803 llvm_unreachable(
"Unimplemented compound assign operator");
807 if (*ResultT != *LHSComputationT) {
808 if (!this->emitCast(*LHSComputationT, *ResultT, E))
814 return this->emitStorePop(*ResultT, E);
815 return this->emitStore(*ResultT, E);
818template <
class Emitter>
823 assert(E->
getNumObjects() == 0 &&
"TODO: Implement cleanups");
824 if (!this->visit(SubExpr))
828 return this->emitPopPtr(E);
832template <
class Emitter>
836 std::optional<PrimType> SubExprT = classify(SubExpr);
839 if (std::optional<unsigned> GlobalIndex =
P.createGlobal(E)) {
843 if (!this->visitInitializer(SubExpr))
846 if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
848 return this->emitGetPtrGlobal(*GlobalIndex, E);
856 if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive(
857 SubExpr, *SubExprT,
true,
true)) {
858 if (!this->visitInitializer(SubExpr))
860 this->emitSetLocal(*SubExprT, *LocalIndex, E);
861 return this->emitGetPtrLocal(*LocalIndex, E);
864 if (std::optional<unsigned> LocalIndex =
865 allocateLocal(SubExpr,
true)) {
866 if (!this->emitGetPtrLocal(*LocalIndex, E))
868 return this->visitInitializer(SubExpr);
874template <
class Emitter>
877 std::optional<PrimType> T = classify(E->
getType());
880 if (std::optional<unsigned> GlobalIndex =
P.createGlobal(E)) {
882 return this->visit(Init);
883 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
885 return this->visitInitializer(Init);
892 return this->visit(Init);
894 if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) {
895 if (!this->emitGetPtrLocal(*LocalIndex, E))
897 return this->visitInitializer(Init);
909 return this->Visit(E);
912template <
class Emitter>
918 return this->Visit(E);
921template <
class Emitter>
923 if (std::optional<PrimType> T = classify(E->
getType())) {
926 return this->bail(E);
930template <
class Emitter>
934 return this->emitZeroBool(E);
936 return this->emitZeroSint8(E);
938 return this->emitZeroUint8(E);
940 return this->emitZeroSint16(E);
942 return this->emitZeroUint16(E);
944 return this->emitZeroSint32(E);
946 return this->emitZeroUint32(E);
948 return this->emitZeroSint64(E);
950 return this->emitZeroUint64(E);
952 return this->emitNullPtr(E);
956 llvm_unreachable(
"unknown primitive type");
959template <
class Emitter>
961 const Expr *LV, DerefKind AK, llvm::function_ref<
bool(
PrimType)> Direct,
962 llvm::function_ref<
bool(
PrimType)> Indirect) {
963 if (std::optional<PrimType> T = classify(LV->
getType())) {
966 if (
const auto *DE = dyn_cast<DeclRefExpr>(LV)) {
967 if (!DE->getDecl()->getType()->isReferenceType()) {
968 if (
const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
969 return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
970 if (
const auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
971 return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
984template <
class Emitter>
987 llvm::function_ref<
bool(
PrimType)> Direct,
988 llvm::function_ref<
bool(
PrimType)> Indirect) {
989 auto It = this->Params.find(PD);
990 if (It != this->Params.end()) {
991 unsigned Idx = It->second;
993 case DerefKind::Read:
994 return DiscardResult ?
true : this->emitGetParam(T, Idx, LV);
996 case DerefKind::Write:
999 if (!this->emitSetParam(T, Idx, LV))
1001 return DiscardResult ?
true : this->emitGetPtrParam(Idx, LV);
1003 case DerefKind::ReadWrite:
1004 if (!this->emitGetParam(T, Idx, LV))
1008 if (!this->emitSetParam(T, Idx, LV))
1010 return DiscardResult ?
true : this->emitGetPtrParam(Idx, LV);
1016 if (!DiscardResult && T ==
PT_Ptr && AK == DerefKind::Read) {
1017 if (
auto Idx =
P.getOrCreateDummy(PD))
1018 return this->emitGetPtrGlobal(*Idx, PD);
1023 return visit(LV) && Indirect(T);
1026template <
class Emitter>
1029 llvm::function_ref<
bool(
PrimType)> Direct,
1030 llvm::function_ref<
bool(
PrimType)> Indirect) {
1031 auto It = Locals.find(VD);
1032 if (It != Locals.end()) {
1033 const auto &L = It->second;
1035 case DerefKind::Read:
1036 if (!this->emitGetLocal(T, L.Offset, LV))
1038 return DiscardResult ? this->emitPop(T, LV) :
true;
1040 case DerefKind::Write:
1043 if (!this->emitSetLocal(T, L.Offset, LV))
1045 return DiscardResult ?
true : this->emitGetPtrLocal(L.Offset, LV);
1047 case DerefKind::ReadWrite:
1048 if (!this->emitGetLocal(T, L.Offset, LV))
1052 if (!this->emitSetLocal(T, L.Offset, LV))
1054 return DiscardResult ?
true : this->emitGetPtrLocal(L.Offset, LV);
1056 }
else if (
auto Idx =
P.getGlobal(VD)) {
1058 case DerefKind::Read:
1059 if (!this->emitGetGlobal(T, *Idx, LV))
1061 return DiscardResult ? this->emitPop(T, LV) :
true;
1063 case DerefKind::Write:
1066 if (!this->emitSetGlobal(T, *Idx, LV))
1068 return DiscardResult ?
true : this->emitGetPtrGlobal(*Idx, LV);
1070 case DerefKind::ReadWrite:
1071 if (!this->emitGetGlobal(T, *Idx, LV))
1075 if (!this->emitSetGlobal(T, *Idx, LV))
1077 return DiscardResult ?
true : this->emitGetPtrGlobal(*Idx, LV);
1084 if (!DiscardResult && AK == DerefKind::Read) {
1088 return this->visit(VD->
getInit());
1093 return visit(LV) && Indirect(T);
1096template <
class Emitter>
1097template <
typename T>
1099 switch (classifyPrim(E->
getType())) {
1101 return this->emitConstSint8(
Value, E);
1103 return this->emitConstUint8(
Value, E);
1105 return this->emitConstSint16(
Value, E);
1107 return this->emitConstUint16(
Value, E);
1109 return this->emitConstSint32(
Value, E);
1111 return this->emitConstUint32(
Value, E);
1113 return this->emitConstSint64(
Value, E);
1115 return this->emitConstUint64(
Value, E);
1117 return this->emitConstBool(
Value, E);
1120 llvm_unreachable(
"Invalid integral type");
1123 llvm_unreachable(
"unknown primitive type");
1126template <
class Emitter>
1128 if (
Value.isSigned())
1129 return this->emitConst(
Value.getSExtValue(), E);
1130 return this->emitConst(
Value.getZExtValue(), E);
1133template <
class Emitter>
1139 if (
const auto *VD =
1140 dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>())) {
1141 assert(!
P.getGlobal(VD));
1142 assert(!Locals.contains(VD));
1149 Src.is<
const Expr *>());
1151 if (
auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>()))
1152 Locals.insert({VD, Local});
1153 VarScope->add(Local, IsExtended);
1154 return Local.Offset;
1157template <
class Emitter>
1158std::optional<unsigned>
1161 if (
const auto *VD =
1162 dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>())) {
1163 assert(!
P.getGlobal(VD));
1164 assert(!Locals.contains(VD));
1169 const Expr *Init =
nullptr;
1170 bool IsTemporary =
false;
1171 if (
auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<
const Decl *>())) {
1175 if (
const auto *VarD = dyn_cast<VarDecl>(VD))
1176 Init = VarD->getInit();
1178 if (
auto *E = Src.dyn_cast<
const Expr *>()) {
1185 IsTemporary,
false, Init);
1191 Locals.insert({Key, Local});
1192 VarScope->add(Local, IsExtended);
1193 return Local.Offset;
1198template <
class Emitter>
1203 if (
const auto *InitList = dyn_cast<InitListExpr>(
Initializer)) {
1204 unsigned ElementIndex = 0;
1205 for (
const Expr *Init : InitList->inits()) {
1206 if (std::optional<PrimType> T = classify(Init->getType())) {
1208 if (!this->visit(Init))
1210 if (!this->emitInitElem(*T, ElementIndex, Init))
1215 if (!this->emitConstUint32(ElementIndex, Init))
1217 if (!this->emitArrayElemPtrUint32(Init))
1219 if (!visitInitializer(Init))
1221 if (!this->emitPopPtr(Init))
1228 }
else if (
const auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Initializer)) {
1229 return this->visitInitializer(DIE->getExpr());
1230 }
else if (
const auto *AILE = dyn_cast<ArrayInitLoopExpr>(
Initializer)) {
1234 const Expr *SubExpr = AILE->getSubExpr();
1235 size_t Size = AILE->getArraySize().getZExtValue();
1236 std::optional<PrimType> ElemT = classify(SubExpr->
getType());
1241 for (
size_t I = 0; I != Size; ++I) {
1245 if (!this->visit(SubExpr))
1251 if (!this->emitConstUint64(I, SubExpr))
1253 if (!this->emitArrayElemPtrUint64(SubExpr))
1255 if (!visitInitializer(SubExpr))
1262 }
else if (
const auto *IVIE = dyn_cast<ImplicitValueInitExpr>(
Initializer)) {
1265 const auto *CAT = cast<ConstantArrayType>(AT);
1266 size_t NumElems = CAT->getSize().getZExtValue();
1268 if (std::optional<PrimType> ElemT = classify(CAT->getElementType())) {
1272 for (
size_t I = 0; I != NumElems; ++I) {
1279 assert(
false &&
"default initializer for non-primitive type");
1283 }
else if (
const auto *Ctor = dyn_cast<CXXConstructExpr>(
Initializer)) {
1285 Ctx.getASTContext().getAsConstantArrayType(Ctor->getType());
1287 size_t NumElems = CAT->
getSize().getZExtValue();
1288 const Function *Func = getFunction(Ctor->getConstructor());
1294 for (
size_t I = 0; I != NumElems; ++I) {
1301 for (
const auto *Arg : Ctor->arguments()) {
1302 if (!this->visit(Arg))
1310 }
else if (
const auto *SL = dyn_cast<StringLiteral>(
Initializer)) {
1312 Ctx.getASTContext().getAsConstantArrayType(SL->getType());
1313 assert(CAT &&
"a string literal that's not a constant array?");
1318 std::min(
unsigned(CAT->
getSize().getZExtValue()), SL->getLength());
1319 size_t CharWidth = SL->getCharByteWidth();
1321 for (
unsigned I = 0; I != N; ++I) {
1322 uint32_t CodeUnit = SL->getCodeUnit(I);
1324 if (CharWidth == 1) {
1325 this->emitConstSint8(CodeUnit, SL);
1326 this->emitInitElemSint8(I, SL);
1327 }
else if (CharWidth == 2) {
1328 this->emitConstUint16(CodeUnit, SL);
1329 this->emitInitElemUint16(I, SL);
1330 }
else if (CharWidth == 4) {
1331 this->emitConstUint32(CodeUnit, SL);
1332 this->emitInitElemUint32(I, SL);
1334 llvm_unreachable(
"unsupported character width");
1338 }
else if (
const auto *CLE = dyn_cast<CompoundLiteralExpr>(
Initializer)) {
1339 return visitInitializer(CLE->getInitializer());
1340 }
else if (
const auto *EWC = dyn_cast<ExprWithCleanups>(
Initializer)) {
1341 return visitInitializer(EWC->getSubExpr());
1344 assert(
false &&
"Unknown expression for array initialization");
1348template <
class Emitter>
1353 if (
const auto CtorExpr = dyn_cast<CXXConstructExpr>(
Initializer)) {
1354 const Function *Func = getFunction(CtorExpr->getConstructor());
1365 for (
const auto *Arg : CtorExpr->arguments()) {
1366 if (!this->visit(Arg))
1371 }
else if (
const auto *InitList = dyn_cast<InitListExpr>(
Initializer)) {
1372 const Record *R = getRecord(InitList->getType());
1374 unsigned InitIndex = 0;
1375 for (
const Expr *Init : InitList->inits()) {
1381 if (std::optional<PrimType> T = classify(Init)) {
1382 if (!this->visit(Init))
1393 if (!this->emitGetPtrField(FieldToInit->
Offset, Init))
1396 if (!this->visitInitializer(Init))
1412 return this->VisitCallExpr(CE);
1413 }
else if (
const auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Initializer)) {
1414 return this->visitInitializer(DIE->getExpr());
1415 }
else if (
const auto *CE = dyn_cast<CastExpr>(
Initializer)) {
1416 return this->visitInitializer(CE->getSubExpr());
1417 }
else if (
const auto *CE = dyn_cast<CXXBindTemporaryExpr>(
Initializer)) {
1418 return this->visitInitializer(CE->getSubExpr());
1424template <
class Emitter>
1438template <
class Emitter>
1440 if (
const PointerType *PT = dyn_cast<PointerType>(Ty))
1446template <
class Emitter>
1448 if (
auto *RecordTy = getRecordTy(Ty)) {
1449 return getRecord(RecordTy->getDecl());
1454template <
class Emitter>
1456 return P.getOrCreateRecord(RD);
1459template <
class Emitter>
1462 const Function *Func =
P.getFunction(FD);
1464 bool WasNotDefined = Func && !Func->
hasBody();
1466 if (IsBeingCompiled)
1469 if (!Func || WasNotDefined) {
1473 llvm::consumeError(R.takeError());
1481template <
class Emitter>
1487 if (std::optional<PrimType> T = classify(Exp))
1488 return this->emitRet(*T, Exp);
1490 return this->emitRetValue(Exp);
1496template <
class Emitter>
1498 assert(!VD->
isInvalidDecl() &&
"Trying to constant evaluate an invalid decl");
1499 std::optional<PrimType> VarT = classify(VD->
getType());
1502 if (!this->visitVarDecl(VD))
1506 if (shouldBeGloballyIndexed(VD)) {
1507 auto GlobalIndex =
P.getGlobal(VD);
1508 assert(GlobalIndex);
1509 if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
1512 auto Local = Locals.find(VD);
1513 assert(Local != Locals.end());
1514 if (!this->emitGetPtrLocal(Local->second.Offset, VD))
1520 if (!this->emitLoadPop(*VarT, VD))
1523 return this->emitRet(*VarT, VD);
1526 return this->emitRetValue(VD);
1529template <
class Emitter>
1536 std::optional<PrimType> VarT = classify(VD->
getType());
1538 if (shouldBeGloballyIndexed(VD)) {
1539 std::optional<unsigned> GlobalIndex =
P.getOrCreateGlobal(VD, Init);
1542 return this->bail(VD);
1549 if (!this->visit(Init))
1551 return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
1553 return this->visitGlobalInitializer(Init, *GlobalIndex);
1558 unsigned Offset = this->allocateLocalPrimitive(
1563 if (!this->visit(Init))
1566 return this->emitSetLocal(*VarT,
Offset, VD);
1569 if (std::optional<unsigned>
Offset = this->allocateLocal(VD)) {
1571 return this->visitLocalInitializer(Init, *
Offset);
1580template <
class Emitter>
1587 for (
const auto *Arg : E->
arguments()) {
1588 if (!this->visit(Arg))
1592 if (!this->emitCallBI(Func, E))
1596 if (DiscardResult && !ReturnType->
isVoidType()) {
1597 PrimType T = classifyPrim(ReturnType);
1598 return this->emitPop(T, E);
1604template <
class Emitter>
1607 return VisitBuiltinCallExpr(E);
1610 if (
const auto *FuncDecl = dyn_cast_if_present<FunctionDecl>(Callee)) {
1611 const Function *Func = getFunction(FuncDecl);
1623 std::optional<PrimType> T = classify(ReturnType);
1625 if (Func->
hasRVO() && DiscardResult) {
1629 if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {
1630 if (!this->emitGetPtrLocal(*LocalIndex, E))
1636 for (
const auto *Arg : E->
arguments()) {
1637 if (!this->visit(Arg))
1644 if (!this->emitCall(Func, E))
1647 if (DiscardResult && !ReturnType->
isVoidType() && T)
1648 return this->emitPop(*T, E);
1652 assert(
false &&
"We don't support non-FunctionDecl callees right now.");
1658template <
class Emitter>
1665 return VisitCallExpr(E);
1668template <
class Emitter>
1671 return this->visit(E->
getExpr());
1674template <
class Emitter>
1677 return this->visit(E->
getExpr());
1680template <
class Emitter>
1686 return this->emitConstBool(E->
getValue(), E);
1689template <
class Emitter>
1695 return this->emitNullPtr(E);
1698template <
class Emitter>
1702 return this->emitThis(E);
1705template <
class Emitter>
1708 std::optional<PrimType> T = classify(SubExpr->
getType());
1712 if (!this->visit(SubExpr))
1716 if (!this->emitIncPtr(E))
1719 return DiscardResult ? this->emitPopPtr(E) :
true;
1722 return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
1725 if (!this->visit(SubExpr))
1729 if (!this->emitDecPtr(E))
1732 return DiscardResult ? this->emitPopPtr(E) :
true;
1735 return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
1738 if (!this->visit(SubExpr))
1742 this->emitLoadPtr(E);
1743 this->emitConstUint8(1, E);
1744 this->emitAddOffsetUint8(E);
1745 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
1750 return this->emitIncPop(*T, E);
1752 this->emitLoad(*T, E);
1753 this->emitConst(1, E);
1754 this->emitAdd(*T, E);
1755 return this->emitStore(*T, E);
1758 if (!this->visit(SubExpr))
1762 this->emitLoadPtr(E);
1763 this->emitConstUint8(1, E);
1764 this->emitSubOffsetUint8(E);
1765 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
1770 return this->emitDecPop(*T, E);
1772 this->emitLoad(*T, E);
1773 this->emitConst(1, E);
1774 this->emitSub(*T, E);
1775 return this->emitStore(*T, E);
1778 if (!this->visit(SubExpr))
1781 return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E);
1783 if (!this->visit(SubExpr))
1785 return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
1787 if (!this->visit(SubExpr))
1789 return DiscardResult ? this->emitPop(*T, E) :
true;
1792 if (!this->visit(SubExpr))
1794 return DiscardResult ? this->emitPop(*T, E) :
true;
1797 SubExpr, DerefKind::Read,
1799 llvm_unreachable(
"Dereferencing requires a pointer");
1803 return DiscardResult ? this->emitPop(T, E) :
true;
1806 if (!this->visit(SubExpr))
1808 return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
1813 assert(
false &&
"Unhandled opcode");
1819template <
class Emitter>
1826 bool IsReference =
Decl->getType()->isReferenceType();
1828 if (
auto It = Locals.find(
Decl); It != Locals.end()) {
1829 const unsigned Offset = It->second.Offset;
1833 return this->emitGetPtrLocal(
Offset, E);
1834 }
else if (
auto GlobalIndex =
P.getGlobal(
Decl)) {
1836 return this->emitGetGlobal(
PT_Ptr, *GlobalIndex, E);
1838 return this->emitGetPtrGlobal(*GlobalIndex, E);
1839 }
else if (
const auto *PVD = dyn_cast<ParmVarDecl>(
Decl)) {
1840 if (
auto It = this->Params.find(PVD); It != this->Params.end()) {
1842 return this->emitGetParam(
PT_Ptr, It->second, E);
1843 return this->emitGetPtrParam(It->second, E);
1845 }
else if (
const auto *ECD = dyn_cast<EnumConstantDecl>(
Decl)) {
1846 return this->emitConst(ECD->getInitVal(), E);
1847 }
else if (
const auto *BD = dyn_cast<BindingDecl>(
Decl)) {
1848 return this->visit(BD->getBinding());
1854template <
class Emitter>
1857 C->emitDestruction();
ASTImporterLookupTable & LT
static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, UnaryExprOrTypeTrait Kind)
const NamedDecl * FromDecl
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...
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 * getTrueExpr() const
Expr * getFalseExpr() const
Represents the index of the current element of an array being initialized by an ArrayInitLoopExpr.
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)
A boolean literal, per ([C++ lex.bool] Boolean literals).
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 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.
The null pointer literal (C++11 [lex.nullptr])
Represents a C++ struct/union/class.
Represents the this expression in C++.
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...
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.
Represents an implicitly-generated value initialization of an object of a given type.
Describes an C or C++ initializer list.
ArrayRef< Expr * > inits()
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.
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.
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...
Base for LValueReferenceType and RValueReferenceType.
StringLiteral - This represents a string literal expression, e.g.
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Expr * getReplacement() 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.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
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.
bool VisitIntegerLiteral(const IntegerLiteral *E)
bool VisitCharacterLiteral(const CharacterLiteral *E)
bool VisitDeclRefExpr(const DeclRefExpr *E)
bool VisitExprWithCleanups(const ExprWithCleanups *E)
bool VisitMemberExpr(const MemberExpr *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.
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable, bool IsExtended=false)
Creates a local primitive value.
bool visitRecordInitializer(const Expr *Initializer)
Compiles a record initializer.
bool VisitParenExpr(const ParenExpr *E)
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E)
bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E)
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E)
bool VisitBuiltinCallExpr(const CallExpr *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 VisitBinaryOperator(const BinaryOperator *E)
bool visit(const Expr *E)
Evaluates an expression and places result on stack.
bool VisitInitListExpr(const InitListExpr *E)
bool VisitFloatingLiteral(const FloatingLiteral *E)
bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *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)
Record * getRecord(QualType Ty)
Returns a record from a record or pointer type.
bool VisitOpaqueValueExpr(const OpaqueValueExpr *E)
bool VisitCXXThisExpr(const CXXThisExpr *E)
typename Emitter::LabelTy LabelTy
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 VisitConstantExpr(const ConstantExpr *E)
bool VisitCastExpr(const CastExpr *E)
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E)
bool visitArrayInitializer(const Expr *Initializer)
Compiles an array initializer.
Compilation context for statements.
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 isConstexpr() const
Checks if the function is valid to call in constexpr.
bool hasRVO() const
Checks if the first argument is a RVO pointer.
Scope for local variables.
void addLocal(const Scope::Local &Local) override
Scope used to handle initialization methods.
OptionScope(ByteCodeExprGen< Emitter > *Ctx, bool NewDiscardResult)
Root constructor, compiling or discarding primitives.
Context to manage declaration lifetimes.
Structure/Class descriptor.
const Field * getField(const FieldDecl *FD) const
Returns a field.
const Base * getBase(const RecordDecl *FD) const
Returns a base descriptor.
Scope chain managing the variable lifetimes.
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
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.
static constexpr MetadataSize InlineDescMD
Describes a record field.
Information about a local's storage.