94#include <system_error>
101#define DEBUG_TYPE "lowertypetests"
104STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
105STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
106STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
107STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
133 for (uint64_t
B :
Bits)
176 assert(Fragments.front().empty() &&
"Cannot add fragments after build()");
179 Fragments.emplace_back();
180 std::vector<uint64_t> &
Fragment = Fragments.back();
181 uint64_t FragmentIndex = Fragments.size() - 1;
183 std::vector<std::vector<uint64_t>> SubFragments;
184 for (
auto ObjIndex :
F) {
185 uint64_t OldFragmentIndex = FragmentMap[ObjIndex];
186 if (OldFragmentIndex == 0) {
189 SubFragments.push_back({ObjIndex});
190 }
else if (!Fragments[OldFragmentIndex].empty()) {
196 SubFragments.push_back(std::move(Fragments[OldFragmentIndex]));
202 const std::vector<uint64_t> &
B) {
203 return Less(
A.back(),
B.back());
207 for (
auto &SF : SubFragments)
212 FragmentMap[ObjIndex] = FragmentIndex;
221 [](
const std::vector<uint64_t> &
F) {
return F.empty(); });
223 const std::vector<uint64_t> &FB) {
224 return Less(FA.back(), FB.back());
228 std::vector<uint64_t> Layout;
229 Layout.reserve(FragmentMap.size());
230 for (
auto &&
F : Fragments)
233 Fragments.push_back(std::move(Layout));
234 return Fragments.front();
238 uint64_t BitSize, uint64_t &AllocByteOffset,
249 unsigned ReqSize = AllocByteOffset + BitSize;
251 if (
Bytes.size() < ReqSize)
252 Bytes.resize(ReqSize);
255 AllocMask = 1 << Bit;
256 for (uint64_t
B : Bits)
257 Bytes[AllocByteOffset +
B] |= AllocMask;
261 if (
F->isDeclarationForLinker())
264 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
265 if (!CI || !CI->isZero())
267 return F->hasFnAttribute(
"cfi-canonical-jump-table");
274 if (AssocGO->hasMetadata(LLVMContext::MD_type))
284 for (
auto &
A : M.aliases())
301 if (
C->getBitWidth() != 64)
312 GO.getMetadata(LLVMContext::MD_type, Types);
315 TypeIds.
insert(TypeId->getZExtValue());
318 if (
NamedMDNode *CfiFunctionsMD = M.getNamedMetadata(
"cfi.functions")) {
319 for (
auto *Func : CfiFunctionsMD->operands()) {
320 assert(Func->getNumOperands() >= 3);
322 for (
unsigned I = 3;
I < Func->getNumOperands(); ++
I)
325 TypeIds.
insert(TypeId->getZExtValue());
334enum class CfiFunctionLinkage :
uint8_t {
341class CfiFunctionHotness {
354 CfiFunctionHotness() =
default;
363 static CfiFunctionHotness
364 fromFunction(
Function &
F, ProfileSummaryInfo &PSI,
365 function_ref<
const BlockFrequencyInfo &(
Function &)> BFIGetter) {
366 if (
F.isDeclaration())
367 return Kind::Unknown;
370 const BlockFrequencyInfo &BFI = BFIGetter(
F);
371 if (
F.hasFnAttribute(Attribute::Hot) ||
377 F.hasFnAttribute(Attribute::Cold)) {
386 static CfiFunctionHotness fromUint6(uint8_t
V) {
387 return CfiFunctionHotness(
static_cast<Kind>(
V & 0x3));
390 uint8_t asUint6()
const {
return static_cast<uint8_t
>(
Type) & 0x3; }
397 auto Rank = [](
Kind K) ->
int {
398 return (K == Kind::Cold) ? -1 :
static_cast<int>(
K);
407 return static_cast<CfiFunctionLinkage
>(Encoded & 0x3);
411 return CfiFunctionHotness::fromUint6(Encoded >> 2);
415 CfiFunctionHotness Hotness) {
430 for (
auto *
V : CfiFunctions) {
433 F.getMetadata(LLVMContext::MD_type, Types);
437 CfiFunctionLinkage
Linkage = CfiFunctionLinkage::Declaration;
439 Linkage = CfiFunctionLinkage::Definition;
440 else if (
F.hasExternalWeakLinkage())
441 Linkage = CfiFunctionLinkage::WeakDeclaration;
443 CfiFunctionHotness Hotness =
444 Opts.reorder_cfi_jump_tables_profiles
445 ? CfiFunctionHotness::fromFunction(
F, PSI, BFIGetter)
446 : CfiFunctionHotness();
459 if (!CfiFunctionMDs.
empty()) {
461 for (
auto *MD : CfiFunctionMDs)
469 for (
const auto &
A : SrcM.
aliases()) {
474 FunctionAliases[
F].push_back(&
A);
477 if (!FunctionAliases.
empty()) {
479 for (
auto &Alias : FunctionAliases) {
482 for (
auto *
A : Alias.second)
495 if (!
F ||
F->use_empty())
502 if (!Symvers.
empty()) {
504 for (
auto *MD : Symvers)
520struct ByteArrayInfo {
521 std::set<uint64_t> Bits;
533class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
544 bool IsJumpTableCanonical;
552 bool IsJumpTableCanonical,
bool IsExported,
554 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
555 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
557 GTM->NTypes = Types.size();
558 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
559 GTM->IsExported = IsExported;
564 GlobalObject *getGlobal()
const {
569 return IsJumpTableCanonical;
572 bool isExported()
const {
579struct ICallBranchFunnel final
580 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
584 auto *
Call =
static_cast<ICallBranchFunnel *
>(
585 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
586 alignof(ICallBranchFunnel)));
588 Call->UniqueId = UniqueId;
596 return getTrailingObjects(NTargets);
605struct ScopedSaveAliaseesAndUsed {
608 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
609 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
614 void collectAndEraseUsedFunctions(
Module &M,
615 SmallVectorImpl<GlobalValue *> &Vec,
623 GV->eraseFromParent();
625 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
626 return isa<Function>(GV);
635 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
648 collectAndEraseUsedFunctions(M, Used,
false);
649 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
651 for (
auto &GA :
M.aliases()) {
655 FunctionAliases.push_back({&GA,
F});
658 for (
auto &GI :
M.ifuncs())
660 ResolverIFuncs.push_back({&GI,
F});
663 ~ScopedSaveAliaseesAndUsed() {
667 for (
auto P : FunctionAliases)
668 P.first->setAliasee(
P.second);
670 for (
auto P : ResolverIFuncs) {
674 P.first->setResolver(
P.second);
679class LowerTypeTestsModule {
680 const IPOOptions &Opts;
683 ModuleSummaryIndex *ExportSummary;
684 const ModuleSummaryIndex *ImportSummary;
693 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
696 int HasBranchTargetEnforcement = -1;
699 DenseMap<const Function *, CfiFunctionHotness> FunctionSummaryHotness;
701 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
702 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
703 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
704 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
705 IntegerType *Int32Ty = Type::getInt32Ty(
M.getContext());
706 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
707 IntegerType *
IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
715 struct TypeIdUserInfo {
716 std::vector<CallInst *> CallSites;
717 bool IsExported =
false;
719 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
725 struct TypeIdLowering {
750 std::vector<ByteArrayInfo> ByteArrayInfos;
752 Function *WeakInitializerFn =
nullptr;
754 GlobalVariable *GlobalAnnotation;
755 DenseSet<Value *> FunctionAnnotations;
759 bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
761 bool shouldExportConstantsAsAbsoluteSymbols();
762 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
763 TypeIdLowering importTypeId(StringRef TypeId);
764 void importTypeTest(CallInst *CI);
767 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
768 void allocateByteArrays();
771 void lowerTypeTestCalls(
773 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
775 const TypeIdLowering &TIL);
781 bool hasBranchTargetEnforcement();
784 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
796 void replaceWeakDeclarationWithJumpTablePtr(
Function *
F, Constant *JT,
797 bool IsJumpTableCanonical);
798 void moveInitializerToModuleConstructor(GlobalVariable *GV);
799 void findGlobalVariableUsersOf(Constant *
C,
800 SmallSetVector<GlobalVariable *, 8> &Out);
809 void replaceCfiUses(
Function *Old,
Value *New,
bool IsJumpTableCanonical);
813 void replaceDirectCalls(
Value *Old,
Value *New);
815 bool isFunctionAnnotation(
Value *
V)
const {
819 void maybeReplaceComdat(
Function *
F, StringRef OriginalName);
823 ModuleSummaryIndex *ExportSummary,
824 const ModuleSummaryIndex *ImportSummary);
846 unsigned BitWidth = BitsType->getBitWidth();
848 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
850 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
851 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
852 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
853 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
856ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
860 auto ByteArrayGlobal =
new GlobalVariable(
862 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
865 ByteArrayInfos.emplace_back();
866 ByteArrayInfo *BAI = &ByteArrayInfos.back();
868 BAI->Bits = BSI.
Bits;
870 BAI->ByteArray = ByteArrayGlobal;
871 BAI->MaskGlobal = MaskGlobal;
875void LowerTypeTestsModule::allocateByteArrays() {
877 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
878 return BAI1.BitSize > BAI2.BitSize;
881 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
884 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
885 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
888 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
894 *BAI->MaskPtr =
Mask;
899 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
902 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
903 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
905 ByteArray, ConstantInt::get(
IntPtrTy, ByteArrayOffsets[
I]));
919 ByteArraySizeBytes = BAB.
Bytes.size();
925 const TypeIdLowering &TIL,
933 if (Opts.lowertypetests_avoid_reuse && !ImportSummary) {
939 "bits_use", ByteArray, &M);
942 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
947 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
955 GV->getMetadata(LLVMContext::MD_type, Types);
957 if (
Type->getOperand(1) != TypeId)
970 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
971 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
979 if (
Op->getOpcode() == Instruction::BitCast)
982 if (
Op->getOpcode() == Instruction::Select)
992Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
993 const TypeIdLowering &TIL) {
1001 const DataLayout &
DL =
M.getDataLayout();
1014 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
1020 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
1031 {PtrOffset, PtrOffset, TIL.AlignLog2});
1033 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
1037 return OffsetInRange;
1050 Br->getMetadata(LLVMContext::MD_prof));
1054 for (
auto &Phi :
Else->phis())
1055 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
1058 return createBitSetTest(ThenB, TIL, BitOffset);
1061 MDBuilder MDB(
M.getContext());
1063 MDB.createLikelyBranchWeights()));
1067 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
1072 B.SetInsertPoint(CI);
1073 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
1074 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
1075 P->addIncoming(Bit, ThenB.GetInsertBlock());
1081void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
1088 std::vector<Constant *> GlobalInits;
1089 const DataLayout &
DL =
M.getDataLayout();
1090 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1094 for (GlobalTypeMember *
G : Globals) {
1097 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
1098 MaxAlign = std::max(MaxAlign, Alignment);
1100 GlobalLayout[
G] = GVOffset;
1101 if (GVOffset != 0) {
1103 GlobalInits.push_back(
1107 GlobalInits.push_back(GV->getInitializer());
1109 CurOffset = GVOffset + InitSize;
1112 DesiredPadding =
NextPowerOf2(InitSize - 1) - InitSize;
1118 if (DesiredPadding > 32)
1119 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
1123 auto *CombinedGlobal =
1124 new GlobalVariable(M, NewInit->
getType(),
true,
1126 CombinedGlobal->setAlignment(MaxAlign);
1129 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
1134 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
1138 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
1139 ConstantInt::get(Int32Ty,
I * 2)};
1141 DL, NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs,
1144 GlobalAlias *GAlias =
1146 "", CombinedGlobalElemPtr, &M);
1154bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
1167uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
1168 const TypeIdLowering &TIL) {
1169 TypeTestResolution &TTRes =
1176 "__typeid_" + TypeId +
"_" + Name,
C, &M);
1181 if (shouldExportConstantsAsAbsoluteSymbols())
1188 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
1193 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
1194 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
1204 ExportGlobal(
"byte_array", TIL.TheByteArray);
1205 if (shouldExportConstantsAsAbsoluteSymbols())
1206 ExportGlobal(
"bit_mask", TIL.BitMask);
1212 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
1217LowerTypeTestsModule::TypeIdLowering
1218LowerTypeTestsModule::importTypeId(StringRef TypeId) {
1222 const TypeTestResolution &TTRes = TidSummary->
TTRes;
1227 auto ImportGlobal = [&](StringRef
Name) {
1230 GlobalVariable *GV =
M.getOrInsertGlobal(
1231 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
1238 if (!shouldExportConstantsAsAbsoluteSymbols()) {
1250 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
1259 if (AbsWidth ==
IntPtrTy->getBitWidth()) {
1263 SetAbsRange(0, 1ull << AbsWidth);
1269 auto *GV = ImportGlobal(
"global_addr");
1282 TIL.OffsetedGlobal = GV;
1294 TIL.TheByteArray = ImportGlobal(
"byte_array");
1295 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1299 TIL.InlineBits = ImportConstant(
1306void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1318 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1319 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1326void LowerTypeTestsModule::maybeReplaceComdat(
Function *
F,
1327 StringRef OriginalName) {
1333 F->getComdat()->getName() == OriginalName) {
1334 Comdat *OldComdat =
F->getComdat();
1335 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1336 for (GlobalObject &GO :
M.global_objects()) {
1345void LowerTypeTestsModule::importFunction(
Function *
F,
1347 assert(
F->getType()->getAddressSpace() == 0);
1350 std::string
Name = std::string(
F->getName());
1355 if (!
F->isDSOLocal())
1357 if (
F->isDeclaration()) {
1362 F->getAddressSpace(),
1365 replaceDirectCalls(
F, RealF);
1382 F->getAddressSpace(), Name +
".cfi_jt", &M);
1385 F->setName(Name +
".cfi");
1386 maybeReplaceComdat(
F, Name);
1388 F->getAddressSpace(), Name, &M);
1396 for (
auto &U :
F->uses()) {
1398 std::string AliasName =
A->getName().str() +
".cfi";
1401 F->getAddressSpace(),
"", &M);
1403 A->replaceAllUsesWith(AliasDecl);
1404 A->setName(AliasName);
1410 if (
F->hasExternalWeakLinkage())
1417 F->setVisibility(Visibility);
1426 OffsetsByTypeID[TypeId];
1427 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1429 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1430 if (It == OffsetsByTypeID.
end())
1436 It->second.push_back(MemOff +
Offset);
1446 dbgs() << MDS->getString() <<
": ";
1448 dbgs() <<
"<unnamed>: ";
1449 BitSets.
back().second.print(
dbgs());
1456void LowerTypeTestsModule::lowerTypeTestCalls(
1458 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1460 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1461 ByteArrayInfo *BAI =
nullptr;
1467 CombinedGlobalAddr, ConstantInt::get(
IntPtrTy, GlobalOffset)),
1472 : TypeTestResolution::
AllOnes;
1476 for (
auto Bit : BSI.
Bits)
1478 if (InlineBits == 0)
1481 TIL.InlineBits = ConstantInt::get(
1482 (BSI.
BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1485 ++NumByteArraysCreated;
1486 BAI = createByteArray(BSI);
1487 TIL.TheByteArray = BAI->ByteArray;
1488 TIL.BitMask = BAI->MaskGlobal;
1491 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1493 if (TIUI.IsExported) {
1494 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1496 BAI->MaskPtr = MaskPtr;
1500 for (CallInst *CI : TIUI.CallSites) {
1501 ++NumTypeTestCallsLowered;
1502 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1511void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1512 if (
Type->getNumOperands() != 2)
1519 "A member of a type identifier may not have an explicit section");
1542bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1543 if (HasBranchTargetEnforcement == -1) {
1547 M.getModuleFlag(
"branch-target-enforcement")))
1548 HasBranchTargetEnforcement = !BTE->isZero();
1550 HasBranchTargetEnforcement = 0;
1552 return HasBranchTargetEnforcement;
1556LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1557 switch (JumpTableArch) {
1561 M.getModuleFlag(
"cf-protection-branch")))
1562 if (MD->getZExtValue())
1568 if (CanUseThumbBWJumpTable) {
1569 if (hasBranchTargetEnforcement())
1576 if (hasBranchTargetEnforcement())
1595LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1597 raw_string_ostream AsmOS(Asm);
1602 M.getModuleFlag(
"cf-protection-branch")))
1603 Endbr = !MD->isZero();
1605 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1606 AsmOS <<
"jmp ${0:c}@plt\n";
1608 AsmOS <<
".balign 16, 0xcc\n";
1610 AsmOS <<
"int3\nint3\nint3\n";
1614 if (hasBranchTargetEnforcement())
1618 if (!CanUseThumbBWJumpTable) {
1634 AsmOS <<
"push {r0,r1}\n"
1636 <<
"0: add r0, r0, pc\n"
1637 <<
"str r0, [sp, #4]\n"
1640 <<
"1: .word $0 - (0b + 4)\n";
1642 if (hasBranchTargetEnforcement())
1644 AsmOS <<
"b.w $0\n";
1648 AsmOS <<
"tail $0@plt\n";
1650 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1651 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1653 AsmOS <<
"jump $0\n";
1666void LowerTypeTestsModule::buildBitSetsFromFunctions(
1672 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1674 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1679void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1680 GlobalVariable *GV) {
1681 if (WeakInitializerFn ==
nullptr) {
1686 M.getDataLayout().getProgramAddressSpace(),
1687 "__cfi_global_var_init", &M);
1693 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1706void LowerTypeTestsModule::findGlobalVariableUsersOf(
1707 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1708 for (
auto *U :
C->users()){
1712 findGlobalVariableUsersOf(C2, Out);
1717void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1718 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1721 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1722 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1723 for (
auto *GV : GlobalVarUsers) {
1724 if (GV == GlobalAnnotation)
1726 moveInitializerToModuleConstructor(GV);
1733 F->getAddressSpace(),
"", &M);
1734 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1741 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1744 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1756 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1764 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1769 if (Feature ==
"-thumb-mode")
1771 else if (Feature ==
"+thumb-mode")
1787 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1795 unsigned ArmCount = 0, ThumbCount = 0;
1796 for (
const auto GTM : Functions) {
1797 if (!GTM->isJumpTableCanonical()) {
1818 auto CUs = M.debug_compile_units();
1835 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1836 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1838 F->setSubprogram(UbsanSP);
1843 Locations.
reserve(Functions.size());
1845 for (
auto *Func : Functions) {
1846 StringRef FuncName = Func->getGlobal()->getName();
1849 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1850 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1855 Locations.push_back(EntryLoc);
1863void LowerTypeTestsModule::createJumpTable(
1872 F->setMetadata(LLVMContext::MD_elf_section_properties,
1875 ConstantAsMetadata::get(ConstantInt::get(
1876 Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
1877 ConstantAsMetadata::get(ConstantInt::get(
1878 Int64Ty, JumpTableEntrySize))}));
1884 if (
M.getDwarfVersion() != 0 && Opts.lowertypetests_jump_table_debug_info)
1887 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1893 bool areAllEntriesNounwind =
true;
1895 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1896 if (Loc.has_value())
1897 IRB.SetCurrentDebugLocation(*Loc);
1899 ->hasFnAttribute(Attribute::NoUnwind)) {
1900 areAllEntriesNounwind =
false;
1902 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1904 IRB.CreateUnreachable();
1907 F->setPreferredAlignment(
Align(JumpTableEntrySize));
1908 F->addFnAttr(Attribute::Naked);
1910 F->addFnAttr(
"target-features",
"-thumb-mode");
1912 if (hasBranchTargetEnforcement()) {
1915 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1917 F->addFnAttr(
"target-features",
"+thumb-mode");
1918 if (CanUseThumbBWJumpTable) {
1921 F->addFnAttr(
"target-cpu",
"cortex-a8");
1929 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1930 F->removeFnAttr(
"branch-target-enforcement");
1931 if (
F->hasFnAttribute(
"sign-return-address"))
1932 F->removeFnAttr(
"sign-return-address");
1937 F->addFnAttr(
"target-features",
"-c,-relax");
1943 F->addFnAttr(Attribute::NoCfCheck);
1946 if (areAllEntriesNounwind)
1947 F->addFnAttr(Attribute::NoUnwind);
1950 F->addFnAttr(Attribute::NoInline);
1955void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
2040 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
2041 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
2042 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
2043 GlobalLayout[Functions[
I]] =
I * EntrySize;
2049 M.getDataLayout().getProgramAddressSpace(),
2050 ".cfi.jumptable", &M);
2057 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
2061 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
2063 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
2066 F->getDataLayout(), JumpTableType, JumpTable,
2067 {ConstantInt::get(IntPtrTy, 0), ConstantInt::get(IntPtrTy, I)},
2070 const bool IsExported = Functions[
I]->isExported();
2071 if (!IsJumpTableCanonical) {
2075 F->getName() +
".cfi_jt",
2076 CombinedGlobalElemPtr, &M);
2085 if (IsJumpTableCanonical)
2093 if (!IsJumpTableCanonical) {
2094 if (
F->hasExternalWeakLinkage())
2095 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
2096 IsJumpTableCanonical);
2098 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
2100 assert(
F->getType()->getAddressSpace() == 0);
2102 GlobalAlias *FAlias =
2104 CombinedGlobalElemPtr, &M);
2109 F->setName(FAlias->
getName() +
".cfi");
2110 maybeReplaceComdat(
F, FAlias->
getName());
2112 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
2113 if (!
F->hasLocalLinkage())
2118 createJumpTable(JumpTableFn, Functions, JumpTableArch);
2127void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
2132 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
2134 for (GlobalTypeMember *GTM : Functions) {
2138 if (!
F->hasAddressTaken())
2144 ConstantInt::get(Int64Ty, IndirectIndex))));
2145 F->setMetadata(
"wasm.index", MD);
2148 GlobalLayout[GTM] = IndirectIndex++;
2157void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
2160 DenseMap<Metadata *, uint64_t> TypeIdIndices;
2161 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
2162 TypeIdIndices[TypeIds[
I]] =
I;
2166 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
2167 unsigned GlobalIndex = 0;
2168 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
2169 for (GlobalTypeMember *GTM : Globals) {
2170 for (MDNode *
Type : GTM->types()) {
2172 auto I = TypeIdIndices.
find(
Type->getOperand(1));
2173 if (
I != TypeIdIndices.
end())
2174 TypeMembers[
I->second].insert(GlobalIndex);
2176 GlobalIndices[GTM] = GlobalIndex;
2180 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
2181 TypeMembers.emplace_back();
2182 std::set<uint64_t> &TMSet = TypeMembers.back();
2183 for (GlobalTypeMember *
T : JT->targets())
2184 TMSet.insert(GlobalIndices[
T]);
2190 const std::set<uint64_t> &
O2) {
2191 return O1.size() <
O2.size();
2198 if (!IsGlobalSet && !FunctionSummaryHotness.
empty() &&
2199 Opts.reorder_cfi_jump_tables_profiles) {
2201 std::vector<CfiFunctionHotness> GTMHotness;
2202 GTMHotness.reserve(Globals.size());
2203 for (GlobalTypeMember *GTM : Globals) {
2204 GTMHotness.push_back(
2221 return GTMHotness[
A] < GTMHotness[
B];
2229 for (
auto &&MemSet : TypeMembers)
2230 GLB.addFragment(MemSet);
2233 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
2234 auto OGTMI = OrderedGTMs.begin();
2238 "variables and functions");
2239 *OGTMI++ = Globals[
Offset];
2244 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
2246 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
2250LowerTypeTestsModule::LowerTypeTestsModule(
2252 const ModuleSummaryIndex *ImportSummary)
2254 ImportSummary(ImportSummary) {
2255 assert(!(ExportSummary && ImportSummary));
2256 Triple TargetTriple(M.getTargetTriple());
2257 Arch = TargetTriple.getArch();
2261 CanUseArmJumpTable =
true;
2265 if (
F.isDeclaration())
2268 if (
TTI.hasArmWideBranch(
false))
2269 CanUseArmJumpTable =
true;
2270 if (
TTI.hasArmWideBranch(
true))
2271 CanUseThumbBWJumpTable =
true;
2274 OS = TargetTriple.getOS();
2275 ObjectFormat = TargetTriple.getObjectFormat();
2279 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
2289 StringRef ReadSummary = Opts.lowertypetests_read_summary;
2290 StringRef WriteSummary = Opts.lowertypetests_write_summary;
2292 std::unique_ptr<ModuleSummaryIndex>
Summary;
2296 if (!ReadSummary.
empty()) {
2297 ExitOnError ExitOnErr(
2298 (
"-lowertypetests-read-summary: " + ReadSummary +
": ").str());
2299 auto ReadSummaryFile = ExitOnErr(
2303 if (ReadSummaryFile->getBuffer().starts_with(
"---")) {
2304 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2305 yaml::Input
In(ReadSummaryFile->getBuffer());
2318 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2322 LowerTypeTestsModule(
2324 SummaryAction == PassSummaryAction::Export ?
Summary.get() :
nullptr,
2325 SummaryAction == PassSummaryAction::Import ?
Summary.get() :
nullptr)
2328 if (!WriteSummary.
empty()) {
2329 ExitOnError ExitOnErr(
2330 (
"-lowertypetests-write-summary: " + WriteSummary +
": ").str());
2335 yaml::Output
Out(OS);
2344 return Usr && Usr->isCallee(&U);
2347void LowerTypeTestsModule::replaceCfiUses(
Function *Old,
Value *New,
2348 bool IsJumpTableCanonical) {
2349 SmallSetVector<Constant *, 4>
Constants;
2361 if (isFunctionAnnotation(
U.getUser()))
2379 for (
auto *
C : Constants)
2380 C->handleOperandChange(Old, New);
2383void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2399 Value *Ptr =
I->getOperand(0);
2401 Type *PtrTy =
I->getType()->getStructElementType(0);
2406 Intrinsic::load_relative, {
Offset->getType()}, {Ptr,
Offset},
2407 nullptr,
"rel_load");
2416 I->replaceAllUsesWith(Replacement);
2419 I->eraseFromParent();
2428 bool ShouldDropAll) {
2434 Assume->eraseFromParent();
2443 return isa<PHINode>(U) || isa<SelectInst>(U);
2459 bool DroppedCheckedLoads =
false;
2460 if (ShouldDropAll) {
2463 DroppedCheckedLoads |=
2466 &M, Intrinsic::type_checked_load_relative))
2467 DroppedCheckedLoads |=
2475 if (PublicTypeTestFunc)
2477 if (TypeTestFunc || PublicTypeTestFunc || DroppedCheckedLoads) {
2488bool LowerTypeTestsModule::lower() {
2502 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2503 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2504 !ExportSummary && !ImportSummary)
2507 if (ImportSummary) {
2512 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2514 "unexpected call to llvm.icall.branch.funnel during import phase");
2521 if (
A.hasLocalLinkage())
2526 if (
F->hasExternalLinkage()) {
2541 A.replaceAllUsesWith(
F);
2543 A.eraseFromParent();
2553 if (
F.hasLocalLinkage())
2562 ScopedSaveAliaseesAndUsed S(M);
2563 for (
auto *
F : Defs)
2564 importFunction(
F,
true);
2565 for (
auto *
F : Decls)
2566 importFunction(
F,
false);
2569 for (
auto &[
F, Name] : PromotedFuncs)
2578 using GlobalClassesTy = EquivalenceClasses<
2579 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2580 GlobalClassesTy GlobalClasses;
2592 std::vector<GlobalTypeMember *> RefGlobals;
2594 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2595 unsigned CurUniqueId = 0;
2598 struct ExportedFunctionInfo {
2602 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2603 if (ExportSummary) {
2604 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2605 if (CfiFunctionsMD) {
2607 DenseSet<GlobalValue::GUID> AddressTaken;
2608 for (
auto &
I : *ExportSummary)
2609 for (
auto &GVS :
I.second.getSummaryList())
2611 for (
const auto &
Ref : GVS->refs()) {
2613 for (
auto &RefGVS :
Ref.getSummaryList())
2615 AddressTaken.
insert(Alias->getAliaseeGUID());
2618 if (AddressTaken.
count(GUID))
2620 auto VI = ExportSummary->getValueInfo(GUID);
2623 for (
auto &
I :
VI.getSummaryList())
2625 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2629 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2630 assert(FuncMD->getNumOperands() >= 2);
2631 StringRef FunctionName =
2636 ->getUniqueInteger()
2641 ->getUniqueInteger()
2645 if (!ExportSummary->isGUIDLive(GUID))
2648 if (!CrossDsoCfi ||
Linkage != CfiFunctionLinkage::Definition)
2652 if (
auto VI = ExportSummary->getValueInfo(GUID))
2653 for (
const auto &GVS :
VI.getSummaryList())
2660 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2662 P.first->second.Linkage != CfiFunctionLinkage::Definition)
2663 P.first->second = {
Linkage, FuncMD};
2666 for (
const auto &
P : ExportedFunctions) {
2667 StringRef FunctionName =
P.first;
2668 CfiFunctionLinkage
Linkage =
P.second.Linkage;
2669 MDNode *FuncMD =
P.second.FuncMD;
2671 if (
F &&
F->hasLocalLinkage()) {
2678 F->setName(
F->getName() +
".1");
2684 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2685 GlobalVariable::ExternalLinkage,
2686 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2688 LLVMContext::MD_guid,
2689 MDTuple::get(
M.getContext(), {FuncMD->getOperand(2).get()}));
2690 if (ExportSummary) {
2694 ->getUniqueInteger()
2696 if (
auto VI = ExportSummary->getValueInfo(GUID))
2698 VI.isDSOLocal(ExportSummary->withDSOLocalPropagation()));
2706 if (
F->hasAvailableExternallyLinkage()) {
2708 auto *OrigGUIDMD =
F->getMetadata(LLVMContext::MD_guid);
2711 F->setComdat(
nullptr);
2713 F->setMetadata(LLVMContext::MD_guid, OrigGUIDMD);
2718 if (
Linkage == CfiFunctionLinkage::Definition &&
2719 F->hasExternalWeakLinkage())
2726 if (
F->isDeclaration()) {
2727 if (
Linkage == CfiFunctionLinkage::WeakDeclaration)
2730 F->eraseMetadata(LLVMContext::MD_type);
2732 F->addMetadata(LLVMContext::MD_type,
2737 ->getUniqueInteger()
2745 struct AliasToCreate {
2747 std::string TargetName;
2749 std::vector<AliasToCreate> AliasesToCreate;
2753 if (ExportSummary) {
2754 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2755 for (
auto *AliasMD : AliasesMD->operands()) {
2758 StringRef AliasName = MDS->getString();
2759 if (!ExportedFunctions.count(AliasName))
2761 auto *AliasF =
M.getFunction(AliasName);
2766 if (Aliases.
empty())
2769 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2770 auto *AliasF = Aliases[
I];
2771 ExportedFunctions.
erase(AliasF->getName());
2772 AliasesToCreate.push_back(
2773 {AliasF, std::string(Aliases[0]->
getName())});
2779 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2780 for (GlobalObject &GO :
M.global_objects()) {
2787 bool IsJumpTableCanonical =
false;
2788 bool IsExported =
false;
2791 if (
auto It = ExportedFunctions.find(
F->getName());
2792 It != ExportedFunctions.end()) {
2793 IsJumpTableCanonical |=
2794 It->second.Linkage == CfiFunctionLinkage::Definition;
2800 }
else if (!
F->hasAddressTaken()) {
2801 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2810 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2812 GlobalTypeMembers[&GO] = GTM;
2813 for (MDNode *
Type : Types) {
2814 verifyTypeMDNode(&GO,
Type);
2815 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2816 Info.UniqueId = ++CurUniqueId;
2817 Info.RefGlobals.push_back(GTM);
2821 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2826 auto Ins = TypeIdUsers.
insert({TypeId, {}});
2829 auto &GCI = GlobalClasses.insert(TypeId);
2830 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2833 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2834 CurSet = GlobalClasses.unionSets(
2835 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2838 return Ins.first->second;
2842 for (
const Use &U : TypeTestFunc->
uses()) {
2851 for (
const Use &CIU : CI->
uses()) {
2854 OnlyAssumeUses =
false;
2863 auto TypeId = TypeIdMDVal->getMetadata();
2864 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2868 if (ICallBranchFunnelFunc) {
2869 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2872 "llvm.icall.branch.funnel not supported on this target");
2876 std::vector<GlobalTypeMember *> Targets;
2880 GlobalClassesTy::member_iterator CurSet;
2881 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2887 "Expected branch funnel operand to be global value");
2889 auto It = GlobalTypeMembers.
find(
Base);
2890 if (It == GlobalTypeMembers.
end())
2892 "defined global value with type metadata");
2893 GlobalTypeMember *GTM = It->second;
2894 Targets.push_back(GTM);
2895 GlobalClassesTy::member_iterator NewSet =
2896 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2900 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2903 GlobalClasses.unionSets(
2904 CurSet, GlobalClasses.findLeader(
2905 GlobalClasses.insert(ICallBranchFunnel::create(
2906 Alloc, CI, Targets, ++CurUniqueId))));
2910 if (ExportSummary) {
2911 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2912 for (
auto &
P : TypeIdInfo) {
2915 TypeId->getString())]
2919 for (
auto &
P : *ExportSummary) {
2920 for (
auto &S :
P.second.getSummaryList()) {
2921 if (!ExportSummary->isGlobalValueLive(S.get()))
2926 AddTypeIdUse(MD).IsExported =
true;
2931 if (GlobalClasses.empty())
2935 ScopedSaveAliaseesAndUsed S(M);
2937 for (
const auto &
C : GlobalClasses) {
2941 ++NumTypeIdDisjointSets;
2943 std::vector<Metadata *> TypeIds;
2944 std::vector<GlobalTypeMember *> Globals;
2945 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2946 for (
auto M : GlobalClasses.members(*
C)) {
2959 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2964 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2965 return F1->UniqueId < F2->UniqueId;
2969 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2973 allocateByteArrays();
2975 for (
auto A : AliasesToCreate) {
2976 auto *
Target =
M.getNamedValue(
A.TargetName);
2980 AliasGA->setVisibility(
A.Alias->getVisibility());
2981 AliasGA->setLinkage(
A.Alias->getLinkage());
2982 AliasGA->setDSOLocal(
A.Alias->isDSOLocal());
2983 AliasGA->takeName(
A.Alias);
2984 A.Alias->replaceAllUsesWith(AliasGA);
2985 A.Alias->eraseFromParent();
2989 if (ExportSummary) {
2990 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2991 for (
auto *Symver : SymversMD->operands()) {
2992 assert(Symver->getNumOperands() >= 2);
2995 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2997 if (!ExportedFunctions.count(SymbolName))
3000 M.appendModuleInlineAsm(
3001 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
3013 Changed = LowerTypeTestsModule::runForTesting(M, AM);
3015 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
3023 static_cast<PassInfoMixin<DropTypeTestsPass> *
>(
this)->
printPipeline(
3024 OS, MapClassName2PassName);
3027 case DropTestKind::Assume:
3030 case DropTestKind::All:
3063 for (
auto &GV : M.globals()) {
3070 auto MaySimplifyPtr = [&](
Value *Ptr) {
3072 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
3076 auto MaySimplifyInt = [&](
Value *
Op) {
3078 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
3080 return MaySimplifyPtr(PtrAsInt->getOperand(0));
3096 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
3100 if (U.getOperandNo() == 0 && CE &&
3101 CE->getOpcode() == Instruction::Sub &&
3102 MaySimplifyInt(CE->getOperand(1))) {
3108 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
3112 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")
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 ConstantInt * extractNumericTypeId(MDNode &MD)
Extracts a numeric type identifier from an MDNode containing type metadata.
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 void createCfiSymversMetadata(Module &DestM, const Module &SrcM)
static const unsigned kARMBTIJumpTableEntrySize
static CfiFunctionLinkage decodeCfiFunctionLinkage(uint8_t Encoded)
static void createCfiFunctionsMetadata(Module &DestM, ArrayRef< GlobalValue * > CfiFunctions, ProfileSummaryInfo &PSI, function_ref< const BlockFrequencyInfo &(Function &)> BFIGetter)
static BitSetInfo buildBitSet(ArrayRef< uint64_t > Offsets)
Build a bit set for list of offsets.
static const unsigned kARMv6MJumpTableEntrySize
static uint8_t encodeCfiFunctionLinkage(CfiFunctionLinkage Linkage, CfiFunctionHotness Hotness)
static CfiFunctionHotness decodeCfiFunctionHotness(uint8_t Encoded)
static const unsigned kHexagonJumpTableEntrySize
static void createCfiAliasesMetadata(Module &DestM, const Module &SrcM)
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
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...
static bool isDirectCall(const MCInst &Inst)
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.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
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 LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP Constant * getInBoundsPtrAdd(Constant *Ptr, Constant *Offset)
Create a getelementptr inbounds i8, ptr, offset 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 LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
This is the shared class of boolean and integer constants.
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)
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
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 GEPNoWrapFlags inBounds()
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.
bool hasMetadata() const
Return true if this GlobalObject has any metadata attached to it.
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.
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreatePtrAddWithSExtOrTrunc(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Create a ptradd where the offset is sign-extended or truncated to the index type.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
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.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
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)
This class implements a map that also provides access to all stored values in a deterministic order.
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()
static LLVM_ABI void CollectAsmSymvers(const Module &M, function_ref< void(StringRef, StringRef)> AsmSymver)
Parse inline ASM and collect the symvers directives that are defined in the current module.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
iterator_range< alias_iterator > aliases()
NamedMDNode * getOrInsertNamedMetadata(StringRef Name)
Return the named MDNode in the module with the specified name.
iterator_range< op_iterator > operands()
LLVM_ABI void addOperand(MDNode *M)
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.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified 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.
Analysis providing profile information.
bool isFunctionColdInCallGraph(const FuncT *F, BFIT &BFI) const
Returns true if F contains only cold code.
LLVM_ABI bool isFunctionHotnessUnknown(const Function &F) const
Returns true if the hotness of F is unknown.
bool isFunctionHotInCallGraph(const FuncT *F, BFIT &BFI) const
Returns true if F contains hot code.
LLVM_ABI bool hasPartialSampleProfile() const
Returns true if module M has partial-profile sample profile.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
A vector that has set insertion semantics.
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.
std::string str() const
Get the contents as an std::string.
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 bool empty() const
Check if the string is empty.
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 IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(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.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
void insert_range(Range &&R)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements a layout algorithm for globals referenced by bit sets that tries to keep member...
LLVM_ABI const std::vector< uint64_t > & build()
Flatten fragments into a single layout and return it.
LLVM_ABI void addFragment(const std::set< uint64_t > &F)
Add F to the layout while trying to keep its indices contiguous.
This class implements an extremely fast bulk output stream that can only output to a stream.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI SetVector< uint64_t > findCfiTypeIds(const Module &M)
Finds all 64-bit numeric type identifiers in M used for cross-DSO CFI.
LLVM_ABI bool cleanUpTypeCheckedLoad(Module &M, Function &CheckedLoadFn, bool IsRelative)
Lower @llvm.type.checked.load[.relative] calls to the guarded load with the check assumed true,...
LLVM_ABI void createCfiMetadata(Module &DestM, const Module &SrcM, ArrayRef< GlobalValue * > CfiFunctions, ProfileSummaryInfo &PSI, function_ref< const BlockFrequencyInfo &(Function &)> BFIGetter)
Creates cfi.functions, aliases, and symvers named metadata in DestM for CFI functions in CfiFunctions...
LLVM_ABI bool isJumpTableCanonical(Function *F)
LLVM_ABI bool hasTypeMetadata(const GlobalObject &GO)
Returns whether a global or its associated global has attached type metadata.
LLVM_ABI SetVector< GlobalValue * > findCfiFunctions(Module &M)
Finds all functions and aliases in M that may need CFI jump table entries.
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.
bool operator<(int64_t V1, const APSInt &V2)
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.
@ Unknown
Not known to have no common set bits.
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.
@ Load
The value being inserted comes from a load (InsertElement only).
PassSummaryAction
What to do with the summary when running passes that operate on it.
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...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
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 make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
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.
const IPOOptions & getIPOOptions(const LLVMContext &C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
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.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
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.
LLVM_ABI std::unique_ptr< ModuleSummaryIndex > parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err)
Parse LLVM Assembly for summary index from a MemoryBuffer.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
LLVM_ABI GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Kind
Specifies which kind of type check we should emit for this byte array.
@ Unknown
Unknown (analysis not performed, don't lower)
@ Single
Single element (last example in "Short Inline Bit Vectors")
@ Inline
Inlined bit vector ("Short Inline Bit Vectors")
@ Unsat
Unsatisfiable type (i.e. no global has this type metadata)
@ AllOnes
All-ones bit vector ("Eliminating Bit Vector Checks for All-Ones Bit Vectors")
@ ByteArray
Test a byte array (first example)
unsigned SizeM1BitWidth
Range of size-1 expressed as a bit width.
enum llvm::TypeTestResolution::Kind TheKind
LLVM_ABI BitSetInfo build()
SmallVector< uint64_t, 16 > Offsets
LLVM_ABI bool containsGlobalOffset(uint64_t Offset) const
LLVM_ABI void print(raw_ostream &OS) const
std::set< uint64_t > Bits
This class is used to build a byte array containing overlapping bit sets.
uint64_t BitAllocs[BitsPerByte]
The number of bytes allocated so far for each of the bits.
std::vector< uint8_t > Bytes
The byte array built so far.
LLVM_ABI void allocate(const std::set< uint64_t > &Bits, uint64_t BitSize, uint64_t &AllocByteOffset, uint8_t &AllocMask)
Allocate BitSize bits in the byte array where Bits contains the bits to set.