[llvm] r251866 - Restore "Support for ThinLTO function importing and symbol linking."
Teresa Johnson via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 2 16:14:16 PST 2015
Author: tejohnson
Date: Mon Nov 2 18:14:15 2015
New Revision: 251866
URL: http://llvm.org/viewvc/llvm-project?rev=251866&view=rev
Log:
Restore "Support for ThinLTO function importing and symbol linking."
This restores commit r251837, with the new library dependence added to
llvm-link/Makefile to address bot failures.
Added:
llvm/trunk/test/Linker/Inputs/funcimport.ll
llvm/trunk/test/Linker/funcimport.ll
Modified:
llvm/trunk/include/llvm/Bitcode/ReaderWriter.h
llvm/trunk/include/llvm/IR/FunctionInfo.h
llvm/trunk/include/llvm/Linker/Linker.h
llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h
llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/trunk/lib/Linker/LinkModules.cpp
llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp
llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp
llvm/trunk/tools/llvm-link/CMakeLists.txt
llvm/trunk/tools/llvm-link/LLVMBuild.txt
llvm/trunk/tools/llvm-link/Makefile
llvm/trunk/tools/llvm-link/llvm-link.cpp
Modified: llvm/trunk/include/llvm/Bitcode/ReaderWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/ReaderWriter.h?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/ReaderWriter.h (original)
+++ llvm/trunk/include/llvm/Bitcode/ReaderWriter.h Mon Nov 2 18:14:15 2015
@@ -64,6 +64,8 @@ namespace llvm {
DiagnosticHandlerFunction DiagnosticHandler);
/// Parse the specified bitcode buffer, returning the function info index.
+ /// If ExportingModule is true, check for functions in the index from this
+ /// module when the combined index is built during parsing and set flag.
/// If IsLazy is true, parse the entire function summary into
/// the index. Otherwise skip the function summary section, and only create
/// an index object with a map from function name to function summary offset.
@@ -71,6 +73,7 @@ namespace llvm {
ErrorOr<std::unique_ptr<FunctionInfoIndex>>
getFunctionInfoIndex(MemoryBufferRef Buffer, LLVMContext &Context,
DiagnosticHandlerFunction DiagnosticHandler,
+ const Module *ExportingModule = nullptr,
bool IsLazy = false);
/// This method supports lazy reading of function summary data from the
Modified: llvm/trunk/include/llvm/IR/FunctionInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/FunctionInfo.h?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/FunctionInfo.h (original)
+++ llvm/trunk/include/llvm/IR/FunctionInfo.h Mon Nov 2 18:14:15 2015
@@ -165,8 +165,18 @@ private:
/// Holds strings for combined index, mapping to the corresponding module ID.
ModulePathStringTableTy ModulePathStringTable;
+ /// The main module being compiled, that we are importing into, if applicable.
+ /// Used to check if any of its functions are in the index and therefore
+ /// potentially exported.
+ const Module *ExportingModule;
+
+ /// Flag indicating whether the exporting module has any functions in the
+ /// index and therefore potentially exported (imported into another module).
+ bool HasExportedFunctions;
+
public:
- FunctionInfoIndex() = default;
+ FunctionInfoIndex(const Module *M = nullptr)
+ : ExportingModule(M), HasExportedFunctions(false){};
~FunctionInfoIndex() = default;
// Disable the copy constructor and assignment operators, so
@@ -186,6 +196,12 @@ public:
/// Add a function info for a function of the given name.
void addFunctionInfo(StringRef FuncName, std::unique_ptr<FunctionInfo> Info) {
+ if (ExportingModule) {
+ assert(Info->functionSummary());
+ if (ExportingModule->getModuleIdentifier() ==
+ Info->functionSummary()->modulePath())
+ HasExportedFunctions = true;
+ }
FunctionMap[FuncName].push_back(std::move(Info));
}
@@ -223,6 +239,14 @@ public:
return ModulePathStringTable.insert(std::make_pair(ModPath, ModId))
.first->first();
}
+
+ /// Check if the given Module has any functions available for exporting
+ /// in the index.
+ bool hasExportedFunctions(const Module *M) {
+ assert(M == ExportingModule &&
+ "Checking for exported functions on unexpected module");
+ return HasExportedFunctions;
+ }
};
} // End llvm namespace
Modified: llvm/trunk/include/llvm/Linker/Linker.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Linker/Linker.h?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Linker/Linker.h (original)
+++ llvm/trunk/include/llvm/Linker/Linker.h Mon Nov 2 18:14:15 2015
@@ -14,6 +14,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/FunctionInfo.h"
namespace llvm {
class Module;
@@ -76,8 +77,13 @@ public:
/// \brief Link \p Src into the composite. The source is destroyed.
/// Passing OverrideSymbols as true will have symbols from Src
/// shadow those in the Dest.
+ /// For ThinLTO function importing/exporting the \p FunctionInfoIndex
+ /// is passed. If a \p FuncToImport is provided, only that single
+ /// function is imported from the source module.
/// Returns true on error.
- bool linkInModule(Module *Src, unsigned Flags = Flags::None);
+ bool linkInModule(Module *Src, unsigned Flags = Flags::None,
+ FunctionInfoIndex *Index = nullptr,
+ Function *FuncToImport = nullptr);
/// \brief Set the composite to the passed-in module.
void setModule(Module *Dst);
Modified: llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h Mon Nov 2 18:14:15 2015
@@ -18,6 +18,7 @@
namespace llvm {
class FunctionInfoIndex;
+class Module;
namespace object {
class ObjectFile;
@@ -84,7 +85,8 @@ public:
/// Return new FunctionIndexObjectFile instance containing parsed function
/// summary/index.
static ErrorOr<std::unique_ptr<FunctionIndexObjectFile>>
- create(MemoryBufferRef Object, LLVMContext &Context, bool IsLazy = false);
+ create(MemoryBufferRef Object, LLVMContext &Context,
+ const Module *ExportingModule = nullptr, bool IsLazy = false);
/// \brief Parse the function summary information for function with the
/// given name out of the given buffer. Parsed information is
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Mon Nov 2 18:14:15 2015
@@ -5813,12 +5813,12 @@ llvm::getBitcodeTargetTriple(MemoryBuffe
ErrorOr<std::unique_ptr<FunctionInfoIndex>>
llvm::getFunctionInfoIndex(MemoryBufferRef Buffer, LLVMContext &Context,
DiagnosticHandlerFunction DiagnosticHandler,
- bool IsLazy) {
+ const Module *ExportingModule, bool IsLazy) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler, IsLazy);
std::unique_ptr<FunctionInfoIndex> Index =
- llvm::make_unique<FunctionInfoIndex>();
+ llvm::make_unique<FunctionInfoIndex>(ExportingModule);
auto cleanupOnError = [&](std::error_code EC) {
R.releaseBuffer(); // Never take ownership on error.
Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Nov 2 18:14:15 2015
@@ -369,12 +369,14 @@ class ValueMaterializerTy final : public
TypeMapTy &TypeMap;
Module *DstM;
std::vector<GlobalValue *> &LazilyLinkGlobalValues;
+ ModuleLinker *ModLinker;
public:
ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM,
- std::vector<GlobalValue *> &LazilyLinkGlobalValues)
+ std::vector<GlobalValue *> &LazilyLinkGlobalValues,
+ ModuleLinker *ModLinker)
: ValueMaterializer(), TypeMap(TypeMap), DstM(DstM),
- LazilyLinkGlobalValues(LazilyLinkGlobalValues) {}
+ LazilyLinkGlobalValues(LazilyLinkGlobalValues), ModLinker(ModLinker) {}
Value *materializeValueFor(Value *V) override;
};
@@ -427,12 +429,38 @@ class ModuleLinker {
/// For symbol clashes, prefer those from Src.
unsigned Flags;
+ /// Function index passed into ModuleLinker for using in function
+ /// importing/exporting handling.
+ FunctionInfoIndex *ImportIndex;
+
+ /// Function to import from source module, all other functions are
+ /// imported as declarations instead of definitions.
+ Function *ImportFunction;
+
+ /// 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;
+
public:
ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM,
- DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags)
+ DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags,
+ FunctionInfoIndex *Index = nullptr,
+ Function *FuncToImport = nullptr)
: DstM(dstM), SrcM(srcM), TypeMap(Set),
- ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues),
- DiagnosticHandler(DiagnosticHandler), Flags(Flags) {}
+ ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues, this),
+ DiagnosticHandler(DiagnosticHandler), Flags(Flags), ImportIndex(Index),
+ ImportFunction(FuncToImport), HasExportedFunctions(false) {
+ assert((ImportIndex || !ImportFunction) &&
+ "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 && !ImportFunction)
+ HasExportedFunctions = ImportIndex->hasExportedFunctions(SrcM);
+ }
bool run();
@@ -442,6 +470,14 @@ public:
return Flags & Linker::InternalizeLinkedSymbols;
}
+ /// Handles cloning of a global values from the source module into
+ /// the destination module, including setting the attributes and visibility.
+ GlobalValue *copyGlobalValueProto(TypeMapTy &TypeMap, const GlobalValue *SGV,
+ const GlobalValue *DGV = nullptr);
+
+ /// Check if we should promote the given local value to global scope.
+ bool doPromoteLocalToGlobal(const GlobalValue *SGV);
+
private:
bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest,
const GlobalValue &Src);
@@ -508,6 +544,42 @@ private:
void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src);
bool linkGlobalValueBody(GlobalValue &Src);
+ /// Functions that take care of cloning a specific global value type
+ /// into the destination module.
+ GlobalVariable *copyGlobalVariableProto(TypeMapTy &TypeMap,
+ const GlobalVariable *SGVar);
+ Function *copyFunctionProto(TypeMapTy &TypeMap, const Function *SF);
+ GlobalValue *copyGlobalAliasProto(TypeMapTy &TypeMap, const GlobalAlias *SGA);
+
+ /// Helper methods to check if we are importing from or potentially
+ /// exporting from the current source module.
+ bool isPerformingImport() { return ImportFunction != nullptr; }
+ bool isModuleExporting() { 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);
+
+ /// 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);
+
+ /// Copies the necessary global value attributes and name from the source
+ /// to the newly cloned global value.
+ void copyGVAttributes(GlobalValue *NewGV, const GlobalValue *SrcGV);
+
+ /// Updates the visibility for the new global cloned from the source
+ /// and, if applicable, linked with an existing destination global.
+ /// Handles visibility change required for promoted locals.
+ void setVisibility(GlobalValue *NewGV, const GlobalValue *SGV,
+ const GlobalValue *DGV = nullptr);
+
void linkNamedMDNodes();
void stripReplacedSubprograms();
};
@@ -519,6 +591,9 @@ private:
static void forceRenaming(GlobalValue *GV, StringRef Name) {
// If the global doesn't force its name or if it already has the right name,
// there is nothing for us to do.
+ // Note that any required local to global promotion should already be done,
+ // so promoted locals will not skip this handling as their linkage is no
+ // longer local.
if (GV->hasLocalLinkage() || GV->getName() == Name)
return;
@@ -536,9 +611,23 @@ static void forceRenaming(GlobalValue *G
/// copy additional attributes (those not needed to construct a GlobalValue)
/// from the SrcGV to the DestGV.
-static void copyGVAttributes(GlobalValue *DestGV, const GlobalValue *SrcGV) {
- DestGV->copyAttributesFrom(SrcGV);
- forceRenaming(DestGV, SrcGV->getName());
+void ModuleLinker::copyGVAttributes(GlobalValue *NewGV,
+ const GlobalValue *SrcGV) {
+ auto *GA = dyn_cast<GlobalAlias>(SrcGV);
+ // Check for the special case of converting an alias (definition) to a
+ // non-alias (declaration). This can happen when we are importing and
+ // encounter a weak_any alias (weak_any defs may not be imported, see
+ // comments in ModuleLinker::getLinkage) or an alias whose base object is
+ // being imported as a declaration. In that case copy the attributes from the
+ // base object.
+ if (GA && !dyn_cast<GlobalAlias>(NewGV)) {
+ assert(isPerformingImport() &&
+ (GA->hasWeakAnyLinkage() ||
+ !doImportAsDefinition(GA->getBaseObject())));
+ NewGV->copyAttributesFrom(GA->getBaseObject());
+ } else
+ NewGV->copyAttributesFrom(SrcGV);
+ forceRenaming(NewGV, getName(SrcGV));
}
static bool isLessConstraining(GlobalValue::VisibilityTypes a,
@@ -554,17 +643,169 @@ static bool isLessConstraining(GlobalVal
return false;
}
+bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) {
+ if (!isPerformingImport())
+ return false;
+ // Always import GlobalVariable definitions. The linkage changes
+ // described in ModuleLinker::getLinkage ensure the correct behavior (e.g.
+ // global variables with external linkage are transformed to
+ // available_externally defintions, which are ultimately turned into
+ // declaratios after the EliminateAvailableExternally pass).
+ if (dyn_cast<GlobalVariable>(SGV) && !SGV->isDeclaration())
+ return true;
+ // Only import the function requested for importing.
+ auto *SF = dyn_cast<Function>(SGV);
+ if (SF && SF == ImportFunction)
+ return true;
+ // Otherwise no.
+ return false;
+}
+
+bool ModuleLinker::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 ModuleLinker::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 ModuleLinker::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))
+ 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))
+ 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 linkGlobalValueProto.
+ assert(false && "Cannot import appending linkage variable");
+
+ 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))
+ 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");
+}
+
/// Loop through the global variables in the src module and merge them into the
/// dest module.
-static GlobalVariable *copyGlobalVariableProto(TypeMapTy &TypeMap, Module &DstM,
- const GlobalVariable *SGVar) {
+GlobalVariable *
+ModuleLinker::copyGlobalVariableProto(TypeMapTy &TypeMap,
+ const GlobalVariable *SGVar) {
// No linking to be performed or linking from the source: simply create an
// identical version of the symbol over in the dest module... the
// initializer will be filled in later by LinkGlobalInits.
GlobalVariable *NewDGV = new GlobalVariable(
- DstM, TypeMap.get(SGVar->getType()->getElementType()),
- SGVar->isConstant(), SGVar->getLinkage(), /*init*/ nullptr,
- SGVar->getName(), /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
+ *DstM, TypeMap.get(SGVar->getType()->getElementType()),
+ SGVar->isConstant(), getLinkage(SGVar), /*init*/ nullptr, getName(SGVar),
+ /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
SGVar->getType()->getAddressSpace());
return NewDGV;
@@ -572,34 +813,75 @@ static GlobalVariable *copyGlobalVariabl
/// Link the function in the source module into the destination module if
/// needed, setting up mapping information.
-static Function *copyFunctionProto(TypeMapTy &TypeMap, Module &DstM,
- const Function *SF) {
+Function *ModuleLinker::copyFunctionProto(TypeMapTy &TypeMap,
+ const Function *SF) {
// If there is no linkage to be performed or we are linking from the source,
// bring SF over.
- return Function::Create(TypeMap.get(SF->getFunctionType()), SF->getLinkage(),
- SF->getName(), &DstM);
+ return Function::Create(TypeMap.get(SF->getFunctionType()), getLinkage(SF),
+ getName(SF), DstM);
}
/// Set up prototypes for any aliases that come over from the source module.
-static GlobalAlias *copyGlobalAliasProto(TypeMapTy &TypeMap, Module &DstM,
- const GlobalAlias *SGA) {
+GlobalValue *ModuleLinker::copyGlobalAliasProto(TypeMapTy &TypeMap,
+ const GlobalAlias *SGA) {
+ // If we are importing and encounter a weak_any alias, or an alias to
+ // an object being imported as a declaration, we must import the alias
+ // as a declaration as well, which involves converting it to a non-alias.
+ // See comments in ModuleLinker::getLinkage for why we cannot import
+ // weak_any defintions.
+ if (isPerformingImport() && (SGA->hasWeakAnyLinkage() ||
+ !doImportAsDefinition(SGA->getBaseObject()))) {
+ // Need to convert to declaration. All aliases must be definitions.
+ const GlobalValue *GVal = SGA->getBaseObject();
+ GlobalValue *NewGV;
+ if (auto *GVar = dyn_cast<GlobalVariable>(GVal))
+ NewGV = copyGlobalVariableProto(TypeMap, GVar);
+ else {
+ auto *F = dyn_cast<Function>(GVal);
+ assert(F);
+ NewGV = copyFunctionProto(TypeMap, F);
+ }
+ // Set the linkage to ExternalWeak, see also comments in
+ // ModuleLinker::getLinkage.
+ if (SGA->hasWeakAnyLinkage())
+ NewGV->setLinkage(GlobalValue::ExternalWeakLinkage);
+ // Don't attempt to link body, needs to be a declaration.
+ DoNotLinkFromSource.insert(SGA);
+ return NewGV;
+ }
// If there is no linkage to be performed or we're linking from the source,
// bring over SGA.
auto *Ty = TypeMap.get(SGA->getValueType());
return GlobalAlias::create(Ty, SGA->getType()->getPointerAddressSpace(),
- SGA->getLinkage(), SGA->getName(), &DstM);
+ getLinkage(SGA), getName(SGA), DstM);
+}
+
+void ModuleLinker::setVisibility(GlobalValue *NewGV, const GlobalValue *SGV,
+ const GlobalValue *DGV) {
+ GlobalValue::VisibilityTypes Visibility = SGV->getVisibility();
+ if (DGV)
+ Visibility = isLessConstraining(Visibility, DGV->getVisibility())
+ ? DGV->getVisibility()
+ : Visibility;
+ // For promoted locals, mark them hidden so that they can later be
+ // stripped from the symbol table to reduce bloat.
+ if (SGV->hasLocalLinkage() && doPromoteLocalToGlobal(SGV))
+ Visibility = GlobalValue::HiddenVisibility;
+ NewGV->setVisibility(Visibility);
}
-static GlobalValue *copyGlobalValueProto(TypeMapTy &TypeMap, Module &DstM,
- const GlobalValue *SGV) {
+GlobalValue *ModuleLinker::copyGlobalValueProto(TypeMapTy &TypeMap,
+ const GlobalValue *SGV,
+ const GlobalValue *DGV) {
GlobalValue *NewGV;
if (auto *SGVar = dyn_cast<GlobalVariable>(SGV))
- NewGV = copyGlobalVariableProto(TypeMap, DstM, SGVar);
+ NewGV = copyGlobalVariableProto(TypeMap, SGVar);
else if (auto *SF = dyn_cast<Function>(SGV))
- NewGV = copyFunctionProto(TypeMap, DstM, SF);
+ NewGV = copyFunctionProto(TypeMap, SF);
else
- NewGV = copyGlobalAliasProto(TypeMap, DstM, cast<GlobalAlias>(SGV));
+ NewGV = copyGlobalAliasProto(TypeMap, cast<GlobalAlias>(SGV));
copyGVAttributes(NewGV, SGV);
+ setVisibility(NewGV, SGV, DGV);
return NewGV;
}
@@ -608,7 +890,7 @@ Value *ValueMaterializerTy::materializeV
if (!SGV)
return nullptr;
- GlobalValue *DGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
+ GlobalValue *DGV = ModLinker->copyGlobalValueProto(TypeMap, SGV);
if (Comdat *SC = SGV->getComdat()) {
if (auto *DGO = dyn_cast<GlobalObject>(DGV)) {
@@ -742,6 +1024,9 @@ bool ModuleLinker::shouldLinkFromSource(
// We always have to add Src if it has appending linkage.
if (Src.hasAppendingLinkage()) {
+ // Caller should have already determined that we can't link from source
+ // when importing (see comments in linkGlobalValueProto).
+ assert(!isPerformingImport());
LinkFromSrc = true;
return false;
}
@@ -749,6 +1034,28 @@ bool ModuleLinker::shouldLinkFromSource(
bool SrcIsDeclaration = Src.isDeclarationForLinker();
bool DestIsDeclaration = Dest.isDeclarationForLinker();
+ if (isPerformingImport()) {
+ if (isa<Function>(&Src)) {
+ // For functions, LinkFromSrc iff this is the function requested
+ // for importing. For variables, decide below normally.
+ LinkFromSrc = (&Src == ImportFunction);
+ return false;
+ }
+
+ // Check if this is an alias with an already existing definition
+ // in Dest, which must have come from a prior importing pass from
+ // the same Src module. Unlike imported function and variable
+ // definitions, which are imported as available_externally and are
+ // not definitions for the linker, that is not a valid linkage for
+ // imported aliases which must be definitions. Simply use the existing
+ // Dest copy.
+ if (isa<GlobalAlias>(&Src) && !DestIsDeclaration) {
+ assert(isa<GlobalAlias>(&Dest));
+ LinkFromSrc = false;
+ return false;
+ }
+ }
+
if (SrcIsDeclaration) {
// If Src is external or if both Src & Dest are external.. Just link the
// external globals, we aren't adding anything.
@@ -1040,13 +1347,21 @@ bool ModuleLinker::linkGlobalValueProto(
GlobalValue *DGV = getLinkedToGlobal(SGV);
// Handle the ultra special appending linkage case first.
+ assert(!DGV || SGV->hasAppendingLinkage() == DGV->hasAppendingLinkage());
+ if (SGV->hasAppendingLinkage() && isPerformingImport()) {
+ // Don't want to append to global_ctors list, for example, when we
+ // are importing for ThinLTO, otherwise the global ctors and dtors
+ // get executed multiple times for local variables (the latter causing
+ // double frees).
+ DoNotLinkFromSource.insert(SGV);
+ return false;
+ }
if (DGV && DGV->hasAppendingLinkage())
return linkAppendingVarProto(cast<GlobalVariable>(DGV),
cast<GlobalVariable>(SGV));
bool LinkFromSrc = true;
Comdat *C = nullptr;
- GlobalValue::VisibilityTypes Visibility = SGV->getVisibility();
bool HasUnnamedAddr = SGV->hasUnnamedAddr();
if (const Comdat *SC = SGV->getComdat()) {
@@ -1070,12 +1385,8 @@ bool ModuleLinker::linkGlobalValueProto(
ConstantExpr::getBitCast(DGV, TypeMap.get(SGV->getType()));
}
- if (DGV) {
- Visibility = isLessConstraining(Visibility, DGV->getVisibility())
- ? DGV->getVisibility()
- : Visibility;
+ if (DGV)
HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr();
- }
if (!LinkFromSrc && !DGV)
return false;
@@ -1083,10 +1394,12 @@ bool ModuleLinker::linkGlobalValueProto(
GlobalValue *NewGV;
if (!LinkFromSrc) {
NewGV = DGV;
+ // When linking from source we setVisibility from copyGlobalValueProto.
+ setVisibility(NewGV, SGV, DGV);
} else {
// If the GV is to be lazily linked, don't create it just yet.
// The ValueMaterializerTy will deal with creating it if it's used.
- if (!DGV && !shouldOverrideFromSrc() &&
+ if (!DGV && !shouldOverrideFromSrc() && SGV != ImportFunction &&
(SGV->hasLocalLinkage() || SGV->hasLinkOnceLinkage() ||
SGV->hasAvailableExternallyLinkage())) {
DoNotLinkFromSource.insert(SGV);
@@ -1100,7 +1413,7 @@ bool ModuleLinker::linkGlobalValueProto(
return false;
}
- NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
+ NewGV = copyGlobalValueProto(TypeMap, SGV, DGV);
if (DGV && isa<Function>(DGV))
if (auto *NewF = dyn_cast<Function>(NewGV))
@@ -1108,7 +1421,6 @@ bool ModuleLinker::linkGlobalValueProto(
}
NewGV->setUnnamedAddr(HasUnnamedAddr);
- NewGV->setVisibility(Visibility);
if (auto *NewGO = dyn_cast<GlobalObject>(NewGV)) {
if (C)
@@ -1613,6 +1925,10 @@ bool ModuleLinker::run() {
if (DoNotLinkFromSource.count(&SF))
continue;
+ // When importing, only materialize the function requested for import.
+ if (isPerformingImport() && &SF != ImportFunction)
+ continue;
+
if (linkGlobalValueBody(SF))
return true;
}
@@ -1646,6 +1962,8 @@ bool ModuleLinker::run() {
while (!LazilyLinkGlobalValues.empty()) {
GlobalValue *SGV = LazilyLinkGlobalValues.back();
LazilyLinkGlobalValues.pop_back();
+ if (isPerformingImport() && !doImportAsDefinition(SGV))
+ continue;
// Skip declarations that ValueMaterializer may have created in
// case we link in only some of SrcM.
@@ -1779,9 +2097,10 @@ void Linker::deleteModule() {
Composite = nullptr;
}
-bool Linker::linkInModule(Module *Src, unsigned Flags) {
+bool Linker::linkInModule(Module *Src, unsigned Flags, FunctionInfoIndex *Index,
+ Function *FuncToImport) {
ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src,
- DiagnosticHandler, Flags);
+ DiagnosticHandler, Flags, Index, FuncToImport);
bool RetCode = TheLinker.run();
Composite->dropTriviallyDeadConstantArrays();
return RetCode;
Modified: llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp Mon Nov 2 18:14:15 2015
@@ -1,5 +1,4 @@
-//===- FunctionIndexObjectFile.cpp - Function index file implementation
-//----===//
+//===- FunctionIndexObjectFile.cpp - Function index file implementation ---===//
//
// The LLVM Compiler Infrastructure
//
@@ -86,15 +85,15 @@ bool FunctionIndexObjectFile::hasFunctio
// function summary/index.
ErrorOr<std::unique_ptr<FunctionIndexObjectFile>>
FunctionIndexObjectFile::create(MemoryBufferRef Object, LLVMContext &Context,
- bool IsLazy) {
+ const Module *ExportingModule, bool IsLazy) {
std::unique_ptr<FunctionInfoIndex> Index;
ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
if (!BCOrErr)
return BCOrErr.getError();
- ErrorOr<std::unique_ptr<FunctionInfoIndex>> IOrErr =
- getFunctionInfoIndex(BCOrErr.get(), Context, nullptr, IsLazy);
+ ErrorOr<std::unique_ptr<FunctionInfoIndex>> IOrErr = getFunctionInfoIndex(
+ BCOrErr.get(), Context, nullptr, ExportingModule, IsLazy);
if (std::error_code EC = IOrErr.getError())
return EC;
Modified: llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp Mon Nov 2 18:14:15 2015
@@ -49,9 +49,46 @@ ModulePass *llvm::createEliminateAvailab
return new EliminateAvailableExternally();
}
+static void convertAliasToDeclaration(GlobalAlias &GA, Module &M) {
+ GlobalValue *GVal = GA.getBaseObject();
+ GlobalValue *NewGV;
+ if (auto *GVar = dyn_cast<GlobalVariable>(GVal)) {
+ GlobalVariable *NewGVar = new GlobalVariable(
+ M, GVar->getType()->getElementType(), GVar->isConstant(),
+ GVar->getLinkage(), /*init*/ nullptr, GA.getName(), GVar,
+ GVar->getThreadLocalMode(), GVar->getType()->getAddressSpace());
+ NewGV = NewGVar;
+ NewGV->copyAttributesFrom(GVar);
+ } else {
+ auto *F = dyn_cast<Function>(GVal);
+ assert(F);
+ Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
+ GA.getName(), &M);
+ NewGV = NewF;
+ NewGV->copyAttributesFrom(F);
+ }
+ GA.replaceAllUsesWith(ConstantExpr::getBitCast(NewGV, GA.getType()));
+ GA.eraseFromParent();
+}
+
bool EliminateAvailableExternally::runOnModule(Module &M) {
bool Changed = false;
+ // Convert any aliases that alias with an available externally
+ // value (which will be turned into declarations later on in this routine)
+ // into declarations themselves. All aliases must be definitions, and
+ // must alias with a definition. So this involves creating a declaration
+ // equivalent to the alias's base object.
+ for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;) {
+ // Increment the iterator first since we may delete the current alias.
+ GlobalAlias &GA = *(I++);
+ GlobalValue *GVal = GA.getBaseObject();
+ if (!GVal->hasAvailableExternallyLinkage())
+ continue;
+ convertAliasToDeclaration(GA, M);
+ Changed = true;
+ }
+
// Drop initializers of available externally global variables.
for (GlobalVariable &GV : M.globals()) {
if (!GV.hasAvailableExternallyLinkage())
@@ -65,6 +102,7 @@ bool EliminateAvailableExternally::runOn
GV.removeDeadConstantUsers();
GV.setLinkage(GlobalValue::ExternalLinkage);
NumVariables++;
+ Changed = true;
}
// Drop the bodies of available externally functions.
@@ -76,6 +114,7 @@ bool EliminateAvailableExternally::runOn
F.deleteBody();
F.removeDeadConstantUsers();
NumFunctions++;
+ Changed = true;
}
return Changed;
Added: llvm/trunk/test/Linker/Inputs/funcimport.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/funcimport.ll?rev=251866&view=auto
==============================================================================
--- llvm/trunk/test/Linker/Inputs/funcimport.ll (added)
+++ llvm/trunk/test/Linker/Inputs/funcimport.ll Mon Nov 2 18:14:15 2015
@@ -0,0 +1,28 @@
+define i32 @main() #0 {
+entry:
+ call void (...) @weakalias()
+ call void (...) @analias()
+ %call = call i32 (...) @referencestatics()
+ %call1 = call i32 (...) @referenceglobals()
+ %call2 = call i32 (...) @referencecommon()
+ call void (...) @setfuncptr()
+ call void (...) @callfuncptr()
+ call void (...) @callweakfunc()
+ ret i32 0
+}
+
+declare void @weakalias(...) #1
+
+declare void @analias(...) #1
+
+declare i32 @referencestatics(...) #1
+
+declare i32 @referenceglobals(...) #1
+
+declare i32 @referencecommon(...) #1
+
+declare void @setfuncptr(...) #1
+
+declare void @callfuncptr(...) #1
+
+declare void @callweakfunc(...) #1
Added: llvm/trunk/test/Linker/funcimport.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/funcimport.ll?rev=251866&view=auto
==============================================================================
--- llvm/trunk/test/Linker/funcimport.ll (added)
+++ llvm/trunk/test/Linker/funcimport.ll Mon Nov 2 18:14:15 2015
@@ -0,0 +1,169 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: llvm-as -function-summary %s -o %t.bc
+; RUN: llvm-as -function-summary %p/Inputs/funcimport.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; Ensure statics are promoted/renamed correctly from this file (all but
+; constant variable need promotion).
+; RUN: llvm-link %t.bc -functionindex=%t3.thinlto.bc -S | FileCheck %s --check-prefix=EXPORTSTATIC
+; EXPORTSTATIC: @staticvar.llvm.1 = hidden global
+; EXPORTSTATIC: @staticconstvar = internal unnamed_addr constant
+; EXPORTSTATIC: @P.llvm.1 = hidden global void ()* null
+; EXPORTSTATIC: define hidden i32 @staticfunc.llvm.1
+; EXPORTSTATIC: define hidden void @staticfunc2.llvm.1
+
+; Ensure that both weak alias to an imported function and strong alias to a
+; non-imported function are correctly turned into declarations.
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc1:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB1
+; IMPORTGLOB1: define available_externally void @globalfunc1
+; IMPORTGLOB1: declare void @globalfunc2
+; IMPORTGLOB1: declare extern_weak void @weakalias
+; IMPORTGLOB1: declare void @analias
+
+; Ensure that weak alias to a non-imported function is correctly
+; turned into a declaration, but that strong alias to an imported function
+; is imported as alias.
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB2
+; IMPORTGLOB2: @analias = alias void (...), bitcast (void ()* @globalfunc2
+; IMPORTGLOB2: declare void @globalfunc1
+; IMPORTGLOB2: define available_externally void @globalfunc2
+; IMPORTGLOB2: declare extern_weak void @weakalias
+
+; Ensure that strong alias imported in second pass of importing ends up
+; as an alias.
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc1:%t.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB3
+; IMPORTGLOB3: @analias = alias void (...), bitcast (void ()* @globalfunc2
+; IMPORTGLOB3: define available_externally void @globalfunc1
+; IMPORTGLOB3: define available_externally void @globalfunc2
+; IMPORTGLOB3: declare extern_weak void @weakalias
+
+; Ensure that strong alias imported in first pass of importing ends up
+; as an alias, and that seeing the alias definition during a second inlining
+; pass is handled correctly.
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -import=globalfunc1:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB4
+; IMPORTGLOB4: @analias = alias void (...), bitcast (void ()* @globalfunc2
+; IMPORTGLOB4: define available_externally void @globalfunc2
+; IMPORTGLOB4: define available_externally void @globalfunc1
+; IMPORTGLOB4: declare extern_weak void @weakalias
+
+; Ensure that imported static variable and function references are correctly
+; promoted and renamed (including static constant variable).
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referencestatics:%t.bc -S | FileCheck %s --check-prefix=IMPORTSTATIC
+; IMPORTSTATIC: @staticvar.llvm.1 = available_externally hidden global
+; IMPORTSTATIC: @staticconstvar.llvm.1 = internal unnamed_addr constant
+; IMPORTSTATIC: define available_externally i32 @referencestatics
+; IMPORTSTATIC: %call = call i32 @staticfunc.llvm.1
+; IMPORTSTATIC: %0 = load i32, i32* @staticvar.llvm.1
+; IMPORTSTATIC: declare hidden i32 @staticfunc.llvm.1
+
+; Ensure that imported global (external) function and variable references
+; are handled correctly (including referenced variable imported as
+; available_externally definition)
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referenceglobals:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOBALS
+; IMPORTGLOBALS: @globalvar = available_externally global
+; IMPORTGLOBALS: declare void @globalfunc1()
+; IMPORTGLOBALS: define available_externally i32 @referenceglobals
+
+; Ensure that common variable correctly imported as common defition.
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referencecommon:%t.bc -S | FileCheck %s --check-prefix=IMPORTCOMMON
+; IMPORTCOMMON: @commonvar = common global
+; IMPORTCOMMON: define available_externally i32 @referencecommon
+
+; Ensure that imported static function pointer correctly promoted and renamed.
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=callfuncptr:%t.bc -S | FileCheck %s --check-prefix=IMPORTFUNCPTR
+; IMPORTFUNCPTR: @P.llvm.1 = available_externally hidden global void ()* null
+; IMPORTFUNCPTR: define available_externally void @callfuncptr
+; IMPORTFUNCPTR: %0 = load void ()*, void ()** @P.llvm.1
+
+; Ensure that imported weak function reference/definition handled properly.
+; Imported weak_any definition should be skipped with warning, and imported
+; reference should turned into an external_weak declaration.
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=callweakfunc:%t.bc -import=weakfunc:%t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORTWEAKFUNC
+; IMPORTWEAKFUNC: Ignoring import request for weak-any function weakfunc
+; IMPORTWEAKFUNC: declare extern_weak void @weakfunc
+; IMPORTWEAKFUNC: define available_externally void @callweakfunc
+
+ at globalvar = global i32 1, align 4
+ at staticvar = internal global i32 1, align 4
+ at staticconstvar = internal unnamed_addr constant [2 x i32] [i32 10, i32 20], align 4
+ at commonvar = common global i32 0, align 4
+ at P = internal global void ()* null, align 8
+
+ at weakalias = weak alias void (...), bitcast (void ()* @globalfunc1 to void (...)*)
+ at analias = alias void (...), bitcast (void ()* @globalfunc2 to void (...)*)
+
+define void @globalfunc1() #0 {
+entry:
+ ret void
+}
+
+define void @globalfunc2() #0 {
+entry:
+ ret void
+}
+
+define i32 @referencestatics(i32 %i) #0 {
+entry:
+ %i.addr = alloca i32, align 4
+ store i32 %i, i32* %i.addr, align 4
+ %call = call i32 @staticfunc()
+ %0 = load i32, i32* @staticvar, align 4
+ %add = add nsw i32 %call, %0
+ %1 = load i32, i32* %i.addr, align 4
+ %idxprom = sext i32 %1 to i64
+ %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* @staticconstvar, i64 0, i64 %idxprom
+ %2 = load i32, i32* %arrayidx, align 4
+ %add1 = add nsw i32 %add, %2
+ ret i32 %add1
+}
+
+define i32 @referenceglobals(i32 %i) #0 {
+entry:
+ %i.addr = alloca i32, align 4
+ store i32 %i, i32* %i.addr, align 4
+ call void @globalfunc1()
+ %0 = load i32, i32* @globalvar, align 4
+ ret i32 %0
+}
+
+define i32 @referencecommon(i32 %i) #0 {
+entry:
+ %i.addr = alloca i32, align 4
+ store i32 %i, i32* %i.addr, align 4
+ %0 = load i32, i32* @commonvar, align 4
+ ret i32 %0
+}
+
+define void @setfuncptr() #0 {
+entry:
+ store void ()* @staticfunc2, void ()** @P, align 8
+ ret void
+}
+
+define void @callfuncptr() #0 {
+entry:
+ %0 = load void ()*, void ()** @P, align 8
+ call void %0()
+ ret void
+}
+
+define weak void @weakfunc() #0 {
+entry:
+ ret void
+}
+
+define void @callweakfunc() #0 {
+entry:
+ call void @weakfunc()
+ ret void
+}
+
+define internal i32 @staticfunc() #0 {
+entry:
+ ret i32 1
+}
+
+define internal void @staticfunc2() #0 {
+entry:
+ ret void
+}
Modified: llvm/trunk/tools/llvm-link/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-link/CMakeLists.txt?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-link/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-link/CMakeLists.txt Mon Nov 2 18:14:15 2015
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS
Core
IRReader
Linker
+ Object
Support
)
Modified: llvm/trunk/tools/llvm-link/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-link/LLVMBuild.txt?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-link/LLVMBuild.txt (original)
+++ llvm/trunk/tools/llvm-link/LLVMBuild.txt Mon Nov 2 18:14:15 2015
@@ -19,4 +19,4 @@
type = Tool
name = llvm-link
parent = Tools
-required_libraries = AsmParser BitReader BitWriter IRReader Linker
+required_libraries = AsmParser BitReader BitWriter IRReader Linker Object
Modified: llvm/trunk/tools/llvm-link/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-link/Makefile?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-link/Makefile (original)
+++ llvm/trunk/tools/llvm-link/Makefile Mon Nov 2 18:14:15 2015
@@ -9,7 +9,7 @@
LEVEL := ../..
TOOLNAME := llvm-link
-LINK_COMPONENTS := linker bitreader bitwriter asmparser irreader
+LINK_COMPONENTS := linker bitreader bitwriter asmparser irreader object
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
Modified: llvm/trunk/tools/llvm-link/llvm-link.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-link/llvm-link.cpp?rev=251866&r1=251865&r2=251866&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-link/llvm-link.cpp (original)
+++ llvm/trunk/tools/llvm-link/llvm-link.cpp Mon Nov 2 18:14:15 2015
@@ -18,10 +18,12 @@
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/FunctionInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
+#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
@@ -43,6 +45,23 @@ static cl::list<std::string> OverridingI
cl::desc(
"input bitcode file which can override previously defined symbol(s)"));
+// Option to simulate function importing for testing. This enables using
+// llvm-link to simulate ThinLTO backend processes.
+static cl::list<std::string> Imports(
+ "import", cl::ZeroOrMore, cl::value_desc("function:filename"),
+ cl::desc("Pair of function name and filename, where function should be "
+ "imported from bitcode in filename"));
+
+// Option to support testing of function importing. The function index
+// must be specified in the case were we request imports via the -import
+// option, as well as when compiling any module with functions that may be
+// exported (imported by a different llvm-link -import invocation), to ensure
+// consistent promotion and renaming of locals.
+static cl::opt<std::string> FunctionIndex("functionindex",
+ cl::desc("Function index filename"),
+ cl::init(""),
+ cl::value_desc("filename"));
+
static cl::opt<std::string>
OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
cl::value_desc("filename"));
@@ -118,6 +137,90 @@ static void diagnosticHandler(const Diag
errs() << '\n';
}
+/// Load a function index if requested by the -functionindex option.
+static ErrorOr<std::unique_ptr<FunctionInfoIndex>>
+loadIndex(LLVMContext &Context, const Module *ExportingModule = nullptr) {
+ assert(!FunctionIndex.empty());
+ ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
+ MemoryBuffer::getFileOrSTDIN(FunctionIndex);
+ std::error_code EC = FileOrErr.getError();
+ if (EC)
+ return EC;
+ MemoryBufferRef BufferRef = (FileOrErr.get())->getMemBufferRef();
+ ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
+ object::FunctionIndexObjectFile::create(BufferRef, Context,
+ ExportingModule);
+ EC = ObjOrErr.getError();
+ if (EC)
+ return EC;
+
+ object::FunctionIndexObjectFile &Obj = **ObjOrErr;
+ return Obj.takeIndex();
+}
+
+/// Import any functions requested via the -import option.
+static bool importFunctions(const char *argv0, LLVMContext &Context,
+ Linker &L) {
+ for (const auto &Import : Imports) {
+ // Identify the requested function and its bitcode source file.
+ size_t Idx = Import.find(':');
+ if (Idx == std::string::npos) {
+ errs() << "Import parameter bad format: " << Import << "\n";
+ return false;
+ }
+ std::string FunctionName = Import.substr(0, Idx);
+ std::string FileName = Import.substr(Idx + 1, std::string::npos);
+
+ // Load the specified source module.
+ std::unique_ptr<Module> M = loadFile(argv0, FileName, Context);
+ if (!M.get()) {
+ errs() << argv0 << ": error loading file '" << FileName << "'\n";
+ return false;
+ }
+
+ if (verifyModule(*M, &errs())) {
+ errs() << argv0 << ": " << FileName
+ << ": error: input module is broken!\n";
+ return false;
+ }
+
+ Function *F = M->getFunction(FunctionName);
+ if (!F) {
+ errs() << "Ignoring import request for non-existent function "
+ << FunctionName << " from " << FileName << "\n";
+ continue;
+ }
+ // We cannot import weak_any functions without possibly affecting the
+ // order they are seen and selected by the linker, changing program
+ // semantics.
+ if (F->hasWeakAnyLinkage()) {
+ errs() << "Ignoring import request for weak-any function " << FunctionName
+ << " from " << FileName << "\n";
+ continue;
+ }
+
+ if (Verbose)
+ errs() << "Importing " << FunctionName << " from " << FileName << "\n";
+
+ std::unique_ptr<FunctionInfoIndex> Index;
+ if (!FunctionIndex.empty()) {
+ ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
+ loadIndex(Context);
+ std::error_code EC = IndexOrErr.getError();
+ if (EC) {
+ errs() << EC.message() << '\n';
+ return false;
+ }
+ Index = std::move(IndexOrErr.get());
+ }
+
+ // Link in the specified function.
+ if (L.linkInModule(M.get(), false, Index.get(), F))
+ return false;
+ }
+ return true;
+}
+
static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
const cl::list<std::string> &Files,
unsigned Flags) {
@@ -135,10 +238,24 @@ static bool linkFiles(const char *argv0,
return false;
}
+ // If a function index is supplied, load it so linkInModule can treat
+ // local functions/variables as exported and promote if necessary.
+ std::unique_ptr<FunctionInfoIndex> Index;
+ if (!FunctionIndex.empty()) {
+ ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
+ loadIndex(Context, &*M);
+ std::error_code EC = IndexOrErr.getError();
+ if (EC) {
+ errs() << EC.message() << '\n';
+ return false;
+ }
+ Index = std::move(IndexOrErr.get());
+ }
+
if (Verbose)
errs() << "Linking in '" << File << "'\n";
- if (L.linkInModule(M.get(), ApplicableFlags))
+ if (L.linkInModule(M.get(), ApplicableFlags, Index.get()))
return false;
// All linker flags apply to linking of subsequent files.
ApplicableFlags = Flags;
@@ -174,6 +291,10 @@ int main(int argc, char **argv) {
Flags | Linker::Flags::OverrideFromSrc))
return 1;
+ // Import any functions requested via -import
+ if (!importFunctions(argv[0], Context, L))
+ return 1;
+
if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;
std::error_code EC;
More information about the llvm-commits
mailing list