forked from OSchip/llvm-project
Revert "Support for ThinLTO function importing and symbol linking."
This reverts commit r251837, due to a number of bot failures of the form: /home/grosser/buildslave/perf-x86_64-penryn-O3-polly-fast/llvm.obj/tools/llvm-link/Release+Asserts/llvm-link.o:llvm-link.cpp:function loadIndex(llvm::LLVMContext&, llvm::Module const*): error: undefined reference to 'llvm::object::FunctionIndexObjectFile::create(llvm::MemoryBufferRef, llvm::LLVMContext&, llvm::Module const*, bool)' /home/grosser/buildslave/perf-x86_64-penryn-O3-polly-fast/llvm.obj/tools/llvm-link/Release+Asserts/llvm-link.o:llvm-link.cpp:function loadIndex(llvm::LLVMContext&, llvm::Module const*): error: undefined reference to 'llvm::object::FunctionIndexObjectFile::takeIndex()' I'm not sure why these are happening - I added Object to the requred libraries in tools/llvm-link/LLVMBuild.txt and the LLVM_LINK_COMPONENTS in tools/llvm-link/CMakeLists.txt. Confirmed for my build that these symbols come out of libLLVMObject.a. What am I missing? llvm-svn: 251841
This commit is contained in:
parent
a7cd16b252
commit
227a923140
|
@ -64,8 +64,6 @@ 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.
|
||||
|
@ -73,7 +71,6 @@ 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
|
||||
|
|
|
@ -165,18 +165,8 @@ 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(const Module *M = nullptr)
|
||||
: ExportingModule(M), HasExportedFunctions(false){};
|
||||
FunctionInfoIndex() = default;
|
||||
~FunctionInfoIndex() = default;
|
||||
|
||||
// Disable the copy constructor and assignment operators, so
|
||||
|
@ -196,12 +186,6 @@ 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));
|
||||
}
|
||||
|
||||
|
@ -239,14 +223,6 @@ 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
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/IR/DiagnosticInfo.h"
|
||||
#include "llvm/IR/FunctionInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
|
@ -77,13 +76,8 @@ 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,
|
||||
FunctionInfoIndex *Index = nullptr,
|
||||
Function *FuncToImport = nullptr);
|
||||
bool linkInModule(Module *Src, unsigned Flags = Flags::None);
|
||||
|
||||
/// \brief Set the composite to the passed-in module.
|
||||
void setModule(Module *Dst);
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
namespace llvm {
|
||||
class FunctionInfoIndex;
|
||||
class Module;
|
||||
|
||||
namespace object {
|
||||
class ObjectFile;
|
||||
|
@ -85,8 +84,7 @@ public:
|
|||
/// Return new FunctionIndexObjectFile instance containing parsed function
|
||||
/// summary/index.
|
||||
static ErrorOr<std::unique_ptr<FunctionIndexObjectFile>>
|
||||
create(MemoryBufferRef Object, LLVMContext &Context,
|
||||
const Module *ExportingModule = nullptr, bool IsLazy = false);
|
||||
create(MemoryBufferRef Object, LLVMContext &Context, bool IsLazy = false);
|
||||
|
||||
/// \brief Parse the function summary information for function with the
|
||||
/// given name out of the given buffer. Parsed information is
|
||||
|
|
|
@ -5813,12 +5813,12 @@ llvm::getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context,
|
|||
ErrorOr<std::unique_ptr<FunctionInfoIndex>>
|
||||
llvm::getFunctionInfoIndex(MemoryBufferRef Buffer, LLVMContext &Context,
|
||||
DiagnosticHandlerFunction DiagnosticHandler,
|
||||
const Module *ExportingModule, bool IsLazy) {
|
||||
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>(ExportingModule);
|
||||
llvm::make_unique<FunctionInfoIndex>();
|
||||
|
||||
auto cleanupOnError = [&](std::error_code EC) {
|
||||
R.releaseBuffer(); // Never take ownership on error.
|
||||
|
|
|
@ -369,14 +369,12 @@ class ValueMaterializerTy final : public ValueMaterializer {
|
|||
TypeMapTy &TypeMap;
|
||||
Module *DstM;
|
||||
std::vector<GlobalValue *> &LazilyLinkGlobalValues;
|
||||
ModuleLinker *ModLinker;
|
||||
|
||||
public:
|
||||
ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM,
|
||||
std::vector<GlobalValue *> &LazilyLinkGlobalValues,
|
||||
ModuleLinker *ModLinker)
|
||||
std::vector<GlobalValue *> &LazilyLinkGlobalValues)
|
||||
: ValueMaterializer(), TypeMap(TypeMap), DstM(DstM),
|
||||
LazilyLinkGlobalValues(LazilyLinkGlobalValues), ModLinker(ModLinker) {}
|
||||
LazilyLinkGlobalValues(LazilyLinkGlobalValues) {}
|
||||
|
||||
Value *materializeValueFor(Value *V) override;
|
||||
};
|
||||
|
@ -429,38 +427,12 @@ 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,
|
||||
FunctionInfoIndex *Index = nullptr,
|
||||
Function *FuncToImport = nullptr)
|
||||
DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags)
|
||||
: DstM(dstM), SrcM(srcM), TypeMap(Set),
|
||||
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);
|
||||
}
|
||||
ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues),
|
||||
DiagnosticHandler(DiagnosticHandler), Flags(Flags) {}
|
||||
|
||||
bool run();
|
||||
|
||||
|
@ -470,14 +442,6 @@ 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);
|
||||
|
@ -544,42 +508,6 @@ 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();
|
||||
};
|
||||
|
@ -591,9 +519,6 @@ 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;
|
||||
|
||||
|
@ -611,23 +536,9 @@ static void forceRenaming(GlobalValue *GV, StringRef Name) {
|
|||
|
||||
/// copy additional attributes (those not needed to construct a GlobalValue)
|
||||
/// from the SrcGV to the DestGV.
|
||||
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 void copyGVAttributes(GlobalValue *DestGV, const GlobalValue *SrcGV) {
|
||||
DestGV->copyAttributesFrom(SrcGV);
|
||||
forceRenaming(DestGV, SrcGV->getName());
|
||||
}
|
||||
|
||||
static bool isLessConstraining(GlobalValue::VisibilityTypes a,
|
||||
|
@ -643,169 +554,17 @@ static bool isLessConstraining(GlobalValue::VisibilityTypes a,
|
|||
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.
|
||||
GlobalVariable *
|
||||
ModuleLinker::copyGlobalVariableProto(TypeMapTy &TypeMap,
|
||||
static GlobalVariable *copyGlobalVariableProto(TypeMapTy &TypeMap, Module &DstM,
|
||||
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(), getLinkage(SGVar), /*init*/ nullptr, getName(SGVar),
|
||||
/*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
|
||||
DstM, TypeMap.get(SGVar->getType()->getElementType()),
|
||||
SGVar->isConstant(), SGVar->getLinkage(), /*init*/ nullptr,
|
||||
SGVar->getName(), /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
|
||||
SGVar->getType()->getAddressSpace());
|
||||
|
||||
return NewDGV;
|
||||
|
@ -813,75 +572,34 @@ ModuleLinker::copyGlobalVariableProto(TypeMapTy &TypeMap,
|
|||
|
||||
/// Link the function in the source module into the destination module if
|
||||
/// needed, setting up mapping information.
|
||||
Function *ModuleLinker::copyFunctionProto(TypeMapTy &TypeMap,
|
||||
static Function *copyFunctionProto(TypeMapTy &TypeMap, Module &DstM,
|
||||
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()), getLinkage(SF),
|
||||
getName(SF), DstM);
|
||||
return Function::Create(TypeMap.get(SF->getFunctionType()), SF->getLinkage(),
|
||||
SF->getName(), &DstM);
|
||||
}
|
||||
|
||||
/// Set up prototypes for any aliases that come over from the source module.
|
||||
GlobalValue *ModuleLinker::copyGlobalAliasProto(TypeMapTy &TypeMap,
|
||||
static GlobalAlias *copyGlobalAliasProto(TypeMapTy &TypeMap, Module &DstM,
|
||||
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(),
|
||||
getLinkage(SGA), getName(SGA), DstM);
|
||||
SGA->getLinkage(), SGA->getName(), &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);
|
||||
}
|
||||
|
||||
GlobalValue *ModuleLinker::copyGlobalValueProto(TypeMapTy &TypeMap,
|
||||
const GlobalValue *SGV,
|
||||
const GlobalValue *DGV) {
|
||||
static GlobalValue *copyGlobalValueProto(TypeMapTy &TypeMap, Module &DstM,
|
||||
const GlobalValue *SGV) {
|
||||
GlobalValue *NewGV;
|
||||
if (auto *SGVar = dyn_cast<GlobalVariable>(SGV))
|
||||
NewGV = copyGlobalVariableProto(TypeMap, SGVar);
|
||||
NewGV = copyGlobalVariableProto(TypeMap, DstM, SGVar);
|
||||
else if (auto *SF = dyn_cast<Function>(SGV))
|
||||
NewGV = copyFunctionProto(TypeMap, SF);
|
||||
NewGV = copyFunctionProto(TypeMap, DstM, SF);
|
||||
else
|
||||
NewGV = copyGlobalAliasProto(TypeMap, cast<GlobalAlias>(SGV));
|
||||
NewGV = copyGlobalAliasProto(TypeMap, DstM, cast<GlobalAlias>(SGV));
|
||||
copyGVAttributes(NewGV, SGV);
|
||||
setVisibility(NewGV, SGV, DGV);
|
||||
return NewGV;
|
||||
}
|
||||
|
||||
|
@ -890,7 +608,7 @@ Value *ValueMaterializerTy::materializeValueFor(Value *V) {
|
|||
if (!SGV)
|
||||
return nullptr;
|
||||
|
||||
GlobalValue *DGV = ModLinker->copyGlobalValueProto(TypeMap, SGV);
|
||||
GlobalValue *DGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
|
||||
|
||||
if (Comdat *SC = SGV->getComdat()) {
|
||||
if (auto *DGO = dyn_cast<GlobalObject>(DGV)) {
|
||||
|
@ -1024,9 +742,6 @@ bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,
|
|||
|
||||
// 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;
|
||||
}
|
||||
|
@ -1034,28 +749,6 @@ bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,
|
|||
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.
|
||||
|
@ -1347,21 +1040,13 @@ bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) {
|
|||
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()) {
|
||||
|
@ -1385,8 +1070,12 @@ bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) {
|
|||
ConstantExpr::getBitCast(DGV, TypeMap.get(SGV->getType()));
|
||||
}
|
||||
|
||||
if (DGV)
|
||||
if (DGV) {
|
||||
Visibility = isLessConstraining(Visibility, DGV->getVisibility())
|
||||
? DGV->getVisibility()
|
||||
: Visibility;
|
||||
HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr();
|
||||
}
|
||||
|
||||
if (!LinkFromSrc && !DGV)
|
||||
return false;
|
||||
|
@ -1394,12 +1083,10 @@ bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) {
|
|||
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() && SGV != ImportFunction &&
|
||||
if (!DGV && !shouldOverrideFromSrc() &&
|
||||
(SGV->hasLocalLinkage() || SGV->hasLinkOnceLinkage() ||
|
||||
SGV->hasAvailableExternallyLinkage())) {
|
||||
DoNotLinkFromSource.insert(SGV);
|
||||
|
@ -1413,7 +1100,7 @@ bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) {
|
|||
return false;
|
||||
}
|
||||
|
||||
NewGV = copyGlobalValueProto(TypeMap, SGV, DGV);
|
||||
NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
|
||||
|
||||
if (DGV && isa<Function>(DGV))
|
||||
if (auto *NewF = dyn_cast<Function>(NewGV))
|
||||
|
@ -1421,6 +1108,7 @@ bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) {
|
|||
}
|
||||
|
||||
NewGV->setUnnamedAddr(HasUnnamedAddr);
|
||||
NewGV->setVisibility(Visibility);
|
||||
|
||||
if (auto *NewGO = dyn_cast<GlobalObject>(NewGV)) {
|
||||
if (C)
|
||||
|
@ -1925,10 +1613,6 @@ 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;
|
||||
}
|
||||
|
@ -1962,8 +1646,6 @@ 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.
|
||||
|
@ -2097,10 +1779,9 @@ void Linker::deleteModule() {
|
|||
Composite = nullptr;
|
||||
}
|
||||
|
||||
bool Linker::linkInModule(Module *Src, unsigned Flags, FunctionInfoIndex *Index,
|
||||
Function *FuncToImport) {
|
||||
bool Linker::linkInModule(Module *Src, unsigned Flags) {
|
||||
ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src,
|
||||
DiagnosticHandler, Flags, Index, FuncToImport);
|
||||
DiagnosticHandler, Flags);
|
||||
bool RetCode = TheLinker.run();
|
||||
Composite->dropTriviallyDeadConstantArrays();
|
||||
return RetCode;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//===- FunctionIndexObjectFile.cpp - Function index file implementation ---===//
|
||||
//===- FunctionIndexObjectFile.cpp - Function index file implementation
|
||||
//----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -85,15 +86,15 @@ bool FunctionIndexObjectFile::hasFunctionSummaryInMemBuffer(
|
|||
// function summary/index.
|
||||
ErrorOr<std::unique_ptr<FunctionIndexObjectFile>>
|
||||
FunctionIndexObjectFile::create(MemoryBufferRef Object, LLVMContext &Context,
|
||||
const Module *ExportingModule, bool IsLazy) {
|
||||
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, ExportingModule, IsLazy);
|
||||
ErrorOr<std::unique_ptr<FunctionInfoIndex>> IOrErr =
|
||||
getFunctionInfoIndex(BCOrErr.get(), Context, nullptr, IsLazy);
|
||||
|
||||
if (std::error_code EC = IOrErr.getError())
|
||||
return EC;
|
||||
|
|
|
@ -49,46 +49,9 @@ ModulePass *llvm::createEliminateAvailableExternallyPass() {
|
|||
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())
|
||||
|
@ -102,7 +65,6 @@ bool EliminateAvailableExternally::runOnModule(Module &M) {
|
|||
GV.removeDeadConstantUsers();
|
||||
GV.setLinkage(GlobalValue::ExternalLinkage);
|
||||
NumVariables++;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
// Drop the bodies of available externally functions.
|
||||
|
@ -114,7 +76,6 @@ bool EliminateAvailableExternally::runOnModule(Module &M) {
|
|||
F.deleteBody();
|
||||
F.removeDeadConstantUsers();
|
||||
NumFunctions++;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
return Changed;
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
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
|
|
@ -1,169 +0,0 @@
|
|||
; 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
|
||||
|
||||
@globalvar = global i32 1, align 4
|
||||
@staticvar = internal global i32 1, align 4
|
||||
@staticconstvar = internal unnamed_addr constant [2 x i32] [i32 10, i32 20], align 4
|
||||
@commonvar = common global i32 0, align 4
|
||||
@P = internal global void ()* null, align 8
|
||||
|
||||
@weakalias = weak alias void (...), bitcast (void ()* @globalfunc1 to void (...)*)
|
||||
@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
|
||||
}
|
|
@ -3,7 +3,6 @@ set(LLVM_LINK_COMPONENTS
|
|||
Core
|
||||
IRReader
|
||||
Linker
|
||||
Object
|
||||
Support
|
||||
)
|
||||
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
type = Tool
|
||||
name = llvm-link
|
||||
parent = Tools
|
||||
required_libraries = AsmParser BitReader BitWriter IRReader Linker Object
|
||||
required_libraries = AsmParser BitReader BitWriter IRReader Linker
|
||||
|
|
|
@ -18,12 +18,10 @@
|
|||
#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"
|
||||
|
@ -45,23 +43,6 @@ static cl::list<std::string> OverridingInputs(
|
|||
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"));
|
||||
|
@ -137,90 +118,6 @@ static void diagnosticHandler(const DiagnosticInfo &DI) {
|
|||
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) {
|
||||
|
@ -238,24 +135,10 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
|
|||
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, Index.get()))
|
||||
if (L.linkInModule(M.get(), ApplicableFlags))
|
||||
return false;
|
||||
// All linker flags apply to linking of subsequent files.
|
||||
ApplicableFlags = Flags;
|
||||
|
@ -291,10 +174,6 @@ 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;
|
||||
|
|
Loading…
Reference in New Issue