86#include <system_error>
93#define DEBUG_TYPE "lowertypetests"
95STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
96STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
97STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
98STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
99STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
102 "lowertypetests-avoid-reuse",
103 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
107 "lowertypetests-summary-action",
108 cl::desc(
"What to do with the summary when running this pass"),
111 "Import typeid resolutions from summary and globals"),
113 "Export typeid resolutions to summary and globals")),
117 "lowertypetests-read-summary",
118 cl::desc(
"Read summary from given YAML file before running pass"),
122 "lowertypetests-write-summary",
123 cl::desc(
"Write summary to given YAML file after running pass"),
195 std::vector<uint64_t> &Fragment =
Fragments.back();
198 for (
auto ObjIndex :
F) {
200 if (OldFragmentIndex == 0) {
203 Fragment.push_back(ObjIndex);
210 std::vector<uint64_t> &OldFragment =
Fragments[OldFragmentIndex];
233 unsigned ReqSize = AllocByteOffset + BitSize;
235 if (
Bytes.size() < ReqSize)
236 Bytes.resize(ReqSize);
239 AllocMask = 1 << Bit;
241 Bytes[AllocByteOffset +
B] |= AllocMask;
245 if (
F->isDeclarationForLinker())
248 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
249 if (!CI || !CI->isZero())
251 return F->hasFnAttribute(
"cfi-canonical-jump-table");
256struct ByteArrayInfo {
257 std::set<uint64_t> Bits;
269class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
280 bool IsJumpTableCanonical;
288 bool IsJumpTableCanonical,
bool IsExported,
290 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
291 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
293 GTM->NTypes = Types.size();
294 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
295 GTM->IsExported = IsExported;
300 GlobalObject *getGlobal()
const {
305 return IsJumpTableCanonical;
308 bool isExported()
const {
315struct ICallBranchFunnel final
316 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
320 auto *
Call =
static_cast<ICallBranchFunnel *
>(
321 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
322 alignof(ICallBranchFunnel)));
324 Call->UniqueId = UniqueId;
332 return getTrailingObjects(NTargets);
341struct ScopedSaveAliaseesAndUsed {
344 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
345 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
350 void collectAndEraseUsedFunctions(
Module &M,
351 SmallVectorImpl<GlobalValue *> &Vec,
359 GV->eraseFromParent();
361 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
362 return isa<Function>(GV);
371 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
384 collectAndEraseUsedFunctions(M, Used,
false);
385 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
387 for (
auto &GA :
M.aliases()) {
391 FunctionAliases.push_back({&GA,
F});
394 for (
auto &GI :
M.ifuncs())
396 ResolverIFuncs.push_back({&GI,
F});
399 ~ScopedSaveAliaseesAndUsed() {
403 for (
auto P : FunctionAliases)
404 P.first->setAliasee(
P.second);
406 for (
auto P : ResolverIFuncs) {
410 P.first->setResolver(
P.second);
415class LowerTypeTestsModule {
418 ModuleSummaryIndex *ExportSummary;
419 const ModuleSummaryIndex *ImportSummary;
428 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
431 int HasBranchTargetEnforcement = -1;
433 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
434 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
435 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
436 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
437 IntegerType *
Int32Ty = Type::getInt32Ty(
M.getContext());
438 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
439 IntegerType *IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
442 uint64_t IndirectIndex = 1;
447 struct TypeIdUserInfo {
448 std::vector<CallInst *> CallSites;
449 bool IsExported =
false;
451 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
457 struct TypeIdLowering {
482 std::vector<ByteArrayInfo> ByteArrayInfos;
484 Function *WeakInitializerFn =
nullptr;
486 GlobalVariable *GlobalAnnotation;
487 DenseSet<Value *> FunctionAnnotations;
489 bool shouldExportConstantsAsAbsoluteSymbols();
490 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
491 TypeIdLowering importTypeId(StringRef TypeId);
492 void importTypeTest(CallInst *CI);
495 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
496 void allocateByteArrays();
499 void lowerTypeTestCalls(
501 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
503 const TypeIdLowering &TIL);
509 bool hasBranchTargetEnforcement();
512 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
524 void replaceWeakDeclarationWithJumpTablePtr(Function *
F, Constant *JT,
525 bool IsJumpTableCanonical);
526 void moveInitializerToModuleConstructor(GlobalVariable *GV);
527 void findGlobalVariableUsersOf(Constant *
C,
528 SmallSetVector<GlobalVariable *, 8> &Out);
538 void replaceCfiUses(Function *Old,
Value *New,
bool IsJumpTableCanonical);
542 void replaceDirectCalls(
Value *Old,
Value *New);
544 bool isFunctionAnnotation(
Value *V)
const {
545 return FunctionAnnotations.
contains(V);
548 void maybeReplaceComdat(Function *
F, StringRef OriginalName);
552 ModuleSummaryIndex *ExportSummary,
553 const ModuleSummaryIndex *ImportSummary);
575 unsigned BitWidth = BitsType->getBitWidth();
577 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
579 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
580 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
581 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
582 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
585ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
589 auto ByteArrayGlobal =
new GlobalVariable(
591 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
594 ByteArrayInfos.emplace_back();
595 ByteArrayInfo *BAI = &ByteArrayInfos.back();
597 BAI->Bits = BSI.
Bits;
599 BAI->ByteArray = ByteArrayGlobal;
600 BAI->MaskGlobal = MaskGlobal;
604void LowerTypeTestsModule::allocateByteArrays() {
606 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
607 return BAI1.BitSize > BAI2.BitSize;
610 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
613 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
614 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
617 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
623 *BAI->MaskPtr =
Mask;
628 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
631 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
632 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
634 ByteArray, ConstantInt::get(IntPtrTy, ByteArrayOffsets[
I]));
648 ByteArraySizeBytes = BAB.
Bytes.size();
654 const TypeIdLowering &TIL,
668 "bits_use", ByteArray, &M);
671 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
676 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
684 GV->getMetadata(LLVMContext::MD_type, Types);
686 if (
Type->getOperand(1) != TypeId)
699 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
700 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
708 if (
Op->getOpcode() == Instruction::BitCast)
711 if (
Op->getOpcode() == Instruction::Select)
721Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
722 const TypeIdLowering &TIL) {
730 const DataLayout &
DL =
M.getDataLayout();
738 Value *PtrAsInt =
B.CreatePtrToInt(Ptr, IntPtrTy);
743 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
749 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
759 Value *BitOffset =
B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr,
760 {PtrOffset, PtrOffset, TIL.AlignLog2});
762 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
766 return OffsetInRange;
778 NewBr->setMetadata(LLVMContext::MD_prof,
779 Br->getMetadata(LLVMContext::MD_prof));
783 for (
auto &Phi :
Else->phis())
784 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
787 return createBitSetTest(ThenB, TIL, BitOffset);
790 MDBuilder MDB(
M.getContext());
792 MDB.createLikelyBranchWeights()));
796 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
801 B.SetInsertPoint(CI);
802 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
803 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
804 P->addIncoming(Bit, ThenB.GetInsertBlock());
810void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
817 std::vector<Constant *> GlobalInits;
818 const DataLayout &
DL =
M.getDataLayout();
819 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
821 uint64_t CurOffset = 0;
822 uint64_t DesiredPadding = 0;
823 for (GlobalTypeMember *
G : Globals) {
826 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
827 MaxAlign = std::max(MaxAlign, Alignment);
828 uint64_t GVOffset =
alignTo(CurOffset + DesiredPadding, Alignment);
829 GlobalLayout[
G] = GVOffset;
831 uint64_t
Padding = GVOffset - CurOffset;
832 GlobalInits.push_back(
836 GlobalInits.push_back(GV->getInitializer());
837 uint64_t InitSize = GV->getGlobalSize(
DL);
838 CurOffset = GVOffset + InitSize;
847 if (DesiredPadding > 32)
848 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
852 auto *CombinedGlobal =
853 new GlobalVariable(M, NewInit->
getType(),
true,
855 CombinedGlobal->setAlignment(MaxAlign);
858 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
863 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
870 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
872 GlobalAlias *GAlias =
874 "", CombinedGlobalElemPtr, &M);
882bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
895uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
896 const TypeIdLowering &TIL) {
897 TypeTestResolution &TTRes =
904 "__typeid_" + TypeId +
"_" + Name,
C, &M);
908 auto ExportConstant = [&](StringRef
Name, uint64_t &Storage,
Constant *
C) {
909 if (shouldExportConstantsAsAbsoluteSymbols())
916 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
921 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
922 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
932 ExportGlobal(
"byte_array", TIL.TheByteArray);
933 if (shouldExportConstantsAsAbsoluteSymbols())
934 ExportGlobal(
"bit_mask", TIL.BitMask);
940 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
945LowerTypeTestsModule::TypeIdLowering
946LowerTypeTestsModule::importTypeId(StringRef TypeId) {
950 const TypeTestResolution &TTRes = TidSummary->
TTRes;
955 auto ImportGlobal = [&](StringRef
Name) {
958 GlobalVariable *GV =
M.getOrInsertGlobal(
959 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
964 auto ImportConstant = [&](StringRef
Name, uint64_t
Const,
unsigned AbsWidth,
966 if (!shouldExportConstantsAsAbsoluteSymbols()) {
978 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
981 auto SetAbsRange = [&](uint64_t Min, uint64_t
Max) {
991 SetAbsRange(0, 1ull << AbsWidth);
997 auto *GV = ImportGlobal(
"global_addr");
1010 TIL.OffsetedGlobal = GV;
1016 TIL.AlignLog2 = ImportConstant(
"align", TTRes.
AlignLog2, 8, IntPtrTy);
1022 TIL.TheByteArray = ImportGlobal(
"byte_array");
1023 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1027 TIL.InlineBits = ImportConstant(
1034void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1046 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1047 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1054void LowerTypeTestsModule::maybeReplaceComdat(Function *
F,
1055 StringRef OriginalName) {
1061 F->getComdat()->getName() == OriginalName) {
1062 Comdat *OldComdat =
F->getComdat();
1063 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1064 for (GlobalObject &GO :
M.global_objects()) {
1073void LowerTypeTestsModule::importFunction(Function *
F,
1075 assert(
F->getType()->getAddressSpace() == 0);
1078 std::string
Name = std::string(
F->getName());
1083 if (
F->isDSOLocal()) {
1086 F->getAddressSpace(),
1089 replaceDirectCalls(
F, RealF);
1099 F->getAddressSpace(), Name +
".cfi_jt", &M);
1102 F->setName(Name +
".cfi");
1103 maybeReplaceComdat(
F, Name);
1105 F->getAddressSpace(), Name, &M);
1112 for (
auto &U :
F->uses()) {
1114 std::string AliasName =
A->getName().str() +
".cfi";
1117 F->getAddressSpace(),
"", &M);
1119 A->replaceAllUsesWith(AliasDecl);
1120 A->setName(AliasName);
1125 if (
F->hasExternalWeakLinkage())
1132 F->setVisibility(Visibility);
1141 OffsetsByTypeID[TypeId];
1142 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1144 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1145 if (It == OffsetsByTypeID.
end())
1151 It->second.push_back(MemOff +
Offset);
1161 dbgs() << MDS->getString() <<
": ";
1163 dbgs() <<
"<unnamed>: ";
1164 BitSets.
back().second.print(
dbgs());
1171void LowerTypeTestsModule::lowerTypeTestCalls(
1173 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1175 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1176 ByteArrayInfo *BAI =
nullptr;
1179 uint64_t GlobalOffset =
1182 CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),
1183 TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.
AlignLog2);
1184 TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.
BitSize - 1);
1187 : TypeTestResolution::
AllOnes;
1190 uint64_t InlineBits = 0;
1191 for (
auto Bit : BSI.
Bits)
1192 InlineBits |= uint64_t(1) <<
Bit;
1193 if (InlineBits == 0)
1196 TIL.InlineBits = ConstantInt::get(
1200 ++NumByteArraysCreated;
1201 BAI = createByteArray(BSI);
1202 TIL.TheByteArray = BAI->ByteArray;
1203 TIL.BitMask = BAI->MaskGlobal;
1206 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1208 if (TIUI.IsExported) {
1209 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1211 BAI->MaskPtr = MaskPtr;
1215 for (CallInst *CI : TIUI.CallSites) {
1216 ++NumTypeTestCallsLowered;
1217 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1226void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1227 if (
Type->getNumOperands() != 2)
1234 "A member of a type identifier may not have an explicit section");
1257bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1258 if (HasBranchTargetEnforcement == -1) {
1262 M.getModuleFlag(
"branch-target-enforcement")))
1263 HasBranchTargetEnforcement = !BTE->isZero();
1265 HasBranchTargetEnforcement = 0;
1267 return HasBranchTargetEnforcement;
1271LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1272 switch (JumpTableArch) {
1276 M.getModuleFlag(
"cf-protection-branch")))
1277 if (MD->getZExtValue())
1283 if (CanUseThumbBWJumpTable) {
1284 if (hasBranchTargetEnforcement())
1291 if (hasBranchTargetEnforcement())
1310LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1312 raw_string_ostream AsmOS(Asm);
1317 M.getModuleFlag(
"cf-protection-branch")))
1318 Endbr = !MD->isZero();
1320 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1321 AsmOS <<
"jmp ${0:c}@plt\n";
1323 AsmOS <<
".balign 16, 0xcc\n";
1325 AsmOS <<
"int3\nint3\nint3\n";
1329 if (hasBranchTargetEnforcement())
1333 if (!CanUseThumbBWJumpTable) {
1349 AsmOS <<
"push {r0,r1}\n"
1351 <<
"0: add r0, r0, pc\n"
1352 <<
"str r0, [sp, #4]\n"
1355 <<
"1: .word $0 - (0b + 4)\n";
1357 if (hasBranchTargetEnforcement())
1359 AsmOS <<
"b.w $0\n";
1363 AsmOS <<
"tail $0@plt\n";
1365 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1366 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1368 AsmOS <<
"jump $0\n";
1381void LowerTypeTestsModule::buildBitSetsFromFunctions(
1387 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1389 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1394void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1395 GlobalVariable *GV) {
1396 if (WeakInitializerFn ==
nullptr) {
1401 M.getDataLayout().getProgramAddressSpace(),
1402 "__cfi_global_var_init", &M);
1406 WeakInitializerFn->setSection(
1408 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1415 IRBuilder<> IRB(WeakInitializerFn->getEntryBlock().getTerminator());
1421void LowerTypeTestsModule::findGlobalVariableUsersOf(
1422 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1423 for (
auto *U :
C->users()){
1427 findGlobalVariableUsersOf(C2, Out);
1432void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1433 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1436 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1437 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1438 for (
auto *GV : GlobalVarUsers) {
1439 if (GV == GlobalAnnotation)
1441 moveInitializerToModuleConstructor(GV);
1448 F->getAddressSpace(),
"", &M);
1449 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1456 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1459 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1471 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1479 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1484 if (Feature ==
"-thumb-mode")
1486 else if (Feature ==
"+thumb-mode")
1502 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1510 unsigned ArmCount = 0, ThumbCount = 0;
1511 for (
const auto GTM : Functions) {
1512 if (!GTM->isJumpTableCanonical()) {
1526void LowerTypeTestsModule::createJumpTable(
1532 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1538 bool areAllEntriesNounwind =
true;
1539 for (GlobalTypeMember *GTM : Functions) {
1541 ->hasFnAttribute(llvm::Attribute::NoUnwind)) {
1542 areAllEntriesNounwind =
false;
1544 IRB.CreateCall(JumpTableAsm, GTM->getGlobal());
1546 IRB.CreateUnreachable();
1549 F->setAlignment(
Align(getJumpTableEntrySize(JumpTableArch)));
1550 F->addFnAttr(Attribute::Naked);
1552 F->addFnAttr(
"target-features",
"-thumb-mode");
1554 if (hasBranchTargetEnforcement()) {
1557 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1559 F->addFnAttr(
"target-features",
"+thumb-mode");
1560 if (CanUseThumbBWJumpTable) {
1563 F->addFnAttr(
"target-cpu",
"cortex-a8");
1571 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1572 F->removeFnAttr(
"branch-target-enforcement");
1573 if (
F->hasFnAttribute(
"sign-return-address"))
1574 F->removeFnAttr(
"sign-return-address");
1579 F->addFnAttr(
"target-features",
"-c,-relax");
1585 F->addFnAttr(Attribute::NoCfCheck);
1588 if (areAllEntriesNounwind)
1589 F->addFnAttr(Attribute::NoUnwind);
1592 F->addFnAttr(Attribute::NoInline);
1597void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1682 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1683 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1684 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1685 GlobalLayout[Functions[
I]] =
I * EntrySize;
1691 M.getDataLayout().getProgramAddressSpace(),
1692 ".cfi.jumptable", &M);
1699 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1703 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1705 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1708 JumpTableType, JumpTable,
1710 ConstantInt::get(IntPtrTy,
I)});
1712 const bool IsExported = Functions[
I]->isExported();
1713 if (!IsJumpTableCanonical) {
1717 F->getName() +
".cfi_jt",
1718 CombinedGlobalElemPtr, &M);
1726 if (IsJumpTableCanonical)
1732 if (!IsJumpTableCanonical) {
1733 if (
F->hasExternalWeakLinkage())
1734 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1735 IsJumpTableCanonical);
1737 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1739 assert(
F->getType()->getAddressSpace() == 0);
1741 GlobalAlias *FAlias =
1743 CombinedGlobalElemPtr, &M);
1747 F->setName(FAlias->
getName() +
".cfi");
1748 maybeReplaceComdat(
F, FAlias->
getName());
1750 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1751 if (!
F->hasLocalLinkage())
1756 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1765void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1770 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1772 for (GlobalTypeMember *GTM : Functions) {
1776 if (!
F->hasAddressTaken())
1782 ConstantInt::get(Int64Ty, IndirectIndex))));
1783 F->setMetadata(
"wasm.index", MD);
1786 GlobalLayout[GTM] = IndirectIndex++;
1795void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1798 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1799 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1800 TypeIdIndices[TypeIds[
I]] =
I;
1804 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1805 unsigned GlobalIndex = 0;
1806 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1807 for (GlobalTypeMember *GTM : Globals) {
1808 for (MDNode *
Type : GTM->types()) {
1810 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1811 if (
I != TypeIdIndices.
end())
1812 TypeMembers[
I->second].insert(GlobalIndex);
1814 GlobalIndices[GTM] = GlobalIndex;
1818 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1819 TypeMembers.emplace_back();
1820 std::set<uint64_t> &TMSet = TypeMembers.back();
1821 for (GlobalTypeMember *
T : JT->targets())
1822 TMSet.insert(GlobalIndices[
T]);
1828 const std::set<uint64_t> &O2) {
1829 return O1.size() < O2.size();
1836 for (
auto &&MemSet : TypeMembers)
1837 GLB.addFragment(MemSet);
1842 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1843 auto OGTMI = OrderedGTMs.begin();
1844 for (
auto &&
F : GLB.Fragments) {
1848 "variables and functions");
1849 *OGTMI++ = Globals[
Offset];
1855 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1857 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1861LowerTypeTestsModule::LowerTypeTestsModule(
1863 const ModuleSummaryIndex *ImportSummary)
1864 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
1865 assert(!(ExportSummary && ImportSummary));
1866 Triple TargetTriple(M.getTargetTriple());
1867 Arch = TargetTriple.getArch();
1869 CanUseArmJumpTable =
true;
1875 if (
F.isDeclaration())
1878 if (
TTI.hasArmWideBranch(
false))
1879 CanUseArmJumpTable =
true;
1880 if (
TTI.hasArmWideBranch(
true))
1881 CanUseThumbBWJumpTable =
true;
1884 OS = TargetTriple.getOS();
1885 ObjectFormat = TargetTriple.getObjectFormat();
1889 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
1890 if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {
1893 FunctionAnnotations.insert_range(CA->
operands());
1898 ModuleSummaryIndex
Summary(
false);
1903 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
1908 yaml::Input
In(ReadSummaryFile->getBuffer());
1914 LowerTypeTestsModule(
1921 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
1927 yaml::Output Out(OS);
1936 return Usr && Usr->isCallee(&U);
1939void LowerTypeTestsModule::replaceCfiUses(Function *Old,
Value *New,
1940 bool IsJumpTableCanonical) {
1941 SmallSetVector<Constant *, 4>
Constants;
1953 if (isFunctionAnnotation(
U.getUser()))
1971 for (
auto *
C : Constants)
1972 C->handleOperandChange(Old, New);
1975void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
1980 bool ShouldDropAll) {
1986 Assume->eraseFromParent();
1995 return isa<PHINode>(U) || isa<SelectInst>(U);
2013 if (PublicTypeTestFunc)
2015 if (TypeTestFunc || PublicTypeTestFunc) {
2026bool LowerTypeTestsModule::lower() {
2040 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2041 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2042 !ExportSummary && !ImportSummary)
2045 if (ImportSummary) {
2050 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2052 "unexpected call to llvm.icall.branch.funnel during import phase");
2059 if (
F.hasLocalLinkage())
2068 ScopedSaveAliaseesAndUsed S(M);
2069 for (
auto *
F : Defs)
2070 importFunction(
F,
true);
2071 for (
auto *
F : Decls)
2072 importFunction(
F,
false);
2081 using GlobalClassesTy = EquivalenceClasses<
2082 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2083 GlobalClassesTy GlobalClasses;
2095 std::vector<GlobalTypeMember *> RefGlobals;
2097 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2098 unsigned CurUniqueId = 0;
2103 const bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
2105 struct ExportedFunctionInfo {
2109 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2110 if (ExportSummary) {
2111 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2112 if (CfiFunctionsMD) {
2114 DenseSet<GlobalValue::GUID> AddressTaken;
2115 for (
auto &
I : *ExportSummary)
2116 for (
auto &GVS :
I.second.getSummaryList())
2118 for (
const auto &
Ref : GVS->refs()) {
2120 for (
auto &RefGVS :
Ref.getSummaryList())
2122 AddressTaken.
insert(Alias->getAliaseeGUID());
2125 if (AddressTaken.
count(GUID))
2127 auto VI = ExportSummary->getValueInfo(GUID);
2130 for (
auto &
I :
VI.getSummaryList())
2132 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2136 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2137 assert(FuncMD->getNumOperands() >= 2);
2138 StringRef FunctionName =
2143 ->getUniqueInteger()
2150 if (!ExportSummary->isGUIDLive(GUID))
2157 if (
auto VI = ExportSummary->getValueInfo(GUID))
2158 for (
const auto &GVS :
VI.getSummaryList())
2165 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2167 P.first->second = {
Linkage, FuncMD};
2170 for (
const auto &
P : ExportedFunctions) {
2171 StringRef FunctionName =
P.first;
2173 MDNode *FuncMD =
P.second.FuncMD;
2175 if (
F &&
F->hasLocalLinkage()) {
2182 F->setName(
F->getName() +
".1");
2188 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2189 GlobalVariable::ExternalLinkage,
2190 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2197 if (
F->hasAvailableExternallyLinkage()) {
2200 F->setComdat(
nullptr);
2213 if (
F->isDeclaration()) {
2217 F->eraseMetadata(LLVMContext::MD_type);
2219 F->addMetadata(LLVMContext::MD_type,
2226 struct AliasToCreate {
2228 std::string TargetName;
2230 std::vector<AliasToCreate> AliasesToCreate;
2234 if (ExportSummary) {
2235 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2236 for (
auto *AliasMD : AliasesMD->operands()) {
2238 for (
Metadata *MD : AliasMD->operands()) {
2242 StringRef AliasName = MDS->getString();
2243 if (!ExportedFunctions.count(AliasName))
2245 auto *AliasF =
M.getFunction(AliasName);
2250 if (Aliases.
empty())
2253 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2254 auto *AliasF = Aliases[
I];
2255 ExportedFunctions.
erase(AliasF->getName());
2256 AliasesToCreate.push_back(
2257 {AliasF, std::string(Aliases[0]->
getName())});
2263 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2264 for (GlobalObject &GO :
M.global_objects()) {
2271 bool IsJumpTableCanonical =
false;
2272 bool IsExported =
false;
2275 if (
auto It = ExportedFunctions.find(
F->getName());
2276 It != ExportedFunctions.end()) {
2283 }
else if (!
F->hasAddressTaken()) {
2284 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2289 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2291 GlobalTypeMembers[&GO] = GTM;
2292 for (MDNode *
Type : Types) {
2293 verifyTypeMDNode(&GO,
Type);
2294 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2295 Info.UniqueId = ++CurUniqueId;
2296 Info.RefGlobals.push_back(GTM);
2300 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2305 auto Ins = TypeIdUsers.insert({TypeId, {}});
2308 auto &GCI = GlobalClasses.insert(TypeId);
2309 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2312 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2313 CurSet = GlobalClasses.unionSets(
2314 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2317 return Ins.first->second;
2321 for (
const Use &U : TypeTestFunc->
uses()) {
2330 for (
const Use &CIU : CI->
uses()) {
2333 OnlyAssumeUses =
false;
2342 auto TypeId = TypeIdMDVal->getMetadata();
2343 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2347 if (ICallBranchFunnelFunc) {
2348 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2351 "llvm.icall.branch.funnel not supported on this target");
2355 std::vector<GlobalTypeMember *> Targets;
2359 GlobalClassesTy::member_iterator CurSet;
2360 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2366 "Expected branch funnel operand to be global value");
2368 GlobalTypeMember *GTM = GlobalTypeMembers[
Base];
2369 Targets.push_back(GTM);
2370 GlobalClassesTy::member_iterator NewSet =
2371 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2375 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2378 GlobalClasses.unionSets(
2379 CurSet, GlobalClasses.findLeader(
2380 GlobalClasses.insert(ICallBranchFunnel::create(
2381 Alloc, CI, Targets, ++CurUniqueId))));
2385 if (ExportSummary) {
2386 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2387 for (
auto &
P : TypeIdInfo) {
2390 TypeId->getString())]
2394 for (
auto &
P : *ExportSummary) {
2395 for (
auto &S :
P.second.getSummaryList()) {
2396 if (!ExportSummary->isGlobalValueLive(S.get()))
2401 AddTypeIdUse(MD).IsExported =
true;
2406 if (GlobalClasses.empty())
2410 ScopedSaveAliaseesAndUsed S(M);
2412 for (
const auto &
C : GlobalClasses) {
2416 ++NumTypeIdDisjointSets;
2418 std::vector<Metadata *> TypeIds;
2419 std::vector<GlobalTypeMember *> Globals;
2420 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2421 for (
auto M : GlobalClasses.members(*
C)) {
2434 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2439 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2440 return F1->UniqueId < F2->UniqueId;
2444 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2448 allocateByteArrays();
2450 for (
auto A : AliasesToCreate) {
2451 auto *
Target =
M.getNamedValue(
A.TargetName);
2455 AliasGA->setVisibility(
A.Alias->getVisibility());
2456 AliasGA->setLinkage(
A.Alias->getLinkage());
2457 AliasGA->takeName(
A.Alias);
2458 A.Alias->replaceAllUsesWith(AliasGA);
2459 A.Alias->eraseFromParent();
2463 if (ExportSummary) {
2464 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2465 for (
auto *Symver : SymversMD->operands()) {
2466 assert(Symver->getNumOperands() >= 2);
2469 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2471 if (!ExportedFunctions.count(SymbolName))
2474 M.appendModuleInlineAsm(
2475 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2487 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2489 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
2498 OS, MapClassName2PassName);
2501 case DropTestKind::Assume:
2504 case DropTestKind::All:
2537 for (
auto &GV : M.globals()) {
2544 auto MaySimplifyPtr = [&](
Value *Ptr) {
2546 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2550 auto MaySimplifyInt = [&](
Value *
Op) {
2552 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2554 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2570 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2574 if (U.getOperandNo() == 0 && CE &&
2575 CE->getOpcode() == Instruction::Sub &&
2576 MaySimplifyInt(CE->getOperand(1))) {
2582 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2586 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< 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 bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)
static const unsigned kX86IBTJumpTableEntrySize
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
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< 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 contains library features backported from future STL versions.
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.
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.
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 emplace(Args &&...A)
size_t count(StringRef S) 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.
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.
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)
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.
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.
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.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
uint64_t getBitMask() const
Return a bitmask with ones set for all of the bits that can be set by an unsigned version of this typ...
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)
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)
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 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.
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 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)
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.
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<X> - 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)
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...
@ 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.
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 ...
A CRTP mix-in to automatically provide informational APIs needed for passes.
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.
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.
std::vector< uint64_t > FragmentMap
Mapping from object index to fragment index.