diff options
author | Shih-wei Liao <sliao@google.com> | 2010-04-28 01:47:00 -0700 |
---|---|---|
committer | Shih-wei Liao <sliao@google.com> | 2010-04-28 01:47:00 -0700 |
commit | 7abe37e4aee38cc79d91dd069a37d7e91d5bef53 (patch) | |
tree | c13b26fc3d8909240f981988535c0b82dd9bf37c /tools | |
parent | 6037a7c3c97b651dd70e48ebe5453134713971ed (diff) | |
download | external_llvm-7abe37e4aee38cc79d91dd069a37d7e91d5bef53.tar.gz external_llvm-7abe37e4aee38cc79d91dd069a37d7e91d5bef53.tar.bz2 external_llvm-7abe37e4aee38cc79d91dd069a37d7e91d5bef53.zip |
Sync upstream to r102410.
Re-turn on sdk.
Change-Id: I91a890863989a67243b4d2dfd1ae09b843ebaeaf
Diffstat (limited to 'tools')
49 files changed, 1457 insertions, 884 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 8b5d77e2c4..b9c77b1c8a 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory(llvm-extract) add_subdirectory(bugpoint) add_subdirectory(llvm-bcanalyzer) add_subdirectory(llvm-stub) +add_subdirectory(edis) add_subdirectory(llvmc) if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt ) diff --git a/tools/Makefile b/tools/Makefile index 86ba72ddac..9d2e576dfb 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -15,14 +15,16 @@ OPTIONAL_PARALLEL_DIRS := clang # NOTE: The tools are organized into five groups of four consisting of one # large and three small executables. This is done to minimize memory load # in parallel builds. Please retain this ordering. -DIRS := llvm-config + +# libEnhancedDisassembly must be built ahead of llvm-mc +# because llvm-mc links against libEnhancedDisassembly +DIRS := llvm-config edis llvm-mc PARALLEL_DIRS := opt llvm-as llvm-dis \ llc llvm-ranlib llvm-ar llvm-nm \ llvm-ld llvm-prof llvm-link \ lli llvm-extract \ bugpoint llvm-bcanalyzer llvm-stub \ - llvm-mc llvmc - + llvmc # Let users override the set of tools to build from the command line. ifdef ONLY_TOOLS @@ -37,21 +39,18 @@ include $(LEVEL)/Makefile.config ifeq ($(ENABLE_PIC),1) # No support for dynamic libraries on windows targets. ifneq ($(TARGET_OS), $(filter $(TARGET_OS), Cygwin MingW)) - PARALLEL_DIRS += edis - # gold only builds if binutils is around. It requires "lto" to build before # it so it is added to DIRS. ifdef BINUTILS_INCDIR - PARALLEL_DIRS += gold - DIRS += lto + DIRS += lto gold else PARALLEL_DIRS += lto endif endif endif -# Only build edis if X86 target support is enabled. -ifeq ($(filter $(TARGETS_TO_BUILD), X86),) +# Don't build edis if we explicitly disabled it. +ifeq ($(DISABLE_EDIS),1) PARALLEL_DIRS := $(filter-out edis, $(PARALLEL_DIRS)) endif diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index abf5d8ef72..45a0d4dd17 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -21,7 +21,6 @@ #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 "llvm/System/Host.h" @@ -68,12 +67,16 @@ std::string llvm::getPassesString(const std::vector<const PassInfo*> &Passes) { } BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs, - unsigned timeout, unsigned memlimit, + unsigned timeout, unsigned memlimit, bool use_valgrind, LLVMContext& ctxt) : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), Program(0), Interpreter(0), SafeInterpreter(0), gcc(0), run_as_child(as_child), run_find_bugs(find_bugs), Timeout(timeout), - MemoryLimit(memlimit) {} + MemoryLimit(memlimit), UseValgrind(use_valgrind) {} + +BugDriver::~BugDriver() { + delete Program; +} /// ParseInputFile - Given a bitcode or assembly input filename, parse and @@ -112,30 +115,25 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) { assert(Program == 0 && "Cannot call addSources multiple times!"); assert(!Filenames.empty() && "Must specify at least on input filename!"); - try { - // Load the first input file. - Program = ParseInputFile(Filenames[0], Context); - if (Program == 0) return true; + // Load the first input file. + Program = ParseInputFile(Filenames[0], Context); + if (Program == 0) return true; + if (!run_as_child) + 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) - 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) - outs() << "Linking in input file: '" << Filenames[i] << "'\n"; - std::string ErrorMessage; - if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) { - errs() << ToolName << ": error linking in '" << Filenames[i] << "': " - << ErrorMessage << '\n'; - return true; - } + outs() << "Linking in input file: '" << Filenames[i] << "'\n"; + std::string ErrorMessage; + if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) { + errs() << ToolName << ": error linking in '" << Filenames[i] << "': " + << ErrorMessage << '\n'; + return true; } - } catch (const std::string &Error) { - errs() << ToolName << ": error reading input '" << Error << "'\n"; - return true; } if (!run_as_child) @@ -150,7 +148,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) { /// run - The top level method that is invoked after all of the instance /// variables are set up from command line arguments. /// -bool BugDriver::run() { +bool BugDriver::run(std::string &ErrMsg) { // The first thing to do is determine if we're running as a child. If we are, // then what to do is very narrow. This form of invocation is only called // from the runPasses method to actually run those passes in a child process. @@ -162,7 +160,7 @@ bool BugDriver::run() { if (run_find_bugs) { // Rearrange the passes and apply them to the program. Repeat this process // until the user kills the program or we find a bug. - return runManyPasses(PassesToRun); + return runManyPasses(PassesToRun, ErrMsg); } // If we're not running as a child, the first thing that we must do is @@ -183,14 +181,13 @@ bool BugDriver::run() { // Test to see if we have a code generator crash. outs() << "Running the code generator to test for a crash: "; - try { - compileProgram(Program); - outs() << '\n'; - } catch (ToolExecutionError &TEE) { - outs() << TEE.what(); - return debugCodeGeneratorCrash(); + std::string Error; + compileProgram(Program, &Error); + if (!Error.empty()) { + outs() << Error; + return debugCodeGeneratorCrash(ErrMsg); } - + outs() << '\n'; // Run the raw input to see where we are coming from. If a reference output // was specified, make sure that the raw output matches it. If not, it's a @@ -199,8 +196,8 @@ bool BugDriver::run() { bool CreatedOutput = false; if (ReferenceOutputFile.empty()) { outs() << "Generating reference output from raw program: "; - if(!createReferenceFile(Program)){ - return debugCodeGeneratorCrash(); + if (!createReferenceFile(Program)) { + return debugCodeGeneratorCrash(ErrMsg); } CreatedOutput = true; } @@ -214,24 +211,29 @@ bool BugDriver::run() { // matches, then we assume there is a miscompilation bug and try to // diagnose it. outs() << "*** Checking the code generator...\n"; - try { - if (!diffProgram()) { - outs() << "\n*** Output matches: Debugging miscompilation!\n"; - return debugMiscompilation(); + bool Diff = diffProgram("", "", false, &Error); + if (!Error.empty()) { + errs() << Error; + return debugCodeGeneratorCrash(ErrMsg); + } + if (!Diff) { + outs() << "\n*** Output matches: Debugging miscompilation!\n"; + debugMiscompilation(&Error); + if (!Error.empty()) { + errs() << Error; + return debugCodeGeneratorCrash(ErrMsg); } - } catch (ToolExecutionError &TEE) { - errs() << TEE.what(); - return debugCodeGeneratorCrash(); + return false; } outs() << "\n*** Input program does not match reference diff!\n"; outs() << "Debugging code generator problem!\n"; - try { - return debugCodeGenerator(); - } catch (ToolExecutionError &TEE) { - errs() << TEE.what(); - return debugCodeGeneratorCrash(); + bool Failure = debugCodeGenerator(&Error); + if (!Error.empty()) { + errs() << Error; + return debugCodeGeneratorCrash(ErrMsg); } + return Failure; } void llvm::PrintFunctionList(const std::vector<Function*> &Funcs) { diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index db35c851d9..e5b7373f04 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -55,6 +55,7 @@ class BugDriver { bool run_find_bugs; unsigned Timeout; unsigned MemoryLimit; + bool UseValgrind; // FIXME: sort out public/private distinctions... friend class ReducePassList; @@ -62,7 +63,9 @@ class BugDriver { public: BugDriver(const char *toolname, bool as_child, bool find_bugs, - unsigned timeout, unsigned memlimit, LLVMContext& ctxt); + unsigned timeout, unsigned memlimit, bool use_valgrind, + LLVMContext& ctxt); + ~BugDriver(); const char *getToolName() const { return ToolName; } @@ -85,7 +88,7 @@ public: /// variables are set up from command line arguments. The \p as_child argument /// indicates whether the driver is to run in parent mode or child mode. /// - bool run(); + bool run(std::string &ErrMsg); /// debugOptimizerCrash - This method is called when some optimizer pass /// crashes on input. It attempts to prune down the testcase to something @@ -96,12 +99,12 @@ public: /// debugCodeGeneratorCrash - This method is called when the code generator /// crashes on an input. It attempts to reduce the input as much as possible /// while still causing the code generator to crash. - bool debugCodeGeneratorCrash(); + bool debugCodeGeneratorCrash(std::string &Error); /// debugMiscompilation - This method is used when the passes selected are not /// crashing, but the generated output is semantically different from the /// input. - bool debugMiscompilation(); + void debugMiscompilation(std::string *Error); /// debugPassMiscompilation - This method is called when the specified pass /// miscompiles Program as input. It tries to reduce the testcase to @@ -115,12 +118,13 @@ public: /// compileSharedObject - This method creates a SharedObject from a given /// BitcodeFile for debugging a code generator. /// - std::string compileSharedObject(const std::string &BitcodeFile); + std::string compileSharedObject(const std::string &BitcodeFile, + std::string &Error); /// debugCodeGenerator - This method narrows down a module to a function or /// set of functions, using the CBE as a ``safe'' code generator for other /// functions that are not under consideration. - bool debugCodeGenerator(); + bool debugCodeGenerator(std::string *Error); /// isExecutingJIT - Returns true if bugpoint is currently testing the JIT /// @@ -161,28 +165,27 @@ public: /// the specified one as the current program. void setNewProgram(Module *M); - /// compileProgram - Try to compile the specified module, throwing an - /// exception if an error occurs, or returning normally if not. This is used - /// for code generation crash testing. + /// compileProgram - Try to compile the specified module, returning false and + /// setting Error if an error occurs. This is used for code generation + /// crash testing. /// - void compileProgram(Module *M); + void compileProgram(Module *M, std::string *Error); /// executeProgram - This method runs "Program", capturing the output of the - /// program to a file, returning the filename of the file. A recommended - /// filename may be optionally specified. If there is a problem with the code - /// generator (e.g., llc crashes), this will throw an exception. + /// program to a file. A recommended filename may be optionally specified. /// - std::string executeProgram(std::string RequestedOutputFilename = "", - std::string Bitcode = "", - const std::string &SharedObjects = "", - AbstractInterpreter *AI = 0, - bool *ProgramExitedNonzero = 0); + std::string executeProgram(std::string OutputFilename, + std::string Bitcode, + const std::string &SharedObjects, + AbstractInterpreter *AI, + std::string *Error); /// executeProgramSafely - Used to create reference output with the "safe" /// backend, if reference output is not provided. If there is a problem with - /// the code generator (e.g., llc crashes), this will throw an exception. + /// the code generator (e.g., llc crashes), this will return false and set + /// Error. /// - std::string executeProgramSafely(std::string OutputFile = ""); + std::string executeProgramSafely(std::string OutputFile, std::string *Error); /// createReferenceFile - calls compileProgram and then records the output /// into ReferenceOutputFile. Returns true if reference file created, false @@ -194,13 +197,14 @@ public: /// diffProgram - This method executes the specified module and diffs the /// output against the file specified by ReferenceOutputFile. If the output - /// is different, true is returned. If there is a problem with the code - /// generator (e.g., llc crashes), this will throw an exception. + /// is different, 1 is returned. If there is a problem with the code + /// generator (e.g., llc crashes), this will return -1 and set Error. /// bool diffProgram(const std::string &BitcodeFile = "", const std::string &SharedObj = "", - bool RemoveBitcode = false); - + bool RemoveBitcode = false, + std::string *Error = 0); + /// EmitProgressBitcode - This function is used to output the current Program /// to a file named "bugpoint-ID.bc". /// @@ -264,7 +268,8 @@ public: /// If the passes did not compile correctly, output the command required to /// recreate the failure. This returns true if a compiler error is found. /// - bool runManyPasses(const std::vector<const PassInfo*> &AllPasses); + bool runManyPasses(const std::vector<const PassInfo*> &AllPasses, + std::string &ErrMsg); /// writeProgramToFile - This writes the current "Program" to the named /// bitcode file. If an error occurs, true is returned. diff --git a/tools/bugpoint/CMakeLists.txt b/tools/bugpoint/CMakeLists.txt index 90f24bac58..34b759fd87 100644 --- a/tools/bugpoint/CMakeLists.txt +++ b/tools/bugpoint/CMakeLists.txt @@ -1,6 +1,5 @@ set(LLVM_LINK_COMPONENTS asmparser instrumentation scalaropts ipo linker bitreader bitwriter) -set(LLVM_REQUIRES_EH 1) add_llvm_tool(bugpoint BugDriver.cpp diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index b51bdb4509..46b33d2a72 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -53,13 +53,15 @@ namespace llvm { // passes. If we return true, we update the current module of bugpoint. // virtual TestResult doTest(std::vector<const PassInfo*> &Removed, - std::vector<const PassInfo*> &Kept); + std::vector<const PassInfo*> &Kept, + std::string &Error); }; } ReducePassList::TestResult ReducePassList::doTest(std::vector<const PassInfo*> &Prefix, - std::vector<const PassInfo*> &Suffix) { + std::vector<const PassInfo*> &Suffix, + std::string &Error) { sys::Path PrefixOutput; Module *OrigProgram = 0; if (!Prefix.empty()) { @@ -107,27 +109,26 @@ namespace { bool (*TestFn)(BugDriver &, Module *); public: ReduceCrashingGlobalVariables(BugDriver &bd, - bool (*testFn)(BugDriver&, Module*)) + bool (*testFn)(BugDriver &, Module *)) : BD(bd), TestFn(testFn) {} - virtual TestResult doTest(std::vector<GlobalVariable*>& Prefix, - std::vector<GlobalVariable*>& Kept) { + virtual TestResult doTest(std::vector<GlobalVariable*> &Prefix, + std::vector<GlobalVariable*> &Kept, + std::string &Error) { if (!Kept.empty() && TestGlobalVariables(Kept)) return KeepSuffix; - if (!Prefix.empty() && TestGlobalVariables(Prefix)) return KeepPrefix; - return NoFailure; } - bool TestGlobalVariables(std::vector<GlobalVariable*>& GVs); + bool TestGlobalVariables(std::vector<GlobalVariable*> &GVs); }; } bool ReduceCrashingGlobalVariables::TestGlobalVariables( - std::vector<GlobalVariable*>& GVs) { + std::vector<GlobalVariable*> &GVs) { // Clone the program to try hacking it apart... DenseMap<const Value*, Value*> ValueMap; Module *M = CloneModule(BD.getProgram(), ValueMap); @@ -182,7 +183,8 @@ namespace llvm { : BD(bd), TestFn(testFn) {} virtual TestResult doTest(std::vector<Function*> &Prefix, - std::vector<Function*> &Kept) { + std::vector<Function*> &Kept, + std::string &Error) { if (!Kept.empty() && TestFuncs(Kept)) return KeepSuffix; if (!Prefix.empty() && TestFuncs(Prefix)) @@ -253,7 +255,8 @@ namespace { : BD(bd), TestFn(testFn) {} virtual TestResult doTest(std::vector<const BasicBlock*> &Prefix, - std::vector<const BasicBlock*> &Kept) { + std::vector<const BasicBlock*> &Kept, + std::string &Error) { if (!Kept.empty() && TestBlocks(Kept)) return KeepSuffix; if (!Prefix.empty() && TestBlocks(Prefix)) @@ -355,7 +358,8 @@ namespace { : BD(bd), TestFn(testFn) {} virtual TestResult doTest(std::vector<const Instruction*> &Prefix, - std::vector<const Instruction*> &Kept) { + std::vector<const Instruction*> &Kept, + std::string &Error) { if (!Kept.empty() && TestInsts(Kept)) return KeepSuffix; if (!Prefix.empty() && TestInsts(Prefix)) @@ -421,7 +425,8 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> /// DebugACrash - Given a predicate that determines whether a component crashes /// on a program, try to destructively reduce the program while still keeping /// the predicate true. -static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { +static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *), + std::string &Error) { // See if we can get away with nuking some of the global variable initializers // in the program... if (!NoGlobalRM && @@ -464,7 +469,9 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { << "variables in the testcase\n"; unsigned OldSize = GVs.size(); - ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs); + ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs, Error); + if (!Error.empty()) + return true; if (GVs.size() < OldSize) BD.EmitProgressBitcode("reduced-global-variables"); @@ -485,7 +492,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { "in the testcase\n"; unsigned OldSize = Functions.size(); - ReduceCrashingFunctions(BD, TestFn).reduceList(Functions); + ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error); if (Functions.size() < OldSize) BD.EmitProgressBitcode("reduced-function"); @@ -503,7 +510,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI) Blocks.push_back(FI); unsigned OldSize = Blocks.size(); - ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks); + ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error); if (Blocks.size() < OldSize) BD.EmitProgressBitcode("reduced-blocks"); } @@ -521,7 +528,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { if (!isa<TerminatorInst>(I)) Insts.push_back(I); - ReduceCrashingInstructions(BD, TestFn).reduceList(Insts); + ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error); } // FIXME: This should use the list reducer to converge faster by deleting @@ -614,9 +621,11 @@ static bool TestForOptimizerCrash(BugDriver &BD, Module *M) { bool BugDriver::debugOptimizerCrash(const std::string &ID) { outs() << "\n*** Debugging optimizer crash!\n"; + std::string Error; // Reduce the list of passes which causes the optimizer to crash... if (!BugpointIsInterrupted) - ReducePassList(*this).reduceList(PassesToRun); + ReducePassList(*this).reduceList(PassesToRun, Error); + assert(Error.empty()); outs() << "\n*** Found crashing pass" << (PassesToRun.size() == 1 ? ": " : "es: ") @@ -624,25 +633,27 @@ bool BugDriver::debugOptimizerCrash(const std::string &ID) { EmitProgressBitcode(ID); - return DebugACrash(*this, TestForOptimizerCrash); + bool Success = DebugACrash(*this, TestForOptimizerCrash, Error); + assert(Error.empty()); + return Success; } static bool TestForCodeGenCrash(BugDriver &BD, Module *M) { - try { - BD.compileProgram(M); - errs() << '\n'; - return false; - } catch (ToolExecutionError &) { + std::string Error; + BD.compileProgram(M, &Error); + if (!Error.empty()) { errs() << "<crash>\n"; return true; // Tool is still crashing. } + errs() << '\n'; + return false; } /// debugCodeGeneratorCrash - This method is called when the code generator /// 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() { +bool BugDriver::debugCodeGeneratorCrash(std::string &Error) { errs() << "*** Debugging code generator crash!\n"; - return DebugACrash(*this, TestForCodeGenCrash); + return DebugACrash(*this, TestForCodeGenCrash, Error); } diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index feda331177..9eb3314969 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -28,7 +28,7 @@ namespace { // for miscompilation. // enum OutputType { - AutoPick, RunLLI, RunJIT, RunLLC, RunCBE, CBE_bug, LLC_Safe, Custom + AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe,Custom }; cl::opt<double> @@ -45,6 +45,8 @@ namespace { "Execute with the interpreter"), clEnumValN(RunJIT, "run-jit", "Execute with JIT"), clEnumValN(RunLLC, "run-llc", "Compile with LLC"), + clEnumValN(RunLLCIA, "run-llc-ia", + "Compile with LLC with integrated assembler"), clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), clEnumValN(CBE_bug,"cbe-bug", "Find CBE bugs"), clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"), @@ -168,9 +170,11 @@ bool BugDriver::initializeExecutionEnvironment() { &ToolArgv); break; case RunLLC: + case RunLLCIA: case LLC_Safe: Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - &ToolArgv, &GCCToolArgv); + &ToolArgv, &GCCToolArgv, + InterpreterSel == RunLLCIA); break; case RunJIT: Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, @@ -244,10 +248,12 @@ bool BugDriver::initializeExecutionEnvironment() { } break; case RunLLC: + case RunLLCIA: SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, &SafeToolArgs, - &GCCToolArgv); + &GCCToolArgv, + SafeInterpreterSel == RunLLCIA); break; case RunCBE: SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, @@ -272,15 +278,15 @@ bool BugDriver::initializeExecutionEnvironment() { return Interpreter == 0; } -/// compileProgram - Try to compile the specified module, throwing an exception -/// if an error occurs, or returning normally if not. This is used for code -/// generation crash testing. +/// compileProgram - Try to compile the specified module, returning false and +/// setting Error if an error occurs. This is used for code generation +/// crash testing. /// -void BugDriver::compileProgram(Module *M) { +void BugDriver::compileProgram(Module *M, std::string *Error) { // Emit the program to a bitcode file... sys::Path BitcodeFile (OutputPrefix + "-test-program.bc"); std::string ErrMsg; - if (BitcodeFile.makeUnique(true,&ErrMsg)) { + if (BitcodeFile.makeUnique(true, &ErrMsg)) { errs() << ToolName << ": Error making unique filename: " << ErrMsg << "\n"; exit(1); @@ -291,11 +297,11 @@ void BugDriver::compileProgram(Module *M) { exit(1); } - // Remove the temporary bitcode file when we are done. + // Remove the temporary bitcode file when we are done. FileRemover BitcodeFileRemover(BitcodeFile, !SaveTemps); // Actually compile the program! - Interpreter->compileProgram(BitcodeFile.str()); + Interpreter->compileProgram(BitcodeFile.str(), Error); } @@ -307,7 +313,7 @@ std::string BugDriver::executeProgram(std::string OutputFile, std::string BitcodeFile, const std::string &SharedObj, AbstractInterpreter *AI, - bool *ProgramExitedNonzero) { + std::string *Error) { if (AI == 0) AI = Interpreter; assert(AI && "Interpreter should have been created already!"); bool CreatedBitcode = false; @@ -331,7 +337,7 @@ std::string BugDriver::executeProgram(std::string OutputFile, } // Remove the temporary bitcode file when we are done. - sys::Path BitcodePath (BitcodeFile); + sys::Path BitcodePath(BitcodeFile); FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps); if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output"; @@ -350,9 +356,11 @@ std::string BugDriver::executeProgram(std::string OutputFile, if (!SharedObj.empty()) SharedObjs.push_back(SharedObj); - int RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, - OutputFile, AdditionalLinkerArgs, SharedObjs, + int RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, OutputFile, + Error, AdditionalLinkerArgs, SharedObjs, Timeout, MemoryLimit); + if (!Error->empty()) + return OutputFile; if (RetVal == -1) { errs() << "<timeout>"; @@ -373,9 +381,6 @@ std::string BugDriver::executeProgram(std::string OutputFile, outFile.close(); } - if (ProgramExitedNonzero != 0) - *ProgramExitedNonzero = (RetVal != 0); - // Return the filename we captured the output to. return OutputFile; } @@ -383,23 +388,28 @@ std::string BugDriver::executeProgram(std::string OutputFile, /// executeProgramSafely - Used to create reference output with the "safe" /// backend, if reference output is not provided. /// -std::string BugDriver::executeProgramSafely(std::string OutputFile) { - bool ProgramExitedNonzero; - std::string outFN = executeProgram(OutputFile, "", "", SafeInterpreter, - &ProgramExitedNonzero); - return outFN; +std::string BugDriver::executeProgramSafely(std::string OutputFile, + std::string *Error) { + return executeProgram(OutputFile, "", "", SafeInterpreter, Error); } -std::string BugDriver::compileSharedObject(const std::string &BitcodeFile) { +std::string BugDriver::compileSharedObject(const std::string &BitcodeFile, + std::string &Error) { assert(Interpreter && "Interpreter should have been created already!"); sys::Path OutputFile; // Using the known-good backend. - GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile); + GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile, + Error); + if (!Error.empty()) + return ""; std::string SharedObjectFile; - if (gcc->MakeSharedObject(OutputFile.str(), FT, - SharedObjectFile, AdditionalLinkerArgs)) + bool Failure = gcc->MakeSharedObject(OutputFile.str(), FT, SharedObjectFile, + AdditionalLinkerArgs, Error); + if (!Error.empty()) + return ""; + if (Failure) exit(1); // Remove the intermediate C file @@ -414,16 +424,14 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile) { /// this function. /// bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) { - try { - compileProgram(Program); - } catch (ToolExecutionError &) { + std::string Error; + compileProgram(Program, &Error); + if (!Error.empty()) return false; - } - try { - ReferenceOutputFile = executeProgramSafely(Filename); - outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; - } catch (ToolExecutionError &TEE) { - errs() << TEE.what(); + + ReferenceOutputFile = executeProgramSafely(Filename, &Error); + if (!Error.empty()) { + errs() << Error; if (Interpreter != SafeInterpreter) { errs() << "*** There is a bug running the \"safe\" backend. Either" << " debug it (for example with the -run-cbe bugpoint option," @@ -432,22 +440,23 @@ bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) { } return false; } + outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; return true; } /// diffProgram - This method executes the specified module and diffs the /// output against the file specified by ReferenceOutputFile. If the output -/// is different, true is returned. If there is a problem with the code -/// generator (e.g., llc crashes), this will throw an exception. +/// is different, 1 is returned. If there is a problem with the code +/// generator (e.g., llc crashes), this will return -1 and set Error. /// bool BugDriver::diffProgram(const std::string &BitcodeFile, const std::string &SharedObject, - bool RemoveBitcode) { - bool ProgramExitedNonzero; - + bool RemoveBitcode, + std::string *ErrMsg) { // Execute the program, generating an output file... - sys::Path Output(executeProgram("", BitcodeFile, SharedObject, 0, - &ProgramExitedNonzero)); + sys::Path Output(executeProgram("", BitcodeFile, SharedObject, 0, ErrMsg)); + if (!ErrMsg->empty()) + return false; std::string Error; bool FilesDifferent = false; diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp index 2c11d29f60..224c71747a 100644 --- a/tools/bugpoint/FindBugs.cpp +++ b/tools/bugpoint/FindBugs.cpp @@ -29,7 +29,8 @@ using namespace llvm; /// If the passes did not compile correctly, output the command required to /// recreate the failure. This returns true if a compiler error is found. /// -bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) { +bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses, + std::string &ErrMsg) { setPassesToRun(AllPasses); outs() << "Starting bug finding procedure...\n\n"; @@ -57,7 +58,7 @@ bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) { // outs() << "Running selected passes on program to test for crash: "; for(int i = 0, e = PassesToRun.size(); i != e; i++) { - outs() << "-" << PassesToRun[i]->getPassArgument( )<< " "; + outs() << "-" << PassesToRun[i]->getPassArgument() << " "; } std::string Filename; @@ -74,33 +75,33 @@ bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) { // Step 3: Compile the optimized code. // outs() << "Running the code generator to test for a crash: "; - try { - compileProgram(Program); - outs() << '\n'; - } catch (ToolExecutionError &TEE) { + std::string Error; + compileProgram(Program, &Error); + if (!Error.empty()) { outs() << "\n*** compileProgram threw an exception: "; - outs() << TEE.what(); - return debugCodeGeneratorCrash(); + outs() << Error; + return debugCodeGeneratorCrash(ErrMsg); } + outs() << '\n'; // // Step 4: Run the program and compare its output to the reference // output (created above). // outs() << "*** Checking if passes caused miscompliation:\n"; - try { - if (diffProgram(Filename, "", false)) { - outs() << "\n*** diffProgram returned true!\n"; - debugMiscompilation(); + bool Diff = diffProgram(Filename, "", false, &Error); + if (Error.empty() && Diff) { + outs() << "\n*** diffProgram returned true!\n"; + debugMiscompilation(&Error); + if (Error.empty()) return true; - } else { - outs() << "\n*** diff'd output matches!\n"; - } - } catch (ToolExecutionError &TEE) { - errs() << TEE.what(); - debugCodeGeneratorCrash(); + } + if (!Error.empty()) { + errs() << Error; + debugCodeGeneratorCrash(ErrMsg); return true; } + outs() << "\n*** diff'd output matches!\n"; sys::Path(Filename).eraseFromDisk(); diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h index 8036d1f544..5e9cff0efa 100644 --- a/tools/bugpoint/ListReducer.h +++ b/tools/bugpoint/ListReducer.h @@ -16,6 +16,7 @@ #define BUGPOINT_LIST_REDUCER_H #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" #include <vector> #include <cstdlib> #include <algorithm> @@ -29,7 +30,8 @@ struct ListReducer { enum TestResult { NoFailure, // No failure of the predicate was detected KeepSuffix, // The suffix alone satisfies the predicate - KeepPrefix // The prefix alone satisfies the predicate + KeepPrefix, // The prefix alone satisfies the predicate + InternalError // Encountered an error trying to run the predicate }; virtual ~ListReducer() {} @@ -40,16 +42,17 @@ struct ListReducer { // the prefix anyway, it can. // virtual TestResult doTest(std::vector<ElTy> &Prefix, - std::vector<ElTy> &Kept) = 0; + std::vector<ElTy> &Kept, + std::string &Error) = 0; // reduceList - This function attempts to reduce the length of the specified // list while still maintaining the "test" property. This is the core of the // "work" that bugpoint does. // - bool reduceList(std::vector<ElTy> &TheList) { + bool reduceList(std::vector<ElTy> &TheList, std::string &Error) { std::vector<ElTy> empty; std::srand(0x6e5ea738); // Seed the random number generator - switch (doTest(TheList, empty)) { + switch (doTest(TheList, empty, Error)) { case KeepPrefix: if (TheList.size() == 1) // we are done, it's the base case and it fails return true; @@ -58,11 +61,15 @@ struct ListReducer { case KeepSuffix: // cannot be reached! - errs() << "bugpoint ListReducer internal error: selected empty set.\n"; - abort(); + llvm_unreachable("bugpoint ListReducer internal error: " + "selected empty set."); case NoFailure: return false; // there is no failure with the full set of passes/funcs! + + case InternalError: + assert(!Error.empty()); + return true; } // Maximal number of allowed splitting iterations, @@ -90,7 +97,7 @@ Backjump: std::random_shuffle(ShuffledList.begin(), ShuffledList.end()); errs() << "\n\n*** Testing shuffled set...\n\n"; // Check that random shuffle doesn't loose the bug - if (doTest(ShuffledList, empty) == KeepPrefix) { + if (doTest(ShuffledList, empty, Error) == KeepPrefix) { // If the bug is still here, use the shuffled list. TheList.swap(ShuffledList); MidTop = TheList.size(); @@ -109,7 +116,7 @@ Backjump: std::vector<ElTy> Prefix(TheList.begin(), TheList.begin()+Mid); std::vector<ElTy> Suffix(TheList.begin()+Mid, TheList.end()); - switch (doTest(Prefix, Suffix)) { + switch (doTest(Prefix, Suffix, Error)) { case KeepSuffix: // The property still holds. We can just drop the prefix elements, and // shorten the list to the "kept" elements. @@ -133,7 +140,10 @@ Backjump: MidTop = Mid; NumOfIterationsWithoutProgress++; break; + case InternalError: + return true; // Error was set by doTest. } + assert(Error.empty() && "doTest did not return InternalError for error"); } // Probability of backjumping from the trimming loop back to the binary @@ -167,12 +177,14 @@ Backjump: std::vector<ElTy> TestList(TheList); TestList.erase(TestList.begin()+i); - if (doTest(EmptyList, TestList) == KeepSuffix) { + if (doTest(EmptyList, TestList, Error) == KeepSuffix) { // We can trim down the list! TheList.swap(TestList); --i; // Don't skip an element of the list Changed = true; } + if (!Error.empty()) + return true; } // This can take a long time if left uncontrolled. For now, don't // iterate. diff --git a/tools/bugpoint/Makefile b/tools/bugpoint/Makefile index b821b6c7bd..5d287ef188 100644 --- a/tools/bugpoint/Makefile +++ b/tools/bugpoint/Makefile @@ -12,6 +12,5 @@ TOOLNAME = bugpoint LINK_COMPONENTS := asmparser instrumentation scalaropts ipo \ linker bitreader bitwriter -REQUIRES_EH := 1 include $(LEVEL)/Makefile.common diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index c2b002f9dd..6af1f6a57e 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -49,7 +49,8 @@ namespace { ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {} virtual TestResult doTest(std::vector<const PassInfo*> &Prefix, - std::vector<const PassInfo*> &Suffix); + std::vector<const PassInfo*> &Suffix, + std::string &Error); }; } @@ -58,7 +59,8 @@ namespace { /// ReduceMiscompilingPasses::TestResult ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, - std::vector<const PassInfo*> &Suffix) { + std::vector<const PassInfo*> &Suffix, + std::string &Error) { // First, run the program with just the Suffix passes. If it is still broken // with JUST the kept passes, discard the prefix passes. outs() << "Checking to see if '" << getPassesString(Suffix) @@ -74,7 +76,11 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, } // Check to see if the finished program matches the reference output... - if (BD.diffProgram(BitcodeResult, "", true /*delete bitcode*/)) { + bool Diff = BD.diffProgram(BitcodeResult, "", true /*delete bitcode*/, + &Error); + if (!Error.empty()) + return InternalError; + if (Diff) { outs() << " nope.\n"; if (Suffix.empty()) { errs() << BD.getToolName() << ": I'm confused: the test fails when " @@ -107,7 +113,10 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, } // If the prefix maintains the predicate by itself, only keep the prefix! - if (BD.diffProgram(BitcodeResult)) { + Diff = BD.diffProgram(BitcodeResult, "", false, &Error); + if (!Error.empty()) + return InternalError; + if (Diff) { outs() << " nope.\n"; sys::Path(BitcodeResult).eraseFromDisk(); return KeepPrefix; @@ -143,7 +152,10 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, } // Run the result... - if (BD.diffProgram(BitcodeResult, "", true/*delete bitcode*/)) { + Diff = BD.diffProgram(BitcodeResult, "", true /*delete bitcode*/, &Error); + if (!Error.empty()) + return InternalError; + if (Diff) { outs() << " nope.\n"; delete OriginalInput; // We pruned down the original input... return KeepSuffix; @@ -158,22 +170,34 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, namespace { class ReduceMiscompilingFunctions : public ListReducer<Function*> { BugDriver &BD; - bool (*TestFn)(BugDriver &, Module *, Module *); + bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); public: ReduceMiscompilingFunctions(BugDriver &bd, - bool (*F)(BugDriver &, Module *, Module *)) + bool (*F)(BugDriver &, Module *, Module *, + std::string &)) : BD(bd), TestFn(F) {} virtual TestResult doTest(std::vector<Function*> &Prefix, - std::vector<Function*> &Suffix) { - if (!Suffix.empty() && TestFuncs(Suffix)) - return KeepSuffix; - if (!Prefix.empty() && TestFuncs(Prefix)) - return KeepPrefix; + std::vector<Function*> &Suffix, + std::string &Error) { + if (!Suffix.empty()) { + bool Ret = TestFuncs(Suffix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepSuffix; + } + if (!Prefix.empty()) { + bool Ret = TestFuncs(Prefix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepPrefix; + } return NoFailure; } - bool TestFuncs(const std::vector<Function*> &Prefix); + int TestFuncs(const std::vector<Function*> &Prefix, std::string &Error); }; } @@ -184,7 +208,7 @@ namespace { /// returns. /// static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2, - bool DeleteInputs) { + bool DeleteInputs, std::string &Error) { // Link the two portions of the program back to together. std::string ErrorMsg; if (!DeleteInputs) { @@ -202,11 +226,12 @@ static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2, // Execute the program. If it does not match the expected output, we must // return true. - bool Broken = BD.diffProgram(); - - // Delete the linked module & restore the original - BD.swapProgramIn(OldProgram); - delete M1; + bool Broken = BD.diffProgram("", "", false, &Error); + if (!Error.empty()) { + // Delete the linked module & restore the original + BD.swapProgramIn(OldProgram); + delete M1; + } return Broken; } @@ -214,7 +239,8 @@ static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2, /// under consideration for miscompilation vs. those that are not, and test /// accordingly. Each group of functions becomes a separate Module. /// -bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*>&Funcs){ +int ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs, + std::string &Error) { // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. outs() << "Checking to see if the program is misoptimized when " @@ -231,7 +257,7 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*>&Funcs){ ValueMap); // Run the predicate, note that the predicate will delete both input modules. - return TestFn(BD, ToOptimize, ToNotOptimize); + return TestFn(BD, ToOptimize, ToNotOptimize, Error); } /// DisambiguateGlobalSymbols - Give anonymous global values names. @@ -251,8 +277,10 @@ static void DisambiguateGlobalSymbols(Module *M) { /// bug. If so, it reduces the amount of code identified. /// static bool ExtractLoops(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *), - std::vector<Function*> &MiscompiledFunctions) { + bool (*TestFn)(BugDriver &, Module *, Module *, + std::string &), + std::vector<Function*> &MiscompiledFunctions, + std::string &Error) { bool MadeChange = false; while (1) { if (BugpointIsInterrupted) return MadeChange; @@ -279,7 +307,11 @@ static bool ExtractLoops(BugDriver &BD, // has broken. If something broke, then we'll inform the user and stop // extraction. AbstractInterpreter *AI = BD.switchToSafeInterpreter(); - if (TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, false)) { + bool Failure = TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, + false, Error); + if (!Error.empty()) + return false; + if (Failure) { BD.switchToInterpreter(AI); // Merged program doesn't work anymore! @@ -308,7 +340,10 @@ static bool ExtractLoops(BugDriver &BD, // Clone modules, the tester function will free them. Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted); Module *TNOBackup = CloneModule(ToNotOptimize); - if (!TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize)) { + Failure = TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize, Error); + if (!Error.empty()) + return false; + if (!Failure) { 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. @@ -361,31 +396,44 @@ static bool ExtractLoops(BugDriver &BD, namespace { class ReduceMiscompiledBlocks : public ListReducer<BasicBlock*> { BugDriver &BD; - bool (*TestFn)(BugDriver &, Module *, Module *); + bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); std::vector<Function*> FunctionsBeingTested; public: ReduceMiscompiledBlocks(BugDriver &bd, - bool (*F)(BugDriver &, Module *, Module *), + bool (*F)(BugDriver &, Module *, Module *, + std::string &), const std::vector<Function*> &Fns) : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {} virtual TestResult doTest(std::vector<BasicBlock*> &Prefix, - std::vector<BasicBlock*> &Suffix) { - if (!Suffix.empty() && TestFuncs(Suffix)) - return KeepSuffix; - if (TestFuncs(Prefix)) - return KeepPrefix; + std::vector<BasicBlock*> &Suffix, + std::string &Error) { + if (!Suffix.empty()) { + bool Ret = TestFuncs(Suffix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepSuffix; + } + if (!Prefix.empty()) { + bool Ret = TestFuncs(Prefix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepPrefix; + } return NoFailure; } - bool TestFuncs(const std::vector<BasicBlock*> &Prefix); + bool TestFuncs(const std::vector<BasicBlock*> &BBs, std::string &Error); }; } /// TestFuncs - Extract all blocks for the miscompiled functions except for the /// specified blocks. If the problem still exists, return true. /// -bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs) { +bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs, + std::string &Error) { // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. outs() << "Checking to see if the program is misoptimized when all "; @@ -411,7 +459,7 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs) { if (Module *New = BD.ExtractMappedBlocksFromModule(BBs, ToOptimize)) { delete ToOptimize; // Run the predicate, not that the predicate will delete both input modules. - return TestFn(BD, New, ToNotOptimize); + return TestFn(BD, New, ToNotOptimize, Error); } delete ToOptimize; delete ToNotOptimize; @@ -424,8 +472,10 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs) { /// the bug. /// static bool ExtractBlocks(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *), - std::vector<Function*> &MiscompiledFunctions) { + bool (*TestFn)(BugDriver &, Module *, Module *, + std::string &), + std::vector<Function*> &MiscompiledFunctions, + std::string &Error) { if (BugpointIsInterrupted) return false; std::vector<BasicBlock*> Blocks; @@ -440,11 +490,17 @@ static bool ExtractBlocks(BugDriver &BD, unsigned OldSize = Blocks.size(); // Check to see if all blocks are extractible first. - if (ReduceMiscompiledBlocks(BD, TestFn, - MiscompiledFunctions).TestFuncs(std::vector<BasicBlock*>())) { + bool Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions) + .TestFuncs(std::vector<BasicBlock*>(), Error); + if (!Error.empty()) + return false; + if (Ret) { Blocks.clear(); } else { - ReduceMiscompiledBlocks(BD, TestFn,MiscompiledFunctions).reduceList(Blocks); + ReduceMiscompiledBlocks(BD, TestFn, + MiscompiledFunctions).reduceList(Blocks, Error); + if (!Error.empty()) + return false; if (Blocks.size() == OldSize) return false; } @@ -505,7 +561,9 @@ static bool ExtractBlocks(BugDriver &BD, /// static std::vector<Function*> DebugAMiscompilation(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *)) { + bool (*TestFn)(BugDriver &, Module *, Module *, + std::string &), + std::string &Error) { // Okay, now that we have reduced the list of passes which are causing the // failure, see if we can pin down which functions are being // miscompiled... first build a list of all of the non-external functions in @@ -518,7 +576,10 @@ DebugAMiscompilation(BugDriver &BD, // Do the reduction... if (!BugpointIsInterrupted) - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, + Error); + if (!Error.empty()) + return MiscompiledFunctions; outs() << "\n*** The following function" << (MiscompiledFunctions.size() == 1 ? " is" : "s are") @@ -529,37 +590,51 @@ DebugAMiscompilation(BugDriver &BD, // See if we can rip any loops out of the miscompiled functions and still // trigger the problem. - if (!BugpointIsInterrupted && !DisableLoopExtraction && - ExtractLoops(BD, TestFn, MiscompiledFunctions)) { - // Okay, we extracted some loops and the problem still appears. See if we - // can eliminate some of the created functions from being candidates. - DisambiguateGlobalSymbols(BD.getProgram()); - - // Do the reduction... - if (!BugpointIsInterrupted) - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); - - outs() << "\n*** The following function" - << (MiscompiledFunctions.size() == 1 ? " is" : "s are") - << " being miscompiled: "; - PrintFunctionList(MiscompiledFunctions); - outs() << '\n'; + if (!BugpointIsInterrupted && !DisableLoopExtraction) { + bool Ret = ExtractLoops(BD, TestFn, MiscompiledFunctions, Error); + if (!Error.empty()) + return MiscompiledFunctions; + if (Ret) { + // Okay, we extracted some loops and the problem still appears. See if + // we can eliminate some of the created functions from being candidates. + DisambiguateGlobalSymbols(BD.getProgram()); + + // Do the reduction... + if (!BugpointIsInterrupted) + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, + Error); + if (!Error.empty()) + return MiscompiledFunctions; + + outs() << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; + PrintFunctionList(MiscompiledFunctions); + outs() << '\n'; + } } - 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. - DisambiguateGlobalSymbols(BD.getProgram()); - - // Do the reduction... - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); - - outs() << "\n*** The following function" - << (MiscompiledFunctions.size() == 1 ? " is" : "s are") - << " being miscompiled: "; - PrintFunctionList(MiscompiledFunctions); - outs() << '\n'; + if (!BugpointIsInterrupted && !DisableBlockExtraction) { + bool Ret = ExtractBlocks(BD, TestFn, MiscompiledFunctions, Error); + if (!Error.empty()) + return MiscompiledFunctions; + if (Ret) { + // Okay, we extracted some blocks and the problem still appears. See if + // we can eliminate some of the created functions from being candidates. + DisambiguateGlobalSymbols(BD.getProgram()); + + // Do the reduction... + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, + Error); + if (!Error.empty()) + return MiscompiledFunctions; + + outs() << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; + PrintFunctionList(MiscompiledFunctions); + outs() << '\n'; + } } return MiscompiledFunctions; @@ -569,7 +644,8 @@ DebugAMiscompilation(BugDriver &BD, /// "Test" portion of the program is misoptimized. If so, return true. In any /// case, both module arguments are deleted. /// -static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe) { +static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe, + std::string &Error) { // Run the optimization passes on ToOptimize, producing a transformed version // of the functions being tested. outs() << " Optimizing functions being tested: "; @@ -579,8 +655,8 @@ static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe) { delete Test; outs() << " Checking to see if the merged program executes correctly: "; - bool Broken = TestMergedProgram(BD, Optimized, Safe, true); - outs() << (Broken ? " nope.\n" : " yup.\n"); + bool Broken = TestMergedProgram(BD, Optimized, Safe, true, Error); + if (Error.empty()) outs() << (Broken ? " nope.\n" : " yup.\n"); return Broken; } @@ -589,13 +665,14 @@ static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe) { /// crashing, but the generated output is semantically different from the /// input. /// -bool BugDriver::debugMiscompilation() { +void BugDriver::debugMiscompilation(std::string *Error) { // Make sure something was miscompiled... if (!BugpointIsInterrupted) - if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) { - errs() << "*** Optimized program matches reference output! No problem" - << " detected...\nbugpoint can't help you with your problem!\n"; - return false; + if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun, *Error)) { + if (Error->empty()) + errs() << "*** Optimized program matches reference output! No problem" + << " detected...\nbugpoint can't help you with your problem!\n"; + return; } outs() << "\n*** Found miscompiling pass" @@ -603,8 +680,10 @@ bool BugDriver::debugMiscompilation() { << getPassesString(getPassesToRun()) << '\n'; EmitProgressBitcode("passinput"); - std::vector<Function*> MiscompiledFunctions = - DebugAMiscompilation(*this, TestOptimizer); + std::vector<Function *> MiscompiledFunctions = + DebugAMiscompilation(*this, TestOptimizer, *Error); + if (!Error->empty()) + return; // Output a bunch of bitcode files for the user... outs() << "Outputting reduced bitcode files which expose the problem:\n"; @@ -624,7 +703,7 @@ bool BugDriver::debugMiscompilation() { EmitProgressBitcode("tooptimize"); setNewProgram(ToOptimize); // Delete hacked module. - return false; + return; } /// CleanupAndPrepareModules - Get the specified modules ready for code @@ -797,7 +876,8 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, /// the "Test" portion of the program is miscompiled by the code generator under /// test. If so, return true. In any case, both module arguments are deleted. /// -static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) { +static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, + std::string &Error) { CleanupAndPrepareModules(BD, Test, Safe); sys::Path TestModuleBC("bugpoint.test.bc"); @@ -827,12 +907,16 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) { << "'\nExiting."; exit(1); } - std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str()); + std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error); + if (!Error.empty()) + return false; 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.str(), SharedObject, false); + bool Result = BD.diffProgram(TestModuleBC.str(), SharedObject, false, &Error); + if (!Error.empty()) + return false; if (Result) errs() << ": still failing!\n"; @@ -848,23 +932,28 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) { /// debugCodeGenerator - debug errors in LLC, LLI, or CBE. /// -bool BugDriver::debugCodeGenerator() { +bool BugDriver::debugCodeGenerator(std::string *Error) { if ((void*)SafeInterpreter == (void*)Interpreter) { - std::string Result = executeProgramSafely("bugpoint.safe.out"); - 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"; + std::string Result = executeProgramSafely("bugpoint.safe.out", Error); + if (Error->empty()) { + 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; } DisambiguateGlobalSymbols(Program); - std::vector<Function*> Funcs = DebugAMiscompilation(*this, TestCodeGenerator); + std::vector<Function*> Funcs = DebugAMiscompilation(*this, TestCodeGenerator, + *Error); + if (!Error->empty()) + return true; // Split the module into the two halves of the program we want. DenseMap<const Value*, Value*> ValueMap; @@ -902,7 +991,9 @@ bool BugDriver::debugCodeGenerator() { << "'\nExiting."; exit(1); } - std::string SharedObject = compileSharedObject(SafeModuleBC.str()); + std::string SharedObject = compileSharedObject(SafeModuleBC.str(), *Error); + if (!Error->empty()) + return true; delete ToNotCodeGen; outs() << "You can reproduce the problem with the command line: \n"; @@ -919,7 +1010,7 @@ bool BugDriver::debugCodeGenerator() { outs() << "\n"; outs() << " " << TestModuleBC.str() << ".exe"; } - for (unsigned i=0, e = InputArgv.size(); i != e; ++i) + for (unsigned i = 0, e = InputArgv.size(); i != e; ++i) outs() << " " << InputArgv[i]; outs() << '\n'; outs() << "The shared object was created with:\n llc -march=c " diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index 9f712e097a..3a6149b24a 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -45,8 +45,6 @@ namespace { // ChildOutput - This option captures the name of the child output file that // is set up by the parent bugpoint process cl::opt<std::string> ChildOutput("child-output", cl::ReallyHidden); - cl::opt<bool> UseValgrind("enable-valgrind", - cl::desc("Run optimizations through valgrind")); } /// writeProgramToFile - This writes the current "Program" to the named bitcode diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 645776eafd..9c8c2f92d3 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -50,11 +50,9 @@ namespace { cl::desc("Remote execution (rsh/ssh) extra options")); } -ToolExecutionError::~ToolExecutionError() throw() { } - /// RunProgramWithTimeout - This function provides an alternate interface /// to the sys::Program::ExecuteAndWait interface. -/// @see sys:Program::ExecuteAndWait +/// @see sys::Program::ExecuteAndWait static int RunProgramWithTimeout(const sys::Path &ProgramPath, const char **Args, const sys::Path &StdInFile, @@ -86,7 +84,7 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath, /// 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 +/// @see sys::Program::ExecuteAndWait static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, const char **Args, const sys::Path &StdInFile, @@ -129,19 +127,19 @@ static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, ErrorFile.close(); } - throw ToolExecutionError(OS.str()); + errs() << OS; } return ReturnCode; } -static void ProcessFailure(sys::Path ProgPath, const char** Args) { +static std::string ProcessFailure(sys::Path ProgPath, const char** Args) { std::ostringstream OS; OS << "\nError running tool:\n "; for (const char **Arg = Args; *Arg; ++Arg) OS << " " << *Arg; OS << "\n"; - + // Rerun the compiler, capturing any error messages to print them. sys::Path ErrorFilename("bugpoint.program_error_messages"); std::string ErrMsg; @@ -162,7 +160,7 @@ static void ProcessFailure(sys::Path ProgPath, const char** Args) { } ErrorFilename.eraseFromDisk(); - throw ToolExecutionError(OS.str()); + return OS.str(); } //===---------------------------------------------------------------------===// @@ -183,6 +181,7 @@ namespace { const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs, const std::vector<std::string> &SharedLibs = std::vector<std::string>(), @@ -195,6 +194,7 @@ int LLI::ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs, const std::vector<std::string> &SharedLibs, unsigned Timeout, @@ -263,9 +263,10 @@ namespace { const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs, const std::vector<std::string> &SharedLibs = - std::vector<std::string>(), + std::vector<std::string>(), unsigned Timeout = 0, unsigned MemoryLimit = 0); }; @@ -275,6 +276,7 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs, const std::vector<std::string> &SharedLibs, unsigned Timeout, @@ -289,7 +291,7 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, ProgramArgs.push_back(0); // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) + for (unsigned i = 0, e = Args.size(); i != e; ++i) ProgramArgs.push_back(Args[i].c_str()); return RunProgramWithTimeout( @@ -351,8 +353,9 @@ AbstractInterpreter *AbstractInterpreter::createCustom( // LLC Implementation of AbstractIntepreter interface // GCC::FileType LLC::OutputCode(const std::string &Bitcode, - sys::Path &OutputAsmFile) { - sys::Path uniqueFile(Bitcode+".llc.s"); + sys::Path &OutputAsmFile, std::string &Error) { + const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); + sys::Path uniqueFile(Bitcode + Suffix); std::string ErrMsg; if (uniqueFile.makeUnique(true, &ErrMsg)) { errs() << "Error making unique filename: " << ErrMsg << "\n"; @@ -360,33 +363,37 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, } OutputAsmFile = uniqueFile; std::vector<const char *> LLCArgs; - LLCArgs.push_back (LLCPath.c_str()); + LLCArgs.push_back(LLCPath.c_str()); // Add any extra LLC args. for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) LLCArgs.push_back(ToolArgs[i].c_str()); - LLCArgs.push_back ("-o"); - LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file - LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode + LLCArgs.push_back("-o"); + LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file + LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode + + if (UseIntegratedAssembler) + LLCArgs.push_back("-filetype=obj"); + LLCArgs.push_back (0); - outs() << "<llc>"; outs().flush(); + outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); + outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) + for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) errs() << " " << LLCArgs[i]; errs() << "\n"; ); if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], sys::Path(), sys::Path(), sys::Path())) - ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]); - - return GCC::AsmFile; + Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]); + return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; } -void LLC::compileProgram(const std::string &Bitcode) { +void LLC::compileProgram(const std::string &Bitcode, std::string *Error) { sys::Path OutputAsmFile; - OutputCode(Bitcode, OutputAsmFile); + OutputCode(Bitcode, OutputAsmFile, *Error); OutputAsmFile.eraseFromDisk(); } @@ -394,13 +401,14 @@ int LLC::ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &ArgsForGCC, const std::vector<std::string> &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { sys::Path OutputAsmFile; - OutputCode(Bitcode, OutputAsmFile); + GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error); FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); std::vector<std::string> GCCArgs(ArgsForGCC); @@ -408,8 +416,8 @@ int LLC::ExecuteProgram(const std::string &Bitcode, GCCArgs.insert(GCCArgs.end(), gccArgs.begin(), gccArgs.end()); // Assuming LLC worked, compile the result with GCC and run it. - return gcc->ExecuteProgram(OutputAsmFile.str(), Args, GCC::AsmFile, - InputFile, OutputFile, GCCArgs, + return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, + InputFile, OutputFile, Error, GCCArgs, Timeout, MemoryLimit); } @@ -418,7 +426,8 @@ int LLC::ExecuteProgram(const std::string &Bitcode, LLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message, const std::vector<std::string> *Args, - const std::vector<std::string> *GCCArgs) { + const std::vector<std::string> *GCCArgs, + bool UseIntegratedAssembler) { std::string LLCPath = FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str(); if (LLCPath.empty()) { @@ -432,7 +441,7 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0, errs() << Message << "\n"; exit(1); } - return new LLC(LLCPath, gcc, Args, GCCArgs); + return new LLC(LLCPath, gcc, Args, GCCArgs, UseIntegratedAssembler); } //===---------------------------------------------------------------------===// @@ -453,12 +462,13 @@ namespace { const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = std::vector<std::string>(), - unsigned Timeout =0, - unsigned MemoryLimit =0); + unsigned Timeout = 0, + unsigned MemoryLimit = 0); }; } @@ -466,6 +476,7 @@ int JIT::ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs, const std::vector<std::string> &SharedLibs, unsigned Timeout, @@ -517,7 +528,7 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, } GCC::FileType CBE::OutputCode(const std::string &Bitcode, - sys::Path &OutputCFile) { + sys::Path &OutputCFile, std::string &Error) { sys::Path uniqueFile(Bitcode+".cbe.c"); std::string ErrMsg; if (uniqueFile.makeUnique(true, &ErrMsg)) { @@ -526,34 +537,34 @@ GCC::FileType CBE::OutputCode(const std::string &Bitcode, } OutputCFile = uniqueFile; std::vector<const char *> LLCArgs; - LLCArgs.push_back (LLCPath.c_str()); + LLCArgs.push_back(LLCPath.c_str()); // Add any extra LLC args. for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) LLCArgs.push_back(ToolArgs[i].c_str()); - LLCArgs.push_back ("-o"); - LLCArgs.push_back (OutputCFile.c_str()); // Output to the C file - LLCArgs.push_back ("-march=c"); // Output C language - LLCArgs.push_back ("-f"); // Overwrite as necessary... - LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode - LLCArgs.push_back (0); + LLCArgs.push_back("-o"); + LLCArgs.push_back(OutputCFile.c_str()); // Output to the C file + LLCArgs.push_back("-march=c"); // Output C language + LLCArgs.push_back("-f"); // Overwrite as necessary... + LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode + LLCArgs.push_back(0); outs() << "<cbe>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) + for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) errs() << " " << LLCArgs[i]; errs() << "\n"; ); if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), sys::Path())) - ProcessFailure(LLCPath, &LLCArgs[0]); + Error = ProcessFailure(LLCPath, &LLCArgs[0]); return GCC::CFile; } -void CBE::compileProgram(const std::string &Bitcode) { +void CBE::compileProgram(const std::string &Bitcode, std::string *Error) { sys::Path OutputCFile; - OutputCode(Bitcode, OutputCFile); + OutputCode(Bitcode, OutputCFile, *Error); OutputCFile.eraseFromDisk(); } @@ -561,12 +572,13 @@ int CBE::ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &ArgsForGCC, const std::vector<std::string> &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { sys::Path OutputCFile; - OutputCode(Bitcode, OutputCFile); + OutputCode(Bitcode, OutputCFile, *Error); FileRemover CFileRemove(OutputCFile, !SaveTemps); @@ -574,7 +586,7 @@ int CBE::ExecuteProgram(const std::string &Bitcode, GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, - InputFile, OutputFile, GCCArgs, + InputFile, OutputFile, Error, GCCArgs, Timeout, MemoryLimit); } @@ -605,17 +617,14 @@ CBE *AbstractInterpreter::createCBE(const char *Argv0, // GCC abstraction // -static bool -IsARMArchitecture(std::vector<std::string> Args) -{ +static bool IsARMArchitecture(std::vector<std::string> Args) { for (std::vector<std::string>::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { StringRef S(*I); if (!S.equals_lower("-arch")) { ++I; - if (I != E && !S.substr(0, strlen("arm")).equals_lower("arm")) { + if (I != E && !S.substr(0, strlen("arm")).equals_lower("arm")) return true; - } } } @@ -627,6 +636,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, FileType fileType, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &ArgsForGCC, unsigned Timeout, unsigned MemoryLimit) { @@ -634,26 +644,33 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, GCCArgs.push_back(GCCPath.c_str()); + if (TargetTriple.getArch() == Triple::x86) + GCCArgs.push_back("-m32"); + for (std::vector<std::string>::const_iterator I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) GCCArgs.push_back(I->c_str()); // Specify -x explicitly in case the extension is wonky - GCCArgs.push_back("-x"); - if (fileType == CFile) { - GCCArgs.push_back("c"); - GCCArgs.push_back("-fno-strict-aliasing"); - } else { - GCCArgs.push_back("assembler"); - - // 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"); + if (fileType != ObjectFile) { + GCCArgs.push_back("-x"); + if (fileType == CFile) { + GCCArgs.push_back("c"); + GCCArgs.push_back("-fno-strict-aliasing"); + } else { + GCCArgs.push_back("assembler"); + + // 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(ProgramFile.c_str()); // Specify the input filename. + GCCArgs.push_back("-x"); GCCArgs.push_back("none"); GCCArgs.push_back("-o"); @@ -683,14 +700,14 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, outs() << "<gcc>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) + for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) errs() << " " << GCCArgs[i]; errs() << "\n"; ); if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), sys::Path())) { - ProcessFailure(GCCPath, &GCCArgs[0]); - exit(1); + *Error = ProcessFailure(GCCPath, &GCCArgs[0]); + return -1; } std::vector<const char*> ProgramArgs; @@ -723,14 +740,14 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, } // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) + for (unsigned i = 0, e = Args.size(); i != e; ++i) ProgramArgs.push_back(Args[i].c_str()); ProgramArgs.push_back(0); // NULL terminator // Now that we have a binary, run it! outs() << "<program>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i) + for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) errs() << " " << ProgramArgs[i]; errs() << "\n"; ); @@ -738,7 +755,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps); if (RemoteClientPath.isEmpty()) { - DEBUG(errs() << "<run locally>";); + DEBUG(errs() << "<run locally>"); return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), Timeout, MemoryLimit); @@ -752,7 +769,8 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, std::string &OutputFile, - const std::vector<std::string> &ArgsForGCC) { + const std::vector<std::string> &ArgsForGCC, + std::string &Error) { sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); std::string ErrMsg; if (uniqueFilename.makeUnique(true, &ErrMsg)) { @@ -765,13 +783,18 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back(GCCPath.c_str()); + if (TargetTriple.getArch() == Triple::x86) + GCCArgs.push_back("-m32"); + for (std::vector<std::string>::const_iterator I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) GCCArgs.push_back(I->c_str()); // Compile the C/asm file into a shared object - GCCArgs.push_back("-x"); - GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); + if (fileType != ObjectFile) { + GCCArgs.push_back("-x"); + GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); + } GCCArgs.push_back("-fno-strict-aliasing"); GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. GCCArgs.push_back("-x"); @@ -815,13 +838,13 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, outs() << "<gcc>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) + for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) errs() << " " << GCCArgs[i]; errs() << "\n"; ); if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), sys::Path())) { - ProcessFailure(GCCPath, &GCCArgs[0]); + Error = ProcessFailure(GCCPath, &GCCArgs[0]); return 1; } return 0; diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index 39b0bbfdd5..cba10f214a 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -19,6 +19,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SystemUtils.h" #include "llvm/System/Path.h" #include <exception> @@ -32,19 +33,6 @@ extern Triple TargetTriple; class CBE; class LLC; -/// ToolExecutionError - An instance of this class is thrown by the -/// AbstractInterpreter instances if there is an error running a tool (e.g., LLC -/// crashes) which prevents execution of the program. -/// -class ToolExecutionError : std::exception { - std::string Message; -public: - explicit ToolExecutionError(const std::string &M) : Message(M) {} - virtual ~ToolExecutionError() throw(); - virtual const char* what() const throw() { return Message.c_str(); } -}; - - //===---------------------------------------------------------------------===// // GCC abstraction // @@ -58,7 +46,7 @@ class GCC { if (GCCArgs) gccArgs = *GCCArgs; } public: - enum FileType { AsmFile, CFile }; + enum FileType { AsmFile, ObjectFile, CFile }; static GCC *create(std::string &Message, const std::vector<std::string> *Args); @@ -75,6 +63,7 @@ public: FileType fileType, const std::string &InputFile, const std::string &OutputFile, + std::string *Error = 0, const std::vector<std::string> &GCCArgs = std::vector<std::string>(), unsigned Timeout = 0, @@ -85,7 +74,8 @@ public: /// int MakeSharedObject(const std::string &InputFile, FileType fileType, std::string &OutputFile, - const std::vector<std::string> &ArgsForGCC); + const std::vector<std::string> &ArgsForGCC, + std::string &Error); }; @@ -101,7 +91,8 @@ public: const std::vector<std::string> *GCCArgs = 0); static LLC *createLLC(const char *Argv0, std::string &Message, const std::vector<std::string> *Args = 0, - const std::vector<std::string> *GCCArgs = 0); + const std::vector<std::string> *GCCArgs = 0, + bool UseIntegratedAssembler = false); static AbstractInterpreter* createLLI(const char *Argv0, std::string &Message, const std::vector<std::string> *Args=0); @@ -117,26 +108,29 @@ public: /// compileProgram - Compile the specified program from bitcode to executable /// code. This does not produce any output, it is only used when debugging - /// the code generator. If the code generator fails, an exception should be - /// thrown, otherwise, this function will just return. - virtual void compileProgram(const std::string &Bitcode) {} + /// the code generator. It returns false if the code generator fails. + virtual void compileProgram(const std::string &Bitcode, std::string *Error) {} /// OutputCode - Compile the specified program from bitcode to code /// understood by the GCC driver (either C or asm). If the code generator - /// fails, an exception should be thrown, otherwise, this function returns the - /// type of code emitted. + /// fails, it sets Error, otherwise, this function returns the type of code + /// emitted. virtual GCC::FileType OutputCode(const std::string &Bitcode, - sys::Path &OutFile) { - throw std::string("OutputCode not supported by this AbstractInterpreter!"); + sys::Path &OutFile, std::string &Error) { + Error = "OutputCode not supported by this AbstractInterpreter!"; + return GCC::AsmFile; } - + /// ExecuteProgram - Run the specified bitcode file, emitting output to the - /// specified filename. This returns the exit code of the program. + /// specified filename. This sets RetVal to the exit code of the program or + /// returns false if a problem was encountered that prevented execution of + /// the program. /// virtual int ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = @@ -163,14 +157,14 @@ public: /// compileProgram - Compile the specified program from bitcode to executable /// code. This does not produce any output, it is only used when debugging - /// the code generator. If the code generator fails, an exception should be - /// thrown, otherwise, this function will just return. - virtual void compileProgram(const std::string &Bitcode); + /// the code generator. Returns false if the code generator fails. + virtual void compileProgram(const std::string &Bitcode, std::string *Error); virtual int ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = @@ -180,10 +174,10 @@ public: /// OutputCode - Compile the specified program from bitcode to code /// understood by the GCC driver (either C or asm). If the code generator - /// fails, an exception should be thrown, otherwise, this function returns the - /// type of code emitted. + /// fails, it sets Error, otherwise, this function returns the type of code + /// emitted. virtual GCC::FileType OutputCode(const std::string &Bitcode, - sys::Path &OutFile); + sys::Path &OutFile, std::string &Error); }; @@ -195,11 +189,14 @@ class LLC : public AbstractInterpreter { std::vector<std::string> ToolArgs; // Extra args to pass to LLC. std::vector<std::string> gccArgs; // Extra args to pass to GCC. GCC *gcc; + bool UseIntegratedAssembler; public: LLC(const std::string &llcPath, GCC *Gcc, const std::vector<std::string> *Args, - const std::vector<std::string> *GCCArgs) - : LLCPath(llcPath), gcc(Gcc) { + const std::vector<std::string> *GCCArgs, + bool useIntegratedAssembler) + : LLCPath(llcPath), gcc(Gcc), + UseIntegratedAssembler(useIntegratedAssembler) { ToolArgs.clear(); if (Args) ToolArgs = *Args; if (GCCArgs) gccArgs = *GCCArgs; @@ -208,14 +205,14 @@ public: /// compileProgram - Compile the specified program from bitcode to executable /// code. This does not produce any output, it is only used when debugging - /// the code generator. If the code generator fails, an exception should be - /// thrown, otherwise, this function will just return. - virtual void compileProgram(const std::string &Bitcode); + /// the code generator. Returns false if the code generator fails. + virtual void compileProgram(const std::string &Bitcode, std::string *Error); virtual int ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &Args, const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector<std::string> &GCCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = @@ -223,9 +220,12 @@ public: unsigned Timeout = 0, unsigned MemoryLimit = 0); + /// OutputCode - Compile the specified program from bitcode to code + /// understood by the GCC driver (either C or asm). If the code generator + /// fails, it sets Error, otherwise, this function returns the type of code + /// emitted. virtual GCC::FileType OutputCode(const std::string &Bitcode, - sys::Path &OutFile); - + sys::Path &OutFile, std::string &Error); }; } // End llvm namespace diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index 565f3f9a70..ba5234bdc8 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/StandardPasses.h" #include "llvm/System/Process.h" #include "llvm/System/Signals.h" +#include "llvm/System/Valgrind.h" #include "llvm/LinkAllVMCore.h" using namespace llvm; @@ -48,9 +49,14 @@ 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")); -static cl::opt<unsigned> -MemoryLimit("mlimit", cl::init(100), cl::value_desc("MBytes"), - cl::desc("Maximum amount of memory to use. 0 disables check.")); +static cl::opt<int> +MemoryLimit("mlimit", cl::init(-1), cl::value_desc("MBytes"), + cl::desc("Maximum amount of memory to use. 0 disables check." + " Defaults to 100MB (800MB under valgrind).")); + +static cl::opt<bool> +UseValgrind("enable-valgrind", + cl::desc("Run optimizations through valgrind")); // The AnalysesList is automatically populated with registered Passes by the // PassNameParser. @@ -108,7 +114,17 @@ int main(int argc, char **argv) { outs() << "Override triple set to '" << OverrideTriple << "'\n"; } - BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit, Context); + if (MemoryLimit < 0) { + // Set the default MemoryLimit. Be sure to update the flag's description if + // you change this. + if (sys::RunningOnValgrind() || UseValgrind) + MemoryLimit = 800; + else + MemoryLimit = 100; + } + + BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit, + UseValgrind, Context); if (D.addSources(InputFilenames)) return 1; AddToDriver PM(D); @@ -133,23 +149,11 @@ int main(int argc, char **argv) { // avoid filling up the disk, we prevent it sys::Process::PreventCoreFiles(); - try { - return D.run(); - } catch (ToolExecutionError &TEE) { - errs() << "Tool execution error: " << TEE.what() << '\n'; - } catch (const std::string& msg) { - 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) { - errs() << "Whoops, a std::exception leaked out of bugpoint: " - << e.what() << "\n" - << "This is a bug in bugpoint!\n"; - } catch (...) { - errs() << "Whoops, an exception leaked out of bugpoint. " - << "This is a bug in bugpoint!\n"; + std::string Error; + bool Failure = D.run(Error); + if (!Error.empty()) { + errs() << Error; + return 1; } - return 1; + return Failure; } diff --git a/tools/edis/CMakeLists.txt b/tools/edis/CMakeLists.txt new file mode 100644 index 0000000000..f7a199d597 --- /dev/null +++ b/tools/edis/CMakeLists.txt @@ -0,0 +1,25 @@ +set(LLVM_NO_RTTI 1) + +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/EDInfo.inc + COMMAND ${LLVM_TABLEGEN_EXE} -o ${CMAKE_CURRENT_BINARY_DIR}/EDInfo.inc + -gen-enhanced-disassembly-header ${CMAKE_CURRENT_SOURCE_DIR}/EDInfo.td + DEPENDS tblgen + COMMENT "Building enhanced disassembly semantic information header (EDInfo.inc)") +set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/EDInfo.inc PROPERTIES GENERATED 1) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_llvm_library(EnhancedDisassembly + EDDisassembler.cpp + EDInst.cpp + EDMain.cpp + EDOperand.cpp + EDToken.cpp + ../../include/llvm-c/EnhancedDisassembly.h + ${CMAKE_CURRENT_BINARY_DIR}/EDInfo.inc +) + +set_target_properties(EnhancedDisassembly + PROPERTIES + LINKER_LANGUAGE CXX) + diff --git a/tools/edis/EDDisassembler.cpp b/tools/edis/EDDisassembler.cpp index 99864fb322..00b5d8d33a 100644 --- a/tools/edis/EDDisassembler.cpp +++ b/tools/edis/EDDisassembler.cpp @@ -13,8 +13,12 @@ // //===----------------------------------------------------------------------===// +#include "EDDisassembler.h" +#include "EDInst.h" + #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/MC/EDInstInfo.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" @@ -36,38 +40,34 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSelect.h" -#include "EDDisassembler.h" -#include "EDInst.h" - -#include "../../lib/Target/X86/X86GenEDInfo.inc" - using namespace llvm; bool EDDisassembler::sInitialized = false; EDDisassembler::DisassemblerMap_t EDDisassembler::sDisassemblers; -struct InfoMap { +struct TripleMap { Triple::ArchType Arch; const char *String; - const InstInfo *Info; }; -static struct InfoMap infomap[] = { - { Triple::x86, "i386-unknown-unknown", instInfoX86 }, - { Triple::x86_64, "x86_64-unknown-unknown", instInfoX86 }, - { Triple::InvalidArch, NULL, NULL } +static struct TripleMap triplemap[] = { + { Triple::x86, "i386-unknown-unknown" }, + { Triple::x86_64, "x86_64-unknown-unknown" }, + { Triple::arm, "arm-unknown-unknown" }, + { Triple::thumb, "thumb-unknown-unknown" }, + { Triple::InvalidArch, NULL, } }; -/// infoFromArch - Returns the InfoMap corresponding to a given architecture, +/// infoFromArch - Returns the TripleMap corresponding to a given architecture, /// or NULL if there is an error /// /// @arg arch - The Triple::ArchType for the desired architecture -static const InfoMap *infoFromArch(Triple::ArchType arch) { +static const char *tripleFromArch(Triple::ArchType arch) { unsigned int infoIndex; - for (infoIndex = 0; infomap[infoIndex].String != NULL; ++infoIndex) { - if(arch == infomap[infoIndex].Arch) - return &infomap[infoIndex]; + for (infoIndex = 0; triplemap[infoIndex].String != NULL; ++infoIndex) { + if (arch == triplemap[infoIndex].Arch) + return triplemap[infoIndex].String; } return NULL; @@ -95,23 +95,25 @@ static int getLLVMSyntaxVariant(Triple::ArchType arch, return 1; else return -1; + case kEDAssemblySyntaxARMUAL: + if (arch == Triple::arm || arch == Triple::thumb) + return 0; + else + return -1; } } -#define BRINGUP_TARGET(tgt) \ - LLVMInitialize##tgt##TargetInfo(); \ - LLVMInitialize##tgt##Target(); \ - LLVMInitialize##tgt##AsmPrinter(); \ - LLVMInitialize##tgt##AsmParser(); \ - LLVMInitialize##tgt##Disassembler(); - void EDDisassembler::initialize() { if (sInitialized) return; sInitialized = true; - BRINGUP_TARGET(X86) + InitializeAllTargetInfos(); + InitializeAllTargets(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); + InitializeAllDisassemblers(); } #undef BRINGUP_TARGET @@ -126,10 +128,9 @@ EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch, if (i != sDisassemblers.end()) { return i->second; - } - else { + } else { EDDisassembler* sdd = new EDDisassembler(key); - if(!sdd->valid()) { + if (!sdd->valid()) { delete sdd; return NULL; } @@ -150,17 +151,18 @@ EDDisassembler *EDDisassembler::getDisassembler(StringRef str, } EDDisassembler::EDDisassembler(CPUKey &key) : - Valid(false), ErrorString(), ErrorStream(ErrorString), Key(key) { - const InfoMap *infoMap = infoFromArch(key.Arch); - - if (!infoMap) + Valid(false), + HasSemantics(false), + ErrorStream(nulls()), + Key(key) { + const char *triple = tripleFromArch(key.Arch); + + if (!triple) return; - const char *triple = infoMap->String; + LLVMSyntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax); - int syntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax); - - if (syntaxVariant < 0) + if (LLVMSyntaxVariant < 0) return; std::string tripleString(triple); @@ -182,6 +184,8 @@ EDDisassembler::EDDisassembler(CPUKey &key) : if (!registerInfo) return; + + initMaps(*registerInfo); AsmInfo.reset(Tgt->createAsmInfo(tripleString)); @@ -192,13 +196,12 @@ EDDisassembler::EDDisassembler(CPUKey &key) : if (!Disassembler) return; + + InstInfos = Disassembler->getEDInfo(); InstString.reset(new std::string); InstStream.reset(new raw_string_ostream(*InstString)); - - InstPrinter.reset(Tgt->createMCInstPrinter(syntaxVariant, - *AsmInfo, - *InstStream)); + InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo)); if (!InstPrinter) return; @@ -206,8 +209,6 @@ EDDisassembler::EDDisassembler(CPUKey &key) : GenericAsmLexer.reset(new AsmLexer(*AsmInfo)); SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo)); SpecificAsmLexer->InstallLexer(*GenericAsmLexer); - - InstInfos = infoMap->Info; initMaps(*targetMachine->getRegisterInfo()); @@ -215,7 +216,7 @@ EDDisassembler::EDDisassembler(CPUKey &key) : } EDDisassembler::~EDDisassembler() { - if(!valid()) + if (!valid()) return; } @@ -233,10 +234,10 @@ namespace { uint64_t getBase() const { return 0x0; } uint64_t getExtent() const { return (uint64_t)-1; } int readByte(uint64_t address, uint8_t *ptr) const { - if(!Callback) + if (!Callback) return -1; - if(Callback(ptr, address, Arg)) + if (Callback(ptr, address, Arg)) return -1; return 0; @@ -259,9 +260,10 @@ EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader, ErrorStream)) { delete inst; return NULL; - } - else { - const InstInfo *thisInstInfo = &InstInfos[inst->getOpcode()]; + } else { + const llvm::EDInstInfo *thisInstInfo; + + thisInstInfo = &InstInfos[inst->getOpcode()]; EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo); return sdInst; @@ -279,8 +281,11 @@ void EDDisassembler::initMaps(const TargetRegisterInfo ®isterInfo) { RegRMap[registerName] = registerIndex; } - if (Key.Arch == Triple::x86 || - Key.Arch == Triple::x86_64) { + switch (Key.Arch) { + default: + break; + case Triple::x86: + case Triple::x86_64: stackPointers.insert(registerIDWithName("SP")); stackPointers.insert(registerIDWithName("ESP")); stackPointers.insert(registerIDWithName("RSP")); @@ -288,6 +293,13 @@ void EDDisassembler::initMaps(const TargetRegisterInfo ®isterInfo) { programCounters.insert(registerIDWithName("IP")); programCounters.insert(registerIDWithName("EIP")); programCounters.insert(registerIDWithName("RIP")); + break; + case Triple::arm: + case Triple::thumb: + stackPointers.insert(registerIDWithName("SP")); + + programCounters.insert(registerIDWithName("PC")); + break; } } @@ -314,11 +326,10 @@ bool EDDisassembler::registerIsProgramCounter(unsigned registerID) { return (programCounters.find(registerID) != programCounters.end()); } -int EDDisassembler::printInst(std::string& str, - MCInst& inst) { +int EDDisassembler::printInst(std::string &str, MCInst &inst) { PrinterMutex.acquire(); - InstPrinter->printInst(&inst); + InstPrinter->printInst(&inst, *InstStream); InstStream->flush(); str = *InstString; InstString->clear(); @@ -333,6 +344,16 @@ int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands, const std::string &str) { int ret = 0; + switch (Key.Arch) { + default: + return -1; + case Triple::x86: + case Triple::x86_64: + case Triple::arm: + case Triple::thumb: + break; + } + const char *cStr = str.c_str(); MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr)); @@ -341,22 +362,22 @@ int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands, SourceMgr sourceMgr; sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over - MCContext context; - OwningPtr<MCStreamer> streamer - (createNullStreamer(context)); + MCContext context(*AsmInfo); + OwningPtr<MCStreamer> streamer(createNullStreamer(context)); AsmParser genericParser(sourceMgr, context, *streamer, *AsmInfo); - OwningPtr<TargetAsmParser> specificParser - (Tgt->createAsmParser(genericParser)); + OwningPtr<TargetAsmParser> TargetParser(Tgt->createAsmParser(genericParser)); AsmToken OpcodeToken = genericParser.Lex(); - - if(OpcodeToken.is(AsmToken::Identifier)) { + AsmToken NextToken = genericParser.Lex(); // consume next token, because specificParser expects us to + + if (OpcodeToken.is(AsmToken::Identifier)) { instName = OpcodeToken.getString(); instLoc = OpcodeToken.getLoc(); - if (specificParser->ParseInstruction(instName, instLoc, operands)) + + if (NextToken.isNot(AsmToken::Eof) && + TargetParser->ParseInstruction(instName, instLoc, operands)) ret = -1; - } - else { + } else { ret = -1; } diff --git a/tools/edis/EDDisassembler.h b/tools/edis/EDDisassembler.h index 6be9152fac..74a260e825 100644 --- a/tools/edis/EDDisassembler.h +++ b/tools/edis/EDDisassembler.h @@ -48,6 +48,8 @@ template <typename T> class SmallVectorImpl; class SourceMgr; class Target; class TargetRegisterInfo; + +struct EDInstInfo; } /// EDDisassembler - Encapsulates a disassembler for a single architecture and @@ -113,13 +115,13 @@ struct EDDisassembler { // Per-object members // //////////////////////// - /// True only if the object has been fully and successfully initialized + /// True only if the object has been successfully initialized bool Valid; + /// True if the disassembler can provide semantic information + bool HasSemantics; - /// The string that stores disassembler errors from the backend - std::string ErrorString; - /// The stream that wraps the ErrorString - llvm::raw_string_ostream ErrorStream; + /// The stream to write errors to + llvm::raw_ostream &ErrorStream; /// The architecture/syntax pair for the current architecture CPUKey Key; @@ -143,7 +145,7 @@ struct EDDisassembler { llvm::sys::Mutex PrinterMutex; /// The array of instruction information provided by the TableGen backend for /// the target architecture - const InstInfo *InstInfos; + const llvm::EDInstInfo *InstInfos; /// The target-specific lexer for use in tokenizing strings, in /// target-independent and target-specific portions llvm::OwningPtr<llvm::AsmLexer> GenericAsmLexer; @@ -180,6 +182,12 @@ struct EDDisassembler { return Valid; } + /// hasSemantics - reports whether the disassembler can provide operands and + /// tokens. + bool hasSemantics() { + return HasSemantics; + } + ~EDDisassembler(); /// createInst - creates and returns an instruction given a callback and diff --git a/tools/edis/EDInfo.td b/tools/edis/EDInfo.td new file mode 100644 index 0000000000..bd9ec079d8 --- /dev/null +++ b/tools/edis/EDInfo.td @@ -0,0 +1 @@ +// Intentionally empty. diff --git a/tools/edis/EDInst.cpp b/tools/edis/EDInst.cpp index 9ed27002ad..af3a54abbc 100644 --- a/tools/edis/EDInst.cpp +++ b/tools/edis/EDInst.cpp @@ -18,6 +18,7 @@ #include "EDOperand.h" #include "EDToken.h" +#include "llvm/MC/EDInstInfo.h" #include "llvm/MC/MCInst.h" using namespace llvm; @@ -25,7 +26,7 @@ using namespace llvm; EDInst::EDInst(llvm::MCInst *inst, uint64_t byteSize, EDDisassembler &disassembler, - const InstInfo *info) : + const llvm::EDInstInfo *info) : Disassembler(disassembler), Inst(inst), ThisInstInfo(info), @@ -33,6 +34,7 @@ EDInst::EDInst(llvm::MCInst *inst, BranchTarget(-1), MoveSource(-1), MoveTarget(-1) { + OperandOrder = ThisInstInfo->operandOrders[Disassembler.llvmSyntaxVariant()]; } EDInst::~EDInst() { @@ -60,8 +62,6 @@ int EDInst::stringify() { if (Disassembler.printInst(String, *Inst)) return StringifyResult.setResult(-1); - - OperandOrder = ThisInstInfo->operandOrders[Disassembler.llvmSyntaxVariant()]; return StringifyResult.setResult(0); } @@ -81,21 +81,21 @@ unsigned EDInst::instID() { bool EDInst::isBranch() { if (ThisInstInfo) - return ThisInstInfo->instructionFlags & kInstructionFlagBranch; + return ThisInstInfo->instructionType == kInstructionTypeBranch; else return false; } bool EDInst::isMove() { if (ThisInstInfo) - return ThisInstInfo->instructionFlags & kInstructionFlagMove; + return ThisInstInfo->instructionType == kInstructionTypeMove; else return false; } int EDInst::parseOperands() { if (ParseResult.valid()) - return ParseResult.result(); + return ParseResult.result(); if (!ThisInstInfo) return ParseResult.setResult(-1); diff --git a/tools/edis/EDInst.h b/tools/edis/EDInst.h index db03a7852e..c8a747ff99 100644 --- a/tools/edis/EDInst.h +++ b/tools/edis/EDInst.h @@ -23,6 +23,10 @@ #include <string> #include <vector> +namespace llvm { + struct EDInstInfo; +} + /// CachedResult - Encapsulates the result of a function along with the validity /// of that result, so that slow functions don't need to run twice struct CachedResult { @@ -54,7 +58,7 @@ struct EDInst { /// The containing MCInst llvm::MCInst *Inst; /// The instruction information provided by TableGen for this instruction - const InstInfo *ThisInstInfo; + const llvm::EDInstInfo *ThisInstInfo; /// The number of bytes for the machine code representation of the instruction uint64_t ByteSize; @@ -95,7 +99,7 @@ struct EDInst { EDInst(llvm::MCInst *inst, uint64_t byteSize, EDDisassembler &disassembler, - const InstInfo *instInfo); + const llvm::EDInstInfo *instInfo); ~EDInst(); /// byteSize - returns the number of bytes consumed by the machine code diff --git a/tools/edis/EDMain.cpp b/tools/edis/EDMain.cpp index 3585657ca6..b6ca32f2db 100644 --- a/tools/edis/EDMain.cpp +++ b/tools/edis/EDMain.cpp @@ -29,8 +29,7 @@ int EDGetDisassembler(EDDisassemblerRef *disassembler, if (ret) { *disassembler = ret; return 0; - } - else { + } else { return -1; } } @@ -39,7 +38,7 @@ int EDGetRegisterName(const char** regName, EDDisassemblerRef disassembler, unsigned regID) { const char* name = disassembler->nameWithRegisterID(regID); - if(!name) + if (!name) return -1; *regName = name; return 0; @@ -63,10 +62,10 @@ unsigned int EDCreateInsts(EDInstRef *insts, void *arg) { unsigned int index; - for (index = 0; index < count; index++) { + for (index = 0; index < count; ++index) { EDInst *inst = disassembler->createInst(byteReader, address, arg); - if(!inst) + if (!inst) return index; insts[index] = inst; @@ -134,42 +133,42 @@ int EDOperandIndexForToken(EDTokenRef token) { } int EDTokenIsWhitespace(EDTokenRef token) { - if(token->type() == EDToken::kTokenWhitespace) + if (token->type() == EDToken::kTokenWhitespace) return 1; else return 0; } int EDTokenIsPunctuation(EDTokenRef token) { - if(token->type() == EDToken::kTokenPunctuation) + if (token->type() == EDToken::kTokenPunctuation) return 1; else return 0; } int EDTokenIsOpcode(EDTokenRef token) { - if(token->type() == EDToken::kTokenOpcode) + if (token->type() == EDToken::kTokenOpcode) return 1; else return 0; } int EDTokenIsLiteral(EDTokenRef token) { - if(token->type() == EDToken::kTokenLiteral) + if (token->type() == EDToken::kTokenLiteral) return 1; else return 0; } int EDTokenIsRegister(EDTokenRef token) { - if(token->type() == EDToken::kTokenRegister) + if (token->type() == EDToken::kTokenRegister) return 1; else return 0; } int EDTokenIsNegativeLiteral(EDTokenRef token) { - if(token->type() != EDToken::kTokenLiteral) + if (token->type() != EDToken::kTokenLiteral) return -1; return token->literalSign(); @@ -177,7 +176,7 @@ int EDTokenIsNegativeLiteral(EDTokenRef token) { int EDLiteralTokenAbsoluteValue(uint64_t *value, EDTokenRef token) { - if(token->type() != EDToken::kTokenLiteral) + if (token->type() != EDToken::kTokenLiteral) return -1; return token->literalAbsoluteValue(*value); @@ -185,7 +184,7 @@ int EDLiteralTokenAbsoluteValue(uint64_t *value, int EDRegisterTokenValue(unsigned *registerID, EDTokenRef token) { - if(token->type() != EDToken::kTokenRegister) + if (token->type() != EDToken::kTokenRegister) return -1; return token->registerID(*registerID); @@ -215,7 +214,7 @@ int EDOperandIsMemory(EDOperandRef operand) { int EDRegisterOperandValue(unsigned *value, EDOperandRef operand) { - if(!operand->isRegister()) + if (!operand->isRegister()) return -1; *value = operand->regVal(); return 0; @@ -223,7 +222,7 @@ int EDRegisterOperandValue(unsigned *value, int EDImmediateOperandValue(uint64_t *value, EDOperandRef operand) { - if(!operand->isImmediate()) + if (!operand->isImmediate()) return -1; *value = operand->immediateVal(); return 0; diff --git a/tools/edis/EDOperand.cpp b/tools/edis/EDOperand.cpp index da6797e035..d63c1c6bfb 100644 --- a/tools/edis/EDOperand.cpp +++ b/tools/edis/EDOperand.cpp @@ -17,6 +17,7 @@ #include "EDInst.h" #include "EDOperand.h" +#include "llvm/MC/EDInstInfo.h" #include "llvm/MC/MCInst.h" using namespace llvm; @@ -31,26 +32,77 @@ EDOperand::EDOperand(const EDDisassembler &disassembler, MCOpIndex(mcOpIndex) { unsigned int numMCOperands = 0; - if(Disassembler.Key.Arch == Triple::x86 || - Disassembler.Key.Arch == Triple::x86_64) { - uint8_t operandFlags = inst.ThisInstInfo->operandFlags[opIndex]; + if (Disassembler.Key.Arch == Triple::x86 || + Disassembler.Key.Arch == Triple::x86_64) { + uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex]; - if (operandFlags & kOperandFlagImmediate) { + switch (operandType) { + default: + break; + case kOperandTypeImmediate: numMCOperands = 1; - } - else if (operandFlags & kOperandFlagRegister) { + break; + case kOperandTypeRegister: numMCOperands = 1; + break; + case kOperandTypeX86Memory: + numMCOperands = 5; + break; + case kOperandTypeX86EffectiveAddress: + numMCOperands = 4; + break; + case kOperandTypeX86PCRelative: + numMCOperands = 1; + break; } - else if (operandFlags & kOperandFlagMemory) { - if (operandFlags & kOperandFlagPCRelative) { - numMCOperands = 1; - } - else { - numMCOperands = 5; - } - } - else if (operandFlags & kOperandFlagEffectiveAddress) { + } + else if (Disassembler.Key.Arch == Triple::arm || + Disassembler.Key.Arch == Triple::thumb) { + uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex]; + + switch (operandType) { + default: + case kOperandTypeARMRegisterList: + break; + case kOperandTypeImmediate: + case kOperandTypeRegister: + case kOperandTypeARMBranchTarget: + case kOperandTypeARMSoImm: + case kOperandTypeThumb2SoImm: + case kOperandTypeARMSoImm2Part: + case kOperandTypeARMPredicate: + case kOperandTypeThumbITMask: + case kOperandTypeThumb2AddrModeImm8Offset: + case kOperandTypeARMTBAddrMode: + case kOperandTypeThumb2AddrModeImm8s4Offset: + numMCOperands = 1; + break; + case kOperandTypeThumb2SoReg: + case kOperandTypeARMAddrMode2Offset: + case kOperandTypeARMAddrMode3Offset: + case kOperandTypeARMAddrMode4: + case kOperandTypeARMAddrMode5: + case kOperandTypeARMAddrModePC: + case kOperandTypeThumb2AddrModeImm8: + case kOperandTypeThumb2AddrModeImm12: + case kOperandTypeThumb2AddrModeImm8s4: + case kOperandTypeThumbAddrModeRR: + case kOperandTypeThumbAddrModeSP: + numMCOperands = 2; + break; + case kOperandTypeARMSoReg: + case kOperandTypeARMAddrMode2: + case kOperandTypeARMAddrMode3: + case kOperandTypeThumb2AddrModeSoReg: + case kOperandTypeThumbAddrModeS1: + case kOperandTypeThumbAddrModeS2: + case kOperandTypeThumbAddrModeS4: + case kOperandTypeARMAddrMode6Offset: + numMCOperands = 3; + break; + case kOperandTypeARMAddrMode6: numMCOperands = 4; + break; } } @@ -63,70 +115,103 @@ EDOperand::~EDOperand() { int EDOperand::evaluate(uint64_t &result, EDRegisterReaderCallback callback, void *arg) { - if (Disassembler.Key.Arch == Triple::x86 || - Disassembler.Key.Arch == Triple::x86_64) { - uint8_t operandFlags = Inst.ThisInstInfo->operandFlags[OpIndex]; - - if (operandFlags & kOperandFlagImmediate) { + uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex]; + + switch (Disassembler.Key.Arch) { + default: + return -1; + case Triple::x86: + case Triple::x86_64: + switch (operandType) { + default: + return -1; + case kOperandTypeImmediate: result = Inst.Inst->getOperand(MCOpIndex).getImm(); return 0; - } - if (operandFlags & kOperandFlagRegister) { + case kOperandTypeRegister: + { unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg(); return callback(&result, reg, arg); } - if (operandFlags & kOperandFlagMemory || - operandFlags & kOperandFlagEffectiveAddress){ - if(operandFlags & kOperandFlagPCRelative) { - int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); + case kOperandTypeX86PCRelative: + { + int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); - uint64_t ripVal; + uint64_t ripVal; - // TODO fix how we do this + // TODO fix how we do this - if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg)) - return -1; + if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg)) + return -1; - result = ripVal + displacement; - return 0; - } - else { - unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg(); - uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm(); - unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg(); - int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm(); - //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg(); + result = ripVal + displacement; + return 0; + } + case kOperandTypeX86Memory: + case kOperandTypeX86EffectiveAddress: + { + unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg(); + uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm(); + unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg(); + int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm(); + //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg(); - uint64_t addr = 0; + uint64_t addr = 0; - if(baseReg) { - uint64_t baseVal; - if (callback(&baseVal, baseReg, arg)) - return -1; - addr += baseVal; - } - - if(indexReg) { - uint64_t indexVal; - if (callback(&indexVal, indexReg, arg)) - return -1; - addr += (scaleAmount * indexVal); - } - - addr += displacement; + if (baseReg) { + uint64_t baseVal; + if (callback(&baseVal, baseReg, arg)) + return -1; + addr += baseVal; + } - result = addr; - return 0; + if (indexReg) { + uint64_t indexVal; + if (callback(&indexVal, indexReg, arg)) + return -1; + addr += (scaleAmount * indexVal); } + + addr += displacement; + + result = addr; + return 0; + } + } + break; + case Triple::arm: + case Triple::thumb: + switch (operandType) { + default: + return -1; + case kOperandTypeImmediate: + result = Inst.Inst->getOperand(MCOpIndex).getImm(); + return 0; + case kOperandTypeRegister: + { + unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg(); + return callback(&result, reg, arg); + } + case kOperandTypeARMBranchTarget: + { + int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); + + uint64_t pcVal; + + if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg)) + return -1; + + result = pcVal + displacement; + return 0; + } } - return -1; } return -1; } int EDOperand::isRegister() { - return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagRegister); + return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister); } unsigned EDOperand::regVal() { @@ -134,7 +219,7 @@ unsigned EDOperand::regVal() { } int EDOperand::isImmediate() { - return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagImmediate); + return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate); } uint64_t EDOperand::immediateVal() { @@ -142,7 +227,38 @@ uint64_t EDOperand::immediateVal() { } int EDOperand::isMemory() { - return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagMemory); + uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex]; + + switch (operandType) { + default: + return 0; + case kOperandTypeX86Memory: + case kOperandTypeX86PCRelative: + case kOperandTypeX86EffectiveAddress: + case kOperandTypeARMSoReg: + case kOperandTypeARMSoImm: + case kOperandTypeARMAddrMode2: + case kOperandTypeARMAddrMode2Offset: + case kOperandTypeARMAddrMode3: + case kOperandTypeARMAddrMode3Offset: + case kOperandTypeARMAddrMode4: + case kOperandTypeARMAddrMode5: + case kOperandTypeARMAddrMode6: + case kOperandTypeARMAddrModePC: + case kOperandTypeARMBranchTarget: + case kOperandTypeThumbAddrModeS1: + case kOperandTypeThumbAddrModeS2: + case kOperandTypeThumbAddrModeS4: + case kOperandTypeThumbAddrModeRR: + case kOperandTypeThumbAddrModeSP: + case kOperandTypeThumb2SoImm: + case kOperandTypeThumb2AddrModeImm8: + case kOperandTypeThumb2AddrModeImm8Offset: + case kOperandTypeThumb2AddrModeImm12: + case kOperandTypeThumb2AddrModeSoReg: + case kOperandTypeThumb2AddrModeImm8s4: + return 1; + } } #ifdef __BLOCKS__ diff --git a/tools/edis/EDToken.cpp b/tools/edis/EDToken.cpp index cd79152e35..3bcb0a14b8 100644 --- a/tools/edis/EDToken.cpp +++ b/tools/edis/EDToken.cpp @@ -68,20 +68,20 @@ int EDToken::operandID() const { } int EDToken::literalSign() const { - if(Type != kTokenLiteral) + if (Type != kTokenLiteral) return -1; return (LiteralSign ? 1 : 0); } int EDToken::literalAbsoluteValue(uint64_t &value) const { - if(Type != kTokenLiteral) + if (Type != kTokenLiteral) return -1; value = LiteralAbsoluteValue; return 0; } int EDToken::registerID(unsigned ®isterID) const { - if(Type != kTokenRegister) + if (Type != kTokenRegister) return -1; registerID = RegisterID; return 0; @@ -94,7 +94,7 @@ int EDToken::tokenize(std::vector<EDToken*> &tokens, SmallVector<MCParsedAsmOperand*, 5> parsedOperands; SmallVector<AsmToken, 10> asmTokens; - if(disassembler.parseInst(parsedOperands, asmTokens, str)) + if (disassembler.parseInst(parsedOperands, asmTokens, str)) return -1; SmallVectorImpl<MCParsedAsmOperand*>::iterator operandIterator; @@ -115,7 +115,7 @@ int EDToken::tokenize(std::vector<EDToken*> &tokens, const char *tokenPointer = tokenLoc.getPointer(); - if(tokenPointer > wsPointer) { + if (tokenPointer > wsPointer) { unsigned long wsLength = tokenPointer - wsPointer; EDToken *whitespaceToken = new EDToken(StringRef(wsPointer, wsLength), @@ -164,7 +164,7 @@ int EDToken::tokenize(std::vector<EDToken*> &tokens, int64_t intVal = tokenIterator->getIntVal(); - if(intVal < 0) + if (intVal < 0) token->makeLiteral(true, -intVal); else token->makeLiteral(false, intVal); @@ -182,14 +182,14 @@ int EDToken::tokenize(std::vector<EDToken*> &tokens, } } - if(operandIterator != parsedOperands.end() && + if (operandIterator != parsedOperands.end() && tokenLoc.getPointer() >= (*operandIterator)->getStartLoc().getPointer()) { /// operandIndex == 0 means the operand is the instruction (which the /// AsmParser treats as an operand but edis does not). We therefore skip /// operandIndex == 0 and subtract 1 from all other operand indices. - if(operandIndex > 0) + if (operandIndex > 0) token->setOperandID(operandOrder[operandIndex - 1]); } @@ -200,7 +200,7 @@ int EDToken::tokenize(std::vector<EDToken*> &tokens, } int EDToken::getString(const char*& buf) { - if(PermStr.length() == 0) { + if (PermStr.length() == 0) { PermStr = Str.str(); } buf = PermStr.c_str(); diff --git a/tools/edis/EnhancedDisassembly.exports b/tools/edis/EnhancedDisassembly.exports index d3f87435cc..7050f7f329 100644 --- a/tools/edis/EnhancedDisassembly.exports +++ b/tools/edis/EnhancedDisassembly.exports @@ -1,36 +1,36 @@ -_EDGetDisassembler -_EDGetRegisterName -_EDRegisterIsStackPointer -_EDRegisterIsProgramCounter -_EDCreateInsts -_EDReleaseInst -_EDInstByteSize -_EDGetInstString -_EDInstIsBranch -_EDInstIsMove -_EDBranchTargetID -_EDMoveSourceID -_EDMoveTargetID -_EDNumTokens -_EDGetToken -_EDGetTokenString -_EDOperandIndexForToken -_EDTokenIsWhitespace -_EDTokenIsPunctuation -_EDTokenIsOpcode -_EDTokenIsLiteral -_EDTokenIsRegister -_EDTokenIsNegativeLiteral -_EDLiteralTokenAbsoluteValue -_EDRegisterTokenValue -_EDNumOperands -_EDGetOperand -_EDOperandIsRegister -_EDOperandIsImmediate -_EDOperandIsMemory -_EDRegisterOperandValue -_EDImmediateOperandValue -_EDEvaluateOperand -_EDBlockCreateInsts -_EDBlockEvaluateOperand -_EDBlockVisitTokens +EDGetDisassembler +EDGetRegisterName +EDRegisterIsStackPointer +EDRegisterIsProgramCounter +EDCreateInsts +EDReleaseInst +EDInstByteSize +EDGetInstString +EDInstIsBranch +EDInstIsMove +EDBranchTargetID +EDMoveSourceID +EDMoveTargetID +EDNumTokens +EDGetToken +EDGetTokenString +EDOperandIndexForToken +EDTokenIsWhitespace +EDTokenIsPunctuation +EDTokenIsOpcode +EDTokenIsLiteral +EDTokenIsRegister +EDTokenIsNegativeLiteral +EDLiteralTokenAbsoluteValue +EDRegisterTokenValue +EDNumOperands +EDGetOperand +EDOperandIsRegister +EDOperandIsImmediate +EDOperandIsMemory +EDRegisterOperandValue +EDImmediateOperandValue +EDEvaluateOperand +EDBlockCreateInsts +EDBlockEvaluateOperand +EDBlockVisitTokens diff --git a/tools/edis/Makefile b/tools/edis/Makefile index a3c5879668..9151f627bb 100644 --- a/tools/edis/Makefile +++ b/tools/edis/Makefile @@ -12,38 +12,41 @@ LIBRARYNAME = EnhancedDisassembly BUILT_SOURCES = EDInfo.inc +EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/EnhancedDisassembly.exports + # Include this here so we can get the configuration of the targets # that have been configured for construction. We have to do this # early so we can set up LINK_COMPONENTS before including Makefile.rules include $(LEVEL)/Makefile.config -LINK_LIBS_IN_SHARED = 1 -SHARED_LIBRARY = 1 +ifeq ($(ENABLE_PIC),1) + ifneq ($(TARGET_OS), $(filter $(TARGET_OS), Cygwin MingW)) + LINK_LIBS_IN_SHARED = 1 + SHARED_LIBRARY = 1 + endif +endif LINK_COMPONENTS := $(TARGETS_TO_BUILD) x86asmprinter x86disassembler include $(LEVEL)/Makefile.common ifeq ($(HOST_OS),Darwin) - # set dylib internal version number to llvmCore submission number - ifdef LLVM_SUBMIT_VERSION - LLVMLibsOptions := $(LLVMLibsOptions) -Wl,-current_version \ - -Wl,$(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION) \ - -Wl,-compatibility_version -Wl,1 - endif # extra options to override libtool defaults LLVMLibsOptions := $(LLVMLibsOptions) \ -avoid-version \ - -Wl,-exported_symbols_list -Wl,$(PROJ_SRC_DIR)/EnhancedDisassembly.exports \ - -Wl,-dead_strip \ - -Wl,-seg1addr -Wl,0xE0000000 + -Wl,-dead_strip + + ifdef EDIS_VERSION + LLVMLibsOptions := $(LLVMLibsOptions) -Wl,-current_version -Wl,$(EDIS_VERSION) \ + -Wl,-compatibility_version -Wl,1 + endif # Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/') ifneq ($(DARWIN_VERS),8) LLVMLibsOptions := $(LLVMLibsOptions) \ -no-undefined -Wl,-install_name \ - -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)" + -Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)" endif endif diff --git a/tools/gold/Makefile b/tools/gold/Makefile index 7bac4ec62d..77eacb7ee5 100644 --- a/tools/gold/Makefile +++ b/tools/gold/Makefile @@ -10,6 +10,8 @@ LEVEL = ../.. LIBRARYNAME = libLLVMgold +EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/gold.exports + # Include this here so we can get the configuration of the targets # that have been configured for construction. We have to do this # early so we can set up LINK_COMPONENTS before including Makefile.rules diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 0e1db1bf2e..16e645f8da 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -58,16 +58,16 @@ namespace { } namespace options { - bool generate_api_file = false; - const char *as_path = NULL; + static bool generate_api_file = false; + static const char *as_path = NULL; // Additional options to pass into the code generator. // Note: This array will contain all plugin options which are not claimed // as plugin exclusive to pass to the code generator. // For example, "generate-api-file" and "as"options are for the plugin // use only and will not be passed. - std::vector<std::string> extra; + static std::vector<std::string> extra; - void process_plugin_option(const char* opt) + static void process_plugin_option(const char* opt) { if (opt == NULL) return; @@ -88,10 +88,10 @@ namespace options { } } -ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, - int *claimed); -ld_plugin_status all_symbols_read_hook(void); -ld_plugin_status cleanup_hook(void); +static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, + int *claimed); +static ld_plugin_status all_symbols_read_hook(void); +static ld_plugin_status cleanup_hook(void); extern "C" ld_plugin_status onload(ld_plugin_tv *tv); ld_plugin_status onload(ld_plugin_tv *tv) { @@ -192,8 +192,8 @@ ld_plugin_status onload(ld_plugin_tv *tv) { /// claim_file_hook - called by gold to see whether this file is one that /// our plugin can handle. We'll try to open it and register all the symbols /// with add_symbol if possible. -ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, - int *claimed) { +static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, + int *claimed) { void *buf = NULL; if (file->offset) { // Gold has found what might be IR part-way inside of a file, such as @@ -316,7 +316,7 @@ ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, /// At this point, we use get_symbols to see if any of our definitions have /// been overridden by a native object file. Then, perform optimization and /// codegen. -ld_plugin_status all_symbols_read_hook(void) { +static ld_plugin_status all_symbols_read_hook(void) { lto_code_gen_t cg = lto_codegen_create(); for (std::list<claimed_file>::iterator I = Modules.begin(), @@ -340,9 +340,7 @@ ld_plugin_status all_symbols_read_hook(void) { E = Modules.end(); I != E; ++I) { (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]); for (unsigned i = 0, e = I->syms.size(); i != e; i++) { - if (I->syms[i].resolution == LDPR_PREVAILING_DEF || - (I->syms[i].def == LDPK_COMMON && - I->syms[i].resolution == LDPR_RESOLVED_IR)) { + if (I->syms[i].resolution == LDPR_PREVAILING_DEF) { lto_codegen_add_must_preserve_symbol(cg, I->syms[i].name); anySymbolsPreserved = true; @@ -387,7 +385,7 @@ ld_plugin_status all_symbols_read_hook(void) { (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); return LDPS_ERR; } - raw_fd_ostream *objFile = + raw_fd_ostream *objFile = new raw_fd_ostream(uniqueObjPath.c_str(), ErrMsg, raw_fd_ostream::F_Binary); if (!ErrMsg.empty()) { @@ -412,7 +410,7 @@ ld_plugin_status all_symbols_read_hook(void) { return LDPS_OK; } -ld_plugin_status cleanup_hook(void) { +static ld_plugin_status cleanup_hook(void) { std::string ErrMsg; for (int i = 0, e = Cleanup.size(); i != e; ++i) diff --git a/tools/gold/gold.exports b/tools/gold/gold.exports new file mode 100644 index 0000000000..277a33a1ec --- /dev/null +++ b/tools/gold/gold.exports @@ -0,0 +1 @@ +onload diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 810ba42200..dccfb26e74 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -23,13 +23,10 @@ #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" #include "llvm/Config/config.h" -#include "llvm/LinkAllVMCore.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/FileUtilities.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/System/Host.h" @@ -39,7 +36,6 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetSelect.h" -#include "llvm/Transforms/Scalar.h" #include <memory> using namespace llvm; @@ -218,6 +214,7 @@ int main(int argc, char **argv) { // Initialize targets first, so that --version shows registered targets. InitializeAllTargets(); InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 81c17cd8fc..4e3e07ffd2 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -192,7 +192,7 @@ int main(int argc, char **argv, char * const *envp) { } else { // Otherwise, if there is a .bc suffix on the executable strip it off, it // might confuse the program. - if (InputFile.rfind(".bc") == InputFile.length() - 3) + if (StringRef(InputFile).endswith(".bc")) InputFile.erase(InputFile.length() - 3); } diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 6d5b2b51a8..732ff11fe4 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -237,6 +237,8 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::FUNC_CODE_INST_INSERTVAL: return "INST_INSERTVAL"; case bitc::FUNC_CODE_INST_CMP2: return "INST_CMP2"; case bitc::FUNC_CODE_INST_VSELECT: return "INST_VSELECT"; + case bitc::FUNC_CODE_DEBUG_LOC: return "DEBUG_LOC"; + case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: return "DEBUG_LOC_AGAIN"; } case bitc::TYPE_SYMTAB_BLOCK_ID: switch (CodeID) { @@ -259,9 +261,11 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, default:return 0; case bitc::METADATA_STRING: return "MDSTRING"; case bitc::METADATA_NODE: return "MDNODE"; + case bitc::METADATA_FN_NODE: return "FN_MDNODE"; case bitc::METADATA_NAME: return "METADATA_NAME"; case bitc::METADATA_NAMED_NODE: return "NAMEDMDNODE"; case bitc::METADATA_KIND: return "METADATA_KIND"; + case bitc::METADATA_ATTACHMENT: return "METADATA_ATTACHMENT"; } } } diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index 231634c84b..276dfd638b 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -22,7 +22,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/SystemUtils.h" diff --git a/tools/llvm-ld/Optimize.cpp b/tools/llvm-ld/Optimize.cpp index 6143dc87d3..3fb0079dfe 100644 --- a/tools/llvm-ld/Optimize.cpp +++ b/tools/llvm-ld/Optimize.cpp @@ -13,17 +13,12 @@ #include "llvm/Module.h" #include "llvm/PassManager.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Verifier.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/DynamicLibrary.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Scalar.h" #include "llvm/Support/PassNameParser.h" #include "llvm/Support/PluginLoader.h" using namespace llvm; diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp index 118f6b720c..ce52b59f0d 100644 --- a/tools/llvm-ld/llvm-ld.cpp +++ b/tools/llvm-ld/llvm-ld.cpp @@ -125,13 +125,18 @@ static cl::opt<std::string> CO9("m", cl::Hidden, /// everywhere. static std::string progname; +/// FileRemover objects to clean up output files in the event of an error. +static FileRemover OutputRemover; +static FileRemover BitcodeOutputRemover; + /// PrintAndExit - Prints a message to standard error and exits with error code /// /// Inputs: /// Message - The message to print to standard error. /// -static void PrintAndExit(const std::string &Message, int errcode = 1) { +static void PrintAndExit(const std::string &Message, Module *M, int errcode = 1) { errs() << progname << ": " << Message << "\n"; + delete M; llvm_shutdown(); exit(errcode); } @@ -234,17 +239,10 @@ void GenerateBitcode(Module* M, const std::string& FileName) { raw_fd_ostream Out(FileName.c_str(), ErrorInfo, raw_fd_ostream::F_Binary); if (!ErrorInfo.empty()) - PrintAndExit(ErrorInfo); - - // Ensure that the bitcode file gets removed from the disk if we get a - // terminating signal. - sys::RemoveFileOnSignal(sys::Path(FileName)); + PrintAndExit(ErrorInfo, M); // Write it out WriteBitcodeToFile(M, Out); - - // Close the bitcode file. - Out.close(); } /// GenerateAssembly - generates a native assembly language source file from the @@ -401,14 +399,14 @@ static int GenerateNative(const std::string &OutputFilename, // Run the compiler to assembly and link together the program. int R = sys::Program::ExecuteAndWait( - gcc, &Args[0], (const char**)clean_env, 0, 0, 0, &ErrMsg); + gcc, &Args[0], const_cast<const char **>(clean_env), 0, 0, 0, &ErrMsg); delete [] clean_env; return R; } /// EmitShellScript - Output the wrapper file that invokes the JIT on the LLVM /// bitcode file for the program. -static void EmitShellScript(char **argv) { +static void EmitShellScript(char **argv, Module *M) { if (Verbose) outs() << "Emitting Shell Script\n"; #if defined(_WIN32) || defined(__CYGWIN__) @@ -419,10 +417,10 @@ static void EmitShellScript(char **argv) { sys::Path llvmstub = FindExecutable("llvm-stub.exe", argv[0], (void *)(intptr_t)&Optimize); if (llvmstub.isEmpty()) - PrintAndExit("Could not find llvm-stub.exe executable!"); + PrintAndExit("Could not find llvm-stub.exe executable!", M); if (0 != sys::CopyFile(sys::Path(OutputFilename), llvmstub, &ErrMsg)) - PrintAndExit(ErrMsg); + PrintAndExit(ErrMsg, M); return; #endif @@ -431,7 +429,7 @@ static void EmitShellScript(char **argv) { std::string ErrorInfo; raw_fd_ostream Out2(OutputFilename.c_str(), ErrorInfo); if (!ErrorInfo.empty()) - PrintAndExit(ErrorInfo); + PrintAndExit(ErrorInfo, M); Out2 << "#!/bin/sh\n"; // Allow user to setenv LLVMINTERP if lli is not in their PATH. @@ -470,7 +468,6 @@ static void EmitShellScript(char **argv) { Out2 << " -load=" << FullLibraryPath.str() << " \\\n"; } Out2 << " " << BitcodeOutputFilename << " ${1+\"$@\"}\n"; - Out2.close(); } // BuildLinkItems -- This function generates a LinkItemList for the LinkItems @@ -521,6 +518,39 @@ int main(int argc, char **argv, char **envp) { // Parse the command line options cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); +#if defined(_WIN32) || defined(__CYGWIN__) + if (!LinkAsLibrary) { + // Default to "a.exe" instead of "a.out". + if (OutputFilename.getNumOccurrences() == 0) + OutputFilename = "a.exe"; + + // If there is no suffix add an "exe" one. + sys::Path ExeFile( OutputFilename ); + if (ExeFile.getSuffix() == "") { + ExeFile.appendSuffix("exe"); + OutputFilename = ExeFile.str(); + } + } +#endif + + // Generate the bitcode for the optimized module. + // If -b wasn't specified, use the name specified + // with -o to construct BitcodeOutputFilename. + if (BitcodeOutputFilename.empty()) { + BitcodeOutputFilename = OutputFilename; + if (!LinkAsLibrary) BitcodeOutputFilename += ".bc"; + } + + // Arrange for the bitcode output file to be deleted on any errors. + BitcodeOutputRemover.setFile(sys::Path(BitcodeOutputFilename)); + sys::RemoveFileOnSignal(sys::Path(BitcodeOutputFilename)); + + // Arrange for the output file to be deleted on any errors. + if (!LinkAsLibrary) { + OutputRemover.setFile(sys::Path(OutputFilename)); + sys::RemoveFileOnSignal(sys::Path(OutputFilename)); + } + // Construct a Linker (now that Verbose is set) Linker TheLinker(progname, OutputFilename, Context, Verbose); @@ -563,29 +593,7 @@ int main(int argc, char **argv, char **envp) { // Optimize the module Optimize(Composite.get()); -#if defined(_WIN32) || defined(__CYGWIN__) - if (!LinkAsLibrary) { - // Default to "a.exe" instead of "a.out". - if (OutputFilename.getNumOccurrences() == 0) - OutputFilename = "a.exe"; - - // If there is no suffix add an "exe" one. - sys::Path ExeFile( OutputFilename ); - if (ExeFile.getSuffix() == "") { - ExeFile.appendSuffix("exe"); - OutputFilename = ExeFile.str(); - } - } -#endif - - // Generate the bitcode for the optimized module. - // If -b wasn't specified, use the name specified - // with -o to construct BitcodeOutputFilename. - if (BitcodeOutputFilename.empty()) { - BitcodeOutputFilename = OutputFilename; - if (!LinkAsLibrary) BitcodeOutputFilename += ".bc"; - } - + // Generate the bitcode output. GenerateBitcode(Composite.get(), BitcodeOutputFilename); // If we are not linking a library, generate either a native executable @@ -601,13 +609,13 @@ int main(int argc, char **argv, char **envp) { prog = sys::Program::FindProgramByName(*I); if (prog.isEmpty()) PrintAndExit(std::string("Optimization program '") + *I + - "' is not found or not executable."); + "' is not found or not executable.", Composite.get()); } // Get the program arguments sys::Path tmp_output("opt_result"); std::string ErrMsg; if (tmp_output.createTemporaryFileOnDisk(true, &ErrMsg)) - PrintAndExit(ErrMsg); + PrintAndExit(ErrMsg, Composite.get()); const char* args[4]; args[0] = I->c_str(); @@ -615,15 +623,16 @@ int main(int argc, char **argv, char **envp) { args[2] = tmp_output.c_str(); args[3] = 0; if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0,0, &ErrMsg)) { - if (tmp_output.isBitcodeFile() || tmp_output.isBitcodeFile()) { + if (tmp_output.isBitcodeFile()) { sys::Path target(BitcodeOutputFilename); target.eraseFromDisk(); if (tmp_output.renamePathOnDisk(target, &ErrMsg)) - PrintAndExit(ErrMsg, 2); + PrintAndExit(ErrMsg, Composite.get(), 2); } else - PrintAndExit("Post-link optimization output is not bitcode"); + PrintAndExit("Post-link optimization output is not bitcode", + Composite.get()); } else { - PrintAndExit(ErrMsg); + PrintAndExit(ErrMsg, Composite.get()); } } } @@ -637,79 +646,77 @@ int main(int argc, char **argv, char **envp) { sys::Path AssemblyFile ( OutputFilename); AssemblyFile.appendSuffix("s"); - // Mark the output files for removal if we get an interrupt. + // Mark the output files for removal. + FileRemover AssemblyFileRemover(AssemblyFile); sys::RemoveFileOnSignal(AssemblyFile); - sys::RemoveFileOnSignal(sys::Path(OutputFilename)); // Determine the locations of the llc and gcc programs. sys::Path llc = FindExecutable("llc", argv[0], (void *)(intptr_t)&Optimize); if (llc.isEmpty()) - PrintAndExit("Failed to find llc"); + PrintAndExit("Failed to find llc", Composite.get()); sys::Path gcc = sys::Program::FindProgramByName("gcc"); if (gcc.isEmpty()) - PrintAndExit("Failed to find gcc"); + PrintAndExit("Failed to find gcc", Composite.get()); // Generate an assembly language file for the bitcode. std::string ErrMsg; if (0 != GenerateAssembly(AssemblyFile.str(), BitcodeOutputFilename, llc, ErrMsg)) - PrintAndExit(ErrMsg); + PrintAndExit(ErrMsg, Composite.get()); if (0 != GenerateNative(OutputFilename, AssemblyFile.str(), NativeLinkItems, gcc, envp, ErrMsg)) - PrintAndExit(ErrMsg); - - // Remove the assembly language file. - AssemblyFile.eraseFromDisk(); + PrintAndExit(ErrMsg, Composite.get()); } else if (NativeCBE) { sys::Path CFile (OutputFilename); CFile.appendSuffix("cbe.c"); - // Mark the output files for removal if we get an interrupt. + // Mark the output files for removal. + FileRemover CFileRemover(CFile); sys::RemoveFileOnSignal(CFile); - sys::RemoveFileOnSignal(sys::Path(OutputFilename)); // Determine the locations of the llc and gcc programs. sys::Path llc = FindExecutable("llc", argv[0], (void *)(intptr_t)&Optimize); if (llc.isEmpty()) - PrintAndExit("Failed to find llc"); + PrintAndExit("Failed to find llc", Composite.get()); sys::Path gcc = sys::Program::FindProgramByName("gcc"); if (gcc.isEmpty()) - PrintAndExit("Failed to find gcc"); + PrintAndExit("Failed to find gcc", Composite.get()); // Generate an assembly language file for the bitcode. std::string ErrMsg; if (GenerateCFile(CFile.str(), BitcodeOutputFilename, llc, ErrMsg)) - PrintAndExit(ErrMsg); + PrintAndExit(ErrMsg, Composite.get()); if (GenerateNative(OutputFilename, CFile.str(), NativeLinkItems, gcc, envp, ErrMsg)) - PrintAndExit(ErrMsg); - - // Remove the assembly language file. - CFile.eraseFromDisk(); - + PrintAndExit(ErrMsg, Composite.get()); } else { - EmitShellScript(argv); + EmitShellScript(argv, Composite.get()); } // Make the script executable... std::string ErrMsg; if (sys::Path(OutputFilename).makeExecutableOnDisk(&ErrMsg)) - PrintAndExit(ErrMsg); + PrintAndExit(ErrMsg, Composite.get()); // Make the bitcode file readable and directly executable in LLEE as well if (sys::Path(BitcodeOutputFilename).makeExecutableOnDisk(&ErrMsg)) - PrintAndExit(ErrMsg); + PrintAndExit(ErrMsg, Composite.get()); if (sys::Path(BitcodeOutputFilename).makeReadableOnDisk(&ErrMsg)) - PrintAndExit(ErrMsg); + PrintAndExit(ErrMsg, Composite.get()); } + // Operations which may fail are now complete. + BitcodeOutputRemover.releaseFile(); + if (!LinkAsLibrary) + OutputRemover.releaseFile(); + // Graceful exit return 0; } diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index fae4d107b1..c60e56ae9b 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -19,7 +19,6 @@ #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/SystemUtils.h" diff --git a/tools/llvm-mc/CMakeLists.txt b/tools/llvm-mc/CMakeLists.txt index 49c29324d4..8b61a4e8db 100644 --- a/tools/llvm-mc/CMakeLists.txt +++ b/tools/llvm-mc/CMakeLists.txt @@ -1,3 +1,4 @@ +set( LLVM_USED_LIBS EnhancedDisassembly) set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC MCParser) add_llvm_tool(llvm-mc diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index dbfe7a5d06..9234a14bc1 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -15,6 +15,7 @@ #include "Disassembler.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" @@ -24,6 +25,9 @@ #include "llvm/Support/MemoryObject.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/SourceMgr.h" + +#include "llvm-c/EnhancedDisassembly.h" + using namespace llvm; typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy; @@ -47,9 +51,9 @@ public: }; } -static bool PrintInsts(const llvm::MCDisassembler &DisAsm, - llvm::MCInstPrinter &Printer, const ByteArrayTy &Bytes, - SourceMgr &SM) { +static bool PrintInsts(const MCDisassembler &DisAsm, + MCInstPrinter &Printer, const ByteArrayTy &Bytes, + SourceMgr &SM) { // Wrap the vector in a MemoryObject. VectorMemoryObject memoryObject(Bytes); @@ -62,10 +66,9 @@ static bool PrintInsts(const llvm::MCDisassembler &DisAsm, if (DisAsm.getInstruction(Inst, Size, memoryObject, Index, /*REMOVE*/ nulls())) { - Printer.printInst(&Inst); + Printer.printInst(&Inst, outs()); outs() << "\n"; - } - else { + } else { SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), "invalid instruction encoding", "warning"); if (Size == 0) @@ -76,38 +79,9 @@ static bool PrintInsts(const llvm::MCDisassembler &DisAsm, return false; } -int Disassembler::disassemble(const Target &T, const std::string &Triple, - MemoryBuffer &Buffer) { - // Set up disassembler. - llvm::OwningPtr<const llvm::MCAsmInfo> AsmInfo(T.createAsmInfo(Triple)); - - if (!AsmInfo) { - errs() << "error: no assembly info for target " << Triple << "\n"; - return -1; - } - - llvm::OwningPtr<const llvm::MCDisassembler> DisAsm(T.createMCDisassembler()); - if (!DisAsm) { - errs() << "error: no disassembler for target " << Triple << "\n"; - return -1; - } - - llvm::MCInstPrinter *InstPrinter = T.createMCInstPrinter(0, *AsmInfo, outs()); - - if (!InstPrinter) { - errs() << "error: no instruction printer for target " << Triple << '\n'; - return -1; - } - - bool ErrorOccurred = false; - - SourceMgr SM; - SM.AddNewSourceBuffer(&Buffer, SMLoc()); - - // Convert the input to a vector for disassembly. - ByteArrayTy ByteArray; - - StringRef Str = Buffer.getBuffer(); +static bool ByteArrayFromString(ByteArrayTy &ByteArray, + StringRef &Str, + SourceMgr &SM) { while (!Str.empty()) { // Strip horizontal whitespace. if (size_t Pos = Str.find_first_not_of(" \t\r")) { @@ -120,9 +94,9 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, if (Str[0] == '\n' || Str[0] == '#') { // Strip to the end of line if we already processed any bytes on this // line. This strips the comment and/or the \n. - if (Str[0] == '\n') + if (Str[0] == '\n') { Str = Str.substr(1); - else { + } else { Str = Str.substr(Str.find_first_of('\n')); if (!Str.empty()) Str = Str.substr(1); @@ -139,8 +113,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) { // If we have an error, print it and skip to the end of line. SM.PrintMessage(SMLoc::getFromPointer(Value.data()), - "invalid input token", "error"); - ErrorOccurred = true; + "invalid input token", "error"); Str = Str.substr(Str.find('\n')); ByteArray.clear(); continue; @@ -150,8 +123,231 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, Str = Str.substr(Next); } + return false; +} + +int Disassembler::disassemble(const Target &T, const std::string &Triple, + MemoryBuffer &Buffer) { + // Set up disassembler. + OwningPtr<const MCAsmInfo> AsmInfo(T.createAsmInfo(Triple)); + + if (!AsmInfo) { + errs() << "error: no assembly info for target " << Triple << "\n"; + return -1; + } + + OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler()); + if (!DisAsm) { + errs() << "error: no disassembler for target " << Triple << "\n"; + return -1; + } + + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, + *AsmInfo)); + if (!IP) { + errs() << "error: no instruction printer for target " << Triple << '\n'; + return -1; + } + + bool ErrorOccurred = false; + + SourceMgr SM; + SM.AddNewSourceBuffer(&Buffer, SMLoc()); + + // Convert the input to a vector for disassembly. + ByteArrayTy ByteArray; + StringRef Str = Buffer.getBuffer(); + + ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); + if (!ByteArray.empty()) - ErrorOccurred |= PrintInsts(*DisAsm, *InstPrinter, ByteArray, SM); + ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM); return ErrorOccurred; } + +static int byteArrayReader(uint8_t *B, uint64_t A, void *Arg) { + ByteArrayTy &ByteArray = *((ByteArrayTy*)Arg); + + if (A >= ByteArray.size()) + return -1; + + *B = ByteArray[A].first; + + return 0; +} + +static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) { + EDDisassemblerRef &disassembler = *((EDDisassemblerRef*)Arg); + + const char *regName; + + if (!EDGetRegisterName(®Name, + disassembler, + R)) + outs() << "[" << regName << "/" << R << "]"; + if (EDRegisterIsStackPointer(disassembler, R)) + outs() << "(sp)"; + if (EDRegisterIsProgramCounter(disassembler, R)) + outs() << "(pc)"; + + *V = 0; + + return 0; +} + +int Disassembler::disassembleEnhanced(const std::string &TS, + MemoryBuffer &Buffer) { + ByteArrayTy ByteArray; + StringRef Str = Buffer.getBuffer(); + SourceMgr SM; + + SM.AddNewSourceBuffer(&Buffer, SMLoc()); + + if (ByteArrayFromString(ByteArray, Str, SM)) { + return -1; + } + + EDDisassemblerRef disassembler; + + Triple T(TS); + EDAssemblySyntax_t AS; + + switch (T.getArch()) { + default: + errs() << "error: no default assembly syntax for " << TS.c_str() << "\n"; + return -1; + case Triple::arm: + case Triple::thumb: + AS = kEDAssemblySyntaxARMUAL; + break; + case Triple::x86: + case Triple::x86_64: + AS = kEDAssemblySyntaxX86ATT; + break; + } + + if (EDGetDisassembler(&disassembler, + TS.c_str(), + AS)) { + errs() << "error: couldn't get disassembler for " << TS.c_str() << "\n"; + return -1; + } + + EDInstRef inst; + + if (EDCreateInsts(&inst, 1, disassembler, byteArrayReader, 0,&ByteArray) + != 1) { + errs() << "error: Didn't get an instruction\n"; + return -1; + } + + int numTokens = EDNumTokens(inst); + + if (numTokens < 0) { + errs() << "error: Couldn't count the instruction's tokens\n"; + return -1; + } + + int tokenIndex; + + for (tokenIndex = 0; tokenIndex < numTokens; ++tokenIndex) { + EDTokenRef token; + + if (EDGetToken(&token, inst, tokenIndex)) { + errs() << "error: Couldn't get token\n"; + return -1; + } + + const char *buf; + + if (EDGetTokenString(&buf, token)) { + errs() << "error: Couldn't get string for token\n"; + return -1; + } + + outs() << "["; + + int operandIndex = EDOperandIndexForToken(token); + + if (operandIndex >= 0) + outs() << operandIndex << "-"; + + if (EDTokenIsWhitespace(token)) { + outs() << "w"; + } else if (EDTokenIsPunctuation(token)) { + outs() << "p"; + } else if (EDTokenIsOpcode(token)) { + outs() << "o"; + } else if (EDTokenIsLiteral(token)) { + outs() << "l"; + } else if (EDTokenIsRegister(token)) { + outs() << "r"; + } else { + outs() << "?"; + } + + outs() << ":" << buf; + + if (EDTokenIsLiteral(token)) { + outs() << "="; + if (EDTokenIsNegativeLiteral(token)) + outs() << "-"; + uint64_t absoluteValue; + if (EDLiteralTokenAbsoluteValue(&absoluteValue, token)) { + errs() << "error: Couldn't get the value of a literal token\n"; + return -1; + } + outs() << absoluteValue; + } else if (EDTokenIsRegister(token)) { + outs() << "="; + unsigned regID; + if (EDRegisterTokenValue(®ID, token)) { + errs() << "error: Couldn't get the ID of a register token\n"; + return -1; + } + outs() << "r" << regID; + } + + outs() << "]"; + } + + outs() << " "; + + int numOperands = EDNumOperands(inst); + + if (numOperands < 0) { + errs() << "error: Couldn't count operands\n"; + return -1; + } + + int operandIndex; + + for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + outs() << operandIndex << ":"; + + EDOperandRef operand; + + if (EDGetOperand(&operand, + inst, + operandIndex)) { + errs() << "error: Couldn't get operand\n"; + return -1; + } + + uint64_t evaluatedResult; + + EDEvaluateOperand(&evaluatedResult, + operand, + verboseEvaluator, + &disassembler); + + outs() << " "; + } + + outs() << "\n"; + + return 0; +} + diff --git a/tools/llvm-mc/Disassembler.h b/tools/llvm-mc/Disassembler.h index 78c2f85494..3da23965bd 100644 --- a/tools/llvm-mc/Disassembler.h +++ b/tools/llvm-mc/Disassembler.h @@ -27,6 +27,9 @@ public: static int disassemble(const Target &target, const std::string &tripleString, MemoryBuffer &buffer); + + static int disassembleEnhanced(const std::string &tripleString, + MemoryBuffer &buffer); }; } // namespace llvm diff --git a/tools/llvm-mc/Makefile b/tools/llvm-mc/Makefile index 5b0fe3f544..f92e643c33 100644 --- a/tools/llvm-mc/Makefile +++ b/tools/llvm-mc/Makefile @@ -22,3 +22,6 @@ include $(LEVEL)/Makefile.config LINK_COMPONENTS := $(TARGETS_TO_BUILD) MCParser MC support include $(LLVM_SRC_ROOT)/Makefile.rules + +# Using LIBS instead of USEDLIBS to force static linking +LIBS += $(LLVMLibDir)/libEnhancedDisassembly.a diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 76ce080cae..47f67c5e1b 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -18,6 +18,13 @@ #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCParser/AsmParser.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmParser.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetMachine.h" // FIXME. +#include "llvm/Target/TargetSelect.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" @@ -26,13 +33,8 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/System/Host.h" #include "llvm/System/Signals.h" -#include "llvm/Target/TargetAsmParser.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetMachine.h" // FIXME. -#include "llvm/Target/TargetSelect.h" -#include "llvm/MC/MCParser/AsmParser.h" #include "Disassembler.h" using namespace llvm; @@ -53,7 +55,11 @@ static cl::opt<unsigned> OutputAsmVariant("output-asm-variant", cl::desc("Syntax variant to use for output printing")); +static cl::opt<bool> +RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); + enum OutputFileType { + OFT_Null, OFT_AssemblyFile, OFT_ObjectFile }; @@ -63,6 +69,8 @@ FileType("filetype", cl::init(OFT_AssemblyFile), cl::values( clEnumValN(OFT_AssemblyFile, "asm", "Emit an assembly ('.s') file"), + clEnumValN(OFT_Null, "null", + "Don't emit anything (for timing purposes)"), clEnumValN(OFT_ObjectFile, "obj", "Emit a native object ('.o') file"), clEnumValEnd)); @@ -75,14 +83,22 @@ IncludeDirs("I", cl::desc("Directory of include files"), cl::value_desc("directory"), cl::Prefix); static cl::opt<std::string> +ArchName("arch", cl::desc("Target arch to assemble for, " + "see -version for available targets")); + +static cl::opt<std::string> TripleName("triple", cl::desc("Target triple to assemble for, " - "see -version for available targets"), - cl::init(LLVM_HOSTTRIPLE)); + "see -version for available targets")); + +static cl::opt<bool> +NoInitialTextSection("n", cl::desc( + "Don't assume assembly file starts in the text section")); enum ActionType { AC_AsLex, AC_Assemble, - AC_Disassemble + AC_Disassemble, + AC_EDisassemble }; static cl::opt<ActionType> @@ -94,9 +110,20 @@ Action(cl::desc("Action to perform:"), "Assemble a .s file (default)"), clEnumValN(AC_Disassemble, "disassemble", "Disassemble strings of hex bytes"), + clEnumValN(AC_EDisassemble, "edis", + "Enhanced disassembly of strings of hex bytes"), clEnumValEnd)); static const Target *GetTarget(const char *ProgName) { + // Figure out the target triple. + if (TripleName.empty()) + TripleName = sys::getHostTriple(); + if (!ArchName.empty()) { + llvm::Triple TT(TripleName); + TT.setArchName(ArchName); + TripleName = TT.str(); + } + // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); @@ -134,7 +161,7 @@ static int AsLexInput(const char *ProgName) { if (!TheTarget) return 1; - const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName); + llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); AsmLexer Lexer(*MAI); @@ -241,7 +268,11 @@ static int AssembleInput(const char *ProgName) { // it later. SrcMgr.setIncludeDirs(IncludeDirs); - MCContext Ctx; + + llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(TripleName)); + assert(MAI && "Unable to create target asm info!"); + + MCContext Ctx(*MAI); formatted_raw_ostream *Out = GetOutputStream(); if (!Out) return 1; @@ -256,25 +287,24 @@ static int AssembleInput(const char *ProgName) { return 1; } - OwningPtr<MCInstPrinter> IP; OwningPtr<MCCodeEmitter> CE; OwningPtr<MCStreamer> Str; - - const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName); - assert(MAI && "Unable to create target asm info!"); + OwningPtr<TargetAsmBackend> TAB; if (FileType == OFT_AssemblyFile) { - IP.reset(TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *Out)); + MCInstPrinter *IP = + TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI); if (ShowEncoding) CE.reset(TheTarget->createCodeEmitter(*TM, Ctx)); - Str.reset(createAsmStreamer(Ctx, *Out, *MAI, - TM->getTargetData()->isLittleEndian(), - /*asmverbose*/true, IP.get(), CE.get(), - ShowInst)); + Str.reset(createAsmStreamer(Ctx, *Out,TM->getTargetData()->isLittleEndian(), + /*asmverbose*/true, IP, CE.get(), ShowInst)); + } else if (FileType == OFT_Null) { + Str.reset(createNullStreamer(Ctx)); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); CE.reset(TheTarget->createCodeEmitter(*TM, Ctx)); - Str.reset(createMachOStreamer(Ctx, *Out, CE.get())); + TAB.reset(TheTarget->createAsmBackend(TripleName)); + Str.reset(createMachOStreamer(Ctx, *TAB, *Out, CE.get(), RelaxAll)); } AsmParser Parser(SrcMgr, Ctx, *Str.get(), *MAI); @@ -287,21 +317,21 @@ static int AssembleInput(const char *ProgName) { Parser.setTargetParser(*TAP.get()); - int Res = Parser.Run(); + int Res = Parser.Run(NoInitialTextSection); if (Out != &fouts()) delete Out; + // Delete output on errors. + if (Res && OutputFilename != "-") + sys::Path(OutputFilename).eraseFromDisk(); + return Res; } -static int DisassembleInput(const char *ProgName) { - std::string Error; - const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); - if (TheTarget == 0) { - errs() << ProgName << ": error: unable to get target for '" << TripleName - << "', see --version and --triple.\n"; +static int DisassembleInput(const char *ProgName, bool Enhanced) { + const Target *TheTarget = GetTarget(ProgName); + if (!TheTarget) return 0; - } std::string ErrorMessage; @@ -317,7 +347,10 @@ static int DisassembleInput(const char *ProgName) { return 1; } - return Disassembler::disassemble(*TheTarget, TripleName, *Buffer); + if (Enhanced) + return Disassembler::disassembleEnhanced(TripleName, *Buffer); + else + return Disassembler::disassemble(*TheTarget, TripleName, *Buffer); } @@ -344,7 +377,9 @@ int main(int argc, char **argv) { case AC_Assemble: return AssembleInput(argv[0]); case AC_Disassemble: - return DisassembleInput(argv[0]); + return DisassembleInput(argv[0], false); + case AC_EDisassemble: + return DisassembleInput(argv[0], true); } return 0; diff --git a/tools/llvmc/plugins/Base/Base.td.in b/tools/llvmc/plugins/Base/Base.td.in index ac0f665925..e04970fa5a 100644 --- a/tools/llvmc/plugins/Base/Base.td.in +++ b/tools/llvmc/plugins/Base/Base.td.in @@ -46,6 +46,8 @@ def OptList : OptionList<[ (help "Relocation model: PIC"), (hidden)), (switch_option "mdynamic-no-pic", (help "Relocation model: dynamic-no-pic"), (hidden)), + (switch_option "shared", + (help "Create a DLL instead of the regular executable")), (parameter_option "linker", (help "Choose linker (possible values: gcc, g++)")), (parameter_option "mtune", @@ -233,6 +235,8 @@ def llvm_gcc_assembler : Tool< (switch_on "c"), (stop_compilation), (not_empty "arch"), (forward "arch"), (not_empty "Xassembler"), (forward "Xassembler"), + (switch_on "m32"), (forward "m32"), + (switch_on "m64"), (forward "m64"), (not_empty "Wa,"), (forward "Wa,"))) ]>; @@ -259,7 +263,7 @@ def llc : Tool< // Base class for linkers class llvm_gcc_based_linker <string cmd_prefix> : Tool< -[(in_language "object-code"), +[(in_language ["object-code", "static-library"]), (out_language "executable"), (output_suffix "out"), (command cmd_prefix), @@ -279,6 +283,7 @@ class llvm_gcc_based_linker <string cmd_prefix> : Tool< (not_empty "l"), (forward "l"), (not_empty "Xlinker"), (forward "Xlinker"), (not_empty "Wl,"), (forward "Wl,"), + (switch_on "shared"), (forward "shared"), (switch_on "dynamiclib"), (forward "dynamiclib"), (switch_on "prebind"), (forward "prebind"), (switch_on "dead_strip"), (forward "dead_strip"), @@ -312,6 +317,7 @@ def LanguageMap : LanguageMap< LangToSuffixes<"llvm-assembler", ["ll"]>, LangToSuffixes<"llvm-bitcode", ["bc"]>, LangToSuffixes<"object-code", ["o", "*empty*"]>, + LangToSuffixes<"static-library", ["a", "lib"]>, LangToSuffixes<"executable", ["out"]> ]>; diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 0a58aa7e89..0eb9a48d0d 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -24,9 +24,16 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/SubtargetFeature.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetSelect.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MemoryBuffer.h" @@ -35,16 +42,6 @@ #include "llvm/System/Host.h" #include "llvm/System/Program.h" #include "llvm/System/Signals.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/SubtargetFeature.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetSelect.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Scalar.h" #include "llvm/Config/config.h" #include <cstdlib> #include <unistd.h> @@ -252,7 +249,8 @@ bool LTOCodeGenerator::assemble(const std::string& asmPath, args.push_back(arch); } // add -static to assembler command line when code model requires - if ( (_assemblerPath != NULL) && (_codeModel == LTO_CODEGEN_PIC_MODEL_STATIC) ) + if ( (_assemblerPath != NULL) && + (_codeModel == LTO_CODEGEN_PIC_MODEL_STATIC) ) args.push_back("-static"); } if ( needsCompilerOptions ) { @@ -303,44 +301,44 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg) // construct LTModule, hand over ownership of module and target const std::string FeatureStr = - SubtargetFeatures::getDefaultSubtargetFeatures(llvm::Triple(Triple)); + SubtargetFeatures::getDefaultSubtargetFeatures(llvm::Triple(Triple)); _target = march->createTargetMachine(Triple, FeatureStr); } return false; } -void LTOCodeGenerator::applyScopeRestrictions() -{ - if ( !_scopeRestrictionsDone ) { - Module* mergedModule = _linker.getModule(); - - // Start off with a verification pass. - PassManager passes; - passes.add(createVerifierPass()); - - // mark which symbols can not be internalized - if ( !_mustPreserveSymbols.empty() ) { - Mangler mangler(*_target->getMCAsmInfo()); - std::vector<const char*> mustPreserveList; - for (Module::iterator f = mergedModule->begin(), - e = mergedModule->end(); f != e; ++f) { - if ( !f->isDeclaration() - && _mustPreserveSymbols.count(mangler.getNameWithPrefix(f)) ) - mustPreserveList.push_back(::strdup(f->getNameStr().c_str())); - } - for (Module::global_iterator v = mergedModule->global_begin(), - e = mergedModule->global_end(); v != e; ++v) { - if ( !v->isDeclaration() - && _mustPreserveSymbols.count(mangler.getNameWithPrefix(v)) ) - mustPreserveList.push_back(::strdup(v->getNameStr().c_str())); - } - passes.add(createInternalizePass(mustPreserveList)); - } - // apply scope restrictions - passes.run(*mergedModule); - - _scopeRestrictionsDone = true; +void LTOCodeGenerator::applyScopeRestrictions() { + if (_scopeRestrictionsDone) return; + Module *mergedModule = _linker.getModule(); + + // Start off with a verification pass. + PassManager passes; + passes.add(createVerifierPass()); + + // mark which symbols can not be internalized + if (!_mustPreserveSymbols.empty()) { + MCContext Context(*_target->getMCAsmInfo()); + Mangler mangler(Context, *_target->getTargetData()); + std::vector<const char*> mustPreserveList; + for (Module::iterator f = mergedModule->begin(), + e = mergedModule->end(); f != e; ++f) { + if (!f->isDeclaration() && + _mustPreserveSymbols.count(mangler.getNameWithPrefix(f))) + mustPreserveList.push_back(::strdup(f->getNameStr().c_str())); + } + for (Module::global_iterator v = mergedModule->global_begin(), + e = mergedModule->global_end(); v != e; ++v) { + if (!v->isDeclaration() && + _mustPreserveSymbols.count(mangler.getNameWithPrefix(v))) + mustPreserveList.push_back(::strdup(v->getNameStr().c_str())); } + passes.add(createInternalizePass(mustPreserveList)); + } + + // apply scope restrictions + passes.run(*mergedModule); + + _scopeRestrictionsDone = true; } /// Optimize merged modules using various IPO passes @@ -372,7 +370,7 @@ bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out, // if options were requested, set them if ( !_codegenOptions.empty() ) cl::ParseCommandLineOptions(_codegenOptions.size(), - (char**)&_codegenOptions[0]); + const_cast<char **>(&_codegenOptions[0])); // Instantiate the pass manager to organize the passes. PassManager passes; diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 15fb3f549b..b269e78237 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -1,4 +1,4 @@ -//===-LTOModule.cpp - LLVM Link Time Optimizer ----------------------------===// +//===-- LTOModule.cpp - LLVM Link Time Optimizer --------------------------===// // // The LLVM Compiler Infrastructure // @@ -29,6 +29,7 @@ #include "llvm/Target/Mangler.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetSelect.h" @@ -100,13 +101,13 @@ LTOModule* LTOModule::makeLTOModule(const char* path, /// Also if next byte is on a different page, don't assume it is readable. MemoryBuffer* LTOModule::makeBuffer(const void* mem, size_t length) { - const char* startPtr = (char*)mem; - const char* endPtr = startPtr+length; - if ((((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0) - || (*endPtr != 0)) - return MemoryBuffer::getMemBufferCopy(startPtr, endPtr); - else - return MemoryBuffer::getMemBuffer(startPtr, endPtr); + const char *startPtr = (char*)mem; + const char *endPtr = startPtr+length; + if (((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0 || + *endPtr != 0) + return MemoryBuffer::getMemBufferCopy(StringRef(startPtr, length)); + + return MemoryBuffer::getMemBuffer(StringRef(startPtr, length)); } @@ -437,7 +438,8 @@ void LTOModule::lazyParseSymbols() _symbolsParsed = true; // Use mangler to add GlobalPrefix to names to match linker names. - Mangler mangler(*_target->getMCAsmInfo()); + MCContext Context(*_target->getMCAsmInfo()); + Mangler mangler(Context, *_target->getTargetData()); // add functions for (Module::iterator f = _module->begin(); f != _module->end(); ++f) { diff --git a/tools/lto/Makefile b/tools/lto/Makefile index 3120aa52c9..8d57333f9c 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -10,6 +10,8 @@ LEVEL = ../.. LIBRARYNAME = LTO +EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/lto.exports + # Include this here so we can get the configuration of the targets # that have been configured for construction. We have to do this # early so we can set up LINK_COMPONENTS before including Makefile.rules @@ -32,7 +34,6 @@ ifeq ($(HOST_OS),Darwin) # extra options to override libtool defaults LLVMLibsOptions := $(LLVMLibsOptions) \ -avoid-version \ - -Wl,-exported_symbols_list -Wl,$(PROJ_SRC_DIR)/lto.exports \ -Wl,-dead_strip \ -Wl,-seg1addr -Wl,0xE0000000 diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index 01f43d1c36..9011cf602b 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -1,24 +1,23 @@ -_lto_get_error_message -_lto_get_version -_lto_module_create -_lto_module_create_from_memory -_lto_module_get_num_symbols -_lto_module_get_symbol_attribute -_lto_module_get_symbol_name -_lto_module_get_target_triple -_lto_module_is_object_file -_lto_module_is_object_file_for_target -_lto_module_is_object_file_in_memory -_lto_module_is_object_file_in_memory_for_target -_lto_module_dispose -_lto_codegen_add_module -_lto_codegen_add_must_preserve_symbol -_lto_codegen_compile -_lto_codegen_create -_lto_codegen_dispose -_lto_codegen_set_debug_model -_lto_codegen_set_pic_model -_lto_codegen_write_merged_modules -_lto_codegen_debug_options -_lto_codegen_set_assembler_path - +lto_get_error_message +lto_get_version +lto_module_create +lto_module_create_from_memory +lto_module_get_num_symbols +lto_module_get_symbol_attribute +lto_module_get_symbol_name +lto_module_get_target_triple +lto_module_is_object_file +lto_module_is_object_file_for_target +lto_module_is_object_file_in_memory +lto_module_is_object_file_in_memory_for_target +lto_module_dispose +lto_codegen_add_module +lto_codegen_add_must_preserve_symbol +lto_codegen_compile +lto_codegen_create +lto_codegen_dispose +lto_codegen_set_debug_model +lto_codegen_set_pic_model +lto_codegen_write_merged_modules +lto_codegen_debug_options +lto_codegen_set_assembler_path diff --git a/tools/opt/AnalysisWrappers.cpp b/tools/opt/AnalysisWrappers.cpp index 18360f837e..f548d007d7 100644 --- a/tools/opt/AnalysisWrappers.cpp +++ b/tools/opt/AnalysisWrappers.cpp @@ -22,7 +22,6 @@ #include "llvm/Support/CallSite.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Support/raw_ostream.h" -#include <iostream> using namespace llvm; namespace { diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp index bbf8d122e7..86f99324b9 100644 --- a/tools/opt/GraphPrinters.cpp +++ b/tools/opt/GraphPrinters.cpp @@ -19,12 +19,11 @@ #include "llvm/Value.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/Dominators.h" -#include <iostream> -#include <fstream> +#include "llvm/Support/raw_ostream.h" using namespace llvm; template<typename GraphType> -static void WriteGraphToFile(std::ostream &O, const std::string &GraphName, +static void WriteGraphToFile(raw_ostream &O, const std::string &GraphName, const GraphType >) { std::string Filename = GraphName + ".dot"; O << "Writing '" << Filename << "'..."; @@ -69,7 +68,7 @@ namespace { CallGraphPrinter() : ModulePass(&ID) {} virtual bool runOnModule(Module &M) { - WriteGraphToFile(std::cerr, "callgraph", &getAnalysis<CallGraph>()); + WriteGraphToFile(llvm::errs(), "callgraph", &getAnalysis<CallGraph>()); return false; } diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index b123d54eee..ff19942ead 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -28,7 +28,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/StandardPasses.h" @@ -142,15 +141,14 @@ struct CallGraphSCCPassPrinter : public CallGraphSCCPass { CallGraphSCCPassPrinter(const PassInfo *PI) : CallGraphSCCPass(&ID), PassToPrint(PI) {} - virtual bool runOnSCC(std::vector<CallGraphNode *>&SCC) { + virtual bool runOnSCC(CallGraphSCC &SCC) { if (!Quiet) { outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n"; - for (unsigned i = 0, e = SCC.size(); i != e; ++i) { - Function *F = SCC[i]->getFunction(); - if (F) { + for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { + Function *F = (*I)->getFunction(); + if (F) getAnalysisID<Pass>(PassToPrint).print(outs(), F->getParent()); - } } } // Get and print pass... @@ -424,9 +422,9 @@ int main(int argc, char **argv) { if (TD) Passes.add(TD); - FunctionPassManager *FPasses = NULL; + OwningPtr<FunctionPassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelO3) { - FPasses = new FunctionPassManager(M.get()); + FPasses.reset(new FunctionPassManager(M.get())); if (TD) FPasses->add(new TargetData(*TD)); } |