aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/LTO/LTO.cpp
diff options
context:
space:
mode:
authorTeresa Johnson <tejohnson@google.com>2017-06-30 14:03:24 +0000
committerTeresa Johnson <tejohnson@google.com>2017-06-30 14:03:24 +0000
commitb247ffbaed52c4518b8bd688a9716ba21f5513ca (patch)
tree477988f624fd143b6586ef2fffecc69dceec05f0 /llvm/lib/LTO/LTO.cpp
parent7b6097ce737a17d69e14ec9203b2b6eb0db3e57c (diff)
downloadllvm-b247ffbaed52c4518b8bd688a9716ba21f5513ca.zip
llvm-b247ffbaed52c4518b8bd688a9716ba21f5513ca.tar.gz
llvm-b247ffbaed52c4518b8bd688a9716ba21f5513ca.tar.bz2
[LTO] Remove values from non-prevailing comdats
Summary: When linking a regular LTO module, if it has any non-prevailing values (dropped to available_externally) in comdats, we need to do more than just remove those values from their comdat. We also remove all values from that comdat, so as to avoid leaving an incomplete comdat. This is necessary in case we are compiling in mixed regular and ThinLTO mode, since the resulting regularLTO native object is always linked into the final binary first. We need to prevent the linker from selecting an incomplete comdat that was not the prevailing copy. Fixes PR32980. Reviewers: pcc, rafael Subscribers: mehdi_amini, david2050, llvm-commits, inglorion Differential Revision: https://reviews.llvm.org/D34803 llvm-svn: 306826
Diffstat (limited to 'llvm/lib/LTO/LTO.cpp')
-rw-r--r--llvm/lib/LTO/LTO.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 35032fd..3587c00 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -472,6 +472,36 @@ Error LTO::addModule(InputFile &Input, unsigned ModI,
return Error::success();
}
+// Checks whether the given global value is in a non-prevailing comdat
+// (comdat containing values the linker indicated were not prevailing,
+// which we then dropped to available_externally), and if so, removes
+// it from the comdat. This is called for all global values to ensure the
+// comdat is empty rather than leaving an incomplete comdat. It is needed for
+// regular LTO modules, in case we are in a mixed-LTO mode (both regular
+// and thin LTO modules) compilation. Since the regular LTO module will be
+// linked first in the final native link, we want to make sure the linker
+// doesn't select any of these incomplete comdats that would be left
+// in the regular LTO module without this cleanup.
+static void
+handleNonPrevailingComdat(GlobalValue &GV,
+ std::set<const Comdat *> &NonPrevailingComdats) {
+ Comdat *C = GV.getComdat();
+ if (!C)
+ return;
+
+ if (!NonPrevailingComdats.count(C))
+ return;
+
+ // Additionally need to drop externally visible global values from the comdat
+ // to available_externally, so that there aren't multiply defined linker
+ // errors.
+ if (!GV.hasLocalLinkage())
+ GV.setLinkage(GlobalValue::AvailableExternallyLinkage);
+
+ if (auto GO = dyn_cast<GlobalObject>(&GV))
+ GO->setComdat(nullptr);
+}
+
// Add a regular LTO object to the link.
// The resulting module needs to be linked into the combined LTO module with
// linkRegularLTO.
@@ -523,6 +553,7 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
};
Skip();
+ std::set<const Comdat *> NonPrevailingComdats;
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
@@ -557,6 +588,8 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
// module (in linkRegularLTO), based on whether it is undefined.
Mod.Keep.push_back(GV);
GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
+ if (GV->hasComdat())
+ NonPrevailingComdats.insert(GV->getComdat());
cast<GlobalObject>(GV)->setComdat(nullptr);
}
}
@@ -574,6 +607,9 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
// FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
}
+ if (!M.getComdatSymbolTable().empty())
+ for (GlobalValue &GV : M.global_values())
+ handleNonPrevailingComdat(GV, NonPrevailingComdats);
assert(MsymI == MsymE);
return std::move(Mod);
}