X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FLinker%2FLinkModules.cpp;h=6ffa71e147790f9d410078181fb666f367bf6024;hb=18a86c95fc36b5f622e8dc87f71252de37a1ed44;hp=373bebd6d4fe8719218ea7942d6e3d28e8d84fb6;hpb=0e1a49a3ee3897eb147b4d30022a62c9f0b96080;p=oota-llvm.git diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 373bebd6d4f..6ffa71e1477 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -38,9 +38,9 @@ class ModuleLinker { /// importing/exporting handling. const FunctionInfoIndex *ImportIndex; - /// Function to import from source module, all other functions are + /// Functions to import from source module, all other functions are /// imported as declarations instead of definitions. - DenseSet *ImportFunction; + DenseSet *FunctionsToImport; /// Set to true if the given FunctionInfoIndex contains any functions /// from this source module, in which case we must conservatively assume @@ -65,9 +65,6 @@ class ModuleLinker { return Flags & Linker::InternalizeLinkedSymbols; } - /// Check if we should promote the given local value to global scope. - bool doPromoteLocalToGlobal(const GlobalValue *SGV); - bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest, const GlobalValue &Src); @@ -97,11 +94,11 @@ class ModuleLinker { Module &DstM = Mover.getModule(); // If the source has no name it can't link. If it has local linkage, // there is no name match-up going on. - if (!SrcGV->hasName() || GlobalValue::isLocalLinkage(getLinkage(SrcGV))) + if (!SrcGV->hasName() || GlobalValue::isLocalLinkage(SrcGV->getLinkage())) return nullptr; // Otherwise see if we have a match in the destination module's symtab. - GlobalValue *DGV = DstM.getNamedValue(getName(SrcGV)); + GlobalValue *DGV = DstM.getNamedValue(SrcGV->getName()); if (!DGV) return nullptr; @@ -116,9 +113,67 @@ class ModuleLinker { bool linkIfNeeded(GlobalValue &GV); + /// Helper method to check if we are importing from the current source + /// module. + bool isPerformingImport() const { return FunctionsToImport != nullptr; } + + /// If we are importing from the source module, checks if we should + /// import SGV as a definition, otherwise import as a declaration. + bool doImportAsDefinition(const GlobalValue *SGV); + +public: + ModuleLinker(IRMover &Mover, Module &SrcM, unsigned Flags, + const FunctionInfoIndex *Index = nullptr, + DenseSet *FunctionsToImport = nullptr, + DenseMap *ValIDToTempMDMap = nullptr) + : Mover(Mover), SrcM(SrcM), Flags(Flags), ImportIndex(Index), + FunctionsToImport(FunctionsToImport), + ValIDToTempMDMap(ValIDToTempMDMap) { + assert((ImportIndex || !FunctionsToImport) && + "Expect a FunctionInfoIndex when importing"); + // If we have a FunctionInfoIndex but no function to import, + // then this is the primary module being compiled in a ThinLTO + // backend compilation, and we need to see if it has functions that + // may be exported to another backend compilation. + if (ImportIndex && !FunctionsToImport) + HasExportedFunctions = ImportIndex->hasExportedFunctions(SrcM); + assert((ValIDToTempMDMap || !FunctionsToImport) && + "Function importing must provide a ValIDToTempMDMap"); + } + + bool run(); +}; + +/// Class to handle necessary GlobalValue changes required by ThinLTO including +/// linkage changes and any necessary renaming. +class ThinLTOGlobalProcessing { + /// The Module which we are exporting or importing functions from. + Module &M; + + /// Function index passed in for function importing/exporting handling. + const FunctionInfoIndex *ImportIndex; + + /// Functions to import from this module, all other functions will be + /// imported as declarations instead of definitions. + DenseSet *FunctionsToImport; + + /// Set to true if the given FunctionInfoIndex contains any functions + /// from this source module, in which case we must conservatively assume + /// that any of its functions may be imported into another module + /// as part of a different backend compilation process. + bool HasExportedFunctions = false; + + /// Populated during ThinLTO global processing with locals promoted + /// to global scope in an exporting module, which now need to be linked + /// in if calling from the ModuleLinker. + SetVector NewExportedValues; + + /// Check if we should promote the given local value to global scope. + bool doPromoteLocalToGlobal(const GlobalValue *SGV); + /// Helper methods to check if we are importing from or potentially /// exporting from the current source module. - bool isPerformingImport() const { return ImportFunction != nullptr; } + bool isPerformingImport() const { return FunctionsToImport != nullptr; } bool isModuleExporting() const { return HasExportedFunctions; } /// If we are importing from the source module, checks if we should @@ -143,31 +198,30 @@ class ModuleLinker { GlobalValue::LinkageTypes getLinkage(const GlobalValue *SGV); public: - ModuleLinker(IRMover &Mover, Module &SrcM, unsigned Flags, - const FunctionInfoIndex *Index = nullptr, - DenseSet *FunctionsToImport = nullptr, - DenseMap *ValIDToTempMDMap = nullptr) - : Mover(Mover), SrcM(SrcM), Flags(Flags), ImportIndex(Index), - ImportFunction(FunctionsToImport), ValIDToTempMDMap(ValIDToTempMDMap) { - assert((ImportIndex || !ImportFunction) && - "Expect a FunctionInfoIndex when importing"); + ThinLTOGlobalProcessing( + Module &M, const FunctionInfoIndex *Index, + DenseSet *FunctionsToImport = nullptr) + : M(M), ImportIndex(Index), FunctionsToImport(FunctionsToImport) { // If we have a FunctionInfoIndex but no function to import, // then this is the primary module being compiled in a ThinLTO // backend compilation, and we need to see if it has functions that // may be exported to another backend compilation. - if (ImportIndex && !ImportFunction) - HasExportedFunctions = ImportIndex->hasExportedFunctions(SrcM); - assert((ValIDToTempMDMap || !ImportFunction) && - "Function importing must provide a ValIDToTempMDMap"); + if (!FunctionsToImport) + HasExportedFunctions = ImportIndex->hasExportedFunctions(M); } bool run(); + + /// Access the promoted globals that are now exported and need to be linked. + SetVector &getNewExportedValues() { return NewExportedValues; } }; } -bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) { - if (!isPerformingImport()) - return false; +/// Checks if we should import SGV as a definition, otherwise import as a +/// declaration. +static bool +doImportAsDefinitionImpl(const GlobalValue *SGV, + DenseSet *FunctionsToImport) { auto *GA = dyn_cast(SGV); if (GA) { if (GA->hasWeakAnyLinkage()) @@ -175,7 +229,7 @@ bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) { const GlobalObject *GO = GA->getBaseObject(); if (!GO->hasLinkOnceODRLinkage()) return false; - return doImportAsDefinition(GO); + return doImportAsDefinitionImpl(GO, FunctionsToImport); } // Always import GlobalVariable definitions, except for the special // case of WeakAny which are imported as ExternalWeak declarations @@ -189,13 +243,25 @@ bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) { return true; // Only import the function requested for importing. auto *SF = dyn_cast(SGV); - if (SF && ImportFunction->count(SF)) + if (SF && FunctionsToImport->count(SF)) return true; // Otherwise no. return false; } -bool ModuleLinker::doPromoteLocalToGlobal(const GlobalValue *SGV) { +bool ThinLTOGlobalProcessing::doImportAsDefinition(const GlobalValue *SGV) { + if (!isPerformingImport()) + return false; + return doImportAsDefinitionImpl(SGV, FunctionsToImport); +} + +bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) { + if (!isPerformingImport()) + return false; + return doImportAsDefinitionImpl(SGV, FunctionsToImport); +} + +bool ThinLTOGlobalProcessing::doPromoteLocalToGlobal(const GlobalValue *SGV) { assert(SGV->hasLocalLinkage()); // Both the imported references and the original local variable must // be promoted. @@ -219,7 +285,7 @@ bool ModuleLinker::doPromoteLocalToGlobal(const GlobalValue *SGV) { return true; } -std::string ModuleLinker::getName(const GlobalValue *SGV) { +std::string ThinLTOGlobalProcessing::getName(const GlobalValue *SGV) { // For locals that must be promoted to global scope, ensure that // the promoted name uniquely identifies the copy in the original module, // using the ID assigned during combined index creation. When importing, @@ -233,7 +299,8 @@ std::string ModuleLinker::getName(const GlobalValue *SGV) { return SGV->getName(); } -GlobalValue::LinkageTypes ModuleLinker::getLinkage(const GlobalValue *SGV) { +GlobalValue::LinkageTypes +ThinLTOGlobalProcessing::getLinkage(const GlobalValue *SGV) { // Any local variable that is referenced by an exported function needs // to be promoted to global scope. Since we don't currently know which // functions reference which local variables/functions, we must treat @@ -297,8 +364,7 @@ GlobalValue::LinkageTypes ModuleLinker::getLinkage(const GlobalValue *SGV) { // since it would cause global constructors/destructors to be // executed multiple times. This should have already been handled // by linkIfNeeded, and we will assert in shouldLinkFromSource - // if we try to import, so we simply return AppendingLinkage here - // as this helper is called more widely in getLinkedToGlobal. + // if we try to import, so we simply return AppendingLinkage. return GlobalValue::AppendingLinkage; case GlobalValue::InternalLinkage: @@ -476,9 +542,9 @@ bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc, if (isPerformingImport()) { if (isa(&Src)) { - // For functions, LinkFromSrc iff this is the function requested + // For functions, LinkFromSrc iff this is a function requested // for importing. For variables, decide below normally. - LinkFromSrc = ImportFunction->count(&Src); + LinkFromSrc = FunctionsToImport->count(&Src); return false; } @@ -651,7 +717,7 @@ void ModuleLinker::addLazyFor(GlobalValue &GV, IRMover::ValueAdder Add) { } } -void ModuleLinker::processGlobalForThinLTO(GlobalValue &GV) { +void ThinLTOGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) { if (GV.hasLocalLinkage() && (doPromoteLocalToGlobal(&GV) || isPerformingImport())) { GV.setName(getName(&GV)); @@ -659,21 +725,26 @@ void ModuleLinker::processGlobalForThinLTO(GlobalValue &GV) { if (!GV.hasLocalLinkage()) GV.setVisibility(GlobalValue::HiddenVisibility); if (isModuleExporting()) - ValuesToLink.insert(&GV); + NewExportedValues.insert(&GV); return; } GV.setLinkage(getLinkage(&GV)); } -void ModuleLinker::processGlobalsForThinLTO() { - for (GlobalVariable &GV : SrcM.globals()) +void ThinLTOGlobalProcessing::processGlobalsForThinLTO() { + for (GlobalVariable &GV : M.globals()) processGlobalForThinLTO(GV); - for (Function &SF : SrcM) + for (Function &SF : M) processGlobalForThinLTO(SF); - for (GlobalAlias &GA : SrcM.aliases()) + for (GlobalAlias &GA : M.aliases()) processGlobalForThinLTO(GA); } +bool ThinLTOGlobalProcessing::run() { + processGlobalsForThinLTO(); + return false; +} + bool ModuleLinker::run() { for (const auto &SMEC : SrcM.getComdatSymbolTable()) { const Comdat &C = SMEC.getValue(); @@ -712,7 +783,14 @@ bool ModuleLinker::run() { if (linkIfNeeded(GA)) return true; - processGlobalsForThinLTO(); + if (ImportIndex) { + ThinLTOGlobalProcessing ThinLTOProcessing(SrcM, ImportIndex, + FunctionsToImport); + if (ThinLTOProcessing.run()) + return true; + for (auto *GV : ThinLTOProcessing.getNewExportedValues()) + ValuesToLink.insert(GV); + } for (unsigned I = 0; I < ValuesToLink.size(); ++I) { GlobalValue *GV = ValuesToLink[I]; @@ -785,15 +863,9 @@ bool Linker::linkModules(Module &Dest, std::unique_ptr Src, return L.linkInModule(std::move(Src), Flags); } -std::unique_ptr -llvm::renameModuleForThinLTO(std::unique_ptr M, - const FunctionInfoIndex *Index) { - std::unique_ptr RenamedModule( - new llvm::Module(M->getModuleIdentifier(), M->getContext())); - Linker L(*RenamedModule.get()); - if (L.linkInModule(std::move(M), llvm::Linker::Flags::None, Index)) - return nullptr; - return RenamedModule; +bool llvm::renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index) { + ThinLTOGlobalProcessing ThinLTOProcessing(M, Index); + return ThinLTOProcessing.run(); } //===----------------------------------------------------------------------===//