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 (Data.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

662 EvalOptions.AA = AA;

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(

835 DL, Offset, true, true);

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 (P.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 (I.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 (I.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 (C)

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 (I.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.