summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Linker/LinkModules.cpp
diff options
context:
space:
mode:
authorTeresa Johnson <tejohnson@google.com>2016-02-10 18:11:31 +0000
committerTeresa Johnson <tejohnson@google.com>2016-02-10 18:11:31 +0000
commit488a800a4cf59dc27101aa81c698128ad8c8d354 (patch)
tree6e4a88a690e4a0dcf50e598cc4423c10d2165280 /llvm/lib/Linker/LinkModules.cpp
parentee195caf661f009f7c0733fb58ace98e350cc2e8 (diff)
downloadbcm5719-llvm-488a800a4cf59dc27101aa81c698128ad8c8d354.tar.gz
bcm5719-llvm-488a800a4cf59dc27101aa81c698128ad8c8d354.zip
[ThinLTO] Move global processing from Linker to TransformUtils (NFC)
Summary: As discussed on IRC, move the ThinLTOGlobalProcessing code out of the linker, and into TransformUtils. The name of the class is changed to FunctionImportGlobalProcessing. Reviewers: joker.eph, rafael Subscribers: joker.eph, llvm-commits Differential Revision: http://reviews.llvm.org/D17081 llvm-svn: 260395
Diffstat (limited to 'llvm/lib/Linker/LinkModules.cpp')
-rw-r--r--llvm/lib/Linker/LinkModules.cpp300
1 files changed, 6 insertions, 294 deletions
diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp
index 4bb4b3f4f23..b96a6f42705 100644
--- a/llvm/lib/Linker/LinkModules.cpp
+++ b/llvm/lib/Linker/LinkModules.cpp
@@ -11,13 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Linker/Linker.h"
#include "LinkDiagnosticInfo.h"
#include "llvm-c/Linker.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/Linker/Linker.h"
+#include "llvm/Transforms/Utils/FunctionImportUtils.h"
using namespace llvm;
namespace {
@@ -141,257 +142,13 @@ public:
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<const GlobalValue *> *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<GlobalValue *> 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 FunctionsToImport != nullptr; }
- bool isModuleExporting() const { return HasExportedFunctions; }
-
- /// 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);
-
- /// Get the name for SGV that should be used in the linked destination
- /// module. Specifically, this handles the case where we need to rename
- /// a local that is being promoted to global scope.
- std::string getName(const GlobalValue *SGV);
-
- /// Process globals so that they can be used in ThinLTO. This includes
- /// promoting local variables so that they can be reference externally by
- /// thin lto imported globals and converting strong external globals to
- /// available_externally.
- void processGlobalsForThinLTO();
- void processGlobalForThinLTO(GlobalValue &GV);
-
- /// Get the new linkage for SGV that should be used in the linked destination
- /// module. Specifically, for ThinLTO importing or exporting it may need
- /// to be adjusted.
- GlobalValue::LinkageTypes getLinkage(const GlobalValue *SGV);
-
-public:
- ThinLTOGlobalProcessing(
- Module &M, const FunctionInfoIndex *Index,
- DenseSet<const GlobalValue *> *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 (!FunctionsToImport)
- HasExportedFunctions = ImportIndex->hasExportedFunctions(M);
- }
-
- bool run();
-
- /// Access the promoted globals that are now exported and need to be linked.
- SetVector<GlobalValue *> &getNewExportedValues() { return NewExportedValues; }
-};
-}
-
-/// Checks if we should import SGV as a definition, otherwise import as a
-/// declaration.
-static bool
-doImportAsDefinitionImpl(const GlobalValue *SGV,
- DenseSet<const GlobalValue *> *FunctionsToImport) {
- auto *GA = dyn_cast<GlobalAlias>(SGV);
- if (GA) {
- if (GA->hasWeakAnyLinkage())
- return false;
- const GlobalObject *GO = GA->getBaseObject();
- if (!GO->hasLinkOnceODRLinkage())
- return false;
- return doImportAsDefinitionImpl(GO, FunctionsToImport);
- }
- // Always import GlobalVariable definitions, except for the special
- // case of WeakAny which are imported as ExternalWeak declarations
- // (see comments in ModuleLinker::getLinkage). The linkage changes
- // described in ModuleLinker::getLinkage ensure the correct behavior (e.g.
- // global variables with external linkage are transformed to
- // available_externally definitions, which are ultimately turned into
- // declarations after the EliminateAvailableExternally pass).
- if (isa<GlobalVariable>(SGV) && !SGV->isDeclaration() &&
- !SGV->hasWeakAnyLinkage())
- return true;
- // Only import the function requested for importing.
- auto *SF = dyn_cast<Function>(SGV);
- if (SF && FunctionsToImport->count(SF))
- return true;
- // Otherwise no.
- return false;
-}
-
-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.
- if (!isPerformingImport() && !isModuleExporting())
- return false;
-
- // Local const variables never need to be promoted unless they are address
- // taken. The imported uses can simply use the clone created in this module.
- // For now we are conservative in determining which variables are not
- // address taken by checking the unnamed addr flag. To be more aggressive,
- // the address taken information must be checked earlier during parsing
- // of the module and recorded in the function index for use when importing
- // from that module.
- auto *GVar = dyn_cast<GlobalVariable>(SGV);
- if (GVar && GVar->isConstant() && GVar->hasUnnamedAddr())
- return false;
-
- // Eventually we only need to promote functions in the exporting module that
- // are referenced by a potentially exported function (i.e. one that is in the
- // function index).
- return true;
-}
-
-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,
- // we rename all locals (not just those that are promoted) in order to
- // avoid naming conflicts between locals imported from different modules.
- if (SGV->hasLocalLinkage() &&
- (doPromoteLocalToGlobal(SGV) || isPerformingImport()))
- return FunctionInfoIndex::getGlobalNameForLocal(
- SGV->getName(),
- ImportIndex->getModuleId(SGV->getParent()->getModuleIdentifier()));
- return SGV->getName();
-}
-
-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
- // all as potentially exported if this module is exporting anything.
- if (isModuleExporting()) {
- if (SGV->hasLocalLinkage() && doPromoteLocalToGlobal(SGV))
- return GlobalValue::ExternalLinkage;
- return SGV->getLinkage();
- }
-
- // Otherwise, if we aren't importing, no linkage change is needed.
- if (!isPerformingImport())
- return SGV->getLinkage();
-
- switch (SGV->getLinkage()) {
- case GlobalValue::ExternalLinkage:
- // External defnitions are converted to available_externally
- // definitions upon import, so that they are available for inlining
- // and/or optimization, but are turned into declarations later
- // during the EliminateAvailableExternally pass.
- if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
- return GlobalValue::AvailableExternallyLinkage;
- // An imported external declaration stays external.
- return SGV->getLinkage();
-
- case GlobalValue::AvailableExternallyLinkage:
- // An imported available_externally definition converts
- // to external if imported as a declaration.
- if (!doImportAsDefinition(SGV))
- return GlobalValue::ExternalLinkage;
- // An imported available_externally declaration stays that way.
- return SGV->getLinkage();
-
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- // These both stay the same when importing the definition.
- // The ThinLTO pass will eventually force-import their definitions.
- return SGV->getLinkage();
-
- case GlobalValue::WeakAnyLinkage:
- // Can't import weak_any definitions correctly, or we might change the
- // program semantics, since the linker will pick the first weak_any
- // definition and importing would change the order they are seen by the
- // linker. The module linking caller needs to enforce this.
- assert(!doImportAsDefinition(SGV));
- // If imported as a declaration, it becomes external_weak.
- return GlobalValue::ExternalWeakLinkage;
-
- case GlobalValue::WeakODRLinkage:
- // For weak_odr linkage, there is a guarantee that all copies will be
- // equivalent, so the issue described above for weak_any does not exist,
- // and the definition can be imported. It can be treated similarly
- // to an imported externally visible global value.
- if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
- return GlobalValue::AvailableExternallyLinkage;
- else
- return GlobalValue::ExternalLinkage;
-
- case GlobalValue::AppendingLinkage:
- // It would be incorrect to import an appending linkage variable,
- // 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.
- return GlobalValue::AppendingLinkage;
-
- case GlobalValue::InternalLinkage:
- case GlobalValue::PrivateLinkage:
- // If we are promoting the local to global scope, it is handled
- // similarly to a normal externally visible global.
- if (doPromoteLocalToGlobal(SGV)) {
- if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
- return GlobalValue::AvailableExternallyLinkage;
- else
- return GlobalValue::ExternalLinkage;
- }
- // A non-promoted imported local definition stays local.
- // The ThinLTO pass will eventually force-import their definitions.
- return SGV->getLinkage();
-
- case GlobalValue::ExternalWeakLinkage:
- // External weak doesn't apply to definitions, must be a declaration.
- assert(!doImportAsDefinition(SGV));
- // Linkage stays external_weak.
- return SGV->getLinkage();
-
- case GlobalValue::CommonLinkage:
- // Linkage stays common on definitions.
- // The ThinLTO pass will eventually force-import their definitions.
- return SGV->getLinkage();
- }
-
- llvm_unreachable("unknown linkage type");
+ return FunctionImportGlobalProcessing::doImportAsDefinition(
+ SGV, FunctionsToImport);
}
static GlobalValue::VisibilityTypes
@@ -713,46 +470,6 @@ void ModuleLinker::addLazyFor(GlobalValue &GV, IRMover::ValueAdder Add) {
}
}
-void ThinLTOGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
- if (GV.hasLocalLinkage() &&
- (doPromoteLocalToGlobal(&GV) || isPerformingImport())) {
- GV.setName(getName(&GV));
- GV.setLinkage(getLinkage(&GV));
- if (!GV.hasLocalLinkage())
- GV.setVisibility(GlobalValue::HiddenVisibility);
- if (isModuleExporting())
- NewExportedValues.insert(&GV);
- } else
- GV.setLinkage(getLinkage(&GV));
-
- // Remove functions imported as available externally defs from comdats,
- // as this is a declaration for the linker, and will be dropped eventually.
- // It is illegal for comdats to contain declarations.
- auto *GO = dyn_cast_or_null<GlobalObject>(&GV);
- if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) {
- // The IRMover should not have placed any imported declarations in
- // a comdat, so the only declaration that should be in a comdat
- // at this point would be a definition imported as available_externally.
- assert(GO->hasAvailableExternallyLinkage() &&
- "Expected comdat on definition (possibly available external)");
- GO->setComdat(nullptr);
- }
-}
-
-void ThinLTOGlobalProcessing::processGlobalsForThinLTO() {
- for (GlobalVariable &GV : M.globals())
- processGlobalForThinLTO(GV);
- for (Function &SF : M)
- processGlobalForThinLTO(SF);
- 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();
@@ -792,8 +509,8 @@ bool ModuleLinker::run() {
return true;
if (ImportIndex) {
- ThinLTOGlobalProcessing ThinLTOProcessing(SrcM, ImportIndex,
- FunctionsToImport);
+ FunctionImportGlobalProcessing ThinLTOProcessing(SrcM, ImportIndex,
+ FunctionsToImport);
if (ThinLTOProcessing.run())
return true;
for (auto *GV : ThinLTOProcessing.getNewExportedValues())
@@ -871,11 +588,6 @@ bool Linker::linkModules(Module &Dest, std::unique_ptr<Module> Src,
return L.linkInModule(std::move(Src), Flags);
}
-bool llvm::renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index) {
- ThinLTOGlobalProcessing ThinLTOProcessing(M, Index);
- return ThinLTOProcessing.run();
-}
-
//===----------------------------------------------------------------------===//
// C API.
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud