Make it possible to use the linker without destroying the source module. This is so the source module can be linked to multiple other destination modules. For all that used LinkModules() before, they will continue to destroy the source module as before.

This line, and those below, will be ignored--

M    include/llvm/Linker.h
M    tools/bugpoint/Miscompilation.cpp
M    tools/bugpoint/BugDriver.cpp
M    tools/llvm-link/llvm-link.cpp
M    lib/Linker/LinkModules.cpp


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141606 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Tanya Lattner 2011-10-11 00:24:54 +00:00
parent fad138dd79
commit f1f1a4f161
5 changed files with 73 additions and 38 deletions

View File

@ -57,7 +57,12 @@ class Linker {
QuietWarnings = 2, ///< Don't print warnings to stderr. QuietWarnings = 2, ///< Don't print warnings to stderr.
QuietErrors = 4 ///< Don't print errors to stderr. QuietErrors = 4 ///< Don't print errors to stderr.
}; };
enum LinkerMode {
DestroySource = 0, // Allow source module to be destroyed.
PreserveSource = 1 // Preserve the source module.
};
/// @} /// @}
/// @name Constructors /// @name Constructors
/// @{ /// @{
@ -245,7 +250,7 @@ class Linker {
Module* Src, ///< Module linked into \p Dest Module* Src, ///< Module linked into \p Dest
std::string* ErrorMsg = 0 /// Error/diagnostic string std::string* ErrorMsg = 0 /// Error/diagnostic string
) { ) {
return LinkModules(Composite, Src, ErrorMsg ); return LinkModules(Composite, Src, Linker::DestroySource, ErrorMsg );
} }
/// This is the heart of the linker. This method will take unconditional /// This is the heart of the linker. This method will take unconditional
@ -259,7 +264,8 @@ class Linker {
/// error. /// error.
/// @returns True if an error occurs, false otherwise. /// @returns True if an error occurs, false otherwise.
/// @brief Generically link two modules together. /// @brief Generically link two modules together.
static bool LinkModules(Module* Dest, Module* Src, std::string* ErrorMsg); static bool LinkModules(Module* Dest, Module* Src, unsigned Mode,
std::string* ErrorMsg);
/// This function looks through the Linker's LibPaths to find a library with /// This function looks through the Linker's LibPaths to find a library with
/// the name \p Filename. If the library cannot be found, the returned path /// the name \p Filename. If the library cannot be found, the returned path

View File

@ -14,9 +14,12 @@
#include "llvm/Linker.h" #include "llvm/Linker.h"
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/ValueMapper.h" #include "llvm/Transforms/Utils/ValueMapper.h"
using namespace llvm; using namespace llvm;
@ -333,10 +336,16 @@ namespace {
std::vector<AppendingVarInfo> AppendingVars; std::vector<AppendingVarInfo> AppendingVars;
unsigned Mode; // Mode to treat source module.
// Set of items not to link in from source.
SmallPtrSet<const Value*, 16> DoNotLinkFromSource;
public: public:
std::string ErrorMsg; std::string ErrorMsg;
ModuleLinker(Module *dstM, Module *srcM) : DstM(dstM), SrcM(srcM) { } ModuleLinker(Module *dstM, Module *srcM, unsigned mode)
: DstM(dstM), SrcM(srcM), Mode(mode) { }
bool run(); bool run();
@ -596,9 +605,9 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType())); DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
DstGV->eraseFromParent(); DstGV->eraseFromParent();
// Zap the initializer in the source variable so we don't try to link it. // Track the source variable so we don't try to link it.
SrcGV->setInitializer(0); DoNotLinkFromSource.insert(SrcGV);
SrcGV->setLinkage(GlobalValue::ExternalLinkage);
return false; return false;
} }
@ -633,11 +642,10 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
// Make sure to remember this mapping. // Make sure to remember this mapping.
ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType())); ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType()));
// Destroy the source global's initializer (and convert it to a prototype) // Track the source global so that we don't attempt to copy it over when
// so that we don't attempt to copy it over when processing global // processing global initializers.
// initializers. DoNotLinkFromSource.insert(SGV);
SGV->setInitializer(0);
SGV->setLinkage(GlobalValue::ExternalLinkage);
return false; return false;
} }
} }
@ -682,8 +690,10 @@ bool ModuleLinker::linkFunctionProto(Function *SF) {
// Make sure to remember this mapping. // Make sure to remember this mapping.
ValueMap[SF] = ConstantExpr::getBitCast(DGV, TypeMap.get(SF->getType())); ValueMap[SF] = ConstantExpr::getBitCast(DGV, TypeMap.get(SF->getType()));
// Remove the body from the source module so we don't attempt to remap it. // Track the function from the source module so we don't attempt to remap
SF->deleteBody(); // it.
DoNotLinkFromSource.insert(SF);
return false; return false;
} }
} }
@ -722,8 +732,9 @@ bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
// Make sure to remember this mapping. // Make sure to remember this mapping.
ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType())); ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType()));
// Remove the body from the source module so we don't attempt to remap it. // Track the alias from the source module so we don't attempt to remap it.
SGA->setAliasee(0); DoNotLinkFromSource.insert(SGA);
return false; return false;
} }
} }
@ -779,7 +790,9 @@ void ModuleLinker::linkGlobalInits() {
// Loop over all of the globals in the src module, mapping them over as we go // Loop over all of the globals in the src module, mapping them over as we go
for (Module::const_global_iterator I = SrcM->global_begin(), for (Module::const_global_iterator I = SrcM->global_begin(),
E = SrcM->global_end(); I != E; ++I) { E = SrcM->global_end(); I != E; ++I) {
if (!I->hasInitializer()) continue; // Only process initialized GV's.
// Only process initialized GV's or ones not already in dest.
if (!I->hasInitializer() || DoNotLinkFromSource.count(I)) continue;
// Grab destination global variable. // Grab destination global variable.
GlobalVariable *DGV = cast<GlobalVariable>(ValueMap[I]); GlobalVariable *DGV = cast<GlobalVariable>(ValueMap[I]);
@ -805,31 +818,42 @@ void ModuleLinker::linkFunctionBody(Function *Dst, Function *Src) {
ValueMap[I] = DI; ValueMap[I] = DI;
} }
// Splice the body of the source function into the dest function. if (Mode == Linker::DestroySource) {
Dst->getBasicBlockList().splice(Dst->end(), Src->getBasicBlockList()); // Splice the body of the source function into the dest function.
Dst->getBasicBlockList().splice(Dst->end(), Src->getBasicBlockList());
// At this point, all of the instructions and values of the function are now
// copied over. The only problem is that they are still referencing values in // At this point, all of the instructions and values of the function are now
// the Source function as operands. Loop through all of the operands of the // copied over. The only problem is that they are still referencing values in
// functions and patch them up to point to the local versions. // the Source function as operands. Loop through all of the operands of the
for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB) // functions and patch them up to point to the local versions.
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB)
RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, &TypeMap); for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, &TypeMap);
} else {
// Clone the body of the function into the dest function.
SmallVector<ReturnInst*, 8> Returns; // Ignore returns.
CloneFunctionInto(Dst, Src, ValueMap, false, Returns);
}
// There is no need to map the arguments anymore. // There is no need to map the arguments anymore.
for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end();
I != E; ++I) I != E; ++I)
ValueMap.erase(I); ValueMap.erase(I);
} }
void ModuleLinker::linkAliasBodies() { void ModuleLinker::linkAliasBodies() {
for (Module::alias_iterator I = SrcM->alias_begin(), E = SrcM->alias_end(); for (Module::alias_iterator I = SrcM->alias_begin(), E = SrcM->alias_end();
I != E; ++I) I != E; ++I) {
if (DoNotLinkFromSource.count(I))
continue;
if (Constant *Aliasee = I->getAliasee()) { if (Constant *Aliasee = I->getAliasee()) {
GlobalAlias *DA = cast<GlobalAlias>(ValueMap[I]); GlobalAlias *DA = cast<GlobalAlias>(ValueMap[I]);
DA->setAliasee(MapValue(Aliasee, ValueMap, RF_None, &TypeMap)); DA->setAliasee(MapValue(Aliasee, ValueMap, RF_None, &TypeMap));
} }
}
} }
/// linkNamedMDNodes - Insert all of the named mdnodes in Src into the Dest /// linkNamedMDNodes - Insert all of the named mdnodes in Src into the Dest
@ -891,7 +915,6 @@ bool ModuleLinker::run() {
StringRef ModuleId = SrcM->getModuleIdentifier(); StringRef ModuleId = SrcM->getModuleIdentifier();
if (!ModuleId.empty()) if (!ModuleId.empty())
DstM->removeLibrary(sys::path::stem(ModuleId)); DstM->removeLibrary(sys::path::stem(ModuleId));
// Loop over all of the linked values to compute type mappings. // Loop over all of the linked values to compute type mappings.
computeTypeMapping(); computeTypeMapping();
@ -928,7 +951,8 @@ bool ModuleLinker::run() {
// Link in the function bodies that are defined in the source module into // Link in the function bodies that are defined in the source module into
// DstM. // DstM.
for (Module::iterator SF = SrcM->begin(), E = SrcM->end(); SF != E; ++SF) { for (Module::iterator SF = SrcM->begin(), E = SrcM->end(); SF != E; ++SF) {
if (SF->isDeclaration()) continue; // No body if function is external. // Skip if no body (function is external) or marked to skip.
if (SF->isDeclaration() || DoNotLinkFromSource.count(SF)) continue;
linkFunctionBody(cast<Function>(ValueMap[SF]), SF); linkFunctionBody(cast<Function>(ValueMap[SF]), SF);
} }
@ -957,8 +981,9 @@ bool ModuleLinker::run() {
// error occurs, true is returned and ErrorMsg (if not null) is set to indicate // error occurs, true is returned and ErrorMsg (if not null) is set to indicate
// the problem. Upon failure, the Dest module could be in a modified state, and // the problem. Upon failure, the Dest module could be in a modified state, and
// shouldn't be relied on to be consistent. // shouldn't be relied on to be consistent.
bool Linker::LinkModules(Module *Dest, Module *Src, std::string *ErrorMsg) { bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode,
ModuleLinker TheLinker(Dest, Src); std::string *ErrorMsg) {
ModuleLinker TheLinker(Dest, Src, Mode);
if (TheLinker.run()) { if (TheLinker.run()) {
if (ErrorMsg) *ErrorMsg = TheLinker.ErrorMsg; if (ErrorMsg) *ErrorMsg = TheLinker.ErrorMsg;
return true; return true;

View File

@ -127,7 +127,8 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
outs() << "Linking in input file: '" << Filenames[i] << "'\n"; outs() << "Linking in input file: '" << Filenames[i] << "'\n";
std::string ErrorMessage; std::string ErrorMessage;
if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) { if (Linker::LinkModules(Program, M.get(), Linker::DestroySource,
&ErrorMessage)) {
errs() << ToolName << ": error linking in '" << Filenames[i] << "': " errs() << ToolName << ": error linking in '" << Filenames[i] << "': "
<< ErrorMessage << '\n'; << ErrorMessage << '\n';
return true; return true;

View File

@ -222,7 +222,7 @@ static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2,
M1 = CloneModule(M1); M1 = CloneModule(M1);
M2 = CloneModule(M2); M2 = CloneModule(M2);
} }
if (Linker::LinkModules(M1, M2, &ErrorMsg)) { if (Linker::LinkModules(M1, M2, Linker::DestroySource, &ErrorMsg)) {
errs() << BD.getToolName() << ": Error linking modules together:" errs() << BD.getToolName() << ": Error linking modules together:"
<< ErrorMsg << '\n'; << ErrorMsg << '\n';
exit(1); exit(1);
@ -396,7 +396,8 @@ static bool ExtractLoops(BugDriver &BD,
// Replace the current program with the loop extracted version, and try to // Replace the current program with the loop extracted version, and try to
// extract another loop. // extract another loop.
std::string ErrorMsg; std::string ErrorMsg;
if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){ if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted,
Linker::DestroySource, &ErrorMsg)){
errs() << BD.getToolName() << ": Error linking modules together:" errs() << BD.getToolName() << ": Error linking modules together:"
<< ErrorMsg << '\n'; << ErrorMsg << '\n';
exit(1); exit(1);
@ -575,7 +576,8 @@ static bool ExtractBlocks(BugDriver &BD,
I->getFunctionType())); I->getFunctionType()));
std::string ErrorMsg; std::string ErrorMsg;
if (Linker::LinkModules(ProgClone, Extracted, &ErrorMsg)) { if (Linker::LinkModules(ProgClone, Extracted, Linker::DestroySource,
&ErrorMsg)) {
errs() << BD.getToolName() << ": Error linking modules together:" errs() << BD.getToolName() << ": Error linking modules together:"
<< ErrorMsg << '\n'; << ErrorMsg << '\n';
exit(1); exit(1);

View File

@ -103,7 +103,8 @@ int main(int argc, char **argv) {
if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n"; if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n";
if (Linker::LinkModules(Composite.get(), M.get(), &ErrorMessage)) { if (Linker::LinkModules(Composite.get(), M.get(), Linker::DestroySource,
&ErrorMessage)) {
errs() << argv[0] << ": link error in '" << InputFilenames[i] errs() << argv[0] << ": link error in '" << InputFilenames[i]
<< "': " << ErrorMessage << "\n"; << "': " << ErrorMessage << "\n";
return 1; return 1;