Add MCAsmParser interface.
[oota-llvm.git] / tools / bugpoint / ExtractFunction.cpp
index 776922aa5d43c32efb168e86a52aecd5bd0a6ca9..a939f995cb981dae3590f50d13703d280c58756d 100644 (file)
 #include "BugDriver.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/LLVMContext.h"
 #include "llvm/Module.h"
 #include "llvm/PassManager.h"
 #include "llvm/Pass.h"
 #include "llvm/Analysis/Verifier.h"
+#include "llvm/Assembly/Writer.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/Utils/Cloning.h"
@@ -30,8 +32,6 @@
 #include "llvm/System/Path.h"
 #include "llvm/System/Signals.h"
 #include <set>
-#include <fstream>
-#include <iostream>
 using namespace llvm;
 
 namespace llvm {
@@ -72,9 +72,9 @@ Module *BugDriver::deleteInstructionFromProgram(const Instruction *I,
 
   // If this instruction produces a value, replace any users with null values
   if (isa<StructType>(TheInst->getType()))
-    TheInst->replaceAllUsesWith(UndefValue::get(TheInst->getType()));
+    TheInst->replaceAllUsesWith(Context.getUndef(TheInst->getType()));
   else if (TheInst->getType() != Type::VoidTy)
-    TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
+    TheInst->replaceAllUsesWith(Context.getNullValue(TheInst->getType()));
 
   // Remove the instruction from the program.
   TheInst->getParent()->getInstList().erase(TheInst);
@@ -125,7 +125,7 @@ Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
 
   Module *New = runPassesOn(M, CleanupPasses);
   if (New == 0) {
-    std::cerr << "Final cleanups failed.  Sorry. :(  Please report a bug!\n";
+    errs() << "Final cleanups failed.  Sorry. :(  Please report a bug!\n";
     return M;
   }
   delete M;
@@ -143,9 +143,9 @@ Module *BugDriver::ExtractLoop(Module *M) {
   Module *NewM = runPassesOn(M, LoopExtractPasses);
   if (NewM == 0) {
     Module *Old = swapProgramIn(M);
-    std::cout << "*** Loop extraction failed: ";
+    outs() << "*** Loop extraction failed: ";
     EmitProgressBitcode("loopextraction", true);
-    std::cout << "*** Sorry. :(  Please report a bug!\n";
+    outs() << "*** Sorry. :(  Please report a bug!\n";
     swapProgramIn(Old);
     return 0;
   }
@@ -181,14 +181,15 @@ void llvm::DeleteFunctionBody(Function *F) {
 /// as a constant array.
 static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
   assert(!TorList.empty() && "Don't create empty tor list!");
+  LLVMContext &Context = *TorList[0].first->getContext();
   std::vector<Constant*> ArrayElts;
   for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
     std::vector<Constant*> Elts;
-    Elts.push_back(ConstantInt::get(Type::Int32Ty, TorList[i].second));
+    Elts.push_back(Context.getConstantInt(Type::Int32Ty, TorList[i].second));
     Elts.push_back(TorList[i].first);
-    ArrayElts.push_back(ConstantStruct::get(Elts));
+    ArrayElts.push_back(Context.getConstantStruct(Elts));
   }
-  return ConstantArray::get(ArrayType::get(ArrayElts[0]->getType(), 
+  return Context.getConstantArray(Context.getArrayType(ArrayElts[0]->getType(), 
                                            ArrayElts.size()),
                             ArrayElts);
 }
@@ -197,9 +198,10 @@ static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
 /// M1 has all of the global variables.  If M2 contains any functions that are
 /// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and
 /// prune appropriate entries out of M1s list.
-static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2){
+static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
+                                DenseMap<const Value*, Value*> ValueMap) {
   GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
-  if (!GV || GV->isDeclaration() || GV->hasInternalLinkage() ||
+  if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() ||
       !GV->use_empty()) return;
   
   std::vector<std::pair<Function*, int> > M1Tors, M2Tors;
@@ -225,7 +227,7 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2){
           M1Tors.push_back(std::make_pair(F, Priority));
         else {
           // Map to M2's version of the function.
-          F = M2->getFunction(F->getName());
+          F = cast<Function>(ValueMap[F]);
           M2Tors.push_back(std::make_pair(F, Priority));
         }
       }
@@ -235,8 +237,9 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2){
   GV->eraseFromParent();
   if (!M1Tors.empty()) {
     Constant *M1Init = GetTorInit(M1Tors);
-    new GlobalVariable(M1Init->getType(), false, GlobalValue::AppendingLinkage,
-                       M1Init, GlobalName, M1);
+    new GlobalVariable(*M1, M1Init->getType(), false,
+                       GlobalValue::AppendingLinkage,
+                       M1Init, GlobalName);
   }
 
   GV = M2->getNamedGlobal(GlobalName);
@@ -246,8 +249,9 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2){
   GV->eraseFromParent();
   if (!M2Tors.empty()) {
     Constant *M2Init = GetTorInit(M2Tors);
-    new GlobalVariable(M2Init->getType(), false, GlobalValue::AppendingLinkage,
-                       M2Init, GlobalName, M2);
+    new GlobalVariable(*M2, M2Init->getType(), false,
+                       GlobalValue::AppendingLinkage,
+                       M2Init, GlobalName);
   }
 }
 
@@ -255,8 +259,10 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2){
 /// SplitFunctionsOutOfModule - Given a module and a list of functions in the
 /// module, split the functions OUT of the specified module, and place them in
 /// the new module.
-Module *llvm::SplitFunctionsOutOfModule(Module *M,
-                                        const std::vector<Function*> &F) {
+Module *
+llvm::SplitFunctionsOutOfModule(Module *M,
+                                const std::vector<Function*> &F,
+                                DenseMap<const Value*, Value*> &ValueMap) {
   // Make sure functions & globals are all external so that linkage
   // between the two modules will work.
   for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
@@ -268,7 +274,8 @@ Module *llvm::SplitFunctionsOutOfModule(Module *M,
     I->setLinkage(GlobalValue::ExternalLinkage);
   }
 
-  Module *New = CloneModule(M);
+  DenseMap<const Value*, Value*> NewValueMap;
+  Module *New = CloneModule(M, NewValueMap);
 
   // Make sure global initializers exist only in the safe module (CBE->.so)
   for (Module::global_iterator I = New->global_begin(), E = New->global_end();
@@ -276,27 +283,27 @@ Module *llvm::SplitFunctionsOutOfModule(Module *M,
     I->setInitializer(0);  // Delete the initializer to make it external
 
   // Remove the Test functions from the Safe module
-  std::set<std::pair<std::string, const PointerType*> > TestFunctions;
+  std::set<Function *> TestFunctions;
   for (unsigned i = 0, e = F.size(); i != e; ++i) {
-    TestFunctions.insert(std::make_pair(F[i]->getName(), F[i]->getType()));  
-    Function *TNOF = M->getFunction(F[i]->getName());
-    assert(TNOF && "Function doesn't exist in module!");
-    assert(TNOF->getFunctionType() == F[i]->getFunctionType() && "wrong type?");
-    DEBUG(std::cerr << "Removing function " << F[i]->getName() << "\n");
+    Function *TNOF = cast<Function>(ValueMap[F[i]]);
+    DEBUG(errs() << "Removing function ");
+    DEBUG(WriteAsOperand(errs(), TNOF, false));
+    DEBUG(errs() << "\n");
+    TestFunctions.insert(cast<Function>(NewValueMap[TNOF]));
     DeleteFunctionBody(TNOF);       // Function is now external in this module!
   }
 
   
   // Remove the Safe functions from the Test module
   for (Module::iterator I = New->begin(), E = New->end(); I != E; ++I)
-    if (!TestFunctions.count(std::make_pair(I->getName(), I->getType())))
+    if (!TestFunctions.count(I))
       DeleteFunctionBody(I);
   
 
   // Make sure that there is a global ctor/dtor array in both halves of the
   // module if they both have static ctor/dtor functions.
-  SplitStaticCtorDtor("llvm.global_ctors", M, New);
-  SplitStaticCtorDtor("llvm.global_dtors", M, New);
+  SplitStaticCtorDtor("llvm.global_ctors", M, New, NewValueMap);
+  SplitStaticCtorDtor("llvm.global_dtors", M, New, NewValueMap);
   
   return New;
 }
@@ -318,8 +325,8 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
   sys::Path uniqueFilename("bugpoint-extractblocks");
   std::string ErrMsg;
   if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) {
-    std::cout << "*** Basic Block extraction failed!\n";
-    std::cerr << "Error creating temporary file: " << ErrMsg << "\n";
+    outs() << "*** Basic Block extraction failed!\n";
+    errs() << "Error creating temporary file: " << ErrMsg << "\n";
     M = swapProgramIn(M);
     EmitProgressBitcode("basicblockextractfail", true);
     swapProgramIn(M);
@@ -327,11 +334,14 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
   }
   sys::RemoveFileOnSignal(uniqueFilename);
 
-  std::ofstream BlocksToNotExtractFile(uniqueFilename.c_str());
-  if (!BlocksToNotExtractFile) {
-    std::cout << "*** Basic Block extraction failed!\n";
-    std::cerr << "Error writing list of blocks to not extract: " << ErrMsg
-              << "\n";
+  std::string ErrorInfo;
+  raw_fd_ostream BlocksToNotExtractFile(uniqueFilename.c_str(),
+                                        /*Binary=*/false, /*Force=*/true,
+                                        ErrorInfo);
+  if (!ErrorInfo.empty()) {
+    outs() << "*** Basic Block extraction failed!\n";
+    errs() << "Error writing list of blocks to not extract: " << ErrorInfo
+           << "\n";
     M = swapProgramIn(M);
     EmitProgressBitcode("basicblockextractfail", true);
     swapProgramIn(M);
@@ -362,7 +372,7 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
   free(ExtraArg);
 
   if (Ret == 0) {
-    std::cout << "*** Basic Block extraction failed, please report a bug!\n";
+    outs() << "*** Basic Block extraction failed, please report a bug!\n";
     M = swapProgramIn(M);
     EmitProgressBitcode("basicblockextractfail", true);
     swapProgramIn(M);