From 6c4846227609423e2a0922a5cefe3aac11cf2ee9 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 21 Nov 2017 22:06:20 +0000 Subject: [PATCH] Object: Improve COFF irsymtab comdat representation. Change the representation of COFF comdats so that a COFF linker is able to accurately resolve comdats between IR and native object files. Specifically, apply name mangling to comdat names consistently with native object files, and do not export comdats with an internal leader because they do not affect symbol resolution. Differential Revision: https://reviews.llvm.org/D40278 llvm-svn: 318805 --- llvm/lib/Object/IRSymtab.cpp | 45 ++++++++++++++++++++------ llvm/test/LTO/Resolution/X86/symtab.ll | 25 +++++++++++--- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp index 7fc84e2046cd7..2d8d3f7c08780 100644 --- a/llvm/lib/Object/IRSymtab.cpp +++ b/llvm/lib/Object/IRSymtab.cpp @@ -72,7 +72,7 @@ struct Builder { BumpPtrAllocator &Alloc) : Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc) {} - DenseMap ComdatMap; + DenseMap ComdatMap; Mangler Mang; Triple TT; @@ -97,6 +97,8 @@ struct Builder { reinterpret_cast(Objs.data() + Objs.size())); } + Expected getComdatIndex(const Comdat *C, const Module *M); + Error addModule(Module *M); Error addSymbol(const ModuleSymbolTable &Msymtab, const SmallPtrSet &Used, @@ -140,6 +142,35 @@ Error Builder::addModule(Module *M) { return Error::success(); } +Expected Builder::getComdatIndex(const Comdat *C, const Module *M) { + auto P = ComdatMap.insert(std::make_pair(C, Comdats.size())); + if (P.second) { + std::string Name; + if (TT.isOSBinFormatCOFF()) { + const GlobalValue *GV = M->getNamedValue(C->getName()); + if (!GV) + return make_error("Could not find leader", + inconvertibleErrorCode()); + // Internal leaders do not affect symbol resolution, therefore they do not + // appear in the symbol table. + if (GV->hasLocalLinkage()) { + P.first->second = -1; + return -1; + } + llvm::raw_string_ostream OS(Name); + Mang.getNameWithPrefix(OS, GV, false); + } else { + Name = C->getName(); + } + + storage::Comdat Comdat; + setStr(Comdat.Name, Saver.save(Name)); + Comdats.push_back(Comdat); + } + + return P.first->second; +} + Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, const SmallPtrSet &Used, ModuleSymbolTable::Symbol Msym) { @@ -216,14 +247,10 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, return make_error("Unable to determine comdat of alias!", inconvertibleErrorCode()); if (const Comdat *C = Base->getComdat()) { - auto P = ComdatMap.insert(std::make_pair(C, Comdats.size())); - Sym.ComdatIndex = P.first->second; - - if (P.second) { - storage::Comdat Comdat; - setStr(Comdat.Name, C->getName()); - Comdats.push_back(Comdat); - } + Expected ComdatIndexOrErr = getComdatIndex(C, GV->getParent()); + if (!ComdatIndexOrErr) + return ComdatIndexOrErr.takeError(); + Sym.ComdatIndex = *ComdatIndexOrErr; } if (TT.isOSBinFormatCOFF()) { diff --git a/llvm/test/LTO/Resolution/X86/symtab.ll b/llvm/test/LTO/Resolution/X86/symtab.ll index fecea0a1e7b47..c43494a5b7e03 100644 --- a/llvm/test/LTO/Resolution/X86/symtab.ll +++ b/llvm/test/LTO/Resolution/X86/symtab.ll @@ -17,6 +17,15 @@ define i32 @fun() { ret i32 0 } +; CHECK: D------X @fun2@8 +; CHECK-NEXT: comdat @fun2@8 +$fun2 = comdat any +define x86_fastcallcc i32 @fun2(i32 inreg %a, i32 inreg %b) comdat { +entry: + %add = add nsw i32 %b, %a + ret i32 %add +} + ; CHECK: H------- _g1 @g1 = hidden global i32 0 @@ -43,11 +52,19 @@ define i32 @fun() { @g8 = common global i32 0, align 8 ; CHECK: D------- _g9 -; CHECK-NEXT: comdat g9 +; CHECK-NEXT: comdat _g9 $g9 = comdat any @g9 = global i32 0, comdat -; CHECK: D--WI--- _g10 -; CHECK-NEXT: comdat g9 +; CHECK-NOT: _g10 +$g10 = comdat any +@g10 = internal global i32 0, comdat + +; CHECK: D------- _g11 +; CHECK-NOT: comdat +@g11 = global i32 0, comdat($g10) + +; CHECK: D--WI--- _a1 +; CHECK-NEXT: comdat _g9 ; CHECK-NEXT: fallback _g9 -@g10 = weak alias i32, i32* @g9 +@a1 = weak alias i32, i32* @g9