LLVM: lib/Analysis/MemoryBuiltins.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
42#include
43#include
44#include
45#include
46#include
47#include
48
49using namespace llvm;
50
51#define DEBUG_TYPE "memory-builtins"
52
54 "object-size-offset-visitor-max-visit-instructions",
55 cl::desc("Maximum number of instructions for ObjectSizeOffsetVisitor to "
56 "look at"),
58
67
79
81 switch (Family) {
83 return "malloc";
85 return "_Znwm";
87 return "_ZnwmSt11align_val_t";
89 return "_Znam";
91 return "_ZnamSt11align_val_t";
93 return "??2@YAPAXI@Z";
95 return "??_U@YAPAXI@Z";
97 return "vec_malloc";
99 return "__kmpc_alloc_shared";
100 }
102}
103
114
115
116
117
124 {LibFunc_Znwm12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}},
126 {LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}},
128 {LibFunc_ZnwmSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}},
130 {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t, {MallocLike, 4, 0, -1, 1, MallocFamily::CPPNewAligned}},
136 {LibFunc_Znam12__hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}},
138 {LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}},
140 {LibFunc_ZnamSt11align_val_t12__hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}},
142 {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t, {MallocLike, 4, 0, -1, 1, MallocFamily::CPPNewAligned}},
146 {LibFunc_msvc_new_longlong_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNew}},
156};
157
158
160
162 return nullptr;
163
165 if (!CB)
166 return nullptr;
167
168 if (CB->isNoBuiltin())
169 return nullptr;
170
171 return CB->getCalledFunction();
172}
173
174
175
176static std::optional
179
180
181 if (!Callee->getReturnType()->isPointerTy())
182 return std::nullopt;
183
184
185 LibFunc TLIFn;
186 if (!TLI || !TLI->getLibFunc(*Callee, TLIFn) || !TLI->has(TLIFn))
187 return std::nullopt;
188
189 const auto *Iter = find_if(
190 AllocationFnData, [TLIFn](const std::pair<LibFunc, AllocFnsTy> &P) {
191 return P.first == TLIFn;
192 });
193
195 return std::nullopt;
196
197 const AllocFnsTy *FnData = &Iter->second;
199 return std::nullopt;
200
201
202 int FstParam = FnData->FstParam;
203 int SndParam = FnData->SndParam;
204 FunctionType *FTy = Callee->getFunctionType();
205
206 if (FTy->getReturnType()->isPointerTy() &&
207 FTy->getNumParams() == FnData->NumParams &&
208 (FstParam < 0 ||
209 (FTy->getParamType(FstParam)->isIntegerTy(32) ||
210 FTy->getParamType(FstParam)->isIntegerTy(64))) &&
211 (SndParam < 0 ||
212 FTy->getParamType(SndParam)->isIntegerTy(32) ||
213 FTy->getParamType(SndParam)->isIntegerTy(64)))
214 return *FnData;
215 return std::nullopt;
216}
217
218static std::optional
223 return std::nullopt;
224}
225
226static std::optional
231 Callee, AllocTy, &GetTLI(const_cast<Function &>(*Callee)));
232 return std::nullopt;
233}
234
235static std::optional
238
239
240 if (std::optional Data =
243 }
244
247 return std::nullopt;
248
249 std::pair<unsigned, std::optional> Args = Attr.getAllocSizeArgs();
250
252
253
255 Result.NumParams = CB->arg_size();
256 Result.FstParam = Args.first;
257 Result.SndParam = Args.second.value_or(-1);
258
259 Result.AlignParam = -1;
260 return Result;
261}
262
265 Attribute Attr = CB->getFnAttr(Attribute::AllocKind);
268 }
270}
271
273 return F->getAttributes().getAllocKind();
274}
275
279
283
284
285
286
297
298
299
303
304
305
310
311
312
317
318
319
323
329
331
332
333
334
335
336
337
339}
340
344 if (FnData && FnData->AlignParam >= 0) {
345 return V->getOperand(FnData->AlignParam);
346 }
347 return V->getArgOperandWithAttribute(Attribute::AllocAlign);
348}
349
350
351
352
353
354
356
357
358
359 if (I.getBitWidth() > IntTyBits && I.getActiveBits() > IntTyBits)
360 return false;
361 if (I.getBitWidth() != IntTyBits)
362 I = I.zextOrTrunc(IntTyBits);
363 return true;
364}
365
366std::optional
369
370
372 if (!FnData)
373 return std::nullopt;
374
375
376
378 const unsigned IntTyBits = DL.getIndexTypeSizeInBits(CB->getType());
379
380
384 return std::nullopt;
385
386
387 if (FnData->FstParam > 0) {
390 if (!Arg)
391 return std::nullopt;
392
394 if (Size.ugt(MaxSize))
395 Size = MaxSize + 1;
396 }
398 }
399
402 if (!Arg)
403 return std::nullopt;
404
407 return std::nullopt;
408
409
410 if (FnData->SndParam < 0)
412
414 if (!Arg)
415 return std::nullopt;
416
419 return std::nullopt;
420
421 bool Overflow;
422 Size = Size.umul_ov(NumElems, Overflow);
423 if (Overflow)
424 return std::nullopt;
426}
427
433
436 return nullptr;
437
438
441
447
448 return nullptr;
449}
450
456
457
458static const std::pair<LibFunc, FreeFnsTy> FreeFnData[] = {
461 {LibFunc_msvc_delete_ptr32, {1, MallocFamily::MSVCNew}},
462 {LibFunc_msvc_delete_ptr64, {1, MallocFamily::MSVCNew}},
467 {LibFunc_ZdlPvRKSt9nothrow_t, {2, MallocFamily::CPPNew}},
473 {LibFunc_msvc_delete_ptr32_int, {2, MallocFamily::MSVCNew}},
474 {LibFunc_msvc_delete_ptr64_longlong, {2, MallocFamily::MSVCNew}},
475 {LibFunc_msvc_delete_ptr32_nothrow, {2, MallocFamily::MSVCNew}},
476 {LibFunc_msvc_delete_ptr64_nothrow, {2, MallocFamily::MSVCNew}},
478 {LibFunc_msvc_delete_array_ptr64_longlong, {2, MallocFamily::MSVCArrayNew}},
479 {LibFunc_msvc_delete_array_ptr32_nothrow, {2, MallocFamily::MSVCArrayNew}},
480 {LibFunc_msvc_delete_array_ptr64_nothrow, {2, MallocFamily::MSVCArrayNew}},
482 {LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewAligned}},
483 {LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t, {3, MallocFamily::CPPNewArrayAligned}},
484 {LibFunc_ZdlPvjSt11align_val_t, {3, MallocFamily::CPPNewAligned}},
485 {LibFunc_ZdlPvmSt11align_val_t, {3, MallocFamily::CPPNewAligned}},
488};
489
490
492 const LibFunc TLIFn) {
493 const auto *Iter =
494 find_if(FreeFnData, [TLIFn](const std::pair<LibFunc, FreeFnsTy> &P) {
495 return P.first == TLIFn;
496 });
498 return std::nullopt;
499 return Iter->second;
500}
501
502std::optional
505 LibFunc TLIFn;
506 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn)) {
507
508 const auto AllocData =
510 if (AllocData)
513 if (FreeData)
515 }
516 }
517
518
524 }
525 return std::nullopt;
526}
527
528
531 if (!FnData)
533
534
535
536
539 return false;
540 if (FTy->getNumParams() != FnData->NumParams)
541 return false;
543 return false;
544
545 return true;
546}
547
550 LibFunc TLIFn;
551 if (TLI && TLI->getLibFunc(*Callee, TLIFn) && TLI->has(TLIFn) &&
553
555 }
556 }
557
560
561 return nullptr;
562}
563
564
565
566
576
577
578
579
580
585 if (.bothKnown())
586 return false;
587
589 return true;
590}
591
597 "Other modes are currently not supported");
598
603 };
604
607
610 return std::nullopt;
612 }
613
615 if (!GV->getValueType()->isSized() || GV->hasExternalWeakLinkage() ||
616 !GV->hasInitializer() || GV->isInterposable())
617 return std::nullopt;
618 return Align(DL.getTypeAllocSize(GV->getValueType()), GV->getAlign());
619 }
620
622 Type *MemoryTy = A->getPointeeInMemoryValueType();
623 if (!MemoryTy || !MemoryTy->isSized())
624 return std::nullopt;
625 return Align(DL.getTypeAllocSize(MemoryTy), A->getParamAlign());
626 }
627
629 if (std::optional Size = AI->getAllocationSize(DL))
630 return Align(*Size, AI->getAlign());
631 return std::nullopt;
632 }
633
636 if (std::optional<uint64_t> ZExtSize = Size->tryZExtValue())
638 }
639 return std::nullopt;
640 }
641
642 return std::nullopt;
643}
644
648 bool MustSucceed) {
650 MustSucceed);
651}
652
658 "ObjectSize must be a call to llvm.objectsize!");
659
663
664
665
666 if (MustSucceed)
669 else
671
674
677 if (StaticOnly) {
678
679
682 isUIntN(ResultType->getBitWidth(), Size))
683 return ConstantInt::get(ResultType, Size);
684 } else {
688
692 if (InsertedInstructions)
694 }));
696
699
700
701
704 ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType);
705 Value *Ret = Builder.CreateSelect(
706 UseZero, ConstantInt::get(ResultType, 0), ResultSize);
707
708
710 Builder.CreateAssumption(Builder.CreateICmpNE(
712
713 return Ret;
714 }
715 }
716
717 if (!MustSucceed)
718 return nullptr;
719
722}
723
725 "Number of arguments with unsolved size and offset");
727 "Number of load instructions with unsolved size and offset");
728
729static std::optional
731 std::optional RHS,
734 return std::nullopt;
737 else
739}
740
743 unsigned recursionDepth) {
744 constexpr unsigned maxRecursionDepth = 4;
745 if (recursionDepth == maxRecursionDepth)
746 return std::nullopt;
747
749 return CI->getValue().sextOrTrunc(BitWidth);
753 BitWidth, recursionDepth + 1),
755 BitWidth, recursionDepth + 1),
756 EvalMode);
758 unsigned Count = PN->getNumIncomingValues();
760 return std::nullopt;
762 PN->getIncomingValue(0), EvalMode, BitWidth, recursionDepth + 1);
763 for (unsigned I = 1; Acc && I < Count; ++I) {
765 PN->getIncomingValue(I), EvalMode, BitWidth, recursionDepth + 1);
767 }
768 return Acc;
769 }
770
771 return std::nullopt;
772}
773
774static std::optional
778 return CI->getValue().sextOrTrunc(BitWidth);
779
782 return std::nullopt;
783
784
785
786
788}
789
790
791
792
794 if (Options.RoundToAlign && Alignment)
795 Size = APInt(IntTyBits, alignTo(Size.getZExtValue(), *Alignment));
796
797 return Size.isNegative() ? APInt() : Size;
798}
799
804 : DL(DL), TLI(TLI), Options(Options) {
805
806
807}
808
810 InstructionsVisited = 0;
812
813
814
818
820 return {};
821
823}
824
825OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
826 unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType());
827
828
829
830
831
832
834 V = V->stripAndAccumulateConstantOffsets(
836
837
838
839
843
844
849
850
851
852 unsigned IdxTyBits = DL.getIndexTypeSizeInBits(V->getType());
853 auto OffsetRangeAnalysis = [EvalMode, IdxTyBits](Value &VOffset,
855 if (auto PossibleOffset =
857 Offset = *PossibleOffset;
858 return true;
859 }
860 return false;
861 };
862
863 V = V->stripAndAccumulateConstantOffsets(
864 DL, Offset, true, true,
865 OffsetRangeAnalysis);
866 }
867
868
869
870 IntTyBits = DL.getIndexTypeSizeInBits(V->getType());
872 OffsetSpan ORT = computeValue(V);
873
874 bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
875 if (!IndexTypeSizeChanged && Offset.isZero())
876 return ORT;
877
878
879
880
881 if (IndexTypeSizeChanged) {
883 !::CheckedZextOrTrunc(ORT.Before, InitialIntTyBits))
884 ORT.Before = APInt();
885 if (ORT.knownAfter() && !::CheckedZextOrTrunc(ORT.After, InitialIntTyBits))
886 ORT.After = APInt();
887 }
888
890 bool Overflow;
892 if (Overflow)
893 ORT.Before = APInt();
894 }
896 bool Overflow;
898 if (Overflow)
899 ORT.After = APInt();
900 }
901
902
904
905
906
907
908
911 return ObjectSizeOffsetVisitor::unknown();
912 }
913
914 }
915 return ORT;
916}
917
918OffsetSpan ObjectSizeOffsetVisitor::computeValue(Value *V) {
920
921
922 auto P = SeenInsts.try_emplace(I, ObjectSizeOffsetVisitor::unknown());
923 if (.second)
924 return P.first->second;
925 ++InstructionsVisited;
927 return ObjectSizeOffsetVisitor::unknown();
928 OffsetSpan Res = visit(*I);
929
930
931 SeenInsts[I] = Res;
932 return Res;
933 }
944
945 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: "
946 << *V << '\n');
947 return ObjectSizeOffsetVisitor::unknown();
948}
949
950bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) {
951 return ::CheckedZextOrTrunc(I, IntTyBits);
952}
953
955 TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType());
957 return ObjectSizeOffsetVisitor::unknown();
959 return ObjectSizeOffsetVisitor::unknown();
961
962 if (.isArrayAllocation())
964
965 Value *ArraySize = I.getArraySize();
967 ArraySize, Options.EvalMode,
969 APInt NumElems = *PossibleSize;
970 if (!CheckedZextOrTrunc(NumElems))
971 return ObjectSizeOffsetVisitor::unknown();
972
973 bool Overflow;
974 Size = Size.umul_ov(NumElems, Overflow);
975
976 return Overflow ? ObjectSizeOffsetVisitor::unknown()
978 }
979 return ObjectSizeOffsetVisitor::unknown();
980}
981
983 Type *MemoryTy = A.getPointeeInMemoryValueType();
984
985 if (!MemoryTy|| !MemoryTy->isSized()) {
986 ++ObjectVisitorArgument;
987 return ObjectSizeOffsetVisitor::unknown();
988 }
989
990 APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy));
992}
993
995 auto Mapper = [this](const Value *V) -> const Value * {
996 if (!V->getType()->isIntegerTy())
997 return V;
998
1000 V, Options.EvalMode, V->getType()->getScalarSizeInBits()))
1001 return ConstantInt::get(V->getType(), *PossibleBound);
1002
1003 return V;
1004 };
1005
1006 if (std::optional Size = getAllocSize(&CB, TLI, Mapper)) {
1007
1008 if (Size->isNegative())
1009 return ObjectSizeOffsetVisitor::unknown();
1011 }
1012 return ObjectSizeOffsetVisitor::unknown();
1013}
1014
1017
1018
1019
1020
1021
1022
1023
1025 return ObjectSizeOffsetVisitor::unknown();
1027}
1028
1031 return ObjectSizeOffsetVisitor::unknown();
1032}
1033
1035
1036 return ObjectSizeOffsetVisitor::unknown();
1037}
1038
1041 return ObjectSizeOffsetVisitor::unknown();
1042 return computeImpl(GA.getAliasee());
1043}
1044
1049 return ObjectSizeOffsetVisitor::unknown();
1050
1053}
1054
1056
1057 return ObjectSizeOffsetVisitor::unknown();
1058}
1059
1060OffsetSpan ObjectSizeOffsetVisitor::findLoadOffsetRange(
1063 unsigned &ScannedInstCount) {
1064 constexpr unsigned MaxInstsToScan = 128;
1065
1068 return Where->second;
1069
1071 return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown();
1072 };
1075 };
1076
1077 do {
1079
1080 if (I.isDebugOrPseudoInst())
1081 continue;
1082
1083 if (++ScannedInstCount > MaxInstsToScan)
1085
1086 if (.mayWriteToMemory())
1087 continue;
1088
1090 AliasResult AR =
1091 Options.AA->alias(SI->getPointerOperand(), Load.getPointerOperand());
1094 continue;
1096 if (SI->getValueOperand()->getType()->isPointerTy())
1097 return Known(computeImpl(SI->getValueOperand()));
1098 else
1099 return Unknown();
1100 default:
1102 }
1103 }
1104
1107
1108 if (!Callee)
1110
1111 LibFunc TLIFn;
1112 if (!TLI || !TLI->getLibFunc(*CB->getCalledFunction(), TLIFn) ||
1113 !TLI->has(TLIFn))
1115
1116
1117 if (TLIFn != LibFunc_posix_memalign)
1119
1120 AliasResult AR =
1121 Options.AA->alias(CB->getOperand(0), Load.getPointerOperand());
1124 continue;
1126 break;
1127 default:
1129 }
1130
1131
1132
1133
1136 if (!Checked || !*Checked)
1138
1141 if ()
1143
1144 APInt CSize = C->getValue();
1147
1148 return Known({APInt(CSize.getBitWidth(), 0), CSize});
1149 }
1150
1152 } while (From-- != BB.begin());
1153
1156 PredecessorSizeOffsets.push_back(findLoadOffsetRange(
1159 if (!PredecessorSizeOffsets.back().bothKnown())
1161 }
1162
1163 if (PredecessorSizeOffsets.empty())
1165
1166 return Known(std::accumulate(
1167 PredecessorSizeOffsets.begin() + 1, PredecessorSizeOffsets.end(),
1168 PredecessorSizeOffsets.front(), [this](OffsetSpan LHS, OffsetSpan RHS) {
1169 return combineOffsetRange(LHS, RHS);
1170 }));
1171}
1172
1174 if (!Options.AA) {
1175 ++ObjectVisitorLoad;
1176 return ObjectSizeOffsetVisitor::unknown();
1177 }
1178
1180 unsigned ScannedInstCount = 0;
1185 ++ObjectVisitorLoad;
1186 return SO;
1187}
1188
1191 if (!LHS.bothKnown() || !RHS.bothKnown())
1192 return ObjectSizeOffsetVisitor::unknown();
1193
1194 switch (Options.EvalMode) {
1196 return {LHS.Before.slt(RHS.Before) ? LHS.Before : RHS.Before,
1197 LHS.After.slt(RHS.After) ? LHS.After : RHS.After};
1199 return {LHS.Before.sgt(RHS.Before) ? LHS.Before : RHS.Before,
1200 LHS.After.sgt(RHS.After) ? LHS.After : RHS.After};
1201 }
1203 return {LHS.Before.eq(RHS.Before) ? LHS.Before : APInt(),
1204 LHS.After.eq(RHS.After) ? LHS.After : APInt()};
1206 return (LHS == RHS) ? LHS : ObjectSizeOffsetVisitor::unknown();
1207 }
1209}
1210
1213 return ObjectSizeOffsetVisitor::unknown();
1215 return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(),
1216 computeImpl(*IncomingValues.begin()),
1218 return combineOffsetRange(LHS, computeImpl(VRHS));
1219 });
1220}
1221
1223 return combineOffsetRange(computeImpl(I.getTrueValue()),
1224 computeImpl(I.getFalseValue()));
1225}
1226
1230
1232 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I
1233 << '\n');
1234 return ObjectSizeOffsetVisitor::unknown();
1235}
1236
1237
1240
1244 : DL(DL), TLI(TLI), Context(Context),
1247 [&](Instruction *I) { InsertedInstructions.insert(I); })),
1248 EvalOpts(EvalOpts) {
1249
1250
1251}
1252
1254
1256 Zero = ConstantInt::get(IntTy, 0);
1257
1259
1260 if (!Result.bothKnown()) {
1261
1262
1263
1264 for (const Value *SeenVal : SeenVals) {
1266
1267 if (CacheIt != CacheMap.end() && CacheIt->second.anyKnown())
1268 CacheMap.erase(CacheIt);
1269 }
1270
1271
1272 for (Instruction *I : InsertedInstructions) {
1274 I->eraseFromParent();
1275 }
1276 }
1277
1278 SeenVals.clear();
1279 InsertedInstructions.clear();
1280 return Result;
1281}
1282
1284
1285
1286
1290
1292 if (Const.bothKnown())
1293 return SizeOffsetValue(ConstantInt::get(Context, Const.Size),
1294 ConstantInt::get(Context, Const.Offset));
1295
1296 V = V->stripPointerCasts();
1297
1298
1300 if (CacheIt != CacheMap.end())
1301 return CacheIt->second;
1302
1303
1304
1307 Builder.SetInsertPoint(I);
1308
1309
1311
1312
1313
1314
1315 if (!SeenVals.insert(V).second) {
1326
1328 } else {
1330 dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V
1331 << '\n');
1333 }
1334
1335
1336 CacheMap[V] = SizeOffsetWeakTrackingVH(Result);
1338}
1339
1341 if (.getAllocatedType()->isSized())
1343
1344
1345 assert(I.isArrayAllocation() || I.getAllocatedType()->isScalableTy());
1346
1347
1348
1349 Value *ArraySize = Builder.CreateZExtOrTrunc(
1350 I.getArraySize(),
1351 DL.getIndexType(I.getContext(), DL.getAllocaAddrSpace()));
1352 assert(ArraySize->getType() == Zero->getType() &&
1353 "Expected zero constant to have pointer index type");
1354
1355 Value *Size = Builder.CreateTypeSize(
1356 ArraySize->getType(), DL.getTypeAllocSize(I.getAllocatedType()));
1357 Size = Builder.CreateMul(Size, ArraySize);
1359}
1360
1363 if (!FnData)
1365
1366
1367 if (FnData->AllocTy == StrDupLike) {
1368
1370 }
1371
1373 FirstArg = Builder.CreateZExtOrTrunc(FirstArg, IntTy);
1374 if (FnData->SndParam < 0)
1376
1378 SecondArg = Builder.CreateZExtOrTrunc(SecondArg, IntTy);
1379 Value *Size = Builder.CreateMul(FirstArg, SecondArg);
1381}
1382
1387
1392
1402
1407
1411
1413
1414 PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1415 PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues());
1416
1417
1419
1420
1421 for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) {
1422 BasicBlock *IncomingBlock = PHI.getIncomingBlock(i);
1423 Builder.SetInsertPoint(IncomingBlock, IncomingBlock->getFirstInsertionPt());
1425
1429 InsertedInstructions.erase(OffsetPHI);
1432 InsertedInstructions.erase(SizePHI);
1434 }
1437 }
1438
1444 InsertedInstructions.erase(SizePHI);
1445 }
1450 InsertedInstructions.erase(OffsetPHI);
1451 }
1453}
1454
1458
1461 if (TrueSide == FalseSide)
1462 return TrueSide;
1463
1465 Builder.CreateSelect(I.getCondition(), TrueSide.Size, FalseSide.Size);
1467 Builder.CreateSelect(I.getCondition(), TrueSide.Offset, FalseSide.Offset);
1469}
1470
1472 LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I
1473 << '\n');
1475}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
SmallPtrSet< const BasicBlock *, 8 > VisitedBlocks
MallocFamily
Definition MemoryBuiltins.cpp:68
@ Malloc
Definition MemoryBuiltins.cpp:69
@ CPPNew
Definition MemoryBuiltins.cpp:70
@ MSVCArrayNew
Definition MemoryBuiltins.cpp:75
@ CPPNewArray
Definition MemoryBuiltins.cpp:72
@ CPPNewAligned
Definition MemoryBuiltins.cpp:71
@ MSVCNew
Definition MemoryBuiltins.cpp:74
@ VecMalloc
Definition MemoryBuiltins.cpp:76
@ KmpcAllocShared
Definition MemoryBuiltins.cpp:77
@ CPPNewArrayAligned
Definition MemoryBuiltins.cpp:73
static std::optional< APInt > combinePossibleConstantValues(std::optional< APInt > LHS, std::optional< APInt > RHS, ObjectSizeOpts::Mode EvalMode)
Definition MemoryBuiltins.cpp:730
static AllocFnKind getAllocFnKind(const Value *V)
Definition MemoryBuiltins.cpp:263
static std::optional< AllocFnsTy > getAllocationDataForFunction(const Function *Callee, AllocType AllocTy, const TargetLibraryInfo *TLI)
Returns the allocation data for the given value if it's a call to a known allocation function.
Definition MemoryBuiltins.cpp:177
static std::optional< AllocFnsTy > getAllocationData(const Value *V, AllocType AllocTy, const TargetLibraryInfo *TLI)
Definition MemoryBuiltins.cpp:219
std::optional< FreeFnsTy > getFreeFunctionDataForFunction(const Function *Callee, const LibFunc TLIFn)
Definition MemoryBuiltins.cpp:491
static bool checkFnAllocKind(const Value *V, AllocFnKind Wanted)
Definition MemoryBuiltins.cpp:276
StringRef mangledNameForMallocFamily(const MallocFamily &Family)
Definition MemoryBuiltins.cpp:80
static std::optional< AllocFnsTy > getAllocationSize(const CallBase *CB, const TargetLibraryInfo *TLI)
Definition MemoryBuiltins.cpp:236
static bool CheckedZextOrTrunc(APInt &I, unsigned IntTyBits)
When we're compiling N-bit code, and the user uses parameters that are greater than N bits (e....
Definition MemoryBuiltins.cpp:355
static std::optional< APInt > aggregatePossibleConstantValuesImpl(const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned BitWidth, unsigned recursionDepth)
Definition MemoryBuiltins.cpp:741
static const std::pair< LibFunc, FreeFnsTy > FreeFnData[]
Definition MemoryBuiltins.cpp:458
static const Function * getCalledFunction(const Value *V)
Definition MemoryBuiltins.cpp:159
static cl::opt< unsigned > ObjectSizeOffsetVisitorMaxVisitInstructions("object-size-offset-visitor-max-visit-instructions", cl::desc("Maximum number of instructions for ObjectSizeOffsetVisitor to " "look at"), cl::init(100))
static const std::pair< LibFunc, AllocFnsTy > AllocationFnData[]
Definition MemoryBuiltins.cpp:118
AllocType
Definition MemoryBuiltins.cpp:59
@ MallocLike
Definition MemoryBuiltins.cpp:61
@ AnyAlloc
Definition MemoryBuiltins.cpp:65
@ AllocLike
Definition MemoryBuiltins.cpp:64
@ StrDupLike
Definition MemoryBuiltins.cpp:62
@ OpNewLike
Definition MemoryBuiltins.cpp:60
@ MallocOrOpNewLike
Definition MemoryBuiltins.cpp:63
static APInt getSizeWithOverflow(const SizeOffsetAPInt &Data)
Definition MemoryBuiltins.cpp:567
static std::optional< APInt > aggregatePossibleConstantValues(const Value *V, ObjectSizeOpts::Mode EvalMode, unsigned BitWidth)
Definition MemoryBuiltins.cpp:775
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
@ NoAlias
The two locations do not alias at all.
@ MustAlias
The two locations precisely alias each other.
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM_ABI uint64_t getValueAsInt() const
Return the attribute's value as an integer.
LLVM_ABI std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
InstListType::iterator iterator
Instruction iterators...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
Value * getArgOperand(unsigned i) const
LLVM_ABI Value * getArgOperandWithAttribute(Attribute::AttrKind Kind) const
If one of the arguments has the specified attribute, returns its operand value.
unsigned arg_size() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
A constant pointer value that points to null.
PointerType * getType() const
Specialize the getType() method to always return an PointerType, which reduces the amount of casting ...
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Class to represent function types.
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Type * getParamType(unsigned i) const
Parameter type accessors.
Type * getReturnType() const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
const Constant * getAliasee() const
bool hasExternalWeakLinkage() const
LLVM_ABI bool isInterposable() const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
Type * getValueType() const
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void visit(Iterator Start, Iterator End)
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This class represents a cast from an integer to a pointer.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Evaluate the size and offset of an object pointed to by a Value*.
LLVM_ABI SizeOffsetValue visitExtractValueInst(ExtractValueInst &I)
Definition MemoryBuiltins.cpp:1389
LLVM_ABI SizeOffsetValue visitExtractElementInst(ExtractElementInst &I)
Definition MemoryBuiltins.cpp:1384
LLVM_ABI SizeOffsetValue compute(Value *V)
Definition MemoryBuiltins.cpp:1253
LLVM_ABI SizeOffsetValue visitInstruction(Instruction &I)
Definition MemoryBuiltins.cpp:1471
LLVM_ABI ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts EvalOpts={})
Definition MemoryBuiltins.cpp:1241
LLVM_ABI SizeOffsetValue visitLoadInst(LoadInst &I)
Definition MemoryBuiltins.cpp:1408
LLVM_ABI SizeOffsetValue visitGEPOperator(GEPOperator &GEP)
Definition MemoryBuiltins.cpp:1393
LLVM_ABI SizeOffsetValue visitIntToPtrInst(IntToPtrInst &)
Definition MemoryBuiltins.cpp:1403
LLVM_ABI SizeOffsetValue visitPHINode(PHINode &PHI)
Definition MemoryBuiltins.cpp:1412
LLVM_ABI SizeOffsetValue visitCallBase(CallBase &CB)
Definition MemoryBuiltins.cpp:1361
LLVM_ABI SizeOffsetValue visitSelectInst(SelectInst &I)
Definition MemoryBuiltins.cpp:1455
LLVM_ABI SizeOffsetValue visitAllocaInst(AllocaInst &I)
Definition MemoryBuiltins.cpp:1340
static SizeOffsetValue unknown()
Evaluate the size and offset of an object pointed to by a Value* statically.
LLVM_ABI OffsetSpan visitSelectInst(SelectInst &I)
Definition MemoryBuiltins.cpp:1222
LLVM_ABI OffsetSpan visitExtractValueInst(ExtractValueInst &I)
Definition MemoryBuiltins.cpp:1034
LLVM_ABI OffsetSpan visitConstantPointerNull(ConstantPointerNull &)
Definition MemoryBuiltins.cpp:1016
LLVM_ABI OffsetSpan visitExtractElementInst(ExtractElementInst &I)
Definition MemoryBuiltins.cpp:1030
LLVM_ABI OffsetSpan visitGlobalVariable(GlobalVariable &GV)
Definition MemoryBuiltins.cpp:1045
LLVM_ABI OffsetSpan visitCallBase(CallBase &CB)
Definition MemoryBuiltins.cpp:994
LLVM_ABI OffsetSpan visitIntToPtrInst(IntToPtrInst &)
Definition MemoryBuiltins.cpp:1055
LLVM_ABI OffsetSpan visitAllocaInst(AllocaInst &I)
Definition MemoryBuiltins.cpp:954
LLVM_ABI ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts Options={})
Definition MemoryBuiltins.cpp:800
LLVM_ABI OffsetSpan visitLoadInst(LoadInst &I)
Definition MemoryBuiltins.cpp:1173
LLVM_ABI OffsetSpan visitPHINode(PHINode &)
Definition MemoryBuiltins.cpp:1211
LLVM_ABI OffsetSpan visitGlobalAlias(GlobalAlias &GA)
Definition MemoryBuiltins.cpp:1039
LLVM_ABI OffsetSpan visitInstruction(Instruction &I)
Definition MemoryBuiltins.cpp:1231
LLVM_ABI SizeOffsetAPInt compute(Value *V)
Definition MemoryBuiltins.cpp:809
LLVM_ABI OffsetSpan visitUndefValue(UndefValue &)
Definition MemoryBuiltins.cpp:1227
LLVM_ABI OffsetSpan visitArgument(Argument &A)
Definition MemoryBuiltins.cpp:982
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
op_range incoming_values()
LLVM_ABI Value * hasConstantValue() const
If the specified PHI node always merges together the same value, return the value,...
unsigned getNumIncomingValues() const
Return the number of incoming edges.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
This class represents the LLVM 'select' instruction.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
TargetFolder - Create constants with target dependent folding.
Provides information about what library functions are available for the current target.
bool has(LibFunc F) const
Tests whether a library function is available.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getZero()
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isVoidTy() const
Return true if this is 'void'.
'undef' values are things that do not have specified contents.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
Definition MemoryBuiltins.cpp:428
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)
Return true if this is a call to an allocation function that does not have side effects that we are r...
Definition MemoryBuiltins.cpp:330
LLVM_ABI std::optional< StringRef > getAllocationFamily(const Value *I, const TargetLibraryInfo *TLI)
If a function is part of an allocation family (e.g.
Definition MemoryBuiltins.cpp:503
LLVM_ABI Value * lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL, const TargetLibraryInfo *TLI, bool MustSucceed)
Try to turn a call to @llvm.objectsize into an integer value of the given Type.
Definition MemoryBuiltins.cpp:645
LLVM_ABI Value * getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI)
Gets the alignment argument for an aligned_alloc-like function, using either built-in knowledge based...
Definition MemoryBuiltins.cpp:341
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
LLVM_ABI bool isLibFreeFunction(const Function *F, const LibFunc TLIFn)
isLibFreeFunction - Returns true if the function is a builtin free()
Definition MemoryBuiltins.cpp:529
LLVM_ABI Value * getReallocatedOperand(const CallBase *CB)
If this is a call to a realloc function, return the reallocated operand.
Definition MemoryBuiltins.cpp:324
LLVM_ABI std::optional< TypeSize > getBaseObjectSize(const Value *Ptr, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Like getObjectSize(), but only returns the size of base objects (like allocas, global variables and a...
Definition MemoryBuiltins.cpp:592
LLVM_ABI bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates memory (either malloc,...
Definition MemoryBuiltins.cpp:313
LLVM_ABI bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Compute the size of the object pointed by Ptr.
Definition MemoryBuiltins.cpp:581
LLVM_ABI Value * emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL, User *GEP, bool NoAssumptions=false)
Given a getelementptr instruction/constantexpr, emit the code necessary to compute the offset from th...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
LLVM_ABI uint64_t GetStringLength(const Value *V, unsigned CharSize=8)
If we can compute the length of the string pointed to by the specified pointer, return 'len+1'.
LLVM_ABI bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates memory similar to malloc or...
Definition MemoryBuiltins.cpp:306
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isReallocLikeFn(const Function *F)
Tests if a function is a call or invoke to a library function that reallocates memory (e....
Definition MemoryBuiltins.cpp:320
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
Definition MemoryBuiltins.cpp:548
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
auto predecessors(const MachineBasicBlock *BB)
LLVM_ABI bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...
Definition MemoryBuiltins.cpp:287
LLVM_ABI std::optional< APInt > getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, function_ref< const Value *(const Value *)> Mapper=[](const Value *V) { return V;})
Return the size of the requested allocation.
Definition MemoryBuiltins.cpp:367
LLVM_ABI std::optional< bool > isImpliedByDomCondition(const Value *Cond, const Instruction *ContextI, const DataLayout &DL)
Return the boolean condition value in the context of the given instruction if it is known based on do...
LLVM_ABI bool isNewLikeFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates memory via new.
Definition MemoryBuiltins.cpp:300
Definition MemoryBuiltins.cpp:104
MallocFamily Family
Definition MemoryBuiltins.cpp:112
int FstParam
Definition MemoryBuiltins.cpp:108
int SndParam
Definition MemoryBuiltins.cpp:108
int AlignParam
Definition MemoryBuiltins.cpp:110
unsigned NumParams
Definition MemoryBuiltins.cpp:106
AllocType AllocTy
Definition MemoryBuiltins.cpp:105
Definition MemoryBuiltins.cpp:451
MallocFamily Family
Definition MemoryBuiltins.cpp:454
unsigned NumParams
Definition MemoryBuiltins.cpp:452
This struct is a compact representation of a valid (non-zero power of two) alignment.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Various options to control the behavior of getObjectSize.
bool NullIsUnknownSize
If this is true, null pointers in address space 0 will be treated as though they can't be evaluated.
Mode EvalMode
How we want to evaluate this object's size.
AAResults * AA
If set, used for more accurate evaluation.
bool RoundToAlign
Whether to round the result up to the alignment of allocas, byval arguments, and global variables.
Mode
Controls how we handle conditional statements with unknown conditions.
@ ExactUnderlyingSizeAndOffset
All branches must be known and have the same underlying size and offset to be merged.
@ Max
Same as Min, except we pick the maximum size of all of the branches.
@ Min
Evaluate all branches of an unknown condition.
@ ExactSizeFromOffset
All branches must be known and have the same size, starting from the offset, to be merged.
OffsetSpan - Used internally by ObjectSizeOffsetVisitor.
APInt After
Number of allocated bytes before this point.
SizeOffsetAPInt - Used by ObjectSizeOffsetVisitor, which works with APInts.
SizeOffsetWeakTrackingVH - Used by ObjectSizeOffsetEvaluator in a DenseMap.