diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 17:57:32 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 17:57:32 +0000 |
commit | 59850d0874429601812bc13408cb1f776649027c (patch) | |
tree | b21f6de4e08b89bb7931806bab798fc2a5e3a686 /tools/bugpoint | |
parent | 18f153bdb9db52e7089a2d5293b96c45a3124a26 (diff) | |
download | src-59850d0874429601812bc13408cb1f776649027c.tar.gz src-59850d0874429601812bc13408cb1f776649027c.zip |
Update llvm to r84119.vendor/llvm/llvm-r84119
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=198090
svn path=/vendor/llvm/llvm-84119/; revision=198091; tag=vendor/llvm/llvm-r84119
Diffstat (limited to 'tools/bugpoint')
-rw-r--r-- | tools/bugpoint/BugDriver.cpp | 83 | ||||
-rw-r--r-- | tools/bugpoint/BugDriver.h | 6 | ||||
-rw-r--r-- | tools/bugpoint/CrashDebugger.cpp | 78 | ||||
-rw-r--r-- | tools/bugpoint/ExecutionDriver.cpp | 120 | ||||
-rw-r--r-- | tools/bugpoint/ExtractFunction.cpp | 61 | ||||
-rw-r--r-- | tools/bugpoint/FindBugs.cpp | 36 | ||||
-rw-r--r-- | tools/bugpoint/ListReducer.h | 14 | ||||
-rw-r--r-- | tools/bugpoint/Miscompilation.cpp | 327 | ||||
-rw-r--r-- | tools/bugpoint/OptimizerDriver.cpp | 127 | ||||
-rw-r--r-- | tools/bugpoint/ToolRunner.cpp | 301 | ||||
-rw-r--r-- | tools/bugpoint/ToolRunner.h | 21 | ||||
-rw-r--r-- | tools/bugpoint/bugpoint.cpp | 75 |
12 files changed, 725 insertions, 524 deletions
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index aab50720c6ef..abf5d8ef7211 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -18,17 +18,20 @@ #include "llvm/Linker.h" #include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/IRReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include <iostream> +#include "llvm/System/Host.h" #include <memory> using namespace llvm; +namespace llvm { + Triple TargetTriple; +} + // Anonymous namespace to define command line options for debugging. // namespace { @@ -78,17 +81,25 @@ BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs, /// Module *llvm::ParseInputFile(const std::string &Filename, LLVMContext& Ctxt) { - std::auto_ptr<MemoryBuffer> Buffer(MemoryBuffer::getFileOrSTDIN(Filename)); - Module *Result = 0; - if (Buffer.get()) - Result = ParseBitcodeFile(Buffer.get(), Ctxt); - SMDiagnostic Err; - if (!Result && !(Result = ParseAssemblyFile(Filename, Err, Ctxt))) { - Err.Print("bugpoint", errs()); - Result = 0; + Module *Result = ParseIRFile(Filename, Err, Ctxt); + if (!Result) + Err.Print("bugpoint", errs()); + + // If we don't have an override triple, use the first one to configure + // bugpoint, or use the host triple if none provided. + if (Result) { + if (TargetTriple.getTriple().empty()) { + Triple TheTriple(Result->getTargetTriple()); + + if (TheTriple.getTriple().empty()) + TheTriple.setTriple(sys::getHostTriple()); + + TargetTriple.setTriple(TheTriple.getTriple()); + } + + Result->setTargetTriple(TargetTriple.getTriple()); // override the triple } - return Result; } @@ -107,28 +118,28 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) { if (Program == 0) return true; if (!run_as_child) - std::cout << "Read input file : '" << Filenames[0] << "'\n"; + outs() << "Read input file : '" << Filenames[0] << "'\n"; for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { std::auto_ptr<Module> M(ParseInputFile(Filenames[i], Context)); if (M.get() == 0) return true; if (!run_as_child) - std::cout << "Linking in input file: '" << Filenames[i] << "'\n"; + outs() << "Linking in input file: '" << Filenames[i] << "'\n"; std::string ErrorMessage; if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) { - std::cerr << ToolName << ": error linking in '" << Filenames[i] << "': " - << ErrorMessage << '\n'; + errs() << ToolName << ": error linking in '" << Filenames[i] << "': " + << ErrorMessage << '\n'; return true; } } } catch (const std::string &Error) { - std::cerr << ToolName << ": error reading input '" << Error << "'\n"; + errs() << ToolName << ": error reading input '" << Error << "'\n"; return true; } if (!run_as_child) - std::cout << "*** All input ok\n"; + outs() << "*** All input ok\n"; // All input files read successfully! return false; @@ -162,7 +173,7 @@ bool BugDriver::run() { // file, then we know the compiler didn't crash, so try to diagnose a // miscompilation. if (!PassesToRun.empty()) { - std::cout << "Running selected passes on program to test for crash: "; + outs() << "Running selected passes on program to test for crash: "; if (runPasses(PassesToRun)) return debugOptimizerCrash(); } @@ -171,12 +182,12 @@ bool BugDriver::run() { if (initializeExecutionEnvironment()) return true; // Test to see if we have a code generator crash. - std::cout << "Running the code generator to test for a crash: "; + outs() << "Running the code generator to test for a crash: "; try { compileProgram(Program); - std::cout << '\n'; + outs() << '\n'; } catch (ToolExecutionError &TEE) { - std::cout << TEE.what(); + outs() << TEE.what(); return debugCodeGeneratorCrash(); } @@ -187,7 +198,7 @@ bool BugDriver::run() { // bool CreatedOutput = false; if (ReferenceOutputFile.empty()) { - std::cout << "Generating reference output from raw program: "; + outs() << "Generating reference output from raw program: "; if(!createReferenceFile(Program)){ return debugCodeGeneratorCrash(); } @@ -197,28 +208,28 @@ bool BugDriver::run() { // Make sure the reference output file gets deleted on exit from this // function, if appropriate. sys::Path ROF(ReferenceOutputFile); - FileRemover RemoverInstance(ROF, CreatedOutput); + FileRemover RemoverInstance(ROF, CreatedOutput && !SaveTemps); // Diff the output of the raw program against the reference output. If it // matches, then we assume there is a miscompilation bug and try to // diagnose it. - std::cout << "*** Checking the code generator...\n"; + outs() << "*** Checking the code generator...\n"; try { if (!diffProgram()) { - std::cout << "\n*** Debugging miscompilation!\n"; + outs() << "\n*** Output matches: Debugging miscompilation!\n"; return debugMiscompilation(); } } catch (ToolExecutionError &TEE) { - std::cerr << TEE.what(); + errs() << TEE.what(); return debugCodeGeneratorCrash(); } - std::cout << "\n*** Input program does not match reference diff!\n"; - std::cout << "Debugging code generator problem!\n"; + outs() << "\n*** Input program does not match reference diff!\n"; + outs() << "Debugging code generator problem!\n"; try { return debugCodeGenerator(); } catch (ToolExecutionError &TEE) { - std::cerr << TEE.what(); + errs() << TEE.what(); return debugCodeGeneratorCrash(); } } @@ -227,18 +238,18 @@ void llvm::PrintFunctionList(const std::vector<Function*> &Funcs) { unsigned NumPrint = Funcs.size(); if (NumPrint > 10) NumPrint = 10; for (unsigned i = 0; i != NumPrint; ++i) - std::cout << " " << Funcs[i]->getName(); + outs() << " " << Funcs[i]->getName(); if (NumPrint < Funcs.size()) - std::cout << "... <" << Funcs.size() << " total>"; - std::cout << std::flush; + outs() << "... <" << Funcs.size() << " total>"; + outs().flush(); } void llvm::PrintGlobalVariableList(const std::vector<GlobalVariable*> &GVs) { unsigned NumPrint = GVs.size(); if (NumPrint > 10) NumPrint = 10; for (unsigned i = 0; i != NumPrint; ++i) - std::cout << " " << GVs[i]->getName(); + outs() << " " << GVs[i]->getName(); if (NumPrint < GVs.size()) - std::cout << "... <" << GVs.size() << " total>"; - std::cout << std::flush; + outs() << "... <" << GVs.size() << " total>"; + outs().flush(); } diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index d637c2438bf9..db35c851d9a4 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -44,7 +44,7 @@ extern bool BugpointIsInterrupted; class BugDriver { LLVMContext& Context; - const std::string ToolName; // Name of bugpoint + const char *ToolName; // argv[0] of bugpoint std::string ReferenceOutputFile; // Name of `good' output file Module *Program; // The raw program, linked together std::vector<const PassInfo*> PassesToRun; @@ -64,7 +64,7 @@ public: BugDriver(const char *toolname, bool as_child, bool find_bugs, unsigned timeout, unsigned memlimit, LLVMContext& ctxt); - const std::string &getToolName() const { return ToolName; } + const char *getToolName() const { return ToolName; } LLVMContext& getContext() { return Context; } @@ -248,7 +248,7 @@ public: /// optimizations fail for some reason (optimizer crashes), return true, /// otherwise return false. If DeleteOutput is set to true, the bitcode is /// deleted on success, and the filename string is undefined. This prints to - /// cout a single line message indicating whether compilation was successful + /// outs() a single line message indicating whether compilation was successful /// or failed, unless Quiet is set. ExtraArgs specifies additional arguments /// to pass to the child bugpoint instance. /// diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index 9697b341f3a2..b348a0875e45 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -28,7 +28,6 @@ #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/CommandLine.h" -#include <fstream> #include <set> using namespace llvm; @@ -64,8 +63,8 @@ ReducePassList::doTest(std::vector<const PassInfo*> &Prefix, sys::Path PrefixOutput; Module *OrigProgram = 0; if (!Prefix.empty()) { - std::cout << "Checking to see if these passes crash: " - << getPassesString(Prefix) << ": "; + outs() << "Checking to see if these passes crash: " + << getPassesString(Prefix) << ": "; std::string PfxOutput; if (BD.runPasses(Prefix, PfxOutput)) return KeepPrefix; @@ -73,17 +72,17 @@ ReducePassList::doTest(std::vector<const PassInfo*> &Prefix, PrefixOutput.set(PfxOutput); OrigProgram = BD.Program; - BD.Program = ParseInputFile(PrefixOutput.toString(), BD.getContext()); + BD.Program = ParseInputFile(PrefixOutput.str(), BD.getContext()); if (BD.Program == 0) { - std::cerr << BD.getToolName() << ": Error reading bitcode file '" - << PrefixOutput << "'!\n"; + errs() << BD.getToolName() << ": Error reading bitcode file '" + << PrefixOutput.str() << "'!\n"; exit(1); } PrefixOutput.eraseFromDisk(); } - std::cout << "Checking to see if these passes crash: " - << getPassesString(Suffix) << ": "; + outs() << "Checking to see if these passes crash: " + << getPassesString(Suffix) << ": "; if (BD.runPasses(Suffix)) { delete OrigProgram; // The suffix crashes alone... @@ -142,9 +141,9 @@ ReduceCrashingGlobalVariables::TestGlobalVariables( GVSet.insert(CMGV); } - std::cout << "Checking for crash with only these global variables: "; + outs() << "Checking for crash with only these global variables: "; PrintGlobalVariableList(GVs); - std::cout << ": "; + outs() << ": "; // Loop over and delete any global variables which we aren't supposed to be // playing with... @@ -216,9 +215,9 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { Functions.insert(CMF); } - std::cout << "Checking for crash with only these functions: "; + outs() << "Checking for crash with only these functions: "; PrintFunctionList(Funcs); - std::cout << ": "; + outs() << ": "; // Loop over and delete any functions which we aren't supposed to be playing // with... @@ -276,14 +275,14 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { for (unsigned i = 0, e = BBs.size(); i != e; ++i) Blocks.insert(cast<BasicBlock>(ValueMap[BBs[i]])); - std::cout << "Checking for crash with only these blocks:"; + outs() << "Checking for crash with only these blocks:"; unsigned NumPrint = Blocks.size(); if (NumPrint > 10) NumPrint = 10; for (unsigned i = 0, e = NumPrint; i != e; ++i) - std::cout << " " << BBs[i]->getName(); + outs() << " " << BBs[i]->getName(); if (NumPrint < Blocks.size()) - std::cout << "... <" << Blocks.size() << " total>"; - std::cout << ": "; + outs() << "... <" << Blocks.size() << " total>"; + outs() << ": "; // Loop over and delete any hack up any blocks that are not listed... for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) @@ -298,12 +297,13 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { if (isa<StructType>(BBTerm->getType())) BBTerm->replaceAllUsesWith(UndefValue::get(BBTerm->getType())); - else if (BB->getTerminator()->getType() != Type::VoidTy) + else if (BB->getTerminator()->getType() != + Type::getVoidTy(BB->getContext())) BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType())); // Replace the old terminator instruction. BB->getInstList().pop_back(); - new UnreachableInst(BB); + new UnreachableInst(BB->getContext(), BB); } // The CFG Simplifier pass may delete one of the basic blocks we are @@ -333,7 +333,7 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { ValueSymbolTable &ST = BlockInfo[i].first->getValueSymbolTable(); Value* V = ST.lookup(BlockInfo[i].second); - if (V && V->getType() == Type::LabelTy) + if (V && V->getType() == Type::getLabelTy(V->getContext())) BBs.push_back(cast<BasicBlock>(V)); } return true; @@ -380,18 +380,18 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> Instructions.insert(cast<Instruction>(ValueMap[Insts[i]])); } - std::cout << "Checking for crash with only " << Instructions.size(); + outs() << "Checking for crash with only " << Instructions.size(); if (Instructions.size() == 1) - std::cout << " instruction: "; + outs() << " instruction: "; else - std::cout << " instructions: "; + outs() << " instructions: "; for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { Instruction *Inst = I++; if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst)) { - if (Inst->getType() != Type::VoidTy) + if (Inst->getType() != Type::getVoidTy(Inst->getContext())) Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); Inst->eraseFromParent(); } @@ -443,13 +443,13 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { delete M; // No change made... } else { // See if the program still causes a crash... - std::cout << "\nChecking to see if we can delete global inits: "; + outs() << "\nChecking to see if we can delete global inits: "; if (TestFn(BD, M)) { // Still crashes? BD.setNewProgram(M); - std::cout << "\n*** Able to remove all global initializers!\n"; + outs() << "\n*** Able to remove all global initializers!\n"; } else { // No longer crashes? - std::cout << " - Removing all global inits hides problem!\n"; + outs() << " - Removing all global inits hides problem!\n"; delete M; std::vector<GlobalVariable*> GVs; @@ -460,7 +460,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { GVs.push_back(I); if (GVs.size() > 1 && !BugpointIsInterrupted) { - std::cout << "\n*** Attempting to reduce the number of global " + outs() << "\n*** Attempting to reduce the number of global " << "variables in the testcase\n"; unsigned OldSize = GVs.size(); @@ -481,7 +481,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { Functions.push_back(I); if (Functions.size() > 1 && !BugpointIsInterrupted) { - std::cout << "\n*** Attempting to reduce the number of functions " + outs() << "\n*** Attempting to reduce the number of functions " "in the testcase\n"; unsigned OldSize = Functions.size(); @@ -530,8 +530,8 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { do { if (BugpointIsInterrupted) break; --Simplification; - std::cout << "\n*** Attempting to reduce testcase by deleting instruc" - << "tions: Simplification Level #" << Simplification << '\n'; + outs() << "\n*** Attempting to reduce testcase by deleting instruc" + << "tions: Simplification Level #" << Simplification << '\n'; // Now that we have deleted the functions that are unnecessary for the // program, try to remove instructions that are not necessary to cause the @@ -559,7 +559,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { } else { if (BugpointIsInterrupted) goto ExitLoops; - std::cout << "Checking instruction: " << *I; + outs() << "Checking instruction: " << *I; Module *M = BD.deleteInstructionFromProgram(I, Simplification); // Find out if the pass still crashes on this pass... @@ -586,7 +586,7 @@ ExitLoops: // Try to clean up the testcase by running funcresolve and globaldce... if (!BugpointIsInterrupted) { - std::cout << "\n*** Attempting to perform final cleanups: "; + outs() << "\n*** Attempting to perform final cleanups: "; Module *M = CloneModule(BD.getProgram()); M = BD.performFinalCleanups(M, true); @@ -612,15 +612,15 @@ static bool TestForOptimizerCrash(BugDriver &BD, Module *M) { /// out exactly which pass is crashing. /// bool BugDriver::debugOptimizerCrash(const std::string &ID) { - std::cout << "\n*** Debugging optimizer crash!\n"; + outs() << "\n*** Debugging optimizer crash!\n"; // Reduce the list of passes which causes the optimizer to crash... if (!BugpointIsInterrupted) ReducePassList(*this).reduceList(PassesToRun); - std::cout << "\n*** Found crashing pass" - << (PassesToRun.size() == 1 ? ": " : "es: ") - << getPassesString(PassesToRun) << '\n'; + outs() << "\n*** Found crashing pass" + << (PassesToRun.size() == 1 ? ": " : "es: ") + << getPassesString(PassesToRun) << '\n'; EmitProgressBitcode(ID); @@ -630,10 +630,10 @@ bool BugDriver::debugOptimizerCrash(const std::string &ID) { static bool TestForCodeGenCrash(BugDriver &BD, Module *M) { try { BD.compileProgram(M); - std::cerr << '\n'; + errs() << '\n'; return false; } catch (ToolExecutionError &) { - std::cerr << "<crash>\n"; + errs() << "<crash>\n"; return true; // Tool is still crashing. } } @@ -642,7 +642,7 @@ static bool TestForCodeGenCrash(BugDriver &BD, Module *M) { /// crashes on an input. It attempts to reduce the input as much as possible /// while still causing the code generator to crash. bool BugDriver::debugCodeGeneratorCrash() { - std::cerr << "*** Debugging code generator crash!\n"; + errs() << "*** Debugging code generator crash!\n"; return DebugACrash(*this, TestForCodeGenCrash); } diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index 640fe2829aeb..feda331177b1 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -18,8 +18,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/SystemUtils.h" +#include "llvm/Support/raw_ostream.h" #include <fstream> -#include <iostream> using namespace llvm; @@ -56,19 +56,19 @@ namespace { cl::opt<OutputType> SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"), - cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"), - clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"), - clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"), - clEnumValN(Custom, "safe-run-custom", - "Use -exec-command to define a command to execute " - "the bitcode. Useful for cross-compilation."), - clEnumValEnd), + cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"), + clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"), + clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"), + clEnumValN(Custom, "safe-run-custom", + "Use -exec-command to define a command to execute " + "the bitcode. Useful for cross-compilation."), + clEnumValEnd), cl::init(AutoPick)); cl::opt<std::string> SafeInterpreterPath("safe-path", - cl::desc("Specify the path to the \"safe\" backend program"), - cl::init("")); + cl::desc("Specify the path to the \"safe\" backend program"), + cl::init("")); cl::opt<bool> AppendProgramExitCode("append-exit-code", @@ -100,6 +100,10 @@ namespace llvm { cl::list<std::string> InputArgv("args", cl::Positional, cl::desc("<program arguments>..."), cl::ZeroOrMore, cl::PositionalEatsArgs); + + cl::opt<std::string> + OutputPrefix("output-prefix", cl::init("bugpoint"), + cl::desc("Prefix to use for outputs (default: 'bugpoint')")); } namespace { @@ -126,7 +130,7 @@ namespace { /// environment for executing LLVM programs. /// bool BugDriver::initializeExecutionEnvironment() { - std::cout << "Initializing execution environment: "; + outs() << "Initializing execution environment: "; // Create an instance of the AbstractInterpreter interface as specified on // the command line @@ -178,17 +182,16 @@ bool BugDriver::initializeExecutionEnvironment() { &ToolArgv, &GCCToolArgv); break; case Custom: - Interpreter = AbstractInterpreter::createCustom(getToolName(), Message, - CustomExecCommand); + Interpreter = AbstractInterpreter::createCustom(Message, CustomExecCommand); break; default: Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; break; } if (!Interpreter) - std::cerr << Message; + errs() << Message; else // Display informational messages on stdout instead of stderr - std::cout << Message; + outs() << Message; std::string Path = SafeInterpreterPath; if (Path.empty()) @@ -201,7 +204,7 @@ bool BugDriver::initializeExecutionEnvironment() { InterpreterSel == CBE_bug) { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path, Message, + SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, &SafeToolArgs, &GCCToolArgv); } @@ -211,7 +214,7 @@ bool BugDriver::initializeExecutionEnvironment() { InterpreterSel == LLC_Safe) { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path, Message, + SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, &SafeToolArgs, &GCCToolArgv); } @@ -222,7 +225,7 @@ bool BugDriver::initializeExecutionEnvironment() { if (!SafeInterpreter && InterpreterSel != RunCBE) { SafeInterpreterSel = RunCBE; - SafeInterpreter = AbstractInterpreter::createCBE(Path, Message, + SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, &SafeToolArgs, &GCCToolArgv); } @@ -231,7 +234,7 @@ bool BugDriver::initializeExecutionEnvironment() { InterpreterSel != RunJIT) { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path, Message, + SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, &SafeToolArgs, &GCCToolArgv); } @@ -242,17 +245,17 @@ bool BugDriver::initializeExecutionEnvironment() { break; case RunLLC: SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path, Message, + SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, &SafeToolArgs, &GCCToolArgv); break; case RunCBE: - SafeInterpreter = AbstractInterpreter::createCBE(Path, Message, + SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, &SafeToolArgs, &GCCToolArgv); break; case Custom: - SafeInterpreter = AbstractInterpreter::createCustom(Path, Message, + SafeInterpreter = AbstractInterpreter::createCustom(Message, CustomExecCommand); break; default: @@ -260,10 +263,10 @@ bool BugDriver::initializeExecutionEnvironment() { "\"safe\" backend right now!\n"; break; } - if (!SafeInterpreter) { std::cout << Message << "\nExiting.\n"; exit(1); } + if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); } - gcc = GCC::create(getToolName(), Message, &GCCToolArgv); - if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); } + gcc = GCC::create(Message, &GCCToolArgv); + if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } // If there was an error creating the selected interpreter, quit with error. return Interpreter == 0; @@ -275,24 +278,24 @@ bool BugDriver::initializeExecutionEnvironment() { /// void BugDriver::compileProgram(Module *M) { // Emit the program to a bitcode file... - sys::Path BitcodeFile ("bugpoint-test-program.bc"); + sys::Path BitcodeFile (OutputPrefix + "-test-program.bc"); std::string ErrMsg; if (BitcodeFile.makeUnique(true,&ErrMsg)) { - std::cerr << ToolName << ": Error making unique filename: " << ErrMsg - << "\n"; + errs() << ToolName << ": Error making unique filename: " << ErrMsg + << "\n"; exit(1); } - if (writeProgramToFile(BitcodeFile.toString(), M)) { - std::cerr << ToolName << ": Error emitting bitcode to file '" - << BitcodeFile << "'!\n"; + if (writeProgramToFile(BitcodeFile.str(), M)) { + errs() << ToolName << ": Error emitting bitcode to file '" + << BitcodeFile.str() << "'!\n"; exit(1); } // Remove the temporary bitcode file when we are done. - FileRemover BitcodeFileRemover(BitcodeFile); + FileRemover BitcodeFileRemover(BitcodeFile, !SaveTemps); // Actually compile the program! - Interpreter->compileProgram(BitcodeFile.toString()); + Interpreter->compileProgram(BitcodeFile.str()); } @@ -311,17 +314,17 @@ std::string BugDriver::executeProgram(std::string OutputFile, std::string ErrMsg; if (BitcodeFile.empty()) { // Emit the program to a bitcode file... - sys::Path uniqueFilename("bugpoint-test-program.bc"); + sys::Path uniqueFilename(OutputPrefix + "-test-program.bc"); if (uniqueFilename.makeUnique(true, &ErrMsg)) { - std::cerr << ToolName << ": Error making unique filename: " - << ErrMsg << "!\n"; + errs() << ToolName << ": Error making unique filename: " + << ErrMsg << "!\n"; exit(1); } - BitcodeFile = uniqueFilename.toString(); + BitcodeFile = uniqueFilename.str(); if (writeProgramToFile(BitcodeFile, Program)) { - std::cerr << ToolName << ": Error emitting bitcode to file '" - << BitcodeFile << "'!\n"; + errs() << ToolName << ": Error emitting bitcode to file '" + << BitcodeFile << "'!\n"; exit(1); } CreatedBitcode = true; @@ -329,18 +332,18 @@ std::string BugDriver::executeProgram(std::string OutputFile, // Remove the temporary bitcode file when we are done. sys::Path BitcodePath (BitcodeFile); - FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode); + FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps); - if (OutputFile.empty()) OutputFile = "bugpoint-execution-output"; + if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output"; // Check to see if this is a valid output filename... sys::Path uniqueFile(OutputFile); if (uniqueFile.makeUnique(true, &ErrMsg)) { - std::cerr << ToolName << ": Error making unique filename: " - << ErrMsg << "\n"; + errs() << ToolName << ": Error making unique filename: " + << ErrMsg << "\n"; exit(1); } - OutputFile = uniqueFile.toString(); + OutputFile = uniqueFile.str(); // Figure out which shared objects to run, if any. std::vector<std::string> SharedObjs(AdditionalSOs); @@ -352,10 +355,10 @@ std::string BugDriver::executeProgram(std::string OutputFile, Timeout, MemoryLimit); if (RetVal == -1) { - std::cerr << "<timeout>"; + errs() << "<timeout>"; static bool FirstTimeout = true; if (FirstTimeout) { - std::cout << "\n" + outs() << "\n" "*** Program execution timed out! This mechanism is designed to handle\n" " programs stuck in infinite loops gracefully. The -timeout option\n" " can be used to change the timeout threshold or disable it completely\n" @@ -395,7 +398,7 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile) { GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile); std::string SharedObjectFile; - if (gcc->MakeSharedObject(OutputFile.toString(), FT, + if (gcc->MakeSharedObject(OutputFile.str(), FT, SharedObjectFile, AdditionalLinkerArgs)) exit(1); @@ -418,14 +421,14 @@ bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) { } try { ReferenceOutputFile = executeProgramSafely(Filename); - std::cout << "\nReference output is: " << ReferenceOutputFile << "\n\n"; + outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; } catch (ToolExecutionError &TEE) { - std::cerr << TEE.what(); + errs() << TEE.what(); if (Interpreter != SafeInterpreter) { - std::cerr << "*** There is a bug running the \"safe\" backend. Either" - << " debug it (for example with the -run-cbe bugpoint option," - << " if CBE is being used as the \"safe\" backend), or fix the" - << " error some other way.\n"; + errs() << "*** There is a bug running the \"safe\" backend. Either" + << " debug it (for example with the -run-cbe bugpoint option," + << " if CBE is being used as the \"safe\" backend), or fix the" + << " error some other way.\n"; } return false; } @@ -449,17 +452,18 @@ bool BugDriver::diffProgram(const std::string &BitcodeFile, std::string Error; bool FilesDifferent = false; if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile), - sys::Path(Output.toString()), + sys::Path(Output.str()), AbsTolerance, RelTolerance, &Error)) { if (Diff == 2) { - std::cerr << "While diffing output: " << Error << '\n'; + errs() << "While diffing output: " << Error << '\n'; exit(1); } FilesDifferent = true; } - - // Remove the generated output. - Output.eraseFromDisk(); + else { + // Remove the generated output if there are no differences. + Output.eraseFromDisk(); + } // Remove the bitcode file if we are supposed to. if (RemoveBitcode) diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index e4affbb0ddcc..918d6a6a2afb 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -15,10 +15,12 @@ #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" @@ -27,15 +29,15 @@ #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,7 +75,7 @@ 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())); - else if (TheInst->getType() != Type::VoidTy) + else if (TheInst->getType() != Type::getVoidTy(I->getContext())) TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType())); // Remove the instruction from the program. @@ -125,7 +127,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 +145,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; } @@ -184,9 +186,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()), @@ -236,8 +240,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); @@ -247,8 +252,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); } } @@ -266,8 +272,8 @@ llvm::SplitFunctionsOutOfModule(Module *M, 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); } @@ -283,9 +289,9 @@ llvm::SplitFunctionsOutOfModule(Module *M, 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"); + 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! } @@ -319,11 +325,11 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const 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); @@ -331,11 +337,12 @@ 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(), 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); @@ -347,7 +354,7 @@ 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(); @@ -366,7 +373,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); diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp index e42cce47ba02..2c11d29f60d5 100644 --- a/tools/bugpoint/FindBugs.cpp +++ b/tools/bugpoint/FindBugs.cpp @@ -17,9 +17,9 @@ #include "BugDriver.h" #include "ToolRunner.h" #include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <ctime> -#include <iostream> using namespace llvm; /// runManyPasses - Take the specified pass list and create different @@ -31,14 +31,14 @@ using namespace llvm; /// bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) { setPassesToRun(AllPasses); - std::cout << "Starting bug finding procedure...\n\n"; + outs() << "Starting bug finding procedure...\n\n"; // Creating a reference output if necessary if (initializeExecutionEnvironment()) return false; - std::cout << "\n"; + outs() << "\n"; if (ReferenceOutputFile.empty()) { - std::cout << "Generating reference output from raw program: \n"; + outs() << "Generating reference output from raw program: \n"; if (!createReferenceFile(Program)) return false; } @@ -55,31 +55,31 @@ bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) { // // Step 2: Run optimizer passes on the program and check for success. // - std::cout << "Running selected passes on program to test for crash: "; + outs() << "Running selected passes on program to test for crash: "; for(int i = 0, e = PassesToRun.size(); i != e; i++) { - std::cout << "-" << PassesToRun[i]->getPassArgument( )<< " "; + outs() << "-" << PassesToRun[i]->getPassArgument( )<< " "; } std::string Filename; if(runPasses(PassesToRun, Filename, false)) { - std::cout << "\n"; - std::cout << "Optimizer passes caused failure!\n\n"; + outs() << "\n"; + outs() << "Optimizer passes caused failure!\n\n"; debugOptimizerCrash(); return true; } else { - std::cout << "Combination " << num << " optimized successfully!\n"; + outs() << "Combination " << num << " optimized successfully!\n"; } // // Step 3: Compile the optimized code. // - std::cout << "Running the code generator to test for a crash: "; + outs() << "Running the code generator to test for a crash: "; try { compileProgram(Program); - std::cout << '\n'; + outs() << '\n'; } catch (ToolExecutionError &TEE) { - std::cout << "\n*** compileProgram threw an exception: "; - std::cout << TEE.what(); + outs() << "\n*** compileProgram threw an exception: "; + outs() << TEE.what(); return debugCodeGeneratorCrash(); } @@ -87,24 +87,24 @@ bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) { // Step 4: Run the program and compare its output to the reference // output (created above). // - std::cout << "*** Checking if passes caused miscompliation:\n"; + outs() << "*** Checking if passes caused miscompliation:\n"; try { if (diffProgram(Filename, "", false)) { - std::cout << "\n*** diffProgram returned true!\n"; + outs() << "\n*** diffProgram returned true!\n"; debugMiscompilation(); return true; } else { - std::cout << "\n*** diff'd output matches!\n"; + outs() << "\n*** diff'd output matches!\n"; } } catch (ToolExecutionError &TEE) { - std::cerr << TEE.what(); + errs() << TEE.what(); debugCodeGeneratorCrash(); return true; } sys::Path(Filename).eraseFromDisk(); - std::cout << "\n\n"; + outs() << "\n\n"; num++; } //end while diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h index de3f3892001e..8036d1f54499 100644 --- a/tools/bugpoint/ListReducer.h +++ b/tools/bugpoint/ListReducer.h @@ -15,8 +15,8 @@ #ifndef BUGPOINT_LIST_REDUCER_H #define BUGPOINT_LIST_REDUCER_H +#include "llvm/Support/raw_ostream.h" #include <vector> -#include <iostream> #include <cstdlib> #include <algorithm> @@ -58,7 +58,7 @@ struct ListReducer { case KeepSuffix: // cannot be reached! - std::cerr << "bugpoint ListReducer internal error: selected empty set.\n"; + errs() << "bugpoint ListReducer internal error: selected empty set.\n"; abort(); case NoFailure: @@ -77,7 +77,7 @@ Backjump: while (MidTop > 1) { // Binary split reduction loop // Halt if the user presses ctrl-c. if (BugpointIsInterrupted) { - std::cerr << "\n\n*** Reduction Interrupted, cleaning up...\n\n"; + errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n"; return true; } @@ -88,7 +88,7 @@ Backjump: NumOfIterationsWithoutProgress > MaxIterations) { std::vector<ElTy> ShuffledList(TheList); std::random_shuffle(ShuffledList.begin(), ShuffledList.end()); - std::cerr << "\n\n*** Testing shuffled set...\n\n"; + errs() << "\n\n*** Testing shuffled set...\n\n"; // Check that random shuffle doesn't loose the bug if (doTest(ShuffledList, empty) == KeepPrefix) { // If the bug is still here, use the shuffled list. @@ -97,10 +97,10 @@ Backjump: // Must increase the shuffling treshold to avoid the small // probability of inifinite looping without making progress. MaxIterations += 2; - std::cerr << "\n\n*** Shuffling does not hide the bug...\n\n"; + errs() << "\n\n*** Shuffling does not hide the bug...\n\n"; } else { ShufflingEnabled = false; // Disable shuffling further on - std::cerr << "\n\n*** Shuffling hides the bug...\n\n"; + errs() << "\n\n*** Shuffling hides the bug...\n\n"; } NumOfIterationsWithoutProgress = 0; } @@ -160,7 +160,7 @@ Backjump: for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts if (BugpointIsInterrupted) { - std::cerr << "\n\n*** Reduction Interrupted, cleaning up...\n\n"; + errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n"; return true; } diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index b3260e13606f..a5914178f12e 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -14,6 +14,7 @@ #include "BugDriver.h" #include "ListReducer.h" +#include "ToolRunner.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Instructions.h" @@ -29,6 +30,7 @@ using namespace llvm; namespace llvm { + extern cl::opt<std::string> OutputPrefix; extern cl::list<std::string> InputArgv; } @@ -37,6 +39,10 @@ namespace { DisableLoopExtraction("disable-loop-extraction", cl::desc("Don't extract loops when searching for miscompilations"), cl::init(false)); + static llvm::cl::opt<bool> + DisableBlockExtraction("disable-block-extraction", + cl::desc("Don't extract blocks when searching for miscompilations"), + cl::init(false)); class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> { BugDriver &BD; @@ -56,36 +62,36 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, std::vector<const PassInfo*> &Suffix) { // First, run the program with just the Suffix passes. If it is still broken // with JUST the kept passes, discard the prefix passes. - std::cout << "Checking to see if '" << getPassesString(Suffix) - << "' compile correctly: "; + outs() << "Checking to see if '" << getPassesString(Suffix) + << "' compiles correctly: "; std::string BitcodeResult; if (BD.runPasses(Suffix, BitcodeResult, false/*delete*/, true/*quiet*/)) { - std::cerr << " Error running this sequence of passes" - << " on the input program!\n"; + errs() << " Error running this sequence of passes" + << " on the input program!\n"; BD.setPassesToRun(Suffix); BD.EmitProgressBitcode("pass-error", false); exit(BD.debugOptimizerCrash()); } - + // Check to see if the finished program matches the reference output... if (BD.diffProgram(BitcodeResult, "", true /*delete bitcode*/)) { - std::cout << " nope.\n"; + outs() << " nope.\n"; if (Suffix.empty()) { - std::cerr << BD.getToolName() << ": I'm confused: the test fails when " - << "no passes are run, nondeterministic program?\n"; + errs() << BD.getToolName() << ": I'm confused: the test fails when " + << "no passes are run, nondeterministic program?\n"; exit(1); } return KeepSuffix; // Miscompilation detected! } - std::cout << " yup.\n"; // No miscompilation! + outs() << " yup.\n"; // No miscompilation! if (Prefix.empty()) return NoFailure; // Next, see if the program is broken if we run the "prefix" passes first, // then separately run the "kept" passes. - std::cout << "Checking to see if '" << getPassesString(Prefix) - << "' compile correctly: "; + outs() << "Checking to see if '" << getPassesString(Prefix) + << "' compiles correctly: "; // If it is not broken with the kept passes, it's possible that the prefix // passes must be run before the kept passes to break it. If the program @@ -94,8 +100,8 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, // prefix passes, then discard the prefix passes. // if (BD.runPasses(Prefix, BitcodeResult, false/*delete*/, true/*quiet*/)) { - std::cerr << " Error running this sequence of passes" - << " on the input program!\n"; + errs() << " Error running this sequence of passes" + << " on the input program!\n"; BD.setPassesToRun(Prefix); BD.EmitProgressBitcode("pass-error", false); exit(BD.debugOptimizerCrash()); @@ -103,19 +109,19 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, // If the prefix maintains the predicate by itself, only keep the prefix! if (BD.diffProgram(BitcodeResult)) { - std::cout << " nope.\n"; + outs() << " nope.\n"; sys::Path(BitcodeResult).eraseFromDisk(); return KeepPrefix; } - std::cout << " yup.\n"; // No miscompilation! + outs() << " yup.\n"; // No miscompilation! // Ok, so now we know that the prefix passes work, try running the suffix // passes on the result of the prefix passes. // Module *PrefixOutput = ParseInputFile(BitcodeResult, BD.getContext()); if (PrefixOutput == 0) { - std::cerr << BD.getToolName() << ": Error reading bitcode file '" - << BitcodeResult << "'!\n"; + errs() << BD.getToolName() << ": Error reading bitcode file '" + << BitcodeResult << "'!\n"; exit(1); } sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk @@ -124,14 +130,14 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, if (Suffix.empty()) return NoFailure; - std::cout << "Checking to see if '" << getPassesString(Suffix) + outs() << "Checking to see if '" << getPassesString(Suffix) << "' passes compile correctly after the '" << getPassesString(Prefix) << "' passes: "; Module *OriginalInput = BD.swapProgramIn(PrefixOutput); if (BD.runPasses(Suffix, BitcodeResult, false/*delete*/, true/*quiet*/)) { - std::cerr << " Error running this sequence of passes" - << " on the input program!\n"; + errs() << " Error running this sequence of passes" + << " on the input program!\n"; BD.setPassesToRun(Suffix); BD.EmitProgressBitcode("pass-error", false); exit(BD.debugOptimizerCrash()); @@ -139,13 +145,13 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, // Run the result... if (BD.diffProgram(BitcodeResult, "", true/*delete bitcode*/)) { - std::cout << " nope.\n"; + outs() << " nope.\n"; delete OriginalInput; // We pruned down the original input... return KeepSuffix; } // Otherwise, we must not be running the bad pass anymore. - std::cout << " yup.\n"; // No miscompilation! + outs() << " yup.\n"; // No miscompilation! delete BD.swapProgramIn(OriginalInput); // Restore orig program & free test return NoFailure; } @@ -187,8 +193,8 @@ static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2, M2 = CloneModule(M2); } if (Linker::LinkModules(M1, M2, &ErrorMsg)) { - std::cerr << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; + errs() << BD.getToolName() << ": Error linking modules together:" + << ErrorMsg << '\n'; exit(1); } delete M2; // We are done with this module. @@ -212,12 +218,12 @@ static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2, bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*>&Funcs){ // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. - std::cout << "Checking to see if the program is misoptimized when " - << (Funcs.size()==1 ? "this function is" : "these functions are") - << " run through the pass" - << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":"; + outs() << "Checking to see if the program is misoptimized when " + << (Funcs.size()==1 ? "this function is" : "these functions are") + << " run through the pass" + << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":"; PrintFunctionList(Funcs); - std::cout << '\n'; + outs() << '\n'; // Split the module into the two halves of the program we want. DenseMap<const Value*, Value*> ValueMap; @@ -241,12 +247,18 @@ static void DisambiguateGlobalSymbols(Module *M) { Mangler Mang(*M); // Agree with the CBE on symbol naming Mang.markCharUnacceptable('.'); - Mang.setPreserveAsmNames(true); for (Module::global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) - I->setName(Mang.getValueName(I)); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - I->setName(Mang.getValueName(I)); + I != E; ++I) { + // Don't mangle asm names. + if (!I->hasName() || I->getName()[0] != 1) + I->setName(Mang.getMangledName(I)); + } + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { + // Don't mangle asm names or intrinsics. + if ((!I->hasName() || I->getName()[0] != 1) && + I->getIntrinsicID() == 0) + I->setName(Mang.getMangledName(I)); + } } /// ExtractLoops - Given a reduced list of functions that still exposed the bug, @@ -274,7 +286,7 @@ static bool ExtractLoops(BugDriver &BD, return MadeChange; } - std::cerr << "Extracted a loop from the breaking portion of the program.\n"; + errs() << "Extracted a loop from the breaking portion of the program.\n"; // Bugpoint is intentionally not very trusting of LLVM transformations. In // particular, we're not going to assume that the loop extractor works, so @@ -286,16 +298,19 @@ static bool ExtractLoops(BugDriver &BD, BD.switchToInterpreter(AI); // Merged program doesn't work anymore! - std::cerr << " *** ERROR: Loop extraction broke the program. :(" - << " Please report a bug!\n"; - std::cerr << " Continuing on with un-loop-extracted version.\n"; - - BD.writeProgramToFile("bugpoint-loop-extract-fail-tno.bc", ToNotOptimize); - BD.writeProgramToFile("bugpoint-loop-extract-fail-to.bc", ToOptimize); - BD.writeProgramToFile("bugpoint-loop-extract-fail-to-le.bc", + errs() << " *** ERROR: Loop extraction broke the program. :(" + << " Please report a bug!\n"; + errs() << " Continuing on with un-loop-extracted version.\n"; + + BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc", + ToNotOptimize); + BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc", + ToOptimize); + BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc", ToOptimizeLoopExtracted); - std::cerr << "Please submit the bugpoint-loop-extract-fail-*.bc files.\n"; + errs() << "Please submit the " + << OutputPrefix << "-loop-extract-fail-*.bc files.\n"; delete ToOptimize; delete ToNotOptimize; delete ToOptimizeLoopExtracted; @@ -304,12 +319,12 @@ static bool ExtractLoops(BugDriver &BD, delete ToOptimize; BD.switchToInterpreter(AI); - std::cout << " Testing after loop extraction:\n"; + outs() << " Testing after loop extraction:\n"; // Clone modules, the tester function will free them. Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted); Module *TNOBackup = CloneModule(ToNotOptimize); if (!TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize)) { - std::cout << "*** Loop extraction masked the problem. Undoing.\n"; + outs() << "*** Loop extraction masked the problem. Undoing.\n"; // If the program is not still broken, then loop extraction did something // that masked the error. Stop loop extraction now. delete TOLEBackup; @@ -319,7 +334,7 @@ static bool ExtractLoops(BugDriver &BD, ToOptimizeLoopExtracted = TOLEBackup; ToNotOptimize = TNOBackup; - std::cout << "*** Loop extraction successful!\n"; + outs() << "*** Loop extraction successful!\n"; std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions; for (Module::iterator I = ToOptimizeLoopExtracted->begin(), @@ -334,8 +349,8 @@ static bool ExtractLoops(BugDriver &BD, // extract another loop. std::string ErrorMsg; if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){ - std::cerr << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; + errs() << BD.getToolName() << ": Error linking modules together:" + << ErrorMsg << '\n'; exit(1); } delete ToOptimizeLoopExtracted; @@ -388,16 +403,16 @@ namespace { bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs) { // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. - std::cout << "Checking to see if the program is misoptimized when all "; + outs() << "Checking to see if the program is misoptimized when all "; if (!BBs.empty()) { - std::cout << "but these " << BBs.size() << " blocks are extracted: "; + outs() << "but these " << BBs.size() << " blocks are extracted: "; for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i) - std::cout << BBs[i]->getName() << " "; - if (BBs.size() > 10) std::cout << "..."; + outs() << BBs[i]->getName() << " "; + if (BBs.size() > 10) outs() << "..."; } else { - std::cout << "blocks are extracted."; + outs() << "blocks are extracted."; } - std::cout << '\n'; + outs() << '\n'; // Split the module into the two halves of the program we want. DenseMap<const Value*, Value*> ValueMap; @@ -457,7 +472,7 @@ static bool ExtractBlocks(BugDriver &BD, Module *Extracted = BD.ExtractMappedBlocksFromModule(Blocks, ToExtract); if (Extracted == 0) { // Weird, extraction should have worked. - std::cerr << "Nondeterministic problem extracting blocks??\n"; + errs() << "Nondeterministic problem extracting blocks??\n"; delete ProgClone; delete ToExtract; return false; @@ -476,8 +491,8 @@ static bool ExtractBlocks(BugDriver &BD, std::string ErrorMsg; if (Linker::LinkModules(ProgClone, Extracted, &ErrorMsg)) { - std::cerr << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; + errs() << BD.getToolName() << ": Error linking modules together:" + << ErrorMsg << '\n'; exit(1); } delete Extracted; @@ -520,11 +535,11 @@ DebugAMiscompilation(BugDriver &BD, if (!BugpointIsInterrupted) ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); - std::cout << "\n*** The following function" - << (MiscompiledFunctions.size() == 1 ? " is" : "s are") - << " being miscompiled: "; + outs() << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; PrintFunctionList(MiscompiledFunctions); - std::cout << '\n'; + outs() << '\n'; // See if we can rip any loops out of the miscompiled functions and still // trigger the problem. @@ -543,14 +558,14 @@ DebugAMiscompilation(BugDriver &BD, if (!BugpointIsInterrupted) ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); - std::cout << "\n*** The following function" - << (MiscompiledFunctions.size() == 1 ? " is" : "s are") - << " being miscompiled: "; + outs() << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; PrintFunctionList(MiscompiledFunctions); - std::cout << '\n'; + outs() << '\n'; } - if (!BugpointIsInterrupted && + if (!BugpointIsInterrupted && !DisableBlockExtraction && ExtractBlocks(BD, TestFn, MiscompiledFunctions)) { // Okay, we extracted some blocks and the problem still appears. See if we // can eliminate some of the created functions from being candidates. @@ -563,11 +578,11 @@ DebugAMiscompilation(BugDriver &BD, // Do the reduction... ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); - std::cout << "\n*** The following function" - << (MiscompiledFunctions.size() == 1 ? " is" : "s are") - << " being miscompiled: "; + outs() << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; PrintFunctionList(MiscompiledFunctions); - std::cout << '\n'; + outs() << '\n'; } return MiscompiledFunctions; @@ -580,15 +595,15 @@ DebugAMiscompilation(BugDriver &BD, static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe) { // Run the optimization passes on ToOptimize, producing a transformed version // of the functions being tested. - std::cout << " Optimizing functions being tested: "; + outs() << " Optimizing functions being tested: "; Module *Optimized = BD.runPassesOn(Test, BD.getPassesToRun(), /*AutoDebugCrashes*/true); - std::cout << "done.\n"; + outs() << "done.\n"; delete Test; - std::cout << " Checking to see if the merged program executes correctly: "; + outs() << " Checking to see if the merged program executes correctly: "; bool Broken = TestMergedProgram(BD, Optimized, Safe, true); - std::cout << (Broken ? " nope.\n" : " yup.\n"); + outs() << (Broken ? " nope.\n" : " yup.\n"); return Broken; } @@ -601,33 +616,33 @@ bool BugDriver::debugMiscompilation() { // Make sure something was miscompiled... if (!BugpointIsInterrupted) if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) { - std::cerr << "*** Optimized program matches reference output! No problem" - << " detected...\nbugpoint can't help you with your problem!\n"; + errs() << "*** Optimized program matches reference output! No problem" + << " detected...\nbugpoint can't help you with your problem!\n"; return false; } - std::cout << "\n*** Found miscompiling pass" - << (getPassesToRun().size() == 1 ? "" : "es") << ": " - << getPassesString(getPassesToRun()) << '\n'; + outs() << "\n*** Found miscompiling pass" + << (getPassesToRun().size() == 1 ? "" : "es") << ": " + << getPassesString(getPassesToRun()) << '\n'; EmitProgressBitcode("passinput"); std::vector<Function*> MiscompiledFunctions = DebugAMiscompilation(*this, TestOptimizer); // Output a bunch of bitcode files for the user... - std::cout << "Outputting reduced bitcode files which expose the problem:\n"; + outs() << "Outputting reduced bitcode files which expose the problem:\n"; DenseMap<const Value*, Value*> ValueMap; Module *ToNotOptimize = CloneModule(getProgram(), ValueMap); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, ValueMap); - std::cout << " Non-optimized portion: "; + outs() << " Non-optimized portion: "; ToNotOptimize = swapProgramIn(ToNotOptimize); EmitProgressBitcode("tonotoptimize", true); setNewProgram(ToNotOptimize); // Delete hacked module. - std::cout << " Portion that is input to optimizer: "; + outs() << " Portion that is input to optimizer: "; ToOptimize = swapProgramIn(ToOptimize); EmitProgressBitcode("tooptimize"); setNewProgram(ToOptimize); // Delete hacked module. @@ -672,12 +687,12 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, } // Call the old main function and return its result - BasicBlock *BB = BasicBlock::Create("entry", newMain); + BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain); CallInst *call = CallInst::Create(oldMainProto, args.begin(), args.end(), "", BB); // If the type of old function wasn't void, return value of call - ReturnInst::Create(call, BB); + ReturnInst::Create(Safe->getContext(), call, BB); } // The second nasty issue we must deal with in the JIT is that the Safe @@ -689,8 +704,9 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Prototype: void *getPointerToNamedFunction(const char* Name) Constant *resolverFunc = Safe->getOrInsertFunction("getPointerToNamedFunction", - PointerType::getUnqual(Type::Int8Ty), - PointerType::getUnqual(Type::Int8Ty), (Type *)0); + Type::getInt8PtrTy(Safe->getContext()), + Type::getInt8PtrTy(Safe->getContext()), + (Type *)0); // Use the function we just added to get addresses of functions we need. for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { @@ -701,18 +717,20 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Don't forward functions which are external in the test module too. if (TestFn && !TestFn->isDeclaration()) { // 1. Add a string constant with its name to the global file - Constant *InitArray = ConstantArray::get(F->getName()); + Constant *InitArray = ConstantArray::get(F->getContext(), F->getName()); GlobalVariable *funcName = - new GlobalVariable(InitArray->getType(), true /*isConstant*/, + new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, GlobalValue::InternalLinkage, InitArray, - F->getName() + "_name", Safe); + F->getName() + "_name"); // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an // sbyte* so it matches the signature of the resolver function. // GetElementPtr *funcName, ulong 0, ulong 0 - std::vector<Constant*> GEPargs(2,Constant::getNullValue(Type::Int32Ty)); - Value *GEP = ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2); + std::vector<Constant*> GEPargs(2, + Constant::getNullValue(Type::getInt32Ty(F->getContext()))); + Value *GEP = + ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2); std::vector<Value*> ResolverArgs; ResolverArgs.push_back(GEP); @@ -722,8 +740,9 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Create a new global to hold the cached function pointer. Constant *NullPtr = ConstantPointerNull::get(F->getType()); GlobalVariable *Cache = - new GlobalVariable(F->getType(), false,GlobalValue::InternalLinkage, - NullPtr,F->getName()+".fpcache", F->getParent()); + new GlobalVariable(*F->getParent(), F->getType(), + false, GlobalValue::InternalLinkage, + NullPtr,F->getName()+".fpcache"); // Construct a new stub function that will re-route calls to F const FunctionType *FuncTy = F->getFunctionType(); @@ -731,14 +750,17 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, GlobalValue::InternalLinkage, F->getName() + "_wrapper", F->getParent()); - BasicBlock *EntryBB = BasicBlock::Create("entry", FuncWrapper); - BasicBlock *DoCallBB = BasicBlock::Create("usecache", FuncWrapper); - BasicBlock *LookupBB = BasicBlock::Create("lookupfp", FuncWrapper); + BasicBlock *EntryBB = BasicBlock::Create(F->getContext(), + "entry", FuncWrapper); + BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(), + "usecache", FuncWrapper); + BasicBlock *LookupBB = BasicBlock::Create(F->getContext(), + "lookupfp", FuncWrapper); // Check to see if we already looked up the value. Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB); - Value *IsNull = new ICmpInst(ICmpInst::ICMP_EQ, CachedVal, - NullPtr, "isNull", EntryBB); + Value *IsNull = new ICmpInst(*EntryBB, ICmpInst::ICMP_EQ, CachedVal, + NullPtr, "isNull"); BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB); // Resolve the call to function F via the JIT API: @@ -770,13 +792,13 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, Args.push_back(i); // Pass on the arguments to the real function, return its result - if (F->getReturnType() == Type::VoidTy) { + if (F->getReturnType() == Type::getVoidTy(F->getContext())) { CallInst::Create(FuncPtr, Args.begin(), Args.end(), "", DoCallBB); - ReturnInst::Create(DoCallBB); + ReturnInst::Create(F->getContext(), DoCallBB); } else { CallInst *Call = CallInst::Create(FuncPtr, Args.begin(), Args.end(), "retval", DoCallBB); - ReturnInst::Create(Call, DoCallBB); + ReturnInst::Create(F->getContext(),Call, DoCallBB); } // Use the wrapper function instead of the old function @@ -787,7 +809,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, } if (verifyModule(*Test) || verifyModule(*Safe)) { - std::cerr << "Bugpoint has a bug, which corrupted a module!!\n"; + errs() << "Bugpoint has a bug, which corrupted a module!!\n"; abort(); } } @@ -804,12 +826,13 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) { sys::Path TestModuleBC("bugpoint.test.bc"); std::string ErrMsg; if (TestModuleBC.makeUnique(true, &ErrMsg)) { - std::cerr << BD.getToolName() << "Error making unique filename: " - << ErrMsg << "\n"; + errs() << BD.getToolName() << "Error making unique filename: " + << ErrMsg << "\n"; exit(1); } - if (BD.writeProgramToFile(TestModuleBC.toString(), Test)) { - std::cerr << "Error writing bitcode to `" << TestModuleBC << "'\nExiting."; + if (BD.writeProgramToFile(TestModuleBC.str(), Test)) { + errs() << "Error writing bitcode to `" << TestModuleBC.str() + << "'\nExiting."; exit(1); } delete Test; @@ -817,26 +840,27 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) { // Make the shared library sys::Path SafeModuleBC("bugpoint.safe.bc"); if (SafeModuleBC.makeUnique(true, &ErrMsg)) { - std::cerr << BD.getToolName() << "Error making unique filename: " - << ErrMsg << "\n"; + errs() << BD.getToolName() << "Error making unique filename: " + << ErrMsg << "\n"; exit(1); } - if (BD.writeProgramToFile(SafeModuleBC.toString(), Safe)) { - std::cerr << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; + if (BD.writeProgramToFile(SafeModuleBC.str(), Safe)) { + errs() << "Error writing bitcode to `" << SafeModuleBC.str() + << "'\nExiting."; exit(1); } - std::string SharedObject = BD.compileSharedObject(SafeModuleBC.toString()); + std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str()); delete Safe; // Run the code generator on the `Test' code, loading the shared library. // The function returns whether or not the new output differs from reference. - int Result = BD.diffProgram(TestModuleBC.toString(), SharedObject, false); + int Result = BD.diffProgram(TestModuleBC.str(), SharedObject, false); if (Result) - std::cerr << ": still failing!\n"; + errs() << ": still failing!\n"; else - std::cerr << ": didn't fail.\n"; + errs() << ": didn't fail.\n"; TestModuleBC.eraseFromDisk(); SafeModuleBC.eraseFromDisk(); sys::Path(SharedObject).eraseFromDisk(); @@ -850,14 +874,14 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) { bool BugDriver::debugCodeGenerator() { if ((void*)SafeInterpreter == (void*)Interpreter) { std::string Result = executeProgramSafely("bugpoint.safe.out"); - std::cout << "\n*** The \"safe\" i.e. 'known good' backend cannot match " - << "the reference diff. This may be due to a\n front-end " - << "bug or a bug in the original program, but this can also " - << "happen if bugpoint isn't running the program with the " - << "right flags or input.\n I left the result of executing " - << "the program with the \"safe\" backend in this file for " - << "you: '" - << Result << "'.\n"; + outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match " + << "the reference diff. This may be due to a\n front-end " + << "bug or a bug in the original program, but this can also " + << "happen if bugpoint isn't running the program with the " + << "right flags or input.\n I left the result of executing " + << "the program with the \"safe\" backend in this file for " + << "you: '" + << Result << "'.\n"; return true; } @@ -876,13 +900,14 @@ bool BugDriver::debugCodeGenerator() { sys::Path TestModuleBC("bugpoint.test.bc"); std::string ErrMsg; if (TestModuleBC.makeUnique(true, &ErrMsg)) { - std::cerr << getToolName() << "Error making unique filename: " - << ErrMsg << "\n"; + errs() << getToolName() << "Error making unique filename: " + << ErrMsg << "\n"; exit(1); } - if (writeProgramToFile(TestModuleBC.toString(), ToCodeGen)) { - std::cerr << "Error writing bitcode to `" << TestModuleBC << "'\nExiting."; + if (writeProgramToFile(TestModuleBC.str(), ToCodeGen)) { + errs() << "Error writing bitcode to `" << TestModuleBC.str() + << "'\nExiting."; exit(1); } delete ToCodeGen; @@ -890,43 +915,45 @@ bool BugDriver::debugCodeGenerator() { // Make the shared library sys::Path SafeModuleBC("bugpoint.safe.bc"); if (SafeModuleBC.makeUnique(true, &ErrMsg)) { - std::cerr << getToolName() << "Error making unique filename: " - << ErrMsg << "\n"; + errs() << getToolName() << "Error making unique filename: " + << ErrMsg << "\n"; exit(1); } - if (writeProgramToFile(SafeModuleBC.toString(), ToNotCodeGen)) { - std::cerr << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; + if (writeProgramToFile(SafeModuleBC.str(), ToNotCodeGen)) { + errs() << "Error writing bitcode to `" << SafeModuleBC.str() + << "'\nExiting."; exit(1); } - std::string SharedObject = compileSharedObject(SafeModuleBC.toString()); + std::string SharedObject = compileSharedObject(SafeModuleBC.str()); delete ToNotCodeGen; - std::cout << "You can reproduce the problem with the command line: \n"; + outs() << "You can reproduce the problem with the command line: \n"; if (isExecutingJIT()) { - std::cout << " lli -load " << SharedObject << " " << TestModuleBC; + outs() << " lli -load " << SharedObject << " " << TestModuleBC.str(); } else { - std::cout << " llc -f " << TestModuleBC << " -o " << TestModuleBC<< ".s\n"; - std::cout << " gcc " << SharedObject << " " << TestModuleBC - << ".s -o " << TestModuleBC << ".exe"; + outs() << " llc -f " << TestModuleBC.str() << " -o " << TestModuleBC.str() + << ".s\n"; + outs() << " gcc " << SharedObject << " " << TestModuleBC.str() + << ".s -o " << TestModuleBC.str() << ".exe"; #if defined (HAVE_LINK_R) - std::cout << " -Wl,-R."; + outs() << " -Wl,-R."; #endif - std::cout << "\n"; - std::cout << " " << TestModuleBC << ".exe"; + outs() << "\n"; + outs() << " " << TestModuleBC.str() << ".exe"; } for (unsigned i=0, e = InputArgv.size(); i != e; ++i) - std::cout << " " << InputArgv[i]; - std::cout << '\n'; - std::cout << "The shared object was created with:\n llc -march=c " - << SafeModuleBC << " -o temporary.c\n" - << " gcc -xc temporary.c -O2 -o " << SharedObject -#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) - << " -G" // Compile a shared library, `-G' for Sparc -#else - << " -fPIC -shared" // `-shared' for Linux/X86, maybe others -#endif - << " -fno-strict-aliasing\n"; + outs() << " " << InputArgv[i]; + outs() << '\n'; + outs() << "The shared object was created with:\n llc -march=c " + << SafeModuleBC.str() << " -o temporary.c\n" + << " gcc -xc temporary.c -O2 -o " << SharedObject; + if (TargetTriple.getArch() == Triple::sparc) + outs() << " -G"; // Compile a shared library, `-G' for Sparc + else + outs() << " -fPIC -shared"; // `-shared' for Linux/X86, maybe others + + outs() << " -fno-strict-aliasing\n"; return false; } diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index 741be24adefd..9f712e097a74 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -27,10 +27,9 @@ #include "llvm/Target/TargetData.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Streams.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" #include "llvm/System/Program.h" -#include "llvm/Config/alloca.h" #define DONT_GET_PLUGIN_LOADER_OPTION #include "llvm/Support/PluginLoader.h" @@ -38,6 +37,9 @@ #include <fstream> using namespace llvm; +namespace llvm { + extern cl::opt<std::string> OutputPrefix; +} namespace { // ChildOutput - This option captures the name of the child output file that @@ -52,10 +54,10 @@ namespace { /// bool BugDriver::writeProgramToFile(const std::string &Filename, Module *M) const { - std::ios::openmode io_mode = std::ios::out | std::ios::trunc | - std::ios::binary; - std::ofstream Out(Filename.c_str(), io_mode); - if (!Out.good()) return true; + std::string ErrInfo; + raw_fd_ostream Out(Filename.c_str(), ErrInfo, + raw_fd_ostream::F_Binary); + if (!ErrInfo.empty()) return true; WriteBitcodeToFile(M ? M : Program, Out); return false; @@ -69,26 +71,26 @@ void BugDriver::EmitProgressBitcode(const std::string &ID, bool NoFlyer) { // Output the input to the current pass to a bitcode file, emit a message // telling the user how to reproduce it: opt -foo blah.bc // - std::string Filename = "bugpoint-" + ID + ".bc"; + std::string Filename = OutputPrefix + "-" + ID + ".bc"; if (writeProgramToFile(Filename)) { - cerr << "Error opening file '" << Filename << "' for writing!\n"; + errs() << "Error opening file '" << Filename << "' for writing!\n"; return; } - cout << "Emitted bitcode to '" << Filename << "'\n"; + outs() << "Emitted bitcode to '" << Filename << "'\n"; if (NoFlyer || PassesToRun.empty()) return; - cout << "\n*** You can reproduce the problem with: "; - cout << "opt " << Filename << " "; - cout << getPassesString(PassesToRun) << "\n"; + outs() << "\n*** You can reproduce the problem with: "; + if (UseValgrind) outs() << "valgrind "; + outs() << "opt " << Filename << " "; + outs() << getPassesString(PassesToRun) << "\n"; } int BugDriver::runPassesAsChild(const std::vector<const PassInfo*> &Passes) { - - std::ios::openmode io_mode = std::ios::out | std::ios::trunc | - std::ios::binary; - std::ofstream OutFile(ChildOutput.c_str(), io_mode); - if (!OutFile.good()) { - cerr << "Error opening bitcode file: " << ChildOutput << "\n"; + std::string ErrInfo; + raw_fd_ostream OutFile(ChildOutput.c_str(), ErrInfo, + raw_fd_ostream::F_Binary); + if (!ErrInfo.empty()) { + errs() << "Error opening bitcode file: " << ChildOutput << "\n"; return 1; } @@ -100,13 +102,13 @@ int BugDriver::runPassesAsChild(const std::vector<const PassInfo*> &Passes) { if (Passes[i]->getNormalCtor()) PM.add(Passes[i]->getNormalCtor()()); else - cerr << "Cannot create pass yet: " << Passes[i]->getPassName() << "\n"; + errs() << "Cannot create pass yet: " << Passes[i]->getPassName() << "\n"; } // Check that the module is well formed on completion of optimization PM.add(createVerifierPass()); // Write bitcode out to disk as the last step... - PM.add(CreateBitcodeWriterPass(OutFile)); + PM.add(createBitcodeWriterPass(OutFile)); // Run all queued passes. PM.run(*Program); @@ -121,58 +123,58 @@ cl::opt<bool> SilencePasses("silence-passes", cl::desc("Suppress output of runni /// optimizations fail for some reason (optimizer crashes), return true, /// otherwise return false. If DeleteOutput is set to true, the bitcode is /// deleted on success, and the filename string is undefined. This prints to -/// cout a single line message indicating whether compilation was successful or -/// failed. +/// outs() a single line message indicating whether compilation was successful +/// or failed. /// bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes, std::string &OutputFilename, bool DeleteOutput, bool Quiet, unsigned NumExtraArgs, const char * const *ExtraArgs) const { // setup the output file name - cout << std::flush; - sys::Path uniqueFilename("bugpoint-output.bc"); + outs().flush(); + sys::Path uniqueFilename(OutputPrefix + "-output.bc"); std::string ErrMsg; if (uniqueFilename.makeUnique(true, &ErrMsg)) { - cerr << getToolName() << ": Error making unique filename: " - << ErrMsg << "\n"; + errs() << getToolName() << ": Error making unique filename: " + << ErrMsg << "\n"; return(1); } - OutputFilename = uniqueFilename.toString(); + OutputFilename = uniqueFilename.str(); // set up the input file name - sys::Path inputFilename("bugpoint-input.bc"); + sys::Path inputFilename(OutputPrefix + "-input.bc"); if (inputFilename.makeUnique(true, &ErrMsg)) { - cerr << getToolName() << ": Error making unique filename: " - << ErrMsg << "\n"; + errs() << getToolName() << ": Error making unique filename: " + << ErrMsg << "\n"; return(1); } - std::ios::openmode io_mode = std::ios::out | std::ios::trunc | - std::ios::binary; - std::ofstream InFile(inputFilename.c_str(), io_mode); - if (!InFile.good()) { - cerr << "Error opening bitcode file: " << inputFilename << "\n"; - return(1); + + std::string ErrInfo; + raw_fd_ostream InFile(inputFilename.c_str(), ErrInfo, + raw_fd_ostream::F_Binary); + + + if (!ErrInfo.empty()) { + errs() << "Error opening bitcode file: " << inputFilename.str() << "\n"; + return 1; } WriteBitcodeToFile(Program, InFile); InFile.close(); // setup the child process' arguments - const char** args = (const char**) - alloca(sizeof(const char*) * - (Passes.size()+13+2*PluginLoader::getNumPlugins()+NumExtraArgs)); - int n = 0; + SmallVector<const char*, 8> Args; sys::Path tool = sys::Program::FindProgramByName(ToolName); if (UseValgrind) { - args[n++] = "valgrind"; - args[n++] = "--error-exitcode=1"; - args[n++] = "-q"; - args[n++] = tool.c_str(); + Args.push_back("valgrind"); + Args.push_back("--error-exitcode=1"); + Args.push_back("-q"); + Args.push_back(tool.c_str()); } else - args[n++] = ToolName.c_str(); + Args.push_back(ToolName); - args[n++] = "-as-child"; - args[n++] = "-child-output"; - args[n++] = OutputFilename.c_str(); + Args.push_back("-as-child"); + Args.push_back("-child-output"); + Args.push_back(OutputFilename.c_str()); std::vector<std::string> pass_args; for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { pass_args.push_back( std::string("-load")); @@ -183,11 +185,11 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes, pass_args.push_back( std::string("-") + (*I)->getPassArgument() ); for (std::vector<std::string>::const_iterator I = pass_args.begin(), E = pass_args.end(); I != E; ++I ) - args[n++] = I->c_str(); - args[n++] = inputFilename.c_str(); + Args.push_back(I->c_str()); + Args.push_back(inputFilename.c_str()); for (unsigned i = 0; i < NumExtraArgs; ++i) - args[n++] = *ExtraArgs; - args[n++] = 0; + Args.push_back(*ExtraArgs); + Args.push_back(0); sys::Path prog; if (UseValgrind) @@ -199,7 +201,8 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes, sys::Path Nowhere; const sys::Path *Redirects[3] = {0, &Nowhere, &Nowhere}; - int result = sys::Program::ExecuteAndWait(prog, args, 0, (SilencePasses ? Redirects : 0), + int result = sys::Program::ExecuteAndWait(prog, Args.data(), 0, + (SilencePasses ? Redirects : 0), Timeout, MemoryLimit, &ErrMsg); // If we are supposed to delete the bitcode file or if the passes crashed, @@ -212,17 +215,17 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes, if (!Quiet) { if (result == 0) - cout << "Success!\n"; + outs() << "Success!\n"; else if (result > 0) - cout << "Exited with error code '" << result << "'\n"; + outs() << "Exited with error code '" << result << "'\n"; else if (result < 0) { if (result == -1) - cout << "Execute failed: " << ErrMsg << "\n"; + outs() << "Execute failed: " << ErrMsg << "\n"; else - cout << "Crashed with signal #" << abs(result) << "\n"; + outs() << "Crashed with signal #" << abs(result) << "\n"; } if (result & 0x01000000) - cout << "Dumped core\n"; + outs() << "Dumped core\n"; } // Was the child successful? @@ -242,8 +245,8 @@ Module *BugDriver::runPassesOn(Module *M, if (runPasses(Passes, BitcodeResult, false/*delete*/, true/*quiet*/, NumExtraArgs, ExtraArgs)) { if (AutoDebugCrashes) { - cerr << " Error running this sequence of passes" - << " on the input program!\n"; + errs() << " Error running this sequence of passes" + << " on the input program!\n"; delete OldProgram; EmitProgressBitcode("pass-error", false); exit(debugOptimizerCrash()); @@ -257,8 +260,8 @@ Module *BugDriver::runPassesOn(Module *M, Module *Ret = ParseInputFile(BitcodeResult, Context); if (Ret == 0) { - cerr << getToolName() << ": Error reading bitcode file '" - << BitcodeResult << "'!\n"; + errs() << getToolName() << ": Error reading bitcode file '" + << BitcodeResult << "'!\n"; exit(1); } sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 978e60bed38a..4551d419d73a 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -13,16 +13,22 @@ #define DEBUG_TYPE "toolrunner" #include "ToolRunner.h" -#include "llvm/Config/config.h" // for HAVE_LINK_R #include "llvm/System/Program.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" // for HAVE_LINK_R #include <fstream> #include <sstream> -#include <iostream> using namespace llvm; +namespace llvm { + cl::opt<bool> + SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); +} + namespace { cl::opt<std::string> RemoteClient("remote-client", @@ -33,6 +39,10 @@ namespace { cl::desc("Remote execution (rsh/ssh) host")); cl::opt<std::string> + RemotePort("remote-port", + cl::desc("Remote execution (rsh/ssh) port")); + + cl::opt<std::string> RemoteUser("remote-user", cl::desc("Remote execution (rsh/ssh) user id")); @@ -43,8 +53,8 @@ namespace { ToolExecutionError::~ToolExecutionError() throw() { } -/// RunProgramWithTimeout - This function provides an alternate interface to the -/// sys::Program::ExecuteAndWait interface. +/// RunProgramWithTimeout - This function provides an alternate interface +/// to the sys::Program::ExecuteAndWait interface. /// @see sys:Program::ExecuteAndWait static int RunProgramWithTimeout(const sys::Path &ProgramPath, const char **Args, @@ -57,20 +67,74 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath, redirects[0] = &StdInFile; redirects[1] = &StdOutFile; redirects[2] = &StdErrFile; - - if (0) { - std::cerr << "RUN:"; + +#if 0 // For debug purposes + { + errs() << "RUN:"; for (unsigned i = 0; Args[i]; ++i) - std::cerr << " " << Args[i]; - std::cerr << "\n"; + errs() << " " << Args[i]; + errs() << "\n"; } +#endif return sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, NumSeconds, MemoryLimit); } +/// RunProgramRemotelyWithTimeout - This function runs the given program +/// remotely using the given remote client and the sys::Program::ExecuteAndWait. +/// Returns the remote program exit code or reports a remote client error if it +/// fails. Remote client is required to return 255 if it failed or program exit +/// code otherwise. +/// @see sys:Program::ExecuteAndWait +static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, + const char **Args, + const sys::Path &StdInFile, + const sys::Path &StdOutFile, + const sys::Path &StdErrFile, + unsigned NumSeconds = 0, + unsigned MemoryLimit = 0) { + const sys::Path* redirects[3]; + redirects[0] = &StdInFile; + redirects[1] = &StdOutFile; + redirects[2] = &StdErrFile; + +#if 0 // For debug purposes + { + errs() << "RUN:"; + for (unsigned i = 0; Args[i]; ++i) + errs() << " " << Args[i]; + errs() << "\n"; + } +#endif + // Run the program remotely with the remote client + int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, + 0, redirects, NumSeconds, MemoryLimit); + + // Has the remote client fail? + if (255 == ReturnCode) { + std::ostringstream OS; + OS << "\nError running remote client:\n "; + for (const char **Arg = Args; *Arg; ++Arg) + OS << " " << *Arg; + OS << "\n"; + + // The error message is in the output file, let's print it out from there. + std::ifstream ErrorFile(StdOutFile.c_str()); + if (ErrorFile) { + std::copy(std::istreambuf_iterator<char>(ErrorFile), + std::istreambuf_iterator<char>(), + std::ostreambuf_iterator<char>(OS)); + ErrorFile.close(); + } + + throw ToolExecutionError(OS.str()); + } + + return ReturnCode; +} static void ProcessFailure(sys::Path ProgPath, const char** Args) { std::ostringstream OS; @@ -83,7 +147,7 @@ static void ProcessFailure(sys::Path ProgPath, const char** Args) { sys::Path ErrorFilename("bugpoint.program_error_messages"); std::string ErrMsg; if (ErrorFilename.makeUnique(true, &ErrMsg)) { - std::cerr << "Error making unique filename: " << ErrMsg << "\n"; + errs() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, @@ -154,11 +218,11 @@ int LLI::ExecuteProgram(const std::string &Bitcode, LLIArgs.push_back(Args[i].c_str()); LLIArgs.push_back(0); - std::cout << "<lli>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\t"; + outs() << "<lli>"; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) - std::cerr << " " << LLIArgs[i]; - std::cerr << "\n"; + errs() << " " << LLIArgs[i]; + errs() << "\n"; ); return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), @@ -166,10 +230,11 @@ int LLI::ExecuteProgram(const std::string &Bitcode, } // LLI create method - Try to find the LLI executable -AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath, +AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, std::string &Message, const std::vector<std::string> *ToolArgs) { - std::string LLIPath = FindExecutable("lli", ProgPath).toString(); + std::string LLIPath = + FindExecutable("lli", Argv0, (void *)(intptr_t)&createLLI).str(); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new LLI(LLIPath, ToolArgs); @@ -236,7 +301,6 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, // Custom execution environment create method, takes the execution command // as arguments AbstractInterpreter *AbstractInterpreter::createCustom( - const std::string &ProgramPath, std::string &Message, const std::string &ExecCommandLine) { @@ -270,7 +334,7 @@ AbstractInterpreter *AbstractInterpreter::createCustom( pos = ExecCommandLine.find_first_of(delimiters, lastPos); } - std::string CmdPath = FindExecutable(Command, ProgramPath).toString(); + std::string CmdPath = sys::Program::FindProgramByName(Command).str(); if (CmdPath.empty()) { Message = std::string("Cannot find '") + Command + @@ -291,7 +355,7 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, sys::Path uniqueFile(Bitcode+".llc.s"); std::string ErrMsg; if (uniqueFile.makeUnique(true, &ErrMsg)) { - std::cerr << "Error making unique filename: " << ErrMsg << "\n"; + errs() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } OutputAsmFile = uniqueFile; @@ -304,15 +368,14 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, LLCArgs.push_back ("-o"); LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file - LLCArgs.push_back ("-f"); // Overwrite as necessary... LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode LLCArgs.push_back (0); - std::cout << "<llc>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\t"; + outs() << "<llc>"; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) - std::cerr << " " << LLCArgs[i]; - std::cerr << "\n"; + errs() << " " << LLCArgs[i]; + errs() << "\n"; ); if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], sys::Path(), sys::Path(), sys::Path())) @@ -338,34 +401,35 @@ int LLC::ExecuteProgram(const std::string &Bitcode, sys::Path OutputAsmFile; OutputCode(Bitcode, OutputAsmFile); - FileRemover OutFileRemover(OutputAsmFile); + FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); std::vector<std::string> GCCArgs(ArgsForGCC); GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); GCCArgs.insert(GCCArgs.end(), gccArgs.begin(), gccArgs.end()); // Assuming LLC worked, compile the result with GCC and run it. - return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile, + return gcc->ExecuteProgram(OutputAsmFile.str(), Args, GCC::AsmFile, InputFile, OutputFile, GCCArgs, Timeout, MemoryLimit); } /// createLLC - Try to find the LLC executable /// -LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath, +LLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message, const std::vector<std::string> *Args, const std::vector<std::string> *GCCArgs) { - std::string LLCPath = FindExecutable("llc", ProgramPath).toString(); + std::string LLCPath = + FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str(); if (LLCPath.empty()) { Message = "Cannot find `llc' in executable directory or PATH!\n"; return 0; } Message = "Found llc: " + LLCPath + "\n"; - GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs); + GCC *gcc = GCC::create(Message, GCCArgs); if (!gcc) { - std::cerr << Message << "\n"; + errs() << Message << "\n"; exit(1); } return new LLC(LLCPath, gcc, Args, GCCArgs); @@ -425,13 +489,13 @@ int JIT::ExecuteProgram(const std::string &Bitcode, JITArgs.push_back(Args[i].c_str()); JITArgs.push_back(0); - std::cout << "<jit>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\t"; + outs() << "<jit>"; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) - std::cerr << " " << JITArgs[i]; - std::cerr << "\n"; + errs() << " " << JITArgs[i]; + errs() << "\n"; ); - DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n"); + DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), Timeout, MemoryLimit); @@ -439,9 +503,10 @@ int JIT::ExecuteProgram(const std::string &Bitcode, /// createJIT - Try to find the LLI executable /// -AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath, +AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, std::string &Message, const std::vector<std::string> *Args) { - std::string LLIPath = FindExecutable("lli", ProgPath).toString(); + std::string LLIPath = + FindExecutable("lli", Argv0, (void *)(intptr_t)&createJIT).str(); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new JIT(LLIPath, Args); @@ -456,7 +521,7 @@ GCC::FileType CBE::OutputCode(const std::string &Bitcode, sys::Path uniqueFile(Bitcode+".cbe.c"); std::string ErrMsg; if (uniqueFile.makeUnique(true, &ErrMsg)) { - std::cerr << "Error making unique filename: " << ErrMsg << "\n"; + errs() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } OutputCFile = uniqueFile; @@ -474,11 +539,11 @@ GCC::FileType CBE::OutputCode(const std::string &Bitcode, LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode LLCArgs.push_back (0); - std::cout << "<cbe>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\t"; + outs() << "<cbe>"; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) - std::cerr << " " << LLCArgs[i]; - std::cerr << "\n"; + errs() << " " << LLCArgs[i]; + errs() << "\n"; ); if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), sys::Path())) @@ -503,33 +568,34 @@ int CBE::ExecuteProgram(const std::string &Bitcode, sys::Path OutputCFile; OutputCode(Bitcode, OutputCFile); - FileRemover CFileRemove(OutputCFile); + FileRemover CFileRemove(OutputCFile, !SaveTemps); std::vector<std::string> GCCArgs(ArgsForGCC); GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); - return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile, + return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, InputFile, OutputFile, GCCArgs, Timeout, MemoryLimit); } /// createCBE - Try to find the 'llc' executable /// -CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath, +CBE *AbstractInterpreter::createCBE(const char *Argv0, std::string &Message, const std::vector<std::string> *Args, const std::vector<std::string> *GCCArgs) { - sys::Path LLCPath = FindExecutable("llc", ProgramPath); + sys::Path LLCPath = + FindExecutable("llc", Argv0, (void *)(intptr_t)&createCBE); if (LLCPath.isEmpty()) { Message = "Cannot find `llc' in executable directory or PATH!\n"; return 0; } - Message = "Found llc: " + LLCPath.toString() + "\n"; - GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs); + Message = "Found llc: " + LLCPath.str() + "\n"; + GCC *gcc = GCC::create(Message, GCCArgs); if (!gcc) { - std::cerr << Message << "\n"; + errs() << Message << "\n"; exit(1); } return new CBE(LLCPath, gcc, Args); @@ -538,6 +604,23 @@ CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath, //===---------------------------------------------------------------------===// // GCC abstraction // + +static bool +IsARMArchitecture(std::vector<std::string> Args) +{ + for (std::vector<std::string>::const_iterator + I = Args.begin(), E = Args.end(); I != E; ++I) { + if (!StringsEqualNoCase(*I, "-arch")) { + ++I; + if ((I != E) && !StringsEqualNoCase(I->c_str(), "arm", strlen("arm"))) { + return true; + } + } + } + + return false; +} + int GCC::ExecuteProgram(const std::string &ProgramFile, const std::vector<std::string> &Args, FileType fileType, @@ -561,9 +644,13 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, GCCArgs.push_back("-fno-strict-aliasing"); } else { GCCArgs.push_back("assembler"); -#ifdef __APPLE__ - GCCArgs.push_back("-force_cpusubtype_ALL"); -#endif + + // For ARM architectures we don't want this flag. bugpoint isn't + // explicitly told what architecture it is working on, so we get + // it from gcc flags + if ((TargetTriple.getOS() == Triple::Darwin) && + !IsARMArchitecture(ArgsForGCC)) + GCCArgs.push_back("-force_cpusubtype_ALL"); } GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename... GCCArgs.push_back("-x"); @@ -572,7 +659,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, sys::Path OutputBinary (ProgramFile+".gcc.exe"); std::string ErrMsg; if (OutputBinary.makeUnique(true, &ErrMsg)) { - std::cerr << "Error making unique filename: " << ErrMsg << "\n"; + errs() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... @@ -589,16 +676,15 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, #if defined (HAVE_LINK_R) GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files #endif -#ifdef __sparc__ - GCCArgs.push_back("-mcpu=v9"); -#endif + if (TargetTriple.getArch() == Triple::sparc) + GCCArgs.push_back("-mcpu=v9"); GCCArgs.push_back(0); // NULL terminator - std::cout << "<gcc>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\t"; + outs() << "<gcc>"; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) - std::cerr << " " << GCCArgs[i]; - std::cerr << "\n"; + errs() << " " << GCCArgs[i]; + errs() << "\n"; ); if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), sys::Path())) { @@ -613,12 +699,20 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, else { ProgramArgs.push_back(RemoteClientPath.c_str()); ProgramArgs.push_back(RemoteHost.c_str()); - ProgramArgs.push_back("-l"); - ProgramArgs.push_back(RemoteUser.c_str()); + if (!RemoteUser.empty()) { + ProgramArgs.push_back("-l"); + ProgramArgs.push_back(RemoteUser.c_str()); + } + if (!RemotePort.empty()) { + ProgramArgs.push_back("-p"); + ProgramArgs.push_back(RemotePort.c_str()); + } if (!RemoteExtra.empty()) { ProgramArgs.push_back(RemoteExtra.c_str()); } + // Full path to the binary. We need to cd to the exec directory because + // there is a dylib there that the exec expects to find in the CWD char* env_pwd = getenv("PWD"); std::string Exec = "cd "; Exec += env_pwd; @@ -633,23 +727,26 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, ProgramArgs.push_back(0); // NULL terminator // Now that we have a binary, run it! - std::cout << "<program>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\t"; + outs() << "<program>"; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i) - std::cerr << " " << ProgramArgs[i]; - std::cerr << "\n"; + errs() << " " << ProgramArgs[i]; + errs() << "\n"; ); - FileRemover OutputBinaryRemover(OutputBinary); + FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps); - if (RemoteClientPath.isEmpty()) + if (RemoteClientPath.isEmpty()) { + DEBUG(errs() << "<run locally>";); return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), Timeout, MemoryLimit); - else - return RunProgramWithTimeout(sys::Path(RemoteClientPath), &ProgramArgs[0], - sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); + } else { + outs() << "<run remotely>"; outs().flush(); + return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), + &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), + sys::Path(OutputFile), Timeout, MemoryLimit); + } } int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, @@ -658,10 +755,10 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); std::string ErrMsg; if (uniqueFilename.makeUnique(true, &ErrMsg)) { - std::cerr << "Error making unique filename: " << ErrMsg << "\n"; + errs() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } - OutputFile = uniqueFilename.toString(); + OutputFile = uniqueFilename.str(); std::vector<const char*> GCCArgs; @@ -678,27 +775,27 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. GCCArgs.push_back("-x"); GCCArgs.push_back("none"); -#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) - GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc -#elif defined(__APPLE__) - // link all source files into a single module in data segment, rather than - // generating blocks. dynamic_lookup requires that you set - // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for - // bugpoint to just pass that in the environment of GCC. - GCCArgs.push_back("-single_module"); - GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC - GCCArgs.push_back("-undefined"); - GCCArgs.push_back("dynamic_lookup"); -#else - GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others -#endif + if (TargetTriple.getArch() == Triple::sparc) + GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc + else if (TargetTriple.getOS() == Triple::Darwin) { + // link all source files into a single module in data segment, rather than + // generating blocks. dynamic_lookup requires that you set + // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for + // bugpoint to just pass that in the environment of GCC. + GCCArgs.push_back("-single_module"); + GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC + GCCArgs.push_back("-undefined"); + GCCArgs.push_back("dynamic_lookup"); + } else + GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others + + if ((TargetTriple.getArch() == Triple::alpha) || + (TargetTriple.getArch() == Triple::x86_64)) + GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC + + if (TargetTriple.getArch() == Triple::sparc) + GCCArgs.push_back("-mcpu=v9"); -#if defined(__ia64__) || defined(__alpha__) || defined(__amd64__) - GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC -#endif -#ifdef __sparc__ - GCCArgs.push_back("-mcpu=v9"); -#endif GCCArgs.push_back("-o"); GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. GCCArgs.push_back("-O2"); // Optimize the program a bit. @@ -715,11 +812,11 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, - std::cout << "<gcc>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\t"; + outs() << "<gcc>"; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) - std::cerr << " " << GCCArgs[i]; - std::cerr << "\n"; + errs() << " " << GCCArgs[i]; + errs() << "\n"; ); if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), sys::Path())) { @@ -731,9 +828,9 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, /// create - Try to find the `gcc' executable /// -GCC *GCC::create(const std::string &ProgramPath, std::string &Message, +GCC *GCC::create(std::string &Message, const std::vector<std::string> *Args) { - sys::Path GCCPath = FindExecutable("gcc", ProgramPath); + sys::Path GCCPath = sys::Program::FindProgramByName("gcc"); if (GCCPath.isEmpty()) { Message = "Cannot find `gcc' in executable directory or PATH!\n"; return 0; @@ -741,8 +838,8 @@ GCC *GCC::create(const std::string &ProgramPath, std::string &Message, sys::Path RemoteClientPath; if (!RemoteClient.empty()) - RemoteClientPath = FindExecutable(RemoteClient.c_str(), ProgramPath); + RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); - Message = "Found gcc: " + GCCPath.toString() + "\n"; + Message = "Found gcc: " + GCCPath.str() + "\n"; return new GCC(GCCPath, RemoteClientPath, Args); } diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index 721f66c126cc..39b0bbfdd5ec 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -17,12 +17,18 @@ #ifndef BUGPOINT_TOOLRUNNER_H #define BUGPOINT_TOOLRUNNER_H +#include "llvm/ADT/Triple.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/SystemUtils.h" +#include "llvm/System/Path.h" #include <exception> #include <vector> namespace llvm { +extern cl::opt<bool> SaveTemps; +extern Triple TargetTriple; + class CBE; class LLC; @@ -54,7 +60,7 @@ class GCC { public: enum FileType { AsmFile, CFile }; - static GCC *create(const std::string &ProgramPath, std::string &Message, + static GCC *create(std::string &Message, const std::vector<std::string> *Args); /// ExecuteProgram - Execute the program specified by "ProgramFile" (which is @@ -90,23 +96,20 @@ public: /// class AbstractInterpreter { public: - static CBE *createCBE(const std::string &ProgramPath, std::string &Message, + static CBE *createCBE(const char *Argv0, std::string &Message, const std::vector<std::string> *Args = 0, const std::vector<std::string> *GCCArgs = 0); - static LLC *createLLC(const std::string &ProgramPath, std::string &Message, + static LLC *createLLC(const char *Argv0, std::string &Message, const std::vector<std::string> *Args = 0, const std::vector<std::string> *GCCArgs = 0); - static AbstractInterpreter* createLLI(const std::string &ProgramPath, - std::string &Message, + static AbstractInterpreter* createLLI(const char *Argv0, std::string &Message, const std::vector<std::string> *Args=0); - static AbstractInterpreter* createJIT(const std::string &ProgramPath, - std::string &Message, + static AbstractInterpreter* createJIT(const char *Argv0, std::string &Message, const std::vector<std::string> *Args=0); - static AbstractInterpreter* createCustom(const std::string &ProgramPath, - std::string &Message, + static AbstractInterpreter* createCustom(std::string &Message, const std::string &ExecCommandLine); diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index 3365b227b1f7..565f3f9a7087 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -22,10 +22,10 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/StandardPasses.h" #include "llvm/System/Process.h" #include "llvm/System/Signals.h" #include "llvm/LinkAllVMCore.h" -#include <iostream> using namespace llvm; // AsChild - Specifies that this invocation of bugpoint is being generated @@ -58,6 +58,17 @@ MemoryLimit("mlimit", cl::init(100), cl::value_desc("MBytes"), static cl::list<const PassInfo*, bool, PassNameParser> PassList(cl::desc("Passes available:"), cl::ZeroOrMore); +static cl::opt<bool> +StandardCompileOpts("std-compile-opts", + cl::desc("Include the standard compile time optimizations")); + +static cl::opt<bool> +StandardLinkOpts("std-link-opts", + cl::desc("Include the standard link time optimizations")); + +static cl::opt<std::string> +OverrideTriple("mtriple", cl::desc("Override target triple for module")); + /// BugpointIsInterrupted - Set to true when the user presses ctrl-c. bool llvm::BugpointIsInterrupted = false; @@ -65,6 +76,20 @@ static void BugpointInterruptFunction() { BugpointIsInterrupted = true; } +// Hack to capture a pass list. +namespace { + class AddToDriver : public PassManager { + BugDriver &D; + public: + AddToDriver(BugDriver &_D) : D(_D) {} + + virtual void add(Pass *P) { + const PassInfo *PI = P->getPassInfo(); + D.addPasses(&PI, &PI + 1); + } + }; +} + int main(int argc, char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); @@ -75,9 +100,33 @@ int main(int argc, char **argv) { " for more information.\n"); sys::SetInterruptFunction(BugpointInterruptFunction); - LLVMContext Context; + LLVMContext& Context = getGlobalContext(); + // If we have an override, set it and then track the triple we want Modules + // to use. + if (!OverrideTriple.empty()) { + TargetTriple.setTriple(OverrideTriple); + outs() << "Override triple set to '" << OverrideTriple << "'\n"; + } + BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit, Context); if (D.addSources(InputFilenames)) return 1; + + AddToDriver PM(D); + if (StandardCompileOpts) { + createStandardModulePasses(&PM, 3, + /*OptimizeSize=*/ false, + /*UnitAtATime=*/ true, + /*UnrollLoops=*/ true, + /*SimplifyLibCalls=*/ true, + /*HaveExceptions=*/ true, + createFunctionInliningPass()); + } + + if (StandardLinkOpts) + createStandardLTOPasses(&PM, /*Internalize=*/true, + /*RunInliner=*/true, + /*VerifyEach=*/false); + D.addPasses(PassList.begin(), PassList.end()); // Bugpoint has the ability of generating a plethora of core files, so to @@ -87,20 +136,20 @@ int main(int argc, char **argv) { try { return D.run(); } catch (ToolExecutionError &TEE) { - std::cerr << "Tool execution error: " << TEE.what() << '\n'; + errs() << "Tool execution error: " << TEE.what() << '\n'; } catch (const std::string& msg) { - std::cerr << argv[0] << ": " << msg << "\n"; - } catch (const std::bad_alloc &e) { - std::cerr << "Oh no, a bugpoint process ran out of memory!\n" - "To increase the allocation limits for bugpoint child\n" - "processes, use the -mlimit option.\n"; + errs() << argv[0] << ": " << msg << "\n"; + } catch (const std::bad_alloc&) { + errs() << "Oh no, a bugpoint process ran out of memory!\n" + "To increase the allocation limits for bugpoint child\n" + "processes, use the -mlimit option.\n"; } catch (const std::exception &e) { - std::cerr << "Whoops, a std::exception leaked out of bugpoint: " - << e.what() << "\n" - << "This is a bug in bugpoint!\n"; + errs() << "Whoops, a std::exception leaked out of bugpoint: " + << e.what() << "\n" + << "This is a bug in bugpoint!\n"; } catch (...) { - std::cerr << "Whoops, an exception leaked out of bugpoint. " - << "This is a bug in bugpoint!\n"; + errs() << "Whoops, an exception leaked out of bugpoint. " + << "This is a bug in bugpoint!\n"; } return 1; } |