ExecutionDriver.cpp revision a328c51bb99666ee0c045a57ea6d6ce2b0198f9b
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// This file was developed by the LLVM research group and is distributed under 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the University of Illinois Open Source License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains code used to execute the program utilizing one of the 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// various ways of running LLVM bytecode. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//===----------------------------------------------------------------------===// 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "BugDriver.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "llvm/Support/ToolRunner.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/CommandLine.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/Debug.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/FileUtilities.h" 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "llvm/Support/SystemUtils.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace llvm; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OutputType - Allow the user to specify the way code should be run, to test 26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // for miscompilation. 27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // 28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch enum OutputType { 29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AutoPick, RunLLI, RunJIT, RunLLC, RunCBE 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<double> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::init(0.0)); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<double> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"), 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::init(0.0)); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<OutputType> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel(cl::desc("Specify how LLVM code should be executed:"), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::values(clEnumValN(AutoPick, "auto", "Use best guess"), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValN(RunLLI, "run-int", 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Execute with the interpreter"), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValN(RunJIT, "run-jit", "Execute with JIT"), 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValN(RunLLC, "run-llc", "Compile with LLC"), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValEnd), 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::init(AutoPick)); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<bool> 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckProgramExitCode("check-exit-code", 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::desc("Assume nonzero exit code is failure (default on)"), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::init(true)); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<std::string> 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InputFile("input", cl::init("/dev/null"), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::desc("Filename to pipe in as stdin (default: /dev/null)")); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::list<std::string> 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AdditionalSOs("additional-so", 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::desc("Additional shared objects to load " 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "into executing programs")); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<unsigned> 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeoutValue("timeout", cl::init(300), cl::value_desc("seconds"), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::desc("Number of seconds program is allowed to run before it " 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "is killed (default is 300s), 0 disables timeout")); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace llvm { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Anything specified after the --args option are taken as arguments to the 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // program being debugged. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::list<std::string> 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InputArgv("args", cl::Positional, cl::desc("<program arguments>..."), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::ZeroOrMore, cl::PositionalEatsArgs); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::list<std::string> 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."), 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::ZeroOrMore, cl::PositionalEatsArgs); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//===----------------------------------------------------------------------===// 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BugDriver method implementation 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/// initializeExecutionEnvironment - This method is used to set up the 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// environment for executing LLVM programs. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BugDriver::initializeExecutionEnvironment() { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cout << "Initializing execution environment: "; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an instance of the AbstractInterpreter interface as specified on 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the command line 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbe = 0; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string Message; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (InterpreterSel) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutoPick: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel = RunCBE; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Interpreter) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel = RunJIT; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!Interpreter) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel = RunLLC; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Interpreter) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel = RunLLI; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Interpreter) { 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InterpreterSel = AutoPick; 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Message = "Sorry, I can't automatically select an interpreter!\n"; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RunLLI: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RunLLC: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RunJIT: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RunCBE: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << Message; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize auxiliary tools for debugging 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cbe) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbe = AbstractInterpreter::createCBE(getToolName(), Message, &ToolArgv); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cbe) { std::cout << Message << "\nExiting.\n"; exit(1); } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gcc = GCC::create(getToolName(), Message); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there was an error creating the selected interpreter, quit with error. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Interpreter == 0; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// compileProgram - Try to compile the specified module, throwing an exception 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// if an error occurs, or returning normally if not. This is used for code 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// generation crash testing. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BugDriver::compileProgram(Module *M) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Emit the program to a bytecode file... 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys::Path BytecodeFile ("bugpoint-test-program.bc"); 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BytecodeFile.makeUnique(); 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (writeProgramToFile(BytecodeFile.toString(), M)) { 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::cerr << ToolName << ": Error emitting bytecode to file '" 166effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << BytecodeFile << "'!\n"; 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch exit(1); 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Remove the temporary bytecode file when we are done. 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FileRemover BytecodeFileRemover(BytecodeFile); 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Actually compile the program! 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Interpreter->compileProgram(BytecodeFile.toString()); 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// executeProgram - This method runs "Program", capturing the output of the 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// program to a file, returning the filename of the file. A recommended 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// filename may be optionally specified. 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstd::string BugDriver::executeProgram(std::string OutputFile, 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string BytecodeFile, 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string &SharedObj, 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AbstractInterpreter *AI, 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool *ProgramExitedNonzero) { 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (AI == 0) AI = Interpreter; 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch assert(AI && "Interpreter should have been created already!"); 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool CreatedBytecode = false; 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (BytecodeFile.empty()) { 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Emit the program to a bytecode file... 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sys::Path uniqueFilename("bugpoint-test-program.bc"); 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uniqueFilename.makeUnique(); 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BytecodeFile = uniqueFilename.toString(); 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (writeProgramToFile(BytecodeFile, Program)) { 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::cerr << ToolName << ": Error emitting bytecode to file '" 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << BytecodeFile << "'!\n"; 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch exit(1); 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreatedBytecode = true; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the temporary bytecode file when we are done. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys::Path BytecodePath (BytecodeFile); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileRemover BytecodeFileRemover(BytecodePath, CreatedBytecode); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OutputFile.empty()) OutputFile = "bugpoint-execution-output"; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if this is a valid output filename... 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys::Path uniqueFile(OutputFile); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uniqueFile.makeUnique(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutputFile = uniqueFile.toString(); 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Figure out which shared objects to run, if any. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> SharedObjs(AdditionalSOs); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SharedObj.empty()) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SharedObjs.push_back(SharedObj); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Actually execute the program! 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile, 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutputFile, SharedObjs, TimeoutValue); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (RetVal == -1) { 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::cerr << "<timeout>"; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool FirstTimeout = true; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FirstTimeout) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cout << "\n" 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "*** Program execution timed out! This mechanism is designed to handle\n" 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " programs stuck in infinite loops gracefully. The -timeout option\n" 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " can be used to change the timeout threshold or disable it completely\n" 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " (with -timeout=0). This message is only displayed once.\n"; 233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FirstTimeout = false; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ProgramExitedNonzero != 0) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ProgramExitedNonzero = (RetVal != 0); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return the filename we captured the output to. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OutputFile; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/// executeProgramWithCBE - Used to create reference output with the C 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/// backend, if reference output is not provided. 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/// 2472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochstd::string BugDriver::executeProgramWithCBE(std::string OutputFile) { 2482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch bool ProgramExitedNonzero; 2492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch std::string outFN = executeProgram(OutputFile, "", "", 2502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch (AbstractInterpreter*)cbe, 2512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch &ProgramExitedNonzero); 2522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (ProgramExitedNonzero) { 2532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch std::cerr 2542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch << "Warning: While generating reference output, program exited with\n" 2552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch << "non-zero exit code. This will NOT be treated as a failure.\n"; 2562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch CheckProgramExitCode = false; 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return outFN; 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string BugDriver::compileSharedObject(const std::string &BytecodeFile) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Interpreter && "Interpreter should have been created already!"); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys::Path OutputCFile; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using CBE 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbe->OutputC(BytecodeFile, OutputCFile); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 /* This is an alternative, as yet unimplemented */ 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using LLC 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string Message; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LLC *llc = createLLCtool(Message); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (llc->OutputAsm(BytecodeFile, OutputFile)) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << "Could not generate asm code with `llc', exiting.\n"; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string SharedObjectFile; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gcc->MakeSharedObject(OutputCFile.toString(), GCC::CFile, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SharedObjectFile)) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the intermediate C file 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutputCFile.destroyFile(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "./" + SharedObjectFile; 287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/// diffProgram - This method executes the specified module and diffs the output 291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// against the file specified by ReferenceOutputFile. If the output is 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// different, true is returned. 293c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch/// 294c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochbool BugDriver::diffProgram(const std::string &BytecodeFile, 295c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch const std::string &SharedObject, 296c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch bool RemoveBytecode) { 297c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch bool ProgramExitedNonzero; 298c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 299c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Execute the program, generating an output file... 300c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch sys::Path Output (executeProgram("", BytecodeFile, SharedObject, 0, 301c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch &ProgramExitedNonzero)); 302c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 303c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // If we're checking the program exit code, assume anything nonzero is bad. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CheckProgramExitCode && ProgramExitedNonzero) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Output.destroyFile(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RemoveBytecode) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys::Path(BytecodeFile).destroyFile(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string Error; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool FilesDifferent = false; 313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile), 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys::Path(Output.toString()), 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AbsTolerance, RelTolerance, &Error)) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Diff == 2) { 317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::cerr << "While diffing output: " << Error << '\n'; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FilesDifferent = true; 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Remove the generated output. 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Output.destroyFile(); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the bytecode file if we are supposed to. 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (RemoveBytecode) sys::Path(BytecodeFile).destroyFile(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilesDifferent; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BugDriver::isExecutingJIT() { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InterpreterSel == RunJIT; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)