From 53544fc15f08687c14becced4ecc22c2356265cd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 11 Dec 2024 08:55:05 -0800 Subject: [PATCH] [ELF] Respect ltoCanOmit for symbols in non-prevailing COMDAT A linkonce_odr definition can be omitted in LTO compilation if `canBeOmittedFromSymbolTable()` is true in all bitcode files. Currently, we don't respect the `canBeOmittedFromSymbolTable()` bit from symbols in a non-prevailing COMDAT, which could lead to incorrect omission of a definition when merging a prevailing linkonce_odr and a non-prevailing weak_odr, e.g. an implicit template instantiation and an explicit template instantiation. To fix #111341, allow the non-prevailing COMDAT code path to clear the `ltoCanOmit` bit, so that `VisibleToRegularObj` could be false in LTO.cpp. We could resolve either an Undefined or a Defined. For simplicity, just use a Defined like the prevailing case (similar to how we resolve symbols in ObjectFile COMDAT reviews.llvm.org/D120626). Pull Request: https://github.com/llvm/llvm-project/pull/119332 --- lld/ELF/InputFiles.cpp | 8 +++----- lld/test/ELF/lto/internalize-exportdyn.ll | 7 +++++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 2084fcfd4d651..c44773d0b7dab 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1709,7 +1709,6 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) { } static void createBitcodeSymbol(Ctx &ctx, Symbol *&sym, - const std::vector &keptComdats, const lto::InputFile::Symbol &objSym, BitcodeFile &f) { uint8_t binding = objSym.isWeak() ? STB_WEAK : STB_GLOBAL; @@ -1726,8 +1725,7 @@ static void createBitcodeSymbol(Ctx &ctx, Symbol *&sym, sym = ctx.symtab->insert(objSym.getName()); } - int c = objSym.getComdatIndex(); - if (objSym.isUndefined() || (c != -1 && !keptComdats[c])) { + if (objSym.isUndefined()) { Undefined newSym(&f, StringRef(), binding, visibility, type); sym->resolve(ctx, newSym); sym->referenced = true; @@ -1766,10 +1764,10 @@ void BitcodeFile::parse() { // ObjFile::initializeSymbols. for (auto [i, irSym] : llvm::enumerate(obj->symbols())) if (!irSym.isUndefined()) - createBitcodeSymbol(ctx, symbols[i], keptComdats, irSym, *this); + createBitcodeSymbol(ctx, symbols[i], irSym, *this); for (auto [i, irSym] : llvm::enumerate(obj->symbols())) if (irSym.isUndefined()) - createBitcodeSymbol(ctx, symbols[i], keptComdats, irSym, *this); + createBitcodeSymbol(ctx, symbols[i], irSym, *this); for (auto l : obj->getDependentLibraries()) addDependentLibrary(ctx, l, this); diff --git a/lld/test/ELF/lto/internalize-exportdyn.ll b/lld/test/ELF/lto/internalize-exportdyn.ll index 7c670a548025f..25e319269bbdb 100644 --- a/lld/test/ELF/lto/internalize-exportdyn.ll +++ b/lld/test/ELF/lto/internalize-exportdyn.ll @@ -56,16 +56,19 @@ define linkonce_odr void @baz() { @use_baz = global ptr @baz +;; Test comdat symbols that are prevailing in this module and non-prevailing in the other module. define void @ext_and_ext() local_unnamed_addr comdat { call void @foo(i64 1) ret void } +;; linkonce_odr in this module and external in the other module. define linkonce_odr void @lo_and_ext() local_unnamed_addr comdat { call void @foo(i64 1) ret void } +;; linkonce_odr in this module and weak_odr in the other module. define linkonce_odr void @lo_and_wo() local_unnamed_addr comdat { ret void } @@ -92,7 +95,7 @@ define weak_odr void @wo_and_lo() local_unnamed_addr comdat { ; CHECK-NEXT: call void @foo(i64 1) ; CHECK: define internal void @lo_and_ext() comdat ; CHECK-NEXT: call void @foo(i64 1) -; CHECK: define internal void @lo_and_wo() comdat +; CHECK: define weak_odr dso_local void @lo_and_wo() comdat ; CHECK: define weak_odr dso_local void @wo_and_lo() comdat ; DSO: @c = weak_odr constant i32 1 @@ -110,7 +113,7 @@ define weak_odr void @wo_and_lo() local_unnamed_addr comdat { ; DSO: define weak_odr void @baz() ; DSO: define void @ext_and_ext() comdat ; DSO: define internal void @lo_and_ext() comdat -; DSO: define internal void @lo_and_wo() comdat +; DSO: define weak_odr void @lo_and_wo() comdat ; DSO: define weak_odr void @wo_and_lo() comdat ;--- lib.s