87#include <system_error>
94#define DEBUG_TYPE "lowertypetests"
96STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
97STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
98STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
99STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
100STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
103 "lowertypetests-avoid-reuse",
104 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
108 "lowertypetests-summary-action",
109 cl::desc(
"What to do with the summary when running this pass"),
112 "Import typeid resolutions from summary and globals"),
114 "Export typeid resolutions to summary and globals")),
118 "lowertypetests-read-summary",
119 cl::desc(
"Read summary from given YAML file before running pass"),
123 "lowertypetests-write-summary",
124 cl::desc(
"Write summary to given YAML file after running pass"),
130 cl::desc(
"Enable debug info generation for jump tables"));
156 for (uint64_t
B :
Bits)
201 std::vector<uint64_t> &Fragment =
Fragments.back();
202 uint64_t FragmentIndex =
Fragments.size() - 1;
204 for (
auto ObjIndex :
F) {
206 if (OldFragmentIndex == 0) {
209 Fragment.push_back(ObjIndex);
216 std::vector<uint64_t> &OldFragment =
Fragments[OldFragmentIndex];
223 for (uint64_t ObjIndex : Fragment)
228 uint64_t BitSize, uint64_t &AllocByteOffset,
239 unsigned ReqSize = AllocByteOffset + BitSize;
241 if (
Bytes.size() < ReqSize)
242 Bytes.resize(ReqSize);
245 AllocMask = 1 << Bit;
246 for (uint64_t
B : Bits)
247 Bytes[AllocByteOffset +
B] |= AllocMask;
251 if (
F->isDeclarationForLinker())
254 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
255 if (!CI || !CI->isZero())
257 return F->hasFnAttribute(
"cfi-canonical-jump-table");
262struct ByteArrayInfo {
263 std::set<uint64_t> Bits;
275class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
286 bool IsJumpTableCanonical;
294 bool IsJumpTableCanonical,
bool IsExported,
296 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
297 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
299 GTM->NTypes = Types.size();
300 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
301 GTM->IsExported = IsExported;
306 GlobalObject *getGlobal()
const {
311 return IsJumpTableCanonical;
314 bool isExported()
const {
321struct ICallBranchFunnel final
322 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
326 auto *
Call =
static_cast<ICallBranchFunnel *
>(
327 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
328 alignof(ICallBranchFunnel)));
330 Call->UniqueId = UniqueId;
338 return getTrailingObjects(NTargets);
347struct ScopedSaveAliaseesAndUsed {
350 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
351 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
356 void collectAndEraseUsedFunctions(
Module &M,
357 SmallVectorImpl<GlobalValue *> &Vec,
365 GV->eraseFromParent();
367 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
368 return isa<Function>(GV);
377 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
390 collectAndEraseUsedFunctions(M, Used,
false);
391 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
393 for (
auto &GA :
M.aliases()) {
397 FunctionAliases.push_back({&GA,
F});
400 for (
auto &GI :
M.ifuncs())
402 ResolverIFuncs.push_back({&GI,
F});
405 ~ScopedSaveAliaseesAndUsed() {
409 for (
auto P : FunctionAliases)
410 P.first->setAliasee(
P.second);
412 for (
auto P : ResolverIFuncs) {
416 P.first->setResolver(
P.second);
421class LowerTypeTestsModule {
424 ModuleSummaryIndex *ExportSummary;
425 const ModuleSummaryIndex *ImportSummary;
434 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
437 int HasBranchTargetEnforcement = -1;
439 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
440 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
441 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
442 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
443 IntegerType *Int32Ty = Type::getInt32Ty(
M.getContext());
444 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
445 IntegerType *
IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
453 struct TypeIdUserInfo {
454 std::vector<CallInst *> CallSites;
455 bool IsExported =
false;
457 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
463 struct TypeIdLowering {
488 std::vector<ByteArrayInfo> ByteArrayInfos;
490 Function *WeakInitializerFn =
nullptr;
492 GlobalVariable *GlobalAnnotation;
493 DenseSet<Value *> FunctionAnnotations;
497 bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
499 bool shouldExportConstantsAsAbsoluteSymbols();
500 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
501 TypeIdLowering importTypeId(StringRef TypeId);
502 void importTypeTest(CallInst *CI);
505 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
506 void allocateByteArrays();
509 void lowerTypeTestCalls(
511 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
513 const TypeIdLowering &TIL);
519 bool hasBranchTargetEnforcement();
522 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
534 void replaceWeakDeclarationWithJumpTablePtr(
Function *
F, Constant *JT,
535 bool IsJumpTableCanonical);
536 void moveInitializerToModuleConstructor(GlobalVariable *GV);
537 void findGlobalVariableUsersOf(Constant *
C,
538 SmallSetVector<GlobalVariable *, 8> &Out);
548 void replaceCfiUses(
Function *Old,
Value *New,
bool IsJumpTableCanonical);
552 void replaceDirectCalls(
Value *Old,
Value *New);
554 bool isFunctionAnnotation(
Value *V)
const {
555 return FunctionAnnotations.
contains(V);
558 void maybeReplaceComdat(
Function *
F, StringRef OriginalName);
562 ModuleSummaryIndex *ExportSummary,
563 const ModuleSummaryIndex *ImportSummary);
585 unsigned BitWidth = BitsType->getBitWidth();
587 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
589 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
590 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
591 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
592 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
595ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
599 auto ByteArrayGlobal =
new GlobalVariable(
601 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
604 ByteArrayInfos.emplace_back();
605 ByteArrayInfo *BAI = &ByteArrayInfos.back();
607 BAI->Bits = BSI.
Bits;
609 BAI->ByteArray = ByteArrayGlobal;
610 BAI->MaskGlobal = MaskGlobal;
614void LowerTypeTestsModule::allocateByteArrays() {
616 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
617 return BAI1.BitSize > BAI2.BitSize;
620 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
623 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
624 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
627 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
633 *BAI->MaskPtr =
Mask;
638 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
641 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
642 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
644 ByteArray, ConstantInt::get(
IntPtrTy, ByteArrayOffsets[
I]));
658 ByteArraySizeBytes = BAB.
Bytes.size();
664 const TypeIdLowering &TIL,
678 "bits_use", ByteArray, &M);
681 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
686 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
694 GV->getMetadata(LLVMContext::MD_type, Types);
696 if (
Type->getOperand(1) != TypeId)
709 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
710 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
718 if (
Op->getOpcode() == Instruction::BitCast)
721 if (
Op->getOpcode() == Instruction::Select)
731Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
732 const TypeIdLowering &TIL) {
740 const DataLayout &
DL =
M.getDataLayout();
753 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
759 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
770 {PtrOffset, PtrOffset, TIL.AlignLog2});
772 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
776 return OffsetInRange;
789 Br->getMetadata(LLVMContext::MD_prof));
793 for (
auto &Phi :
Else->phis())
794 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
797 return createBitSetTest(ThenB, TIL, BitOffset);
800 MDBuilder MDB(
M.getContext());
802 MDB.createLikelyBranchWeights()));
806 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
811 B.SetInsertPoint(CI);
812 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
813 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
814 P->addIncoming(Bit, ThenB.GetInsertBlock());
820void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
827 std::vector<Constant *> GlobalInits;
828 const DataLayout &
DL =
M.getDataLayout();
829 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
833 for (GlobalTypeMember *
G : Globals) {
836 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
837 MaxAlign = std::max(MaxAlign, Alignment);
839 GlobalLayout[
G] = GVOffset;
842 GlobalInits.push_back(
846 GlobalInits.push_back(GV->getInitializer());
848 CurOffset = GVOffset + InitSize;
857 if (DesiredPadding > 32)
858 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
862 auto *CombinedGlobal =
863 new GlobalVariable(M, NewInit->
getType(),
true,
865 CombinedGlobal->setAlignment(MaxAlign);
868 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
873 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
877 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
878 ConstantInt::get(Int32Ty,
I * 2)};
880 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
882 GlobalAlias *GAlias =
884 "", CombinedGlobalElemPtr, &M);
892bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
905uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
906 const TypeIdLowering &TIL) {
907 TypeTestResolution &TTRes =
914 "__typeid_" + TypeId +
"_" + Name,
C, &M);
919 if (shouldExportConstantsAsAbsoluteSymbols())
926 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
931 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
932 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
942 ExportGlobal(
"byte_array", TIL.TheByteArray);
943 if (shouldExportConstantsAsAbsoluteSymbols())
944 ExportGlobal(
"bit_mask", TIL.BitMask);
950 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
955LowerTypeTestsModule::TypeIdLowering
956LowerTypeTestsModule::importTypeId(StringRef TypeId) {
960 const TypeTestResolution &TTRes = TidSummary->
TTRes;
965 auto ImportGlobal = [&](StringRef
Name) {
968 GlobalVariable *GV =
M.getOrInsertGlobal(
969 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
976 if (!shouldExportConstantsAsAbsoluteSymbols()) {
988 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
997 if (AbsWidth ==
IntPtrTy->getBitWidth()) {
1001 SetAbsRange(0, 1ull << AbsWidth);
1007 auto *GV = ImportGlobal(
"global_addr");
1020 TIL.OffsetedGlobal = GV;
1032 TIL.TheByteArray = ImportGlobal(
"byte_array");
1033 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1037 TIL.InlineBits = ImportConstant(
1044void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1056 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1057 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1064void LowerTypeTestsModule::maybeReplaceComdat(
Function *
F,
1065 StringRef OriginalName) {
1071 F->getComdat()->getName() == OriginalName) {
1072 Comdat *OldComdat =
F->getComdat();
1073 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1074 for (GlobalObject &GO :
M.global_objects()) {
1083void LowerTypeTestsModule::importFunction(
Function *
F,
1085 assert(
F->getType()->getAddressSpace() == 0);
1088 std::string
Name = std::string(
F->getName());
1093 if (
F->isDSOLocal()) {
1096 F->getAddressSpace(),
1099 replaceDirectCalls(
F, RealF);
1109 F->getAddressSpace(), Name +
".cfi_jt", &M);
1112 F->setName(Name +
".cfi");
1113 maybeReplaceComdat(
F, Name);
1115 F->getAddressSpace(), Name, &M);
1123 for (
auto &U :
F->uses()) {
1125 std::string AliasName =
A->getName().str() +
".cfi";
1128 F->getAddressSpace(),
"", &M);
1130 A->replaceAllUsesWith(AliasDecl);
1131 A->setName(AliasName);
1137 if (
F->hasExternalWeakLinkage())
1144 F->setVisibility(Visibility);
1153 OffsetsByTypeID[TypeId];
1154 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1156 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1157 if (It == OffsetsByTypeID.
end())
1163 It->second.push_back(MemOff +
Offset);
1173 dbgs() << MDS->getString() <<
": ";
1175 dbgs() <<
"<unnamed>: ";
1176 BitSets.
back().second.print(
dbgs());
1183void LowerTypeTestsModule::lowerTypeTestCalls(
1185 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1187 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1188 ByteArrayInfo *BAI =
nullptr;
1194 CombinedGlobalAddr, ConstantInt::get(
IntPtrTy, GlobalOffset)),
1199 : TypeTestResolution::
AllOnes;
1203 for (
auto Bit : BSI.
Bits)
1205 if (InlineBits == 0)
1208 TIL.InlineBits = ConstantInt::get(
1209 (BSI.
BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1212 ++NumByteArraysCreated;
1213 BAI = createByteArray(BSI);
1214 TIL.TheByteArray = BAI->ByteArray;
1215 TIL.BitMask = BAI->MaskGlobal;
1218 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1220 if (TIUI.IsExported) {
1221 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1223 BAI->MaskPtr = MaskPtr;
1227 for (CallInst *CI : TIUI.CallSites) {
1228 ++NumTypeTestCallsLowered;
1229 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1238void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1239 if (
Type->getNumOperands() != 2)
1246 "A member of a type identifier may not have an explicit section");
1269bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1270 if (HasBranchTargetEnforcement == -1) {
1274 M.getModuleFlag(
"branch-target-enforcement")))
1275 HasBranchTargetEnforcement = !BTE->isZero();
1277 HasBranchTargetEnforcement = 0;
1279 return HasBranchTargetEnforcement;
1283LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1284 switch (JumpTableArch) {
1288 M.getModuleFlag(
"cf-protection-branch")))
1289 if (MD->getZExtValue())
1295 if (CanUseThumbBWJumpTable) {
1296 if (hasBranchTargetEnforcement())
1303 if (hasBranchTargetEnforcement())
1322LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1324 raw_string_ostream AsmOS(Asm);
1329 M.getModuleFlag(
"cf-protection-branch")))
1330 Endbr = !MD->isZero();
1332 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1333 AsmOS <<
"jmp ${0:c}@plt\n";
1335 AsmOS <<
".balign 16, 0xcc\n";
1337 AsmOS <<
"int3\nint3\nint3\n";
1341 if (hasBranchTargetEnforcement())
1345 if (!CanUseThumbBWJumpTable) {
1361 AsmOS <<
"push {r0,r1}\n"
1363 <<
"0: add r0, r0, pc\n"
1364 <<
"str r0, [sp, #4]\n"
1367 <<
"1: .word $0 - (0b + 4)\n";
1369 if (hasBranchTargetEnforcement())
1371 AsmOS <<
"b.w $0\n";
1375 AsmOS <<
"tail $0@plt\n";
1377 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1378 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1380 AsmOS <<
"jump $0\n";
1393void LowerTypeTestsModule::buildBitSetsFromFunctions(
1399 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1401 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1406void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1407 GlobalVariable *GV) {
1408 if (WeakInitializerFn ==
nullptr) {
1413 M.getDataLayout().getProgramAddressSpace(),
1414 "__cfi_global_var_init", &M);
1420 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1433void LowerTypeTestsModule::findGlobalVariableUsersOf(
1434 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1435 for (
auto *U :
C->users()){
1439 findGlobalVariableUsersOf(C2, Out);
1444void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1445 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1448 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1449 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1450 for (
auto *GV : GlobalVarUsers) {
1451 if (GV == GlobalAnnotation)
1453 moveInitializerToModuleConstructor(GV);
1460 F->getAddressSpace(),
"", &M);
1461 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1468 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1471 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1483 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1491 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1496 if (Feature ==
"-thumb-mode")
1498 else if (Feature ==
"+thumb-mode")
1514 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1522 unsigned ArmCount = 0, ThumbCount = 0;
1523 for (
const auto GTM : Functions) {
1524 if (!GTM->isJumpTableCanonical()) {
1545 auto CUs = M.debug_compile_units();
1562 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1563 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1565 F->setSubprogram(UbsanSP);
1570 Locations.
reserve(Functions.size());
1572 for (
auto *Func : Functions) {
1573 StringRef FuncName = Func->getGlobal()->getName();
1576 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1577 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1582 Locations.push_back(EntryLoc);
1590void LowerTypeTestsModule::createJumpTable(
1599 F->setMetadata(LLVMContext::MD_elf_section_properties,
1602 ConstantAsMetadata::get(ConstantInt::get(
1603 Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
1604 ConstantAsMetadata::get(ConstantInt::get(
1605 Int64Ty, JumpTableEntrySize))}));
1614 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1620 bool areAllEntriesNounwind =
true;
1622 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1623 if (Loc.has_value())
1624 IRB.SetCurrentDebugLocation(*Loc);
1626 ->hasFnAttribute(Attribute::NoUnwind)) {
1627 areAllEntriesNounwind =
false;
1629 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1631 IRB.CreateUnreachable();
1634 F->setPreferredAlignment(
Align(JumpTableEntrySize));
1635 F->addFnAttr(Attribute::Naked);
1637 F->addFnAttr(
"target-features",
"-thumb-mode");
1639 if (hasBranchTargetEnforcement()) {
1642 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1644 F->addFnAttr(
"target-features",
"+thumb-mode");
1645 if (CanUseThumbBWJumpTable) {
1648 F->addFnAttr(
"target-cpu",
"cortex-a8");
1656 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1657 F->removeFnAttr(
"branch-target-enforcement");
1658 if (
F->hasFnAttribute(
"sign-return-address"))
1659 F->removeFnAttr(
"sign-return-address");
1664 F->addFnAttr(
"target-features",
"-c,-relax");
1670 F->addFnAttr(Attribute::NoCfCheck);
1673 if (areAllEntriesNounwind)
1674 F->addFnAttr(Attribute::NoUnwind);
1677 F->addFnAttr(Attribute::NoInline);
1682void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1767 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1768 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1769 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1770 GlobalLayout[Functions[
I]] =
I * EntrySize;
1776 M.getDataLayout().getProgramAddressSpace(),
1777 ".cfi.jumptable", &M);
1784 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1788 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1790 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1793 JumpTableType, JumpTable,
1797 const bool IsExported = Functions[
I]->isExported();
1798 if (!IsJumpTableCanonical) {
1802 F->getName() +
".cfi_jt",
1803 CombinedGlobalElemPtr, &M);
1812 if (IsJumpTableCanonical)
1820 if (!IsJumpTableCanonical) {
1821 if (
F->hasExternalWeakLinkage())
1822 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1823 IsJumpTableCanonical);
1825 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1827 assert(
F->getType()->getAddressSpace() == 0);
1829 GlobalAlias *FAlias =
1831 CombinedGlobalElemPtr, &M);
1836 F->setName(FAlias->
getName() +
".cfi");
1837 maybeReplaceComdat(
F, FAlias->
getName());
1839 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1840 if (!
F->hasLocalLinkage())
1845 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1854void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1859 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1861 for (GlobalTypeMember *GTM : Functions) {
1865 if (!
F->hasAddressTaken())
1871 ConstantInt::get(Int64Ty, IndirectIndex))));
1872 F->setMetadata(
"wasm.index", MD);
1875 GlobalLayout[GTM] = IndirectIndex++;
1884void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1887 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1888 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1889 TypeIdIndices[TypeIds[
I]] =
I;
1893 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1894 unsigned GlobalIndex = 0;
1895 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1896 for (GlobalTypeMember *GTM : Globals) {
1897 for (MDNode *
Type : GTM->types()) {
1899 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1900 if (
I != TypeIdIndices.
end())
1901 TypeMembers[
I->second].insert(GlobalIndex);
1903 GlobalIndices[GTM] = GlobalIndex;
1907 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1908 TypeMembers.emplace_back();
1909 std::set<uint64_t> &TMSet = TypeMembers.back();
1910 for (GlobalTypeMember *
T : JT->targets())
1911 TMSet.insert(GlobalIndices[
T]);
1917 const std::set<uint64_t> &
O2) {
1918 return O1.size() <
O2.size();
1925 for (
auto &&MemSet : TypeMembers)
1926 GLB.addFragment(MemSet);
1931 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1932 auto OGTMI = OrderedGTMs.begin();
1933 for (
auto &&
F : GLB.Fragments) {
1937 "variables and functions");
1938 *OGTMI++ = Globals[
Offset];
1944 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1946 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1950LowerTypeTestsModule::LowerTypeTestsModule(
1952 const ModuleSummaryIndex *ImportSummary)
1953 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
1954 assert(!(ExportSummary && ImportSummary));
1955 Triple TargetTriple(M.getTargetTriple());
1956 Arch = TargetTriple.getArch();
1958 CanUseArmJumpTable =
true;
1964 if (
F.isDeclaration())
1967 if (
TTI.hasArmWideBranch(
false))
1968 CanUseArmJumpTable =
true;
1969 if (
TTI.hasArmWideBranch(
true))
1970 CanUseThumbBWJumpTable =
true;
1973 OS = TargetTriple.getOS();
1974 ObjectFormat = TargetTriple.getObjectFormat();
1978 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
1987 ModuleSummaryIndex
Summary(
false);
1992 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
1997 yaml::Input
In(ReadSummaryFile->getBuffer());
2003 LowerTypeTestsModule(
2010 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
2016 yaml::Output Out(OS);
2025 return Usr && Usr->isCallee(&U);
2028void LowerTypeTestsModule::replaceCfiUses(
Function *Old,
Value *New,
2029 bool IsJumpTableCanonical) {
2030 SmallSetVector<Constant *, 4>
Constants;
2042 if (isFunctionAnnotation(
U.getUser()))
2060 for (
auto *
C : Constants)
2061 C->handleOperandChange(Old, New);
2064void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2069 bool ShouldDropAll) {
2075 Assume->eraseFromParent();
2084 return isa<PHINode>(U) || isa<SelectInst>(U);
2102 if (PublicTypeTestFunc)
2104 if (TypeTestFunc || PublicTypeTestFunc) {
2115bool LowerTypeTestsModule::lower() {
2129 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2130 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2131 !ExportSummary && !ImportSummary)
2134 if (ImportSummary) {
2139 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2141 "unexpected call to llvm.icall.branch.funnel during import phase");
2148 if (
A.hasLocalLinkage())
2153 if (
F->hasExternalLinkage()) {
2168 A.replaceAllUsesWith(
F);
2170 A.eraseFromParent();
2180 if (
F.hasLocalLinkage())
2189 ScopedSaveAliaseesAndUsed S(M);
2190 for (
auto *
F : Defs)
2191 importFunction(
F,
true);
2192 for (
auto *
F : Decls)
2193 importFunction(
F,
false);
2196 for (
auto &[
F, Name] : PromotedFuncs)
2205 using GlobalClassesTy = EquivalenceClasses<
2206 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2207 GlobalClassesTy GlobalClasses;
2219 std::vector<GlobalTypeMember *> RefGlobals;
2221 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2222 unsigned CurUniqueId = 0;
2225 struct ExportedFunctionInfo {
2229 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2230 if (ExportSummary) {
2231 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2232 if (CfiFunctionsMD) {
2234 DenseSet<GlobalValue::GUID> AddressTaken;
2235 for (
auto &
I : *ExportSummary)
2236 for (
auto &GVS :
I.second.getSummaryList())
2238 for (
const auto &
Ref : GVS->refs()) {
2240 for (
auto &RefGVS :
Ref.getSummaryList())
2242 AddressTaken.
insert(Alias->getAliaseeGUID());
2245 if (AddressTaken.
count(GUID))
2247 auto VI = ExportSummary->getValueInfo(GUID);
2250 for (
auto &
I :
VI.getSummaryList())
2252 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2256 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2257 assert(FuncMD->getNumOperands() >= 2);
2258 StringRef FunctionName =
2263 ->getUniqueInteger()
2268 ->getUniqueInteger()
2272 if (!ExportSummary->isGUIDLive(GUID))
2279 if (
auto VI = ExportSummary->getValueInfo(GUID))
2280 for (
const auto &GVS :
VI.getSummaryList())
2287 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2289 P.first->second = {
Linkage, FuncMD};
2292 for (
const auto &
P : ExportedFunctions) {
2293 StringRef FunctionName =
P.first;
2295 MDNode *FuncMD =
P.second.FuncMD;
2297 if (
F &&
F->hasLocalLinkage()) {
2304 F->setName(
F->getName() +
".1");
2310 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2311 GlobalVariable::ExternalLinkage,
2312 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2314 LLVMContext::MD_guid,
2315 MDTuple::get(
M.getContext(), {FuncMD->getOperand(2).get()}));
2316 if (ExportSummary) {
2320 ->getUniqueInteger()
2322 if (
auto VI = ExportSummary->getValueInfo(GUID))
2324 VI.isDSOLocal(ExportSummary->withDSOLocalPropagation()));
2332 if (
F->hasAvailableExternallyLinkage()) {
2334 auto *OrigGUIDMD =
F->getMetadata(LLVMContext::MD_guid);
2337 F->setComdat(
nullptr);
2339 F->setMetadata(LLVMContext::MD_guid, OrigGUIDMD);
2351 if (
F->isDeclaration()) {
2355 F->eraseMetadata(LLVMContext::MD_type);
2357 F->addMetadata(LLVMContext::MD_type,
2364 struct AliasToCreate {
2366 std::string TargetName;
2368 std::vector<AliasToCreate> AliasesToCreate;
2372 if (ExportSummary) {
2373 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2374 for (
auto *AliasMD : AliasesMD->operands()) {
2376 for (
Metadata *MD : AliasMD->operands()) {
2380 StringRef AliasName = MDS->getString();
2381 if (!ExportedFunctions.count(AliasName))
2383 auto *AliasF =
M.getFunction(AliasName);
2388 if (Aliases.
empty())
2391 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2392 auto *AliasF = Aliases[
I];
2393 ExportedFunctions.
erase(AliasF->getName());
2394 AliasesToCreate.push_back(
2395 {AliasF, std::string(Aliases[0]->
getName())});
2401 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2402 for (GlobalObject &GO :
M.global_objects()) {
2409 bool IsJumpTableCanonical =
false;
2410 bool IsExported =
false;
2413 if (
auto It = ExportedFunctions.find(
F->getName());
2414 It != ExportedFunctions.end()) {
2421 }
else if (!
F->hasAddressTaken()) {
2422 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2427 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2429 GlobalTypeMembers[&GO] = GTM;
2430 for (MDNode *
Type : Types) {
2431 verifyTypeMDNode(&GO,
Type);
2432 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2433 Info.UniqueId = ++CurUniqueId;
2434 Info.RefGlobals.push_back(GTM);
2438 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2443 auto Ins = TypeIdUsers.
insert({TypeId, {}});
2446 auto &GCI = GlobalClasses.insert(TypeId);
2447 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2450 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2451 CurSet = GlobalClasses.unionSets(
2452 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2455 return Ins.first->second;
2459 for (
const Use &U : TypeTestFunc->
uses()) {
2468 for (
const Use &CIU : CI->
uses()) {
2471 OnlyAssumeUses =
false;
2480 auto TypeId = TypeIdMDVal->getMetadata();
2481 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2485 if (ICallBranchFunnelFunc) {
2486 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2489 "llvm.icall.branch.funnel not supported on this target");
2493 std::vector<GlobalTypeMember *> Targets;
2497 GlobalClassesTy::member_iterator CurSet;
2498 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2504 "Expected branch funnel operand to be global value");
2506 auto It = GlobalTypeMembers.
find(
Base);
2507 if (It == GlobalTypeMembers.
end())
2509 "defined global value with type metadata");
2510 GlobalTypeMember *GTM = It->second;
2511 Targets.push_back(GTM);
2512 GlobalClassesTy::member_iterator NewSet =
2513 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2517 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2520 GlobalClasses.unionSets(
2521 CurSet, GlobalClasses.findLeader(
2522 GlobalClasses.insert(ICallBranchFunnel::create(
2523 Alloc, CI, Targets, ++CurUniqueId))));
2527 if (ExportSummary) {
2528 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2529 for (
auto &
P : TypeIdInfo) {
2532 TypeId->getString())]
2536 for (
auto &
P : *ExportSummary) {
2537 for (
auto &S :
P.second.getSummaryList()) {
2538 if (!ExportSummary->isGlobalValueLive(S.get()))
2543 AddTypeIdUse(MD).IsExported =
true;
2548 if (GlobalClasses.empty())
2552 ScopedSaveAliaseesAndUsed S(M);
2554 for (
const auto &
C : GlobalClasses) {
2558 ++NumTypeIdDisjointSets;
2560 std::vector<Metadata *> TypeIds;
2561 std::vector<GlobalTypeMember *> Globals;
2562 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2563 for (
auto M : GlobalClasses.members(*
C)) {
2576 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2581 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2582 return F1->UniqueId < F2->UniqueId;
2586 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2590 allocateByteArrays();
2592 for (
auto A : AliasesToCreate) {
2593 auto *
Target =
M.getNamedValue(
A.TargetName);
2597 AliasGA->setVisibility(
A.Alias->getVisibility());
2598 AliasGA->setLinkage(
A.Alias->getLinkage());
2599 AliasGA->setDSOLocal(
A.Alias->isDSOLocal());
2600 AliasGA->takeName(
A.Alias);
2601 A.Alias->replaceAllUsesWith(AliasGA);
2602 A.Alias->eraseFromParent();
2606 if (ExportSummary) {
2607 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2608 for (
auto *Symver : SymversMD->operands()) {
2609 assert(Symver->getNumOperands() >= 2);
2612 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2614 if (!ExportedFunctions.count(SymbolName))
2617 M.appendModuleInlineAsm(
2618 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2630 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2632 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
2640 static_cast<PassInfoMixin<DropTypeTestsPass> *
>(
this)->
printPipeline(
2641 OS, MapClassName2PassName);
2644 case DropTestKind::Assume:
2647 case DropTestKind::All:
2680 for (
auto &GV : M.globals()) {
2687 auto MaySimplifyPtr = [&](
Value *Ptr) {
2689 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2693 auto MaySimplifyInt = [&](
Value *
Op) {
2695 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2697 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2713 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2717 if (U.getOperandNo() == 0 && CE &&
2718 CE->getOpcode() == Instruction::Sub &&
2719 MaySimplifyInt(CE->getOperand(1))) {
2725 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2729 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 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 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< 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)
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 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)
auto dyn_cast_or_null(const Y &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 ...
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.
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.