aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/LTO/LTO.cpp
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2017-03-31 02:44:50 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2017-03-31 02:44:50 +0000
commitf10698b94035d8c608f92219f63f3bd48549bac4 (patch)
tree75f2f051a9f27e4b1f61756e7247d902a63d7155 /llvm/lib/LTO/LTO.cpp
parentae9c74280c6def98fad4d4147163f13250d6cb4f (diff)
downloadllvm-f10698b94035d8c608f92219f63f3bd48549bac4.zip
llvm-f10698b94035d8c608f92219f63f3bd48549bac4.tar.gz
llvm-f10698b94035d8c608f92219f63f3bd48549bac4.tar.bz2
Revert r299168 and r299169 due to library dependency issues.
http://bb.pgr.jp/builders/i686-mingw32-RA-on-linux/builds/25073/steps/build_llvmclang/logs/stdio llvm-svn: 299171
Diffstat (limited to 'llvm/lib/LTO/LTO.cpp')
-rw-r--r--llvm/lib/LTO/LTO.cpp212
1 files changed, 127 insertions, 85 deletions
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 4885f65..f3d258e 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -305,6 +305,14 @@ void llvm::thinLTOInternalizeAndPromoteInIndex(
thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
}
+struct InputFile::InputModule {
+ BitcodeModule BM;
+ std::unique_ptr<Module> Mod;
+
+ // The range of ModuleSymbolTable entries for this input module.
+ size_t SymBegin, SymEnd;
+};
+
// Requires a destructor for std::vector<InputModule>.
InputFile::~InputFile() = default;
@@ -325,51 +333,87 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
return make_error<StringError>("Bitcode file does not contain any modules",
inconvertibleErrorCode());
- File->Mods = *BMsOrErr;
-
- LLVMContext Ctx;
- std::vector<Module *> Mods;
- std::vector<std::unique_ptr<Module>> OwnedMods;
+ // Create an InputModule for each module in the InputFile, and add it to the
+ // ModuleSymbolTable.
for (auto BM : *BMsOrErr) {
Expected<std::unique_ptr<Module>> MOrErr =
- BM.getLazyModule(Ctx, /*ShouldLazyLoadMetadata*/ true,
+ BM.getLazyModule(File->Ctx, /*ShouldLazyLoadMetadata*/ true,
/*IsImporting*/ false);
if (!MOrErr)
return MOrErr.takeError();
- if ((*MOrErr)->getDataLayoutStr().empty())
- return make_error<StringError>("input module has no datalayout",
- inconvertibleErrorCode());
+ size_t SymBegin = File->SymTab.symbols().size();
+ File->SymTab.addModule(MOrErr->get());
+ size_t SymEnd = File->SymTab.symbols().size();
- Mods.push_back(MOrErr->get());
- OwnedMods.push_back(std::move(*MOrErr));
- }
+ for (const auto &C : (*MOrErr)->getComdatSymbolTable()) {
+ auto P = File->ComdatMap.insert(
+ std::make_pair(&C.second, File->Comdats.size()));
+ assert(P.second);
+ (void)P;
+ File->Comdats.push_back(C.first());
+ }
- SmallVector<char, 0> Symtab;
- if (Error E = irsymtab::build(Mods, Symtab, File->Strtab))
- return std::move(E);
-
- irsymtab::Reader R({Symtab.data(), Symtab.size()},
- {File->Strtab.data(), File->Strtab.size()});
- File->SourceFileName = R.getSourceFileName();
- File->COFFLinkerOpts = R.getCOFFLinkerOpts();
- File->ComdatTable = R.getComdatTable();
-
- for (unsigned I = 0; I != Mods.size(); ++I) {
- size_t Begin = File->Symbols.size();
- for (const irsymtab::Reader::SymbolRef &Sym : R.module_symbols(I))
- // Skip symbols that are irrelevant to LTO. Note that this condition needs
- // to match the one in Skip() in LTO::addRegularLTO().
- if (Sym.isGlobal() && !Sym.isFormatSpecific())
- File->Symbols.push_back(Sym);
- File->ModuleSymIndices.push_back({Begin, File->Symbols.size()});
+ File->Mods.push_back({BM, std::move(*MOrErr), SymBegin, SymEnd});
}
return std::move(File);
}
+Expected<int> InputFile::Symbol::getComdatIndex() const {
+ if (!isGV())
+ return -1;
+ const GlobalObject *GO = getGV()->getBaseObject();
+ if (!GO)
+ return make_error<StringError>("Unable to determine comdat of alias!",
+ inconvertibleErrorCode());
+ if (const Comdat *C = GO->getComdat()) {
+ auto I = File->ComdatMap.find(C);
+ assert(I != File->ComdatMap.end());
+ return I->second;
+ }
+ return -1;
+}
+
+Expected<std::string> InputFile::getLinkerOpts() {
+ std::string LinkerOpts;
+ raw_string_ostream LOS(LinkerOpts);
+ // Extract linker options from module metadata.
+ for (InputModule &Mod : Mods) {
+ std::unique_ptr<Module> &M = Mod.Mod;
+ if (auto E = M->materializeMetadata())
+ return std::move(E);
+ if (Metadata *Val = M->getModuleFlag("Linker Options")) {
+ MDNode *LinkerOptions = cast<MDNode>(Val);
+ for (const MDOperand &MDOptions : LinkerOptions->operands())
+ for (const MDOperand &MDOption : cast<MDNode>(MDOptions)->operands())
+ LOS << " " << cast<MDString>(MDOption)->getString();
+ }
+ }
+
+ // Synthesize export flags for symbols with dllexport storage.
+ const Triple TT(Mods[0].Mod->getTargetTriple());
+ Mangler M;
+ for (const ModuleSymbolTable::Symbol &Sym : SymTab.symbols())
+ if (auto *GV = Sym.dyn_cast<GlobalValue*>())
+ emitLinkerFlagsForGlobalCOFF(LOS, GV, TT, M);
+ LOS.flush();
+ return LinkerOpts;
+}
+
StringRef InputFile::getName() const {
- return Mods[0].getModuleIdentifier();
+ return Mods[0].BM.getModuleIdentifier();
+}
+
+StringRef InputFile::getSourceFileName() const {
+ return Mods[0].Mod->getSourceFileName();
+}
+
+iterator_range<InputFile::symbol_iterator>
+InputFile::module_symbols(InputModule &IM) {
+ return llvm::make_range(
+ symbol_iterator(SymTab.symbols().data() + IM.SymBegin, SymTab, this),
+ symbol_iterator(SymTab.symbols().data() + IM.SymEnd, SymTab, this));
}
LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
@@ -393,17 +437,21 @@ LTO::LTO(Config Conf, ThinBackend Backend,
LTO::~LTO() = default;
// Add the given symbol to the GlobalResolutions map, and resolve its partition.
-void LTO::addSymbolToGlobalRes(const InputFile::Symbol &Sym,
+void LTO::addSymbolToGlobalRes(SmallPtrSet<GlobalValue *, 8> &Used,
+ const InputFile::Symbol &Sym,
SymbolResolution Res, unsigned Partition) {
- auto &GlobalRes = GlobalResolutions[Sym.getName()];
- GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
- if (Res.Prevailing)
- GlobalRes.IRName = Sym.getIRName();
+ GlobalValue *GV = Sym.isGV() ? Sym.getGV() : nullptr;
+ auto &GlobalRes = GlobalResolutions[Sym.getName()];
+ if (GV) {
+ GlobalRes.UnnamedAddr &= GV->hasGlobalUnnamedAddr();
+ if (Res.Prevailing)
+ GlobalRes.IRName = GV->getName();
+ }
// Set the partition to external if we know it is used elsewhere, e.g.
// it is visible to a regular object, is referenced from llvm.compiler_used,
// or was already recorded as being referenced from a different partition.
- if (Res.VisibleToRegularObj || Sym.isUsed() ||
+ if (Res.VisibleToRegularObj || (GV && Used.count(GV)) ||
(GlobalRes.Partition != GlobalResolution::Unknown &&
GlobalRes.Partition != Partition)) {
GlobalRes.Partition = GlobalResolution::External;
@@ -447,32 +495,41 @@ Error LTO::add(std::unique_ptr<InputFile> Input,
writeToResolutionFile(*Conf.ResolutionFile, Input.get(), Res);
const SymbolResolution *ResI = Res.begin();
- for (unsigned I = 0; I != Input->Mods.size(); ++I)
- if (Error Err = addModule(*Input, I, ResI, Res.end()))
+ for (InputFile::InputModule &IM : Input->Mods)
+ if (Error Err = addModule(*Input, IM, ResI, Res.end()))
return Err;
assert(ResI == Res.end());
return Error::success();
}
-Error LTO::addModule(InputFile &Input, unsigned ModI,
+Error LTO::addModule(InputFile &Input, InputFile::InputModule &IM,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
- Expected<bool> HasThinLTOSummary = Input.Mods[ModI].hasSummary();
+ // FIXME: move to backend
+ Module &M = *IM.Mod;
+
+ if (M.getDataLayoutStr().empty())
+ return make_error<StringError>("input module has no datalayout",
+ inconvertibleErrorCode());
+
+ if (!Conf.OverrideTriple.empty())
+ M.setTargetTriple(Conf.OverrideTriple);
+ else if (M.getTargetTriple().empty())
+ M.setTargetTriple(Conf.DefaultTriple);
+
+ Expected<bool> HasThinLTOSummary = IM.BM.hasSummary();
if (!HasThinLTOSummary)
return HasThinLTOSummary.takeError();
- auto ModSyms = Input.module_symbols(ModI);
if (*HasThinLTOSummary)
- return addThinLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
+ return addThinLTO(IM.BM, M, Input.module_symbols(IM), ResI, ResE);
else
- return addRegularLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
+ return addRegularLTO(IM.BM, ResI, ResE);
}
// Add a regular LTO object to the link.
-Error LTO::addRegularLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
- const SymbolResolution *&ResI,
+Error LTO::addRegularLTO(BitcodeModule BM, const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
if (!RegularLTO.CombinedModule) {
RegularLTO.CombinedModule =
@@ -493,6 +550,9 @@ Error LTO::addRegularLTO(BitcodeModule BM,
ModuleSymbolTable SymTab;
SymTab.addModule(&M);
+ SmallPtrSet<GlobalValue *, 8> Used;
+ collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
+
std::vector<GlobalValue *> Keep;
for (GlobalVariable &GV : M.globals())
@@ -504,35 +564,17 @@ Error LTO::addRegularLTO(BitcodeModule BM,
if (GlobalObject *GO = GA.getBaseObject())
AliasedGlobals.insert(GO);
- // In this function we need IR GlobalValues matching the symbols in Syms
- // (which is not backed by a module), so we need to enumerate them in the same
- // order. The symbol enumeration order of a ModuleSymbolTable intentionally
- // matches the order of an irsymtab, but when we read the irsymtab in
- // InputFile::create we omit some symbols that are irrelevant to LTO. The
- // Skip() function skips the same symbols from the module as InputFile does
- // from the symbol table.
- auto MsymI = SymTab.symbols().begin(), MsymE = SymTab.symbols().end();
- auto Skip = [&]() {
- while (MsymI != MsymE) {
- auto Flags = SymTab.getSymbolFlags(*MsymI);
- if ((Flags & object::BasicSymbolRef::SF_Global) &&
- !(Flags & object::BasicSymbolRef::SF_FormatSpecific))
- return;
- ++MsymI;
- }
- };
- Skip();
-
- for (const InputFile::Symbol &Sym : Syms) {
+ for (const InputFile::Symbol &Sym :
+ make_range(InputFile::symbol_iterator(SymTab.symbols().begin(), SymTab,
+ nullptr),
+ InputFile::symbol_iterator(SymTab.symbols().end(), SymTab,
+ nullptr))) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Sym, Res, 0);
+ addSymbolToGlobalRes(Used, Sym, Res, 0);
- assert(MsymI != MsymE);
- ModuleSymbolTable::Symbol Msym = *MsymI++;
- Skip();
-
- if (GlobalValue *GV = Msym.dyn_cast<GlobalValue *>()) {
+ if (Sym.isGV()) {
+ GlobalValue *GV = Sym.getGV();
if (Res.Prevailing) {
if (Sym.isUndefined())
continue;
@@ -570,7 +612,7 @@ Error LTO::addRegularLTO(BitcodeModule BM,
if (Sym.isCommon()) {
// FIXME: We should figure out what to do about commons defined by asm.
// For now they aren't reported correctly by ModuleSymbolTable.
- auto &CommonRes = RegularLTO.Commons[Sym.getIRName()];
+ auto &CommonRes = RegularLTO.Commons[Sym.getGV()->getName()];
CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize());
CommonRes.Align = std::max(CommonRes.Align, Sym.getCommonAlignment());
CommonRes.Prevailing |= Res.Prevailing;
@@ -578,7 +620,6 @@ Error LTO::addRegularLTO(BitcodeModule BM,
// FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
}
- assert(MsymI == MsymE);
return RegularLTO.Mover->move(std::move(*MOrErr), Keep,
[](GlobalValue &, IRMover::ValueAdder) {},
@@ -586,10 +627,15 @@ Error LTO::addRegularLTO(BitcodeModule BM,
}
// Add a ThinLTO object to the link.
-Error LTO::addThinLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
+// FIXME: This function should not need to take as many parameters once we have
+// a bitcode symbol table.
+Error LTO::addThinLTO(BitcodeModule BM, Module &M,
+ iterator_range<InputFile::symbol_iterator> Syms,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
+ SmallPtrSet<GlobalValue *, 8> Used;
+ collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
+
Expected<std::unique_ptr<ModuleSummaryIndex>> SummaryOrErr = BM.getSummary();
if (!SummaryOrErr)
return SummaryOrErr.takeError();
@@ -599,15 +645,11 @@ Error LTO::addThinLTO(BitcodeModule BM,
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Sym, Res, ThinLTO.ModuleMap.size() + 1);
+ addSymbolToGlobalRes(Used, Sym, Res, ThinLTO.ModuleMap.size() + 1);
- if (Res.Prevailing) {
- if (!Sym.getIRName().empty()) {
- auto GUID = GlobalValue::getGUID(GlobalValue::getGlobalIdentifier(
- Sym.getIRName(), GlobalValue::ExternalLinkage, ""));
- ThinLTO.PrevailingModuleForGUID[GUID] = BM.getModuleIdentifier();
- }
- }
+ if (Res.Prevailing && Sym.isGV())
+ ThinLTO.PrevailingModuleForGUID[Sym.getGV()->getGUID()] =
+ BM.getModuleIdentifier();
}
if (!ThinLTO.ModuleMap.insert({BM.getModuleIdentifier(), BM}).second)