89#include <system_error>
96#define DEBUG_TYPE "lowertypetests"
98STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
99STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
100STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
101STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
102STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
105 "lowertypetests-avoid-reuse",
106 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
110 "lowertypetests-summary-action",
111 cl::desc(
"What to do with the summary when running this pass"),
114 "Import typeid resolutions from summary and globals"),
116 "Export typeid resolutions to summary and globals")),
121 cl::desc(
"Read summary from given textual assembly or YAML "
122 "file before running pass"),
126 "lowertypetests-write-summary",
127 cl::desc(
"Write summary to given YAML file after running pass"),
133 cl::desc(
"Enable debug info generation for jump tables"));
159 for (uint64_t
B :
Bits)
202 assert(Fragments.front().empty() &&
"Cannot add fragments after build()");
205 Fragments.emplace_back();
206 std::vector<uint64_t> &Fragment = Fragments.back();
207 uint64_t FragmentIndex = Fragments.size() - 1;
209 for (
auto ObjIndex :
F) {
210 uint64_t OldFragmentIndex = FragmentMap[ObjIndex];
211 if (OldFragmentIndex == 0) {
214 Fragment.push_back(ObjIndex);
221 std::vector<uint64_t> &OldFragment = Fragments[OldFragmentIndex];
228 for (uint64_t ObjIndex : Fragment)
229 FragmentMap[ObjIndex] = FragmentIndex;
233 std::vector<uint64_t> Layout;
234 Layout.reserve(FragmentMap.size());
235 for (
auto &&
F : Fragments)
238 Fragments.push_back(std::move(Layout));
239 return Fragments.front();
243 uint64_t BitSize, uint64_t &AllocByteOffset,
254 unsigned ReqSize = AllocByteOffset + BitSize;
256 if (
Bytes.size() < ReqSize)
257 Bytes.resize(ReqSize);
260 AllocMask = 1 << Bit;
261 for (uint64_t
B : Bits)
262 Bytes[AllocByteOffset +
B] |= AllocMask;
266 if (
F->isDeclarationForLinker())
269 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
270 if (!CI || !CI->isZero())
272 return F->hasFnAttribute(
"cfi-canonical-jump-table");
277struct ByteArrayInfo {
278 std::set<uint64_t> Bits;
290class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
301 bool IsJumpTableCanonical;
309 bool IsJumpTableCanonical,
bool IsExported,
311 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
312 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
314 GTM->NTypes = Types.size();
315 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
316 GTM->IsExported = IsExported;
321 GlobalObject *getGlobal()
const {
326 return IsJumpTableCanonical;
329 bool isExported()
const {
336struct ICallBranchFunnel final
337 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
341 auto *
Call =
static_cast<ICallBranchFunnel *
>(
342 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
343 alignof(ICallBranchFunnel)));
345 Call->UniqueId = UniqueId;
353 return getTrailingObjects(NTargets);
362struct ScopedSaveAliaseesAndUsed {
365 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
366 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
371 void collectAndEraseUsedFunctions(
Module &M,
372 SmallVectorImpl<GlobalValue *> &Vec,
380 GV->eraseFromParent();
382 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
383 return isa<Function>(GV);
392 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
405 collectAndEraseUsedFunctions(M, Used,
false);
406 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
408 for (
auto &GA :
M.aliases()) {
412 FunctionAliases.push_back({&GA,
F});
415 for (
auto &GI :
M.ifuncs())
417 ResolverIFuncs.push_back({&GI,
F});
420 ~ScopedSaveAliaseesAndUsed() {
424 for (
auto P : FunctionAliases)
425 P.first->setAliasee(
P.second);
427 for (
auto P : ResolverIFuncs) {
431 P.first->setResolver(
P.second);
436class LowerTypeTestsModule {
439 ModuleSummaryIndex *ExportSummary;
440 const ModuleSummaryIndex *ImportSummary;
449 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
452 int HasBranchTargetEnforcement = -1;
454 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
455 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
456 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
457 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
458 IntegerType *Int32Ty = Type::getInt32Ty(
M.getContext());
459 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
460 IntegerType *
IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
468 struct TypeIdUserInfo {
469 std::vector<CallInst *> CallSites;
470 bool IsExported =
false;
472 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
478 struct TypeIdLowering {
503 std::vector<ByteArrayInfo> ByteArrayInfos;
505 Function *WeakInitializerFn =
nullptr;
507 GlobalVariable *GlobalAnnotation;
508 DenseSet<Value *> FunctionAnnotations;
512 bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
514 bool shouldExportConstantsAsAbsoluteSymbols();
515 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
516 TypeIdLowering importTypeId(StringRef TypeId);
517 void importTypeTest(CallInst *CI);
520 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
521 void allocateByteArrays();
524 void lowerTypeTestCalls(
526 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
528 const TypeIdLowering &TIL);
534 bool hasBranchTargetEnforcement();
537 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
549 void replaceWeakDeclarationWithJumpTablePtr(
Function *
F, Constant *JT,
550 bool IsJumpTableCanonical);
551 void moveInitializerToModuleConstructor(GlobalVariable *GV);
552 void findGlobalVariableUsersOf(Constant *
C,
553 SmallSetVector<GlobalVariable *, 8> &Out);
562 void replaceCfiUses(
Function *Old,
Value *New,
bool IsJumpTableCanonical);
566 void replaceDirectCalls(
Value *Old,
Value *New);
568 bool isFunctionAnnotation(
Value *V)
const {
569 return FunctionAnnotations.
contains(V);
572 void maybeReplaceComdat(
Function *
F, StringRef OriginalName);
576 ModuleSummaryIndex *ExportSummary,
577 const ModuleSummaryIndex *ImportSummary);
599 unsigned BitWidth = BitsType->getBitWidth();
601 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
603 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
604 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
605 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
606 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
609ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
613 auto ByteArrayGlobal =
new GlobalVariable(
615 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
618 ByteArrayInfos.emplace_back();
619 ByteArrayInfo *BAI = &ByteArrayInfos.back();
621 BAI->Bits = BSI.
Bits;
623 BAI->ByteArray = ByteArrayGlobal;
624 BAI->MaskGlobal = MaskGlobal;
628void LowerTypeTestsModule::allocateByteArrays() {
630 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
631 return BAI1.BitSize > BAI2.BitSize;
634 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
637 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
638 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
641 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
647 *BAI->MaskPtr =
Mask;
652 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
655 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
656 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
658 ByteArray, ConstantInt::get(
IntPtrTy, ByteArrayOffsets[
I]));
672 ByteArraySizeBytes = BAB.
Bytes.size();
678 const TypeIdLowering &TIL,
692 "bits_use", ByteArray, &M);
695 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
700 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
708 GV->getMetadata(LLVMContext::MD_type, Types);
710 if (
Type->getOperand(1) != TypeId)
723 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
724 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
732 if (
Op->getOpcode() == Instruction::BitCast)
735 if (
Op->getOpcode() == Instruction::Select)
745Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
746 const TypeIdLowering &TIL) {
754 const DataLayout &
DL =
M.getDataLayout();
767 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
773 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
784 {PtrOffset, PtrOffset, TIL.AlignLog2});
786 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
790 return OffsetInRange;
803 Br->getMetadata(LLVMContext::MD_prof));
807 for (
auto &Phi :
Else->phis())
808 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
811 return createBitSetTest(ThenB, TIL, BitOffset);
814 MDBuilder MDB(
M.getContext());
816 MDB.createLikelyBranchWeights()));
820 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
825 B.SetInsertPoint(CI);
826 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
827 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
828 P->addIncoming(Bit, ThenB.GetInsertBlock());
834void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
841 std::vector<Constant *> GlobalInits;
842 const DataLayout &
DL =
M.getDataLayout();
843 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
847 for (GlobalTypeMember *
G : Globals) {
850 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
851 MaxAlign = std::max(MaxAlign, Alignment);
853 GlobalLayout[
G] = GVOffset;
856 GlobalInits.push_back(
860 GlobalInits.push_back(GV->getInitializer());
862 CurOffset = GVOffset + InitSize;
871 if (DesiredPadding > 32)
872 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
876 auto *CombinedGlobal =
877 new GlobalVariable(M, NewInit->
getType(),
true,
879 CombinedGlobal->setAlignment(MaxAlign);
882 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
887 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
891 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
892 ConstantInt::get(Int32Ty,
I * 2)};
894 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
896 GlobalAlias *GAlias =
898 "", CombinedGlobalElemPtr, &M);
906bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
919uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
920 const TypeIdLowering &TIL) {
921 TypeTestResolution &TTRes =
928 "__typeid_" + TypeId +
"_" + Name,
C, &M);
933 if (shouldExportConstantsAsAbsoluteSymbols())
940 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
945 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
946 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
956 ExportGlobal(
"byte_array", TIL.TheByteArray);
957 if (shouldExportConstantsAsAbsoluteSymbols())
958 ExportGlobal(
"bit_mask", TIL.BitMask);
964 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
969LowerTypeTestsModule::TypeIdLowering
970LowerTypeTestsModule::importTypeId(StringRef TypeId) {
974 const TypeTestResolution &TTRes = TidSummary->
TTRes;
979 auto ImportGlobal = [&](StringRef
Name) {
982 GlobalVariable *GV =
M.getOrInsertGlobal(
983 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
990 if (!shouldExportConstantsAsAbsoluteSymbols()) {
1002 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
1011 if (AbsWidth ==
IntPtrTy->getBitWidth()) {
1015 SetAbsRange(0, 1ull << AbsWidth);
1021 auto *GV = ImportGlobal(
"global_addr");
1034 TIL.OffsetedGlobal = GV;
1046 TIL.TheByteArray = ImportGlobal(
"byte_array");
1047 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1051 TIL.InlineBits = ImportConstant(
1058void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1070 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1071 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1078void LowerTypeTestsModule::maybeReplaceComdat(
Function *
F,
1079 StringRef OriginalName) {
1085 F->getComdat()->getName() == OriginalName) {
1086 Comdat *OldComdat =
F->getComdat();
1087 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1088 for (GlobalObject &GO :
M.global_objects()) {
1097void LowerTypeTestsModule::importFunction(
Function *
F,
1099 assert(
F->getType()->getAddressSpace() == 0);
1102 std::string
Name = std::string(
F->getName());
1107 if (!
F->isDSOLocal())
1109 if (
F->isDeclaration()) {
1114 F->getAddressSpace(),
1117 replaceDirectCalls(
F, RealF);
1134 F->getAddressSpace(), Name +
".cfi_jt", &M);
1137 F->setName(Name +
".cfi");
1138 maybeReplaceComdat(
F, Name);
1140 F->getAddressSpace(), Name, &M);
1148 for (
auto &U :
F->uses()) {
1150 std::string AliasName =
A->getName().str() +
".cfi";
1153 F->getAddressSpace(),
"", &M);
1155 A->replaceAllUsesWith(AliasDecl);
1156 A->setName(AliasName);
1162 if (
F->hasExternalWeakLinkage())
1169 F->setVisibility(Visibility);
1178 OffsetsByTypeID[TypeId];
1179 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1181 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1182 if (It == OffsetsByTypeID.
end())
1188 It->second.push_back(MemOff +
Offset);
1198 dbgs() << MDS->getString() <<
": ";
1200 dbgs() <<
"<unnamed>: ";
1201 BitSets.
back().second.print(
dbgs());
1208void LowerTypeTestsModule::lowerTypeTestCalls(
1210 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1212 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1213 ByteArrayInfo *BAI =
nullptr;
1219 CombinedGlobalAddr, ConstantInt::get(
IntPtrTy, GlobalOffset)),
1224 : TypeTestResolution::
AllOnes;
1228 for (
auto Bit : BSI.
Bits)
1230 if (InlineBits == 0)
1233 TIL.InlineBits = ConstantInt::get(
1234 (BSI.
BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1237 ++NumByteArraysCreated;
1238 BAI = createByteArray(BSI);
1239 TIL.TheByteArray = BAI->ByteArray;
1240 TIL.BitMask = BAI->MaskGlobal;
1243 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1245 if (TIUI.IsExported) {
1246 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1248 BAI->MaskPtr = MaskPtr;
1252 for (CallInst *CI : TIUI.CallSites) {
1253 ++NumTypeTestCallsLowered;
1254 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1263void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1264 if (
Type->getNumOperands() != 2)
1271 "A member of a type identifier may not have an explicit section");
1294bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1295 if (HasBranchTargetEnforcement == -1) {
1299 M.getModuleFlag(
"branch-target-enforcement")))
1300 HasBranchTargetEnforcement = !BTE->isZero();
1302 HasBranchTargetEnforcement = 0;
1304 return HasBranchTargetEnforcement;
1308LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1309 switch (JumpTableArch) {
1313 M.getModuleFlag(
"cf-protection-branch")))
1314 if (MD->getZExtValue())
1320 if (CanUseThumbBWJumpTable) {
1321 if (hasBranchTargetEnforcement())
1328 if (hasBranchTargetEnforcement())
1347LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1349 raw_string_ostream AsmOS(Asm);
1354 M.getModuleFlag(
"cf-protection-branch")))
1355 Endbr = !MD->isZero();
1357 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1358 AsmOS <<
"jmp ${0:c}@plt\n";
1360 AsmOS <<
".balign 16, 0xcc\n";
1362 AsmOS <<
"int3\nint3\nint3\n";
1366 if (hasBranchTargetEnforcement())
1370 if (!CanUseThumbBWJumpTable) {
1386 AsmOS <<
"push {r0,r1}\n"
1388 <<
"0: add r0, r0, pc\n"
1389 <<
"str r0, [sp, #4]\n"
1392 <<
"1: .word $0 - (0b + 4)\n";
1394 if (hasBranchTargetEnforcement())
1396 AsmOS <<
"b.w $0\n";
1400 AsmOS <<
"tail $0@plt\n";
1402 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1403 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1405 AsmOS <<
"jump $0\n";
1418void LowerTypeTestsModule::buildBitSetsFromFunctions(
1424 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1426 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1431void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1432 GlobalVariable *GV) {
1433 if (WeakInitializerFn ==
nullptr) {
1438 M.getDataLayout().getProgramAddressSpace(),
1439 "__cfi_global_var_init", &M);
1445 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1458void LowerTypeTestsModule::findGlobalVariableUsersOf(
1459 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1460 for (
auto *U :
C->users()){
1464 findGlobalVariableUsersOf(C2, Out);
1469void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1470 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1473 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1474 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1475 for (
auto *GV : GlobalVarUsers) {
1476 if (GV == GlobalAnnotation)
1478 moveInitializerToModuleConstructor(GV);
1485 F->getAddressSpace(),
"", &M);
1486 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1493 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1496 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1508 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1516 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1521 if (Feature ==
"-thumb-mode")
1523 else if (Feature ==
"+thumb-mode")
1539 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1547 unsigned ArmCount = 0, ThumbCount = 0;
1548 for (
const auto GTM : Functions) {
1549 if (!GTM->isJumpTableCanonical()) {
1570 auto CUs = M.debug_compile_units();
1587 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1588 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1590 F->setSubprogram(UbsanSP);
1595 Locations.
reserve(Functions.size());
1597 for (
auto *Func : Functions) {
1598 StringRef FuncName = Func->getGlobal()->getName();
1601 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1602 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1607 Locations.push_back(EntryLoc);
1615void LowerTypeTestsModule::createJumpTable(
1624 F->setMetadata(LLVMContext::MD_elf_section_properties,
1627 ConstantAsMetadata::get(ConstantInt::get(
1628 Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
1629 ConstantAsMetadata::get(ConstantInt::get(
1630 Int64Ty, JumpTableEntrySize))}));
1639 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1645 bool areAllEntriesNounwind =
true;
1647 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1648 if (Loc.has_value())
1649 IRB.SetCurrentDebugLocation(*Loc);
1651 ->hasFnAttribute(Attribute::NoUnwind)) {
1652 areAllEntriesNounwind =
false;
1654 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1656 IRB.CreateUnreachable();
1659 F->setPreferredAlignment(
Align(JumpTableEntrySize));
1660 F->addFnAttr(Attribute::Naked);
1662 F->addFnAttr(
"target-features",
"-thumb-mode");
1664 if (hasBranchTargetEnforcement()) {
1667 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1669 F->addFnAttr(
"target-features",
"+thumb-mode");
1670 if (CanUseThumbBWJumpTable) {
1673 F->addFnAttr(
"target-cpu",
"cortex-a8");
1681 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1682 F->removeFnAttr(
"branch-target-enforcement");
1683 if (
F->hasFnAttribute(
"sign-return-address"))
1684 F->removeFnAttr(
"sign-return-address");
1689 F->addFnAttr(
"target-features",
"-c,-relax");
1695 F->addFnAttr(Attribute::NoCfCheck);
1698 if (areAllEntriesNounwind)
1699 F->addFnAttr(Attribute::NoUnwind);
1702 F->addFnAttr(Attribute::NoInline);
1707void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1792 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1793 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1794 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1795 GlobalLayout[Functions[
I]] =
I * EntrySize;
1801 M.getDataLayout().getProgramAddressSpace(),
1802 ".cfi.jumptable", &M);
1809 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1813 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1815 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1818 JumpTableType, JumpTable,
1822 const bool IsExported = Functions[
I]->isExported();
1823 if (!IsJumpTableCanonical) {
1827 F->getName() +
".cfi_jt",
1828 CombinedGlobalElemPtr, &M);
1837 if (IsJumpTableCanonical)
1845 if (!IsJumpTableCanonical) {
1846 if (
F->hasExternalWeakLinkage())
1847 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1848 IsJumpTableCanonical);
1850 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1852 assert(
F->getType()->getAddressSpace() == 0);
1854 GlobalAlias *FAlias =
1856 CombinedGlobalElemPtr, &M);
1861 F->setName(FAlias->
getName() +
".cfi");
1862 maybeReplaceComdat(
F, FAlias->
getName());
1864 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1865 if (!
F->hasLocalLinkage())
1870 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1879void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1884 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1886 for (GlobalTypeMember *GTM : Functions) {
1890 if (!
F->hasAddressTaken())
1896 ConstantInt::get(Int64Ty, IndirectIndex))));
1897 F->setMetadata(
"wasm.index", MD);
1900 GlobalLayout[GTM] = IndirectIndex++;
1909void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1912 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1913 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1914 TypeIdIndices[TypeIds[
I]] =
I;
1918 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1919 unsigned GlobalIndex = 0;
1920 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1921 for (GlobalTypeMember *GTM : Globals) {
1922 for (MDNode *
Type : GTM->types()) {
1924 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1925 if (
I != TypeIdIndices.
end())
1926 TypeMembers[
I->second].insert(GlobalIndex);
1928 GlobalIndices[GTM] = GlobalIndex;
1932 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1933 TypeMembers.emplace_back();
1934 std::set<uint64_t> &TMSet = TypeMembers.back();
1935 for (GlobalTypeMember *
T : JT->targets())
1936 TMSet.insert(GlobalIndices[
T]);
1942 const std::set<uint64_t> &
O2) {
1943 return O1.size() <
O2.size();
1950 for (
auto &&MemSet : TypeMembers)
1951 GLB.addFragment(MemSet);
1956 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1957 auto OGTMI = OrderedGTMs.begin();
1961 "variables and functions");
1962 *OGTMI++ = Globals[
Offset];
1967 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1969 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1973LowerTypeTestsModule::LowerTypeTestsModule(
1975 const ModuleSummaryIndex *ImportSummary)
1976 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
1977 assert(!(ExportSummary && ImportSummary));
1978 Triple TargetTriple(M.getTargetTriple());
1979 Arch = TargetTriple.getArch();
1981 CanUseArmJumpTable =
true;
1987 if (
F.isDeclaration())
1990 if (
TTI.hasArmWideBranch(
false))
1991 CanUseArmJumpTable =
true;
1992 if (
TTI.hasArmWideBranch(
true))
1993 CanUseThumbBWJumpTable =
true;
1996 OS = TargetTriple.getOS();
1997 ObjectFormat = TargetTriple.getObjectFormat();
2001 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
2010 std::unique_ptr<ModuleSummaryIndex>
Summary;
2015 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
2021 if (ReadSummaryFile->getBuffer().starts_with(
"---")) {
2022 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2023 yaml::Input
In(ReadSummaryFile->getBuffer());
2036 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2040 LowerTypeTestsModule(
2049 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
2055 yaml::Output Out(OS);
2064 return Usr && Usr->isCallee(&U);
2067void LowerTypeTestsModule::replaceCfiUses(
Function *Old,
Value *New,
2068 bool IsJumpTableCanonical) {
2069 SmallSetVector<Constant *, 4>
Constants;
2081 if (isFunctionAnnotation(
U.getUser()))
2099 for (
auto *
C : Constants)
2100 C->handleOperandChange(Old, New);
2103void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2108 bool ShouldDropAll) {
2114 Assume->eraseFromParent();
2123 return isa<PHINode>(U) || isa<SelectInst>(U);
2141 if (PublicTypeTestFunc)
2143 if (TypeTestFunc || PublicTypeTestFunc) {
2154bool LowerTypeTestsModule::lower() {
2168 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2169 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2170 !ExportSummary && !ImportSummary)
2173 if (ImportSummary) {
2178 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2180 "unexpected call to llvm.icall.branch.funnel during import phase");
2187 if (
F.hasLocalLinkage())
2196 ScopedSaveAliaseesAndUsed S(M);
2197 for (
auto *
F : Defs)
2198 importFunction(
F,
true);
2199 for (
auto *
F : Decls)
2200 importFunction(
F,
false);
2209 using GlobalClassesTy = EquivalenceClasses<
2210 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2211 GlobalClassesTy GlobalClasses;
2223 std::vector<GlobalTypeMember *> RefGlobals;
2225 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2226 unsigned CurUniqueId = 0;
2229 struct ExportedFunctionInfo {
2233 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2234 if (ExportSummary) {
2235 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2236 if (CfiFunctionsMD) {
2238 DenseSet<GlobalValue::GUID> AddressTaken;
2239 for (
auto &
I : *ExportSummary)
2240 for (
auto &GVS :
I.second.getSummaryList())
2242 for (
const auto &
Ref : GVS->refs()) {
2244 for (
auto &RefGVS :
Ref.getSummaryList())
2246 AddressTaken.
insert(Alias->getAliaseeGUID());
2249 if (AddressTaken.
count(GUID))
2251 auto VI = ExportSummary->getValueInfo(GUID);
2254 for (
auto &
I :
VI.getSummaryList())
2256 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2260 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2261 assert(FuncMD->getNumOperands() >= 2);
2262 StringRef FunctionName =
2267 ->getUniqueInteger()
2272 ->getUniqueInteger()
2276 if (!ExportSummary->isGUIDLive(GUID))
2283 if (
auto VI = ExportSummary->getValueInfo(GUID))
2284 for (
const auto &GVS :
VI.getSummaryList())
2291 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2293 P.first->second = {
Linkage, FuncMD};
2296 for (
const auto &
P : ExportedFunctions) {
2297 StringRef FunctionName =
P.first;
2299 MDNode *FuncMD =
P.second.FuncMD;
2301 if (
F &&
F->hasLocalLinkage()) {
2308 F->setName(
F->getName() +
".1");
2314 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2315 GlobalVariable::ExternalLinkage,
2316 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2318 LLVMContext::MD_guid,
2319 MDTuple::get(
M.getContext(), {FuncMD->getOperand(2).get()}));
2320 if (ExportSummary) {
2324 ->getUniqueInteger()
2326 if (
auto VI = ExportSummary->getValueInfo(GUID))
2328 VI.isDSOLocal(ExportSummary->withDSOLocalPropagation()));
2336 if (
F->hasAvailableExternallyLinkage()) {
2338 auto *OrigGUIDMD =
F->getMetadata(LLVMContext::MD_guid);
2341 F->setComdat(
nullptr);
2343 F->setMetadata(LLVMContext::MD_guid, OrigGUIDMD);
2355 if (
F->isDeclaration()) {
2359 F->eraseMetadata(LLVMContext::MD_type);
2361 F->addMetadata(LLVMContext::MD_type,
2368 struct AliasToCreate {
2370 std::string TargetName;
2372 std::vector<AliasToCreate> AliasesToCreate;
2376 if (ExportSummary) {
2377 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2378 for (
auto *AliasMD : AliasesMD->operands()) {
2380 for (
Metadata *MD : AliasMD->operands()) {
2384 StringRef AliasName = MDS->getString();
2385 if (!ExportedFunctions.count(AliasName))
2387 auto *AliasF =
M.getFunction(AliasName);
2392 if (Aliases.
empty())
2395 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2396 auto *AliasF = Aliases[
I];
2397 ExportedFunctions.
erase(AliasF->getName());
2398 AliasesToCreate.push_back(
2399 {AliasF, std::string(Aliases[0]->
getName())});
2405 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2406 for (GlobalObject &GO :
M.global_objects()) {
2413 bool IsJumpTableCanonical =
false;
2414 bool IsExported =
false;
2417 if (
auto It = ExportedFunctions.find(
F->getName());
2418 It != ExportedFunctions.end()) {
2425 }
else if (!
F->hasAddressTaken()) {
2426 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2431 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2433 GlobalTypeMembers[&GO] = GTM;
2434 for (MDNode *
Type : Types) {
2435 verifyTypeMDNode(&GO,
Type);
2436 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2437 Info.UniqueId = ++CurUniqueId;
2438 Info.RefGlobals.push_back(GTM);
2442 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2447 auto Ins = TypeIdUsers.
insert({TypeId, {}});
2450 auto &GCI = GlobalClasses.insert(TypeId);
2451 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2454 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2455 CurSet = GlobalClasses.unionSets(
2456 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2459 return Ins.first->second;
2463 for (
const Use &U : TypeTestFunc->
uses()) {
2472 for (
const Use &CIU : CI->
uses()) {
2475 OnlyAssumeUses =
false;
2484 auto TypeId = TypeIdMDVal->getMetadata();
2485 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2489 if (ICallBranchFunnelFunc) {
2490 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2493 "llvm.icall.branch.funnel not supported on this target");
2497 std::vector<GlobalTypeMember *> Targets;
2501 GlobalClassesTy::member_iterator CurSet;
2502 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2508 "Expected branch funnel operand to be global value");
2510 auto It = GlobalTypeMembers.
find(
Base);
2511 if (It == GlobalTypeMembers.
end())
2513 "defined global value with type metadata");
2514 GlobalTypeMember *GTM = It->second;
2515 Targets.push_back(GTM);
2516 GlobalClassesTy::member_iterator NewSet =
2517 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2521 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2524 GlobalClasses.unionSets(
2525 CurSet, GlobalClasses.findLeader(
2526 GlobalClasses.insert(ICallBranchFunnel::create(
2527 Alloc, CI, Targets, ++CurUniqueId))));
2531 if (ExportSummary) {
2532 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2533 for (
auto &
P : TypeIdInfo) {
2536 TypeId->getString())]
2540 for (
auto &
P : *ExportSummary) {
2541 for (
auto &S :
P.second.getSummaryList()) {
2542 if (!ExportSummary->isGlobalValueLive(S.get()))
2547 AddTypeIdUse(MD).IsExported =
true;
2552 if (GlobalClasses.empty())
2556 ScopedSaveAliaseesAndUsed S(M);
2558 for (
const auto &
C : GlobalClasses) {
2562 ++NumTypeIdDisjointSets;
2564 std::vector<Metadata *> TypeIds;
2565 std::vector<GlobalTypeMember *> Globals;
2566 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2567 for (
auto M : GlobalClasses.members(*
C)) {
2580 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2585 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2586 return F1->UniqueId < F2->UniqueId;
2590 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2594 allocateByteArrays();
2596 for (
auto A : AliasesToCreate) {
2597 auto *
Target =
M.getNamedValue(
A.TargetName);
2601 AliasGA->setVisibility(
A.Alias->getVisibility());
2602 AliasGA->setLinkage(
A.Alias->getLinkage());
2603 AliasGA->setDSOLocal(
A.Alias->isDSOLocal());
2604 AliasGA->takeName(
A.Alias);
2605 A.Alias->replaceAllUsesWith(AliasGA);
2606 A.Alias->eraseFromParent();
2610 if (ExportSummary) {
2611 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2612 for (
auto *Symver : SymversMD->operands()) {
2613 assert(Symver->getNumOperands() >= 2);
2616 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2618 if (!ExportedFunctions.count(SymbolName))
2621 M.appendModuleInlineAsm(
2622 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2634 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2636 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
2644 static_cast<PassInfoMixin<DropTypeTestsPass> *
>(
this)->
printPipeline(
2645 OS, MapClassName2PassName);
2648 case DropTestKind::Assume:
2651 case DropTestKind::All:
2684 for (
auto &GV : M.globals()) {
2691 auto MaySimplifyPtr = [&](
Value *Ptr) {
2693 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2697 auto MaySimplifyInt = [&](
Value *
Op) {
2699 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2701 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2717 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2721 if (U.getOperandNo() == 0 && CE &&
2722 CE->getOpcode() == Instruction::Sub &&
2723 MaySimplifyInt(CE->getOperand(1))) {
2729 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2733 if (U.getOperandNo() == 1 && CI &&
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#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
static const unsigned kLOONGARCH64JumpTableEntrySize
static cl::opt< std::string > ClReadSummary("lowertypetests-read-summary", cl::desc("Read summary from given textual assembly or YAML " "file before running pass"), cl::Hidden)
static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)
static const unsigned kX86IBTJumpTableEntrySize
static SmallVector< DILocation * > createJumpTableDebugInfo(Function *F, ArrayRef< GlobalTypeMember * > Functions)
static const unsigned kRISCVJumpTableEntrySize
static auto buildBitSets(ArrayRef< Metadata * > TypeIds, const DenseMap< GlobalTypeMember *, uint64_t > &GlobalLayout)
static void dropTypeTests(Module &M, Function &TypeTestFunc, bool ShouldDropAll)
static Value * createMaskedBitTest(IRBuilder<> &B, Value *Bits, Value *BitOffset)
Build a test that bit BitOffset mod sizeof(Bits)*8 is set in Bits.
static bool isThumbFunction(Function *F, Triple::ArchType ModuleArch)
static const unsigned kX86JumpTableEntrySize
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
static cl::opt< bool > EnableJumpTableDebugInfo("lowertypetests-jump-table-debug-info", cl::init(true), cl::Hidden, cl::desc("Enable debug info generation for jump tables"))
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.
static bool isDirectCall(Use &U)
static const unsigned kARMv6MJumpTableEntrySize
static const unsigned kHexagonJumpTableEntrySize
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 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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
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.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
void addSymbolWithThinLTOGUID(StringRef Name, GlobalValue::GUID GUID)
Add the function name and the GUID that ThinLTO uses for it.
bool contains(StringRef Name) const
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
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 Constant * getPtrAdd(Constant *Ptr, Constant *Offset, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReduced=nullptr)
Create a getelementptr i8, ptr, offset constant expression.
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getInBoundsPtrAdd(Constant *Ptr, Constant *Offset)
Create a getelementptr inbounds i8, ptr, offset constant expression.
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.
LLVM_ABI void finalize()
Construct any deferred debug info descriptors.
LLVM_ABI DISubroutineType * createSubroutineType(DITypeArray ParameterTypes, DINode::DIFlags Flags=DINode::FlagZero, unsigned CC=0)
Create subroutine type.
LLVM_ABI DISubprogram * createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags=DINode::FlagZero, DISubprogram::DISPFlags SPFlags=DISubprogram::SPFlagZero, DITemplateParameterArray TParams=nullptr, DISubprogram *Decl=nullptr, DITypeArray ThrownTypes=nullptr, DINodeArray Annotations=nullptr, StringRef TargetFuncName="", bool UseKeyInstructions=false)
Create a new descriptor for the specified subprogram.
LLVM_ABI DICompileUnit * createCompileUnit(DISourceLanguageName Lang, DIFile *File, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName=StringRef(), DICompileUnit::DebugEmissionKind Kind=DICompileUnit::DebugEmissionKind::FullDebug, uint64_t DWOId=0, bool SplitDebugInlining=true, bool DebugInfoForProfiling=false, DICompileUnit::DebugNameTableKind NameTableKind=DICompileUnit::DebugNameTableKind::Default, bool RangesBaseAddress=false, StringRef SysRoot={}, StringRef SDK={})
A CompileUnit provides an anchor for all debugging information generated during this instance of comp...
LLVM_ABI DIFile * createFile(StringRef Filename, StringRef Directory, std::optional< DIFile::ChecksumInfo< StringRef > > Checksum=std::nullopt, std::optional< StringRef > Source=std::nullopt)
Create a file descriptor to hold debugging information for a file.
Wrapper structure that holds source language identity metadata that includes language name,...
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
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)
const BasicBlock & getEntryBlock() const
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)
LLVM_ABI void setSection(StringRef S)
Change the section for this global.
const Comdat * getComdat() const
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
bool hasSection() const
Check if this global has a custom object file section.
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.
bool isDeclarationForLinker() const
void setDSOLocal(bool Local)
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 ...
bool hasInitializer() const
Definitions have initializers, declarations don't.
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.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
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)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
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(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
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)
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
bool insert(const value_type &X)
Insert a new element into the SetVector.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
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.
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.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
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
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 bool 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.
void insert_range(Range &&R)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements a layout algorithm for globals referenced by bit sets that tries to keep member...
LLVM_ABI const std::vector< uint64_t > & build()
Flatten fragments into a single layout and return it.
LLVM_ABI void addFragment(const std::set< uint64_t > &F)
Add F to the layout while trying to keep its indices contiguous.
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.
@ 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)
LLVM_ABI bool isJumpTableCanonical(Function *F)
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.
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.
detail::zip_longest_range< T, U, Args... > zip_longest(T &&t, U &&u, Args &&... args)
Iterate over two or more iterators at the same time.
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<X> - Return the argument parameter cast to the specified type.
@ 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.
@ O1
Optimize quickly without destroying debuggability.
@ O2
Optimize for fast execution as much as possible without triggering significant incremental compile ti...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ 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.
DWARFExpression::Operation Op
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
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<X> - 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.
LLVM_ABI std::unique_ptr< ModuleSummaryIndex > parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err)
Parse LLVM Assembly for summary index from a MemoryBuffer.
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 ...
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
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()
SmallVector< uint64_t, 16 > Offsets
LLVM_ABI bool containsGlobalOffset(uint64_t Offset) const
LLVM_ABI void print(raw_ostream &OS) const
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.