88#include <system_error>
95#define DEBUG_TYPE "lowertypetests"
97STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
98STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
99STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
100STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
101STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
104 "lowertypetests-avoid-reuse",
105 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
109 "lowertypetests-summary-action",
110 cl::desc(
"What to do with the summary when running this pass"),
113 "Import typeid resolutions from summary and globals"),
115 "Export typeid resolutions to summary and globals")),
119 "lowertypetests-read-summary",
120 cl::desc(
"Read summary from given YAML file before running pass"),
124 "lowertypetests-write-summary",
125 cl::desc(
"Write summary to given YAML file after running pass"),
131 cl::desc(
"Enable debug info generation for jump tables"));
157 for (uint64_t
B :
Bits)
202 std::vector<uint64_t> &Fragment =
Fragments.back();
203 uint64_t FragmentIndex =
Fragments.size() - 1;
205 for (
auto ObjIndex :
F) {
207 if (OldFragmentIndex == 0) {
210 Fragment.push_back(ObjIndex);
217 std::vector<uint64_t> &OldFragment =
Fragments[OldFragmentIndex];
224 for (uint64_t ObjIndex : Fragment)
229 uint64_t BitSize, uint64_t &AllocByteOffset,
240 unsigned ReqSize = AllocByteOffset + BitSize;
242 if (
Bytes.size() < ReqSize)
243 Bytes.resize(ReqSize);
246 AllocMask = 1 << Bit;
247 for (uint64_t
B : Bits)
248 Bytes[AllocByteOffset +
B] |= AllocMask;
252 if (
F->isDeclarationForLinker())
255 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
256 if (!CI || !CI->isZero())
258 return F->hasFnAttribute(
"cfi-canonical-jump-table");
263struct ByteArrayInfo {
264 std::set<uint64_t> Bits;
276class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
287 bool IsJumpTableCanonical;
295 bool IsJumpTableCanonical,
bool IsExported,
297 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
298 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
300 GTM->NTypes = Types.size();
301 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
302 GTM->IsExported = IsExported;
307 GlobalObject *getGlobal()
const {
312 return IsJumpTableCanonical;
315 bool isExported()
const {
322struct ICallBranchFunnel final
323 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
327 auto *
Call =
static_cast<ICallBranchFunnel *
>(
328 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
329 alignof(ICallBranchFunnel)));
331 Call->UniqueId = UniqueId;
339 return getTrailingObjects(NTargets);
348struct ScopedSaveAliaseesAndUsed {
351 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
352 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
357 void collectAndEraseUsedFunctions(
Module &M,
358 SmallVectorImpl<GlobalValue *> &Vec,
366 GV->eraseFromParent();
368 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
369 return isa<Function>(GV);
378 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
391 collectAndEraseUsedFunctions(M, Used,
false);
392 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
394 for (
auto &GA :
M.aliases()) {
398 FunctionAliases.push_back({&GA,
F});
401 for (
auto &GI :
M.ifuncs())
403 ResolverIFuncs.push_back({&GI,
F});
406 ~ScopedSaveAliaseesAndUsed() {
410 for (
auto P : FunctionAliases)
411 P.first->setAliasee(
P.second);
413 for (
auto P : ResolverIFuncs) {
417 P.first->setResolver(
P.second);
422class LowerTypeTestsModule {
425 ModuleSummaryIndex *ExportSummary;
426 const ModuleSummaryIndex *ImportSummary;
435 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
438 int HasBranchTargetEnforcement = -1;
440 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
441 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
442 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
443 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
444 IntegerType *Int32Ty = Type::getInt32Ty(
M.getContext());
445 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
446 IntegerType *
IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
454 struct TypeIdUserInfo {
455 std::vector<CallInst *> CallSites;
456 bool IsExported =
false;
458 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
464 struct TypeIdLowering {
489 std::vector<ByteArrayInfo> ByteArrayInfos;
491 Function *WeakInitializerFn =
nullptr;
493 GlobalVariable *GlobalAnnotation;
494 DenseSet<Value *> FunctionAnnotations;
498 bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
500 bool shouldExportConstantsAsAbsoluteSymbols();
501 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
502 TypeIdLowering importTypeId(StringRef TypeId);
503 void importTypeTest(CallInst *CI);
506 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
507 void allocateByteArrays();
510 void lowerTypeTestCalls(
512 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
514 const TypeIdLowering &TIL);
520 bool hasBranchTargetEnforcement();
523 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
535 void replaceWeakDeclarationWithJumpTablePtr(
Function *
F, Constant *JT,
536 bool IsJumpTableCanonical);
537 void moveInitializerToModuleConstructor(GlobalVariable *GV);
538 void findGlobalVariableUsersOf(Constant *
C,
539 SmallSetVector<GlobalVariable *, 8> &Out);
549 void replaceCfiUses(
Function *Old,
Value *New,
bool IsJumpTableCanonical);
553 void replaceDirectCalls(
Value *Old,
Value *New);
555 bool isFunctionAnnotation(
Value *V)
const {
556 return FunctionAnnotations.
contains(V);
559 void maybeReplaceComdat(
Function *
F, StringRef OriginalName);
563 ModuleSummaryIndex *ExportSummary,
564 const ModuleSummaryIndex *ImportSummary);
586 unsigned BitWidth = BitsType->getBitWidth();
588 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
590 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
591 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
592 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
593 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
596ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
600 auto ByteArrayGlobal =
new GlobalVariable(
602 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
605 ByteArrayInfos.emplace_back();
606 ByteArrayInfo *BAI = &ByteArrayInfos.back();
608 BAI->Bits = BSI.
Bits;
610 BAI->ByteArray = ByteArrayGlobal;
611 BAI->MaskGlobal = MaskGlobal;
615void LowerTypeTestsModule::allocateByteArrays() {
617 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
618 return BAI1.BitSize > BAI2.BitSize;
621 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
624 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
625 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
628 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
634 *BAI->MaskPtr =
Mask;
639 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
642 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
643 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
645 ByteArray, ConstantInt::get(
IntPtrTy, ByteArrayOffsets[
I]));
659 ByteArraySizeBytes = BAB.
Bytes.size();
665 const TypeIdLowering &TIL,
679 "bits_use", ByteArray, &M);
682 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
687 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
695 GV->getMetadata(LLVMContext::MD_type, Types);
697 if (
Type->getOperand(1) != TypeId)
710 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
711 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
719 if (
Op->getOpcode() == Instruction::BitCast)
722 if (
Op->getOpcode() == Instruction::Select)
732Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
733 const TypeIdLowering &TIL) {
741 const DataLayout &
DL =
M.getDataLayout();
754 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
760 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
771 {PtrOffset, PtrOffset, TIL.AlignLog2});
773 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
777 return OffsetInRange;
790 Br->getMetadata(LLVMContext::MD_prof));
794 for (
auto &Phi :
Else->phis())
795 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
798 return createBitSetTest(ThenB, TIL, BitOffset);
801 MDBuilder MDB(
M.getContext());
803 MDB.createLikelyBranchWeights()));
807 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
812 B.SetInsertPoint(CI);
813 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
814 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
815 P->addIncoming(Bit, ThenB.GetInsertBlock());
821void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
828 std::vector<Constant *> GlobalInits;
829 const DataLayout &
DL =
M.getDataLayout();
830 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
834 for (GlobalTypeMember *
G : Globals) {
837 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
838 MaxAlign = std::max(MaxAlign, Alignment);
840 GlobalLayout[
G] = GVOffset;
843 GlobalInits.push_back(
847 GlobalInits.push_back(GV->getInitializer());
849 CurOffset = GVOffset + InitSize;
858 if (DesiredPadding > 32)
859 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
863 auto *CombinedGlobal =
864 new GlobalVariable(M, NewInit->
getType(),
true,
866 CombinedGlobal->setAlignment(MaxAlign);
869 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
874 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
878 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
879 ConstantInt::get(Int32Ty,
I * 2)};
881 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
883 GlobalAlias *GAlias =
885 "", CombinedGlobalElemPtr, &M);
893bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
906uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
907 const TypeIdLowering &TIL) {
908 TypeTestResolution &TTRes =
915 "__typeid_" + TypeId +
"_" + Name,
C, &M);
920 if (shouldExportConstantsAsAbsoluteSymbols())
927 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
932 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
933 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
943 ExportGlobal(
"byte_array", TIL.TheByteArray);
944 if (shouldExportConstantsAsAbsoluteSymbols())
945 ExportGlobal(
"bit_mask", TIL.BitMask);
951 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
956LowerTypeTestsModule::TypeIdLowering
957LowerTypeTestsModule::importTypeId(StringRef TypeId) {
961 const TypeTestResolution &TTRes = TidSummary->
TTRes;
966 auto ImportGlobal = [&](StringRef
Name) {
969 GlobalVariable *GV =
M.getOrInsertGlobal(
970 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
977 if (!shouldExportConstantsAsAbsoluteSymbols()) {
989 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
998 if (AbsWidth ==
IntPtrTy->getBitWidth()) {
1002 SetAbsRange(0, 1ull << AbsWidth);
1008 auto *GV = ImportGlobal(
"global_addr");
1021 TIL.OffsetedGlobal = GV;
1033 TIL.TheByteArray = ImportGlobal(
"byte_array");
1034 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1038 TIL.InlineBits = ImportConstant(
1045void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1057 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1058 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1065void LowerTypeTestsModule::maybeReplaceComdat(
Function *
F,
1066 StringRef OriginalName) {
1072 F->getComdat()->getName() == OriginalName) {
1073 Comdat *OldComdat =
F->getComdat();
1074 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1075 for (GlobalObject &GO :
M.global_objects()) {
1084void LowerTypeTestsModule::importFunction(
Function *
F,
1086 assert(
F->getType()->getAddressSpace() == 0);
1089 std::string
Name = std::string(
F->getName());
1094 if (
F->isDSOLocal()) {
1097 F->getAddressSpace(),
1100 replaceDirectCalls(
F, RealF);
1110 F->getAddressSpace(), Name +
".cfi_jt", &M);
1113 F->setName(Name +
".cfi");
1114 maybeReplaceComdat(
F, Name);
1116 F->getAddressSpace(), Name, &M);
1124 for (
auto &U :
F->uses()) {
1126 std::string AliasName =
A->getName().str() +
".cfi";
1129 F->getAddressSpace(),
"", &M);
1131 A->replaceAllUsesWith(AliasDecl);
1132 A->setName(AliasName);
1138 if (
F->hasExternalWeakLinkage())
1145 F->setVisibility(Visibility);
1154 OffsetsByTypeID[TypeId];
1155 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1157 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1158 if (It == OffsetsByTypeID.
end())
1164 It->second.push_back(MemOff +
Offset);
1174 dbgs() << MDS->getString() <<
": ";
1176 dbgs() <<
"<unnamed>: ";
1177 BitSets.
back().second.print(
dbgs());
1184void LowerTypeTestsModule::lowerTypeTestCalls(
1186 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1188 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1189 ByteArrayInfo *BAI =
nullptr;
1195 CombinedGlobalAddr, ConstantInt::get(
IntPtrTy, GlobalOffset)),
1200 : TypeTestResolution::
AllOnes;
1204 for (
auto Bit : BSI.
Bits)
1206 if (InlineBits == 0)
1209 TIL.InlineBits = ConstantInt::get(
1210 (BSI.
BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1213 ++NumByteArraysCreated;
1214 BAI = createByteArray(BSI);
1215 TIL.TheByteArray = BAI->ByteArray;
1216 TIL.BitMask = BAI->MaskGlobal;
1219 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1221 if (TIUI.IsExported) {
1222 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1224 BAI->MaskPtr = MaskPtr;
1228 for (CallInst *CI : TIUI.CallSites) {
1229 ++NumTypeTestCallsLowered;
1230 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1239void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1240 if (
Type->getNumOperands() != 2)
1247 "A member of a type identifier may not have an explicit section");
1270bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1271 if (HasBranchTargetEnforcement == -1) {
1275 M.getModuleFlag(
"branch-target-enforcement")))
1276 HasBranchTargetEnforcement = !BTE->isZero();
1278 HasBranchTargetEnforcement = 0;
1280 return HasBranchTargetEnforcement;
1284LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1285 switch (JumpTableArch) {
1289 M.getModuleFlag(
"cf-protection-branch")))
1290 if (MD->getZExtValue())
1296 if (CanUseThumbBWJumpTable) {
1297 if (hasBranchTargetEnforcement())
1304 if (hasBranchTargetEnforcement())
1323LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1325 raw_string_ostream AsmOS(Asm);
1330 M.getModuleFlag(
"cf-protection-branch")))
1331 Endbr = !MD->isZero();
1333 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1334 AsmOS <<
"jmp ${0:c}@plt\n";
1336 AsmOS <<
".balign 16, 0xcc\n";
1338 AsmOS <<
"int3\nint3\nint3\n";
1342 if (hasBranchTargetEnforcement())
1346 if (!CanUseThumbBWJumpTable) {
1362 AsmOS <<
"push {r0,r1}\n"
1364 <<
"0: add r0, r0, pc\n"
1365 <<
"str r0, [sp, #4]\n"
1368 <<
"1: .word $0 - (0b + 4)\n";
1370 if (hasBranchTargetEnforcement())
1372 AsmOS <<
"b.w $0\n";
1376 AsmOS <<
"tail $0@plt\n";
1378 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1379 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1381 AsmOS <<
"jump $0\n";
1394void LowerTypeTestsModule::buildBitSetsFromFunctions(
1400 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1402 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1407void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1408 GlobalVariable *GV) {
1409 if (WeakInitializerFn ==
nullptr) {
1414 M.getDataLayout().getProgramAddressSpace(),
1415 "__cfi_global_var_init", &M);
1421 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1434void LowerTypeTestsModule::findGlobalVariableUsersOf(
1435 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1436 for (
auto *U :
C->users()){
1440 findGlobalVariableUsersOf(C2, Out);
1445void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1446 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1449 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1450 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1451 for (
auto *GV : GlobalVarUsers) {
1452 if (GV == GlobalAnnotation)
1454 moveInitializerToModuleConstructor(GV);
1461 F->getAddressSpace(),
"", &M);
1462 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1469 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1472 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1484 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1492 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1497 if (Feature ==
"-thumb-mode")
1499 else if (Feature ==
"+thumb-mode")
1515 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1523 unsigned ArmCount = 0, ThumbCount = 0;
1524 for (
const auto GTM : Functions) {
1525 if (!GTM->isJumpTableCanonical()) {
1546 auto CUs = M.debug_compile_units();
1563 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1564 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1566 F->setSubprogram(UbsanSP);
1571 Locations.
reserve(Functions.size());
1573 for (
auto *Func : Functions) {
1574 StringRef FuncName = Func->getGlobal()->getName();
1577 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1578 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1583 Locations.push_back(EntryLoc);
1591void LowerTypeTestsModule::createJumpTable(
1600 F->setMetadata(LLVMContext::MD_elf_section_properties,
1603 ConstantAsMetadata::get(ConstantInt::get(
1604 Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
1605 ConstantAsMetadata::get(ConstantInt::get(
1606 Int64Ty, JumpTableEntrySize))}));
1615 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1621 bool areAllEntriesNounwind =
true;
1623 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1624 if (Loc.has_value())
1625 IRB.SetCurrentDebugLocation(*Loc);
1627 ->hasFnAttribute(Attribute::NoUnwind)) {
1628 areAllEntriesNounwind =
false;
1630 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1632 IRB.CreateUnreachable();
1635 F->setPreferredAlignment(
Align(JumpTableEntrySize));
1636 F->addFnAttr(Attribute::Naked);
1638 F->addFnAttr(
"target-features",
"-thumb-mode");
1640 if (hasBranchTargetEnforcement()) {
1643 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1645 F->addFnAttr(
"target-features",
"+thumb-mode");
1646 if (CanUseThumbBWJumpTable) {
1649 F->addFnAttr(
"target-cpu",
"cortex-a8");
1657 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1658 F->removeFnAttr(
"branch-target-enforcement");
1659 if (
F->hasFnAttribute(
"sign-return-address"))
1660 F->removeFnAttr(
"sign-return-address");
1665 F->addFnAttr(
"target-features",
"-c,-relax");
1671 F->addFnAttr(Attribute::NoCfCheck);
1674 if (areAllEntriesNounwind)
1675 F->addFnAttr(Attribute::NoUnwind);
1678 F->addFnAttr(Attribute::NoInline);
1683void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1768 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1769 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1770 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1771 GlobalLayout[Functions[
I]] =
I * EntrySize;
1777 M.getDataLayout().getProgramAddressSpace(),
1778 ".cfi.jumptable", &M);
1785 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1789 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1791 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1794 JumpTableType, JumpTable,
1798 const bool IsExported = Functions[
I]->isExported();
1799 if (!IsJumpTableCanonical) {
1803 F->getName() +
".cfi_jt",
1804 CombinedGlobalElemPtr, &M);
1813 if (IsJumpTableCanonical)
1821 if (!IsJumpTableCanonical) {
1822 if (
F->hasExternalWeakLinkage())
1823 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1824 IsJumpTableCanonical);
1826 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1828 assert(
F->getType()->getAddressSpace() == 0);
1830 GlobalAlias *FAlias =
1832 CombinedGlobalElemPtr, &M);
1837 F->setName(FAlias->
getName() +
".cfi");
1838 maybeReplaceComdat(
F, FAlias->
getName());
1840 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1841 if (!
F->hasLocalLinkage())
1846 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1855void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1860 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1862 for (GlobalTypeMember *GTM : Functions) {
1866 if (!
F->hasAddressTaken())
1872 ConstantInt::get(Int64Ty, IndirectIndex))));
1873 F->setMetadata(
"wasm.index", MD);
1876 GlobalLayout[GTM] = IndirectIndex++;
1885void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1888 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1889 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1890 TypeIdIndices[TypeIds[
I]] =
I;
1894 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1895 unsigned GlobalIndex = 0;
1896 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1897 for (GlobalTypeMember *GTM : Globals) {
1898 for (MDNode *
Type : GTM->types()) {
1900 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1901 if (
I != TypeIdIndices.
end())
1902 TypeMembers[
I->second].insert(GlobalIndex);
1904 GlobalIndices[GTM] = GlobalIndex;
1908 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1909 TypeMembers.emplace_back();
1910 std::set<uint64_t> &TMSet = TypeMembers.back();
1911 for (GlobalTypeMember *
T : JT->targets())
1912 TMSet.insert(GlobalIndices[
T]);
1918 const std::set<uint64_t> &
O2) {
1919 return O1.size() <
O2.size();
1926 for (
auto &&MemSet : TypeMembers)
1927 GLB.addFragment(MemSet);
1932 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1933 auto OGTMI = OrderedGTMs.begin();
1934 for (
auto &&
F : GLB.Fragments) {
1938 "variables and functions");
1939 *OGTMI++ = Globals[
Offset];
1945 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1947 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1951LowerTypeTestsModule::LowerTypeTestsModule(
1953 const ModuleSummaryIndex *ImportSummary)
1954 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
1955 assert(!(ExportSummary && ImportSummary));
1956 Triple TargetTriple(M.getTargetTriple());
1957 Arch = TargetTriple.getArch();
1959 CanUseArmJumpTable =
true;
1965 if (
F.isDeclaration())
1968 if (
TTI.hasArmWideBranch(
false))
1969 CanUseArmJumpTable =
true;
1970 if (
TTI.hasArmWideBranch(
true))
1971 CanUseThumbBWJumpTable =
true;
1974 OS = TargetTriple.getOS();
1975 ObjectFormat = TargetTriple.getObjectFormat();
1979 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
1988 ModuleSummaryIndex
Summary(
false);
1993 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
1998 yaml::Input
In(ReadSummaryFile->getBuffer());
2004 LowerTypeTestsModule(
2011 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
2017 yaml::Output Out(OS);
2026 return Usr && Usr->isCallee(&U);
2029void LowerTypeTestsModule::replaceCfiUses(
Function *Old,
Value *New,
2030 bool IsJumpTableCanonical) {
2031 SmallSetVector<Constant *, 4>
Constants;
2043 if (isFunctionAnnotation(
U.getUser()))
2061 for (
auto *
C : Constants)
2062 C->handleOperandChange(Old, New);
2065void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2070 bool ShouldDropAll) {
2076 Assume->eraseFromParent();
2085 return isa<PHINode>(U) || isa<SelectInst>(U);
2103 if (PublicTypeTestFunc)
2105 if (TypeTestFunc || PublicTypeTestFunc) {
2116bool LowerTypeTestsModule::lower() {
2130 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2131 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2132 !ExportSummary && !ImportSummary)
2135 if (ImportSummary) {
2140 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2142 "unexpected call to llvm.icall.branch.funnel during import phase");
2149 if (
F.hasLocalLinkage())
2158 ScopedSaveAliaseesAndUsed S(M);
2159 for (
auto *
F : Defs)
2160 importFunction(
F,
true);
2161 for (
auto *
F : Decls)
2162 importFunction(
F,
false);
2171 using GlobalClassesTy = EquivalenceClasses<
2172 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2173 GlobalClassesTy GlobalClasses;
2185 std::vector<GlobalTypeMember *> RefGlobals;
2187 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2188 unsigned CurUniqueId = 0;
2191 struct ExportedFunctionInfo {
2195 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2196 if (ExportSummary) {
2197 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2198 if (CfiFunctionsMD) {
2200 DenseSet<GlobalValue::GUID> AddressTaken;
2201 for (
auto &
I : *ExportSummary)
2202 for (
auto &GVS :
I.second.getSummaryList())
2204 for (
const auto &
Ref : GVS->refs()) {
2206 for (
auto &RefGVS :
Ref.getSummaryList())
2208 AddressTaken.
insert(Alias->getAliaseeGUID());
2211 if (AddressTaken.
count(GUID))
2213 auto VI = ExportSummary->getValueInfo(GUID);
2216 for (
auto &
I :
VI.getSummaryList())
2218 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2222 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2223 assert(FuncMD->getNumOperands() >= 2);
2224 StringRef FunctionName =
2229 ->getUniqueInteger()
2234 ->getUniqueInteger()
2238 if (!ExportSummary->isGUIDLive(GUID))
2245 if (
auto VI = ExportSummary->getValueInfo(GUID))
2246 for (
const auto &GVS :
VI.getSummaryList())
2253 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2255 P.first->second = {
Linkage, FuncMD};
2258 for (
const auto &
P : ExportedFunctions) {
2259 StringRef FunctionName =
P.first;
2261 MDNode *FuncMD =
P.second.FuncMD;
2263 if (
F &&
F->hasLocalLinkage()) {
2270 F->setName(
F->getName() +
".1");
2276 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2277 GlobalVariable::ExternalLinkage,
2278 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2280 LLVMContext::MD_guid,
2281 MDTuple::get(
M.getContext(), {FuncMD->getOperand(2).get()}));
2282 if (ExportSummary) {
2286 ->getUniqueInteger()
2288 if (
auto VI = ExportSummary->getValueInfo(GUID))
2290 VI.isDSOLocal(ExportSummary->withDSOLocalPropagation()));
2298 if (
F->hasAvailableExternallyLinkage()) {
2300 auto *OrigGUIDMD =
F->getMetadata(LLVMContext::MD_guid);
2303 F->setComdat(
nullptr);
2305 F->setMetadata(LLVMContext::MD_guid, OrigGUIDMD);
2317 if (
F->isDeclaration()) {
2321 F->eraseMetadata(LLVMContext::MD_type);
2323 F->addMetadata(LLVMContext::MD_type,
2330 struct AliasToCreate {
2332 std::string TargetName;
2334 std::vector<AliasToCreate> AliasesToCreate;
2338 if (ExportSummary) {
2339 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2340 for (
auto *AliasMD : AliasesMD->operands()) {
2342 for (
Metadata *MD : AliasMD->operands()) {
2346 StringRef AliasName = MDS->getString();
2347 if (!ExportedFunctions.count(AliasName))
2349 auto *AliasF =
M.getFunction(AliasName);
2354 if (Aliases.
empty())
2357 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2358 auto *AliasF = Aliases[
I];
2359 ExportedFunctions.
erase(AliasF->getName());
2360 AliasesToCreate.push_back(
2361 {AliasF, std::string(Aliases[0]->
getName())});
2367 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2368 for (GlobalObject &GO :
M.global_objects()) {
2375 bool IsJumpTableCanonical =
false;
2376 bool IsExported =
false;
2379 if (
auto It = ExportedFunctions.find(
F->getName());
2380 It != ExportedFunctions.end()) {
2387 }
else if (!
F->hasAddressTaken()) {
2388 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2393 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2395 GlobalTypeMembers[&GO] = GTM;
2396 for (MDNode *
Type : Types) {
2397 verifyTypeMDNode(&GO,
Type);
2398 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2399 Info.UniqueId = ++CurUniqueId;
2400 Info.RefGlobals.push_back(GTM);
2404 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2409 auto Ins = TypeIdUsers.
insert({TypeId, {}});
2412 auto &GCI = GlobalClasses.insert(TypeId);
2413 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2416 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2417 CurSet = GlobalClasses.unionSets(
2418 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2421 return Ins.first->second;
2425 for (
const Use &U : TypeTestFunc->
uses()) {
2434 for (
const Use &CIU : CI->
uses()) {
2437 OnlyAssumeUses =
false;
2446 auto TypeId = TypeIdMDVal->getMetadata();
2447 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2451 if (ICallBranchFunnelFunc) {
2452 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2455 "llvm.icall.branch.funnel not supported on this target");
2459 std::vector<GlobalTypeMember *> Targets;
2463 GlobalClassesTy::member_iterator CurSet;
2464 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2470 "Expected branch funnel operand to be global value");
2472 auto It = GlobalTypeMembers.
find(
Base);
2473 if (It == GlobalTypeMembers.
end())
2475 "defined global value with type metadata");
2476 GlobalTypeMember *GTM = It->second;
2477 Targets.push_back(GTM);
2478 GlobalClassesTy::member_iterator NewSet =
2479 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2483 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2486 GlobalClasses.unionSets(
2487 CurSet, GlobalClasses.findLeader(
2488 GlobalClasses.insert(ICallBranchFunnel::create(
2489 Alloc, CI, Targets, ++CurUniqueId))));
2493 if (ExportSummary) {
2494 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2495 for (
auto &
P : TypeIdInfo) {
2498 TypeId->getString())]
2502 for (
auto &
P : *ExportSummary) {
2503 for (
auto &S :
P.second.getSummaryList()) {
2504 if (!ExportSummary->isGlobalValueLive(S.get()))
2509 AddTypeIdUse(MD).IsExported =
true;
2514 if (GlobalClasses.empty())
2518 ScopedSaveAliaseesAndUsed S(M);
2520 for (
const auto &
C : GlobalClasses) {
2524 ++NumTypeIdDisjointSets;
2526 std::vector<Metadata *> TypeIds;
2527 std::vector<GlobalTypeMember *> Globals;
2528 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2529 for (
auto M : GlobalClasses.members(*
C)) {
2542 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2547 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2548 return F1->UniqueId < F2->UniqueId;
2552 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2556 allocateByteArrays();
2558 for (
auto A : AliasesToCreate) {
2559 auto *
Target =
M.getNamedValue(
A.TargetName);
2563 AliasGA->setVisibility(
A.Alias->getVisibility());
2564 AliasGA->setLinkage(
A.Alias->getLinkage());
2565 AliasGA->setDSOLocal(
A.Alias->isDSOLocal());
2566 AliasGA->takeName(
A.Alias);
2567 A.Alias->replaceAllUsesWith(AliasGA);
2568 A.Alias->eraseFromParent();
2572 if (ExportSummary) {
2573 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2574 for (
auto *Symver : SymversMD->operands()) {
2575 assert(Symver->getNumOperands() >= 2);
2578 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2580 if (!ExportedFunctions.count(SymbolName))
2583 M.appendModuleInlineAsm(
2584 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2596 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2598 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
2606 static_cast<PassInfoMixin<DropTypeTestsPass> *
>(
this)->
printPipeline(
2607 OS, MapClassName2PassName);
2610 case DropTestKind::Assume:
2613 case DropTestKind::All:
2646 for (
auto &GV : M.globals()) {
2653 auto MaySimplifyPtr = [&](
Value *Ptr) {
2655 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2659 auto MaySimplifyInt = [&](
Value *
Op) {
2661 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2663 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2679 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2683 if (U.getOperandNo() == 0 && CE &&
2684 CE->getOpcode() == Instruction::Sub &&
2685 MaySimplifyInt(CE->getOperand(1))) {
2691 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2695 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 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.
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)
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.