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 DL, NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs,
1179 GlobalAlias *GAlias =
1181 "", CombinedGlobalElemPtr, &M);
1189bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
1202uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
1203 const TypeIdLowering &TIL) {
1204 TypeTestResolution &TTRes =
1211 "__typeid_" + TypeId +
"_" + Name,
C, &M);
1216 if (shouldExportConstantsAsAbsoluteSymbols())
1223 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
1228 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
1229 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
1239 ExportGlobal(
"byte_array", TIL.TheByteArray);
1240 if (shouldExportConstantsAsAbsoluteSymbols())
1241 ExportGlobal(
"bit_mask", TIL.BitMask);
1247 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
1252LowerTypeTestsModule::TypeIdLowering
1253LowerTypeTestsModule::importTypeId(StringRef TypeId) {
1257 const TypeTestResolution &TTRes = TidSummary->
TTRes;
1262 auto ImportGlobal = [&](StringRef
Name) {
1265 GlobalVariable *GV =
M.getOrInsertGlobal(
1266 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
1273 if (!shouldExportConstantsAsAbsoluteSymbols()) {
1285 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
1294 if (AbsWidth ==
IntPtrTy->getBitWidth()) {
1298 SetAbsRange(0, 1ull << AbsWidth);
1304 auto *GV = ImportGlobal(
"global_addr");
1317 TIL.OffsetedGlobal = GV;
1329 TIL.TheByteArray = ImportGlobal(
"byte_array");
1330 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1334 TIL.InlineBits = ImportConstant(
1341void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1353 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1354 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1361void LowerTypeTestsModule::maybeReplaceComdat(
Function *
F,
1362 StringRef OriginalName) {
1368 F->getComdat()->getName() == OriginalName) {
1369 Comdat *OldComdat =
F->getComdat();
1370 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1371 for (GlobalObject &GO :
M.global_objects()) {
1380void LowerTypeTestsModule::importFunction(
Function *
F,
1382 assert(
F->getType()->getAddressSpace() == 0);
1385 std::string
Name = std::string(
F->getName());
1390 if (!
F->isDSOLocal())
1392 if (
F->isDeclaration()) {
1397 F->getAddressSpace(),
1400 replaceDirectCalls(
F, RealF);
1417 F->getAddressSpace(), Name +
".cfi_jt", &M);
1420 F->setName(Name +
".cfi");
1421 maybeReplaceComdat(
F, Name);
1423 F->getAddressSpace(), Name, &M);
1431 for (
auto &U :
F->uses()) {
1433 std::string AliasName =
A->getName().str() +
".cfi";
1436 F->getAddressSpace(),
"", &M);
1438 A->replaceAllUsesWith(AliasDecl);
1439 A->setName(AliasName);
1445 if (
F->hasExternalWeakLinkage())
1452 F->setVisibility(Visibility);
1461 OffsetsByTypeID[TypeId];
1462 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1464 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1465 if (It == OffsetsByTypeID.
end())
1471 It->second.push_back(MemOff +
Offset);
1481 dbgs() << MDS->getString() <<
": ";
1483 dbgs() <<
"<unnamed>: ";
1484 BitSets.
back().second.print(
dbgs());
1491void LowerTypeTestsModule::lowerTypeTestCalls(
1493 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1495 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1496 ByteArrayInfo *BAI =
nullptr;
1502 CombinedGlobalAddr, ConstantInt::get(
IntPtrTy, GlobalOffset)),
1507 : TypeTestResolution::
AllOnes;
1511 for (
auto Bit : BSI.
Bits)
1513 if (InlineBits == 0)
1516 TIL.InlineBits = ConstantInt::get(
1517 (BSI.
BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1520 ++NumByteArraysCreated;
1521 BAI = createByteArray(BSI);
1522 TIL.TheByteArray = BAI->ByteArray;
1523 TIL.BitMask = BAI->MaskGlobal;
1526 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1528 if (TIUI.IsExported) {
1529 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1531 BAI->MaskPtr = MaskPtr;
1535 for (CallInst *CI : TIUI.CallSites) {
1536 ++NumTypeTestCallsLowered;
1537 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1546void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1547 if (
Type->getNumOperands() != 2)
1554 "A member of a type identifier may not have an explicit section");
1577bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1578 if (HasBranchTargetEnforcement == -1) {
1582 M.getModuleFlag(
"branch-target-enforcement")))
1583 HasBranchTargetEnforcement = !BTE->isZero();
1585 HasBranchTargetEnforcement = 0;
1587 return HasBranchTargetEnforcement;
1591LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1592 switch (JumpTableArch) {
1596 M.getModuleFlag(
"cf-protection-branch")))
1597 if (MD->getZExtValue())
1603 if (CanUseThumbBWJumpTable) {
1604 if (hasBranchTargetEnforcement())
1611 if (hasBranchTargetEnforcement())
1630LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1632 raw_string_ostream AsmOS(Asm);
1637 M.getModuleFlag(
"cf-protection-branch")))
1638 Endbr = !MD->isZero();
1640 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1641 AsmOS <<
"jmp ${0:c}@plt\n";
1643 AsmOS <<
".balign 16, 0xcc\n";
1645 AsmOS <<
"int3\nint3\nint3\n";
1649 if (hasBranchTargetEnforcement())
1653 if (!CanUseThumbBWJumpTable) {
1669 AsmOS <<
"push {r0,r1}\n"
1671 <<
"0: add r0, r0, pc\n"
1672 <<
"str r0, [sp, #4]\n"
1675 <<
"1: .word $0 - (0b + 4)\n";
1677 if (hasBranchTargetEnforcement())
1679 AsmOS <<
"b.w $0\n";
1683 AsmOS <<
"tail $0@plt\n";
1685 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1686 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1688 AsmOS <<
"jump $0\n";
1701void LowerTypeTestsModule::buildBitSetsFromFunctions(
1707 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1709 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1714void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1715 GlobalVariable *GV) {
1716 if (WeakInitializerFn ==
nullptr) {
1721 M.getDataLayout().getProgramAddressSpace(),
1722 "__cfi_global_var_init", &M);
1728 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1741void LowerTypeTestsModule::findGlobalVariableUsersOf(
1742 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1743 for (
auto *U :
C->users()){
1747 findGlobalVariableUsersOf(C2, Out);
1752void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1753 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1756 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1757 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1758 for (
auto *GV : GlobalVarUsers) {
1759 if (GV == GlobalAnnotation)
1761 moveInitializerToModuleConstructor(GV);
1768 F->getAddressSpace(),
"", &M);
1769 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1776 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1779 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1791 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1799 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1804 if (Feature ==
"-thumb-mode")
1806 else if (Feature ==
"+thumb-mode")
1822 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1830 unsigned ArmCount = 0, ThumbCount = 0;
1831 for (
const auto GTM : Functions) {
1832 if (!GTM->isJumpTableCanonical()) {
1853 auto CUs = M.debug_compile_units();
1870 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1871 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1873 F->setSubprogram(UbsanSP);
1878 Locations.
reserve(Functions.size());
1880 for (
auto *Func : Functions) {
1881 StringRef FuncName = Func->getGlobal()->getName();
1884 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1885 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1890 Locations.push_back(EntryLoc);
1898void LowerTypeTestsModule::createJumpTable(
1907 F->setMetadata(LLVMContext::MD_elf_section_properties,
1910 ConstantAsMetadata::get(ConstantInt::get(
1911 Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
1912 ConstantAsMetadata::get(ConstantInt::get(
1913 Int64Ty, JumpTableEntrySize))}));
1922 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1928 bool areAllEntriesNounwind =
true;
1930 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1931 if (Loc.has_value())
1932 IRB.SetCurrentDebugLocation(*Loc);
1934 ->hasFnAttribute(Attribute::NoUnwind)) {
1935 areAllEntriesNounwind =
false;
1937 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1939 IRB.CreateUnreachable();
1942 F->setPreferredAlignment(
Align(JumpTableEntrySize));
1943 F->addFnAttr(Attribute::Naked);
1945 F->addFnAttr(
"target-features",
"-thumb-mode");
1947 if (hasBranchTargetEnforcement()) {
1950 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1952 F->addFnAttr(
"target-features",
"+thumb-mode");
1953 if (CanUseThumbBWJumpTable) {
1956 F->addFnAttr(
"target-cpu",
"cortex-a8");
1964 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1965 F->removeFnAttr(
"branch-target-enforcement");
1966 if (
F->hasFnAttribute(
"sign-return-address"))
1967 F->removeFnAttr(
"sign-return-address");
1972 F->addFnAttr(
"target-features",
"-c,-relax");
1978 F->addFnAttr(Attribute::NoCfCheck);
1981 if (areAllEntriesNounwind)
1982 F->addFnAttr(Attribute::NoUnwind);
1985 F->addFnAttr(Attribute::NoInline);
1990void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
2075 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
2076 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
2077 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
2078 GlobalLayout[Functions[
I]] =
I * EntrySize;
2084 M.getDataLayout().getProgramAddressSpace(),
2085 ".cfi.jumptable", &M);
2092 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
2096 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
2098 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
2101 F->getDataLayout(), JumpTableType, JumpTable,
2102 {ConstantInt::get(IntPtrTy, 0), ConstantInt::get(IntPtrTy, I)},
2105 const bool IsExported = Functions[
I]->isExported();
2106 if (!IsJumpTableCanonical) {
2110 F->getName() +
".cfi_jt",
2111 CombinedGlobalElemPtr, &M);
2120 if (IsJumpTableCanonical)
2128 if (!IsJumpTableCanonical) {
2129 if (
F->hasExternalWeakLinkage())
2130 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
2131 IsJumpTableCanonical);
2133 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
2135 assert(
F->getType()->getAddressSpace() == 0);
2137 GlobalAlias *FAlias =
2139 CombinedGlobalElemPtr, &M);
2144 F->setName(FAlias->
getName() +
".cfi");
2145 maybeReplaceComdat(
F, FAlias->
getName());
2147 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
2148 if (!
F->hasLocalLinkage())
2153 createJumpTable(JumpTableFn, Functions, JumpTableArch);
2162void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
2167 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
2169 for (GlobalTypeMember *GTM : Functions) {
2173 if (!
F->hasAddressTaken())
2179 ConstantInt::get(Int64Ty, IndirectIndex))));
2180 F->setMetadata(
"wasm.index", MD);
2183 GlobalLayout[GTM] = IndirectIndex++;
2192void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
2195 DenseMap<Metadata *, uint64_t> TypeIdIndices;
2196 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
2197 TypeIdIndices[TypeIds[
I]] =
I;
2201 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
2202 unsigned GlobalIndex = 0;
2203 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
2204 for (GlobalTypeMember *GTM : Globals) {
2205 for (MDNode *
Type : GTM->types()) {
2207 auto I = TypeIdIndices.
find(
Type->getOperand(1));
2208 if (
I != TypeIdIndices.
end())
2209 TypeMembers[
I->second].insert(GlobalIndex);
2211 GlobalIndices[GTM] = GlobalIndex;
2215 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
2216 TypeMembers.emplace_back();
2217 std::set<uint64_t> &TMSet = TypeMembers.back();
2218 for (GlobalTypeMember *
T : JT->targets())
2219 TMSet.insert(GlobalIndices[
T]);
2225 const std::set<uint64_t> &
O2) {
2226 return O1.size() <
O2.size();
2233 if (!IsGlobalSet && !FunctionSummaryHotness.
empty() &&
2236 std::vector<CfiFunctionHotness> GTMHotness;
2237 GTMHotness.reserve(Globals.size());
2238 for (GlobalTypeMember *GTM : Globals) {
2239 GTMHotness.push_back(
2256 return GTMHotness[
A] < GTMHotness[
B];
2264 for (
auto &&MemSet : TypeMembers)
2265 GLB.addFragment(MemSet);
2268 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
2269 auto OGTMI = OrderedGTMs.begin();
2273 "variables and functions");
2274 *OGTMI++ = Globals[
Offset];
2279 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
2281 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
2285LowerTypeTestsModule::LowerTypeTestsModule(
2287 const ModuleSummaryIndex *ImportSummary)
2288 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
2289 assert(!(ExportSummary && ImportSummary));
2290 Triple TargetTriple(M.getTargetTriple());
2291 Arch = TargetTriple.getArch();
2295 CanUseArmJumpTable =
true;
2299 if (
F.isDeclaration())
2302 if (
TTI.hasArmWideBranch(
false))
2303 CanUseArmJumpTable =
true;
2304 if (
TTI.hasArmWideBranch(
true))
2305 CanUseThumbBWJumpTable =
true;
2308 OS = TargetTriple.getOS();
2309 ObjectFormat = TargetTriple.getObjectFormat();
2313 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
2322 std::unique_ptr<ModuleSummaryIndex>
Summary;
2327 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
2333 if (ReadSummaryFile->getBuffer().starts_with(
"---")) {
2334 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2335 yaml::Input
In(ReadSummaryFile->getBuffer());
2348 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2352 LowerTypeTestsModule(
2361 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
2367 yaml::Output
Out(OS);
2376 return Usr && Usr->isCallee(&U);
2379void LowerTypeTestsModule::replaceCfiUses(
Function *Old,
Value *New,
2380 bool IsJumpTableCanonical) {
2381 SmallSetVector<Constant *, 4>
Constants;
2393 if (isFunctionAnnotation(
U.getUser()))
2411 for (
auto *
C : Constants)
2412 C->handleOperandChange(Old, New);
2415void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2420 bool ShouldDropAll) {
2426 Assume->eraseFromParent();
2435 return isa<PHINode>(U) || isa<SelectInst>(U);
2453 if (PublicTypeTestFunc)
2455 if (TypeTestFunc || PublicTypeTestFunc) {
2466bool LowerTypeTestsModule::lower() {
2480 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2481 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2482 !ExportSummary && !ImportSummary)
2485 if (ImportSummary) {
2490 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2492 "unexpected call to llvm.icall.branch.funnel during import phase");
2499 if (
A.hasLocalLinkage())
2504 if (
F->hasExternalLinkage()) {
2519 A.replaceAllUsesWith(
F);
2521 A.eraseFromParent();
2531 if (
F.hasLocalLinkage())
2540 ScopedSaveAliaseesAndUsed S(M);
2541 for (
auto *
F : Defs)
2542 importFunction(
F,
true);
2543 for (
auto *
F : Decls)
2544 importFunction(
F,
false);
2547 for (
auto &[
F, Name] : PromotedFuncs)
2556 using GlobalClassesTy = EquivalenceClasses<
2557 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2558 GlobalClassesTy GlobalClasses;
2570 std::vector<GlobalTypeMember *> RefGlobals;
2572 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2573 unsigned CurUniqueId = 0;
2576 struct ExportedFunctionInfo {
2580 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2581 if (ExportSummary) {
2582 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2583 if (CfiFunctionsMD) {
2585 DenseSet<GlobalValue::GUID> AddressTaken;
2586 for (
auto &
I : *ExportSummary)
2587 for (
auto &GVS :
I.second.getSummaryList())
2589 for (
const auto &
Ref : GVS->refs()) {
2591 for (
auto &RefGVS :
Ref.getSummaryList())
2593 AddressTaken.
insert(Alias->getAliaseeGUID());
2596 if (AddressTaken.
count(GUID))
2598 auto VI = ExportSummary->getValueInfo(GUID);
2601 for (
auto &
I :
VI.getSummaryList())
2603 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2607 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2608 assert(FuncMD->getNumOperands() >= 2);
2609 StringRef FunctionName =
2614 ->getUniqueInteger()
2619 ->getUniqueInteger()
2623 if (!ExportSummary->isGUIDLive(GUID))
2626 if (!CrossDsoCfi ||
Linkage != CfiFunctionLinkage::Definition)
2630 if (
auto VI = ExportSummary->getValueInfo(GUID))
2631 for (
const auto &GVS :
VI.getSummaryList())
2638 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2640 P.first->second.Linkage != CfiFunctionLinkage::Definition)
2641 P.first->second = {
Linkage, FuncMD};
2644 for (
const auto &
P : ExportedFunctions) {
2645 StringRef FunctionName =
P.first;
2646 CfiFunctionLinkage
Linkage =
P.second.Linkage;
2647 MDNode *FuncMD =
P.second.FuncMD;
2649 if (
F &&
F->hasLocalLinkage()) {
2656 F->setName(
F->getName() +
".1");
2662 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2663 GlobalVariable::ExternalLinkage,
2664 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2666 LLVMContext::MD_guid,
2667 MDTuple::get(
M.getContext(), {FuncMD->getOperand(2).get()}));
2668 if (ExportSummary) {
2672 ->getUniqueInteger()
2674 if (
auto VI = ExportSummary->getValueInfo(GUID))
2676 VI.isDSOLocal(ExportSummary->withDSOLocalPropagation()));
2684 if (
F->hasAvailableExternallyLinkage()) {
2686 auto *OrigGUIDMD =
F->getMetadata(LLVMContext::MD_guid);
2689 F->setComdat(
nullptr);
2691 F->setMetadata(LLVMContext::MD_guid, OrigGUIDMD);
2696 if (
Linkage == CfiFunctionLinkage::Definition &&
2697 F->hasExternalWeakLinkage())
2704 if (
F->isDeclaration()) {
2705 if (
Linkage == CfiFunctionLinkage::WeakDeclaration)
2708 F->eraseMetadata(LLVMContext::MD_type);
2710 F->addMetadata(LLVMContext::MD_type,
2715 ->getUniqueInteger()
2723 struct AliasToCreate {
2725 std::string TargetName;
2727 std::vector<AliasToCreate> AliasesToCreate;
2731 if (ExportSummary) {
2732 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2733 for (
auto *AliasMD : AliasesMD->operands()) {
2736 StringRef AliasName = MDS->getString();
2737 if (!ExportedFunctions.count(AliasName))
2739 auto *AliasF =
M.getFunction(AliasName);
2744 if (Aliases.
empty())
2747 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2748 auto *AliasF = Aliases[
I];
2749 ExportedFunctions.
erase(AliasF->getName());
2750 AliasesToCreate.push_back(
2751 {AliasF, std::string(Aliases[0]->
getName())});
2757 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2758 for (GlobalObject &GO :
M.global_objects()) {
2765 bool IsJumpTableCanonical =
false;
2766 bool IsExported =
false;
2769 if (
auto It = ExportedFunctions.find(
F->getName());
2770 It != ExportedFunctions.end()) {
2771 IsJumpTableCanonical |=
2772 It->second.Linkage == CfiFunctionLinkage::Definition;
2778 }
else if (!
F->hasAddressTaken()) {
2779 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2788 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2790 GlobalTypeMembers[&GO] = GTM;
2791 for (MDNode *
Type : Types) {
2792 verifyTypeMDNode(&GO,
Type);
2793 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2794 Info.UniqueId = ++CurUniqueId;
2795 Info.RefGlobals.push_back(GTM);
2799 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2804 auto Ins = TypeIdUsers.
insert({TypeId, {}});
2807 auto &GCI = GlobalClasses.insert(TypeId);
2808 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2811 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2812 CurSet = GlobalClasses.unionSets(
2813 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2816 return Ins.first->second;
2820 for (
const Use &U : TypeTestFunc->
uses()) {
2829 for (
const Use &CIU : CI->
uses()) {
2832 OnlyAssumeUses =
false;
2841 auto TypeId = TypeIdMDVal->getMetadata();
2842 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2846 if (ICallBranchFunnelFunc) {
2847 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2850 "llvm.icall.branch.funnel not supported on this target");
2854 std::vector<GlobalTypeMember *> Targets;
2858 GlobalClassesTy::member_iterator CurSet;
2859 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2865 "Expected branch funnel operand to be global value");
2867 auto It = GlobalTypeMembers.
find(
Base);
2868 if (It == GlobalTypeMembers.
end())
2870 "defined global value with type metadata");
2871 GlobalTypeMember *GTM = It->second;
2872 Targets.push_back(GTM);
2873 GlobalClassesTy::member_iterator NewSet =
2874 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2878 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2881 GlobalClasses.unionSets(
2882 CurSet, GlobalClasses.findLeader(
2883 GlobalClasses.insert(ICallBranchFunnel::create(
2884 Alloc, CI, Targets, ++CurUniqueId))));
2888 if (ExportSummary) {
2889 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2890 for (
auto &
P : TypeIdInfo) {
2893 TypeId->getString())]
2897 for (
auto &
P : *ExportSummary) {
2898 for (
auto &S :
P.second.getSummaryList()) {
2899 if (!ExportSummary->isGlobalValueLive(S.get()))
2904 AddTypeIdUse(MD).IsExported =
true;
2909 if (GlobalClasses.empty())
2913 ScopedSaveAliaseesAndUsed S(M);
2915 for (
const auto &
C : GlobalClasses) {
2919 ++NumTypeIdDisjointSets;
2921 std::vector<Metadata *> TypeIds;
2922 std::vector<GlobalTypeMember *> Globals;
2923 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2924 for (
auto M : GlobalClasses.members(*
C)) {
2937 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2942 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2943 return F1->UniqueId < F2->UniqueId;
2947 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2951 allocateByteArrays();
2953 for (
auto A : AliasesToCreate) {
2954 auto *
Target =
M.getNamedValue(
A.TargetName);
2958 AliasGA->setVisibility(
A.Alias->getVisibility());
2959 AliasGA->setLinkage(
A.Alias->getLinkage());
2960 AliasGA->setDSOLocal(
A.Alias->isDSOLocal());
2961 AliasGA->takeName(
A.Alias);
2962 A.Alias->replaceAllUsesWith(AliasGA);
2963 A.Alias->eraseFromParent();
2967 if (ExportSummary) {
2968 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2969 for (
auto *Symver : SymversMD->operands()) {
2970 assert(Symver->getNumOperands() >= 2);
2973 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2975 if (!ExportedFunctions.count(SymbolName))
2978 M.appendModuleInlineAsm(
2979 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2991 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2993 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
3001 static_cast<PassInfoMixin<DropTypeTestsPass> *
>(
this)->
printPipeline(
3002 OS, MapClassName2PassName);
3005 case DropTestKind::Assume:
3008 case DropTestKind::All:
3041 for (
auto &GV : M.globals()) {
3048 auto MaySimplifyPtr = [&](
Value *Ptr) {
3050 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
3054 auto MaySimplifyInt = [&](
Value *
Op) {
3056 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
3058 return MaySimplifyPtr(PtrAsInt->getOperand(0));
3074 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
3078 if (U.getOperandNo() == 0 && CE &&
3079 CE->getOpcode() == Instruction::Sub &&
3080 MaySimplifyInt(CE->getOperand(1))) {
3086 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
3090 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 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 Constant * getPtrAdd(Constant *Ptr, Constant *Offset, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReduced=nullptr)
Create a getelementptr i8, ptr, offset constant expression.
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getInBoundsPtrAdd(Constant *Ptr, Constant *Offset)
Create a getelementptr inbounds i8, ptr, offset constant expression.
static 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.
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 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.
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.