diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -503,14 +503,9 @@ SectionChunk *leaderChunk = nullptr; COMDATType leaderSelection = IMAGE_COMDAT_SELECT_ANY; - if (leader->data) { - leaderChunk = leader->getChunk(); - leaderSelection = leaderChunk->selection; - } else { - // FIXME: comdats from LTO files don't know their selection; treat them - // as "any". - selection = leaderSelection; - } + assert(leader->data && "Comdat leader without SectionChunk?"); + leaderChunk = leader->getChunk(); + leaderSelection = leaderChunk->selection; if ((selection == IMAGE_COMDAT_SELECT_ANY && leaderSelection == IMAGE_COMDAT_SELECT_LARGEST) || @@ -1051,10 +1046,22 @@ coff_section section; }; +// Convenience class for initializing a SectionChunk with specific flags. +class FakeSectionChunk { +public: + FakeSectionChunk(const coff_section *section) : chunk(nullptr, section) { + // FIXME: comdats from LTO files don't know their selection; treat them + // as "any". + chunk.selection = IMAGE_COMDAT_SELECT_ANY; + } + + SectionChunk chunk; +}; + FakeSection ltoTextSection(IMAGE_SCN_MEM_EXECUTE); FakeSection ltoDataSection(IMAGE_SCN_CNT_INITIALIZED_DATA); -SectionChunk ltoTextSectionChunk(nullptr, <oTextSection.section); -SectionChunk ltoDataSectionChunk(nullptr, <oDataSection.section); +FakeSectionChunk ltoTextSectionChunk(<oTextSection.section); +FakeSectionChunk ltoDataSectionChunk(<oDataSection.section); } // namespace void BitcodeFile::parse() { @@ -1069,9 +1076,9 @@ Symbol *sym; SectionChunk *fakeSC = nullptr; if (objSym.isExecutable()) - fakeSC = <oTextSectionChunk; + fakeSC = <oTextSectionChunk.chunk; else - fakeSC = <oDataSectionChunk; + fakeSC = <oDataSectionChunk.chunk; if (objSym.isUndefined()) { sym = symtab->addUndefined(symName, this, false); } else if (objSym.isCommon()) { @@ -1083,12 +1090,15 @@ Symbol *alias = symtab->addUndefined(saver.save(fallback)); checkAndSetWeakAlias(symtab, this, sym, alias); } else if (comdatIndex != -1) { - if (symName == obj->getComdatTable()[comdatIndex]) + if (symName == obj->getComdatTable()[comdatIndex]) { sym = comdat[comdatIndex].first; - else if (comdat[comdatIndex].second) + if (cast(sym)->data == nullptr) + cast(sym)->data = &fakeSC->repl; + } else if (comdat[comdatIndex].second) { sym = symtab->addRegular(this, symName, nullptr, fakeSC); - else + } else { sym = symtab->addUndefined(symName, this, false); + } } else { sym = symtab->addRegular(this, symName, nullptr, fakeSC); } diff --git a/lld/test/COFF/export-all-lto.ll b/lld/test/COFF/export-all-lto.ll --- a/lld/test/COFF/export-all-lto.ll +++ b/lld/test/COFF/export-all-lto.ll @@ -6,18 +6,28 @@ ; RUN: llvm-readobj --coff-exports %t.dll | grep Name: | FileCheck %s ; RUN: cat %t.def | FileCheck --check-prefix=IMPLIB %s +; CHECK: Name: MyComdatFunc ; CHECK: Name: MyExtData ; CHECK: Name: MyLibFunc -; IMPLIB: MyExtData @1 DATA -; IMPLIB: MyLibFunc @2{{$}} +; IMPLIB: MyComdatFunc @1{{$}} +; IMPLIB: MyExtData @2 DATA +; IMPLIB: MyLibFunc @3{{$}} target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-w64-windows-gnu" @MyExtData = dso_local global i32 42, align 4 +$MyComdatFunc = comdat any + define dso_local void @MyLibFunc() { +entry: + call void @MyComdatFunc() + ret void +} + +define linkonce_odr void @MyComdatFunc() comdat { entry: ret void }