LLVM: lib/Transforms/IPO/LowerTypeTests.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

80#include

81#include

82#include

83#include

84#include

85#include <system_error>

86#include

87#include

88

89using namespace llvm;

91

92#define DEBUG_TYPE "lowertypetests"

93

94STATISTIC(ByteArraySizeBits, "Byte array size in bits");

95STATISTIC(ByteArraySizeBytes, "Byte array size in bytes");

96STATISTIC(NumByteArraysCreated, "Number of byte arrays created");

97STATISTIC(NumTypeTestCallsLowered, "Number of type test calls lowered");

98STATISTIC(NumTypeIdDisjointSets, "Number of disjoint sets of type identifiers");

99

101 "lowertypetests-avoid-reuse",

102 cl::desc("Try to avoid reuse of byte array addresses using aliases"),

104

106 "lowertypetests-summary-action",

107 cl::desc("What to do with the summary when running this pass"),

110 "Import typeid resolutions from summary and globals"),

112 "Export typeid resolutions to summary and globals")),

114

116 "lowertypetests-read-summary",

117 cl::desc("Read summary from given YAML file before running pass"),

119

121 "lowertypetests-write-summary",

122 cl::desc("Write summary to given YAML file after running pass"),

124

127 cl::desc("Simply drop type test sequences"),

129 "Do not drop any type tests"),

130 clEnumValN(DropTestKind::Assume, "assume",

131 "Drop type test assume sequences"),

133 "Drop all type test sequences")),

135

138 return false;

139

141 return false;

142

144 if (BitOffset >= BitSize)

145 return false;

146

147 return Bits.count(BitSize - 1 - BitOffset);

148}

149

151 OS << "offset " << ByteOffset << " size " << BitSize << " align "

153

155 OS << " all-ones\n";

156 return;

157 }

158

159 OS << " { ";

161 OS << B << ' ';

162 OS << "}\n";

163}

164

168

169

170

171

172

173

178 }

179

182

184 if (Mask != 0)

186

187

188

192

193

194

195

197 }

198

199 return BSI;

200}

201

203

205 std::vector<uint64_t> &Fragment = Fragments.back();

207

208 for (auto ObjIndex : F) {

210 if (OldFragmentIndex == 0) {

211

212

213 Fragment.push_back(ObjIndex);

214 } else {

215

216

217

218

219

220 std::vector<uint64_t> &OldFragment = Fragments[OldFragmentIndex];

222 OldFragment.clear();

223 }

224 }

225

226

227 for (uint64_t ObjIndex : Fragment)

229}

230

234

235 unsigned Bit = 0;

238 Bit = I;

239

240 AllocByteOffset = BitAllocs[Bit];

241

242

243 unsigned ReqSize = AllocByteOffset + BitSize;

245 if (Bytes.size() < ReqSize)

246 Bytes.resize(ReqSize);

247

248

249 AllocMask = 1 << Bit;

251 Bytes[AllocByteOffset + B] |= AllocMask;

252}

253

255 if (F->isDeclarationForLinker())

256 return false;

258 F->getParent()->getModuleFlag("CFI Canonical Jump Tables"));

259 if (!CI || !CI->isZero())

260 return true;

261 return F->hasFnAttribute("cfi-canonical-jump-table");

262}

263

264namespace {

265

266struct ByteArrayInfo {

267 std::set<uint64_t> Bits;

271 uint8_t *MaskPtr = nullptr;

272};

273

274

275

276

277

278

279class GlobalTypeMember final : TrailingObjects<GlobalTypeMember, MDNode *> {

281

283 size_t NTypes;

284

285

286

287

288

289

290 bool IsJumpTableCanonical;

291

292

293

294 bool IsExported;

295

296public:

298 bool IsJumpTableCanonical, bool IsExported,

300 auto *GTM = static_cast<GlobalTypeMember *>(Alloc.Allocate(

301 totalSizeToAlloc<MDNode *>(Types.size()), alignof(GlobalTypeMember)));

302 GTM->GO = GO;

303 GTM->NTypes = Types.size();

304 GTM->IsJumpTableCanonical = IsJumpTableCanonical;

305 GTM->IsExported = IsExported;

306 llvm::copy(Types, GTM->getTrailingObjects());

307 return GTM;

308 }

309

310 GlobalObject *getGlobal() const {

311 return GO;

312 }

313

315 return IsJumpTableCanonical;

316 }

317

318 bool isExported() const {

319 return IsExported;

320 }

321

322 ArrayRef<MDNode *> types() const { return getTrailingObjects(NTypes); }

323};

324

325struct ICallBranchFunnel final

326 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {

329 unsigned UniqueId) {

330 auto *Call = static_cast<ICallBranchFunnel *>(

331 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.size()),

332 alignof(ICallBranchFunnel)));

333 Call->CI = CI;

334 Call->UniqueId = UniqueId;

335 Call->NTargets = Targets.size();

338 }

339

340 CallInst *CI;

342 return getTrailingObjects(NTargets);

343 }

344

345 unsigned UniqueId;

346

347private:

348 size_t NTargets;

349};

350

351struct ScopedSaveAliaseesAndUsed {

354 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;

355 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;

356

357

358

359

360 void collectAndEraseUsedFunctions(Module &M,

361 SmallVectorImpl<GlobalValue *> &Vec,

362 bool CompilerUsed) {

364 if (!GV)

365 return;

366

367

368

369 GV->eraseFromParent();

370 auto NonFuncBegin =

371 std::stable_partition(Vec.begin(), Vec.end(), [](GlobalValue *GV) {

372 return isa(GV);

373 });

374 if (CompilerUsed)

376 else

379 }

380

381 ScopedSaveAliaseesAndUsed(Module &M) : M(M) {

382

383

384

385

386

387

388

389

390

391

392

393

394 collectAndEraseUsedFunctions(M, Used, false);

395 collectAndEraseUsedFunctions(M, CompilerUsed, true);

396

397 for (auto &GA : M.aliases()) {

398

399

401 FunctionAliases.push_back({&GA, F});

402 }

403

404 for (auto &GI : M.ifuncs())

406 ResolverIFuncs.push_back({&GI, F});

407 }

408

409 ~ScopedSaveAliaseesAndUsed() {

412

413 for (auto P : FunctionAliases)

414 P.first->setAliasee(P.second);

415

416 for (auto P : ResolverIFuncs) {

417

418

419

420 P.first->setResolver(P.second);

421 }

422 }

423};

424

425class LowerTypeTestsModule {

427

428 ModuleSummaryIndex *ExportSummary;

429 const ModuleSummaryIndex *ImportSummary;

430

431

433

437

438

439

440

441 bool CanUseArmJumpTable = false, CanUseThumbBWJumpTable = false;

442

443

444 int HasBranchTargetEnforcement = -1;

445

446 IntegerType *Int1Ty = Type::getInt1Ty(M.getContext());

447 IntegerType *Int8Ty = Type::getInt8Ty(M.getContext());

448 PointerType *PtrTy = PointerType::getUnqual(M.getContext());

449 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(M.getContext()), 0);

450 IntegerType *Int32Ty = Type::getInt32Ty(M.getContext());

451 IntegerType *Int64Ty = Type::getInt64Ty(M.getContext());

452 IntegerType *IntPtrTy = M.getDataLayout().getIntPtrType(M.getContext(), 0);

453

454

455 uint64_t IndirectIndex = 1;

456

457

458

459

460 struct TypeIdUserInfo {

461 std::vector<CallInst *> CallSites;

462 bool IsExported = false;

463 };

464 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;

465

466

467

468

469

470 struct TypeIdLowering {

472

473

474

476

477

478

480

481

482

484

485

487

488

490

491

493 };

494

495 std::vector ByteArrayInfos;

496

497 Function *WeakInitializerFn = nullptr;

498

499 GlobalVariable *GlobalAnnotation;

500 DenseSet<Value *> FunctionAnnotations;

501

502 bool shouldExportConstantsAsAbsoluteSymbols();

503 uint8_t *exportTypeId(StringRef TypeId, const TypeIdLowering &TIL);

504 TypeIdLowering importTypeId(StringRef TypeId);

505 void importTypeTest(CallInst *CI);

507

508 ByteArrayInfo *createByteArray(const BitSetInfo &BSI);

509 void allocateByteArrays();

510 Value *createBitSetTest(IRBuilder<> &B, const TypeIdLowering &TIL,

511 Value *BitOffset);

512 void lowerTypeTestCalls(

514 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);

515 Value *lowerTypeTestCall(Metadata *TypeId, CallInst *CI,

516 const TypeIdLowering &TIL);

517

522 bool hasBranchTargetEnforcement();

523 unsigned getJumpTableEntrySize(Triple::ArchType JumpTableArch);

524 InlineAsm *createJumpTableEntryAsm(Triple::ArchType JumpTableArch);

525 void verifyTypeMDNode(GlobalObject *GO, MDNode *Type);

532 void

536

537 void replaceWeakDeclarationWithJumpTablePtr(Function *F, Constant *JT,

538 bool IsJumpTableCanonical);

539 void moveInitializerToModuleConstructor(GlobalVariable *GV);

540 void findGlobalVariableUsersOf(Constant *C,

541 SmallSetVector<GlobalVariable *, 8> &Out);

542

545

546

547

548

549

550

551 void replaceCfiUses(Function *Old, Value *New, bool IsJumpTableCanonical);

552

553

554

555 void replaceDirectCalls(Value *Old, Value *New);

556

557 bool isFunctionAnnotation(Value *V) const {

558 return FunctionAnnotations.contains(V);

559 }

560

561 void maybeReplaceComdat(Function *F, StringRef OriginalName);

562

563public:

565 ModuleSummaryIndex *ExportSummary,

566 const ModuleSummaryIndex *ImportSummary,

568

569 bool lower();

570

571

572

574};

575}

576

577

583

584

585

587 Value *BitOffset) {

589 unsigned BitWidth = BitsType->getBitWidth();

590

591 BitOffset = B.CreateZExtOrTrunc(BitOffset, BitsType);

592 Value *BitIndex =

593 B.CreateAnd(BitOffset, ConstantInt::get(BitsType, BitWidth - 1));

594 Value *BitMask = B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);

595 Value *MaskedBits = B.CreateAnd(Bits, BitMask);

596 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));

597}

598

599ByteArrayInfo *LowerTypeTestsModule::createByteArray(const BitSetInfo &BSI) {

600

601

602

603 auto ByteArrayGlobal = new GlobalVariable(

605 auto MaskGlobal = new GlobalVariable(M, Int8Ty, true,

607

608 ByteArrayInfos.emplace_back();

609 ByteArrayInfo *BAI = &ByteArrayInfos.back();

610

611 BAI->Bits = BSI.Bits;

612 BAI->BitSize = BSI.BitSize;

613 BAI->ByteArray = ByteArrayGlobal;

614 BAI->MaskGlobal = MaskGlobal;

615 return BAI;

616}

617

618void LowerTypeTestsModule::allocateByteArrays() {

620 [](const ByteArrayInfo &BAI1, const ByteArrayInfo &BAI2) {

621 return BAI1.BitSize > BAI2.BitSize;

622 });

623

624 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());

625

627 for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) {

628 ByteArrayInfo *BAI = &ByteArrayInfos[I];

629

630 uint8_t Mask;

631 BAB.allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[I], Mask);

632

636 if (BAI->MaskPtr)

637 *BAI->MaskPtr = Mask;

638 }

639

642 new GlobalVariable(M, ByteArrayConst->getType(), true,

644

645 for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) {

646 ByteArrayInfo *BAI = &ByteArrayInfos[I];

647

648 Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0),

649 ConstantInt::get(IntPtrTy, ByteArrayOffsets[I])};

651 ByteArrayConst->getType(), ByteArray, Idxs);

652

653

654

655

660 }

661

665 ByteArraySizeBytes = BAB.Bytes.size();

666}

667

668

669

671 const TypeIdLowering &TIL,

672 Value *BitOffset) {

674

675

677 } else {

680

681

682

683

685 "bits_use", ByteArray, &M);

686 }

687

688 Value *ByteAddr = B.CreateGEP(Int8Ty, ByteArray, BitOffset);

689 Value *Byte = B.CreateLoad(Int8Ty, ByteAddr);

690

691 Value *ByteAndMask =

693 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));

694 }

695}

696

701 GV->getMetadata(LLVMContext::MD_type, Types);

703 if (Type->getOperand(1) != TypeId)

704 continue;

708 ->getZExtValue();

709 if (COffset == Offset)

710 return true;

711 }

712 return false;

713 }

714

716 APInt APOffset(DL.getIndexSizeInBits(0), 0);

717 bool Result = GEP->accumulateConstantOffset(DL, APOffset);

718 if (!Result)

719 return false;

722 }

723

725 if (Op->getOpcode() == Instruction::BitCast)

727

728 if (Op->getOpcode() == Instruction::Select)

731 }

732

733 return false;

734}

735

736

737

738Value *LowerTypeTestsModule::lowerTypeTestCall(Metadata *TypeId, CallInst *CI,

739 const TypeIdLowering &TIL) {

740

742 return nullptr;

745

747 const DataLayout &DL = M.getDataLayout();

750

752

754

755 Value *PtrAsInt = B.CreatePtrToInt(Ptr, IntPtrTy);

756

757 Constant *OffsetedGlobalAsInt =

760 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);

761

762

763

764

765

766 Value *PtrOffset = B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);

767

768

769

770

771

772

773

774

775

776 Value *BitOffset = B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr,

777 {PtrOffset, PtrOffset, TIL.AlignLog2});

778

779 Value *OffsetInRange = B.CreateICmpULE(BitOffset, TIL.SizeM1);

780

781

783 return OffsetInRange;

784

785

786

787

788

796 Br->getMetadata(LLVMContext::MD_prof));

798

799

800 for (auto &Phi : Else->phis())

801 Phi.addIncoming(Phi.getIncomingValueForBlock(Then), InitialBB);

802

804 return createBitSetTest(ThenB, TIL, BitOffset);

805 }

806

807 MDBuilder MDB(M.getContext());

809 MDB.createLikelyBranchWeights()));

810

811

812

813 Value *Bit = createBitSetTest(ThenB, TIL, BitOffset);

814

815

816

817

818 B.SetInsertPoint(CI);

819 PHINode *P = B.CreatePHI(Int1Ty, 2);

820 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);

821 P->addIncoming(Bit, ThenB.GetInsertBlock());

822 return P;

823}

824

825

826

827void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(

829

830

831

832

833

834 std::vector<Constant *> GlobalInits;

835 const DataLayout &DL = M.getDataLayout();

836 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;

838 uint64_t CurOffset = 0;

839 uint64_t DesiredPadding = 0;

840 for (GlobalTypeMember *G : Globals) {

842 Align Alignment =

843 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());

844 MaxAlign = std::max(MaxAlign, Alignment);

845 uint64_t GVOffset = alignTo(CurOffset + DesiredPadding, Alignment);

846 GlobalLayout[G] = GVOffset;

847 if (GVOffset != 0) {

848 uint64_t Padding = GVOffset - CurOffset;

849 GlobalInits.push_back(

851 }

852

853 GlobalInits.push_back(GV->getInitializer());

854 uint64_t InitSize = DL.getTypeAllocSize(GV->getValueType());

855 CurOffset = GVOffset + InitSize;

856

857

858 DesiredPadding = NextPowerOf2(InitSize - 1) - InitSize;

859

860

861

862

863

864 if (DesiredPadding > 32)

865 DesiredPadding = alignTo(InitSize, 32) - InitSize;

866 }

867

869 auto *CombinedGlobal =

870 new GlobalVariable(M, NewInit->getType(), true,

872 CombinedGlobal->setAlignment(MaxAlign);

873

875 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);

876

877

878

879

880 for (unsigned I = 0; I != Globals.size(); ++I) {

882

883

884 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),

885 ConstantInt::get(Int32Ty, I * 2)};

887 NewInit->getType(), CombinedGlobal, CombinedGlobalIdxs);

889 GlobalAlias *GAlias =

891 "", CombinedGlobalElemPtr, &M);

896 }

897}

898

899bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {

902}

903

904

905

906

907

908

909

910

911

912uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,

913 const TypeIdLowering &TIL) {

914 TypeTestResolution &TTRes =

916 TTRes.TheKind = TIL.TheKind;

917

918 auto ExportGlobal = [&](StringRef Name, Constant *C) {

919 GlobalAlias *GA =

921 "__typeid_" + TypeId + "_" + Name, C, &M);

923 };

924

925 auto ExportConstant = [&](StringRef Name, uint64_t &Storage, Constant *C) {

926 if (shouldExportConstantsAsAbsoluteSymbols())

928 else

930 };

931

933 ExportGlobal("global_addr", TIL.OffsetedGlobal);

934

938 ExportConstant("align", TTRes.AlignLog2, TIL.AlignLog2);

939 ExportConstant("size_m1", TTRes.SizeM1, TIL.SizeM1);

940

941 uint64_t BitSize = cast(TIL.SizeM1)->getZExtValue() + 1;

944 else

946 }

947

949 ExportGlobal("byte_array", TIL.TheByteArray);

950 if (shouldExportConstantsAsAbsoluteSymbols())

951 ExportGlobal("bit_mask", TIL.BitMask);

952 else

954 }

955

957 ExportConstant("inline_bits", TTRes.InlineBits, TIL.InlineBits);

958

959 return nullptr;

960}

961

962LowerTypeTestsModule::TypeIdLowering

963LowerTypeTestsModule::importTypeId(StringRef TypeId) {

964 const TypeIdSummary *TidSummary = ImportSummary->getTypeIdSummary(TypeId);

965 if (!TidSummary)

966 return {};

967 const TypeTestResolution &TTRes = TidSummary->TTRes;

968

969 TypeIdLowering TIL;

970 TIL.TheKind = TTRes.TheKind;

971

972 auto ImportGlobal = [&](StringRef Name) {

973

974

975 GlobalVariable *GV = M.getOrInsertGlobal(

976 ("__typeid_" + TypeId + "_" + Name).str(), Int8Arr0Ty);

978 return GV;

979 };

980

981 auto ImportConstant = [&](StringRef Name, uint64_t Const, unsigned AbsWidth,

983 if (!shouldExportConstantsAsAbsoluteSymbols()) {

985 ConstantInt::get(isa(Ty) ? Ty : Int64Ty, Const);

988 return C;

989 }

990

991 Constant *C = ImportGlobal(Name);

995 if (GV->getMetadata(LLVMContext::MD_absolute_symbol))

996 return C;

997

998 auto SetAbsRange = [&](uint64_t Min, uint64_t Max) {

1001 GV->setMetadata(LLVMContext::MD_absolute_symbol,

1003 };

1004 if (AbsWidth == IntPtrTy->getBitWidth())

1005 SetAbsRange(~0ull, ~0ull);

1006 else

1007 SetAbsRange(0, 1ull << AbsWidth);

1008 return C;

1009 };

1010

1012 auto *GV = ImportGlobal("global_addr");

1013

1014

1015

1016

1017

1018

1019

1020

1021

1022

1023

1025 TIL.OffsetedGlobal = GV;

1026 }

1027

1031 TIL.AlignLog2 = ImportConstant("align", TTRes.AlignLog2, 8, IntPtrTy);

1032 TIL.SizeM1 =

1034 }

1035

1037 TIL.TheByteArray = ImportGlobal("byte_array");

1038 TIL.BitMask = ImportConstant("bit_mask", TTRes.BitMask, 8, PtrTy);

1039 }

1040

1042 TIL.InlineBits = ImportConstant(

1045

1046 return TIL;

1047}

1048

1049void LowerTypeTestsModule::importTypeTest(CallInst *CI) {

1051 if (!TypeIdMDVal)

1052 report_fatal_error("Second argument of llvm.type.test must be metadata");

1053

1055

1056

1057

1058 if (!TypeIdStr)

1059 return;

1060

1061 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());

1062 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);

1063 if (Lowered) {

1066 }

1067}

1068

1069void LowerTypeTestsModule::maybeReplaceComdat(Function *F,

1070 StringRef OriginalName) {

1071

1072

1073

1074

1075 if (F->hasComdat() && ObjectFormat == Triple::COFF &&

1076 F->getComdat()->getName() == OriginalName) {

1077 Comdat *OldComdat = F->getComdat();

1078 Comdat *NewComdat = M.getOrInsertComdat(F->getName());

1079 for (GlobalObject &GO : M.global_objects()) {

1080 if (GO.getComdat() == OldComdat)

1082 }

1083 }

1084}

1085

1086

1087

1088void LowerTypeTestsModule::importFunction(Function *F,

1090 assert(F->getType()->getAddressSpace() == 0);

1091

1093 std::string Name = std::string(F->getName());

1094

1096

1097

1098 if (F->isDSOLocal()) {

1101 F->getAddressSpace(),

1102 Name + ".cfi", &M);

1104 replaceDirectCalls(F, RealF);

1105 }

1106 return;

1107 }

1108

1111

1112

1114 F->getAddressSpace(), Name + ".cfi_jt", &M);

1116 } else {

1117 F->setName(Name + ".cfi");

1118 maybeReplaceComdat(F, Name);

1120 F->getAddressSpace(), Name, &M);

1123

1124

1125

1126

1127 for (auto &U : F->uses()) {

1129 std::string AliasName = A->getName().str() + ".cfi";

1132 F->getAddressSpace(), "", &M);

1134 A->replaceAllUsesWith(AliasDecl);

1135 A->setName(AliasName);

1136 }

1137 }

1138 }

1139

1140 if (F->hasExternalWeakLinkage())

1142 else

1144

1145

1146

1147 F->setVisibility(Visibility);

1148}

1149

1150static auto

1154

1155 for (Metadata *TypeId : TypeIds)

1156 OffsetsByTypeID[TypeId];

1157 for (const auto &[Mem, MemOff] : GlobalLayout) {

1159 auto It = OffsetsByTypeID.find(Type->getOperand(1));

1160 if (It == OffsetsByTypeID.end())

1161 continue;

1165 ->getZExtValue();

1166 It->second.push_back(MemOff + Offset);

1167 }

1168 }

1169

1172 for (Metadata *TypeId : TypeIds) {

1176 dbgs() << MDS->getString() << ": ";

1177 else

1178 dbgs() << ": ";

1179 BitSets.back().second.print(dbgs());

1180 });

1181 }

1182

1183 return BitSets;

1184}

1185

1186void LowerTypeTestsModule::lowerTypeTestCalls(

1188 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {

1189

1190 for (const auto &[TypeId, BSI] : buildBitSets(TypeIds, GlobalLayout)) {

1191 ByteArrayInfo *BAI = nullptr;

1192 TypeIdLowering TIL;

1193

1194 uint64_t GlobalOffset =

1197 Int8Ty, CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),

1198 TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.AlignLog2);

1199 TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.BitSize - 1);

1202 : TypeTestResolution::AllOnes;

1205 uint64_t InlineBits = 0;

1206 for (auto Bit : BSI.Bits)

1207 InlineBits |= uint64_t(1) << Bit;

1208 if (InlineBits == 0)

1210 else

1211 TIL.InlineBits = ConstantInt::get(

1212 (BSI.BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);

1213 } else {

1215 ++NumByteArraysCreated;

1216 BAI = createByteArray(BSI);

1217 TIL.TheByteArray = BAI->ByteArray;

1218 TIL.BitMask = BAI->MaskGlobal;

1219 }

1220

1221 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];

1222

1223 if (TIUI.IsExported) {

1224 uint8_t *MaskPtr = exportTypeId(cast(TypeId)->getString(), TIL);

1225 if (BAI)

1226 BAI->MaskPtr = MaskPtr;

1227 }

1228

1229

1230 for (CallInst *CI : TIUI.CallSites) {

1231 ++NumTypeTestCallsLowered;

1232 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);

1233 if (Lowered) {

1236 }

1237 }

1238 }

1239}

1240

1241void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *Type) {

1242 if (Type->getNumOperands() != 2)

1243 report_fatal_error("All operands of type metadata must have 2 elements");

1244

1249 "A member of a type identifier may not have an explicit section");

1250

1251

1252

1253

1254

1256 if (!OffsetConstMD)

1259 if (!OffsetInt)

1261}

1262

1270

1271bool LowerTypeTestsModule::hasBranchTargetEnforcement() {

1272 if (HasBranchTargetEnforcement == -1) {

1273

1274

1276 M.getModuleFlag("branch-target-enforcement")))

1277 HasBranchTargetEnforcement = !BTE->isZero();

1278 else

1279 HasBranchTargetEnforcement = 0;

1280 }

1281 return HasBranchTargetEnforcement;

1282}

1283

1284unsigned

1285LowerTypeTestsModule::getJumpTableEntrySize(Triple::ArchType JumpTableArch) {

1286 switch (JumpTableArch) {

1290 M.getModuleFlag("cf-protection-branch")))

1291 if (MD->getZExtValue())

1297 if (CanUseThumbBWJumpTable) {

1298 if (hasBranchTargetEnforcement())

1301 } else {

1303 }

1305 if (hasBranchTargetEnforcement())

1313 default:

1315 }

1316}

1317

1318

1319

1320

1321InlineAsm *

1322LowerTypeTestsModule::createJumpTableEntryAsm(Triple::ArchType JumpTableArch) {

1323 std::string Asm;

1324 raw_string_ostream AsmOS(Asm);

1325

1327 bool Endbr = false;

1329 M.getModuleFlag("cf-protection-branch")))

1330 Endbr = !MD->isZero();

1331 if (Endbr)

1332 AsmOS << (JumpTableArch == Triple::x86 ? "endbr32\n" : "endbr64\n");

1333 AsmOS << "jmp ${0:c}@plt\n";

1334 if (Endbr)

1335 AsmOS << ".balign 16, 0xcc\n";

1336 else

1337 AsmOS << "int3\nint3\nint3\n";

1338 } else if (JumpTableArch == Triple::arm) {

1339 AsmOS << "b $0\n";

1341 if (hasBranchTargetEnforcement())

1342 AsmOS << "bti c\n";

1343 AsmOS << "b $0\n";

1345 if (!CanUseThumbBWJumpTable) {

1346

1347

1348

1349

1350

1351

1352

1353

1354

1355

1356

1357

1358

1359

1360

1361 AsmOS << "push {r0,r1}\n"

1362 << "ldr r0, 1f\n"

1363 << "0: add r0, r0, pc\n"

1364 << "str r0, [sp, #4]\n"

1365 << "pop {r0,pc}\n"

1366 << ".balign 4\n"

1367 << "1: .word $0 - (0b + 4)\n";

1368 } else {

1369 if (hasBranchTargetEnforcement())

1370 AsmOS << "bti\n";

1371 AsmOS << "b.w $0\n";

1372 }

1375 AsmOS << "tail $0@plt\n";

1377 AsmOS << "pcalau12i t0, %pc_hi20($0)\n"

1378 << "jirl r0, t0, %pc_lo12($0)\n";

1379 } else {

1381 }

1382

1385 AsmOS.str(), "s",

1386 true);

1387}

1388

1389

1390

1391void LowerTypeTestsModule::buildBitSetsFromFunctions(

1397 buildBitSetsFromFunctionsNative(TypeIds, Functions);

1399 buildBitSetsFromFunctionsWASM(TypeIds, Functions);

1400 else

1402}

1403

1404void LowerTypeTestsModule::moveInitializerToModuleConstructor(

1405 GlobalVariable *GV) {

1406 if (WeakInitializerFn == nullptr) {

1409 false),

1411 M.getDataLayout().getProgramAddressSpace(),

1412 "__cfi_global_var_init", &M);

1416 WeakInitializerFn->setSection(

1418 ? "__TEXT,__StaticInit,regular,pure_instructions"

1419 : ".text.startup");

1420

1421

1423 }

1424

1425 IRBuilder<> IRB(WeakInitializerFn->getEntryBlock().getTerminator());

1429}

1430

1431void LowerTypeTestsModule::findGlobalVariableUsersOf(

1432 Constant *C, SmallSetVector<GlobalVariable *, 8> &Out) {

1433 for (auto *U : C->users()){

1437 findGlobalVariableUsersOf(C2, Out);

1438 }

1439}

1440

1441

1442void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(

1443 Function *F, Constant *JT, bool IsJumpTableCanonical) {

1444

1445

1446 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;

1447 findGlobalVariableUsersOf(F, GlobalVarUsers);

1448 for (auto *GV : GlobalVarUsers) {

1449 if (GV == GlobalAnnotation)

1450 continue;

1451 moveInitializerToModuleConstructor(GV);

1452 }

1453

1454

1455

1459 F->getAddressSpace(), "", &M);

1460 replaceCfiUses(F, PlaceholderFn, IsJumpTableCanonical);

1461

1463

1464 while (!PlaceholderFn->use_empty()) {

1467 assert(InsertPt && "Non-instruction users should have been eliminated");

1469 if (PN)

1470 InsertPt = PN->getIncomingBlock(U)->getTerminator();

1474 Value *Select = Builder.CreateSelect(ICmp, JT,

1476

1479

1480

1481 if (PN)

1482 PN->setIncomingValueForBlock(InsertPt->getParent(), Select);

1483 else

1485 }

1487}

1488

1490 Attribute TFAttr = F->getFnAttribute("target-features");

1494 for (StringRef Feature : Features) {

1495 if (Feature == "-thumb-mode")

1496 return false;

1497 else if (Feature == "+thumb-mode")

1498 return true;

1499 }

1500 }

1501

1503}

1504

1505

1506

1507

1508Triple::ArchType LowerTypeTestsModule::selectJumpTableArmEncoding(

1511 return Arch;

1512

1513 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {

1514

1515

1516

1518 }

1519

1520

1521 unsigned ArmCount = 0, ThumbCount = 0;

1522 for (const auto GTM : Functions) {

1523 if (!GTM->isJumpTableCanonical()) {

1524

1525

1526 ++ArmCount;

1527 continue;

1528 }

1529

1532 }

1533

1535}

1536

1537void LowerTypeTestsModule::createJumpTable(

1542

1543 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);

1544

1545

1546

1547

1548

1549 bool areAllEntriesNounwind = true;

1550 for (GlobalTypeMember *GTM : Functions) {

1552 ->hasFnAttribute(llvm::Attribute::NoUnwind)) {

1553 areAllEntriesNounwind = false;

1554 }

1555 IRB.CreateCall(JumpTableAsm, GTM->getGlobal());

1556 }

1557 IRB.CreateUnreachable();

1558

1559

1560 F->setAlignment(Align(getJumpTableEntrySize(JumpTableArch)));

1561 F->addFnAttr(Attribute::Naked);

1563 F->addFnAttr("target-features", "-thumb-mode");

1565 if (hasBranchTargetEnforcement()) {

1566

1567

1568 F->addFnAttr("target-features", "+thumb-mode,+pacbti");

1569 } else {

1570 F->addFnAttr("target-features", "+thumb-mode");

1571 if (CanUseThumbBWJumpTable) {

1572

1573

1574 F->addFnAttr("target-cpu", "cortex-a8");

1575 }

1576 }

1577 }

1578

1579

1580

1582 if (F->hasFnAttribute("branch-target-enforcement"))

1583 F->removeFnAttr("branch-target-enforcement");

1584 if (F->hasFnAttribute("sign-return-address"))

1585 F->removeFnAttr("sign-return-address");

1586 }

1588

1589

1590 F->addFnAttr("target-features", "-c,-relax");

1591 }

1592

1593

1594

1596 F->addFnAttr(Attribute::NoCfCheck);

1597

1598

1599 if (areAllEntriesNounwind)

1600 F->addFnAttr(Attribute::NoUnwind);

1601

1602

1603 F->addFnAttr(Attribute::NoInline);

1604}

1605

1606

1607

1608void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(

1610

1611

1612

1613

1614

1615

1616

1617

1618

1619

1620

1621

1622

1623

1624

1625

1626

1627

1628

1629

1630

1631

1632

1633

1634

1635

1636

1637

1638

1639

1640

1641

1642

1643

1644

1645

1646

1647

1648

1649

1650

1651

1652

1653

1654

1655

1656

1657

1658

1659

1660

1661

1662

1663

1664

1665

1666

1667

1668

1669

1670

1671

1672

1673

1674

1675

1676

1677

1678

1679

1680

1681

1682

1683

1684

1685

1687

1688

1689

1690 Triple::ArchType JumpTableArch = selectJumpTableArmEncoding(Functions);

1691

1692

1693 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;

1694 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);

1695 for (unsigned I = 0; I != Functions.size(); ++I)

1696 GlobalLayout[Functions[I]] = I * EntrySize;

1697

1700 false),

1702 M.getDataLayout().getProgramAddressSpace(),

1703 ".cfi.jumptable", &M);

1709

1710 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);

1711

1712

1713

1714 for (unsigned I = 0; I != Functions.size(); ++I) {

1716 bool IsJumpTableCanonical = Functions[I]->isJumpTableCanonical();

1717

1719 JumpTableType, JumpTable,

1721 ConstantInt::get(IntPtrTy, I)});

1722

1723 const bool IsExported = Functions[I]->isExported();

1724 if (!IsJumpTableCanonical) {

1728 F->getName() + ".cfi_jt",

1729 CombinedGlobalElemPtr, &M);

1730 if (IsExported)

1732 else

1734 }

1735

1736 if (IsExported) {

1737 if (IsJumpTableCanonical)

1739 else

1741 }

1742

1743 if (!IsJumpTableCanonical) {

1744 if (F->hasExternalWeakLinkage())

1745 replaceWeakDeclarationWithJumpTablePtr(F, CombinedGlobalElemPtr,

1746 IsJumpTableCanonical);

1747 else

1748 replaceCfiUses(F, CombinedGlobalElemPtr, IsJumpTableCanonical);

1749 } else {

1750 assert(F->getType()->getAddressSpace() == 0);

1751

1752 GlobalAlias *FAlias =

1754 CombinedGlobalElemPtr, &M);

1757 if (FAlias->hasName()) {

1758 F->setName(FAlias->getName() + ".cfi");

1759 maybeReplaceComdat(F, FAlias->getName());

1760 }

1761 replaceCfiUses(F, FAlias, IsJumpTableCanonical);

1762 if (F->hasLocalLinkage())

1764 }

1765 }

1766

1767 createJumpTable(JumpTableFn, Functions, JumpTableArch);

1768}

1769

1770

1771

1772

1773

1774

1775

1776void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(

1779

1780

1781 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;

1782

1783 for (GlobalTypeMember *GTM : Functions) {

1785

1786

1787 if (F->hasAddressTaken())

1788 continue;

1789

1790

1793 ConstantInt::get(Int64Ty, IndirectIndex))));

1794 F->setMetadata("wasm.index", MD);

1795

1796

1797 GlobalLayout[GTM] = IndirectIndex++;

1798 }

1799

1800

1801

1803 GlobalLayout);

1804}

1805

1806void LowerTypeTestsModule::buildBitSetsFromDisjointSet(

1809 DenseMap<Metadata *, uint64_t> TypeIdIndices;

1810 for (unsigned I = 0; I != TypeIds.size(); ++I)

1811 TypeIdIndices[TypeIds[I]] = I;

1812

1813

1814

1815 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.size());

1816 unsigned GlobalIndex = 0;

1817 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;

1818 for (GlobalTypeMember *GTM : Globals) {

1819 for (MDNode *Type : GTM->types()) {

1820

1821 auto I = TypeIdIndices.find(Type->getOperand(1));

1822 if (I != TypeIdIndices.end())

1823 TypeMembers[I->second].insert(GlobalIndex);

1824 }

1825 GlobalIndices[GTM] = GlobalIndex;

1826 GlobalIndex++;

1827 }

1828

1829 for (ICallBranchFunnel *JT : ICallBranchFunnels) {

1830 TypeMembers.emplace_back();

1831 std::set<uint64_t> &TMSet = TypeMembers.back();

1832 for (GlobalTypeMember *T : JT->targets())

1833 TMSet.insert(GlobalIndices[T]);

1834 }

1835

1836

1837

1839 const std::set<uint64_t> &O2) {

1840 return O1.size() < O2.size();

1841 });

1842

1843

1844

1845

1847 for (auto &&MemSet : TypeMembers)

1848 GLB.addFragment(MemSet);

1849

1850

1851 bool IsGlobalSet =

1853 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());

1854 auto OGTMI = OrderedGTMs.begin();

1855 for (auto &&F : GLB.Fragments) {

1856 for (auto &&Offset : F) {

1859 "variables and functions");

1860 *OGTMI++ = Globals[Offset];

1861 }

1862 }

1863

1864

1865 if (IsGlobalSet)

1866 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);

1867 else

1868 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);

1869}

1870

1871

1872LowerTypeTestsModule::LowerTypeTestsModule(

1874 const ModuleSummaryIndex *ImportSummary, DropTestKind DropTypeTests)

1875 : M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary),

1877 : DropTypeTests) {

1878 assert(!(ExportSummary && ImportSummary));

1879 Triple TargetTriple(M.getTargetTriple());

1880 Arch = TargetTriple.getArch();

1882 CanUseArmJumpTable = true;

1884 auto &FAM =

1887

1888 if (F.isDeclaration())

1889 continue;

1891 if (TTI.hasArmWideBranch(false))

1892 CanUseArmJumpTable = true;

1893 if (TTI.hasArmWideBranch(true))

1894 CanUseThumbBWJumpTable = true;

1895 }

1896 }

1897 OS = TargetTriple.getOS();

1898 ObjectFormat = TargetTriple.getObjectFormat();

1899

1900

1901

1902 GlobalAnnotation = M.getGlobalVariable("llvm.global.annotations");

1903 if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {

1906 FunctionAnnotations.insert_range(CA->operands());

1907 }

1908}

1909

1911 ModuleSummaryIndex Summary(false);

1912

1913

1914

1916 ExitOnError ExitOnErr("-lowertypetests-read-summary: " + ClReadSummary +

1917 ": ");

1920

1921 yaml::Input In(ReadSummaryFile->getBuffer());

1924 }

1925

1927 LowerTypeTestsModule(

1928 M, AM,

1929 ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr,

1930 ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr,

1931 DropTestKind::None)

1932 .lower();

1933

1935 ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary +

1936 ": ");

1937 std::error_code EC;

1940

1941 yaml::Output Out(OS);

1943 }

1944

1946}

1947

1950 if (Usr) {

1952 if (CB && CB->isCallee(&U))

1953 return true;

1954 }

1955 return false;

1956}

1957

1958void LowerTypeTestsModule::replaceCfiUses(Function *Old, Value *New,

1959 bool IsJumpTableCanonical) {

1960 SmallSetVector<Constant *, 4> Constants;

1962

1963

1965 continue;

1966

1967

1969 continue;

1970

1971

1972 if (isFunctionAnnotation(U.getUser()))

1973 continue;

1974

1975

1976

1979

1980

1982 continue;

1983 }

1984 }

1985

1986 U.set(New);

1987 }

1988

1989

1990 for (auto *C : Constants)

1991 C->handleOperandChange(Old, New);

1992}

1993

1994void LowerTypeTestsModule::replaceDirectCalls(Value *Old, Value *New) {

1996}

1997

1999 bool ShouldDropAll) {

2002

2005 Assume->eraseFromParent();

2006

2007

2008

2009

2010

2011

2014 return isa(U);

2015 }));

2017 }

2019 }

2020}

2021

2022bool LowerTypeTestsModule::lower() {

2025

2026 if (DropTypeTests != DropTestKind::None) {

2027 bool ShouldDropAll = DropTypeTests == DropTestKind::All;

2028 if (TypeTestFunc)

2030

2031

2032

2033 Function *PublicTypeTestFunc =

2035 if (PublicTypeTestFunc)

2036 dropTypeTests(M, *PublicTypeTestFunc, ShouldDropAll);

2037 if (TypeTestFunc || PublicTypeTestFunc) {

2038

2039

2040

2041 for (GlobalVariable &GV : M.globals())

2042 GV.eraseMetadata(LLVMContext::MD_vcall_visibility);

2043 return true;

2044 }

2045 return false;

2046 }

2047

2048

2049

2050

2051

2054 return false;

2055

2056 Function *ICallBranchFunnelFunc =

2058 if ((!TypeTestFunc || TypeTestFunc->use_empty()) &&

2059 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->use_empty()) &&

2060 !ExportSummary && !ImportSummary)

2061 return false;

2062

2063 if (ImportSummary) {

2064 if (TypeTestFunc)

2067

2068 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->use_empty())

2070 "unexpected call to llvm.icall.branch.funnel during import phase");

2071

2074 for (auto &F : M) {

2075

2076

2077 if (F.hasLocalLinkage())

2078 continue;

2083 }

2084

2085 {

2086 ScopedSaveAliaseesAndUsed S(M);

2087 for (auto *F : Defs)

2088 importFunction(F, true);

2089 for (auto *F : Decls)

2090 importFunction(F, false);

2091 }

2092

2093 return true;

2094 }

2095

2096

2097

2098

2099 using GlobalClassesTy = EquivalenceClasses<

2100 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;

2101 GlobalClassesTy GlobalClasses;

2102

2103

2104

2105

2106

2107

2108

2109

2111 struct TIInfo {

2112 unsigned UniqueId;

2113 std::vector<GlobalTypeMember *> RefGlobals;

2114 };

2115 DenseMap<Metadata *, TIInfo> TypeIdInfo;

2116 unsigned CurUniqueId = 0;

2118

2119

2120

2121 const bool CrossDsoCfi = M.getModuleFlag("Cross-DSO CFI") != nullptr;

2122

2123 struct ExportedFunctionInfo {

2125 MDNode *FuncMD;

2126 };

2127 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;

2128 if (ExportSummary) {

2129 NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");

2130 if (CfiFunctionsMD) {

2131

2132 DenseSetGlobalValue::GUID AddressTaken;

2133 for (auto &I : *ExportSummary)

2134 for (auto &GVS : I.second.getSummaryList())

2135 if (GVS->isLive())

2136 for (const auto &Ref : GVS->refs()) {

2137 AddressTaken.insert(Ref.getGUID());

2138 for (auto &RefGVS : Ref.getSummaryList())

2140 AddressTaken.insert(Alias->getAliaseeGUID());

2141 }

2143 if (AddressTaken.count(GUID))

2144 return true;

2145 auto VI = ExportSummary->getValueInfo(GUID);

2146 if (!VI)

2147 return false;

2148 for (auto &I : VI.getSummaryList())

2150 if (AddressTaken.count(Alias->getAliaseeGUID()))

2151 return true;

2152 return false;

2153 };

2154 for (auto *FuncMD : CfiFunctionsMD->operands()) {

2155 assert(FuncMD->getNumOperands() >= 2);

2156 StringRef FunctionName =

2160 ->getValue()

2161 ->getUniqueInteger()

2162 .getZExtValue());

2166

2167

2168 if (!ExportSummary->isGUIDLive(GUID))

2169 continue;

2172 continue;

2173

2175 if (auto VI = ExportSummary->getValueInfo(GUID))

2176 for (const auto &GVS : VI.getSummaryList())

2179

2180 if (!Exported)

2181 continue;

2182 }

2183 auto P = ExportedFunctions.insert({FunctionName, {Linkage, FuncMD}});

2185 P.first->second = {Linkage, FuncMD};

2186 }

2187

2188 for (const auto &P : ExportedFunctions) {

2189 StringRef FunctionName = P.first;

2191 MDNode *FuncMD = P.second.FuncMD;

2192 Function *F = M.getFunction(FunctionName);

2193 if (F && F->hasLocalLinkage()) {

2194

2195

2196

2197

2198

2199

2200 F->setName(F->getName() + ".1");

2201 F = nullptr;

2202 }

2203

2204 if (F)

2206 FunctionType::get(Type::getVoidTy(M.getContext()), false),

2207 GlobalVariable::ExternalLinkage,

2208 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);

2209

2210

2211

2212

2213

2214

2215 if (F->hasAvailableExternallyLinkage()) {

2217 F->deleteBody();

2218 F->setComdat(nullptr);

2219 F->clearMetadata();

2220 }

2221

2222

2223

2226

2227

2228

2229

2230

2231 if (F->isDeclaration()) {

2234

2235 F->eraseMetadata(LLVMContext::MD_type);

2237 F->addMetadata(LLVMContext::MD_type,

2239 }

2240 }

2241 }

2242 }

2243

2244 struct AliasToCreate {

2246 std::string TargetName;

2247 };

2248 std::vector AliasesToCreate;

2249

2250

2251

2252 if (ExportSummary) {

2253 if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) {

2254 for (auto *AliasMD : AliasesMD->operands()) {

2256 for (Metadata *MD : AliasMD->operands()) {

2258 if (!MDS)

2259 continue;

2260 StringRef AliasName = MDS->getString();

2261 if (!ExportedFunctions.count(AliasName))

2262 continue;

2263 auto *AliasF = M.getFunction(AliasName);

2264 if (AliasF)

2266 }

2267

2268 if (Aliases.empty())

2269 continue;

2270

2271 for (unsigned I = 1; I != Aliases.size(); ++I) {

2272 auto *AliasF = Aliases[I];

2273 ExportedFunctions.erase(AliasF->getName());

2274 AliasesToCreate.push_back(

2275 {AliasF, std::string(Aliases[0]->getName())});

2276 }

2277 }

2278 }

2279 }

2280

2281 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;

2282 for (GlobalObject &GO : M.global_objects()) {

2284 continue;

2285

2287 GO.getMetadata(LLVMContext::MD_type, Types);

2288

2289 bool IsJumpTableCanonical = false;

2290 bool IsExported = false;

2293 if (auto It = ExportedFunctions.find(F->getName());

2294 It != ExportedFunctions.end()) {

2295 IsJumpTableCanonical |= It->second.Linkage == CFL_Definition;

2296 IsExported = true;

2297

2298

2299

2300

2301 } else if (F->hasAddressTaken()) {

2302 if (!CrossDsoCfi || !IsJumpTableCanonical || F->hasLocalLinkage())

2303 continue;

2304 }

2305 }

2306

2307 auto *GTM = GlobalTypeMember::create(Alloc, &GO, IsJumpTableCanonical,

2308 IsExported, Types);

2309 GlobalTypeMembers[&GO] = GTM;

2310 for (MDNode *Type : Types) {

2311 verifyTypeMDNode(&GO, Type);

2312 auto &Info = TypeIdInfo[Type->getOperand(1)];

2313 Info.UniqueId = ++CurUniqueId;

2314 Info.RefGlobals.push_back(GTM);

2315 }

2316 }

2317

2318 auto AddTypeIdUse = [&](Metadata *TypeId) -> TypeIdUserInfo & {

2319

2320

2321

2322

2323 auto Ins = TypeIdUsers.insert({TypeId, {}});

2324 if (Ins.second) {

2325

2326 auto &GCI = GlobalClasses.insert(TypeId);

2327 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);

2328

2329

2330 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)

2331 CurSet = GlobalClasses.unionSets(

2332 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));

2333 }

2334

2335 return Ins.first->second;

2336 };

2337

2338 if (TypeTestFunc) {

2339 for (const Use &U : TypeTestFunc->uses()) {

2341

2342

2343

2344

2345

2346

2347 bool OnlyAssumeUses = !CI->use_empty();

2348 for (const Use &CIU : CI->uses()) {

2350 continue;

2351 OnlyAssumeUses = false;

2352 break;

2353 }

2354 if (OnlyAssumeUses)

2355 continue;

2356

2358 if (!TypeIdMDVal)

2359 report_fatal_error("Second argument of llvm.type.test must be metadata");

2360 auto TypeId = TypeIdMDVal->getMetadata();

2361 AddTypeIdUse(TypeId).CallSites.push_back(CI);

2362 }

2363 }

2364

2365 if (ICallBranchFunnelFunc) {

2366 for (const Use &U : ICallBranchFunnelFunc->uses()) {

2369 "llvm.icall.branch.funnel not supported on this target");

2370

2372

2373 std::vector<GlobalTypeMember *> Targets;

2374 if (CI->arg_size() % 2 != 1)

2376

2377 GlobalClassesTy::member_iterator CurSet;

2378 for (unsigned I = 1; I != CI->arg_size(); I += 2) {

2384 "Expected branch funnel operand to be global value");

2385

2386 GlobalTypeMember *GTM = GlobalTypeMembers[Base];

2387 Targets.push_back(GTM);

2388 GlobalClassesTy::member_iterator NewSet =

2389 GlobalClasses.findLeader(GlobalClasses.insert(GTM));

2390 if (I == 1)

2391 CurSet = NewSet;

2392 else

2393 CurSet = GlobalClasses.unionSets(CurSet, NewSet);

2394 }

2395

2396 GlobalClasses.unionSets(

2397 CurSet, GlobalClasses.findLeader(

2398 GlobalClasses.insert(ICallBranchFunnel::create(

2399 Alloc, CI, Targets, ++CurUniqueId))));

2400 }

2401 }

2402

2403 if (ExportSummary) {

2404 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;

2405 for (auto &P : TypeIdInfo) {

2408 TypeId->getString())]

2409 .push_back(TypeId);

2410 }

2411

2412 for (auto &P : *ExportSummary) {

2413 for (auto &S : P.second.getSummaryList()) {

2414 if (!ExportSummary->isGlobalValueLive(S.get()))

2415 continue;

2418 for (Metadata *MD : MetadataByGUID[G])

2419 AddTypeIdUse(MD).IsExported = true;

2420 }

2421 }

2422 }

2423

2424 if (GlobalClasses.empty())

2425 return false;

2426

2427 {

2428 ScopedSaveAliaseesAndUsed S(M);

2429

2430 for (const auto &C : GlobalClasses) {

2431 if (C->isLeader())

2432 continue;

2433

2434 ++NumTypeIdDisjointSets;

2435

2436 std::vector<Metadata *> TypeIds;

2437 std::vector<GlobalTypeMember *> Globals;

2438 std::vector<ICallBranchFunnel *> ICallBranchFunnels;

2439 for (auto M : GlobalClasses.members(*C)) {

2444 else

2446 }

2447

2448

2449

2450

2452 return TypeIdInfo[M1].UniqueId < TypeIdInfo[M2].UniqueId;

2453 });

2454

2455

2457 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {

2458 return F1->UniqueId < F2->UniqueId;

2459 });

2460

2461

2462 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);

2463 }

2464 }

2465

2466 allocateByteArrays();

2467

2468 for (auto A : AliasesToCreate) {

2469 auto *Target = M.getNamedValue(A.TargetName);

2471 continue;

2473 AliasGA->setVisibility(A.Alias->getVisibility());

2474 AliasGA->setLinkage(A.Alias->getLinkage());

2475 AliasGA->takeName(A.Alias);

2476 A.Alias->replaceAllUsesWith(AliasGA);

2477 A.Alias->eraseFromParent();

2478 }

2479

2480

2481 if (ExportSummary) {

2482 if (NamedMDNode *SymversMD = M.getNamedMetadata("symvers")) {

2483 for (auto *Symver : SymversMD->operands()) {

2484 assert(Symver->getNumOperands() >= 2);

2487 StringRef Alias = cast(Symver->getOperand(1))->getString();

2488

2489 if (!ExportedFunctions.count(SymbolName))

2490 continue;

2491

2492 M.appendModuleInlineAsm(

2493 (llvm::Twine(".symver ") + SymbolName + ", " + Alias).str());

2494 }

2495 }

2496 }

2497

2498 return true;

2499}

2500

2504 if (UseCommandLine)

2505 Changed = LowerTypeTestsModule::runForTesting(M, AM);

2506 else

2508 LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, DropTypeTests)

2509 .lower();

2513}

2514

2518

2519

2520

2521

2522

2523

2524

2525

2526

2527

2528

2529

2530

2531

2532

2533

2534

2535

2536 for (auto &GV : M.globals()) {

2539 continue;

2540

2543 auto MaySimplifyPtr = [&](Value *Ptr) {

2545 if (auto *CFIGV = M.getNamedValue((GV->getName() + ".cfi").str()))

2546 Ptr = CFIGV;

2548 };

2549 auto MaySimplifyInt = [&](Value *Op) {

2551 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)

2552 return false;

2553 return MaySimplifyPtr(PtrAsInt->getOperand(0));

2554 };

2558 MaySimplifyPtr(CI->getOperand(0))) {

2559

2560

2561

2565 continue;

2566 }

2567 }

2569 if (!CE || CE->getOpcode() != Instruction::PtrToInt)

2570 continue;

2573 if (U.getOperandNo() == 0 && CE &&

2574 CE->getOpcode() == Instruction::Sub &&

2575 MaySimplifyInt(CE->getOperand(1))) {

2576

2577

2578

2579

2580

2581 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));

2583 }

2585 if (U.getOperandNo() == 1 && CI &&

2587 MaySimplifyInt(CI->getOperand(0))) {

2588

2589

2593 }

2594 }

2595 }

2596 }

2597

2604 return PA;

2605}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

AMDGPU Prepare AGPR Alloc

AMDGPU Register Bank Select

This file implements a class to represent arbitrary precision integral constant values and operations...

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

This file defines the BumpPtrAllocator interface.

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")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Analysis containing CSE Info

#define clEnumValN(ENUMVAL, FLAGNAME, DESC)

This file contains the declarations for the subclasses of Constant, which represent the different fla...

This file defines the DenseMap class.

Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...

Module.h This file contains the declarations for the Module class.

This header defines various interfaces for pass management in LLVM.

This defines the Use class.

static const unsigned kARMJumpTableEntrySize

Definition LowerTypeTests.cpp:1265

static const unsigned kLOONGARCH64JumpTableEntrySize

Definition LowerTypeTests.cpp:1269

static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)

Definition LowerTypeTests.cpp:697

static const unsigned kX86IBTJumpTableEntrySize

Definition LowerTypeTests.cpp:1264

static cl::opt< std::string > ClReadSummary("lowertypetests-read-summary", cl::desc("Read summary from given YAML file before running pass"), cl::Hidden)

static const unsigned kRISCVJumpTableEntrySize

Definition LowerTypeTests.cpp:1268

static auto buildBitSets(ArrayRef< Metadata * > TypeIds, const DenseMap< GlobalTypeMember *, uint64_t > &GlobalLayout)

Definition LowerTypeTests.cpp:1151

static void dropTypeTests(Module &M, Function &TypeTestFunc, bool ShouldDropAll)

Definition LowerTypeTests.cpp:1998

static Value * createMaskedBitTest(IRBuilder<> &B, Value *Bits, Value *BitOffset)

Build a test that bit BitOffset mod sizeof(Bits)*8 is set in Bits.

Definition LowerTypeTests.cpp:586

static bool isThumbFunction(Function *F, Triple::ArchType ModuleArch)

Definition LowerTypeTests.cpp:1489

static const unsigned kX86JumpTableEntrySize

Definition LowerTypeTests.cpp:1263

static cl::opt< bool > AvoidReuse("lowertypetests-avoid-reuse", cl::desc("Try to avoid reuse of byte array addresses using aliases"), cl::Hidden, cl::init(true))

static cl::opt< PassSummaryAction > ClSummaryAction("lowertypetests-summary-action", cl::desc("What to do with the summary when running this pass"), cl::values(clEnumValN(PassSummaryAction::None, "none", "Do nothing"), clEnumValN(PassSummaryAction::Import, "import", "Import typeid resolutions from summary and globals"), clEnumValN(PassSummaryAction::Export, "export", "Export typeid resolutions to summary and globals")), cl::Hidden)

static const unsigned kARMBTIJumpTableEntrySize

Definition LowerTypeTests.cpp:1266

static cl::opt< std::string > ClWriteSummary("lowertypetests-write-summary", cl::desc("Write summary to given YAML file after running pass"), cl::Hidden)

static BitSetInfo buildBitSet(ArrayRef< uint64_t > Offsets)

Build a bit set for list of offsets.

Definition LowerTypeTests.cpp:578

static bool isDirectCall(Use &U)

Definition LowerTypeTests.cpp:1948

static const unsigned kARMv6MJumpTableEntrySize

Definition LowerTypeTests.cpp:1267

static cl::opt< DropTestKind > ClDropTypeTests("lowertypetests-drop-type-tests", cl::desc("Simply drop type test sequences"), cl::values(clEnumValN(DropTestKind::None, "none", "Do not drop any type tests"), clEnumValN(DropTestKind::Assume, "assume", "Drop type test assume sequences"), clEnumValN(DropTestKind::All, "all", "Drop all type test sequences")), cl::Hidden, cl::init(DropTestKind::None))

Machine Check Debug Module

ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...

FunctionAnalysisManager FAM

This file defines the PointerUnion class, which is a discriminated union of pointer types.

This file contains the declarations for profiling metadata utility functions.

static StringRef getName(Value *V)

This file implements a set that has insertion order iteration characteristics.

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

This pass exposes codegen information to IR-level passes.

This header defines support for implementing classes that have some trailing object (or arrays of obj...

Class for arbitrary precision integers.

uint64_t getZExtValue() const

Get zero extended value.

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)

This static method is the primary way to construct an ArrayType.

Functions, function parameters, and return types can have attributes to indicate how they should be t...

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.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)

Split the basic block into two basic blocks at the specified instruction.

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)

Value * getArgOperand(unsigned i) const

unsigned arg_size() const

void emplace(Args &&...A)

size_t count(StringRef S) const

static LLVM_ABI ConstantAggregateZero * get(Type *Ty)

ConstantArray - Constant Array Declarations.

static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)

get() constructor - Return a constant with array type with an element count and element type matching...

static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)

static Constant * getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList)

Create an "inbounds" getelementptr.

static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)

Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.

static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)

static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)

Getelementptr form.

static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)

static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)

static LLVM_ABI ConstantPointerNull * get(PointerType *T)

Static factory methods - Return objects of the specified value.

static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)

Return an anonymous struct that has the specified elements.

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)

Analysis pass which computes a DominatorTree.

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)

void eraseFromParent()

eraseFromParent - This method unlinks 'this' from the containing module and deletes it.

static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)

If a parent module is specified, the alias is automatically inserted into the end of the specified mo...

LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)

Set a particular kind of metadata attachment.

LLVM_ABI void setComdat(Comdat *C)

const Comdat * getComdat() const

LLVM_ABI bool eraseMetadata(unsigned KindID)

Erase all metadata attachments with the given kind.

bool hasSection() const

Check if this global has a custom object file section.

MDNode * getMetadata(unsigned KindID) const

Get the current metadata attachments for the given kind, if any.

static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)

Return a 64-bit global unique ID constructed from the name of a global symbol.

bool isThreadLocal() const

If the value is "Thread Local", its value isn't shared by the threads.

VisibilityTypes getVisibility() const

static bool isLocalLinkage(LinkageTypes Linkage)

LinkageTypes getLinkage() const

uint64_t GUID

Declare a type to represent a global unique identifier for a global value.

static StringRef dropLLVMManglingEscape(StringRef Name)

If the given string begins with the GlobalValue name mangling escape character '\1',...

bool isDeclarationForLinker() const

PointerType * getType() const

Global values are always pointers.

VisibilityTypes

An enumeration for the kinds of visibility of global values.

@ HiddenVisibility

The GV is hidden.

void setVisibility(VisibilityTypes V)

LinkageTypes

An enumeration for the kinds of linkage for global values.

@ PrivateLinkage

Like Internal, but omit from symbol table.

@ InternalLinkage

Rename collisions when linking (static functions).

@ ExternalLinkage

Externally visible function.

@ ExternalWeakLinkage

ExternalWeak linkage description.

Type * getValueType() const

const Constant * getInitializer() const

getInitializer - Return the initializer for this global variable.

LLVM_ABI void setInitializer(Constant *InitVal)

setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...

MaybeAlign getAlign() const

Returns the alignment of the given variable.

void setConstant(bool Val)

LLVM_ABI void setCodeModel(CodeModel::Model CM)

Change the code model for this global.

LLVM_ABI void eraseFromParent()

eraseFromParent - This method unlinks 'this' from the containing module and deletes it.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)

InlineAsm::get - Return the specified uniqued inline asm string.

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)

Set the metadata of the specified kind to the specified node.

unsigned getBitWidth() const

Get the number of bits in this IntegerType.

Analysis pass that exposes the LoopInfo for a function.

LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

Definition LowerTypeTests.cpp:2501

const MDOperand & getOperand(unsigned I) const

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

unsigned getNumOperands() const

Return number of MDNode operands.

static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...

TypeIdSummary & getOrInsertTypeIdSummary(StringRef TypeId)

Return an existing or new TypeIdSummary entry for TypeId.

const TypeIdSummary * getTypeIdSummary(StringRef TypeId) const

This returns either a pointer to the type id summary (if present in the summary map) or null (if not ...

CfiFunctionIndex & cfiFunctionDecls()

bool partiallySplitLTOUnits() const

CfiFunctionIndex & cfiFunctionDefs()

A Module instance is used to store all the information related to an LLVM module.

iterator_range< op_iterator > operands()

static PointerType * getUnqual(Type *ElementType)

This constructs a pointer to an object of the specified type in the default address space (address sp...

unsigned getAddressSpace() const

Return the address space of the Pointer type.

Analysis pass which computes a PostDominatorTree.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses none()

Convenience factory function for the empty preserved set.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

PreservedAnalyses & preserve()

Mark an analysis as preserved.

static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)

bool insert(const value_type &X)

Insert a new element into the SetVector.

LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

Definition LowerTypeTests.cpp:2515

reference emplace_back(ArgTypes &&... Args)

void reserve(size_type N)

iterator erase(const_iterator CI)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

std::pair< StringRef, StringRef > split(char Separator) const

Split into two substrings around the first occurrence of a separator character.

constexpr StringRef substr(size_t Start, size_t N=npos) const

Return a reference to the substring from [Start, Start + N).

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

constexpr size_t size() const

size - Get the string size.

bool ends_with(StringRef Suffix) const

Check if this string ends with the given Suffix.

Type * getElementType(unsigned N) const

Analysis pass providing the TargetTransformInfo.

See the file comment for details on the usage of the TrailingObjects type.

Triple - Helper class for working with autoconf configuration names.

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI Type * getVoidTy(LLVMContext &C)

A Use represents the edge between a Value definition and its users.

Value * getOperand(unsigned i) const

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

user_iterator user_begin()

bool hasOneUse() const

Return true if there is exactly one use of this value.

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

iterator_range< user_iterator > users()

LLVM_ABI void replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)

Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...

iterator_range< use_iterator > uses()

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

LLVM_ABI void takeName(Value *V)

Transfer the name from V to this value.

std::pair< iterator, bool > insert(const ValueT &V)

bool contains(const_arg_type_t< ValueT > V) const

Check if the set contains the given element.

size_type count(const_arg_type_t< ValueT > V) const

Return 1 if the specified key is in the set, 0 otherwise.

const ParentTy * getParent() const

self_iterator getIterator()

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

This class implements an extremely fast bulk output stream that can only output to a stream.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

constexpr char SymbolName[]

Key for Kernel::Metadata::mSymbolName.

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

@ C

The default llvm calling convention, compatible with C.

@ BasicBlock

Various leaf nodes.

LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)

Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.

ValuesClass values(OptsTy... Options)

Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...

initializer< Ty > init(const Ty &Val)

DropTestKind

Specifies how to drop type tests.

@ Assume

Do not drop type tests (default).

LLVM_ABI bool isJumpTableCanonical(Function *F)

Definition LowerTypeTests.cpp:254

std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)

Extract a Value from Metadata, allowing null.

SmallVector< unsigned char, 0 > ByteArray

NodeAddr< PhiNode * > Phi

NodeAddr< UseNode * > Use

@ OF_TextWithCRLF

The file should be opened in text mode and use a carriage linefeed '\r '.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)

Replace the instruction specified by BI with the instruction specified by I.

FunctionAddr VTableAddr Value

void stable_sort(R &&Range)

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)

Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty

@ Export

Export information to summary.

@ Import

Import information from summary.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)

Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy

Provide the FunctionAnalysisManager to Module proxy.

int countr_zero(T Val)

Count number of 0's from the least significant bit to the most stopping at the first 1.

unsigned M1(unsigned Val)

LLVM_ABI bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)

Replace constant expressions users of the given constants with instructions.

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

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

@ Ref

The access may reference the value stored in memory.

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)

Adds global values to the llvm.compiler.used list.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

DWARFExpression::Operation Op

Expected< T > errorOrToExpected(ErrorOr< T > &&EO)

Convert an ErrorOr to an Expected.

ArrayRef(const T &OneElt) -> ArrayRef< T >

OutputIt copy(R &&Range, OutputIt Out)

constexpr unsigned BitWidth

LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)

Append F to the list of global ctors of module M with the given Priority.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

LLVM_ABI Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.

LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)

Split the containing block at the specified instruction - everything before SplitBefore stays in the ...

BumpPtrAllocatorImpl<> BumpPtrAllocator

The standard BumpPtrAllocator which just uses the default template parameters.

LLVM_ABI void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)

Adds global values to the llvm.used list.

CfiFunctionLinkage

The type of CFI jumptable needed for a function.

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

constexpr uint64_t NextPowerOf2(uint64_t A)

Returns the next power of two (in 64-bits) that is strictly greater than A.

LLVM_ABI GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)

Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...

Kind

Specifies which kind of type check we should emit for this byte array.

@ Unknown

Unknown (analysis not performed, don't lower)

@ Single

Single element (last example in "Short Inline Bit Vectors")

@ Inline

Inlined bit vector ("Short Inline Bit Vectors")

@ Unsat

Unsatisfiable type (i.e. no global has this type metadata)

@ AllOnes

All-ones bit vector ("Eliminating Bit Vector Checks for All-Ones Bit Vectors")

@ ByteArray

Test a byte array (first example)

unsigned SizeM1BitWidth

Range of size-1 expressed as a bit width.

enum llvm::TypeTestResolution::Kind TheKind

LLVM_ABI BitSetInfo build()

Definition LowerTypeTests.cpp:165

SmallVector< uint64_t, 16 > Offsets

LLVM_ABI bool containsGlobalOffset(uint64_t Offset) const

Definition LowerTypeTests.cpp:136

LLVM_ABI void print(raw_ostream &OS) const

Definition LowerTypeTests.cpp:150

std::set< uint64_t > Bits

This class is used to build a byte array containing overlapping bit sets.

uint64_t BitAllocs[BitsPerByte]

The number of bytes allocated so far for each of the bits.

std::vector< uint8_t > Bytes

The byte array built so far.

LLVM_ABI void allocate(const std::set< uint64_t > &Bits, uint64_t BitSize, uint64_t &AllocByteOffset, uint8_t &AllocMask)

Allocate BitSize bits in the byte array where Bits contains the bits to set.

Definition LowerTypeTests.cpp:231

This class implements a layout algorithm for globals referenced by bit sets that tries to keep member...

std::vector< std::vector< uint64_t > > Fragments

The computed layout.

LLVM_ABI void addFragment(const std::set< uint64_t > &F)

Add F to the layout while trying to keep its indices contiguous.

Definition LowerTypeTests.cpp:202

std::vector< uint64_t > FragmentMap

Mapping from object index to fragment index.