Make it possible to use the linker without destroying the source module. This is...
authorTanya Lattner <tonic@nondot.org>
Tue, 11 Oct 2011 00:24:54 +0000 (00:24 +0000)
committerTanya Lattner <tonic@nondot.org>
Tue, 11 Oct 2011 00:24:54 +0000 (00:24 +0000)
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

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

index b402a6090e2cf387743036c01f7c41689ecda8f7..88908fbd72a7eaac11390fac7614290a97a33589 100644 (file)
@@ -57,7 +57,12 @@ class Linker {
       QuietWarnings = 2, ///< Don't print warnings 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
   /// @{
@@ -245,7 +250,7 @@ class Linker {
       Module* Src,              ///< Module linked into \p Dest
       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
@@ -259,7 +264,8 @@ class Linker {
     /// error.
     /// @returns True if an error occurs, false otherwise.
     /// @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
     /// the name \p Filename. If the library cannot be found, the returned path
index 62a416eed64ca1f2e6f15d015fa1cc2ca8e3fa58..4ccabcf58600c6e45ef43d43f85d8e5bf0bd28be 100644 (file)
 #include "llvm/Linker.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
 #include "llvm/Module.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/ValueMapper.h"
 using namespace llvm;
 
@@ -333,10 +336,16 @@ namespace {
     
     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:
     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();
     
@@ -596,9 +605,9 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
   DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
   DstGV->eraseFromParent();
   
-  // Zap the initializer in the source variable so we don't try to link it.
-  SrcGV->setInitializer(0);
-  SrcGV->setLinkage(GlobalValue::ExternalLinkage);
+  // Track the source variable so we don't try to link it.
+  DoNotLinkFromSource.insert(SrcGV);
+  
   return false;
 }
 
@@ -633,11 +642,10 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
       // Make sure to remember this mapping.
       ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType()));
       
-      // Destroy the source global's initializer (and convert it to a prototype)
-      // so that we don't attempt to copy it over when processing global
-      // initializers.
-      SGV->setInitializer(0);
-      SGV->setLinkage(GlobalValue::ExternalLinkage);
+      // Track the source global so that we don't attempt to copy it over when 
+      // processing global initializers.
+      DoNotLinkFromSource.insert(SGV);
+      
       return false;
     }
   }
@@ -682,8 +690,10 @@ bool ModuleLinker::linkFunctionProto(Function *SF) {
       // Make sure to remember this mapping.
       ValueMap[SF] = ConstantExpr::getBitCast(DGV, TypeMap.get(SF->getType()));
       
-      // Remove the body from the source module so we don't attempt to remap it.
-      SF->deleteBody();
+      // Track the function from the source module so we don't attempt to remap 
+      // it.
+      DoNotLinkFromSource.insert(SF);
+      
       return false;
     }
   }
@@ -722,8 +732,9 @@ bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
       // Make sure to remember this mapping.
       ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType()));
       
-      // Remove the body from the source module so we don't attempt to remap it.
-      SGA->setAliasee(0);
+      // Track the alias from the source module so we don't attempt to remap it.
+      DoNotLinkFromSource.insert(SGA);
+      
       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
   for (Module::const_global_iterator I = SrcM->global_begin(),
        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.
     GlobalVariable *DGV = cast<GlobalVariable>(ValueMap[I]);
@@ -805,31 +818,42 @@ void ModuleLinker::linkFunctionBody(Function *Dst, Function *Src) {
     ValueMap[I] = DI;
   }
 
-  // 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
-  // the Source function as operands.  Loop through all of the operands of the
-  // functions and patch them up to point to the local versions.
-  for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB)
-    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
-      RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, &TypeMap);
-
+  if (Mode == Linker::DestroySource) {
+    // 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
+    // the Source function as operands.  Loop through all of the operands of the
+    // functions and patch them up to point to the local versions.
+    for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB)
+      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.
   for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end();
        I != E; ++I)
     ValueMap.erase(I);
+  
 }
 
 
 void ModuleLinker::linkAliasBodies() {
   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()) {
       GlobalAlias *DA = cast<GlobalAlias>(ValueMap[I]);
       DA->setAliasee(MapValue(Aliasee, ValueMap, RF_None, &TypeMap));
     }
+  }
 }
 
 /// linkNamedMDNodes - Insert all of the named mdnodes in Src into the Dest
@@ -891,7 +915,6 @@ bool ModuleLinker::run() {
   StringRef ModuleId = SrcM->getModuleIdentifier();
   if (!ModuleId.empty())
     DstM->removeLibrary(sys::path::stem(ModuleId));
-
   
   // Loop over all of the linked values to compute type mappings.
   computeTypeMapping();
@@ -928,7 +951,8 @@ bool ModuleLinker::run() {
   // Link in the function bodies that are defined in the source module into
   // DstM.
   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);
   }
@@ -957,8 +981,9 @@ bool ModuleLinker::run() {
 // 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
 // shouldn't be relied on to be consistent.
-bool Linker::LinkModules(Module *Dest, Module *Src, std::string *ErrorMsg) {
-  ModuleLinker TheLinker(Dest, Src);
+bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode, 
+                         std::string *ErrorMsg) {
+  ModuleLinker TheLinker(Dest, Src, Mode);
   if (TheLinker.run()) {
     if (ErrorMsg) *ErrorMsg = TheLinker.ErrorMsg;
     return true;
index aa3e2906364315feb21b72522a4fbc62c40cfe44..677d17887f40cec78b255d35bdc892bd12e81d1d 100644 (file)
@@ -127,7 +127,8 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
 
     outs() << "Linking in input file: '" << Filenames[i] << "'\n";
     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] << "': "
              << ErrorMessage << '\n';
       return true;
index 422ab62d820041e731cf80d67558ec9941e63f46..7ff16dbf958b3d9633e93203f26341d3b5ac3d78 100644 (file)
@@ -222,7 +222,7 @@ static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2,
     M1 = CloneModule(M1);
     M2 = CloneModule(M2);
   }
-  if (Linker::LinkModules(M1, M2, &ErrorMsg)) {
+  if (Linker::LinkModules(M1, M2, Linker::DestroySource, &ErrorMsg)) {
     errs() << BD.getToolName() << ": Error linking modules together:"
            << ErrorMsg << '\n';
     exit(1);
@@ -396,7 +396,8 @@ static bool ExtractLoops(BugDriver &BD,
     // Replace the current program with the loop extracted version, and try to
     // extract another loop.
     std::string ErrorMsg;
-    if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){
+    if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, 
+                            Linker::DestroySource, &ErrorMsg)){
       errs() << BD.getToolName() << ": Error linking modules together:"
              << ErrorMsg << '\n';
       exit(1);
@@ -575,7 +576,8 @@ static bool ExtractBlocks(BugDriver &BD,
                                                 I->getFunctionType()));
 
   std::string ErrorMsg;
-  if (Linker::LinkModules(ProgClone, Extracted, &ErrorMsg)) {
+  if (Linker::LinkModules(ProgClone, Extracted, Linker::DestroySource, 
+                          &ErrorMsg)) {
     errs() << BD.getToolName() << ": Error linking modules together:"
            << ErrorMsg << '\n';
     exit(1);
index 3fb7ba42cd05727e12e08222954b11bca1806596..95ad1ca5a17ee85cd4665af191f5df10044bff77 100644 (file)
@@ -103,7 +103,8 @@ int main(int argc, char **argv) {
 
     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]
              << "': " << ErrorMessage << "\n";
       return 1;