83#include <system_error>
90#define DEBUG_TYPE "lowertypetests"
92STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
93STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
94STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
95STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
96STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
99 "lowertypetests-avoid-reuse",
100 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
104 "lowertypetests-summary-action",
105 cl::desc(
"What to do with the summary when running this pass"),
108 "Import typeid resolutions from summary and globals"),
110 "Export typeid resolutions to summary and globals")),
114 "lowertypetests-read-summary",
115 cl::desc(
"Read summary from given YAML file before running pass"),
119 "lowertypetests-write-summary",
120 cl::desc(
"Write summary to given YAML file after running pass"),
125 cl::desc(
"Simply drop type test sequences"),
127 "Do not drop any type tests"),
129 "Drop type test assume sequences"),
131 "Drop all type test sequences")),
203 std::vector<uint64_t> &Fragment =
Fragments.back();
206 for (
auto ObjIndex :
F) {
208 if (OldFragmentIndex == 0) {
211 Fragment.push_back(ObjIndex);
218 std::vector<uint64_t> &OldFragment =
Fragments[OldFragmentIndex];
241 unsigned ReqSize = AllocByteOffset + BitSize;
243 if (
Bytes.size() < ReqSize)
244 Bytes.resize(ReqSize);
247 AllocMask = 1 << Bit;
249 Bytes[AllocByteOffset +
B] |= AllocMask;
253 if (
F->isDeclarationForLinker())
256 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
257 if (!CI || !CI->isZero())
259 return F->hasFnAttribute(
"cfi-canonical-jump-table");
264struct ByteArrayInfo {
265 std::set<uint64_t> Bits;
277class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
288 bool IsJumpTableCanonical;
296 bool IsJumpTableCanonical,
bool IsExported,
298 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
299 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
301 GTM->NTypes = Types.size();
302 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
303 GTM->IsExported = IsExported;
308 GlobalObject *getGlobal()
const {
313 return IsJumpTableCanonical;
316 bool isExported()
const {
323struct ICallBranchFunnel final
324 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
328 auto *
Call =
static_cast<ICallBranchFunnel *
>(
329 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
330 alignof(ICallBranchFunnel)));
332 Call->UniqueId = UniqueId;
340 return getTrailingObjects(NTargets);
349struct ScopedSaveAliaseesAndUsed {
352 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
353 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
358 void collectAndEraseUsedFunctions(
Module &M,
359 SmallVectorImpl<GlobalValue *> &Vec,
367 GV->eraseFromParent();
369 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
370 return isa<Function>(GV);
379 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
392 collectAndEraseUsedFunctions(M, Used,
false);
393 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
395 for (
auto &GA :
M.aliases()) {
399 FunctionAliases.push_back({&GA,
F});
402 for (
auto &GI :
M.ifuncs())
404 ResolverIFuncs.push_back({&GI,
F});
407 ~ScopedSaveAliaseesAndUsed() {
411 for (
auto P : FunctionAliases)
412 P.first->setAliasee(
P.second);
414 for (
auto P : ResolverIFuncs) {
418 P.first->setResolver(
P.second);
423class LowerTypeTestsModule {
426 ModuleSummaryIndex *ExportSummary;
427 const ModuleSummaryIndex *ImportSummary;
439 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
442 int HasBranchTargetEnforcement = -1;
444 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
445 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
446 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
447 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
448 IntegerType *
Int32Ty = Type::getInt32Ty(
M.getContext());
449 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
450 IntegerType *IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
453 uint64_t IndirectIndex = 1;
458 struct TypeIdUserInfo {
459 std::vector<CallInst *> CallSites;
460 bool IsExported =
false;
462 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
468 struct TypeIdLowering {
493 std::vector<ByteArrayInfo> ByteArrayInfos;
495 Function *WeakInitializerFn =
nullptr;
497 GlobalVariable *GlobalAnnotation;
498 DenseSet<Value *> FunctionAnnotations;
500 bool shouldExportConstantsAsAbsoluteSymbols();
501 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
502 TypeIdLowering importTypeId(StringRef TypeId);
503 void importTypeTest(CallInst *CI);
506 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
507 void allocateByteArrays();
510 void lowerTypeTestCalls(
512 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
514 const TypeIdLowering &TIL);
520 bool hasBranchTargetEnforcement();
523 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
535 void replaceWeakDeclarationWithJumpTablePtr(Function *
F, Constant *JT,
536 bool IsJumpTableCanonical);
537 void moveInitializerToModuleConstructor(GlobalVariable *GV);
538 void findGlobalVariableUsersOf(Constant *
C,
539 SmallSetVector<GlobalVariable *, 8> &Out);
549 void replaceCfiUses(Function *Old,
Value *New,
bool IsJumpTableCanonical);
553 void replaceDirectCalls(
Value *Old,
Value *New);
555 bool isFunctionAnnotation(
Value *V)
const {
556 return FunctionAnnotations.
contains(V);
559 void maybeReplaceComdat(Function *
F, StringRef OriginalName);
563 ModuleSummaryIndex *ExportSummary,
564 const ModuleSummaryIndex *ImportSummary,
587 unsigned BitWidth = BitsType->getBitWidth();
589 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
591 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
592 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
593 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
594 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
597ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
601 auto ByteArrayGlobal =
new GlobalVariable(
603 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
606 ByteArrayInfos.emplace_back();
607 ByteArrayInfo *BAI = &ByteArrayInfos.back();
609 BAI->Bits = BSI.
Bits;
611 BAI->ByteArray = ByteArrayGlobal;
612 BAI->MaskGlobal = MaskGlobal;
616void LowerTypeTestsModule::allocateByteArrays() {
618 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
619 return BAI1.BitSize > BAI2.BitSize;
622 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
625 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
626 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
629 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
635 *BAI->MaskPtr =
Mask;
640 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
643 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
644 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
646 Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0),
647 ConstantInt::get(IntPtrTy, ByteArrayOffsets[
I])};
649 ByteArrayConst->
getType(), ByteArray, Idxs);
663 ByteArraySizeBytes = BAB.
Bytes.size();
669 const TypeIdLowering &TIL,
683 "bits_use", ByteArray, &M);
686 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
691 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
699 GV->getMetadata(LLVMContext::MD_type, Types);
701 if (
Type->getOperand(1) != TypeId)
714 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
715 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
723 if (
Op->getOpcode() == Instruction::BitCast)
726 if (
Op->getOpcode() == Instruction::Select)
736Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
737 const TypeIdLowering &TIL) {
745 const DataLayout &
DL =
M.getDataLayout();
753 Value *PtrAsInt =
B.CreatePtrToInt(Ptr, IntPtrTy);
758 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
764 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
774 Value *BitOffset =
B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr,
775 {PtrOffset, PtrOffset, TIL.AlignLog2});
777 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
781 return OffsetInRange;
794 Br->getMetadata(LLVMContext::MD_prof));
798 for (
auto &Phi :
Else->phis())
799 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
802 return createBitSetTest(ThenB, TIL, BitOffset);
809 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
814 B.SetInsertPoint(CI);
815 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
816 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
817 P->addIncoming(Bit, ThenB.GetInsertBlock());
823void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
830 std::vector<Constant *> GlobalInits;
831 const DataLayout &
DL =
M.getDataLayout();
832 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
834 uint64_t CurOffset = 0;
835 uint64_t DesiredPadding = 0;
836 for (GlobalTypeMember *
G : Globals) {
839 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
840 MaxAlign = std::max(MaxAlign, Alignment);
841 uint64_t GVOffset =
alignTo(CurOffset + DesiredPadding, Alignment);
842 GlobalLayout[
G] = GVOffset;
844 uint64_t
Padding = GVOffset - CurOffset;
845 GlobalInits.push_back(
849 GlobalInits.push_back(GV->getInitializer());
850 uint64_t InitSize =
DL.getTypeAllocSize(GV->getValueType());
851 CurOffset = GVOffset + InitSize;
860 if (DesiredPadding > 32)
861 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
865 auto *CombinedGlobal =
866 new GlobalVariable(M, NewInit->
getType(),
true,
868 CombinedGlobal->setAlignment(MaxAlign);
871 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
876 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
883 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
885 GlobalAlias *GAlias =
887 "", CombinedGlobalElemPtr, &M);
895bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
908uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
909 const TypeIdLowering &TIL) {
910 TypeTestResolution &TTRes =
917 "__typeid_" + TypeId +
"_" + Name,
C, &M);
921 auto ExportConstant = [&](StringRef
Name, uint64_t &Storage,
Constant *
C) {
922 if (shouldExportConstantsAsAbsoluteSymbols())
929 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
934 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
935 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
945 ExportGlobal(
"byte_array", TIL.TheByteArray);
946 if (shouldExportConstantsAsAbsoluteSymbols())
947 ExportGlobal(
"bit_mask", TIL.BitMask);
953 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
958LowerTypeTestsModule::TypeIdLowering
959LowerTypeTestsModule::importTypeId(StringRef TypeId) {
963 const TypeTestResolution &TTRes = TidSummary->
TTRes;
968 auto ImportGlobal = [&](StringRef
Name) {
971 GlobalVariable *GV =
M.getOrInsertGlobal(
972 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
977 auto ImportConstant = [&](StringRef
Name, uint64_t
Const,
unsigned AbsWidth,
979 if (!shouldExportConstantsAsAbsoluteSymbols()) {
991 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
994 auto SetAbsRange = [&](uint64_t Min, uint64_t
Max) {
1001 SetAbsRange(~0ull, ~0ull);
1003 SetAbsRange(0, 1ull << AbsWidth);
1008 auto *GV = ImportGlobal(
"global_addr");
1021 TIL.OffsetedGlobal = GV;
1027 TIL.AlignLog2 = ImportConstant(
"align", TTRes.
AlignLog2, 8, IntPtrTy);
1033 TIL.TheByteArray = ImportGlobal(
"byte_array");
1034 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1038 TIL.InlineBits = ImportConstant(
1045void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1057 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1058 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1065void LowerTypeTestsModule::maybeReplaceComdat(Function *
F,
1066 StringRef OriginalName) {
1072 F->getComdat()->getName() == OriginalName) {
1073 Comdat *OldComdat =
F->getComdat();
1074 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1075 for (GlobalObject &GO :
M.global_objects()) {
1084void LowerTypeTestsModule::importFunction(Function *
F,
1086 assert(
F->getType()->getAddressSpace() == 0);
1089 std::string
Name = std::string(
F->getName());
1094 if (
F->isDSOLocal()) {
1097 F->getAddressSpace(),
1100 replaceDirectCalls(
F, RealF);
1110 F->getAddressSpace(), Name +
".cfi_jt", &M);
1113 F->setName(Name +
".cfi");
1114 maybeReplaceComdat(
F, Name);
1116 F->getAddressSpace(), Name, &M);
1123 for (
auto &U :
F->uses()) {
1125 std::string AliasName =
A->getName().str() +
".cfi";
1128 F->getAddressSpace(),
"", &M);
1130 A->replaceAllUsesWith(AliasDecl);
1131 A->setName(AliasName);
1136 if (
F->hasExternalWeakLinkage())
1143 F->setVisibility(Visibility);
1152 OffsetsByTypeID[TypeId];
1153 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1155 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1156 if (It == OffsetsByTypeID.
end())
1162 It->second.push_back(MemOff +
Offset);
1172 dbgs() << MDS->getString() <<
": ";
1174 dbgs() <<
"<unnamed>: ";
1175 BitSets.
back().second.print(
dbgs());
1182void LowerTypeTestsModule::lowerTypeTestCalls(
1184 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1186 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1187 ByteArrayInfo *BAI =
nullptr;
1190 uint64_t GlobalOffset =
1193 Int8Ty, CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),
1194 TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.
AlignLog2);
1195 TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.
BitSize - 1);
1198 : TypeTestResolution::
AllOnes;
1201 uint64_t InlineBits = 0;
1202 for (
auto Bit : BSI.
Bits)
1203 InlineBits |= uint64_t(1) <<
Bit;
1204 if (InlineBits == 0)
1207 TIL.InlineBits = ConstantInt::get(
1211 ++NumByteArraysCreated;
1212 BAI = createByteArray(BSI);
1213 TIL.TheByteArray = BAI->ByteArray;
1214 TIL.BitMask = BAI->MaskGlobal;
1217 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1219 if (TIUI.IsExported) {
1220 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1222 BAI->MaskPtr = MaskPtr;
1226 for (CallInst *CI : TIUI.CallSites) {
1227 ++NumTypeTestCallsLowered;
1228 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1237void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1238 if (
Type->getNumOperands() != 2)
1245 "A member of a type identifier may not have an explicit section");
1267bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1268 if (HasBranchTargetEnforcement == -1) {
1272 M.getModuleFlag(
"branch-target-enforcement")))
1273 HasBranchTargetEnforcement = !BTE->isZero();
1275 HasBranchTargetEnforcement = 0;
1277 return HasBranchTargetEnforcement;
1281LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1282 switch (JumpTableArch) {
1286 M.getModuleFlag(
"cf-protection-branch")))
1287 if (MD->getZExtValue())
1293 if (CanUseThumbBWJumpTable) {
1294 if (hasBranchTargetEnforcement())
1301 if (hasBranchTargetEnforcement())
1318LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1320 raw_string_ostream AsmOS(Asm);
1325 M.getModuleFlag(
"cf-protection-branch")))
1326 Endbr = !MD->isZero();
1328 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1329 AsmOS <<
"jmp ${0:c}@plt\n";
1331 AsmOS <<
".balign 16, 0xcc\n";
1333 AsmOS <<
"int3\nint3\nint3\n";
1337 if (hasBranchTargetEnforcement())
1341 if (!CanUseThumbBWJumpTable) {
1357 AsmOS <<
"push {r0,r1}\n"
1359 <<
"0: add r0, r0, pc\n"
1360 <<
"str r0, [sp, #4]\n"
1363 <<
"1: .word $0 - (0b + 4)\n";
1365 if (hasBranchTargetEnforcement())
1367 AsmOS <<
"b.w $0\n";
1371 AsmOS <<
"tail $0@plt\n";
1373 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1374 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1387void LowerTypeTestsModule::buildBitSetsFromFunctions(
1393 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1395 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1400void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1401 GlobalVariable *GV) {
1402 if (WeakInitializerFn ==
nullptr) {
1407 M.getDataLayout().getProgramAddressSpace(),
1408 "__cfi_global_var_init", &M);
1412 WeakInitializerFn->setSection(
1414 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1421 IRBuilder<> IRB(WeakInitializerFn->getEntryBlock().getTerminator());
1427void LowerTypeTestsModule::findGlobalVariableUsersOf(
1428 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1429 for (
auto *U :
C->users()){
1433 findGlobalVariableUsersOf(C2, Out);
1438void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1439 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1442 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1443 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1444 for (
auto *GV : GlobalVarUsers) {
1445 if (GV == GlobalAnnotation)
1447 moveInitializerToModuleConstructor(GV);
1455 F->getAddressSpace(),
"", &M);
1456 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1463 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1466 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1478 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1486 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1491 if (Feature ==
"-thumb-mode")
1493 else if (Feature ==
"+thumb-mode")
1509 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1517 unsigned ArmCount = 0, ThumbCount = 0;
1518 for (
const auto GTM : Functions) {
1519 if (!GTM->isJumpTableCanonical()) {
1533void LowerTypeTestsModule::createJumpTable(
1539 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1545 bool areAllEntriesNounwind =
true;
1546 for (GlobalTypeMember *GTM : Functions) {
1548 ->hasFnAttribute(llvm::Attribute::NoUnwind)) {
1549 areAllEntriesNounwind =
false;
1551 IRB.CreateCall(JumpTableAsm, GTM->getGlobal());
1553 IRB.CreateUnreachable();
1556 F->setAlignment(
Align(getJumpTableEntrySize(JumpTableArch)));
1562 F->addFnAttr(Attribute::Naked);
1564 F->addFnAttr(
"target-features",
"-thumb-mode");
1566 if (hasBranchTargetEnforcement()) {
1569 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1571 F->addFnAttr(
"target-features",
"+thumb-mode");
1572 if (CanUseThumbBWJumpTable) {
1575 F->addFnAttr(
"target-cpu",
"cortex-a8");
1583 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1584 F->removeFnAttr(
"branch-target-enforcement");
1585 if (
F->hasFnAttribute(
"sign-return-address"))
1586 F->removeFnAttr(
"sign-return-address");
1591 F->addFnAttr(
"target-features",
"-c,-relax");
1597 F->addFnAttr(Attribute::NoCfCheck);
1600 if (areAllEntriesNounwind)
1601 F->addFnAttr(Attribute::NoUnwind);
1604 F->addFnAttr(Attribute::NoInline);
1609void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1694 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1695 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1696 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1697 GlobalLayout[Functions[
I]] =
I * EntrySize;
1703 M.getDataLayout().getProgramAddressSpace(),
1704 ".cfi.jumptable", &M);
1711 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1715 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1717 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1720 JumpTableType, JumpTable,
1722 ConstantInt::get(IntPtrTy,
I)});
1724 const bool IsExported = Functions[
I]->isExported();
1725 if (!IsJumpTableCanonical) {
1729 F->getName() +
".cfi_jt",
1730 CombinedGlobalElemPtr, &M);
1738 if (IsJumpTableCanonical)
1744 if (!IsJumpTableCanonical) {
1745 if (
F->hasExternalWeakLinkage())
1746 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1747 IsJumpTableCanonical);
1749 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1751 assert(
F->getType()->getAddressSpace() == 0);
1753 GlobalAlias *FAlias =
1755 CombinedGlobalElemPtr, &M);
1759 F->setName(FAlias->
getName() +
".cfi");
1760 maybeReplaceComdat(
F, FAlias->
getName());
1762 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1763 if (!
F->hasLocalLinkage())
1768 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1777void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1782 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1784 for (GlobalTypeMember *GTM : Functions) {
1788 if (!
F->hasAddressTaken())
1794 ConstantInt::get(Int64Ty, IndirectIndex))));
1795 F->setMetadata(
"wasm.index", MD);
1798 GlobalLayout[GTM] = IndirectIndex++;
1807void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1810 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1811 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1812 TypeIdIndices[TypeIds[
I]] =
I;
1816 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1817 unsigned GlobalIndex = 0;
1818 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1819 for (GlobalTypeMember *GTM : Globals) {
1820 for (MDNode *
Type : GTM->types()) {
1822 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1823 if (
I != TypeIdIndices.
end())
1824 TypeMembers[
I->second].insert(GlobalIndex);
1826 GlobalIndices[GTM] = GlobalIndex;
1830 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1831 TypeMembers.emplace_back();
1832 std::set<uint64_t> &TMSet = TypeMembers.back();
1833 for (GlobalTypeMember *
T :
JT->targets())
1834 TMSet.insert(GlobalIndices[
T]);
1840 const std::set<uint64_t> &O2) {
1841 return O1.size() < O2.size();
1848 for (
auto &&MemSet : TypeMembers)
1849 GLB.addFragment(MemSet);
1854 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1855 auto OGTMI = OrderedGTMs.begin();
1856 for (
auto &&
F : GLB.Fragments) {
1860 "variables and functions");
1861 *OGTMI++ = Globals[
Offset];
1867 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1869 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1873LowerTypeTestsModule::LowerTypeTestsModule(
1875 const ModuleSummaryIndex *ImportSummary,
DropTestKind DropTypeTests)
1876 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary),
1879 assert(!(ExportSummary && ImportSummary));
1880 Triple TargetTriple(M.getTargetTriple());
1881 Arch = TargetTriple.getArch();
1883 CanUseArmJumpTable =
true;
1889 if (
F.isDeclaration())
1892 if (
TTI.hasArmWideBranch(
false))
1893 CanUseArmJumpTable =
true;
1894 if (
TTI.hasArmWideBranch(
true))
1895 CanUseThumbBWJumpTable =
true;
1898 OS = TargetTriple.getOS();
1899 ObjectFormat = TargetTriple.getObjectFormat();
1903 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
1904 if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {
1907 FunctionAnnotations.insert_range(CA->
operands());
1912 ModuleSummaryIndex
Summary(
false);
1917 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
1922 yaml::Input
In(ReadSummaryFile->getBuffer());
1928 LowerTypeTestsModule(
1936 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
1942 yaml::Output Out(OS);
1953 if (CB && CB->isCallee(&U))
1959void LowerTypeTestsModule::replaceCfiUses(Function *Old,
Value *New,
1960 bool IsJumpTableCanonical) {
1961 SmallSetVector<Constant *, 4>
Constants;
1973 if (isFunctionAnnotation(
U.getUser()))
1991 for (
auto *
C : Constants)
1992 C->handleOperandChange(Old, New);
1995void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2000 bool ShouldDropAll) {
2006 Assume->eraseFromParent();
2015 return isa<PHINode>(U);
2023bool LowerTypeTestsModule::lower() {
2027 if (DropTypeTests != DropTestKind::None) {
2028 bool ShouldDropAll = DropTypeTests == DropTestKind::All;
2036 if (PublicTypeTestFunc)
2038 if (TypeTestFunc || PublicTypeTestFunc) {
2042 for (GlobalVariable &GV :
M.globals())
2059 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2060 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2061 !ExportSummary && !ImportSummary)
2064 if (ImportSummary) {
2069 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2071 "unexpected call to llvm.icall.branch.funnel during import phase");
2078 if (
F.hasLocalLinkage())
2087 ScopedSaveAliaseesAndUsed S(M);
2088 for (
auto *
F : Defs)
2089 importFunction(
F,
true);
2090 for (
auto *
F : Decls)
2091 importFunction(
F,
false);
2100 using GlobalClassesTy = EquivalenceClasses<
2101 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2102 GlobalClassesTy GlobalClasses;
2114 std::vector<GlobalTypeMember *> RefGlobals;
2116 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2117 unsigned CurUniqueId = 0;
2122 const bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
2124 struct ExportedFunctionInfo {
2128 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2129 if (ExportSummary) {
2130 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2131 if (CfiFunctionsMD) {
2133 DenseSet<GlobalValue::GUID> AddressTaken;
2134 for (
auto &
I : *ExportSummary)
2135 for (
auto &GVS :
I.second.getSummaryList())
2137 for (
const auto &
Ref : GVS->refs()) {
2139 for (
auto &RefGVS :
Ref.getSummaryList())
2141 AddressTaken.
insert(Alias->getAliaseeGUID());
2144 if (AddressTaken.
count(GUID))
2146 auto VI = ExportSummary->getValueInfo(GUID);
2149 for (
auto &
I :
VI.getSummaryList())
2151 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2155 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2156 assert(FuncMD->getNumOperands() >= 2);
2157 StringRef FunctionName =
2162 ->getUniqueInteger()
2169 if (!ExportSummary->isGUIDLive(GUID))
2176 if (
auto VI = ExportSummary->getValueInfo(GUID))
2177 for (
const auto &GVS :
VI.getSummaryList())
2184 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2186 P.first->second = {
Linkage, FuncMD};
2189 for (
const auto &
P : ExportedFunctions) {
2190 StringRef FunctionName =
P.first;
2192 MDNode *FuncMD =
P.second.FuncMD;
2194 if (
F &&
F->hasLocalLinkage()) {
2201 F->setName(
F->getName() +
".1");
2207 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2208 GlobalVariable::ExternalLinkage,
2209 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2216 if (
F->hasAvailableExternallyLinkage()) {
2219 F->setComdat(
nullptr);
2232 if (
F->isDeclaration()) {
2236 F->eraseMetadata(LLVMContext::MD_type);
2238 F->addMetadata(LLVMContext::MD_type,
2245 struct AliasToCreate {
2247 std::string TargetName;
2249 std::vector<AliasToCreate> AliasesToCreate;
2253 if (ExportSummary) {
2254 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2255 for (
auto *AliasMD : AliasesMD->operands()) {
2257 for (
Metadata *MD : AliasMD->operands()) {
2261 StringRef AliasName = MDS->getString();
2262 if (!ExportedFunctions.count(AliasName))
2264 auto *AliasF =
M.getFunction(AliasName);
2269 if (Aliases.
empty())
2272 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2273 auto *AliasF = Aliases[
I];
2274 ExportedFunctions.
erase(AliasF->getName());
2275 AliasesToCreate.push_back(
2276 {AliasF, std::string(Aliases[0]->
getName())});
2282 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2283 for (GlobalObject &GO :
M.global_objects()) {
2290 bool IsJumpTableCanonical =
false;
2291 bool IsExported =
false;
2294 if (
auto It = ExportedFunctions.find(
F->getName());
2295 It != ExportedFunctions.end()) {
2302 }
else if (!
F->hasAddressTaken()) {
2303 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2308 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2310 GlobalTypeMembers[&GO] = GTM;
2311 for (MDNode *
Type : Types) {
2312 verifyTypeMDNode(&GO,
Type);
2313 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2314 Info.UniqueId = ++CurUniqueId;
2315 Info.RefGlobals.push_back(GTM);
2319 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2324 auto Ins = TypeIdUsers.insert({TypeId, {}});
2327 auto &GCI = GlobalClasses.insert(TypeId);
2328 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2331 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2332 CurSet = GlobalClasses.unionSets(
2333 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2336 return Ins.first->second;
2340 for (
const Use &U : TypeTestFunc->
uses()) {
2349 for (
const Use &CIU : CI->
uses()) {
2352 OnlyAssumeUses =
false;
2361 auto TypeId = TypeIdMDVal->getMetadata();
2362 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2366 if (ICallBranchFunnelFunc) {
2367 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2370 "llvm.icall.branch.funnel not supported on this target");
2374 std::vector<GlobalTypeMember *> Targets;
2378 GlobalClassesTy::member_iterator CurSet;
2379 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2385 "Expected branch funnel operand to be global value");
2387 GlobalTypeMember *GTM = GlobalTypeMembers[
Base];
2388 Targets.push_back(GTM);
2389 GlobalClassesTy::member_iterator NewSet =
2390 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2394 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2397 GlobalClasses.unionSets(
2398 CurSet, GlobalClasses.findLeader(
2399 GlobalClasses.insert(ICallBranchFunnel::create(
2400 Alloc, CI, Targets, ++CurUniqueId))));
2404 if (ExportSummary) {
2405 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2406 for (
auto &
P : TypeIdInfo) {
2409 TypeId->getString())]
2413 for (
auto &
P : *ExportSummary) {
2414 for (
auto &S :
P.second.getSummaryList()) {
2415 if (!ExportSummary->isGlobalValueLive(S.get()))
2420 AddTypeIdUse(MD).IsExported =
true;
2425 if (GlobalClasses.empty())
2429 ScopedSaveAliaseesAndUsed S(M);
2431 for (
const auto &
C : GlobalClasses) {
2435 ++NumTypeIdDisjointSets;
2437 std::vector<Metadata *> TypeIds;
2438 std::vector<GlobalTypeMember *> Globals;
2439 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2440 for (
auto M : GlobalClasses.members(*
C)) {
2453 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2458 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2459 return F1->UniqueId < F2->UniqueId;
2463 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2467 allocateByteArrays();
2469 for (
auto A : AliasesToCreate) {
2470 auto *
Target =
M.getNamedValue(
A.TargetName);
2474 AliasGA->setVisibility(
A.Alias->getVisibility());
2475 AliasGA->setLinkage(
A.Alias->getLinkage());
2476 AliasGA->takeName(
A.Alias);
2477 A.Alias->replaceAllUsesWith(AliasGA);
2478 A.Alias->eraseFromParent();
2482 if (ExportSummary) {
2483 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2484 for (
auto *Symver : SymversMD->operands()) {
2485 assert(Symver->getNumOperands() >= 2);
2488 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2490 if (!ExportedFunctions.count(SymbolName))
2493 M.appendModuleInlineAsm(
2494 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2506 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2509 LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, DropTypeTests)
2537 for (
auto &GV : M.globals()) {
2544 auto MaySimplifyPtr = [&](
Value *Ptr) {
2546 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2550 auto MaySimplifyInt = [&](
Value *
Op) {
2552 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2554 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2570 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2574 if (U.getOperandNo() == 0 && CE &&
2575 CE->getOpcode() == Instruction::Sub &&
2576 MaySimplifyInt(CE->getOperand(1))) {
2582 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2586 if (U.getOperandNo() == 1 && CI &&
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Prepare AGPR Alloc
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
static const unsigned kARMJumpTableEntrySize
static const unsigned kLOONGARCH64JumpTableEntrySize
static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)
static const unsigned kX86IBTJumpTableEntrySize
static cl::opt< std::string > ClReadSummary("lowertypetests-read-summary", cl::desc("Read summary from given YAML file before running pass"), cl::Hidden)
static const unsigned kRISCVJumpTableEntrySize
static auto buildBitSets(ArrayRef< Metadata * > TypeIds, const DenseMap< GlobalTypeMember *, uint64_t > &GlobalLayout)
static void dropTypeTests(Module &M, Function &TypeTestFunc, bool ShouldDropAll)
static Value * createMaskedBitTest(IRBuilder<> &B, Value *Bits, Value *BitOffset)
Build a test that bit BitOffset mod sizeof(Bits)*8 is set in Bits.
static bool isThumbFunction(Function *F, Triple::ArchType ModuleArch)
static const unsigned kX86JumpTableEntrySize
static cl::opt< bool > AvoidReuse("lowertypetests-avoid-reuse", cl::desc("Try to avoid reuse of byte array addresses using aliases"), cl::Hidden, cl::init(true))
static cl::opt< PassSummaryAction > ClSummaryAction("lowertypetests-summary-action", cl::desc("What to do with the summary when running this pass"), cl::values(clEnumValN(PassSummaryAction::None, "none", "Do nothing"), clEnumValN(PassSummaryAction::Import, "import", "Import typeid resolutions from summary and globals"), clEnumValN(PassSummaryAction::Export, "export", "Export typeid resolutions to summary and globals")), cl::Hidden)
static const unsigned kARMBTIJumpTableEntrySize
static cl::opt< 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 cl::opt< DropTestKind > ClDropTypeTests("lowertypetests-drop-type-tests", cl::desc("Simply drop type test sequences"), cl::values(clEnumValN(DropTestKind::None, "none", "Do not drop any type tests"), clEnumValN(DropTestKind::Assume, "assume", "Drop type test assume sequences"), clEnumValN(DropTestKind::All, "all", "Drop all type test sequences")), cl::Hidden, cl::init(DropTestKind::None))
Machine Check Debug Module
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
FunctionAnalysisManager FAM
This file defines the PointerUnion class, which is a discriminated union of pointer types.
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - 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.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
void emplace(Args &&...A)
size_t count(StringRef S) const
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 LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
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.
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.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
Analysis pass which computes a DominatorTree.
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)
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
LLVM_ABI void setComdat(Comdat *C)
const Comdat * getComdat() const
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
bool hasSection() const
Check if this global has a custom object file section.
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
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.
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
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 ...
MaybeAlign getAlign() const
Returns the alignment of the given variable.
void setConstant(bool Val)
LLVM_ABI void setCodeModel(CodeModel::Model CM)
Change the code model for this global.
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
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)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
TypeIdSummary & getOrInsertTypeIdSummary(StringRef TypeId)
Return an existing or new TypeIdSummary entry for TypeId.
const TypeIdSummary * getTypeIdSummary(StringRef TypeId) const
This returns either a pointer to the type id summary (if present in the summary map) or null (if not ...
CfiFunctionIndex & cfiFunctionDecls()
bool partiallySplitLTOUnits() const
CfiFunctionIndex & cfiFunctionDefs()
A Module instance is used to store all the information related to an LLVM module.
iterator_range< op_iterator > operands()
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Analysis pass which computes a PostDominatorTree.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
bool insert(const value_type &X)
Insert a new element into the SetVector.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - 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.
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
size - Get the string size.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetTransformInfo.
See the file comment for details on the usage of the TrailingObjects type.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI void 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.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements an extremely fast bulk output stream that can only output to a stream.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ 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)
DropTestKind
Specifies how to drop type tests.
@ Assume
Do not drop type tests (default).
LLVM_ABI bool isJumpTableCanonical(Function *F)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
SmallVector< unsigned char, 0 > ByteArray
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
FunctionAddr VTableAddr Value
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.
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
@ 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.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
LLVM_ABI bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)
Replace constant expressions users of the given constants with instructions.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Ref
The access may reference the value stored in memory.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
LLVM_ABI void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.used list.
CfiFunctionLinkage
The type of CFI jumptable needed for a function.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
LLVM_ABI GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
Kind
Specifies which kind of type check we should emit for this byte array.
@ Unknown
Unknown (analysis not performed, don't lower)
@ Single
Single element (last example in "Short Inline Bit Vectors")
@ Inline
Inlined bit vector ("Short Inline Bit Vectors")
@ Unsat
Unsatisfiable type (i.e. no global has this type metadata)
@ AllOnes
All-ones bit vector ("Eliminating Bit Vector Checks for All-Ones Bit Vectors")
@ ByteArray
Test a byte array (first example)
unsigned SizeM1BitWidth
Range of size-1 expressed as a bit width.
enum llvm::TypeTestResolution::Kind TheKind
LLVM_ABI BitSetInfo build()
SmallVector< uint64_t, 16 > Offsets
LLVM_ABI bool containsGlobalOffset(uint64_t Offset) const
LLVM_ABI void print(raw_ostream &OS) const
std::set< uint64_t > Bits
This class is used to build a byte array containing overlapping bit sets.
uint64_t BitAllocs[BitsPerByte]
The number of bytes allocated so far for each of the bits.
std::vector< uint8_t > Bytes
The byte array built so far.
LLVM_ABI void allocate(const std::set< uint64_t > &Bits, uint64_t BitSize, uint64_t &AllocByteOffset, uint8_t &AllocMask)
Allocate BitSize bits in the byte array where Bits contains the bits to set.
This class implements a layout algorithm for globals referenced by bit sets that tries to keep member...
std::vector< std::vector< uint64_t > > Fragments
The computed layout.
LLVM_ABI void addFragment(const std::set< uint64_t > &F)
Add F to the layout while trying to keep its indices contiguous.
std::vector< uint64_t > FragmentMap
Mapping from object index to fragment index.