95#include <system_error>
102#define DEBUG_TYPE "lowertypetests"
105STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
106STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
107STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
108STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
111 "lowertypetests-avoid-reuse",
112 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
116 "lowertypetests-summary-action",
117 cl::desc(
"What to do with the summary when running this pass"),
120 "Import typeid resolutions from summary and globals"),
122 "Export typeid resolutions to summary and globals")),
127 cl::desc(
"Read summary from given textual assembly or YAML "
128 "file before running pass"),
132 "lowertypetests-write-summary",
133 cl::desc(
"Write summary to given YAML file after running pass"),
139 cl::desc(
"Enable debug info generation for jump tables"));
144 cl::desc(
"Reorder CFI jump tables using profile information"));
170 for (uint64_t
B :
Bits)
213 assert(Fragments.front().empty() &&
"Cannot add fragments after build()");
216 Fragments.emplace_back();
217 std::vector<uint64_t> &
Fragment = Fragments.back();
218 uint64_t FragmentIndex = Fragments.size() - 1;
220 std::vector<std::vector<uint64_t>> SubFragments;
221 for (
auto ObjIndex :
F) {
222 uint64_t OldFragmentIndex = FragmentMap[ObjIndex];
223 if (OldFragmentIndex == 0) {
226 SubFragments.push_back({ObjIndex});
227 }
else if (!Fragments[OldFragmentIndex].empty()) {
233 SubFragments.push_back(std::move(Fragments[OldFragmentIndex]));
239 const std::vector<uint64_t> &
B) {
240 return Less(
A.back(),
B.back());
244 for (
auto &SF : SubFragments)
249 FragmentMap[ObjIndex] = FragmentIndex;
258 [](
const std::vector<uint64_t> &
F) {
return F.empty(); });
260 const std::vector<uint64_t> &FB) {
261 return Less(FA.back(), FB.back());
265 std::vector<uint64_t> Layout;
266 Layout.reserve(FragmentMap.size());
267 for (
auto &&
F : Fragments)
270 Fragments.push_back(std::move(Layout));
271 return Fragments.front();
275 uint64_t BitSize, uint64_t &AllocByteOffset,
286 unsigned ReqSize = AllocByteOffset + BitSize;
288 if (
Bytes.size() < ReqSize)
289 Bytes.resize(ReqSize);
292 AllocMask = 1 << Bit;
293 for (uint64_t
B : Bits)
294 Bytes[AllocByteOffset +
B] |= AllocMask;
298 if (
F->isDeclarationForLinker())
301 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
302 if (!CI || !CI->isZero())
304 return F->hasFnAttribute(
"cfi-canonical-jump-table");
311 if (AssocGO->hasMetadata(LLVMContext::MD_type))
321 for (
auto &
A : M.aliases())
338 if (
C->getBitWidth() != 64)
349 GO.getMetadata(LLVMContext::MD_type, Types);
352 TypeIds.
insert(TypeId->getZExtValue());
355 if (
NamedMDNode *CfiFunctionsMD = M.getNamedMetadata(
"cfi.functions")) {
356 for (
auto *Func : CfiFunctionsMD->operands()) {
357 assert(Func->getNumOperands() >= 3);
359 for (
unsigned I = 3;
I < Func->getNumOperands(); ++
I)
362 TypeIds.
insert(TypeId->getZExtValue());
371enum class CfiFunctionLinkage :
uint8_t {
378class CfiFunctionHotness {
391 CfiFunctionHotness() =
default;
400 static CfiFunctionHotness
401 fromFunction(
Function &
F, ProfileSummaryInfo &PSI,
402 function_ref<
const BlockFrequencyInfo &(
Function &)> BFIGetter) {
403 if (
F.isDeclaration())
404 return Kind::Unknown;
407 const BlockFrequencyInfo &BFI = BFIGetter(
F);
408 if (
F.hasFnAttribute(Attribute::Hot) ||
414 F.hasFnAttribute(Attribute::Cold)) {
423 static CfiFunctionHotness fromUint6(uint8_t V) {
424 return CfiFunctionHotness(
static_cast<Kind>(V & 0x3));
427 uint8_t asUint6()
const {
return static_cast<uint8_t
>(
Type) & 0x3; }
434 auto Rank = [](
Kind K) ->
int {
435 return (K == Kind::Cold) ? -1 :
static_cast<int>(
K);
444 return static_cast<CfiFunctionLinkage
>(Encoded & 0x3);
448 return CfiFunctionHotness::fromUint6(Encoded >> 2);
452 CfiFunctionHotness Hotness) {
466 for (
auto *V : CfiFunctions) {
469 F.getMetadata(LLVMContext::MD_type, Types);
473 CfiFunctionLinkage
Linkage = CfiFunctionLinkage::Declaration;
475 Linkage = CfiFunctionLinkage::Definition;
476 else if (
F.hasExternalWeakLinkage())
477 Linkage = CfiFunctionLinkage::WeakDeclaration;
479 CfiFunctionHotness Hotness =
481 ? CfiFunctionHotness::fromFunction(
F, PSI, BFIGetter)
482 : CfiFunctionHotness();
495 if (!CfiFunctionMDs.
empty()) {
497 for (
auto *MD : CfiFunctionMDs)
505 for (
const auto &
A : SrcM.
aliases()) {
510 FunctionAliases[
F].push_back(&
A);
513 if (!FunctionAliases.
empty()) {
515 for (
auto &Alias : FunctionAliases) {
518 for (
auto *
A : Alias.second)
531 if (!
F ||
F->use_empty())
538 if (!Symvers.
empty()) {
540 for (
auto *MD : Symvers)
556struct ByteArrayInfo {
557 std::set<uint64_t> Bits;
569class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
580 bool IsJumpTableCanonical;
588 bool IsJumpTableCanonical,
bool IsExported,
590 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
591 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
593 GTM->NTypes = Types.size();
594 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
595 GTM->IsExported = IsExported;
600 GlobalObject *getGlobal()
const {
605 return IsJumpTableCanonical;
608 bool isExported()
const {
615struct ICallBranchFunnel final
616 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
620 auto *
Call =
static_cast<ICallBranchFunnel *
>(
621 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
622 alignof(ICallBranchFunnel)));
624 Call->UniqueId = UniqueId;
632 return getTrailingObjects(NTargets);
641struct ScopedSaveAliaseesAndUsed {
644 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
645 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
650 void collectAndEraseUsedFunctions(
Module &M,
651 SmallVectorImpl<GlobalValue *> &Vec,
659 GV->eraseFromParent();
661 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
662 return isa<Function>(GV);
671 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
684 collectAndEraseUsedFunctions(M, Used,
false);
685 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
687 for (
auto &GA :
M.aliases()) {
691 FunctionAliases.push_back({&GA,
F});
694 for (
auto &GI :
M.ifuncs())
696 ResolverIFuncs.push_back({&GI,
F});
699 ~ScopedSaveAliaseesAndUsed() {
703 for (
auto P : FunctionAliases)
704 P.first->setAliasee(
P.second);
706 for (
auto P : ResolverIFuncs) {
710 P.first->setResolver(
P.second);
715class LowerTypeTestsModule {
718 ModuleSummaryIndex *ExportSummary;
719 const ModuleSummaryIndex *ImportSummary;
728 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
731 int HasBranchTargetEnforcement = -1;
734 DenseMap<const Function *, CfiFunctionHotness> FunctionSummaryHotness;
736 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
737 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
738 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
739 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
740 IntegerType *Int32Ty = Type::getInt32Ty(
M.getContext());
741 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
742 IntegerType *
IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
750 struct TypeIdUserInfo {
751 std::vector<CallInst *> CallSites;
752 bool IsExported =
false;
754 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
760 struct TypeIdLowering {
785 std::vector<ByteArrayInfo> ByteArrayInfos;
787 Function *WeakInitializerFn =
nullptr;
789 GlobalVariable *GlobalAnnotation;
790 DenseSet<Value *> FunctionAnnotations;
794 bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
796 bool shouldExportConstantsAsAbsoluteSymbols();
797 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
798 TypeIdLowering importTypeId(StringRef TypeId);
799 void importTypeTest(CallInst *CI);
802 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
803 void allocateByteArrays();
806 void lowerTypeTestCalls(
808 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
810 const TypeIdLowering &TIL);
816 bool hasBranchTargetEnforcement();
819 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
831 void replaceWeakDeclarationWithJumpTablePtr(
Function *
F, Constant *JT,
832 bool IsJumpTableCanonical);
833 void moveInitializerToModuleConstructor(GlobalVariable *GV);
834 void findGlobalVariableUsersOf(Constant *
C,
835 SmallSetVector<GlobalVariable *, 8> &Out);
844 void replaceCfiUses(
Function *Old,
Value *New,
bool IsJumpTableCanonical);
848 void replaceDirectCalls(
Value *Old,
Value *New);
850 bool isFunctionAnnotation(
Value *V)
const {
851 return FunctionAnnotations.
contains(V);
854 void maybeReplaceComdat(
Function *
F, StringRef OriginalName);
858 ModuleSummaryIndex *ExportSummary,
859 const ModuleSummaryIndex *ImportSummary);
881 unsigned BitWidth = BitsType->getBitWidth();
883 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
885 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
886 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
887 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
888 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
891ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
895 auto ByteArrayGlobal =
new GlobalVariable(
897 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
900 ByteArrayInfos.emplace_back();
901 ByteArrayInfo *BAI = &ByteArrayInfos.back();
903 BAI->Bits = BSI.
Bits;
905 BAI->ByteArray = ByteArrayGlobal;
906 BAI->MaskGlobal = MaskGlobal;
910void LowerTypeTestsModule::allocateByteArrays() {
912 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
913 return BAI1.BitSize > BAI2.BitSize;
916 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
919 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
920 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
923 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
929 *BAI->MaskPtr =
Mask;
934 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
937 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
938 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
940 ByteArray, ConstantInt::get(
IntPtrTy, ByteArrayOffsets[
I]));
954 ByteArraySizeBytes = BAB.
Bytes.size();
960 const TypeIdLowering &TIL,
974 "bits_use", ByteArray, &M);
977 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
982 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
990 GV->getMetadata(LLVMContext::MD_type, Types);
992 if (
Type->getOperand(1) != TypeId)
1005 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
1006 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
1014 if (
Op->getOpcode() == Instruction::BitCast)
1017 if (
Op->getOpcode() == Instruction::Select)
1027Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
1028 const TypeIdLowering &TIL) {
1036 const DataLayout &
DL =
M.getDataLayout();
1049 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
1055 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
1066 {PtrOffset, PtrOffset, TIL.AlignLog2});
1068 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
1072 return OffsetInRange;
1085 Br->getMetadata(LLVMContext::MD_prof));
1089 for (
auto &Phi :
Else->phis())
1090 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
1093 return createBitSetTest(ThenB, TIL, BitOffset);
1096 MDBuilder MDB(
M.getContext());
1098 MDB.createLikelyBranchWeights()));
1102 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
1107 B.SetInsertPoint(CI);
1108 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
1109 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
1110 P->addIncoming(Bit, ThenB.GetInsertBlock());
1116void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
1123 std::vector<Constant *> GlobalInits;
1124 const DataLayout &
DL =
M.getDataLayout();
1125 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1129 for (GlobalTypeMember *
G : Globals) {
1132 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
1133 MaxAlign = std::max(MaxAlign, Alignment);
1135 GlobalLayout[
G] = GVOffset;
1136 if (GVOffset != 0) {
1138 GlobalInits.push_back(
1142 GlobalInits.push_back(GV->getInitializer());
1144 CurOffset = GVOffset + InitSize;
1147 DesiredPadding =
NextPowerOf2(InitSize - 1) - InitSize;
1153 if (DesiredPadding > 32)
1154 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
1158 auto *CombinedGlobal =
1159 new GlobalVariable(M, NewInit->
getType(),
true,
1161 CombinedGlobal->setAlignment(MaxAlign);
1164 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
1169 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
1173 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
1174 ConstantInt::get(Int32Ty,
I * 2)};
1176 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
1178 GlobalAlias *GAlias =
1180 "", CombinedGlobalElemPtr, &M);
1188bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
1201uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
1202 const TypeIdLowering &TIL) {
1203 TypeTestResolution &TTRes =
1210 "__typeid_" + TypeId +
"_" + Name,
C, &M);
1215 if (shouldExportConstantsAsAbsoluteSymbols())
1222 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
1227 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
1228 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
1238 ExportGlobal(
"byte_array", TIL.TheByteArray);
1239 if (shouldExportConstantsAsAbsoluteSymbols())
1240 ExportGlobal(
"bit_mask", TIL.BitMask);
1246 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
1251LowerTypeTestsModule::TypeIdLowering
1252LowerTypeTestsModule::importTypeId(StringRef TypeId) {
1256 const TypeTestResolution &TTRes = TidSummary->
TTRes;
1261 auto ImportGlobal = [&](StringRef
Name) {
1264 GlobalVariable *GV =
M.getOrInsertGlobal(
1265 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
1272 if (!shouldExportConstantsAsAbsoluteSymbols()) {
1284 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
1293 if (AbsWidth ==
IntPtrTy->getBitWidth()) {
1297 SetAbsRange(0, 1ull << AbsWidth);
1303 auto *GV = ImportGlobal(
"global_addr");
1316 TIL.OffsetedGlobal = GV;
1328 TIL.TheByteArray = ImportGlobal(
"byte_array");
1329 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1333 TIL.InlineBits = ImportConstant(
1340void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1352 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1353 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1360void LowerTypeTestsModule::maybeReplaceComdat(
Function *
F,
1361 StringRef OriginalName) {
1367 F->getComdat()->getName() == OriginalName) {
1368 Comdat *OldComdat =
F->getComdat();
1369 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1370 for (GlobalObject &GO :
M.global_objects()) {
1379void LowerTypeTestsModule::importFunction(
Function *
F,
1381 assert(
F->getType()->getAddressSpace() == 0);
1384 std::string
Name = std::string(
F->getName());
1389 if (!
F->isDSOLocal())
1391 if (
F->isDeclaration()) {
1396 F->getAddressSpace(),
1399 replaceDirectCalls(
F, RealF);
1416 F->getAddressSpace(), Name +
".cfi_jt", &M);
1419 F->setName(Name +
".cfi");
1420 maybeReplaceComdat(
F, Name);
1422 F->getAddressSpace(), Name, &M);
1430 for (
auto &U :
F->uses()) {
1432 std::string AliasName =
A->getName().str() +
".cfi";
1435 F->getAddressSpace(),
"", &M);
1437 A->replaceAllUsesWith(AliasDecl);
1438 A->setName(AliasName);
1444 if (
F->hasExternalWeakLinkage())
1451 F->setVisibility(Visibility);
1460 OffsetsByTypeID[TypeId];
1461 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1463 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1464 if (It == OffsetsByTypeID.
end())
1470 It->second.push_back(MemOff +
Offset);
1480 dbgs() << MDS->getString() <<
": ";
1482 dbgs() <<
"<unnamed>: ";
1483 BitSets.
back().second.print(
dbgs());
1490void LowerTypeTestsModule::lowerTypeTestCalls(
1492 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1494 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1495 ByteArrayInfo *BAI =
nullptr;
1501 CombinedGlobalAddr, ConstantInt::get(
IntPtrTy, GlobalOffset)),
1506 : TypeTestResolution::
AllOnes;
1510 for (
auto Bit : BSI.
Bits)
1512 if (InlineBits == 0)
1515 TIL.InlineBits = ConstantInt::get(
1516 (BSI.
BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1519 ++NumByteArraysCreated;
1520 BAI = createByteArray(BSI);
1521 TIL.TheByteArray = BAI->ByteArray;
1522 TIL.BitMask = BAI->MaskGlobal;
1525 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1527 if (TIUI.IsExported) {
1528 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1530 BAI->MaskPtr = MaskPtr;
1534 for (CallInst *CI : TIUI.CallSites) {
1535 ++NumTypeTestCallsLowered;
1536 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1545void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1546 if (
Type->getNumOperands() != 2)
1553 "A member of a type identifier may not have an explicit section");
1576bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1577 if (HasBranchTargetEnforcement == -1) {
1581 M.getModuleFlag(
"branch-target-enforcement")))
1582 HasBranchTargetEnforcement = !BTE->isZero();
1584 HasBranchTargetEnforcement = 0;
1586 return HasBranchTargetEnforcement;
1590LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1591 switch (JumpTableArch) {
1595 M.getModuleFlag(
"cf-protection-branch")))
1596 if (MD->getZExtValue())
1602 if (CanUseThumbBWJumpTable) {
1603 if (hasBranchTargetEnforcement())
1610 if (hasBranchTargetEnforcement())
1629LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1631 raw_string_ostream AsmOS(Asm);
1636 M.getModuleFlag(
"cf-protection-branch")))
1637 Endbr = !MD->isZero();
1639 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1640 AsmOS <<
"jmp ${0:c}@plt\n";
1642 AsmOS <<
".balign 16, 0xcc\n";
1644 AsmOS <<
"int3\nint3\nint3\n";
1648 if (hasBranchTargetEnforcement())
1652 if (!CanUseThumbBWJumpTable) {
1668 AsmOS <<
"push {r0,r1}\n"
1670 <<
"0: add r0, r0, pc\n"
1671 <<
"str r0, [sp, #4]\n"
1674 <<
"1: .word $0 - (0b + 4)\n";
1676 if (hasBranchTargetEnforcement())
1678 AsmOS <<
"b.w $0\n";
1682 AsmOS <<
"tail $0@plt\n";
1684 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1685 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1687 AsmOS <<
"jump $0\n";
1700void LowerTypeTestsModule::buildBitSetsFromFunctions(
1706 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1708 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1713void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1714 GlobalVariable *GV) {
1715 if (WeakInitializerFn ==
nullptr) {
1720 M.getDataLayout().getProgramAddressSpace(),
1721 "__cfi_global_var_init", &M);
1727 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1740void LowerTypeTestsModule::findGlobalVariableUsersOf(
1741 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1742 for (
auto *U :
C->users()){
1746 findGlobalVariableUsersOf(C2, Out);
1751void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1752 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1755 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1756 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1757 for (
auto *GV : GlobalVarUsers) {
1758 if (GV == GlobalAnnotation)
1760 moveInitializerToModuleConstructor(GV);
1767 F->getAddressSpace(),
"", &M);
1768 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1775 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1778 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1790 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1798 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1803 if (Feature ==
"-thumb-mode")
1805 else if (Feature ==
"+thumb-mode")
1821 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1829 unsigned ArmCount = 0, ThumbCount = 0;
1830 for (
const auto GTM : Functions) {
1831 if (!GTM->isJumpTableCanonical()) {
1852 auto CUs = M.debug_compile_units();
1869 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1870 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1872 F->setSubprogram(UbsanSP);
1877 Locations.
reserve(Functions.size());
1879 for (
auto *Func : Functions) {
1880 StringRef FuncName = Func->getGlobal()->getName();
1883 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1884 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1889 Locations.push_back(EntryLoc);
1897void LowerTypeTestsModule::createJumpTable(
1906 F->setMetadata(LLVMContext::MD_elf_section_properties,
1909 ConstantAsMetadata::get(ConstantInt::get(
1910 Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
1911 ConstantAsMetadata::get(ConstantInt::get(
1912 Int64Ty, JumpTableEntrySize))}));
1921 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1927 bool areAllEntriesNounwind =
true;
1929 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1930 if (Loc.has_value())
1931 IRB.SetCurrentDebugLocation(*Loc);
1933 ->hasFnAttribute(Attribute::NoUnwind)) {
1934 areAllEntriesNounwind =
false;
1936 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1938 IRB.CreateUnreachable();
1941 F->setPreferredAlignment(
Align(JumpTableEntrySize));
1942 F->addFnAttr(Attribute::Naked);
1944 F->addFnAttr(
"target-features",
"-thumb-mode");
1946 if (hasBranchTargetEnforcement()) {
1949 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1951 F->addFnAttr(
"target-features",
"+thumb-mode");
1952 if (CanUseThumbBWJumpTable) {
1955 F->addFnAttr(
"target-cpu",
"cortex-a8");
1963 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1964 F->removeFnAttr(
"branch-target-enforcement");
1965 if (
F->hasFnAttribute(
"sign-return-address"))
1966 F->removeFnAttr(
"sign-return-address");
1971 F->addFnAttr(
"target-features",
"-c,-relax");
1977 F->addFnAttr(Attribute::NoCfCheck);
1980 if (areAllEntriesNounwind)
1981 F->addFnAttr(Attribute::NoUnwind);
1984 F->addFnAttr(Attribute::NoInline);
1989void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
2074 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
2075 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
2076 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
2077 GlobalLayout[Functions[
I]] =
I * EntrySize;
2083 M.getDataLayout().getProgramAddressSpace(),
2084 ".cfi.jumptable", &M);
2091 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
2095 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
2097 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
2100 JumpTableType, JumpTable,
2104 const bool IsExported = Functions[
I]->isExported();
2105 if (!IsJumpTableCanonical) {
2109 F->getName() +
".cfi_jt",
2110 CombinedGlobalElemPtr, &M);
2119 if (IsJumpTableCanonical)
2127 if (!IsJumpTableCanonical) {
2128 if (
F->hasExternalWeakLinkage())
2129 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
2130 IsJumpTableCanonical);
2132 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
2134 assert(
F->getType()->getAddressSpace() == 0);
2136 GlobalAlias *FAlias =
2138 CombinedGlobalElemPtr, &M);
2143 F->setName(FAlias->
getName() +
".cfi");
2144 maybeReplaceComdat(
F, FAlias->
getName());
2146 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
2147 if (!
F->hasLocalLinkage())
2152 createJumpTable(JumpTableFn, Functions, JumpTableArch);
2161void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
2166 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
2168 for (GlobalTypeMember *GTM : Functions) {
2172 if (!
F->hasAddressTaken())
2178 ConstantInt::get(Int64Ty, IndirectIndex))));
2179 F->setMetadata(
"wasm.index", MD);
2182 GlobalLayout[GTM] = IndirectIndex++;
2191void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
2194 DenseMap<Metadata *, uint64_t> TypeIdIndices;
2195 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
2196 TypeIdIndices[TypeIds[
I]] =
I;
2200 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
2201 unsigned GlobalIndex = 0;
2202 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
2203 for (GlobalTypeMember *GTM : Globals) {
2204 for (MDNode *
Type : GTM->types()) {
2206 auto I = TypeIdIndices.
find(
Type->getOperand(1));
2207 if (
I != TypeIdIndices.
end())
2208 TypeMembers[
I->second].insert(GlobalIndex);
2210 GlobalIndices[GTM] = GlobalIndex;
2214 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
2215 TypeMembers.emplace_back();
2216 std::set<uint64_t> &TMSet = TypeMembers.back();
2217 for (GlobalTypeMember *
T : JT->targets())
2218 TMSet.insert(GlobalIndices[
T]);
2224 const std::set<uint64_t> &
O2) {
2225 return O1.size() <
O2.size();
2232 if (!IsGlobalSet && !FunctionSummaryHotness.
empty() &&
2235 std::vector<CfiFunctionHotness> GTMHotness;
2236 GTMHotness.reserve(Globals.size());
2237 for (GlobalTypeMember *GTM : Globals) {
2238 GTMHotness.push_back(
2255 return GTMHotness[
A] < GTMHotness[
B];
2263 for (
auto &&MemSet : TypeMembers)
2264 GLB.addFragment(MemSet);
2267 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
2268 auto OGTMI = OrderedGTMs.begin();
2272 "variables and functions");
2273 *OGTMI++ = Globals[
Offset];
2278 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
2280 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
2284LowerTypeTestsModule::LowerTypeTestsModule(
2286 const ModuleSummaryIndex *ImportSummary)
2287 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
2288 assert(!(ExportSummary && ImportSummary));
2289 Triple TargetTriple(M.getTargetTriple());
2290 Arch = TargetTriple.getArch();
2294 CanUseArmJumpTable =
true;
2298 if (
F.isDeclaration())
2301 if (
TTI.hasArmWideBranch(
false))
2302 CanUseArmJumpTable =
true;
2303 if (
TTI.hasArmWideBranch(
true))
2304 CanUseThumbBWJumpTable =
true;
2307 OS = TargetTriple.getOS();
2308 ObjectFormat = TargetTriple.getObjectFormat();
2312 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
2321 std::unique_ptr<ModuleSummaryIndex>
Summary;
2326 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
2332 if (ReadSummaryFile->getBuffer().starts_with(
"---")) {
2333 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2334 yaml::Input
In(ReadSummaryFile->getBuffer());
2347 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2351 LowerTypeTestsModule(
2360 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
2366 yaml::Output
Out(OS);
2375 return Usr && Usr->isCallee(&U);
2378void LowerTypeTestsModule::replaceCfiUses(
Function *Old,
Value *New,
2379 bool IsJumpTableCanonical) {
2380 SmallSetVector<Constant *, 4>
Constants;
2392 if (isFunctionAnnotation(
U.getUser()))
2410 for (
auto *
C : Constants)
2411 C->handleOperandChange(Old, New);
2414void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2419 bool ShouldDropAll) {
2425 Assume->eraseFromParent();
2434 return isa<PHINode>(U) || isa<SelectInst>(U);
2452 if (PublicTypeTestFunc)
2454 if (TypeTestFunc || PublicTypeTestFunc) {
2465bool LowerTypeTestsModule::lower() {
2479 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2480 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2481 !ExportSummary && !ImportSummary)
2484 if (ImportSummary) {
2489 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2491 "unexpected call to llvm.icall.branch.funnel during import phase");
2498 if (
F.hasLocalLinkage())
2507 ScopedSaveAliaseesAndUsed S(M);
2508 for (
auto *
F : Defs)
2509 importFunction(
F,
true);
2510 for (
auto *
F : Decls)
2511 importFunction(
F,
false);
2520 using GlobalClassesTy = EquivalenceClasses<
2521 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2522 GlobalClassesTy GlobalClasses;
2534 std::vector<GlobalTypeMember *> RefGlobals;
2536 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2537 unsigned CurUniqueId = 0;
2540 struct ExportedFunctionInfo {
2544 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2545 if (ExportSummary) {
2546 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2547 if (CfiFunctionsMD) {
2549 DenseSet<GlobalValue::GUID> AddressTaken;
2550 for (
auto &
I : *ExportSummary)
2551 for (
auto &GVS :
I.second.getSummaryList())
2553 for (
const auto &
Ref : GVS->refs()) {
2555 for (
auto &RefGVS :
Ref.getSummaryList())
2557 AddressTaken.
insert(Alias->getAliaseeGUID());
2560 if (AddressTaken.
count(GUID))
2562 auto VI = ExportSummary->getValueInfo(GUID);
2565 for (
auto &
I :
VI.getSummaryList())
2567 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2571 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2572 assert(FuncMD->getNumOperands() >= 2);
2573 StringRef FunctionName =
2578 ->getUniqueInteger()
2583 ->getUniqueInteger()
2587 if (!ExportSummary->isGUIDLive(GUID))
2590 if (!CrossDsoCfi ||
Linkage != CfiFunctionLinkage::Definition)
2594 if (
auto VI = ExportSummary->getValueInfo(GUID))
2595 for (
const auto &GVS :
VI.getSummaryList())
2602 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2604 P.first->second.Linkage != CfiFunctionLinkage::Definition)
2605 P.first->second = {
Linkage, FuncMD};
2608 for (
const auto &
P : ExportedFunctions) {
2609 StringRef FunctionName =
P.first;
2610 CfiFunctionLinkage
Linkage =
P.second.Linkage;
2611 MDNode *FuncMD =
P.second.FuncMD;
2613 if (
F &&
F->hasLocalLinkage()) {
2620 F->setName(
F->getName() +
".1");
2626 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2627 GlobalVariable::ExternalLinkage,
2628 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2630 LLVMContext::MD_guid,
2631 MDTuple::get(
M.getContext(), {FuncMD->getOperand(2).get()}));
2632 if (ExportSummary) {
2636 ->getUniqueInteger()
2638 if (
auto VI = ExportSummary->getValueInfo(GUID))
2640 VI.isDSOLocal(ExportSummary->withDSOLocalPropagation()));
2648 if (
F->hasAvailableExternallyLinkage()) {
2650 auto *OrigGUIDMD =
F->getMetadata(LLVMContext::MD_guid);
2653 F->setComdat(
nullptr);
2655 F->setMetadata(LLVMContext::MD_guid, OrigGUIDMD);
2660 if (
Linkage == CfiFunctionLinkage::Definition &&
2661 F->hasExternalWeakLinkage())
2668 if (
F->isDeclaration()) {
2669 if (
Linkage == CfiFunctionLinkage::WeakDeclaration)
2672 F->eraseMetadata(LLVMContext::MD_type);
2674 F->addMetadata(LLVMContext::MD_type,
2679 ->getUniqueInteger()
2687 struct AliasToCreate {
2689 std::string TargetName;
2691 std::vector<AliasToCreate> AliasesToCreate;
2695 if (ExportSummary) {
2696 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2697 for (
auto *AliasMD : AliasesMD->operands()) {
2700 StringRef AliasName = MDS->getString();
2701 if (!ExportedFunctions.count(AliasName))
2703 auto *AliasF =
M.getFunction(AliasName);
2708 if (Aliases.
empty())
2711 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2712 auto *AliasF = Aliases[
I];
2713 ExportedFunctions.
erase(AliasF->getName());
2714 AliasesToCreate.push_back(
2715 {AliasF, std::string(Aliases[0]->
getName())});
2721 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2722 for (GlobalObject &GO :
M.global_objects()) {
2729 bool IsJumpTableCanonical =
false;
2730 bool IsExported =
false;
2733 if (
auto It = ExportedFunctions.find(
F->getName());
2734 It != ExportedFunctions.end()) {
2735 IsJumpTableCanonical |=
2736 It->second.Linkage == CfiFunctionLinkage::Definition;
2742 }
else if (!
F->hasAddressTaken()) {
2743 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2752 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2754 GlobalTypeMembers[&GO] = GTM;
2755 for (MDNode *
Type : Types) {
2756 verifyTypeMDNode(&GO,
Type);
2757 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2758 Info.UniqueId = ++CurUniqueId;
2759 Info.RefGlobals.push_back(GTM);
2763 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2768 auto Ins = TypeIdUsers.
insert({TypeId, {}});
2771 auto &GCI = GlobalClasses.insert(TypeId);
2772 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2775 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2776 CurSet = GlobalClasses.unionSets(
2777 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2780 return Ins.first->second;
2784 for (
const Use &U : TypeTestFunc->
uses()) {
2793 for (
const Use &CIU : CI->
uses()) {
2796 OnlyAssumeUses =
false;
2805 auto TypeId = TypeIdMDVal->getMetadata();
2806 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2810 if (ICallBranchFunnelFunc) {
2811 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2814 "llvm.icall.branch.funnel not supported on this target");
2818 std::vector<GlobalTypeMember *> Targets;
2822 GlobalClassesTy::member_iterator CurSet;
2823 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2829 "Expected branch funnel operand to be global value");
2831 auto It = GlobalTypeMembers.
find(
Base);
2832 if (It == GlobalTypeMembers.
end())
2834 "defined global value with type metadata");
2835 GlobalTypeMember *GTM = It->second;
2836 Targets.push_back(GTM);
2837 GlobalClassesTy::member_iterator NewSet =
2838 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2842 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2845 GlobalClasses.unionSets(
2846 CurSet, GlobalClasses.findLeader(
2847 GlobalClasses.insert(ICallBranchFunnel::create(
2848 Alloc, CI, Targets, ++CurUniqueId))));
2852 if (ExportSummary) {
2853 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2854 for (
auto &
P : TypeIdInfo) {
2857 TypeId->getString())]
2861 for (
auto &
P : *ExportSummary) {
2862 for (
auto &S :
P.second.getSummaryList()) {
2863 if (!ExportSummary->isGlobalValueLive(S.get()))
2868 AddTypeIdUse(MD).IsExported =
true;
2873 if (GlobalClasses.empty())
2877 ScopedSaveAliaseesAndUsed S(M);
2879 for (
const auto &
C : GlobalClasses) {
2883 ++NumTypeIdDisjointSets;
2885 std::vector<Metadata *> TypeIds;
2886 std::vector<GlobalTypeMember *> Globals;
2887 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2888 for (
auto M : GlobalClasses.members(*
C)) {
2901 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2906 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2907 return F1->UniqueId < F2->UniqueId;
2911 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2915 allocateByteArrays();
2917 for (
auto A : AliasesToCreate) {
2918 auto *
Target =
M.getNamedValue(
A.TargetName);
2922 AliasGA->setVisibility(
A.Alias->getVisibility());
2923 AliasGA->setLinkage(
A.Alias->getLinkage());
2924 AliasGA->setDSOLocal(
A.Alias->isDSOLocal());
2925 AliasGA->takeName(
A.Alias);
2926 A.Alias->replaceAllUsesWith(AliasGA);
2927 A.Alias->eraseFromParent();
2931 if (ExportSummary) {
2932 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2933 for (
auto *Symver : SymversMD->operands()) {
2934 assert(Symver->getNumOperands() >= 2);
2937 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2939 if (!ExportedFunctions.count(SymbolName))
2942 M.appendModuleInlineAsm(
2943 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2955 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2957 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
2965 static_cast<PassInfoMixin<DropTypeTestsPass> *
>(
this)->
printPipeline(
2966 OS, MapClassName2PassName);
2969 case DropTestKind::Assume:
2972 case DropTestKind::All:
3005 for (
auto &GV : M.globals()) {
3012 auto MaySimplifyPtr = [&](
Value *Ptr) {
3014 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
3018 auto MaySimplifyInt = [&](
Value *
Op) {
3020 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
3022 return MaySimplifyPtr(PtrAsInt->getOperand(0));
3038 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
3042 if (U.getOperandNo() == 0 && CE &&
3043 CE->getOpcode() == Instruction::Sub &&
3044 MaySimplifyInt(CE->getOperand(1))) {
3050 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
3054 if (U.getOperandNo() == 1 && CI &&
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
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 cl::opt< bool > ReorderCfiJumpTablesProfiles("reorder-cfi-jump-tables-profiles", cl::init(true), cl::Hidden, cl::desc("Reorder CFI jump tables using profile information"))
static const unsigned kLOONGARCH64JumpTableEntrySize
static cl::opt< std::string > ClReadSummary("lowertypetests-read-summary", cl::desc("Read summary from given textual assembly or YAML " "file before running pass"), cl::Hidden)
static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)
static const unsigned kX86IBTJumpTableEntrySize
static SmallVector< DILocation * > createJumpTableDebugInfo(Function *F, ArrayRef< GlobalTypeMember * > Functions)
static 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 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 CfiFunctionLinkage decodeCfiFunctionLinkage(uint8_t Encoded)
static void createCfiFunctionsMetadata(Module &DestM, ArrayRef< GlobalValue * > CfiFunctions, ProfileSummaryInfo &PSI, function_ref< const BlockFrequencyInfo &(Function &)> BFIGetter)
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 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...
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 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.
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.
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.
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.
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.
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.
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.
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 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.
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 SetVector< uint64_t > findCfiTypeIds(const Module &M)
Finds all 64-bit numeric type identifiers in M used for cross-DSO CFI.
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.
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...
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.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
DWARFExpression::Operation Op
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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.