85#include <system_error>
92#define DEBUG_TYPE "lowertypetests"
94STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
95STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
96STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
97STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
98STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
101 "lowertypetests-avoid-reuse",
102 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
106 "lowertypetests-summary-action",
107 cl::desc(
"What to do with the summary when running this pass"),
110 "Import typeid resolutions from summary and globals"),
112 "Export typeid resolutions to summary and globals")),
116 "lowertypetests-read-summary",
117 cl::desc(
"Read summary from given YAML file before running pass"),
121 "lowertypetests-write-summary",
122 cl::desc(
"Write summary to given YAML file after running pass"),
127 cl::desc(
"Simply drop type test sequences"),
129 "Do not drop any type tests"),
131 "Drop type test assume sequences"),
133 "Drop all type test sequences")),
205 std::vector<uint64_t> &Fragment =
Fragments.back();
208 for (
auto ObjIndex :
F) {
210 if (OldFragmentIndex == 0) {
213 Fragment.push_back(ObjIndex);
220 std::vector<uint64_t> &OldFragment =
Fragments[OldFragmentIndex];
243 unsigned ReqSize = AllocByteOffset + BitSize;
245 if (
Bytes.size() < ReqSize)
246 Bytes.resize(ReqSize);
249 AllocMask = 1 << Bit;
251 Bytes[AllocByteOffset +
B] |= AllocMask;
255 if (
F->isDeclarationForLinker())
258 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
259 if (!CI || !CI->isZero())
261 return F->hasFnAttribute(
"cfi-canonical-jump-table");
266struct ByteArrayInfo {
267 std::set<uint64_t> Bits;
279class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
290 bool IsJumpTableCanonical;
298 bool IsJumpTableCanonical,
bool IsExported,
300 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
301 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
303 GTM->NTypes = Types.size();
304 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
305 GTM->IsExported = IsExported;
310 GlobalObject *getGlobal()
const {
315 return IsJumpTableCanonical;
318 bool isExported()
const {
325struct ICallBranchFunnel final
326 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
330 auto *
Call =
static_cast<ICallBranchFunnel *
>(
331 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
332 alignof(ICallBranchFunnel)));
334 Call->UniqueId = UniqueId;
342 return getTrailingObjects(NTargets);
351struct ScopedSaveAliaseesAndUsed {
354 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
355 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
360 void collectAndEraseUsedFunctions(
Module &M,
361 SmallVectorImpl<GlobalValue *> &Vec,
369 GV->eraseFromParent();
371 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
372 return isa<Function>(GV);
381 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
394 collectAndEraseUsedFunctions(M, Used,
false);
395 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
397 for (
auto &GA :
M.aliases()) {
401 FunctionAliases.push_back({&GA,
F});
404 for (
auto &GI :
M.ifuncs())
406 ResolverIFuncs.push_back({&GI,
F});
409 ~ScopedSaveAliaseesAndUsed() {
413 for (
auto P : FunctionAliases)
414 P.first->setAliasee(
P.second);
416 for (
auto P : ResolverIFuncs) {
420 P.first->setResolver(
P.second);
425class LowerTypeTestsModule {
428 ModuleSummaryIndex *ExportSummary;
429 const ModuleSummaryIndex *ImportSummary;
441 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
444 int HasBranchTargetEnforcement = -1;
446 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
447 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
448 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
449 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
450 IntegerType *
Int32Ty = Type::getInt32Ty(
M.getContext());
451 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
452 IntegerType *IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
455 uint64_t IndirectIndex = 1;
460 struct TypeIdUserInfo {
461 std::vector<CallInst *> CallSites;
462 bool IsExported =
false;
464 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
470 struct TypeIdLowering {
495 std::vector<ByteArrayInfo> ByteArrayInfos;
497 Function *WeakInitializerFn =
nullptr;
499 GlobalVariable *GlobalAnnotation;
500 DenseSet<Value *> FunctionAnnotations;
502 bool shouldExportConstantsAsAbsoluteSymbols();
503 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
504 TypeIdLowering importTypeId(StringRef TypeId);
505 void importTypeTest(CallInst *CI);
508 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
509 void allocateByteArrays();
512 void lowerTypeTestCalls(
514 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
516 const TypeIdLowering &TIL);
522 bool hasBranchTargetEnforcement();
525 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
537 void replaceWeakDeclarationWithJumpTablePtr(Function *
F, Constant *JT,
538 bool IsJumpTableCanonical);
539 void moveInitializerToModuleConstructor(GlobalVariable *GV);
540 void findGlobalVariableUsersOf(Constant *
C,
541 SmallSetVector<GlobalVariable *, 8> &Out);
551 void replaceCfiUses(Function *Old,
Value *New,
bool IsJumpTableCanonical);
555 void replaceDirectCalls(
Value *Old,
Value *New);
557 bool isFunctionAnnotation(
Value *V)
const {
558 return FunctionAnnotations.
contains(V);
561 void maybeReplaceComdat(Function *
F, StringRef OriginalName);
565 ModuleSummaryIndex *ExportSummary,
566 const ModuleSummaryIndex *ImportSummary,
589 unsigned BitWidth = BitsType->getBitWidth();
591 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
593 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
594 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
595 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
596 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
599ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
603 auto ByteArrayGlobal =
new GlobalVariable(
605 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
608 ByteArrayInfos.emplace_back();
609 ByteArrayInfo *BAI = &ByteArrayInfos.back();
611 BAI->Bits = BSI.
Bits;
613 BAI->ByteArray = ByteArrayGlobal;
614 BAI->MaskGlobal = MaskGlobal;
618void LowerTypeTestsModule::allocateByteArrays() {
620 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
621 return BAI1.BitSize > BAI2.BitSize;
624 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
627 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
628 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
631 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
637 *BAI->MaskPtr =
Mask;
642 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
645 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
646 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
648 Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0),
649 ConstantInt::get(IntPtrTy, ByteArrayOffsets[
I])};
651 ByteArrayConst->
getType(), ByteArray, Idxs);
665 ByteArraySizeBytes = BAB.
Bytes.size();
671 const TypeIdLowering &TIL,
685 "bits_use", ByteArray, &M);
688 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
693 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
701 GV->getMetadata(LLVMContext::MD_type, Types);
703 if (
Type->getOperand(1) != TypeId)
716 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
717 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
725 if (
Op->getOpcode() == Instruction::BitCast)
728 if (
Op->getOpcode() == Instruction::Select)
738Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
739 const TypeIdLowering &TIL) {
747 const DataLayout &
DL =
M.getDataLayout();
755 Value *PtrAsInt =
B.CreatePtrToInt(Ptr, IntPtrTy);
760 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
766 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
776 Value *BitOffset =
B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr,
777 {PtrOffset, PtrOffset, TIL.AlignLog2});
779 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
783 return OffsetInRange;
796 Br->getMetadata(LLVMContext::MD_prof));
800 for (
auto &Phi :
Else->phis())
801 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
804 return createBitSetTest(ThenB, TIL, BitOffset);
807 MDBuilder MDB(
M.getContext());
809 MDB.createLikelyBranchWeights()));
813 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
818 B.SetInsertPoint(CI);
819 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
820 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
821 P->addIncoming(Bit, ThenB.GetInsertBlock());
827void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
834 std::vector<Constant *> GlobalInits;
835 const DataLayout &
DL =
M.getDataLayout();
836 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
838 uint64_t CurOffset = 0;
839 uint64_t DesiredPadding = 0;
840 for (GlobalTypeMember *
G : Globals) {
843 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
844 MaxAlign = std::max(MaxAlign, Alignment);
845 uint64_t GVOffset =
alignTo(CurOffset + DesiredPadding, Alignment);
846 GlobalLayout[
G] = GVOffset;
848 uint64_t
Padding = GVOffset - CurOffset;
849 GlobalInits.push_back(
853 GlobalInits.push_back(GV->getInitializer());
854 uint64_t InitSize =
DL.getTypeAllocSize(GV->getValueType());
855 CurOffset = GVOffset + InitSize;
864 if (DesiredPadding > 32)
865 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
869 auto *CombinedGlobal =
870 new GlobalVariable(M, NewInit->
getType(),
true,
872 CombinedGlobal->setAlignment(MaxAlign);
875 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
880 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
887 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
889 GlobalAlias *GAlias =
891 "", CombinedGlobalElemPtr, &M);
899bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
912uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
913 const TypeIdLowering &TIL) {
914 TypeTestResolution &TTRes =
921 "__typeid_" + TypeId +
"_" + Name,
C, &M);
925 auto ExportConstant = [&](StringRef
Name, uint64_t &Storage,
Constant *
C) {
926 if (shouldExportConstantsAsAbsoluteSymbols())
933 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
938 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
939 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
949 ExportGlobal(
"byte_array", TIL.TheByteArray);
950 if (shouldExportConstantsAsAbsoluteSymbols())
951 ExportGlobal(
"bit_mask", TIL.BitMask);
957 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
962LowerTypeTestsModule::TypeIdLowering
963LowerTypeTestsModule::importTypeId(StringRef TypeId) {
967 const TypeTestResolution &TTRes = TidSummary->
TTRes;
972 auto ImportGlobal = [&](StringRef
Name) {
975 GlobalVariable *GV =
M.getOrInsertGlobal(
976 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
981 auto ImportConstant = [&](StringRef
Name, uint64_t
Const,
unsigned AbsWidth,
983 if (!shouldExportConstantsAsAbsoluteSymbols()) {
995 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
998 auto SetAbsRange = [&](uint64_t Min, uint64_t
Max) {
1008 SetAbsRange(0, 1ull << AbsWidth);
1014 auto *GV = ImportGlobal(
"global_addr");
1027 TIL.OffsetedGlobal = GV;
1033 TIL.AlignLog2 = ImportConstant(
"align", TTRes.
AlignLog2, 8, IntPtrTy);
1039 TIL.TheByteArray = ImportGlobal(
"byte_array");
1040 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1044 TIL.InlineBits = ImportConstant(
1051void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1063 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1064 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1071void LowerTypeTestsModule::maybeReplaceComdat(Function *
F,
1072 StringRef OriginalName) {
1078 F->getComdat()->getName() == OriginalName) {
1079 Comdat *OldComdat =
F->getComdat();
1080 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1081 for (GlobalObject &GO :
M.global_objects()) {
1090void LowerTypeTestsModule::importFunction(Function *
F,
1092 assert(
F->getType()->getAddressSpace() == 0);
1095 std::string
Name = std::string(
F->getName());
1100 if (
F->isDSOLocal()) {
1103 F->getAddressSpace(),
1106 replaceDirectCalls(
F, RealF);
1116 F->getAddressSpace(), Name +
".cfi_jt", &M);
1119 F->setName(Name +
".cfi");
1120 maybeReplaceComdat(
F, Name);
1122 F->getAddressSpace(), Name, &M);
1129 for (
auto &U :
F->uses()) {
1131 std::string AliasName =
A->getName().str() +
".cfi";
1134 F->getAddressSpace(),
"", &M);
1136 A->replaceAllUsesWith(AliasDecl);
1137 A->setName(AliasName);
1142 if (
F->hasExternalWeakLinkage())
1149 F->setVisibility(Visibility);
1158 OffsetsByTypeID[TypeId];
1159 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1161 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1162 if (It == OffsetsByTypeID.
end())
1168 It->second.push_back(MemOff +
Offset);
1178 dbgs() << MDS->getString() <<
": ";
1180 dbgs() <<
"<unnamed>: ";
1181 BitSets.
back().second.print(
dbgs());
1188void LowerTypeTestsModule::lowerTypeTestCalls(
1190 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1192 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1193 ByteArrayInfo *BAI =
nullptr;
1196 uint64_t GlobalOffset =
1199 Int8Ty, CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),
1200 TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.
AlignLog2);
1201 TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.
BitSize - 1);
1204 : TypeTestResolution::
AllOnes;
1207 uint64_t InlineBits = 0;
1208 for (
auto Bit : BSI.
Bits)
1209 InlineBits |= uint64_t(1) <<
Bit;
1210 if (InlineBits == 0)
1213 TIL.InlineBits = ConstantInt::get(
1217 ++NumByteArraysCreated;
1218 BAI = createByteArray(BSI);
1219 TIL.TheByteArray = BAI->ByteArray;
1220 TIL.BitMask = BAI->MaskGlobal;
1223 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1225 if (TIUI.IsExported) {
1226 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1228 BAI->MaskPtr = MaskPtr;
1232 for (CallInst *CI : TIUI.CallSites) {
1233 ++NumTypeTestCallsLowered;
1234 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1243void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1244 if (
Type->getNumOperands() != 2)
1251 "A member of a type identifier may not have an explicit section");
1273bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1274 if (HasBranchTargetEnforcement == -1) {
1278 M.getModuleFlag(
"branch-target-enforcement")))
1279 HasBranchTargetEnforcement = !BTE->isZero();
1281 HasBranchTargetEnforcement = 0;
1283 return HasBranchTargetEnforcement;
1287LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1288 switch (JumpTableArch) {
1292 M.getModuleFlag(
"cf-protection-branch")))
1293 if (MD->getZExtValue())
1299 if (CanUseThumbBWJumpTable) {
1300 if (hasBranchTargetEnforcement())
1307 if (hasBranchTargetEnforcement())
1324LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1326 raw_string_ostream AsmOS(Asm);
1331 M.getModuleFlag(
"cf-protection-branch")))
1332 Endbr = !MD->isZero();
1334 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1335 AsmOS <<
"jmp ${0:c}@plt\n";
1337 AsmOS <<
".balign 16, 0xcc\n";
1339 AsmOS <<
"int3\nint3\nint3\n";
1343 if (hasBranchTargetEnforcement())
1347 if (!CanUseThumbBWJumpTable) {
1363 AsmOS <<
"push {r0,r1}\n"
1365 <<
"0: add r0, r0, pc\n"
1366 <<
"str r0, [sp, #4]\n"
1369 <<
"1: .word $0 - (0b + 4)\n";
1371 if (hasBranchTargetEnforcement())
1373 AsmOS <<
"b.w $0\n";
1377 AsmOS <<
"tail $0@plt\n";
1379 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1380 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1393void LowerTypeTestsModule::buildBitSetsFromFunctions(
1399 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1401 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1406void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1407 GlobalVariable *GV) {
1408 if (WeakInitializerFn ==
nullptr) {
1413 M.getDataLayout().getProgramAddressSpace(),
1414 "__cfi_global_var_init", &M);
1418 WeakInitializerFn->setSection(
1420 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1427 IRBuilder<> IRB(WeakInitializerFn->getEntryBlock().getTerminator());
1433void LowerTypeTestsModule::findGlobalVariableUsersOf(
1434 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1435 for (
auto *U :
C->users()){
1439 findGlobalVariableUsersOf(C2, Out);
1444void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1445 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1448 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1449 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1450 for (
auto *GV : GlobalVarUsers) {
1451 if (GV == GlobalAnnotation)
1453 moveInitializerToModuleConstructor(GV);
1461 F->getAddressSpace(),
"", &M);
1462 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1469 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1472 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1484 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1492 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1497 if (Feature ==
"-thumb-mode")
1499 else if (Feature ==
"+thumb-mode")
1515 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1523 unsigned ArmCount = 0, ThumbCount = 0;
1524 for (
const auto GTM : Functions) {
1525 if (!GTM->isJumpTableCanonical()) {
1539void LowerTypeTestsModule::createJumpTable(
1545 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1551 bool areAllEntriesNounwind =
true;
1552 for (GlobalTypeMember *GTM : Functions) {
1554 ->hasFnAttribute(llvm::Attribute::NoUnwind)) {
1555 areAllEntriesNounwind =
false;
1557 IRB.CreateCall(JumpTableAsm, GTM->getGlobal());
1559 IRB.CreateUnreachable();
1562 F->setAlignment(
Align(getJumpTableEntrySize(JumpTableArch)));
1563 F->addFnAttr(Attribute::Naked);
1565 F->addFnAttr(
"target-features",
"-thumb-mode");
1567 if (hasBranchTargetEnforcement()) {
1570 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1572 F->addFnAttr(
"target-features",
"+thumb-mode");
1573 if (CanUseThumbBWJumpTable) {
1576 F->addFnAttr(
"target-cpu",
"cortex-a8");
1584 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1585 F->removeFnAttr(
"branch-target-enforcement");
1586 if (
F->hasFnAttribute(
"sign-return-address"))
1587 F->removeFnAttr(
"sign-return-address");
1592 F->addFnAttr(
"target-features",
"-c,-relax");
1598 F->addFnAttr(Attribute::NoCfCheck);
1601 if (areAllEntriesNounwind)
1602 F->addFnAttr(Attribute::NoUnwind);
1605 F->addFnAttr(Attribute::NoInline);
1610void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1695 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1696 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1697 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1698 GlobalLayout[Functions[
I]] =
I * EntrySize;
1704 M.getDataLayout().getProgramAddressSpace(),
1705 ".cfi.jumptable", &M);
1712 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1716 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1718 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1721 JumpTableType, JumpTable,
1723 ConstantInt::get(IntPtrTy,
I)});
1725 const bool IsExported = Functions[
I]->isExported();
1726 if (!IsJumpTableCanonical) {
1730 F->getName() +
".cfi_jt",
1731 CombinedGlobalElemPtr, &M);
1739 if (IsJumpTableCanonical)
1745 if (!IsJumpTableCanonical) {
1746 if (
F->hasExternalWeakLinkage())
1747 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1748 IsJumpTableCanonical);
1750 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1752 assert(
F->getType()->getAddressSpace() == 0);
1754 GlobalAlias *FAlias =
1756 CombinedGlobalElemPtr, &M);
1760 F->setName(FAlias->
getName() +
".cfi");
1761 maybeReplaceComdat(
F, FAlias->
getName());
1763 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1764 if (!
F->hasLocalLinkage())
1769 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1778void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1783 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1785 for (GlobalTypeMember *GTM : Functions) {
1789 if (!
F->hasAddressTaken())
1795 ConstantInt::get(Int64Ty, IndirectIndex))));
1796 F->setMetadata(
"wasm.index", MD);
1799 GlobalLayout[GTM] = IndirectIndex++;
1808void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1811 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1812 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1813 TypeIdIndices[TypeIds[
I]] =
I;
1817 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1818 unsigned GlobalIndex = 0;
1819 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1820 for (GlobalTypeMember *GTM : Globals) {
1821 for (MDNode *
Type : GTM->types()) {
1823 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1824 if (
I != TypeIdIndices.
end())
1825 TypeMembers[
I->second].insert(GlobalIndex);
1827 GlobalIndices[GTM] = GlobalIndex;
1831 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1832 TypeMembers.emplace_back();
1833 std::set<uint64_t> &TMSet = TypeMembers.back();
1834 for (GlobalTypeMember *
T : JT->targets())
1835 TMSet.insert(GlobalIndices[
T]);
1841 const std::set<uint64_t> &O2) {
1842 return O1.size() < O2.size();
1849 for (
auto &&MemSet : TypeMembers)
1850 GLB.addFragment(MemSet);
1855 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1856 auto OGTMI = OrderedGTMs.begin();
1857 for (
auto &&
F : GLB.Fragments) {
1861 "variables and functions");
1862 *OGTMI++ = Globals[
Offset];
1868 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1870 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1874LowerTypeTestsModule::LowerTypeTestsModule(
1876 const ModuleSummaryIndex *ImportSummary,
DropTestKind DropTypeTests)
1877 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary),
1880 assert(!(ExportSummary && ImportSummary));
1881 Triple TargetTriple(M.getTargetTriple());
1882 Arch = TargetTriple.getArch();
1884 CanUseArmJumpTable =
true;
1890 if (
F.isDeclaration())
1893 if (
TTI.hasArmWideBranch(
false))
1894 CanUseArmJumpTable =
true;
1895 if (
TTI.hasArmWideBranch(
true))
1896 CanUseThumbBWJumpTable =
true;
1899 OS = TargetTriple.getOS();
1900 ObjectFormat = TargetTriple.getObjectFormat();
1904 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
1905 if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {
1908 FunctionAnnotations.insert_range(CA->
operands());
1913 ModuleSummaryIndex
Summary(
false);
1918 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
1923 yaml::Input
In(ReadSummaryFile->getBuffer());
1929 LowerTypeTestsModule(
1937 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
1943 yaml::Output Out(OS);
1954 if (CB && CB->isCallee(&U))
1960void LowerTypeTestsModule::replaceCfiUses(Function *Old,
Value *New,
1961 bool IsJumpTableCanonical) {
1962 SmallSetVector<Constant *, 4>
Constants;
1974 if (isFunctionAnnotation(
U.getUser()))
1992 for (
auto *
C : Constants)
1993 C->handleOperandChange(Old, New);
1996void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2001 bool ShouldDropAll) {
2007 Assume->eraseFromParent();
2016 return isa<PHINode>(U);
2024bool LowerTypeTestsModule::lower() {
2028 if (DropTypeTests != DropTestKind::None) {
2029 bool ShouldDropAll = DropTypeTests == DropTestKind::All;
2037 if (PublicTypeTestFunc)
2039 if (TypeTestFunc || PublicTypeTestFunc) {
2043 for (GlobalVariable &GV :
M.globals())
2060 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2061 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2062 !ExportSummary && !ImportSummary)
2065 if (ImportSummary) {
2070 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2072 "unexpected call to llvm.icall.branch.funnel during import phase");
2079 if (
F.hasLocalLinkage())
2088 ScopedSaveAliaseesAndUsed S(M);
2089 for (
auto *
F : Defs)
2090 importFunction(
F,
true);
2091 for (
auto *
F : Decls)
2092 importFunction(
F,
false);
2101 using GlobalClassesTy = EquivalenceClasses<
2102 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2103 GlobalClassesTy GlobalClasses;
2115 std::vector<GlobalTypeMember *> RefGlobals;
2117 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2118 unsigned CurUniqueId = 0;
2123 const bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
2125 struct ExportedFunctionInfo {
2129 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2130 if (ExportSummary) {
2131 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2132 if (CfiFunctionsMD) {
2134 DenseSet<GlobalValue::GUID> AddressTaken;
2135 for (
auto &
I : *ExportSummary)
2136 for (
auto &GVS :
I.second.getSummaryList())
2138 for (
const auto &
Ref : GVS->refs()) {
2140 for (
auto &RefGVS :
Ref.getSummaryList())
2142 AddressTaken.
insert(Alias->getAliaseeGUID());
2145 if (AddressTaken.
count(GUID))
2147 auto VI = ExportSummary->getValueInfo(GUID);
2150 for (
auto &
I :
VI.getSummaryList())
2152 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2156 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2157 assert(FuncMD->getNumOperands() >= 2);
2158 StringRef FunctionName =
2163 ->getUniqueInteger()
2170 if (!ExportSummary->isGUIDLive(GUID))
2177 if (
auto VI = ExportSummary->getValueInfo(GUID))
2178 for (
const auto &GVS :
VI.getSummaryList())
2185 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2187 P.first->second = {
Linkage, FuncMD};
2190 for (
const auto &
P : ExportedFunctions) {
2191 StringRef FunctionName =
P.first;
2193 MDNode *FuncMD =
P.second.FuncMD;
2195 if (
F &&
F->hasLocalLinkage()) {
2202 F->setName(
F->getName() +
".1");
2208 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2209 GlobalVariable::ExternalLinkage,
2210 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2217 if (
F->hasAvailableExternallyLinkage()) {
2220 F->setComdat(
nullptr);
2233 if (
F->isDeclaration()) {
2237 F->eraseMetadata(LLVMContext::MD_type);
2239 F->addMetadata(LLVMContext::MD_type,
2246 struct AliasToCreate {
2248 std::string TargetName;
2250 std::vector<AliasToCreate> AliasesToCreate;
2254 if (ExportSummary) {
2255 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2256 for (
auto *AliasMD : AliasesMD->operands()) {
2258 for (
Metadata *MD : AliasMD->operands()) {
2262 StringRef AliasName = MDS->getString();
2263 if (!ExportedFunctions.count(AliasName))
2265 auto *AliasF =
M.getFunction(AliasName);
2270 if (Aliases.
empty())
2273 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2274 auto *AliasF = Aliases[
I];
2275 ExportedFunctions.
erase(AliasF->getName());
2276 AliasesToCreate.push_back(
2277 {AliasF, std::string(Aliases[0]->
getName())});
2283 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2284 for (GlobalObject &GO :
M.global_objects()) {
2291 bool IsJumpTableCanonical =
false;
2292 bool IsExported =
false;
2295 if (
auto It = ExportedFunctions.find(
F->getName());
2296 It != ExportedFunctions.end()) {
2303 }
else if (!
F->hasAddressTaken()) {
2304 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2309 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2311 GlobalTypeMembers[&GO] = GTM;
2312 for (MDNode *
Type : Types) {
2313 verifyTypeMDNode(&GO,
Type);
2314 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2315 Info.UniqueId = ++CurUniqueId;
2316 Info.RefGlobals.push_back(GTM);
2320 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2325 auto Ins = TypeIdUsers.insert({TypeId, {}});
2328 auto &GCI = GlobalClasses.insert(TypeId);
2329 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2332 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2333 CurSet = GlobalClasses.unionSets(
2334 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2337 return Ins.first->second;
2341 for (
const Use &U : TypeTestFunc->
uses()) {
2350 for (
const Use &CIU : CI->
uses()) {
2353 OnlyAssumeUses =
false;
2362 auto TypeId = TypeIdMDVal->getMetadata();
2363 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2367 if (ICallBranchFunnelFunc) {
2368 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2371 "llvm.icall.branch.funnel not supported on this target");
2375 std::vector<GlobalTypeMember *> Targets;
2379 GlobalClassesTy::member_iterator CurSet;
2380 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2386 "Expected branch funnel operand to be global value");
2388 GlobalTypeMember *GTM = GlobalTypeMembers[
Base];
2389 Targets.push_back(GTM);
2390 GlobalClassesTy::member_iterator NewSet =
2391 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2395 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2398 GlobalClasses.unionSets(
2399 CurSet, GlobalClasses.findLeader(
2400 GlobalClasses.insert(ICallBranchFunnel::create(
2401 Alloc, CI, Targets, ++CurUniqueId))));
2405 if (ExportSummary) {
2406 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2407 for (
auto &
P : TypeIdInfo) {
2410 TypeId->getString())]
2414 for (
auto &
P : *ExportSummary) {
2415 for (
auto &S :
P.second.getSummaryList()) {
2416 if (!ExportSummary->isGlobalValueLive(S.get()))
2421 AddTypeIdUse(MD).IsExported =
true;
2426 if (GlobalClasses.empty())
2430 ScopedSaveAliaseesAndUsed S(M);
2432 for (
const auto &
C : GlobalClasses) {
2436 ++NumTypeIdDisjointSets;
2438 std::vector<Metadata *> TypeIds;
2439 std::vector<GlobalTypeMember *> Globals;
2440 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2441 for (
auto M : GlobalClasses.members(*
C)) {
2454 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2459 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2460 return F1->UniqueId < F2->UniqueId;
2464 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2468 allocateByteArrays();
2470 for (
auto A : AliasesToCreate) {
2471 auto *
Target =
M.getNamedValue(
A.TargetName);
2475 AliasGA->setVisibility(
A.Alias->getVisibility());
2476 AliasGA->setLinkage(
A.Alias->getLinkage());
2477 AliasGA->takeName(
A.Alias);
2478 A.Alias->replaceAllUsesWith(AliasGA);
2479 A.Alias->eraseFromParent();
2483 if (ExportSummary) {
2484 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2485 for (
auto *Symver : SymversMD->operands()) {
2486 assert(Symver->getNumOperands() >= 2);
2489 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2491 if (!ExportedFunctions.count(SymbolName))
2494 M.appendModuleInlineAsm(
2495 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2507 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2510 LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary, DropTypeTests)
2538 for (
auto &GV : M.globals()) {
2545 auto MaySimplifyPtr = [&](
Value *Ptr) {
2547 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2551 auto MaySimplifyInt = [&](
Value *
Op) {
2553 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2555 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2571 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2575 if (U.getOperandNo() == 0 && CE &&
2576 CE->getOpcode() == Instruction::Sub &&
2577 MaySimplifyInt(CE->getOperand(1))) {
2583 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2587 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.
This file contains the declarations for profiling metadata utility functions.
static StringRef getName(Value *V)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This header defines support for implementing classes that have some trailing object (or arrays of obj...
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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.
uint64_t getBitMask() const
Return a bitmask with ones set for all of the bits that can be set by an unsigned version of this typ...
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.