Add a convenience constructor.
[oota-llvm.git] / tools / bugpoint / ExtractFunction.cpp
index bb35d4fab453ac2d923fe869e17b39d6ef15369f..bbdc728890db566e84d0d10d2747fbfe9bc9537b 100644 (file)
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/System/Path.h"
 #include "llvm/System/Signals.h"
 #include <set>
-#include <fstream>
-#include <iostream>
 using namespace llvm;
 
 namespace llvm {
   bool DisableSimplifyCFG = false;
+  extern cl::opt<std::string> OutputPrefix;
 } // End llvm namespace
 
 namespace {
@@ -73,10 +73,8 @@ Module *BugDriver::deleteInstructionFromProgram(const Instruction *I,
   Instruction *TheInst = RI;              // Got the corresponding instruction!
 
   // If this instruction produces a value, replace any users with null values
-  if (isa<StructType>(TheInst->getType()))
-    TheInst->replaceAllUsesWith(UndefValue::get(TheInst->getType()));
-  else if (TheInst->getType() != Type::VoidTy)
-    TheInst->replaceAllUsesWith(Context.getNullValue(TheInst->getType()));
+  if (!TheInst->getType()->isVoidTy())
+    TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
 
   // Remove the instruction from the program.
   TheInst->getParent()->getInstList().erase(TheInst);
@@ -102,7 +100,8 @@ Module *BugDriver::deleteInstructionFromProgram(const Instruction *I,
 }
 
 static const PassInfo *getPI(Pass *P) {
-  const PassInfo *PI = P->getPassInfo();
+  const void *ID = P->getPassID();
+  const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID);
   delete P;
   return PI;
 }
@@ -118,16 +117,17 @@ Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
 
   std::vector<const PassInfo*> CleanupPasses;
   CleanupPasses.push_back(getPI(createGlobalDCEPass()));
-  CleanupPasses.push_back(getPI(createDeadTypeEliminationPass()));
 
   if (MayModifySemantics)
     CleanupPasses.push_back(getPI(createDeadArgHackingPass()));
   else
     CleanupPasses.push_back(getPI(createDeadArgEliminationPass()));
 
+  CleanupPasses.push_back(getPI(createDeadTypeEliminationPass()));
+
   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;
@@ -144,11 +144,9 @@ Module *BugDriver::ExtractLoop(Module *M) {
 
   Module *NewM = runPassesOn(M, LoopExtractPasses);
   if (NewM == 0) {
-    Module *Old = swapProgramIn(M);
-    std::cout << "*** Loop extraction failed: ";
-    EmitProgressBitcode("loopextraction", true);
-    std::cout << "*** Sorry. :(  Please report a bug!\n";
-    swapProgramIn(Old);
+    outs() << "*** Loop extraction failed: ";
+    EmitProgressBitcode(M, "loopextraction", true);
+    outs() << "*** Sorry. :(  Please report a bug!\n";
     return 0;
   }
 
@@ -186,9 +184,11 @@ static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
   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(ConstantInt::get(
+          Type::getInt32Ty(TorList[i].first->getContext()), TorList[i].second));
     Elts.push_back(TorList[i].first);
-    ArrayElts.push_back(ConstantStruct::get(Elts));
+    ArrayElts.push_back(ConstantStruct::get(TorList[i].first->getContext(),
+                                            Elts, false));
   }
   return ConstantArray::get(ArrayType::get(ArrayElts[0]->getType(), 
                                            ArrayElts.size()),
@@ -200,7 +200,7 @@ static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
 /// 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,
-                                DenseMap<const Value*, Value*> ValueMap) {
+                                ValueMap<const Value*, Value*> &VMap) {
   GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
   if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() ||
       !GV->use_empty()) return;
@@ -228,7 +228,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 = cast<Function>(ValueMap[F]);
+          F = cast<Function>(VMap[F]);
           M2Tors.push_back(std::make_pair(F, Priority));
         }
       }
@@ -263,20 +263,20 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
 Module *
 llvm::SplitFunctionsOutOfModule(Module *M,
                                 const std::vector<Function*> &F,
-                                DenseMap<const Value*, Value*> &ValueMap) {
+                                ValueMap<const Value*, Value*> &VMap) {
   // 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)
     I->setLinkage(GlobalValue::ExternalLinkage);
   for (Module::global_iterator I = M->global_begin(), E = M->global_end();
        I != E; ++I) {
-    if (I->hasName() && *I->getNameStart() == '\01')
-      I->setName(I->getNameStart()+1, I->getNameLen()-1);
+    if (I->hasName() && I->getName()[0] == '\01')
+      I->setName(I->getName().substr(1));
     I->setLinkage(GlobalValue::ExternalLinkage);
   }
 
-  DenseMap<const Value*, Value*> NewValueMap;
-  Module *New = CloneModule(M, NewValueMap);
+  ValueMap<const Value*, Value*> NewVMap;
+  Module *New = CloneModule(M, NewVMap);
 
   // Make sure global initializers exist only in the safe module (CBE->.so)
   for (Module::global_iterator I = New->global_begin(), E = New->global_end();
@@ -286,11 +286,11 @@ llvm::SplitFunctionsOutOfModule(Module *M,
   // Remove the Test functions from the Safe module
   std::set<Function *> TestFunctions;
   for (unsigned i = 0, e = F.size(); i != e; ++i) {
-    Function *TNOF = cast<Function>(ValueMap[F[i]]);
-    DEBUG(std::cerr << "Removing function ");
-    DEBUG(WriteAsOperand(std::cerr, TNOF, false));
-    DEBUG(std::cerr << "\n");
-    TestFunctions.insert(cast<Function>(NewValueMap[TNOF]));
+    Function *TNOF = cast<Function>(VMap[F[i]]);
+    DEBUG(errs() << "Removing function ");
+    DEBUG(WriteAsOperand(errs(), TNOF, false));
+    DEBUG(errs() << "\n");
+    TestFunctions.insert(cast<Function>(NewVMap[TNOF]));
     DeleteFunctionBody(TNOF);       // Function is now external in this module!
   }
 
@@ -303,8 +303,8 @@ llvm::SplitFunctionsOutOfModule(Module *M,
 
   // 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, NewValueMap);
-  SplitStaticCtorDtor("llvm.global_dtors", M, New, NewValueMap);
+  SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap);
+  SplitStaticCtorDtor("llvm.global_dtors", M, New, NewVMap);
   
   return New;
 }
@@ -321,28 +321,23 @@ llvm::SplitFunctionsOutOfModule(Module *M,
 Module *BugDriver::ExtractMappedBlocksFromModule(const
                                                  std::vector<BasicBlock*> &BBs,
                                                  Module *M) {
-  char *ExtraArg = NULL;
-
-  sys::Path uniqueFilename("bugpoint-extractblocks");
+  sys::Path uniqueFilename(OutputPrefix + "-extractblocks");
   std::string ErrMsg;
   if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) {
-    std::cout << "*** Basic Block extraction failed!\n";
-    std::cerr << "Error creating temporary file: " << ErrMsg << "\n";
-    M = swapProgramIn(M);
-    EmitProgressBitcode("basicblockextractfail", true);
-    swapProgramIn(M);
+    outs() << "*** Basic Block extraction failed!\n";
+    errs() << "Error creating temporary file: " << ErrMsg << "\n";
+    EmitProgressBitcode(M, "basicblockextractfail", true);
     return 0;
   }
   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";
-    M = swapProgramIn(M);
-    EmitProgressBitcode("basicblockextractfail", true);
-    swapProgramIn(M);
+  std::string ErrorInfo;
+  raw_fd_ostream BlocksToNotExtractFile(uniqueFilename.c_str(), ErrorInfo);
+  if (!ErrorInfo.empty()) {
+    outs() << "*** Basic Block extraction failed!\n";
+    errs() << "Error writing list of blocks to not extract: " << ErrorInfo
+           << "\n";
+    EmitProgressBitcode(M, "basicblockextractfail", true);
     return 0;
   }
   for (std::vector<BasicBlock*>::const_iterator I = BBs.begin(), E = BBs.end();
@@ -351,29 +346,23 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
     // If the BB doesn't have a name, give it one so we have something to key
     // off of.
     if (!BB->hasName()) BB->setName("tmpbb");
-    BlocksToNotExtractFile << BB->getParent()->getName() << " "
+    BlocksToNotExtractFile << BB->getParent()->getNameStr() << " "
                            << BB->getName() << "\n";
   }
   BlocksToNotExtractFile.close();
 
-  const char *uniqueFN = uniqueFilename.c_str();
-  ExtraArg = (char*)malloc(23 + strlen(uniqueFN));
-  strcat(strcpy(ExtraArg, "--extract-blocks-file="), uniqueFN);
+  std::string uniqueFN = "--extract-blocks-file=" + uniqueFilename.str();
+  const char *ExtraArg = uniqueFN.c_str();
 
   std::vector<const PassInfo*> PI;
-  std::vector<BasicBlock *> EmptyBBs; // This parameter is ignored.
-  PI.push_back(getPI(createBlockExtractorPass(EmptyBBs)));
+  PI.push_back(getPI(createBlockExtractorPass()));
   Module *Ret = runPassesOn(M, PI, false, 1, &ExtraArg);
 
-  if (uniqueFilename.exists())
-    uniqueFilename.eraseFromDisk(); // Free disk space
-  free(ExtraArg);
+  uniqueFilename.eraseFromDisk(); // Free disk space
 
   if (Ret == 0) {
-    std::cout << "*** Basic Block extraction failed, please report a bug!\n";
-    M = swapProgramIn(M);
-    EmitProgressBitcode("basicblockextractfail", true);
-    swapProgramIn(M);
+    outs() << "*** Basic Block extraction failed, please report a bug!\n";
+    EmitProgressBitcode(M, "basicblockextractfail", true);
   }
   return Ret;
 }