//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#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"
#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 {
Instruction *TheInst = RI; // Got the corresponding instruction!
// If this instruction produces a value, replace any users with null values
- if (TheInst->getType() != Type::VoidTy)
+ if (TheInst->getType()->isStructTy())
+ TheInst->replaceAllUsesWith(UndefValue::get(TheInst->getType()));
+ else if (TheInst->getType() != Type::getVoidTy(I->getContext()))
TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
// Remove the instruction from the program.
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;
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;
}
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()),
/// 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;
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));
}
}
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);
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);
}
}
/// 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)
I->setLinkage(GlobalValue::ExternalLinkage);
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
- I != E; ++I)
+ I != E; ++I) {
+ if (I->hasName() && I->getName()[0] == '\01')
+ I->setName(I->getName().substr(1));
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();
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;
}
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";
+ outs() << "*** Basic Block extraction failed!\n";
+ errs() << "Error creating temporary file: " << ErrMsg << "\n";
M = swapProgramIn(M);
EmitProgressBitcode("basicblockextractfail", true);
swapProgramIn(M);
}
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(), 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);
for (std::vector<BasicBlock*>::const_iterator I = BBs.begin(), E = BBs.end();
I != E; ++I) {
BasicBlock *BB = *I;
- BlocksToNotExtractFile << BB->getParent()->getName() << " "
+ // 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()->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)));
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";
+ outs() << "*** Basic Block extraction failed, please report a bug!\n";
M = swapProgramIn(M);
EmitProgressBitcode("basicblockextractfail", true);
swapProgramIn(M);