Index: lib/Linker/LinkModules.cpp =================================================================== --- lib/Linker/LinkModules.cpp +++ lib/Linker/LinkModules.cpp @@ -102,6 +102,9 @@ return DGV; } + void dropReplacedComdat(GlobalValue &GV, + const DenseSet &ReplacedDstComdats); + bool linkIfNeeded(GlobalValue &GV); /// Helper method to check if we are importing from the current source @@ -449,6 +452,38 @@ } } +// Drop GV if it is a member of a comdat that we are dropping. This can happen +// with COFF's largest selection kind. +void ModuleLinker::dropReplacedComdat( + GlobalValue &GV, const DenseSet &ReplacedDstComdats) { + Comdat *C = GV.getComdat(); + if (!C) + return; + if (!ReplacedDstComdats.count(C)) + return; + if (GV.use_empty()) { + GV.eraseFromParent(); + return; + } + + if (auto *F = dyn_cast(&GV)) { + F->deleteBody(); + } else if (auto *Var = dyn_cast(&GV)) { + Var->setInitializer(nullptr); + } else { + auto &Alias = cast(GV); + Module &M = *Alias.getParent(); + PointerType &Ty = *cast(Alias.getType()); + GlobalValue::LinkageTypes L = Alias.getLinkage(); + GlobalValue *Declaration = + new GlobalVariable(M, Ty.getElementType(), /*isConstant*/ false, L, + /*Initializer*/ nullptr); + Declaration->takeName(&Alias); + Alias.replaceAllUsesWith(Declaration); + Alias.eraseFromParent(); + } +} + bool ModuleLinker::run() { for (const auto &SMEC : SrcM->getComdatSymbolTable()) { const Comdat &C = SMEC.getValue(); @@ -461,6 +496,40 @@ ComdatsChosen[&C] = std::make_pair(SK, LinkFromSrc); } + Module &DstM = Mover.getModule(); + DenseSet ReplacedDstComdats; + for (auto &P : ComdatsChosen) { + const Comdat *C = P.first; + bool LinkFromSource = P.second.second; + if (!LinkFromSource) + continue; + + Module::ComdatSymTabType &ComdatSymTab = DstM.getComdatSymbolTable(); + StringRef ComdatName = C->getName(); + Module::ComdatSymTabType::iterator DstCI = ComdatSymTab.find(ComdatName); + if (DstCI == ComdatSymTab.end()) + continue; + + // The source comdat is replacing the dest one. + const Comdat *DstC = &DstCI->second; + ReplacedDstComdats.insert(DstC); + } + + for (auto I = DstM.global_begin(), E = DstM.global_end(); I != E;) { + GlobalVariable &GV = *I++; + dropReplacedComdat(GV, ReplacedDstComdats); + } + + for (auto I = DstM.begin(), E = DstM.end(); I != E;) { + Function &GV = *I++; + dropReplacedComdat(GV, ReplacedDstComdats); + } + + for (auto I = DstM.alias_begin(), E = DstM.alias_end(); I != E;) { + GlobalAlias &GV = *I++; + dropReplacedComdat(GV, ReplacedDstComdats); + } + for (GlobalVariable &GV : SrcM->globals()) if (const Comdat *SC = GV.getComdat()) ComdatMembers[SC].push_back(&GV); @@ -507,7 +576,6 @@ }, ValIDToTempMDMap, false)) return true; - Module &DstM = Mover.getModule(); for (auto &P : Internalize) { GlobalValue *GV = DstM.getNamedValue(P.first()); GV->setLinkage(GlobalValue::InternalLinkage); Index: test/Linker/Inputs/comdat-rm-dst.ll =================================================================== --- /dev/null +++ test/Linker/Inputs/comdat-rm-dst.ll @@ -0,0 +1,5 @@ +target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32" +target triple = "i686-pc-windows-msvc" + +$foo = comdat largest +@foo = global i64 43, comdat Index: test/Linker/comdat-rm-dst.ll =================================================================== --- /dev/null +++ test/Linker/comdat-rm-dst.ll @@ -0,0 +1,21 @@ +; RUN: llvm-link -S -o %t %s %p/Inputs/comdat-rm-dst.ll +; RUN: FileCheck %s < %t +; RUN: FileCheck --check-prefix=RM %s < %t + +target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32" +target triple = "i686-pc-windows-msvc" + +$foo = comdat largest +@foo = global i32 42, comdat +; CHECK: @foo = global i64 43, comdat + +; RM-NOT: ailas +@alias = alias i32, i32* @foo + +; RM-NOT: func +define void @func() comdat($foo) { + ret void +} + +; RM-NOT: var +@var = global i32 42, comdat($foo)