//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===//
-//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
// This file contains code used to execute the program utilizing one of the
//===----------------------------------------------------------------------===//
#include "BugDriver.h"
-#include "llvm/Support/ToolRunner.h"
+#include "ToolRunner.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/SystemUtils.h"
#include <fstream>
+#include <iostream>
+
using namespace llvm;
namespace {
AutoPick, RunLLI, RunJIT, RunLLC, RunCBE
};
+ cl::opt<double>
+ AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"),
+ cl::init(0.0));
+ cl::opt<double>
+ RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"),
+ cl::init(0.0));
+
cl::opt<OutputType>
InterpreterSel(cl::desc("Specify how LLVM code should be executed:"),
cl::values(clEnumValN(AutoPick, "auto", "Use best guess"),
cl::desc("Additional shared objects to load "
"into executing programs"));
- cl::opt<unsigned>
- TimeoutValue("timeout", cl::init(300), cl::value_desc("seconds"),
- cl::desc("Number of seconds program is allowed to run before it "
- "is killed (default is 300s), 0 disables timeout"));
+ cl::list<std::string>
+ AdditionalLinkerArgs("Xlinker",
+ cl::desc("Additional arguments to pass to the linker"));
}
namespace llvm {
}
// Remove the temporary bytecode file when we are done.
- FileRemover BytecodeFileRemover(sys::Path(BytecodeFile), CreatedBytecode);
+ sys::Path BytecodePath (BytecodeFile);
+ FileRemover BytecodeFileRemover(BytecodePath, CreatedBytecode);
if (OutputFile.empty()) OutputFile = "bugpoint-execution-output";
if (!SharedObj.empty())
SharedObjs.push_back(SharedObj);
- // Actually execute the program!
- int RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
- OutputFile, SharedObjs, TimeoutValue);
+
+ // If this is an LLC or CBE run, then the GCC compiler might get run to
+ // compile the program. If so, we should pass the user's -Xlinker options
+ // as the GCCArgs.
+ int RetVal = 0;
+ if (InterpreterSel == RunLLC || InterpreterSel == RunCBE)
+ RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
+ OutputFile, AdditionalLinkerArgs, SharedObjs,
+ Timeout);
+ else
+ RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile,
+ OutputFile, std::vector<std::string>(),
+ SharedObjs, Timeout);
if (RetVal == -1) {
std::cerr << "<timeout>";
#endif
std::string SharedObjectFile;
- if (gcc->MakeSharedObject(OutputCFile.toString(), GCC::CFile,
- SharedObjectFile))
+ if (gcc->MakeSharedObject(OutputCFile.toString(), GCC::CFile,
+ SharedObjectFile, AdditionalLinkerArgs))
exit(1);
// Remove the intermediate C file
- OutputCFile.destroyFile();
+ OutputCFile.eraseFromDisk();
return "./" + SharedObjectFile;
}
bool ProgramExitedNonzero;
// Execute the program, generating an output file...
- sys::Path Output (executeProgram("", BytecodeFile, SharedObject, 0,
+ sys::Path Output(executeProgram("", BytecodeFile, SharedObject, 0,
&ProgramExitedNonzero));
// If we're checking the program exit code, assume anything nonzero is bad.
if (CheckProgramExitCode && ProgramExitedNonzero) {
- Output.destroyFile();
- if (RemoveBytecode)
- sys::Path(BytecodeFile).destroyFile();
+ Output.eraseFromDisk();
+ if (RemoveBytecode)
+ sys::Path(BytecodeFile).eraseFromDisk();
return true;
}
std::string Error;
bool FilesDifferent = false;
- if (DiffFiles(ReferenceOutputFile, Output.toString(), &Error)) {
- if (!Error.empty()) {
+ if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile),
+ sys::Path(Output.toString()),
+ AbsTolerance, RelTolerance, &Error)) {
+ if (Diff == 2) {
std::cerr << "While diffing output: " << Error << '\n';
exit(1);
}
FilesDifferent = true;
}
-
+
// Remove the generated output.
- Output.destroyFile();
+ Output.eraseFromDisk();
// Remove the bytecode file if we are supposed to.
- if (RemoveBytecode) sys::Path(BytecodeFile).destroyFile();
+ if (RemoveBytecode)
+ sys::Path(BytecodeFile).eraseFromDisk();
return FilesDifferent;
}