89#include <system_error>
96#define DEBUG_TYPE "lowertypetests"
98STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
99STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
100STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
101STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
102STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
105 "lowertypetests-avoid-reuse",
106 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
110 "lowertypetests-summary-action",
111 cl::desc(
"What to do with the summary when running this pass"),
114 "Import typeid resolutions from summary and globals"),
116 "Export typeid resolutions to summary and globals")),
121 cl::desc(
"Read summary from given textual assembly or YAML "
122 "file before running pass"),
126 "lowertypetests-write-summary",
127 cl::desc(
"Write summary to given YAML file after running pass"),
133 cl::desc(
"Enable debug info generation for jump tables"));
159 for (uint64_t
B :
Bits)
202 assert(Fragments.front().empty() &&
"Cannot add fragments after build()");
205 Fragments.emplace_back();
206 std::vector<uint64_t> &Fragment = Fragments.back();
207 uint64_t FragmentIndex = Fragments.size() - 1;
209 std::vector<std::vector<uint64_t>> SubFragments;
210 for (
auto ObjIndex :
F) {
211 uint64_t OldFragmentIndex = FragmentMap[ObjIndex];
212 if (OldFragmentIndex == 0) {
215 SubFragments.push_back({ObjIndex});
216 }
else if (!Fragments[OldFragmentIndex].empty()) {
222 SubFragments.push_back(std::move(Fragments[OldFragmentIndex]));
228 const std::vector<uint64_t> &
B) {
229 return Less(
A.back(),
B.back());
233 for (
auto &SF : SubFragments)
237 for (uint64_t ObjIndex : Fragment)
238 FragmentMap[ObjIndex] = FragmentIndex;
247 [](
const std::vector<uint64_t> &
F) {
return F.empty(); });
249 const std::vector<uint64_t> &FB) {
250 return Less(FA.back(), FB.back());
254 std::vector<uint64_t> Layout;
255 Layout.reserve(FragmentMap.size());
256 for (
auto &&
F : Fragments)
259 Fragments.push_back(std::move(Layout));
260 return Fragments.front();
264 uint64_t BitSize, uint64_t &AllocByteOffset,
275 unsigned ReqSize = AllocByteOffset + BitSize;
277 if (
Bytes.size() < ReqSize)
278 Bytes.resize(ReqSize);
281 AllocMask = 1 << Bit;
282 for (uint64_t
B : Bits)
283 Bytes[AllocByteOffset +
B] |= AllocMask;
287 if (
F->isDeclarationForLinker())
290 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
291 if (!CI || !CI->isZero())
293 return F->hasFnAttribute(
"cfi-canonical-jump-table");
298struct ByteArrayInfo {
299 std::set<uint64_t> Bits;
311class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
322 bool IsJumpTableCanonical;
330 bool IsJumpTableCanonical,
bool IsExported,
332 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
333 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
335 GTM->NTypes = Types.size();
336 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
337 GTM->IsExported = IsExported;
342 GlobalObject *getGlobal()
const {
347 return IsJumpTableCanonical;
350 bool isExported()
const {
357struct ICallBranchFunnel final
358 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
362 auto *
Call =
static_cast<ICallBranchFunnel *
>(
363 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
364 alignof(ICallBranchFunnel)));
366 Call->UniqueId = UniqueId;
374 return getTrailingObjects(NTargets);
383struct ScopedSaveAliaseesAndUsed {
386 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
387 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
392 void collectAndEraseUsedFunctions(
Module &M,
393 SmallVectorImpl<GlobalValue *> &Vec,
401 GV->eraseFromParent();
403 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
404 return isa<Function>(GV);
413 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
426 collectAndEraseUsedFunctions(M, Used,
false);
427 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
429 for (
auto &GA :
M.aliases()) {
433 FunctionAliases.push_back({&GA,
F});
436 for (
auto &GI :
M.ifuncs())
438 ResolverIFuncs.push_back({&GI,
F});
441 ~ScopedSaveAliaseesAndUsed() {
445 for (
auto P : FunctionAliases)
446 P.first->setAliasee(
P.second);
448 for (
auto P : ResolverIFuncs) {
452 P.first->setResolver(
P.second);
457class LowerTypeTestsModule {
460 ModuleSummaryIndex *ExportSummary;
461 const ModuleSummaryIndex *ImportSummary;
470 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
473 int HasBranchTargetEnforcement = -1;
475 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
476 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
477 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
478 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
479 IntegerType *Int32Ty = Type::getInt32Ty(
M.getContext());
480 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
481 IntegerType *
IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
489 struct TypeIdUserInfo {
490 std::vector<CallInst *> CallSites;
491 bool IsExported =
false;
493 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
499 struct TypeIdLowering {
524 std::vector<ByteArrayInfo> ByteArrayInfos;
526 Function *WeakInitializerFn =
nullptr;
528 GlobalVariable *GlobalAnnotation;
529 DenseSet<Value *> FunctionAnnotations;
533 bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
535 bool shouldExportConstantsAsAbsoluteSymbols();
536 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
537 TypeIdLowering importTypeId(StringRef TypeId);
538 void importTypeTest(CallInst *CI);
541 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
542 void allocateByteArrays();
545 void lowerTypeTestCalls(
547 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
549 const TypeIdLowering &TIL);
555 bool hasBranchTargetEnforcement();
558 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
570 void replaceWeakDeclarationWithJumpTablePtr(
Function *
F, Constant *JT,
571 bool IsJumpTableCanonical);
572 void moveInitializerToModuleConstructor(GlobalVariable *GV);
573 void findGlobalVariableUsersOf(Constant *
C,
574 SmallSetVector<GlobalVariable *, 8> &Out);
583 void replaceCfiUses(
Function *Old,
Value *New,
bool IsJumpTableCanonical);
587 void replaceDirectCalls(
Value *Old,
Value *New);
589 bool isFunctionAnnotation(
Value *V)
const {
590 return FunctionAnnotations.
contains(V);
593 void maybeReplaceComdat(
Function *
F, StringRef OriginalName);
597 ModuleSummaryIndex *ExportSummary,
598 const ModuleSummaryIndex *ImportSummary);
620 unsigned BitWidth = BitsType->getBitWidth();
622 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
624 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
625 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
626 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
627 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
630ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
634 auto ByteArrayGlobal =
new GlobalVariable(
636 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
639 ByteArrayInfos.emplace_back();
640 ByteArrayInfo *BAI = &ByteArrayInfos.back();
642 BAI->Bits = BSI.
Bits;
644 BAI->ByteArray = ByteArrayGlobal;
645 BAI->MaskGlobal = MaskGlobal;
649void LowerTypeTestsModule::allocateByteArrays() {
651 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
652 return BAI1.BitSize > BAI2.BitSize;
655 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
658 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
659 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
662 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
668 *BAI->MaskPtr =
Mask;
673 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
676 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
677 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
679 ByteArray, ConstantInt::get(
IntPtrTy, ByteArrayOffsets[
I]));
693 ByteArraySizeBytes = BAB.
Bytes.size();
699 const TypeIdLowering &TIL,
713 "bits_use", ByteArray, &M);
716 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
721 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
729 GV->getMetadata(LLVMContext::MD_type, Types);
731 if (
Type->getOperand(1) != TypeId)
744 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
745 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
753 if (
Op->getOpcode() == Instruction::BitCast)
756 if (
Op->getOpcode() == Instruction::Select)
766Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
767 const TypeIdLowering &TIL) {
775 const DataLayout &
DL =
M.getDataLayout();
788 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
794 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
805 {PtrOffset, PtrOffset, TIL.AlignLog2});
807 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
811 return OffsetInRange;
824 Br->getMetadata(LLVMContext::MD_prof));
828 for (
auto &Phi :
Else->phis())
829 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
832 return createBitSetTest(ThenB, TIL, BitOffset);
835 MDBuilder MDB(
M.getContext());
837 MDB.createLikelyBranchWeights()));
841 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
846 B.SetInsertPoint(CI);
847 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
848 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
849 P->addIncoming(Bit, ThenB.GetInsertBlock());
855void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
862 std::vector<Constant *> GlobalInits;
863 const DataLayout &
DL =
M.getDataLayout();
864 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
868 for (GlobalTypeMember *
G : Globals) {
871 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
872 MaxAlign = std::max(MaxAlign, Alignment);
874 GlobalLayout[
G] = GVOffset;
877 GlobalInits.push_back(
881 GlobalInits.push_back(GV->getInitializer());
883 CurOffset = GVOffset + InitSize;
892 if (DesiredPadding > 32)
893 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
897 auto *CombinedGlobal =
898 new GlobalVariable(M, NewInit->
getType(),
true,
900 CombinedGlobal->setAlignment(MaxAlign);
903 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
908 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
912 Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0),
913 ConstantInt::get(Int32Ty,
I * 2)};
915 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
917 GlobalAlias *GAlias =
919 "", CombinedGlobalElemPtr, &M);
927bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
940uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
941 const TypeIdLowering &TIL) {
942 TypeTestResolution &TTRes =
949 "__typeid_" + TypeId +
"_" + Name,
C, &M);
954 if (shouldExportConstantsAsAbsoluteSymbols())
961 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
966 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
967 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
977 ExportGlobal(
"byte_array", TIL.TheByteArray);
978 if (shouldExportConstantsAsAbsoluteSymbols())
979 ExportGlobal(
"bit_mask", TIL.BitMask);
985 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
990LowerTypeTestsModule::TypeIdLowering
991LowerTypeTestsModule::importTypeId(StringRef TypeId) {
995 const TypeTestResolution &TTRes = TidSummary->
TTRes;
1000 auto ImportGlobal = [&](StringRef
Name) {
1003 GlobalVariable *GV =
M.getOrInsertGlobal(
1004 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
1011 if (!shouldExportConstantsAsAbsoluteSymbols()) {
1023 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
1032 if (AbsWidth ==
IntPtrTy->getBitWidth()) {
1036 SetAbsRange(0, 1ull << AbsWidth);
1042 auto *GV = ImportGlobal(
"global_addr");
1055 TIL.OffsetedGlobal = GV;
1067 TIL.TheByteArray = ImportGlobal(
"byte_array");
1068 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1072 TIL.InlineBits = ImportConstant(
1079void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1091 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1092 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1099void LowerTypeTestsModule::maybeReplaceComdat(
Function *
F,
1100 StringRef OriginalName) {
1106 F->getComdat()->getName() == OriginalName) {
1107 Comdat *OldComdat =
F->getComdat();
1108 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1109 for (GlobalObject &GO :
M.global_objects()) {
1118void LowerTypeTestsModule::importFunction(
Function *
F,
1120 assert(
F->getType()->getAddressSpace() == 0);
1123 std::string
Name = std::string(
F->getName());
1128 if (!
F->isDSOLocal())
1130 if (
F->isDeclaration()) {
1135 F->getAddressSpace(),
1138 replaceDirectCalls(
F, RealF);
1155 F->getAddressSpace(), Name +
".cfi_jt", &M);
1158 F->setName(Name +
".cfi");
1159 maybeReplaceComdat(
F, Name);
1161 F->getAddressSpace(), Name, &M);
1169 for (
auto &U :
F->uses()) {
1171 std::string AliasName =
A->getName().str() +
".cfi";
1174 F->getAddressSpace(),
"", &M);
1176 A->replaceAllUsesWith(AliasDecl);
1177 A->setName(AliasName);
1183 if (
F->hasExternalWeakLinkage())
1190 F->setVisibility(Visibility);
1199 OffsetsByTypeID[TypeId];
1200 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1202 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1203 if (It == OffsetsByTypeID.
end())
1209 It->second.push_back(MemOff +
Offset);
1219 dbgs() << MDS->getString() <<
": ";
1221 dbgs() <<
"<unnamed>: ";
1222 BitSets.
back().second.print(
dbgs());
1229void LowerTypeTestsModule::lowerTypeTestCalls(
1231 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1233 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1234 ByteArrayInfo *BAI =
nullptr;
1240 CombinedGlobalAddr, ConstantInt::get(
IntPtrTy, GlobalOffset)),
1245 : TypeTestResolution::
AllOnes;
1249 for (
auto Bit : BSI.
Bits)
1251 if (InlineBits == 0)
1254 TIL.InlineBits = ConstantInt::get(
1255 (BSI.
BitSize <= 32) ? Int32Ty : Int64Ty, InlineBits);
1258 ++NumByteArraysCreated;
1259 BAI = createByteArray(BSI);
1260 TIL.TheByteArray = BAI->ByteArray;
1261 TIL.BitMask = BAI->MaskGlobal;
1264 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1266 if (TIUI.IsExported) {
1267 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1269 BAI->MaskPtr = MaskPtr;
1273 for (CallInst *CI : TIUI.CallSites) {
1274 ++NumTypeTestCallsLowered;
1275 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1284void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1285 if (
Type->getNumOperands() != 2)
1292 "A member of a type identifier may not have an explicit section");
1315bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1316 if (HasBranchTargetEnforcement == -1) {
1320 M.getModuleFlag(
"branch-target-enforcement")))
1321 HasBranchTargetEnforcement = !BTE->isZero();
1323 HasBranchTargetEnforcement = 0;
1325 return HasBranchTargetEnforcement;
1329LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1330 switch (JumpTableArch) {
1334 M.getModuleFlag(
"cf-protection-branch")))
1335 if (MD->getZExtValue())
1341 if (CanUseThumbBWJumpTable) {
1342 if (hasBranchTargetEnforcement())
1349 if (hasBranchTargetEnforcement())
1368LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1370 raw_string_ostream AsmOS(Asm);
1375 M.getModuleFlag(
"cf-protection-branch")))
1376 Endbr = !MD->isZero();
1378 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1379 AsmOS <<
"jmp ${0:c}@plt\n";
1381 AsmOS <<
".balign 16, 0xcc\n";
1383 AsmOS <<
"int3\nint3\nint3\n";
1387 if (hasBranchTargetEnforcement())
1391 if (!CanUseThumbBWJumpTable) {
1407 AsmOS <<
"push {r0,r1}\n"
1409 <<
"0: add r0, r0, pc\n"
1410 <<
"str r0, [sp, #4]\n"
1413 <<
"1: .word $0 - (0b + 4)\n";
1415 if (hasBranchTargetEnforcement())
1417 AsmOS <<
"b.w $0\n";
1421 AsmOS <<
"tail $0@plt\n";
1423 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1424 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1426 AsmOS <<
"jump $0\n";
1439void LowerTypeTestsModule::buildBitSetsFromFunctions(
1445 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1447 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1452void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1453 GlobalVariable *GV) {
1454 if (WeakInitializerFn ==
nullptr) {
1459 M.getDataLayout().getProgramAddressSpace(),
1460 "__cfi_global_var_init", &M);
1466 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1479void LowerTypeTestsModule::findGlobalVariableUsersOf(
1480 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1481 for (
auto *U :
C->users()){
1485 findGlobalVariableUsersOf(C2, Out);
1490void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1491 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1494 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1495 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1496 for (
auto *GV : GlobalVarUsers) {
1497 if (GV == GlobalAnnotation)
1499 moveInitializerToModuleConstructor(GV);
1506 F->getAddressSpace(),
"", &M);
1507 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1514 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1517 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1529 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1537 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1542 if (Feature ==
"-thumb-mode")
1544 else if (Feature ==
"+thumb-mode")
1560 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1568 unsigned ArmCount = 0, ThumbCount = 0;
1569 for (
const auto GTM : Functions) {
1570 if (!GTM->isJumpTableCanonical()) {
1591 auto CUs = M.debug_compile_units();
1608 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1609 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1611 F->setSubprogram(UbsanSP);
1616 Locations.
reserve(Functions.size());
1618 for (
auto *Func : Functions) {
1619 StringRef FuncName = Func->getGlobal()->getName();
1622 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1623 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1628 Locations.push_back(EntryLoc);
1636void LowerTypeTestsModule::createJumpTable(
1645 F->setMetadata(LLVMContext::MD_elf_section_properties,
1648 ConstantAsMetadata::get(ConstantInt::get(
1649 Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
1650 ConstantAsMetadata::get(ConstantInt::get(
1651 Int64Ty, JumpTableEntrySize))}));
1660 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1666 bool areAllEntriesNounwind =
true;
1668 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1669 if (Loc.has_value())
1670 IRB.SetCurrentDebugLocation(*Loc);
1672 ->hasFnAttribute(Attribute::NoUnwind)) {
1673 areAllEntriesNounwind =
false;
1675 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1677 IRB.CreateUnreachable();
1680 F->setPreferredAlignment(
Align(JumpTableEntrySize));
1681 F->addFnAttr(Attribute::Naked);
1683 F->addFnAttr(
"target-features",
"-thumb-mode");
1685 if (hasBranchTargetEnforcement()) {
1688 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1690 F->addFnAttr(
"target-features",
"+thumb-mode");
1691 if (CanUseThumbBWJumpTable) {
1694 F->addFnAttr(
"target-cpu",
"cortex-a8");
1702 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1703 F->removeFnAttr(
"branch-target-enforcement");
1704 if (
F->hasFnAttribute(
"sign-return-address"))
1705 F->removeFnAttr(
"sign-return-address");
1710 F->addFnAttr(
"target-features",
"-c,-relax");
1716 F->addFnAttr(Attribute::NoCfCheck);
1719 if (areAllEntriesNounwind)
1720 F->addFnAttr(Attribute::NoUnwind);
1723 F->addFnAttr(Attribute::NoInline);
1728void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1813 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1814 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1815 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1816 GlobalLayout[Functions[
I]] =
I * EntrySize;
1822 M.getDataLayout().getProgramAddressSpace(),
1823 ".cfi.jumptable", &M);
1830 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1834 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1836 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1839 JumpTableType, JumpTable,
1843 const bool IsExported = Functions[
I]->isExported();
1844 if (!IsJumpTableCanonical) {
1848 F->getName() +
".cfi_jt",
1849 CombinedGlobalElemPtr, &M);
1858 if (IsJumpTableCanonical)
1866 if (!IsJumpTableCanonical) {
1867 if (
F->hasExternalWeakLinkage())
1868 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1869 IsJumpTableCanonical);
1871 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1873 assert(
F->getType()->getAddressSpace() == 0);
1875 GlobalAlias *FAlias =
1877 CombinedGlobalElemPtr, &M);
1882 F->setName(FAlias->
getName() +
".cfi");
1883 maybeReplaceComdat(
F, FAlias->
getName());
1885 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1886 if (!
F->hasLocalLinkage())
1891 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1900void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1905 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1907 for (GlobalTypeMember *GTM : Functions) {
1911 if (!
F->hasAddressTaken())
1917 ConstantInt::get(Int64Ty, IndirectIndex))));
1918 F->setMetadata(
"wasm.index", MD);
1921 GlobalLayout[GTM] = IndirectIndex++;
1930void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1933 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1934 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1935 TypeIdIndices[TypeIds[
I]] =
I;
1939 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1940 unsigned GlobalIndex = 0;
1941 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1942 for (GlobalTypeMember *GTM : Globals) {
1943 for (MDNode *
Type : GTM->types()) {
1945 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1946 if (
I != TypeIdIndices.
end())
1947 TypeMembers[
I->second].insert(GlobalIndex);
1949 GlobalIndices[GTM] = GlobalIndex;
1953 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1954 TypeMembers.emplace_back();
1955 std::set<uint64_t> &TMSet = TypeMembers.back();
1956 for (GlobalTypeMember *
T : JT->targets())
1957 TMSet.insert(GlobalIndices[
T]);
1963 const std::set<uint64_t> &
O2) {
1964 return O1.size() <
O2.size();
1971 for (
auto &&MemSet : TypeMembers)
1972 GLB.addFragment(MemSet);
1977 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1978 auto OGTMI = OrderedGTMs.begin();
1982 "variables and functions");
1983 *OGTMI++ = Globals[
Offset];
1988 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1990 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1994LowerTypeTestsModule::LowerTypeTestsModule(
1996 const ModuleSummaryIndex *ImportSummary)
1997 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
1998 assert(!(ExportSummary && ImportSummary));
1999 Triple TargetTriple(M.getTargetTriple());
2000 Arch = TargetTriple.getArch();
2002 CanUseArmJumpTable =
true;
2008 if (
F.isDeclaration())
2011 if (
TTI.hasArmWideBranch(
false))
2012 CanUseArmJumpTable =
true;
2013 if (
TTI.hasArmWideBranch(
true))
2014 CanUseThumbBWJumpTable =
true;
2017 OS = TargetTriple.getOS();
2018 ObjectFormat = TargetTriple.getObjectFormat();
2022 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
2031 std::unique_ptr<ModuleSummaryIndex>
Summary;
2036 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
2042 if (ReadSummaryFile->getBuffer().starts_with(
"---")) {
2043 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2044 yaml::Input
In(ReadSummaryFile->getBuffer());
2057 Summary = std::make_unique<ModuleSummaryIndex>(
false);
2061 LowerTypeTestsModule(
2070 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
2076 yaml::Output Out(OS);
2085 return Usr && Usr->isCallee(&U);
2088void LowerTypeTestsModule::replaceCfiUses(
Function *Old,
Value *New,
2089 bool IsJumpTableCanonical) {
2090 SmallSetVector<Constant *, 4>
Constants;
2102 if (isFunctionAnnotation(
U.getUser()))
2120 for (
auto *
C : Constants)
2121 C->handleOperandChange(Old, New);
2124void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2129 bool ShouldDropAll) {
2135 Assume->eraseFromParent();
2144 return isa<PHINode>(U) || isa<SelectInst>(U);
2162 if (PublicTypeTestFunc)
2164 if (TypeTestFunc || PublicTypeTestFunc) {
2175bool LowerTypeTestsModule::lower() {
2189 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2190 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2191 !ExportSummary && !ImportSummary)
2194 if (ImportSummary) {
2199 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2201 "unexpected call to llvm.icall.branch.funnel during import phase");
2208 if (
F.hasLocalLinkage())
2217 ScopedSaveAliaseesAndUsed S(M);
2218 for (
auto *
F : Defs)
2219 importFunction(
F,
true);
2220 for (
auto *
F : Decls)
2221 importFunction(
F,
false);
2230 using GlobalClassesTy = EquivalenceClasses<
2231 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2232 GlobalClassesTy GlobalClasses;
2244 std::vector<GlobalTypeMember *> RefGlobals;
2246 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2247 unsigned CurUniqueId = 0;
2250 struct ExportedFunctionInfo {
2254 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2255 if (ExportSummary) {
2256 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2257 if (CfiFunctionsMD) {
2259 DenseSet<GlobalValue::GUID> AddressTaken;
2260 for (
auto &
I : *ExportSummary)
2261 for (
auto &GVS :
I.second.getSummaryList())
2263 for (
const auto &
Ref : GVS->refs()) {
2265 for (
auto &RefGVS :
Ref.getSummaryList())
2267 AddressTaken.
insert(Alias->getAliaseeGUID());
2270 if (AddressTaken.
count(GUID))
2272 auto VI = ExportSummary->getValueInfo(GUID);
2275 for (
auto &
I :
VI.getSummaryList())
2277 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2281 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2282 assert(FuncMD->getNumOperands() >= 2);
2283 StringRef FunctionName =
2288 ->getUniqueInteger()
2293 ->getUniqueInteger()
2297 if (!ExportSummary->isGUIDLive(GUID))
2304 if (
auto VI = ExportSummary->getValueInfo(GUID))
2305 for (
const auto &GVS :
VI.getSummaryList())
2312 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2314 P.first->second = {
Linkage, FuncMD};
2317 for (
const auto &
P : ExportedFunctions) {
2318 StringRef FunctionName =
P.first;
2320 MDNode *FuncMD =
P.second.FuncMD;
2322 if (
F &&
F->hasLocalLinkage()) {
2329 F->setName(
F->getName() +
".1");
2335 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2336 GlobalVariable::ExternalLinkage,
2337 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2339 LLVMContext::MD_guid,
2340 MDTuple::get(
M.getContext(), {FuncMD->getOperand(2).get()}));
2341 if (ExportSummary) {
2345 ->getUniqueInteger()
2347 if (
auto VI = ExportSummary->getValueInfo(GUID))
2349 VI.isDSOLocal(ExportSummary->withDSOLocalPropagation()));
2357 if (
F->hasAvailableExternallyLinkage()) {
2359 auto *OrigGUIDMD =
F->getMetadata(LLVMContext::MD_guid);
2362 F->setComdat(
nullptr);
2364 F->setMetadata(LLVMContext::MD_guid, OrigGUIDMD);
2376 if (
F->isDeclaration()) {
2380 F->eraseMetadata(LLVMContext::MD_type);
2382 F->addMetadata(LLVMContext::MD_type,
2389 struct AliasToCreate {
2391 std::string TargetName;
2393 std::vector<AliasToCreate> AliasesToCreate;
2397 if (ExportSummary) {
2398 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2399 for (
auto *AliasMD : AliasesMD->operands()) {
2401 for (
Metadata *MD : AliasMD->operands()) {
2405 StringRef AliasName = MDS->getString();
2406 if (!ExportedFunctions.count(AliasName))
2408 auto *AliasF =
M.getFunction(AliasName);
2413 if (Aliases.
empty())
2416 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2417 auto *AliasF = Aliases[
I];
2418 ExportedFunctions.
erase(AliasF->getName());
2419 AliasesToCreate.push_back(
2420 {AliasF, std::string(Aliases[0]->
getName())});
2426 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2427 for (GlobalObject &GO :
M.global_objects()) {
2434 bool IsJumpTableCanonical =
false;
2435 bool IsExported =
false;
2438 if (
auto It = ExportedFunctions.find(
F->getName());
2439 It != ExportedFunctions.end()) {
2446 }
else if (!
F->hasAddressTaken()) {
2447 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2452 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2454 GlobalTypeMembers[&GO] = GTM;
2455 for (MDNode *
Type : Types) {
2456 verifyTypeMDNode(&GO,
Type);
2457 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2458 Info.UniqueId = ++CurUniqueId;
2459 Info.RefGlobals.push_back(GTM);
2463 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2468 auto Ins = TypeIdUsers.
insert({TypeId, {}});
2471 auto &GCI = GlobalClasses.insert(TypeId);
2472 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2475 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2476 CurSet = GlobalClasses.unionSets(
2477 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2480 return Ins.first->second;
2484 for (
const Use &U : TypeTestFunc->
uses()) {
2493 for (
const Use &CIU : CI->
uses()) {
2496 OnlyAssumeUses =
false;
2505 auto TypeId = TypeIdMDVal->getMetadata();
2506 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2510 if (ICallBranchFunnelFunc) {
2511 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2514 "llvm.icall.branch.funnel not supported on this target");
2518 std::vector<GlobalTypeMember *> Targets;
2522 GlobalClassesTy::member_iterator CurSet;
2523 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2529 "Expected branch funnel operand to be global value");
2531 auto It = GlobalTypeMembers.
find(
Base);
2532 if (It == GlobalTypeMembers.
end())
2534 "defined global value with type metadata");
2535 GlobalTypeMember *GTM = It->second;
2536 Targets.push_back(GTM);
2537 GlobalClassesTy::member_iterator NewSet =
2538 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2542 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2545 GlobalClasses.unionSets(
2546 CurSet, GlobalClasses.findLeader(
2547 GlobalClasses.insert(ICallBranchFunnel::create(
2548 Alloc, CI, Targets, ++CurUniqueId))));
2552 if (ExportSummary) {
2553 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2554 for (
auto &
P : TypeIdInfo) {
2557 TypeId->getString())]
2561 for (
auto &
P : *ExportSummary) {
2562 for (
auto &S :
P.second.getSummaryList()) {
2563 if (!ExportSummary->isGlobalValueLive(S.get()))
2568 AddTypeIdUse(MD).IsExported =
true;
2573 if (GlobalClasses.empty())
2577 ScopedSaveAliaseesAndUsed S(M);
2579 for (
const auto &
C : GlobalClasses) {
2583 ++NumTypeIdDisjointSets;
2585 std::vector<Metadata *> TypeIds;
2586 std::vector<GlobalTypeMember *> Globals;
2587 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2588 for (
auto M : GlobalClasses.members(*
C)) {
2601 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2606 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2607 return F1->UniqueId < F2->UniqueId;
2611 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2615 allocateByteArrays();
2617 for (
auto A : AliasesToCreate) {
2618 auto *
Target =
M.getNamedValue(
A.TargetName);
2622 AliasGA->setVisibility(
A.Alias->getVisibility());
2623 AliasGA->setLinkage(
A.Alias->getLinkage());
2624 AliasGA->setDSOLocal(
A.Alias->isDSOLocal());
2625 AliasGA->takeName(
A.Alias);
2626 A.Alias->replaceAllUsesWith(AliasGA);
2627 A.Alias->eraseFromParent();
2631 if (ExportSummary) {
2632 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2633 for (
auto *Symver : SymversMD->operands()) {
2634 assert(Symver->getNumOperands() >= 2);
2637 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2639 if (!ExportedFunctions.count(SymbolName))
2642 M.appendModuleInlineAsm(
2643 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2655 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2657 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
2665 static_cast<PassInfoMixin<DropTypeTestsPass> *
>(
this)->
printPipeline(
2666 OS, MapClassName2PassName);
2669 case DropTestKind::Assume:
2672 case DropTestKind::All:
2705 for (
auto &GV : M.globals()) {
2712 auto MaySimplifyPtr = [&](
Value *Ptr) {
2714 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2718 auto MaySimplifyInt = [&](
Value *
Op) {
2720 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2722 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2738 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2742 if (U.getOperandNo() == 0 && CE &&
2743 CE->getOpcode() == Instruction::Sub &&
2744 MaySimplifyInt(CE->getOperand(1))) {
2750 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2754 if (U.getOperandNo() == 1 && CI &&
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the BumpPtrAllocator interface.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
static const unsigned kARMJumpTableEntrySize
static const unsigned kLOONGARCH64JumpTableEntrySize
static cl::opt< std::string > ClReadSummary("lowertypetests-read-summary", cl::desc("Read summary from given textual assembly or YAML " "file before running pass"), cl::Hidden)
static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL, Value *V, uint64_t COffset)
static const unsigned kX86IBTJumpTableEntrySize
static SmallVector< DILocation * > createJumpTableDebugInfo(Function *F, ArrayRef< GlobalTypeMember * > Functions)
static 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< bool > EnableJumpTableDebugInfo("lowertypetests-jump-table-debug-info", cl::init(true), cl::Hidden, cl::desc("Enable debug info generation for jump tables"))
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 const unsigned kHexagonJumpTableEntrySize
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
void addSymbolWithThinLTOGUID(StringRef Name, GlobalValue::GUID GUID)
Add the function name and the GUID that ThinLTO uses for it.
bool contains(StringRef Name) const
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
ConstantArray - Constant Array Declarations.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList)
Create an "inbounds" getelementptr.
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static Constant * getPtrAdd(Constant *Ptr, Constant *Offset, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReduced=nullptr)
Create a getelementptr i8, ptr, offset constant expression.
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getInBoundsPtrAdd(Constant *Ptr, Constant *Offset)
Create a getelementptr inbounds i8, ptr, offset constant expression.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI void finalize()
Construct any deferred debug info descriptors.
LLVM_ABI DISubroutineType * createSubroutineType(DITypeArray ParameterTypes, DINode::DIFlags Flags=DINode::FlagZero, unsigned CC=0)
Create subroutine type.
LLVM_ABI DISubprogram * createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags=DINode::FlagZero, DISubprogram::DISPFlags SPFlags=DISubprogram::SPFlagZero, DITemplateParameterArray TParams=nullptr, DISubprogram *Decl=nullptr, DITypeArray ThrownTypes=nullptr, DINodeArray Annotations=nullptr, StringRef TargetFuncName="", bool UseKeyInstructions=false)
Create a new descriptor for the specified subprogram.
LLVM_ABI DICompileUnit * createCompileUnit(DISourceLanguageName Lang, DIFile *File, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName=StringRef(), DICompileUnit::DebugEmissionKind Kind=DICompileUnit::DebugEmissionKind::FullDebug, uint64_t DWOId=0, bool SplitDebugInlining=true, bool DebugInfoForProfiling=false, DICompileUnit::DebugNameTableKind NameTableKind=DICompileUnit::DebugNameTableKind::Default, bool RangesBaseAddress=false, StringRef SysRoot={}, StringRef SDK={})
A CompileUnit provides an anchor for all debugging information generated during this instance of comp...
LLVM_ABI DIFile * createFile(StringRef Filename, StringRef Directory, std::optional< DIFile::ChecksumInfo< StringRef > > Checksum=std::nullopt, std::optional< StringRef > Source=std::nullopt)
Create a file descriptor to hold debugging information for a file.
Wrapper structure that holds source language identity metadata that includes language name,...
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const BasicBlock & getEntryBlock() const
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
LLVM_ABI void setComdat(Comdat *C)
LLVM_ABI void setSection(StringRef S)
Change the section for this global.
const Comdat * getComdat() const
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
bool hasSection() const
Check if this global has a custom object file section.
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
static bool isLocalLinkage(LinkageTypes Linkage)
LinkageTypes getLinkage() const
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
bool isDeclarationForLinker() const
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
VisibilityTypes
An enumeration for the kinds of visibility of global values.
@ HiddenVisibility
The GV is hidden.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
@ ExternalWeakLinkage
ExternalWeak linkage description.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
LLVM_ABI void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
void setConstant(bool Val)
LLVM_ABI void setCodeModel(CodeModel::Model CM)
Change the code model for this global.
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
const MDOperand & getOperand(unsigned I) const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
unsigned getNumOperands() const
Return number of MDNode operands.
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
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(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Analysis pass which computes a PostDominatorTree.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
bool insert(const value_type &X)
Insert a new element into the SetVector.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetTransformInfo.
See the file comment for details on the usage of the TrailingObjects type.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI 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 bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
void insert_range(Range &&R)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements a layout algorithm for globals referenced by bit sets that tries to keep member...
LLVM_ABI const std::vector< uint64_t > & build()
Flatten fragments into a single layout and return it.
LLVM_ABI void addFragment(const std::set< uint64_t > &F)
Add F to the layout while trying to keep its indices contiguous.
This class implements an extremely fast bulk output stream that can only output to a stream.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
LLVM_ABI 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.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
detail::zip_longest_range< T, U, Args... > zip_longest(T &&t, U &&u, Args &&... args)
Iterate over two or more iterators at the same time.
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Export
Export information to summary.
@ Import
Import information from summary.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
@ O1
Optimize quickly without destroying debuggability.
@ O2
Optimize for fast execution as much as possible without triggering significant incremental compile ti...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
LLVM_ABI bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)
Replace constant expressions users of the given constants with instructions.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
DWARFExpression::Operation Op
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
LLVM_ABI void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.used list.
CfiFunctionLinkage
The type of CFI jumptable needed for a function.
LLVM_ABI std::unique_ptr< ModuleSummaryIndex > parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err)
Parse LLVM Assembly for summary index from a MemoryBuffer.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
LLVM_ABI GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Kind
Specifies which kind of type check we should emit for this byte array.
@ Unknown
Unknown (analysis not performed, don't lower)
@ Single
Single element (last example in "Short Inline Bit Vectors")
@ Inline
Inlined bit vector ("Short Inline Bit Vectors")
@ Unsat
Unsatisfiable type (i.e. no global has this type metadata)
@ AllOnes
All-ones bit vector ("Eliminating Bit Vector Checks for All-Ones Bit Vectors")
@ ByteArray
Test a byte array (first example)
unsigned SizeM1BitWidth
Range of size-1 expressed as a bit width.
enum llvm::TypeTestResolution::Kind TheKind
LLVM_ABI BitSetInfo build()
SmallVector< uint64_t, 16 > Offsets
LLVM_ABI bool containsGlobalOffset(uint64_t Offset) const
LLVM_ABI void print(raw_ostream &OS) const
std::set< uint64_t > Bits
This class is used to build a byte array containing overlapping bit sets.
uint64_t BitAllocs[BitsPerByte]
The number of bytes allocated so far for each of the bits.
std::vector< uint8_t > Bytes
The byte array built so far.
LLVM_ABI void allocate(const std::set< uint64_t > &Bits, uint64_t BitSize, uint64_t &AllocByteOffset, uint8_t &AllocMask)
Allocate BitSize bits in the byte array where Bits contains the bits to set.