87#include <system_error>
94#define DEBUG_TYPE "lowertypetests"
96STATISTIC(ByteArraySizeBits,
"Byte array size in bits");
97STATISTIC(ByteArraySizeBytes,
"Byte array size in bytes");
98STATISTIC(NumByteArraysCreated,
"Number of byte arrays created");
99STATISTIC(NumTypeTestCallsLowered,
"Number of type test calls lowered");
100STATISTIC(NumTypeIdDisjointSets,
"Number of disjoint sets of type identifiers");
103 "lowertypetests-avoid-reuse",
104 cl::desc(
"Try to avoid reuse of byte array addresses using aliases"),
108 "lowertypetests-summary-action",
109 cl::desc(
"What to do with the summary when running this pass"),
112 "Import typeid resolutions from summary and globals"),
114 "Export typeid resolutions to summary and globals")),
118 "lowertypetests-read-summary",
119 cl::desc(
"Read summary from given YAML file before running pass"),
123 "lowertypetests-write-summary",
124 cl::desc(
"Write summary to given YAML file after running pass"),
130 cl::desc(
"Enable debug info generation for jump tables"));
201 std::vector<uint64_t> &Fragment =
Fragments.back();
204 for (
auto ObjIndex :
F) {
206 if (OldFragmentIndex == 0) {
209 Fragment.push_back(ObjIndex);
216 std::vector<uint64_t> &OldFragment =
Fragments[OldFragmentIndex];
239 unsigned ReqSize = AllocByteOffset + BitSize;
241 if (
Bytes.size() < ReqSize)
242 Bytes.resize(ReqSize);
245 AllocMask = 1 << Bit;
247 Bytes[AllocByteOffset +
B] |= AllocMask;
251 if (
F->isDeclarationForLinker())
254 F->getParent()->getModuleFlag(
"CFI Canonical Jump Tables"));
255 if (!CI || !CI->isZero())
257 return F->hasFnAttribute(
"cfi-canonical-jump-table");
262struct ByteArrayInfo {
263 std::set<uint64_t> Bits;
275class GlobalTypeMember final :
TrailingObjects<GlobalTypeMember, MDNode *> {
286 bool IsJumpTableCanonical;
294 bool IsJumpTableCanonical,
bool IsExported,
296 auto *GTM =
static_cast<GlobalTypeMember *
>(
Alloc.Allocate(
297 totalSizeToAlloc<MDNode *>(Types.size()),
alignof(GlobalTypeMember)));
299 GTM->NTypes = Types.size();
300 GTM->IsJumpTableCanonical = IsJumpTableCanonical;
301 GTM->IsExported = IsExported;
306 GlobalObject *getGlobal()
const {
311 return IsJumpTableCanonical;
314 bool isExported()
const {
321struct ICallBranchFunnel final
322 : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
326 auto *
Call =
static_cast<ICallBranchFunnel *
>(
327 Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.
size()),
328 alignof(ICallBranchFunnel)));
330 Call->UniqueId = UniqueId;
338 return getTrailingObjects(NTargets);
347struct ScopedSaveAliaseesAndUsed {
350 std::vector<std::pair<GlobalAlias *, Function *>> FunctionAliases;
351 std::vector<std::pair<GlobalIFunc *, Function *>> ResolverIFuncs;
356 void collectAndEraseUsedFunctions(
Module &M,
357 SmallVectorImpl<GlobalValue *> &Vec,
365 GV->eraseFromParent();
367 std::stable_partition(Vec.
begin(), Vec.
end(), [](GlobalValue *GV) {
368 return isa<Function>(GV);
377 ScopedSaveAliaseesAndUsed(
Module &M) :
M(
M) {
390 collectAndEraseUsedFunctions(M, Used,
false);
391 collectAndEraseUsedFunctions(M, CompilerUsed,
true);
393 for (
auto &GA :
M.aliases()) {
397 FunctionAliases.push_back({&GA,
F});
400 for (
auto &GI :
M.ifuncs())
402 ResolverIFuncs.push_back({&GI,
F});
405 ~ScopedSaveAliaseesAndUsed() {
409 for (
auto P : FunctionAliases)
410 P.first->setAliasee(
P.second);
412 for (
auto P : ResolverIFuncs) {
416 P.first->setResolver(
P.second);
421class LowerTypeTestsModule {
424 ModuleSummaryIndex *ExportSummary;
425 const ModuleSummaryIndex *ImportSummary;
434 bool CanUseArmJumpTable =
false, CanUseThumbBWJumpTable =
false;
437 int HasBranchTargetEnforcement = -1;
439 IntegerType *Int1Ty = Type::getInt1Ty(
M.getContext());
440 IntegerType *Int8Ty = Type::getInt8Ty(
M.getContext());
441 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
442 ArrayType *Int8Arr0Ty = ArrayType::get(Type::getInt8Ty(
M.getContext()), 0);
443 IntegerType *
Int32Ty = Type::getInt32Ty(
M.getContext());
444 IntegerType *Int64Ty = Type::getInt64Ty(
M.getContext());
445 IntegerType *IntPtrTy =
M.getDataLayout().getIntPtrType(
M.getContext(), 0);
448 uint64_t IndirectIndex = 1;
453 struct TypeIdUserInfo {
454 std::vector<CallInst *> CallSites;
455 bool IsExported =
false;
457 DenseMap<Metadata *, TypeIdUserInfo> TypeIdUsers;
463 struct TypeIdLowering {
488 std::vector<ByteArrayInfo> ByteArrayInfos;
490 Function *WeakInitializerFn =
nullptr;
492 GlobalVariable *GlobalAnnotation;
493 DenseSet<Value *> FunctionAnnotations;
495 bool shouldExportConstantsAsAbsoluteSymbols();
496 uint8_t *exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL);
497 TypeIdLowering importTypeId(StringRef TypeId);
498 void importTypeTest(CallInst *CI);
501 ByteArrayInfo *createByteArray(
const BitSetInfo &BSI);
502 void allocateByteArrays();
505 void lowerTypeTestCalls(
507 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout);
509 const TypeIdLowering &TIL);
515 bool hasBranchTargetEnforcement();
518 void verifyTypeMDNode(GlobalObject *GO, MDNode *
Type);
530 void replaceWeakDeclarationWithJumpTablePtr(Function *
F, Constant *JT,
531 bool IsJumpTableCanonical);
532 void moveInitializerToModuleConstructor(GlobalVariable *GV);
533 void findGlobalVariableUsersOf(Constant *
C,
534 SmallSetVector<GlobalVariable *, 8> &Out);
544 void replaceCfiUses(Function *Old,
Value *New,
bool IsJumpTableCanonical);
548 void replaceDirectCalls(
Value *Old,
Value *New);
550 bool isFunctionAnnotation(
Value *V)
const {
551 return FunctionAnnotations.
contains(V);
554 void maybeReplaceComdat(Function *
F, StringRef OriginalName);
558 ModuleSummaryIndex *ExportSummary,
559 const ModuleSummaryIndex *ImportSummary);
581 unsigned BitWidth = BitsType->getBitWidth();
583 BitOffset =
B.CreateZExtOrTrunc(BitOffset, BitsType);
585 B.CreateAnd(BitOffset, ConstantInt::get(BitsType,
BitWidth - 1));
586 Value *BitMask =
B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex);
587 Value *MaskedBits =
B.CreateAnd(Bits, BitMask);
588 return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
591ByteArrayInfo *LowerTypeTestsModule::createByteArray(
const BitSetInfo &BSI) {
595 auto ByteArrayGlobal =
new GlobalVariable(
597 auto MaskGlobal =
new GlobalVariable(M, Int8Ty,
true,
600 ByteArrayInfos.emplace_back();
601 ByteArrayInfo *BAI = &ByteArrayInfos.back();
603 BAI->Bits = BSI.
Bits;
605 BAI->ByteArray = ByteArrayGlobal;
606 BAI->MaskGlobal = MaskGlobal;
610void LowerTypeTestsModule::allocateByteArrays() {
612 [](
const ByteArrayInfo &BAI1,
const ByteArrayInfo &BAI2) {
613 return BAI1.BitSize > BAI2.BitSize;
616 std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size());
619 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
620 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
623 BAB.
allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[
I], Mask);
629 *BAI->MaskPtr =
Mask;
634 new GlobalVariable(M, ByteArrayConst->
getType(),
true,
637 for (
unsigned I = 0;
I != ByteArrayInfos.size(); ++
I) {
638 ByteArrayInfo *BAI = &ByteArrayInfos[
I];
640 ByteArray, ConstantInt::get(IntPtrTy, ByteArrayOffsets[
I]));
654 ByteArraySizeBytes = BAB.
Bytes.size();
660 const TypeIdLowering &TIL,
674 "bits_use", ByteArray, &M);
677 Value *ByteAddr =
B.CreateGEP(Int8Ty, ByteArray, BitOffset);
682 return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0));
690 GV->getMetadata(LLVMContext::MD_type, Types);
692 if (
Type->getOperand(1) != TypeId)
705 APInt APOffset(
DL.getIndexSizeInBits(0), 0);
706 bool Result =
GEP->accumulateConstantOffset(
DL, APOffset);
714 if (
Op->getOpcode() == Instruction::BitCast)
717 if (
Op->getOpcode() == Instruction::Select)
727Value *LowerTypeTestsModule::lowerTypeTestCall(
Metadata *TypeId, CallInst *CI,
728 const TypeIdLowering &TIL) {
736 const DataLayout &
DL =
M.getDataLayout();
744 Value *PtrAsInt =
B.CreatePtrToInt(Ptr, IntPtrTy);
749 return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt);
755 Value *PtrOffset =
B.CreateSub(OffsetedGlobalAsInt, PtrAsInt);
765 Value *BitOffset =
B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr,
766 {PtrOffset, PtrOffset, TIL.AlignLog2});
768 Value *OffsetInRange =
B.CreateICmpULE(BitOffset, TIL.SizeM1);
772 return OffsetInRange;
784 NewBr->setMetadata(LLVMContext::MD_prof,
785 Br->getMetadata(LLVMContext::MD_prof));
789 for (
auto &Phi :
Else->phis())
790 Phi.addIncoming(
Phi.getIncomingValueForBlock(Then), InitialBB);
793 return createBitSetTest(ThenB, TIL, BitOffset);
796 MDBuilder MDB(
M.getContext());
798 MDB.createLikelyBranchWeights()));
802 Value *
Bit = createBitSetTest(ThenB, TIL, BitOffset);
807 B.SetInsertPoint(CI);
808 PHINode *
P =
B.CreatePHI(Int1Ty, 2);
809 P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB);
810 P->addIncoming(Bit, ThenB.GetInsertBlock());
816void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
823 std::vector<Constant *> GlobalInits;
824 const DataLayout &
DL =
M.getDataLayout();
825 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
827 uint64_t CurOffset = 0;
828 uint64_t DesiredPadding = 0;
829 for (GlobalTypeMember *
G : Globals) {
832 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
833 MaxAlign = std::max(MaxAlign, Alignment);
834 uint64_t GVOffset =
alignTo(CurOffset + DesiredPadding, Alignment);
835 GlobalLayout[
G] = GVOffset;
837 uint64_t
Padding = GVOffset - CurOffset;
838 GlobalInits.push_back(
842 GlobalInits.push_back(GV->getInitializer());
843 uint64_t InitSize = GV->getGlobalSize(
DL);
844 CurOffset = GVOffset + InitSize;
853 if (DesiredPadding > 32)
854 DesiredPadding =
alignTo(InitSize, 32) - InitSize;
858 auto *CombinedGlobal =
859 new GlobalVariable(M, NewInit->
getType(),
true,
861 CombinedGlobal->setAlignment(MaxAlign);
864 lowerTypeTestCalls(TypeIds, CombinedGlobal, GlobalLayout);
869 for (
unsigned I = 0;
I != Globals.size(); ++
I) {
876 NewInit->
getType(), CombinedGlobal, CombinedGlobalIdxs);
878 GlobalAlias *GAlias =
880 "", CombinedGlobalElemPtr, &M);
888bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() {
901uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
902 const TypeIdLowering &TIL) {
903 TypeTestResolution &TTRes =
910 "__typeid_" + TypeId +
"_" + Name,
C, &M);
914 auto ExportConstant = [&](StringRef
Name, uint64_t &Storage,
Constant *
C) {
915 if (shouldExportConstantsAsAbsoluteSymbols())
922 ExportGlobal(
"global_addr", TIL.OffsetedGlobal);
927 ExportConstant(
"align", TTRes.
AlignLog2, TIL.AlignLog2);
928 ExportConstant(
"size_m1", TTRes.
SizeM1, TIL.SizeM1);
938 ExportGlobal(
"byte_array", TIL.TheByteArray);
939 if (shouldExportConstantsAsAbsoluteSymbols())
940 ExportGlobal(
"bit_mask", TIL.BitMask);
946 ExportConstant(
"inline_bits", TTRes.
InlineBits, TIL.InlineBits);
951LowerTypeTestsModule::TypeIdLowering
952LowerTypeTestsModule::importTypeId(StringRef TypeId) {
956 const TypeTestResolution &TTRes = TidSummary->
TTRes;
961 auto ImportGlobal = [&](StringRef
Name) {
964 GlobalVariable *GV =
M.getOrInsertGlobal(
965 (
"__typeid_" + TypeId +
"_" + Name).str(), Int8Arr0Ty);
970 auto ImportConstant = [&](StringRef
Name, uint64_t
Const,
unsigned AbsWidth,
972 if (!shouldExportConstantsAsAbsoluteSymbols()) {
984 if (GV->
getMetadata(LLVMContext::MD_absolute_symbol))
987 auto SetAbsRange = [&](uint64_t Min, uint64_t
Max) {
997 SetAbsRange(0, 1ull << AbsWidth);
1003 auto *GV = ImportGlobal(
"global_addr");
1016 TIL.OffsetedGlobal = GV;
1022 TIL.AlignLog2 = ImportConstant(
"align", TTRes.
AlignLog2, 8, IntPtrTy);
1028 TIL.TheByteArray = ImportGlobal(
"byte_array");
1029 TIL.BitMask = ImportConstant(
"bit_mask", TTRes.
BitMask, 8, PtrTy);
1033 TIL.InlineBits = ImportConstant(
1040void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
1052 TypeIdLowering TIL = importTypeId(TypeIdStr->getString());
1053 Value *Lowered = lowerTypeTestCall(TypeIdStr, CI, TIL);
1060void LowerTypeTestsModule::maybeReplaceComdat(Function *
F,
1061 StringRef OriginalName) {
1067 F->getComdat()->getName() == OriginalName) {
1068 Comdat *OldComdat =
F->getComdat();
1069 Comdat *NewComdat =
M.getOrInsertComdat(
F->getName());
1070 for (GlobalObject &GO :
M.global_objects()) {
1079void LowerTypeTestsModule::importFunction(Function *
F,
1081 assert(
F->getType()->getAddressSpace() == 0);
1084 std::string
Name = std::string(
F->getName());
1089 if (
F->isDSOLocal()) {
1092 F->getAddressSpace(),
1095 replaceDirectCalls(
F, RealF);
1105 F->getAddressSpace(), Name +
".cfi_jt", &M);
1108 F->setName(Name +
".cfi");
1109 maybeReplaceComdat(
F, Name);
1111 F->getAddressSpace(), Name, &M);
1118 for (
auto &U :
F->uses()) {
1120 std::string AliasName =
A->getName().str() +
".cfi";
1123 F->getAddressSpace(),
"", &M);
1125 A->replaceAllUsesWith(AliasDecl);
1126 A->setName(AliasName);
1131 if (
F->hasExternalWeakLinkage())
1138 F->setVisibility(Visibility);
1147 OffsetsByTypeID[TypeId];
1148 for (
const auto &[Mem, MemOff] : GlobalLayout) {
1150 auto It = OffsetsByTypeID.
find(
Type->getOperand(1));
1151 if (It == OffsetsByTypeID.
end())
1157 It->second.push_back(MemOff +
Offset);
1167 dbgs() << MDS->getString() <<
": ";
1169 dbgs() <<
"<unnamed>: ";
1170 BitSets.
back().second.print(
dbgs());
1177void LowerTypeTestsModule::lowerTypeTestCalls(
1179 const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1181 for (
const auto &[TypeId, BSI] :
buildBitSets(TypeIds, GlobalLayout)) {
1182 ByteArrayInfo *BAI =
nullptr;
1185 uint64_t GlobalOffset =
1188 CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),
1189 TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.
AlignLog2);
1190 TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.
BitSize - 1);
1193 : TypeTestResolution::
AllOnes;
1196 uint64_t InlineBits = 0;
1197 for (
auto Bit : BSI.
Bits)
1198 InlineBits |= uint64_t(1) <<
Bit;
1199 if (InlineBits == 0)
1202 TIL.InlineBits = ConstantInt::get(
1206 ++NumByteArraysCreated;
1207 BAI = createByteArray(BSI);
1208 TIL.TheByteArray = BAI->ByteArray;
1209 TIL.BitMask = BAI->MaskGlobal;
1212 TypeIdUserInfo &TIUI = TypeIdUsers[TypeId];
1214 if (TIUI.IsExported) {
1215 uint8_t *MaskPtr = exportTypeId(
cast<MDString>(TypeId)->getString(), TIL);
1217 BAI->MaskPtr = MaskPtr;
1221 for (CallInst *CI : TIUI.CallSites) {
1222 ++NumTypeTestCallsLowered;
1223 Value *Lowered = lowerTypeTestCall(TypeId, CI, TIL);
1232void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *
Type) {
1233 if (
Type->getNumOperands() != 2)
1240 "A member of a type identifier may not have an explicit section");
1263bool LowerTypeTestsModule::hasBranchTargetEnforcement() {
1264 if (HasBranchTargetEnforcement == -1) {
1268 M.getModuleFlag(
"branch-target-enforcement")))
1269 HasBranchTargetEnforcement = !BTE->isZero();
1271 HasBranchTargetEnforcement = 0;
1273 return HasBranchTargetEnforcement;
1277LowerTypeTestsModule::getJumpTableEntrySize(
Triple::ArchType JumpTableArch) {
1278 switch (JumpTableArch) {
1282 M.getModuleFlag(
"cf-protection-branch")))
1283 if (MD->getZExtValue())
1289 if (CanUseThumbBWJumpTable) {
1290 if (hasBranchTargetEnforcement())
1297 if (hasBranchTargetEnforcement())
1316LowerTypeTestsModule::createJumpTableEntryAsm(
Triple::ArchType JumpTableArch) {
1318 raw_string_ostream AsmOS(Asm);
1323 M.getModuleFlag(
"cf-protection-branch")))
1324 Endbr = !MD->isZero();
1326 AsmOS << (JumpTableArch ==
Triple::x86 ?
"endbr32\n" :
"endbr64\n");
1327 AsmOS <<
"jmp ${0:c}@plt\n";
1329 AsmOS <<
".balign 16, 0xcc\n";
1331 AsmOS <<
"int3\nint3\nint3\n";
1335 if (hasBranchTargetEnforcement())
1339 if (!CanUseThumbBWJumpTable) {
1355 AsmOS <<
"push {r0,r1}\n"
1357 <<
"0: add r0, r0, pc\n"
1358 <<
"str r0, [sp, #4]\n"
1361 <<
"1: .word $0 - (0b + 4)\n";
1363 if (hasBranchTargetEnforcement())
1365 AsmOS <<
"b.w $0\n";
1369 AsmOS <<
"tail $0@plt\n";
1371 AsmOS <<
"pcalau12i $$t0, %pc_hi20($0)\n"
1372 <<
"jirl $$r0, $$t0, %pc_lo12($0)\n";
1374 AsmOS <<
"jump $0\n";
1387void LowerTypeTestsModule::buildBitSetsFromFunctions(
1393 buildBitSetsFromFunctionsNative(TypeIds, Functions);
1395 buildBitSetsFromFunctionsWASM(TypeIds, Functions);
1400void LowerTypeTestsModule::moveInitializerToModuleConstructor(
1401 GlobalVariable *GV) {
1402 if (WeakInitializerFn ==
nullptr) {
1407 M.getDataLayout().getProgramAddressSpace(),
1408 "__cfi_global_var_init", &M);
1412 WeakInitializerFn->setSection(
1414 ?
"__TEXT,__StaticInit,regular,pure_instructions"
1421 IRBuilder<> IRB(WeakInitializerFn->getEntryBlock().getTerminator());
1427void LowerTypeTestsModule::findGlobalVariableUsersOf(
1428 Constant *
C, SmallSetVector<GlobalVariable *, 8> &Out) {
1429 for (
auto *U :
C->users()){
1433 findGlobalVariableUsersOf(C2, Out);
1438void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
1439 Function *
F, Constant *JT,
bool IsJumpTableCanonical) {
1442 SmallSetVector<GlobalVariable *, 8> GlobalVarUsers;
1443 findGlobalVariableUsersOf(
F, GlobalVarUsers);
1444 for (
auto *GV : GlobalVarUsers) {
1445 if (GV == GlobalAnnotation)
1447 moveInitializerToModuleConstructor(GV);
1454 F->getAddressSpace(),
"", &M);
1455 replaceCfiUses(
F, PlaceholderFn, IsJumpTableCanonical);
1462 assert(InsertPt &&
"Non-instruction users should have been eliminated");
1465 InsertPt = PN->getIncomingBlock(U)->getTerminator();
1477 PN->setIncomingValueForBlock(InsertPt->getParent(),
Select);
1485 Attribute TFAttr =
F->getFnAttribute(
"target-features");
1490 if (Feature ==
"-thumb-mode")
1492 else if (Feature ==
"+thumb-mode")
1508 if (!CanUseThumbBWJumpTable && CanUseArmJumpTable) {
1516 unsigned ArmCount = 0, ThumbCount = 0;
1517 for (
const auto GTM : Functions) {
1518 if (!GTM->isJumpTableCanonical()) {
1539 auto CUs = M.debug_compile_units();
1556 CU,
"__ubsan_check_cfi_icall_jt", {}, File, 0, DIFnTy, 0,
1557 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1559 F->setSubprogram(UbsanSP);
1564 Locations.
reserve(Functions.size());
1566 for (
auto *Func : Functions) {
1567 StringRef FuncName = Func->getGlobal()->getName();
1570 CU, (FuncName +
".cfi_jt").str(), {}, File, 0, DIFnTy, 0,
1571 DINode::FlagArtificial, DISubprogram::SPFlagDefinition);
1576 Locations.push_back(EntryLoc);
1584void LowerTypeTestsModule::createJumpTable(
1594 InlineAsm *JumpTableAsm = createJumpTableEntryAsm(JumpTableArch);
1600 bool areAllEntriesNounwind =
true;
1602 for (
auto [GTM, Loc] :
zip_longest(Functions, Locations)) {
1603 if (Loc.has_value())
1604 IRB.SetCurrentDebugLocation(*Loc);
1606 ->hasFnAttribute(Attribute::NoUnwind)) {
1607 areAllEntriesNounwind =
false;
1609 IRB.CreateCall(JumpTableAsm, (*GTM)->getGlobal());
1611 IRB.CreateUnreachable();
1614 F->setAlignment(
Align(getJumpTableEntrySize(JumpTableArch)));
1615 F->addFnAttr(Attribute::Naked);
1617 F->addFnAttr(
"target-features",
"-thumb-mode");
1619 if (hasBranchTargetEnforcement()) {
1622 F->addFnAttr(
"target-features",
"+thumb-mode,+pacbti");
1624 F->addFnAttr(
"target-features",
"+thumb-mode");
1625 if (CanUseThumbBWJumpTable) {
1628 F->addFnAttr(
"target-cpu",
"cortex-a8");
1636 if (
F->hasFnAttribute(
"branch-target-enforcement"))
1637 F->removeFnAttr(
"branch-target-enforcement");
1638 if (
F->hasFnAttribute(
"sign-return-address"))
1639 F->removeFnAttr(
"sign-return-address");
1644 F->addFnAttr(
"target-features",
"-c,-relax");
1650 F->addFnAttr(Attribute::NoCfCheck);
1653 if (areAllEntriesNounwind)
1654 F->addFnAttr(Attribute::NoUnwind);
1657 F->addFnAttr(Attribute::NoInline);
1662void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
1747 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1748 unsigned EntrySize = getJumpTableEntrySize(JumpTableArch);
1749 for (
unsigned I = 0;
I != Functions.
size(); ++
I)
1750 GlobalLayout[Functions[
I]] =
I * EntrySize;
1756 M.getDataLayout().getProgramAddressSpace(),
1757 ".cfi.jumptable", &M);
1764 lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
1768 for (
unsigned I = 0;
I != Functions.
size(); ++
I) {
1770 bool IsJumpTableCanonical = Functions[
I]->isJumpTableCanonical();
1773 JumpTableType, JumpTable,
1775 ConstantInt::get(IntPtrTy,
I)});
1777 const bool IsExported = Functions[
I]->isExported();
1778 if (!IsJumpTableCanonical) {
1782 F->getName() +
".cfi_jt",
1783 CombinedGlobalElemPtr, &M);
1791 if (IsJumpTableCanonical)
1797 if (!IsJumpTableCanonical) {
1798 if (
F->hasExternalWeakLinkage())
1799 replaceWeakDeclarationWithJumpTablePtr(
F, CombinedGlobalElemPtr,
1800 IsJumpTableCanonical);
1802 replaceCfiUses(
F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1804 assert(
F->getType()->getAddressSpace() == 0);
1806 GlobalAlias *FAlias =
1808 CombinedGlobalElemPtr, &M);
1812 F->setName(FAlias->
getName() +
".cfi");
1813 maybeReplaceComdat(
F, FAlias->
getName());
1815 replaceCfiUses(
F, FAlias, IsJumpTableCanonical);
1816 if (!
F->hasLocalLinkage())
1821 createJumpTable(JumpTableFn, Functions, JumpTableArch);
1830void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
1835 DenseMap<GlobalTypeMember *, uint64_t> GlobalLayout;
1837 for (GlobalTypeMember *GTM : Functions) {
1841 if (!
F->hasAddressTaken())
1847 ConstantInt::get(Int64Ty, IndirectIndex))));
1848 F->setMetadata(
"wasm.index", MD);
1851 GlobalLayout[GTM] = IndirectIndex++;
1860void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
1863 DenseMap<Metadata *, uint64_t> TypeIdIndices;
1864 for (
unsigned I = 0;
I != TypeIds.
size(); ++
I)
1865 TypeIdIndices[TypeIds[
I]] =
I;
1869 std::vector<std::set<uint64_t>> TypeMembers(TypeIds.
size());
1870 unsigned GlobalIndex = 0;
1871 DenseMap<GlobalTypeMember *, uint64_t> GlobalIndices;
1872 for (GlobalTypeMember *GTM : Globals) {
1873 for (MDNode *
Type : GTM->types()) {
1875 auto I = TypeIdIndices.
find(
Type->getOperand(1));
1876 if (
I != TypeIdIndices.
end())
1877 TypeMembers[
I->second].insert(GlobalIndex);
1879 GlobalIndices[GTM] = GlobalIndex;
1883 for (ICallBranchFunnel *JT : ICallBranchFunnels) {
1884 TypeMembers.emplace_back();
1885 std::set<uint64_t> &TMSet = TypeMembers.back();
1886 for (GlobalTypeMember *
T : JT->targets())
1887 TMSet.insert(GlobalIndices[
T]);
1893 const std::set<uint64_t> &O2) {
1894 return O1.size() < O2.size();
1901 for (
auto &&MemSet : TypeMembers)
1902 GLB.addFragment(MemSet);
1907 std::vector<GlobalTypeMember *> OrderedGTMs(Globals.size());
1908 auto OGTMI = OrderedGTMs.begin();
1909 for (
auto &&
F : GLB.Fragments) {
1913 "variables and functions");
1914 *OGTMI++ = Globals[
Offset];
1920 buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs);
1922 buildBitSetsFromFunctions(TypeIds, OrderedGTMs);
1926LowerTypeTestsModule::LowerTypeTestsModule(
1928 const ModuleSummaryIndex *ImportSummary)
1929 :
M(
M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
1930 assert(!(ExportSummary && ImportSummary));
1931 Triple TargetTriple(M.getTargetTriple());
1932 Arch = TargetTriple.getArch();
1934 CanUseArmJumpTable =
true;
1940 if (
F.isDeclaration())
1943 if (
TTI.hasArmWideBranch(
false))
1944 CanUseArmJumpTable =
true;
1945 if (
TTI.hasArmWideBranch(
true))
1946 CanUseThumbBWJumpTable =
true;
1949 OS = TargetTriple.getOS();
1950 ObjectFormat = TargetTriple.getObjectFormat();
1954 GlobalAnnotation = M.getGlobalVariable(
"llvm.global.annotations");
1955 if (GlobalAnnotation && GlobalAnnotation->hasInitializer()) {
1958 FunctionAnnotations.insert_range(CA->
operands());
1963 ModuleSummaryIndex
Summary(
false);
1968 ExitOnError ExitOnErr(
"-lowertypetests-read-summary: " +
ClReadSummary +
1973 yaml::Input
In(ReadSummaryFile->getBuffer());
1979 LowerTypeTestsModule(
1986 ExitOnError ExitOnErr(
"-lowertypetests-write-summary: " +
ClWriteSummary +
1992 yaml::Output Out(OS);
2001 return Usr && Usr->isCallee(&U);
2004void LowerTypeTestsModule::replaceCfiUses(Function *Old,
Value *New,
2005 bool IsJumpTableCanonical) {
2006 SmallSetVector<Constant *, 4>
Constants;
2018 if (isFunctionAnnotation(
U.getUser()))
2036 for (
auto *
C : Constants)
2037 C->handleOperandChange(Old, New);
2040void LowerTypeTestsModule::replaceDirectCalls(
Value *Old,
Value *New) {
2045 bool ShouldDropAll) {
2051 Assume->eraseFromParent();
2060 return isa<PHINode>(U) || isa<SelectInst>(U);
2078 if (PublicTypeTestFunc)
2080 if (TypeTestFunc || PublicTypeTestFunc) {
2091bool LowerTypeTestsModule::lower() {
2105 if ((!TypeTestFunc || TypeTestFunc->
use_empty()) &&
2106 (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->
use_empty()) &&
2107 !ExportSummary && !ImportSummary)
2110 if (ImportSummary) {
2115 if (ICallBranchFunnelFunc && !ICallBranchFunnelFunc->
use_empty())
2117 "unexpected call to llvm.icall.branch.funnel during import phase");
2124 if (
F.hasLocalLinkage())
2133 ScopedSaveAliaseesAndUsed S(M);
2134 for (
auto *
F : Defs)
2135 importFunction(
F,
true);
2136 for (
auto *
F : Decls)
2137 importFunction(
F,
false);
2146 using GlobalClassesTy = EquivalenceClasses<
2147 PointerUnion<GlobalTypeMember *, Metadata *, ICallBranchFunnel *>>;
2148 GlobalClassesTy GlobalClasses;
2160 std::vector<GlobalTypeMember *> RefGlobals;
2162 DenseMap<Metadata *, TIInfo> TypeIdInfo;
2163 unsigned CurUniqueId = 0;
2168 const bool CrossDsoCfi =
M.getModuleFlag(
"Cross-DSO CFI") !=
nullptr;
2170 struct ExportedFunctionInfo {
2174 MapVector<StringRef, ExportedFunctionInfo> ExportedFunctions;
2175 if (ExportSummary) {
2176 NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions");
2177 if (CfiFunctionsMD) {
2179 DenseSet<GlobalValue::GUID> AddressTaken;
2180 for (
auto &
I : *ExportSummary)
2181 for (
auto &GVS :
I.second.getSummaryList())
2183 for (
const auto &
Ref : GVS->refs()) {
2185 for (
auto &RefGVS :
Ref.getSummaryList())
2187 AddressTaken.
insert(Alias->getAliaseeGUID());
2190 if (AddressTaken.
count(GUID))
2192 auto VI = ExportSummary->getValueInfo(GUID);
2195 for (
auto &
I :
VI.getSummaryList())
2197 if (AddressTaken.
count(Alias->getAliaseeGUID()))
2201 for (
auto *FuncMD : CfiFunctionsMD->
operands()) {
2202 assert(FuncMD->getNumOperands() >= 2);
2203 StringRef FunctionName =
2208 ->getUniqueInteger()
2215 if (!ExportSummary->isGUIDLive(GUID))
2222 if (
auto VI = ExportSummary->getValueInfo(GUID))
2223 for (
const auto &GVS :
VI.getSummaryList())
2230 auto P = ExportedFunctions.
insert({FunctionName, {
Linkage, FuncMD}});
2232 P.first->second = {
Linkage, FuncMD};
2235 for (
const auto &
P : ExportedFunctions) {
2236 StringRef FunctionName =
P.first;
2238 MDNode *FuncMD =
P.second.FuncMD;
2240 if (
F &&
F->hasLocalLinkage()) {
2247 F->setName(
F->getName() +
".1");
2253 FunctionType::get(Type::getVoidTy(
M.getContext()),
false),
2254 GlobalVariable::ExternalLinkage,
2255 M.getDataLayout().getProgramAddressSpace(), FunctionName, &M);
2262 if (
F->hasAvailableExternallyLinkage()) {
2265 F->setComdat(
nullptr);
2278 if (
F->isDeclaration()) {
2282 F->eraseMetadata(LLVMContext::MD_type);
2284 F->addMetadata(LLVMContext::MD_type,
2291 struct AliasToCreate {
2293 std::string TargetName;
2295 std::vector<AliasToCreate> AliasesToCreate;
2299 if (ExportSummary) {
2300 if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
2301 for (
auto *AliasMD : AliasesMD->operands()) {
2303 for (
Metadata *MD : AliasMD->operands()) {
2307 StringRef AliasName = MDS->getString();
2308 if (!ExportedFunctions.count(AliasName))
2310 auto *AliasF =
M.getFunction(AliasName);
2315 if (Aliases.
empty())
2318 for (
unsigned I = 1;
I != Aliases.
size(); ++
I) {
2319 auto *AliasF = Aliases[
I];
2320 ExportedFunctions.
erase(AliasF->getName());
2321 AliasesToCreate.push_back(
2322 {AliasF, std::string(Aliases[0]->
getName())});
2328 DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
2329 for (GlobalObject &GO :
M.global_objects()) {
2336 bool IsJumpTableCanonical =
false;
2337 bool IsExported =
false;
2340 if (
auto It = ExportedFunctions.find(
F->getName());
2341 It != ExportedFunctions.end()) {
2348 }
else if (!
F->hasAddressTaken()) {
2349 if (!CrossDsoCfi || !IsJumpTableCanonical ||
F->hasLocalLinkage())
2354 auto *GTM = GlobalTypeMember::create(
Alloc, &GO, IsJumpTableCanonical,
2356 GlobalTypeMembers[&GO] = GTM;
2357 for (MDNode *
Type : Types) {
2358 verifyTypeMDNode(&GO,
Type);
2359 auto &
Info = TypeIdInfo[
Type->getOperand(1)];
2360 Info.UniqueId = ++CurUniqueId;
2361 Info.RefGlobals.push_back(GTM);
2365 auto AddTypeIdUse = [&](
Metadata *TypeId) -> TypeIdUserInfo & {
2370 auto Ins = TypeIdUsers.insert({TypeId, {}});
2373 auto &GCI = GlobalClasses.insert(TypeId);
2374 GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
2377 for (GlobalTypeMember *GTM : TypeIdInfo[TypeId].RefGlobals)
2378 CurSet = GlobalClasses.unionSets(
2379 CurSet, GlobalClasses.findLeader(GlobalClasses.insert(GTM)));
2382 return Ins.first->second;
2386 for (
const Use &U : TypeTestFunc->
uses()) {
2395 for (
const Use &CIU : CI->
uses()) {
2398 OnlyAssumeUses =
false;
2407 auto TypeId = TypeIdMDVal->getMetadata();
2408 AddTypeIdUse(TypeId).CallSites.push_back(CI);
2412 if (ICallBranchFunnelFunc) {
2413 for (
const Use &U : ICallBranchFunnelFunc->
uses()) {
2416 "llvm.icall.branch.funnel not supported on this target");
2420 std::vector<GlobalTypeMember *> Targets;
2424 GlobalClassesTy::member_iterator CurSet;
2425 for (
unsigned I = 1;
I != CI->
arg_size();
I += 2) {
2431 "Expected branch funnel operand to be global value");
2433 GlobalTypeMember *GTM = GlobalTypeMembers[
Base];
2434 Targets.push_back(GTM);
2435 GlobalClassesTy::member_iterator NewSet =
2436 GlobalClasses.findLeader(GlobalClasses.insert(GTM));
2440 CurSet = GlobalClasses.unionSets(CurSet, NewSet);
2443 GlobalClasses.unionSets(
2444 CurSet, GlobalClasses.findLeader(
2445 GlobalClasses.insert(ICallBranchFunnel::create(
2446 Alloc, CI, Targets, ++CurUniqueId))));
2450 if (ExportSummary) {
2451 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2452 for (
auto &
P : TypeIdInfo) {
2455 TypeId->getString())]
2459 for (
auto &
P : *ExportSummary) {
2460 for (
auto &S :
P.second.getSummaryList()) {
2461 if (!ExportSummary->isGlobalValueLive(S.get()))
2466 AddTypeIdUse(MD).IsExported =
true;
2471 if (GlobalClasses.empty())
2475 ScopedSaveAliaseesAndUsed S(M);
2477 for (
const auto &
C : GlobalClasses) {
2481 ++NumTypeIdDisjointSets;
2483 std::vector<Metadata *> TypeIds;
2484 std::vector<GlobalTypeMember *> Globals;
2485 std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2486 for (
auto M : GlobalClasses.members(*
C)) {
2499 return TypeIdInfo[
M1].UniqueId < TypeIdInfo[M2].UniqueId;
2504 [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2505 return F1->UniqueId < F2->UniqueId;
2509 buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2513 allocateByteArrays();
2515 for (
auto A : AliasesToCreate) {
2516 auto *
Target =
M.getNamedValue(
A.TargetName);
2520 AliasGA->setVisibility(
A.Alias->getVisibility());
2521 AliasGA->setLinkage(
A.Alias->getLinkage());
2522 AliasGA->takeName(
A.Alias);
2523 A.Alias->replaceAllUsesWith(AliasGA);
2524 A.Alias->eraseFromParent();
2528 if (ExportSummary) {
2529 if (NamedMDNode *SymversMD =
M.getNamedMetadata(
"symvers")) {
2530 for (
auto *Symver : SymversMD->operands()) {
2531 assert(Symver->getNumOperands() >= 2);
2534 StringRef Alias =
cast<MDString>(Symver->getOperand(1))->getString();
2536 if (!ExportedFunctions.count(SymbolName))
2539 M.appendModuleInlineAsm(
2540 (llvm::Twine(
".symver ") + SymbolName +
", " + Alias).str());
2552 Changed = LowerTypeTestsModule::runForTesting(M, AM);
2554 Changed = LowerTypeTestsModule(M, AM, ExportSummary, ImportSummary).lower();
2563 OS, MapClassName2PassName);
2566 case DropTestKind::Assume:
2569 case DropTestKind::All:
2602 for (
auto &GV : M.globals()) {
2609 auto MaySimplifyPtr = [&](
Value *Ptr) {
2611 if (
auto *CFIGV = M.getNamedValue((GV->
getName() +
".cfi").str()))
2615 auto MaySimplifyInt = [&](
Value *
Op) {
2617 if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
2619 return MaySimplifyPtr(PtrAsInt->getOperand(0));
2635 if (!CE || CE->getOpcode() != Instruction::PtrToInt)
2639 if (U.getOperandNo() == 0 && CE &&
2640 CE->getOpcode() == Instruction::Sub &&
2641 MaySimplifyInt(CE->getOperand(1))) {
2647 CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
2651 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< 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 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 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< 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 contains library features backported from future STL versions.
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 emplace(Args &&...A)
size_t count(StringRef S) 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 a language name and its version.
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)
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)
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.
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.
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.
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.
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.
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 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)
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.
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.
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)
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...
@ 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.
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 ...
A CRTP mix-in to automatically provide informational APIs needed for passes.
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.