From ff38981a5817f06afad2c7e263e3bf8486f35da9 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 30 Jul 2025 14:04:11 -0700 Subject: LTO: Redesign the CFI !aliases metadata. With the current aliases metadata we lose information about which groups of aliases survive symbol resolution. This causes various problems such as #150075 where symbol resolution breaks the link between alias groups. In this redesign of the aliases metadata, we stop representing the individual aliases in !aliases. Instead, the individual aliases are represented in !cfi.functions in the same way as functions, and the alias groups (i.e. groups of symbols with the same address) are stored in !aliases. At symbol resolution time, we filter out all non-prevailing members of !aliases; the resulting set is used by LowerTypeTests to recreate the aliases. With this change it is now possible for a jump table entry to refer to an alias in one of the ThinLTO object files (e.g. if a function is non-prevailing but its alias is prevailing), so instead of deleting them, rename them with the ".cfi" suffix. Fixes #150070. Fixes #150075. Reviewers: teresajohnson, vitalybuka Reviewed By: vitalybuka Pull Request: https://github.com/llvm/llvm-project/pull/150690 --- llvm/lib/LTO/LTO.cpp | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'llvm/lib/LTO/LTO.cpp') diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 7f07568..814bb2a 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -743,8 +743,9 @@ Error LTO::add(std::unique_ptr Input, Conf.VisibilityScheme = Config::ELF; } + ArrayRef InputRes = Res; for (unsigned I = 0; I != Input->Mods.size(); ++I) { - if (auto Err = addModule(*Input, I, Res).moveInto(Res)) + if (auto Err = addModule(*Input, InputRes, I, Res).moveInto(Res)) return Err; } @@ -753,8 +754,8 @@ Error LTO::add(std::unique_ptr Input, } Expected> -LTO::addModule(InputFile &Input, unsigned ModI, - ArrayRef Res) { +LTO::addModule(InputFile &Input, ArrayRef InputRes, + unsigned ModI, ArrayRef Res) { Expected LTOInfo = Input.Mods[ModI].getLTOInfo(); if (!LTOInfo) return LTOInfo.takeError(); @@ -791,7 +792,7 @@ LTO::addModule(InputFile &Input, unsigned ModI, return addThinLTO(BM, ModSyms, Res); RegularLTO.EmptyCombinedModule = false; - auto ModOrErr = addRegularLTO(BM, ModSyms, Res); + auto ModOrErr = addRegularLTO(Input, InputRes, BM, ModSyms, Res); if (!ModOrErr) return ModOrErr.takeError(); Res = ModOrErr->second; @@ -846,7 +847,8 @@ handleNonPrevailingComdat(GlobalValue &GV, // linkRegularLTO. Expected< std::pair>> -LTO::addRegularLTO(BitcodeModule BM, ArrayRef Syms, +LTO::addRegularLTO(InputFile &Input, ArrayRef InputRes, + BitcodeModule BM, ArrayRef Syms, ArrayRef Res) { RegularLTOState::AddedModule Mod; Expected> MOrErr = @@ -860,13 +862,34 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef Syms, if (Error Err = M.materializeMetadata()) return std::move(Err); - // If cfi.functions is present and we are in regular LTO mode, LowerTypeTests - // will rename local functions in the merged module as ".1". - // This causes linking errors, since other parts of the module expect the - // original function name. - if (LTOMode == LTOK_UnifiedRegular) + if (LTOMode == LTOK_UnifiedRegular) { + // cfi.functions metadata is intended to be used with ThinLTO and may + // trigger invalid IR transformations if they are present when doing regular + // LTO, so delete it. if (NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions")) M.eraseNamedMetadata(CfiFunctionsMD); + } else if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) { + // Delete aliases entries for non-prevailing symbols on the ThinLTO side of + // this input file. + DenseSet Prevailing; + for (auto [I, R] : zip(Input.symbols(), Res)) + if (R.Prevailing && !I.getIRName().empty()) + Prevailing.insert(I.getIRName()); + std::vector AliasGroups; + for (MDNode *AliasGroup : AliasesMD->operands()) { + std::vector Aliases; + for (Metadata *Alias : AliasGroup->operands()) { + if (isa(Alias) && + Prevailing.count(cast(Alias)->getString())) + Aliases.push_back(Alias); + } + if (Aliases.size() > 1) + AliasGroups.push_back(MDTuple::get(RegularLTO.Ctx, Aliases)); + } + AliasesMD->clearOperands(); + for (MDNode *G : AliasGroups) + AliasesMD->addOperand(G); + } UpgradeDebugInfo(M); -- cgit v1.1