84#include <system_error>
91#define DEBUG_TYPE "lowertypetests"
93STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
94STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
95STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
96STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
97STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
100 "lowertypetests-avoid-reuse",
101 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
105 "lowertypetests-summary-action",
106 cl::desc(
"What to do with the summary when running this pass"),
109 "Import typeid resolutions from summary and globals"),
111 "Export typeid resolutions to summary and globals")),
115 "lowertypetests-read-summary",
116 cl::desc(
"Read summary from given YAML file before running pass"),
120 "lowertypetests-write-summary",
121 cl::desc(
"Write summary to given YAML file after running pass"),
126 cl::desc(
"Simply drop type test sequences"),
128 "Do not drop any type tests"),
130 "Drop type test assume sequences"),
132 "Drop all type test sequences")),
204 std::vector<uint64_t> &Fragment =
Fragments.back();
207 for (
auto ObjIndex :
F) {
209 if (OldFragmentIndex == 0) {
212 Fragment.push_back(ObjIndex);
219 std::vector<uint64_t> &OldFragment =
Fragments[OldFragmentIndex];
242 unsigned ReqSize = AllocByteOffset + BitSize;
244 if (
Bytes.size() < ReqSize)
245 Bytes.resize(ReqSize);
248 AllocMask = 1 << Bit;
250 Bytes[AllocByteOffset +
B] |= AllocMask;
254 if (
F->isDeclarationForLinker())
257 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
258 if (!CI || !CI->isZero())
260 return F->hasFnAttribute(
"cfi-canonical-jump-table");
265struct ByteArrayInfo {
266 std::set<uint64_t> Bits;
278class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
289 bool IsJumpTableCanonical;
297 bool IsJumpTableCanonical,
bool IsExported,
299 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
300 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
302 GTM->NTypes = Types.size();
303 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
304 GTM->IsExported = IsExported;
309 GlobalObject *getGlobal()
const {
314 return IsJumpTableCanonical;
317 bool isExported()
const {
324struct ICallBranchFunnel final
325 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
329 auto *
Call =
static_cast<ICallBranchFunnel *
>(
330 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
331 alignof(ICallBranchFunnel)));
333 Call->UniqueId = UniqueId;
341 return getTrailingObjects(NTargets);
350struct ScopedSaveAliaseesAndUsed {
353 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
354 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
359 void collectAndEraseUsedFunctions(
Module &M,
360 SmallVectorImpl<GlobalValue *> &Vec,
368 GV->eraseFromParent();
370 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
371 return isa<Function>(GV);
380 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
393 collectAndEraseUsedFunctions(M, Used,
false);
394 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
396 for (
auto &GA :
M.aliases()) {
400 FunctionAliases.push_back({&GA,
F});
403 for (
auto &GI :
M.ifuncs())
405 ResolverIFuncs.push_back({&GI,
F});
408 ~ScopedSaveAliaseesAndUsed() {
412 for (
auto P : FunctionAliases)
413 P.first->setAliasee(
P.second);
415 for (
auto P : ResolverIFuncs) {
419 P.first->setResolver(
P.second);
424class LowerTypeTestsModule {
427 ModuleSummaryIndex *ExportSummary;
428 const ModuleSummaryIndex *ImportSummary;
440 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
443 int HasBranchTargetEnforcement = -1;
445 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
446 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
447 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
448 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
449 IntegerType *
Int32Ty = Type::getInt32Ty(
M.getContext());
450 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
451 IntegerType *IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
454 uint64_t IndirectIndex = 1;
459 struct TypeIdUserInfo {
460 std::vector<CallInst *> CallSites;
461 bool IsExported =
false;
463 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
469 struct TypeIdLowering {
494 std::vector<ByteArrayInfo> ByteArrayInfos;
496 Function *WeakInitializerFn =
nullptr;
498 GlobalVariable *GlobalAnnotation;
499 DenseSet<Value *> FunctionAnnotations;
501 bool shouldExportConstantsAsAbsoluteSymbols();
502 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
503 TypeIdLowering importTypeId(StringRef TypeId);
504 void importTypeTest(CallInst *CI);
507 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
508 void allocateByteArrays();
511 void lowerTypeTestCalls(
513 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
515 const TypeIdLowering &TIL);
521 bool hasBranchTargetEnforcement();
524 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
536 void replaceWeakDeclarationWithJumpTablePtr(Function *
F, Constant *JT,
537 bool IsJumpTableCanonical);
538 void moveInitializerToModuleConstructor(GlobalVariable *GV);
539 void findGlobalVariableUsersOf(Constant *
C,
540 SmallSetVector<GlobalVariable *, 8> &Out);
550 void replaceCfiUses(Function *Old,
Value *New,
bool IsJumpTableCanonical);
554 void replaceDirectCalls(
Value *Old,
Value *New);
556 bool isFunctionAnnotation(
Value *V)
const {
557 return FunctionAnnotations.
contains(V);
560 void maybeReplaceComdat(Function *
F, StringRef OriginalName);
564 ModuleSummaryIndex *ExportSummary,
565 const ModuleSummaryIndex *ImportSummary,
588 unsigned BitWidth = BitsType->getBitWidth();
590 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
592 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
593 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
594 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
595 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
598ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
602 auto ByteArrayGlobal =
new GlobalVariable(
604 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
607 ByteArrayInfos.emplace_back();
608 ByteArrayInfo *BAI = &ByteArrayInfos.back();
610 BAI->Bits = BSI.
Bits;
612 BAI->ByteArray = ByteArrayGlobal;
613 BAI->MaskGlobal = MaskGlobal;
617void LowerTypeTestsModule::allocateByteArrays() {
619 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
620 return BAI1.BitSize > BAI2.BitSize;
623 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
626 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
627 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
630 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
636 *BAI->MaskPtr =
Mask;
641 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
644 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
645 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
647 Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0),
648 ConstantInt::get(IntPtrTy, ByteArrayOffsets[
I])};
650 ByteArrayConst->
getType(), ByteArray, Idxs);
664 ByteArraySizeBytes = BAB.
Bytes.size();
670 const TypeIdLowering &TIL,
684 "bits_use", ByteArray, &M);
687 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
692 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
700 GV->getMetadata(LLVMContext::MD_type, Types);
702 if (
Type->getOperand(1) != TypeId)
715 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
716 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
724 if (
Op->getOpcode() == Instruction::BitCast)
727 if (
Op->getOpcode() == Instruction::Select)
737Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
738 const TypeIdLowering &TIL) {
746 const DataLayout &
DL =
M.getDataLayout();
754 Value *PtrAsInt =
B.CreatePtrToInt(
Ptr, IntPtrTy);
759 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
765 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
775 Value *BitOffset =
B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr,
776 {PtrOffset, PtrOffset, TIL.AlignLog2});
778 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
782 return OffsetInRange;
795 Br->getMetadata(LLVMContext::MD_prof));
799 for (
auto &Phi :
Else->phis())
800 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
803 return createBitSetTest(ThenB, TIL, BitOffset);
810 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
815 B.SetInsertPoint(CI);
816 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
817 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
818 P->addIncoming(Bit, ThenB.GetInsertBlock());
824void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
831 std::vector<Constant *> GlobalInits;
832 const DataLayout &
DL =
M.getDataLayout();
833 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
835 uint64_t CurOffset = 0;
836 uint64_t DesiredPadding = 0;
837 for (GlobalTypeMember *
G : Globals) {
840 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
841 MaxAlign = std::max(MaxAlign, Alignment);
842 uint64_t GVOffset =
alignTo(CurOffset + DesiredPadding, Alignment);
843 GlobalLayout[
G] = GVOffset;
845 uint64_t
Padding = GVOffset - CurOffset;
846 GlobalInits.push_back(
850 GlobalInits.push_back(GV->getInitializer());
851 uint64_t InitSize =
DL.getTypeAllocSize(GV->getValueType());
852 CurOffset = GVOffset + InitSize;
861 if (DesiredPadding > 32)
862 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
866 auto *CombinedGlobal =
867 new GlobalVariable(M, NewInit->
getType(),
true,
869 CombinedGlobal->setAlignment(MaxAlign);
872 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
877 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
884 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
886 GlobalAlias *GAlias =
888 "", CombinedGlobalElemPtr, &M);
896bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
909uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
910 const TypeIdLowering &TIL) {
911 TypeTestResolution &TTRes =
918 "__typeid_" + TypeId +
"_" + Name,
C, &M);
922 auto ExportConstant = [&](StringRef
Name, uint64_t &Storage,
Constant *
C) {
923 if (shouldExportConstantsAsAbsoluteSymbols())
930 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
935 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
936 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
946 ExportGlobal(
"byte_array", TIL.TheByteArray);
947 if (shouldExportConstantsAsAbsoluteSymbols())
948 ExportGlobal(
"bit_mask", TIL.BitMask);
954 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
959LowerTypeTestsModule::TypeIdLowering
960LowerTypeTestsModule::importTypeId(StringRef TypeId) {
964 const TypeTestResolution &TTRes = TidSummary->
TTRes;
969 auto ImportGlobal = [&](StringRef
Name) {
972 GlobalVariable *GV =
M.getOrInsertGlobal(
973 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
978 auto ImportConstant = [&](StringRef
Name, uint64_t
Const,
unsigned AbsWidth,
980 if (!shouldExportConstantsAsAbsoluteSymbols()) {
992 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
995 auto SetAbsRange = [&](uint64_t Min, uint64_t
Max) {
1002 SetAbsRange(~0ull, ~0ull);
1004 SetAbsRange(0, 1ull << AbsWidth);
1009 auto *GV = ImportGlobal(
"global_addr");
1022 TIL.OffsetedGlobal = GV;
1028 TIL.AlignLog2 = ImportConstant(
"align", TTRes.
AlignLog2, 8, IntPtrTy);
1034 TIL.TheByteArray = ImportGlobal(
"byte_array");
1035 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1039 TIL.InlineBits = ImportConstant(
1046void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1058 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1059 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1066void LowerTypeTestsModule::maybeReplaceComdat(Function *
F,
1067 StringRef OriginalName) {
1073 F->getComdat()->getName() == OriginalName) {
1074 Comdat *OldComdat =
F->getComdat();
1075 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1076 for (GlobalObject &GO :
M.global_objects()) {
1085void LowerTypeTestsModule::importFunction(Function *
F,
1087 assert(
F->getType()->getAddressSpace() == 0);
1090 std::string
Name = std::string(
F->getName());
1095 if (
F->isDSOLocal()) {
1098 F->getAddressSpace(),
1101 replaceDirectCalls(
F, RealF);
1111 F->getAddressSpace(), Name +
".cfi_jt", &M);
1114 F->setName(Name +
".cfi");
1115 maybeReplaceComdat(
F, Name);
1117 F->getAddressSpace(), Name, &M);
1124 for (
auto &U :
F->uses()) {
1126 std::string AliasName =
A->getName().str() +
".cfi";
1129 F->getAddressSpace(),
"", &M);
1131 A->replaceAllUsesWith(AliasDecl);
1132 A->setName(AliasName);
1137 if (
F->hasExternalWeakLinkage())
1144 F->setVisibility(Visibility);
1153 OffsetsByTypeID[TypeId];
1154 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1156 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1157 if (It == OffsetsByTypeID.
end())
1163 It->second.push_back(MemOff +
Offset);
1173 dbgs() << MDS->getString() <<
": ";
1175 dbgs() <<
"<unnamed>: ";
1176 BitSets.
back().second.print(
dbgs());
1183void LowerTypeTestsModule::lowerTypeTestCalls(
1185 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1187 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1188 ByteArrayInfo *BAI =
nullptr;
1191 uint64_t GlobalOffset =
1194 Int8Ty, CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),
1195 TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.
AlignLog2);
1196 TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.
BitSize - 1);
1199 : TypeTestResolution::
AllOnes;
1202 uint64_t InlineBits = 0;
1203 for (
auto Bit : BSI.
Bits)
1204 InlineBits |= uint64_t(1) <<
Bit;
1205 if (InlineBits == 0)
1208 TIL.InlineBits = ConstantInt::get(
1212 ++NumByteArraysCreated;
1213 BAI = createByteArray(BSI);
1214 TIL.TheByteArray = BAI->ByteArray;
1215 TIL.BitMask = BAI->MaskGlobal;
1218 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1220 if (TIUI.IsExported) {
1221 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1223 BAI->MaskPtr = MaskPtr;
1227 for (CallInst *CI : TIUI.CallSites) {
1228 ++NumTypeTestCallsLowered;
1229 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1238void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1239 if (
Type->getNumOperands() != 2)
1246 "A member of a type identifier may not have an explicit section");
1268bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1269 if (HasBranchTargetEnforcement == -1) {
1273 M.getModuleFlag(
"branch-target-enforcement")))
1274 HasBranchTargetEnforcement = (BTE->getZExtValue() != 0);
1276 HasBranchTargetEnforcement = 0;
1278 return HasBranchTargetEnforcement;
1282LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1283 switch (JumpTableArch) {
1287 M.getModuleFlag(
"cf-protection-branch")))
1288 if (MD->getZExtValue())
1294 if (CanUseThumbBWJumpTable) {
1295 if (hasBranchTargetEnforcement())
1302 if (hasBranchTargetEnforcement())
1319LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1321 raw_string_ostream AsmOS(Asm);
1326 M.getModuleFlag(
"cf-protection-branch")))
1327 Endbr = !MD->isZero();
1329 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1330 AsmOS <<
"jmp ${0:c}@plt\n";
1332 AsmOS <<
".balign 16, 0xcc\n";
1334 AsmOS <<
"int3\nint3\nint3\n";
1338 if (hasBranchTargetEnforcement())
1342 if (!CanUseThumbBWJumpTable) {
1358 AsmOS <<
"push {r0,r1}\n"
1360 <<
"0: add r0, r0, pc\n"
1361 <<
"str r0, [sp, #4]\n"
1364 <<
"1: .word $0 - (0b + 4)\n";
1366 if (hasBranchTargetEnforcement())
1368 AsmOS <<
"b.w $0\n";
1372 AsmOS <<
"tail $0@plt\n";
1374 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1375 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1388void LowerTypeTestsModule::buildBitSetsFromFunctions(
1394 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1396 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1401void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1402 GlobalVariable *GV) {
1403 if (WeakInitializerFn ==
nullptr) {
1408 M.getDataLayout().getProgramAddressSpace(),
1409 "__cfi_global_var_init", &M);
1413 WeakInitializerFn->setSection(
1415 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1422 IRBuilder<> IRB(WeakInitializerFn->getEntryBlock().getTerminator());
1428void LowerTypeTestsModule::findGlobalVariableUsersOf(
1429 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1430 for (
auto *U :
C->users()){
1434 findGlobalVariableUsersOf(C2, Out);
1439void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1440 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1443 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1444 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1445 for (
auto *GV : GlobalVarUsers) {
1446 if (GV == GlobalAnnotation)
1448 moveInitializerToModuleConstructor(GV);
1456 F->getAddressSpace(),
"", &M);
1457 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1464 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1467 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1476 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1484 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1489 if (Feature ==
"-thumb-mode")
1491 else if (Feature ==
"+thumb-mode")
1507 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1515 unsigned ArmCount = 0, ThumbCount = 0;
1516 for (
const auto GTM : Functions) {
1517 if (!GTM->isJumpTableCanonical()) {
1531void LowerTypeTestsModule::createJumpTable(
1537 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1543 bool areAllEntriesNounwind =
true;
1544 for (GlobalTypeMember *GTM : Functions) {
1546 ->hasFnAttribute(llvm::Attribute::NoUnwind)) {
1547 areAllEntriesNounwind =
false;
1549 IRB.CreateCall(JumpTableAsm, GTM->getGlobal());
1551 IRB.CreateUnreachable();
1554 F->setAlignment(
Align(getJumpTableEntrySize(JumpTableArch)));
1560 F->addFnAttr(Attribute::Naked);
1562 F->addFnAttr(
"target-features",
"-thumb-mode");
1564 if (hasBranchTargetEnforcement()) {
1567 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1569 F->addFnAttr(
"target-features",
"+thumb-mode");
1570 if (CanUseThumbBWJumpTable) {
1573 F->addFnAttr(
"target-cpu",
"cortex-a8");
1581 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1582 F->removeFnAttr(
"branch-target-enforcement");
1583 if (
F->hasFnAttribute(
"sign-return-address"))
1584 F->removeFnAttr(
"sign-return-address");
1589 F->addFnAttr(
"target-features",
"-c,-relax");
1595 F->addFnAttr(Attribute::NoCfCheck);
1598 if (areAllEntriesNounwind)
1599 F->addFnAttr(Attribute::NoUnwind);
1602 F->addFnAttr(Attribute::NoInline);
1607void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1692 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1693 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1694 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1695 GlobalLayout[Functions[
I]] =
I * EntrySize;
1701 M.getDataLayout().getProgramAddressSpace(),
1702 ".cfi.jumptable", &M);
1709 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1713 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1715 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1718 JumpTableType, JumpTable,
1720 ConstantInt::get(IntPtrTy,
I)});
1722 const bool IsExported = Functions[
I]->isExported();
1723 if (!IsJumpTableCanonical) {
1727 F->getName() +
".cfi_jt",
1728 CombinedGlobalElemPtr, &M);
1736 if (IsJumpTableCanonical)
1742 if (!IsJumpTableCanonical) {
1743 if (
F->hasExternalWeakLinkage())
1744 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1745 IsJumpTableCanonical);
1747 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1749 assert(
F->getType()->getAddressSpace() == 0);
1751 GlobalAlias *FAlias =
1753 CombinedGlobalElemPtr, &M);
1757 F->setName(FAlias->
getName() +
".cfi");
1758 maybeReplaceComdat(
F, FAlias->
getName());
1760 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1761 if (!
F->hasLocalLinkage())
1766 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1775void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1780 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1782 for (GlobalTypeMember *GTM : Functions) {
1786 if (!
F->hasAddressTaken())
1792 ConstantInt::get(Int64Ty, IndirectIndex))));
1793 F->setMetadata(
"wasm.index", MD);
1796 GlobalLayout[GTM] = IndirectIndex++;
1805void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1808 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1809 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1810 TypeIdIndices[TypeIds[
I]] =
I;
1814 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1815 unsigned GlobalIndex = 0;
1816 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1817 for (GlobalTypeMember *GTM : Globals) {
1818 for (MDNode *
Type : GTM->types()) {
1820 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1821 if (
I != TypeIdIndices.
end())
1822 TypeMembers[
I->second].insert(GlobalIndex);
1824 GlobalIndices[GTM] = GlobalIndex;
1828 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1829 TypeMembers.emplace_back();
1830 std::set<uint64_t> &TMSet = TypeMembers.back();
1831 for (GlobalTypeMember *
T :
JT->targets())
1832 TMSet.insert(GlobalIndices[
T]);
1838 const std::set<uint64_t> &O2) {
1839 return O1.size() < O2.size();
1846 for (
auto &&MemSet : TypeMembers)
1847 GLB.addFragment(MemSet);
1852 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1853 auto OGTMI = OrderedGTMs.begin();
1854 for (
auto &&
F : GLB.Fragments) {
1858 "variables and functions");
1859 *OGTMI++ = Globals[
Offset];
1865 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1867 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1871LowerTypeTestsModule::LowerTypeTestsModule(
1873 const ModuleSummaryIndex *ImportSummary,
DropTestKind DropTypeTests)
1874 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary),
1877 assert(!(ExportSummary && ImportSummary));
1878 Triple TargetTriple(M.getTargetTriple());
1879 Arch = TargetTriple.getArch();
1881 CanUseArmJumpTable =
true;
1887 if (
F.isDeclaration())
1890 if (
TTI.hasArmWideBranch(
false))
1891 CanUseArmJumpTable =
true;
1892 if (
TTI.hasArmWideBranch(
true))
1893 CanUseThumbBWJumpTable =
true;
1896 OS = TargetTriple.getOS();
1897 ObjectFormat = TargetTriple.getObjectFormat();
1901 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
1902 if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {
1905 FunctionAnnotations.insert_range(CA->
operands());
1910 ModuleSummaryIndex
Summary(
false);
1915 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
1920 yaml::Input
In(ReadSummaryFile->getBuffer());
1926 LowerTypeTestsModule(
1934 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
1940 yaml::Output Out(OS);
1951 if (CB && CB->isCallee(&U))
1957void LowerTypeTestsModule::replaceCfiUses(Function *Old,
Value *New,
1958 bool IsJumpTableCanonical) {
1959 SmallSetVector<Constant *, 4>
Constants;
1971 if (isFunctionAnnotation(
U.getUser()))
1989 for (
auto *
C : Constants)
1990 C->handleOperandChange(Old, New);
1993void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
1998 bool ShouldDropAll) {
2004 Assume->eraseFromParent();
2013 return isa<PHINode>(U);
2021bool LowerTypeTestsModule::lower() {
2025 if (DropTypeTests != DropTestKind::None) {
2026 bool ShouldDropAll = DropTypeTests == DropTestKind::All;
2034 if (PublicTypeTestFunc)
2036 if (TypeTestFunc || PublicTypeTestFunc) {
2040 for (GlobalVariable &GV :
M.globals())
2057 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2058 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2059 !ExportSummary && !ImportSummary)
2062 if (ImportSummary) {
2067 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2069 "unexpected call to llvm.icall.branch.funnel during import phase");
2076 if (
F.hasLocalLinkage())
2085 ScopedSaveAliaseesAndUsed S(M);
2086 for (
auto *
F : Defs)
2087 importFunction(
F,
true);
2088 for (
auto *
F : Decls)
2089 importFunction(
F,
false);
2098 using GlobalClassesTy = EquivalenceClasses<
2099 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2100 GlobalClassesTy GlobalClasses;
2112 std::vector<GlobalTypeMember *> RefGlobals;
2114 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2115 unsigned CurUniqueId = 0;
2120 const bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
2122 struct ExportedFunctionInfo {
2126 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2127 if (ExportSummary) {
2128 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2129 if (CfiFunctionsMD) {
2131 DenseSet<GlobalValue::GUID> AddressTaken;
2132 for (
auto &
I : *ExportSummary)
2133 for (
auto &GVS :
I.second.SummaryList)
2135 for (
const auto &
Ref : GVS->refs()) {
2137 for (
auto &RefGVS :
Ref.getSummaryList())
2139 AddressTaken.
insert(Alias->getAliaseeGUID());
2142 if (AddressTaken.
count(GUID))
2144 auto VI = ExportSummary->getValueInfo(GUID);
2147 for (
auto &
I :
VI.getSummaryList())
2149 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2153 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2154 assert(FuncMD->getNumOperands() >= 2);
2155 StringRef FunctionName =
2160 ->getUniqueInteger()
2167 if (!ExportSummary->isGUIDLive(GUID))
2174 if (
auto VI = ExportSummary->getValueInfo(GUID))
2175 for (
const auto &GVS :
VI.getSummaryList())
2182 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2184 P.first->second = {
Linkage, FuncMD};
2187 for (
const auto &
P : ExportedFunctions) {
2188 StringRef FunctionName =
P.first;
2190 MDNode *FuncMD =
P.second.FuncMD;
2192 if (
F &&
F->hasLocalLinkage()) {
2199 F->setName(
F->getName() +
".1");
2205 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2206 GlobalVariable::ExternalLinkage,
2207 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2214 if (
F->hasAvailableExternallyLinkage()) {
2217 F->setComdat(
nullptr);
2230 if (
F->isDeclaration()) {
2234 F->eraseMetadata(LLVMContext::MD_type);
2236 F->addMetadata(LLVMContext::MD_type,
2243 struct AliasToCreate {
2245 std::string TargetName;
2247 std::vector<AliasToCreate> AliasesToCreate;
2251 if (ExportSummary) {
2252 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2253 for (
auto *AliasMD : AliasesMD->operands()) {
2255 for (
Metadata *MD : AliasMD->operands()) {
2259 StringRef AliasName = MDS->getString();
2260 if (!ExportedFunctions.count(AliasName))
2262 auto *AliasF =
M.getFunction(AliasName);
2267 if (Aliases.
empty())
2270 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2271 auto *AliasF = Aliases[
I];
2272 ExportedFunctions.
erase(AliasF->getName());
2273 AliasesToCreate.push_back(
2274 {AliasF, std::string(Aliases[0]->
getName())});
2280 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2281 for (GlobalObject &GO :
M.global_objects()) {
2288 bool IsJumpTableCanonical =
false;
2289 bool IsExported =
false;
2292 if (
auto It = ExportedFunctions.find(
F->getName());
2293 It != ExportedFunctions.end()) {
2300 }
else if (!
F->hasAddressTaken()) {
2301 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2306 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2308 GlobalTypeMembers[&GO] = GTM;
2309 for (MDNode *
Type : Types) {
2310 verifyTypeMDNode(&GO,
Type);
2311 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2312 Info.UniqueId = ++CurUniqueId;
2313 Info.RefGlobals.push_back(GTM);
2317 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2322 auto Ins = TypeIdUsers.insert({TypeId, {}});
2325 auto &GCI = GlobalClasses.insert(TypeId);
2326 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2329 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2330 CurSet = GlobalClasses.unionSets(
2331 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2334 return Ins.first->second;
2338 for (
const Use &U : TypeTestFunc->
uses()) {
2347 for (
const Use &CIU : CI->
uses()) {
2350 OnlyAssumeUses =
false;
2359 auto TypeId = TypeIdMDVal->getMetadata();
2360 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2364 if (ICallBranchFunnelFunc) {
2365 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2368 "llvm.icall.branch.funnel not supported on this target");
2372 std::vector<GlobalTypeMember *> Targets;
2376 GlobalClassesTy::member_iterator CurSet;
2377 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2383 "Expected branch funnel operand to be global value");
2385 GlobalTypeMember *GTM = GlobalTypeMembers[
Base];
2386 Targets.push_back(GTM);
2387 GlobalClassesTy::member_iterator NewSet =
2388 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2392 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2395 GlobalClasses.unionSets(
2396 CurSet, GlobalClasses.findLeader(
2397 GlobalClasses.insert(ICallBranchFunnel::create(
2398 Alloc, CI, Targets, ++CurUniqueId))));
2402 if (ExportSummary) {
2403 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2404 for (
auto &
P : TypeIdInfo) {
2407 TypeId->getString())]
2411 for (
auto &
P : *ExportSummary) {
2412 for (
auto &S :
P.second.SummaryList) {
2413 if (!ExportSummary->isGlobalValueLive(S.get()))
2418 AddTypeIdUse(MD).IsExported =
true;
2423 if (GlobalClasses.empty())
2427 ScopedSaveAliaseesAndUsed S(M);
2429 for (
const auto &
C : GlobalClasses) {
2433 ++NumTypeIdDisjointSets;
2435 std::vector<Metadata *> TypeIds;
2436 std::vector<GlobalTypeMember *> Globals;
2437 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2438 for (
auto M : GlobalClasses.members(*
C)) {
2451 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2456 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2457 return F1->UniqueId < F2->UniqueId;
2461 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2465 allocateByteArrays();
2467 for (
auto A : AliasesToCreate) {
2468 auto *
Target =
M.getNamedValue(
A.TargetName);
2472 AliasGA->setVisibility(
A.Alias->getVisibility());
2473 AliasGA->setLinkage(
A.Alias->getLinkage());
2474 AliasGA->takeName(
A.Alias);
2475 A.Alias->replaceAllUsesWith(AliasGA);
2476 A.Alias->eraseFromParent();
2480 if (ExportSummary) {
2481 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2482 for (
auto *Symver : SymversMD->operands()) {
2483 assert(Symver->getNumOperands() >= 2);
2486 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2488 if (!ExportedFunctions.count(SymbolName))
2491 M.appendModuleInlineAsm(
2492 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2504 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2507 LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, DropTypeTests)
2535 for (
auto &GV : M.globals()) {
2542 auto MaySimplifyPtr = [&](
Value *
Ptr) {
2544 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2548 auto MaySimplifyInt = [&](
Value *
Op) {
2550 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2552 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2568 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2572 if (U.getOperandNo() == 0 && CE &&
2573 CE->getOpcode() == Instruction::Sub &&
2574 MaySimplifyInt(CE->getOperand(1))) {
2580 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2584 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.
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)
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
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 ...
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.