diff options
author | Jush Lu <jush.msn@gmail.com> | 2011-04-09 11:27:00 +0800 |
---|---|---|
committer | Jush Lu <jush.msn@gmail.com> | 2011-04-09 11:27:00 +0800 |
commit | 8feda7ee332f1f91e4d3a42d9f7ad729012ed174 (patch) | |
tree | a2c1041fd0aad673c2ea522b68a0078fd1a90b2d /tools | |
parent | 12c27e38e875ae53f47e4a1b1c00a601457c20f2 (diff) | |
parent | 2c44a80d991df258a45e2f5fa76d5ada9e99015c (diff) | |
download | external_llvm-8feda7ee332f1f91e4d3a42d9f7ad729012ed174.zip external_llvm-8feda7ee332f1f91e4d3a42d9f7ad729012ed174.tar.gz external_llvm-8feda7ee332f1f91e4d3a42d9f7ad729012ed174.tar.bz2 |
Merge upstream r129128
Diffstat (limited to 'tools')
44 files changed, 1077 insertions, 625 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 2f37911..c9072a7 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -38,6 +38,7 @@ add_subdirectory(llvm-extract) add_subdirectory(llvm-diff) add_subdirectory(macho-dump) add_subdirectory(llvm-objdump) +add_subdirectory(llvm-rtdyld) add_subdirectory(bugpoint) add_subdirectory(bugpoint-passes) @@ -46,6 +47,17 @@ add_subdirectory(llvm-stub) add_subdirectory(edis) add_subdirectory(llvmc) +if( NOT WIN32 ) + add_subdirectory(lto) +endif() + +if( LLVM_ENABLE_PIC ) + # TODO: support other systems: + if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) + add_subdirectory(gold) + endif() +endif() + if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt ) add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/clang ) endif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt ) diff --git a/tools/Makefile b/tools/Makefile index 7310247..5960433 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -13,19 +13,20 @@ LEVEL := .. OPTIONAL_PARALLEL_DIRS := clang # Build LLDB if present. Note LLDB must be built last as it depends on the -# wider LLVM infrastructure (including Clang). +# wider LLVM infrastructure (including Clang). OPTIONAL_DIRS := lldb # 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 +DIRS := llvm-config PARALLEL_DIRS := opt llvm-as llvm-dis \ llc llvm-ranlib llvm-ar llvm-nm \ llvm-ld llvm-prof llvm-link \ lli llvm-extract llvm-mc \ bugpoint llvm-bcanalyzer llvm-stub \ - llvmc llvm-diff macho-dump llvm-objdump + llvmc llvm-diff macho-dump llvm-objdump \ + llvm-rtdyld # Let users override the set of tools to build from the command line. ifdef ONLY_TOOLS diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index 1cbf632..aa3e290 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -71,7 +71,7 @@ BugDriver::BugDriver(const char *toolname, bool find_bugs, LLVMContext& ctxt) : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), Program(0), Interpreter(0), SafeInterpreter(0), gcc(0), - run_find_bugs(find_bugs), Timeout(timeout), + run_find_bugs(find_bugs), Timeout(timeout), MemoryLimit(memlimit), UseValgrind(use_valgrind) {} BugDriver::~BugDriver() { @@ -97,7 +97,7 @@ Module *llvm::ParseInputFile(const std::string &Filename, if (TheTriple.getTriple().empty()) TheTriple.setTriple(sys::getHostTriple()); - + TargetTriple.setTriple(TheTriple.getTriple()); } @@ -118,7 +118,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) { // Load the first input file. Program = ParseInputFile(Filenames[0], Context); if (Program == 0) return true; - + outs() << "Read input file : '" << Filenames[0] << "'\n"; for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { @@ -152,12 +152,12 @@ bool BugDriver::run(std::string &ErrMsg) { return runManyPasses(PassesToRun, ErrMsg); } - // If we're not running as a child, the first thing that we must do is - // determine what the problem is. Does the optimization series crash the - // compiler, or does it produce illegal code? We make the top-level - // decision by trying to run all of the passes on the the input program, - // which should generate a bitcode file. If it does generate a bitcode - // file, then we know the compiler didn't crash, so try to diagnose a + // If we're not running as a child, the first thing that we must do is + // determine what the problem is. Does the optimization series crash the + // compiler, or does it produce illegal code? We make the top-level + // decision by trying to run all of the passes on the the input program, + // which should generate a bitcode file. If it does generate a bitcode + // file, then we know the compiler didn't crash, so try to diagnose a // miscompilation. if (!PassesToRun.empty()) { outs() << "Running selected passes on program to test for crash: "; @@ -194,10 +194,10 @@ bool BugDriver::run(std::string &ErrMsg) { // Make sure the reference output file gets deleted on exit from this // function, if appropriate. sys::Path ROF(ReferenceOutputFile); - FileRemover RemoverInstance(ROF, CreatedOutput && !SaveTemps); + FileRemover RemoverInstance(ROF.str(), CreatedOutput && !SaveTemps); // Diff the output of the raw program against the reference output. If it - // matches, then we assume there is a miscompilation bug and try to + // matches, then we assume there is a miscompilation bug and try to // diagnose it. outs() << "*** Checking the code generator...\n"; bool Diff = diffProgram(Program, "", "", false, &Error); diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index f1601cd..9be9dfd 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -323,7 +323,7 @@ void BugDriver::compileProgram(Module *M, std::string *Error) const { } // Remove the temporary bitcode file when we are done. - FileRemover BitcodeFileRemover(BitcodeFile, !SaveTemps); + FileRemover BitcodeFileRemover(BitcodeFile.str(), !SaveTemps); // Actually compile the program! Interpreter->compileProgram(BitcodeFile.str(), Error, Timeout, MemoryLimit); @@ -364,7 +364,8 @@ std::string BugDriver::executeProgram(const Module *Program, // Remove the temporary bitcode file when we are done. sys::Path BitcodePath(BitcodeFile); - FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps); + FileRemover BitcodeFileRemover(BitcodePath.str(), + CreatedBitcode && !SaveTemps); if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output"; diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 3a5f143..a9db38f 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -34,12 +34,12 @@ namespace llvm { } namespace { - static llvm::cl::opt<bool> - DisableLoopExtraction("disable-loop-extraction", + static llvm::cl::opt<bool> + DisableLoopExtraction("disable-loop-extraction", cl::desc("Don't extract loops when searching for miscompilations"), cl::init(false)); - static llvm::cl::opt<bool> - DisableBlockExtraction("disable-block-extraction", + static llvm::cl::opt<bool> + DisableBlockExtraction("disable-block-extraction", cl::desc("Don't extract blocks when searching for miscompilations"), cl::init(false)); @@ -75,7 +75,7 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix, BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); exit(BD.debugOptimizerCrash()); } - + // Check to see if the finished program matches the reference output... bool Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", true /*delete bitcode*/, &Error); @@ -309,7 +309,7 @@ static bool ExtractLoops(BugDriver &BD, bool MadeChange = false; while (1) { if (BugpointIsInterrupted) return MadeChange; - + ValueToValueMapTy VMap; Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, @@ -354,7 +354,7 @@ static bool ExtractLoops(BugDriver &BD, BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc", ToOptimizeLoopExtracted); - errs() << "Please submit the " + errs() << "Please submit the " << OutputPrefix << "-loop-extract-fail-*.bc files.\n"; delete ToOptimize; delete ToNotOptimize; @@ -409,9 +409,9 @@ static bool ExtractLoops(BugDriver &BD, MiscompiledFunctions.clear(); for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first); - + assert(NewF && "Function not found??"); - assert(NewF->getFunctionType() == MisCompFunctions[i].second && + assert(NewF->getFunctionType() == MisCompFunctions[i].second && "found wrong function type?"); MiscompiledFunctions.push_back(NewF); } @@ -523,7 +523,7 @@ static bool ExtractBlocks(BugDriver &BD, std::vector<Function*> &MiscompiledFunctions, std::string &Error) { if (BugpointIsInterrupted) return false; - + std::vector<BasicBlock*> Blocks; for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) for (Function::iterator I = MiscompiledFunctions[i]->begin(), @@ -593,7 +593,7 @@ static bool ExtractBlocks(BugDriver &BD, for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first); assert(NewF && "Function not found??"); - assert(NewF->getFunctionType() == MisCompFunctions[i].second && + assert(NewF->getFunctionType() == MisCompFunctions[i].second && "Function has wrong type??"); MiscompiledFunctions.push_back(NewF); } @@ -731,7 +731,7 @@ void BugDriver::debugMiscompilation(std::string *Error) { << getPassesString(getPassesToRun()) << '\n'; EmitProgressBitcode(Program, "passinput"); - std::vector<Function *> MiscompiledFunctions = + std::vector<Function *> MiscompiledFunctions = DebugAMiscompilation(*this, TestOptimizer, *Error); if (!Error->empty()) return; @@ -845,7 +845,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Create a new global to hold the cached function pointer. Constant *NullPtr = ConstantPointerNull::get(F->getType()); GlobalVariable *Cache = - new GlobalVariable(*F->getParent(), F->getType(), + new GlobalVariable(*F->getParent(), F->getType(), false, GlobalValue::InternalLinkage, NullPtr,F->getName()+".fpcache"); @@ -885,7 +885,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, new StoreInst(CastedResolver, Cache, LookupBB); BranchInst::Create(DoCallBB, LookupBB); - PHINode *FuncPtr = PHINode::Create(NullPtr->getType(), + PHINode *FuncPtr = PHINode::Create(NullPtr->getType(), 2, "fp", DoCallBB); FuncPtr->addIncoming(CastedResolver, LookupBB); FuncPtr->addIncoming(CachedVal, EntryBB); @@ -943,7 +943,7 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, } delete Test; - FileRemover TestModuleBCRemover(TestModuleBC, !SaveTemps); + FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps); // Make the shared library sys::Path SafeModuleBC("bugpoint.safe.bc"); @@ -959,14 +959,14 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, exit(1); } - FileRemover SafeModuleBCRemover(SafeModuleBC, !SaveTemps); + FileRemover SafeModuleBCRemover(SafeModuleBC.str(), !SaveTemps); std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error); if (!Error.empty()) return false; delete Safe; - FileRemover SharedObjectRemover(sys::Path(SharedObject), !SaveTemps); + FileRemover SharedObjectRemover(SharedObject, !SaveTemps); // Run the code generator on the `Test' code, loading the shared library. // The function returns whether or not the new output differs from reference. diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 37cc902..1719703 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -503,7 +503,7 @@ int LLC::ExecuteProgram(const std::string &Bitcode, sys::Path OutputAsmFile; GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); - FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); + FileRemover OutFileRemover(OutputAsmFile.str(), !SaveTemps); std::vector<std::string> GCCArgs(ArgsForGCC); GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); @@ -675,7 +675,7 @@ int CBE::ExecuteProgram(const std::string &Bitcode, sys::Path OutputCFile; OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); - FileRemover CFileRemove(OutputCFile, !SaveTemps); + FileRemover CFileRemove(OutputCFile.str(), !SaveTemps); std::vector<std::string> GCCArgs(ArgsForGCC); GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); @@ -851,7 +851,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, errs() << "\n"; ); - FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps); + FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); if (RemoteClientPath.isEmpty()) { DEBUG(errs() << "<run locally>"); diff --git a/tools/edis/CMakeLists.txt b/tools/edis/CMakeLists.txt index 5037f9f..9406c2a 100644 --- a/tools/edis/CMakeLists.txt +++ b/tools/edis/CMakeLists.txt @@ -1,11 +1,34 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) -add_llvm_library(EnhancedDisassembly +set(SOURCES ../../include/llvm-c/EnhancedDisassembly.h EDMain.cpp -) + ) -set_target_properties(EnhancedDisassembly - PROPERTIES - LINKER_LANGUAGE CXX) +set(LLVM_LINK_COMPONENTS mcdisassembler) +if( LLVM_TARGETS_TO_BUILD MATCHES X86 ) + list(APPEND LLVM_LINK_COMPONENTS x86asmprinter x86disassembler) +endif() +if( LLVM_TARGETS_TO_BUILD MATCHES ARM ) + list(APPEND LLVM_LINK_COMPONENTS armasmprinter armdisassembler) +endif() +# TODO: Process EnhancedDisassembly.exports + +if( NOT WIN32 AND LLVM_ENABLE_PIC ) + set(bsl ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS ON) + add_llvm_library(EnhancedDisassembly ${SOURCES}) + set_property(TARGET EnhancedDisassembly PROPERTY + OUTPUT_NAME "EnhancedDisassembly") + set(BUILD_SHARED_LIBS ${bsl}) + set(EnhancedDisassembly_STATIC_TARGET_NAME EnhancedDisassembly_static) +else() + set(EnhancedDisassembly_STATIC_TARGET_NAME EnhancedDisassembly) +endif() + +if( NOT BUILD_SHARED_LIBS ) + add_llvm_library(${EnhancedDisassembly_STATIC_TARGET_NAME} ${SOURCES}) + set_property(TARGET ${EnhancedDisassembly_STATIC_TARGET_NAME} PROPERTY + OUTPUT_NAME "EnhancedDisassembly") +endif() diff --git a/tools/gold/CMakeLists.txt b/tools/gold/CMakeLists.txt new file mode 100644 index 0000000..d8633e6 --- /dev/null +++ b/tools/gold/CMakeLists.txt @@ -0,0 +1,43 @@ +set(LLVM_BINUTILS_INCDIR "/usr/include" CACHE PATH + "PATH to binutils/include containing plugin-api.h for gold plugin.") + +if( NOT EXISTS "${LLVM_BINUTILS_INCDIR}/plugin-api.h" ) + message(STATUS "plugin-api.h not found. gold plugin excluded from the build.") +else() + include_directories( ${LLVM_BINUTILS_INCDIR} ) + + # Because off_t is used in the public API, the largefile parts are required for + # ABI compatibility. + add_definitions( -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 ) + + set(LLVM_LINK_COMPONENTS support) + + add_llvm_loadable_module(LLVMgold + gold-plugin.cpp + ) + + # Makefile.rules contains a special cases for OpenBSD, Darwin and + # Windows. We restrict ourselves to Linux for the time being. + set(srcexp ${CMAKE_CURRENT_SOURCE_DIR}/gold.exports) + add_custom_command(OUTPUT exportsfile + COMMAND echo "{" > exportsfile + COMMAND grep -q "\\<" ${srcexp} && echo " global:" >> exportsfile || : + COMMAND sed -e "s/$/;/" -e "s/^/ /" < ${srcexp} >> exportsfile + COMMAND echo " local: *;" >> exportsfile + COMMAND echo "};" >> exportsfile + DEPENDS ${srcexp} + VERBATIM + COMMENT "Creating export file for gold plugin") + add_custom_target(gold_exports DEPENDS exportsfile) + set_property(DIRECTORY APPEND + PROPERTY ADDITIONAL_MAKE_CLEAN_FILES exportsfile) + + # Force re-linking when the exports file changes. Actually, it + # forces recompilation of gold-plugin.cpp. The LINK_DEPENDS target + # property only works for makefile-based generators. + set_property(SOURCE gold-plugin.cpp APPEND PROPERTY + OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/exportsfile) + + target_link_libraries(LLVMgold LTO -Wl,--version-script,exportsfile) + add_dependencies(LLVMgold gold_exports) +endif() diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index e959d95..dd66eae 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -50,6 +50,7 @@ namespace { ld_plugin_add_input_file add_input_file = NULL; ld_plugin_add_input_library add_input_library = NULL; ld_plugin_set_extra_library_path set_extra_library_path = NULL; + ld_plugin_get_view get_view = NULL; ld_plugin_message message = discard_message; int api_version = 0; @@ -205,6 +206,9 @@ ld_plugin_status onload(ld_plugin_tv *tv) { case LDPT_SET_EXTRA_LIBRARY_PATH: set_extra_library_path = tv->tv_u.tv_set_extra_library_path; break; + case LDPT_GET_VIEW: + get_view = tv->tv_u.tv_get_view; + break; case LDPT_MESSAGE: message = tv->tv_u.tv_message; break; @@ -232,49 +236,23 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, int *claimed) { lto_module_t M; - if (file->offset) { - // Gold has found what might be IR part-way inside of a file, such as - // an .a archive. - if (lseek(file->fd, file->offset, SEEK_SET) == -1) { - (*message)(LDPL_ERROR, - "Failed to seek to archive member of %s at offset %d: %s\n", - file->name, - file->offset, sys::StrError(errno).c_str()); - return LDPS_ERR; - } - void *buf = malloc(file->filesize); - if (!buf) { - (*message)(LDPL_ERROR, - "Failed to allocate buffer for archive member of size: %d\n", - file->filesize); - return LDPS_ERR; - } - if (read(file->fd, buf, file->filesize) != file->filesize) { - (*message)(LDPL_ERROR, - "Failed to read archive member of %s at offset %d: %s\n", - file->name, - file->offset, - sys::StrError(errno).c_str()); - free(buf); - return LDPS_ERR; - } - if (!lto_module_is_object_file_in_memory(buf, file->filesize)) { - free(buf); - return LDPS_OK; - } - M = lto_module_create_from_memory(buf, file->filesize); - if (!M) { - (*message)(LDPL_ERROR, "Failed to create LLVM module: %s", - lto_get_error_message()); + if (get_view) { + const void *view; + if (get_view(file->handle, &view) != LDPS_OK) { + (*message)(LDPL_ERROR, "Failed to get a view of %s", file->name); return LDPS_ERR; } - free(buf); + M = lto_module_create_from_memory(view, file->filesize); + } else if (file->offset) { + // Gold has found what might be IR part-way inside of a file, such as + // an .a archive. + M = lto_module_create_from_fd_at_offset(file->fd, file->name, -1, + file->filesize, file->offset); } else { - lseek(file->fd, 0, SEEK_SET); M = lto_module_create_from_fd(file->fd, file->name, file->filesize); - if (!M) - return LDPS_OK; } + if (!M) + return LDPS_OK; *claimed = 1; Modules.resize(Modules.size() + 1); @@ -431,38 +409,10 @@ static ld_plugin_status all_symbols_read_hook(void) { exit(0); } size_t bufsize = 0; - const char *buffer = static_cast<const char *>(lto_codegen_compile(code_gen, - &bufsize)); - - std::string ErrMsg; - const char *objPath; - sys::Path uniqueObjPath("/tmp/llvmgold.o"); - if (!options::obj_path.empty()) { - objPath = options::obj_path.c_str(); - } else { - if (uniqueObjPath.createTemporaryFileOnDisk(true, &ErrMsg)) { - (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); - return LDPS_ERR; - } - objPath = uniqueObjPath.c_str(); - } - tool_output_file objFile(objPath, ErrMsg, - raw_fd_ostream::F_Binary); - if (!ErrMsg.empty()) { - (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); - return LDPS_ERR; - } - - objFile.os().write(buffer, bufsize); - objFile.os().close(); - if (objFile.os().has_error()) { - (*message)(LDPL_ERROR, "Error writing output file '%s'", - objPath); - objFile.os().clear_error(); - return LDPS_ERR; + if (lto_codegen_compile_to_file(code_gen, &objPath)) { + (*message)(LDPL_ERROR, "Could not produce a combined object file\n"); } - objFile.keep(); lto_codegen_dispose(code_gen); for (std::list<claimed_file>::iterator I = Modules.begin(), diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index bb426a9..7f5fa3f 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -207,7 +207,7 @@ int main(int argc, char **argv) { InitializeAllAsmParsers(); cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); - + // Load the module to be compiled... SMDiagnostic Err; std::auto_ptr<Module> M; @@ -271,7 +271,7 @@ int main(int argc, char **argv) { FeaturesStr = Features.getString(); } - std::auto_ptr<TargetMachine> + std::auto_ptr<TargetMachine> target(TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr)); assert(target.get() && "Could not allocate target machine!"); TargetMachine &Target = *target.get(); @@ -338,6 +338,9 @@ int main(int argc, char **argv) { return 1; } + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + PM.run(mod); } diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index a756459..014925c 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -133,6 +133,7 @@ int main(int argc, char **argv, char * const *envp) { // If we have a native target, initialize it to ensure it is linked in and // usable by the JIT. InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); cl::ParseCommandLineOptions(argc, argv, "llvm interpreter & dynamic compiler\n"); diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 980f278..9a92671 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -471,11 +471,11 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { } static void PrintSize(double Bits) { - fprintf(stderr, "%.2f/%.2fB/%lluW", Bits, Bits/8,(unsigned long long)Bits/32); + fprintf(stderr, "%.2f/%.2fB/%luW", Bits, Bits/8,(unsigned long)(Bits/32)); } static void PrintSize(uint64_t Bits) { - fprintf(stderr, "%llub/%.2fB/%lluW", (unsigned long long)Bits, - (double)Bits/8, (unsigned long long)Bits/32); + fprintf(stderr, "%lub/%.2fB/%luW", (unsigned long)Bits, + (double)Bits/8, (unsigned long)(Bits/32)); } @@ -601,8 +601,8 @@ static int AnalyzeBitcode() { for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) { const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second]; - fprintf(stderr, "\t\t%7d %9llu ", RecStats.NumInstances, - (unsigned long long)RecStats.TotalBits); + fprintf(stderr, "\t\t%7d %9lu ", RecStats.NumInstances, + (unsigned long)RecStats.TotalBits); if (RecStats.NumAbbrev) fprintf(stderr, "%7.2f ", diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt index b6f4289..bc23a64 100644 --- a/tools/llvm-config/CMakeLists.txt +++ b/tools/llvm-config/CMakeLists.txt @@ -7,7 +7,7 @@ endif( NOT PERL_FOUND ) set(PERL ${PERL_EXECUTABLE}) set(VERSION PACKAGE_VERSION) -set(PREFIX ${LLVM_BINARY_DIR}) # TODO: Root for `make install'. +set(PREFIX ${CMAKE_INSTALL_PREFIX}) set(abs_top_srcdir ${LLVM_MAIN_SRC_DIR}) set(abs_top_builddir ${LLVM_BINARY_DIR}) execute_process(COMMAND date @@ -27,6 +27,7 @@ endif( IS_BIG_ENDIAN ) set(SHLIBEXT ${LTDL_SHLIB_EXT}) #EXEEXT already set. set(OS "${CMAKE_SYSTEM}") +set(target "${TARGET_TRIPLE}") set(ARCH "${LLVM_NATIVE_ARCH}") get_system_libs(LLVM_SYSTEM_LIBS_LIST) @@ -54,9 +55,9 @@ configure_file( @ONLY ) -set(LIBDEPS ${CMAKE_CURRENT_BINARY_DIR}/LibDeps.txt) -set(LIBDEPS_TMP ${CMAKE_CURRENT_BINARY_DIR}/LibDeps.txt.tmp) -set(FINAL_LIBDEPS ${CMAKE_CURRENT_BINARY_DIR}/FinalLibDeps.txt) +set(LIBDEPS LibDeps.txt) +set(LIBDEPS_TMP LibDeps.txt.tmp) +set(FINAL_LIBDEPS FinalLibDeps.txt) set(LLVM_CONFIG ${LLVM_TOOLS_BINARY_DIR}/llvm-config) set(LLVM_CONFIG_IN ${CMAKE_CURRENT_BINARY_DIR}/llvm-config.in) @@ -90,9 +91,9 @@ add_custom_command(OUTPUT ${FINAL_LIBDEPS} DEPENDS ${LIBDEPS} COMMENT "Checking for cyclic dependencies between LLVM libraries.") -set(C_FLGS "${CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") -set(CXX_FLGS "${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") -set(CPP_FLGS "${CMAKE_CPP_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") +set(C_FLGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") +set(CXX_FLGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") +set(CPP_FLGS "${CMAKE_CPP_FLAGS} ${CMAKE_CPP_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}") # We don't want certain flags on the output of # llvm-config --cflags --cxxflags @@ -106,17 +107,18 @@ remove_option_from_llvm_config("-Wall") remove_option_from_llvm_config("-W") add_custom_command(OUTPUT ${LLVM_CONFIG} - COMMAND echo 's!@LLVM_CPPFLAGS@!${CPP_FLGS}!' > temp.sed - COMMAND echo 's!@LLVM_CFLAGS@!${C_FLGS}!' >> temp.sed - COMMAND echo 's!@LLVM_CXXFLAGS@!${CXX_FLGS}!' >> temp.sed + COMMAND echo s!@LLVM_CPPFLAGS@!${CPP_FLGS}! > temp.sed + COMMAND echo s!@LLVM_CFLAGS@!${C_FLGS}! >> temp.sed + COMMAND echo s!@LLVM_CXXFLAGS@!${CXX_FLGS}! >> temp.sed # TODO: Use general flags for linking! not just for shared libs: - COMMAND echo 's!@LLVM_LDFLAGS@!${CMAKE_SHARED_LINKER_FLAGS}!' >> temp.sed - COMMAND echo 's!@LIBS@!${LLVM_SYSTEM_LIBS}!' >> temp.sed - COMMAND echo 's!@LLVM_BUILDMODE@!${CMAKE_BUILD_TYPE}!' >> temp.sed + COMMAND echo s!@LLVM_LDFLAGS@!${CMAKE_SHARED_LINKER_FLAGS}! >> temp.sed + COMMAND echo s!@LIBS@!${LLVM_SYSTEM_LIBS}! >> temp.sed + COMMAND echo s!@LLVM_BUILDMODE@!${CMAKE_BUILD_TYPE}! >> temp.sed COMMAND sed -f temp.sed < ${LLVM_CONFIG_IN} > ${LLVM_CONFIG} COMMAND ${CMAKE_COMMAND} -E remove -f temp.sed COMMAND cat ${FINAL_LIBDEPS} >> ${LLVM_CONFIG} COMMAND chmod +x ${LLVM_CONFIG} + VERBATIM DEPENDS ${FINAL_LIBDEPS} ${LLVM_CONFIG_IN} COMMENT "Building llvm-config script." ) @@ -140,7 +142,7 @@ install(FILES ${LLVM_CONFIG} # Regeneration of library dependencies. -# See the comments at the end of cmake/modules/LLVMConfig.cmake for +# See the comments at the end of cmake/modules/LLVM-Config.cmake for # notes and guidelines. set(LLVMLibDeps ${LLVM_MAIN_SRC_DIR}/cmake/modules/LLVMLibDeps.cmake) diff --git a/tools/llvm-diff/CMakeLists.txt b/tools/llvm-diff/CMakeLists.txt index f6d65c9..c59d69e 100644 --- a/tools/llvm-diff/CMakeLists.txt +++ b/tools/llvm-diff/CMakeLists.txt @@ -2,5 +2,7 @@ set(LLVM_LINK_COMPONENTS support asmparser bitreader) add_llvm_tool(llvm-diff llvm-diff.cpp + DiffConsumer.cpp + DiffLog.cpp DifferenceEngine.cpp ) diff --git a/tools/llvm-diff/DiffConsumer.cpp b/tools/llvm-diff/DiffConsumer.cpp new file mode 100644 index 0000000..c23e8fb --- /dev/null +++ b/tools/llvm-diff/DiffConsumer.cpp @@ -0,0 +1,209 @@ +//===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files implements the the LLVM difference Consumer +// +//===----------------------------------------------------------------------===// + +#include "DiffConsumer.h" + +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){ + unsigned IN = 0; + + // Arguments get the first numbers. + for (Function::arg_iterator + AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) + if (!AI->hasName()) + Numbering[&*AI] = IN++; + + // Walk the basic blocks in order. + for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { + if (!FI->hasName()) + Numbering[&*FI] = IN++; + + // Walk the instructions in order. + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) + // void instructions don't get numbers. + if (!BI->hasName() && !BI->getType()->isVoidTy()) + Numbering[&*BI] = IN++; + } + + assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); +} + + +void DiffConsumer::printValue(Value *V, bool isL) { + if (V->hasName()) { + out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName(); + return; + } + if (V->getType()->isVoidTy()) { + if (isa<StoreInst>(V)) { + out << "store to "; + printValue(cast<StoreInst>(V)->getPointerOperand(), isL); + } else if (isa<CallInst>(V)) { + out << "call to "; + printValue(cast<CallInst>(V)->getCalledValue(), isL); + } else if (isa<InvokeInst>(V)) { + out << "invoke to "; + printValue(cast<InvokeInst>(V)->getCalledValue(), isL); + } else { + out << *V; + } + return; + } + + unsigned N = contexts.size(); + while (N > 0) { + --N; + DiffContext &ctxt = contexts[N]; + if (!ctxt.IsFunction) continue; + if (isL) { + if (ctxt.LNumbering.empty()) + ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering); + out << '%' << ctxt.LNumbering[V]; + return; + } else { + if (ctxt.RNumbering.empty()) + ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering); + out << '%' << ctxt.RNumbering[V]; + return; + } + } + + out << "<anonymous>"; +} + +void DiffConsumer::header() { + if (contexts.empty()) return; + for (SmallVectorImpl<DiffContext>::iterator + I = contexts.begin(), E = contexts.end(); I != E; ++I) { + if (I->Differences) continue; + if (isa<Function>(I->L)) { + // Extra newline between functions. + if (Differences) out << "\n"; + + Function *L = cast<Function>(I->L); + Function *R = cast<Function>(I->R); + if (L->getName() != R->getName()) + out << "in function " << L->getName() + << " / " << R->getName() << ":\n"; + else + out << "in function " << L->getName() << ":\n"; + } else if (isa<BasicBlock>(I->L)) { + BasicBlock *L = cast<BasicBlock>(I->L); + BasicBlock *R = cast<BasicBlock>(I->R); + if (L->hasName() && R->hasName() && L->getName() == R->getName()) + out << " in block %" << L->getName() << ":\n"; + else { + out << " in block "; + printValue(L, true); + out << " / "; + printValue(R, false); + out << ":\n"; + } + } else if (isa<Instruction>(I->L)) { + out << " in instruction "; + printValue(I->L, true); + out << " / "; + printValue(I->R, false); + out << ":\n"; + } + + I->Differences = true; + } +} + +void DiffConsumer::indent() { + unsigned N = Indent; + while (N--) out << ' '; +} + +bool DiffConsumer::hadDifferences() const { + return Differences; +} + +void DiffConsumer::enterContext(Value *L, Value *R) { + contexts.push_back(DiffContext(L, R)); + Indent += 2; +} + +void DiffConsumer::exitContext() { + Differences |= contexts.back().Differences; + contexts.pop_back(); + Indent -= 2; +} + +void DiffConsumer::log(StringRef text) { + header(); + indent(); + out << text << '\n'; +} + +void DiffConsumer::logf(const LogBuilder &Log) { + header(); + indent(); + + unsigned arg = 0; + + StringRef format = Log.getFormat(); + while (true) { + size_t percent = format.find('%'); + if (percent == StringRef::npos) { + out << format; + break; + } + assert(format[percent] == '%'); + + if (percent > 0) out << format.substr(0, percent); + + switch (format[percent+1]) { + case '%': out << '%'; break; + case 'l': printValue(Log.getArgument(arg++), true); break; + case 'r': printValue(Log.getArgument(arg++), false); break; + default: llvm_unreachable("unknown format character"); + } + + format = format.substr(percent+2); + } + + out << '\n'; +} + +void DiffConsumer::logd(const DiffLogBuilder &Log) { + header(); + + for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) { + indent(); + switch (Log.getLineKind(I)) { + case DC_match: + out << " "; + Log.getLeft(I)->dump(); + //printValue(Log.getLeft(I), true); + break; + case DC_left: + out << "< "; + Log.getLeft(I)->dump(); + //printValue(Log.getLeft(I), true); + break; + case DC_right: + out << "> "; + Log.getRight(I)->dump(); + //printValue(Log.getRight(I), false); + break; + } + //out << "\n"; + } +} diff --git a/tools/llvm-diff/DiffConsumer.h b/tools/llvm-diff/DiffConsumer.h new file mode 100644 index 0000000..b95d427 --- /dev/null +++ b/tools/llvm-diff/DiffConsumer.h @@ -0,0 +1,92 @@ +//===-- DiffConsumer.h - Difference Consumer --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference Consumer +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_DIFFCONSUMER_H_ +#define _LLVM_DIFFCONSUMER_H_ + +#include "DiffLog.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + class Module; + class Value; + class Function; + + /// The interface for consumers of difference data. + class Consumer { + public: + /// Record that a local context has been entered. Left and + /// Right are IR "containers" of some sort which are being + /// considered for structural equivalence: global variables, + /// functions, blocks, instructions, etc. + virtual void enterContext(Value *Left, Value *Right) = 0; + + /// Record that a local context has been exited. + virtual void exitContext() = 0; + + /// Record a difference within the current context. + virtual void log(StringRef Text) = 0; + + /// Record a formatted difference within the current context. + virtual void logf(const LogBuilder &Log) = 0; + + /// Record a line-by-line instruction diff. + virtual void logd(const DiffLogBuilder &Log) = 0; + + protected: + virtual ~Consumer() {} + }; + + class DiffConsumer : public Consumer { + private: + struct DiffContext { + DiffContext(Value *L, Value *R) + : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {} + Value *L; + Value *R; + bool Differences; + bool IsFunction; + DenseMap<Value*,unsigned> LNumbering; + DenseMap<Value*,unsigned> RNumbering; + }; + + raw_ostream &out; + Module *LModule; + Module *RModule; + SmallVector<DiffContext, 5> contexts; + bool Differences; + unsigned Indent; + + void printValue(Value *V, bool isL); + void header(); + void indent(); + + public: + DiffConsumer(Module *L, Module *R) + : out(errs()), LModule(L), RModule(R), Differences(false), Indent(0) {} + + bool hadDifferences() const; + void enterContext(Value *L, Value *R); + void exitContext(); + void log(StringRef text); + void logf(const LogBuilder &Log); + void logd(const DiffLogBuilder &Log); + }; +} + +#endif diff --git a/tools/llvm-diff/DiffLog.cpp b/tools/llvm-diff/DiffLog.cpp new file mode 100644 index 0000000..9cc0c88 --- /dev/null +++ b/tools/llvm-diff/DiffLog.cpp @@ -0,0 +1,53 @@ +//===-- DiffLog.h - Difference Log Builder and accessories ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference log builder. +// +//===----------------------------------------------------------------------===// + +#include "DiffLog.h" +#include "DiffConsumer.h" + +#include "llvm/Instructions.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +using namespace llvm; + +LogBuilder::~LogBuilder() { + consumer.logf(*this); +} + +StringRef LogBuilder::getFormat() const { return Format; } + +unsigned LogBuilder::getNumArguments() const { return Arguments.size(); } +Value *LogBuilder::getArgument(unsigned I) const { return Arguments[I]; } + +DiffLogBuilder::~DiffLogBuilder() { consumer.logd(*this); } + +void DiffLogBuilder::addMatch(Instruction *L, Instruction *R) { + Diff.push_back(DiffRecord(L, R)); +} +void DiffLogBuilder::addLeft(Instruction *L) { + // HACK: VS 2010 has a bug in the stdlib that requires this. + Diff.push_back(DiffRecord(L, DiffRecord::second_type(0))); +} +void DiffLogBuilder::addRight(Instruction *R) { + // HACK: VS 2010 has a bug in the stdlib that requires this. + Diff.push_back(DiffRecord(DiffRecord::first_type(0), R)); +} + +unsigned DiffLogBuilder::getNumLines() const { return Diff.size(); } + +DiffChange DiffLogBuilder::getLineKind(unsigned I) const { + return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left) + : DC_right); +} +Instruction *DiffLogBuilder::getLeft(unsigned I) const { return Diff[I].first; } +Instruction *DiffLogBuilder::getRight(unsigned I) const { return Diff[I].second; } diff --git a/tools/llvm-diff/DiffLog.h b/tools/llvm-diff/DiffLog.h new file mode 100644 index 0000000..43e318a --- /dev/null +++ b/tools/llvm-diff/DiffLog.h @@ -0,0 +1,80 @@ +//===-- DiffLog.h - Difference Log Builder and accessories ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference log builder. +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_DIFFLOG_H_ +#define _LLVM_DIFFLOG_H_ + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class Instruction; + class Value; + class Consumer; + + /// Trichotomy assumption + enum DiffChange { DC_match, DC_left, DC_right }; + + /// A temporary-object class for building up log messages. + class LogBuilder { + Consumer &consumer; + + /// The use of a stored StringRef here is okay because + /// LogBuilder should be used only as a temporary, and as a + /// temporary it will be destructed before whatever temporary + /// might be initializing this format. + StringRef Format; + + SmallVector<Value*, 4> Arguments; + + public: + LogBuilder(Consumer &c, StringRef Format) + : consumer(c), Format(Format) {} + + LogBuilder &operator<<(Value *V) { + Arguments.push_back(V); + return *this; + } + + ~LogBuilder(); + + StringRef getFormat() const; + unsigned getNumArguments() const; + Value *getArgument(unsigned I) const; + }; + + /// A temporary-object class for building up diff messages. + class DiffLogBuilder { + typedef std::pair<Instruction*,Instruction*> DiffRecord; + SmallVector<DiffRecord, 20> Diff; + + Consumer &consumer; + + public: + DiffLogBuilder(Consumer &c) : consumer(c) {} + ~DiffLogBuilder(); + + void addMatch(Instruction *L, Instruction *R); + // HACK: VS 2010 has a bug in the stdlib that requires this. + void addLeft(Instruction *L); + void addRight(Instruction *R); + + unsigned getNumLines() const; + DiffChange getLineKind(unsigned I) const; + Instruction *getLeft(unsigned I) const; + Instruction *getRight(unsigned I) const; + }; + +} + +#endif diff --git a/tools/llvm-diff/DifferenceEngine.cpp b/tools/llvm-diff/DifferenceEngine.cpp index b0a24d0..3cf178e 100644 --- a/tools/llvm-diff/DifferenceEngine.cpp +++ b/tools/llvm-diff/DifferenceEngine.cpp @@ -506,30 +506,30 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart, for (unsigned I = 0; I != NL+1; ++I) { Cur[I].Cost = I * LeftCost; for (unsigned J = 0; J != I; ++J) - Cur[I].Path.push_back(DifferenceEngine::DC_left); + Cur[I].Path.push_back(DC_left); } for (BasicBlock::iterator RI = RStart; RI != RE; ++RI) { // Initialize the first row. Next[0] = Cur[0]; Next[0].Cost += RightCost; - Next[0].Path.push_back(DifferenceEngine::DC_right); + Next[0].Path.push_back(DC_right); unsigned Index = 1; for (BasicBlock::iterator LI = LStart; LI != LE; ++LI, ++Index) { if (matchForBlockDiff(&*LI, &*RI)) { Next[Index] = Cur[Index-1]; Next[Index].Cost += MatchCost; - Next[Index].Path.push_back(DifferenceEngine::DC_match); + Next[Index].Path.push_back(DC_match); TentativeValues.insert(std::make_pair(&*LI, &*RI)); } else if (Next[Index-1].Cost <= Cur[Index].Cost) { Next[Index] = Next[Index-1]; Next[Index].Cost += LeftCost; - Next[Index].Path.push_back(DifferenceEngine::DC_left); + Next[Index].Path.push_back(DC_left); } else { Next[Index] = Cur[Index]; Next[Index].Cost += RightCost; - Next[Index].Path.push_back(DifferenceEngine::DC_right); + Next[Index].Path.push_back(DC_right); } } @@ -543,23 +543,23 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart, SmallVectorImpl<char> &Path = Cur[NL].Path; BasicBlock::iterator LI = LStart, RI = RStart; - DifferenceEngine::DiffLogBuilder Diff(Engine); + DiffLogBuilder Diff(Engine.getConsumer()); // Drop trailing matches. - while (Path.back() == DifferenceEngine::DC_match) + while (Path.back() == DC_match) Path.pop_back(); // Skip leading matches. SmallVectorImpl<char>::iterator PI = Path.begin(), PE = Path.end(); - while (PI != PE && *PI == DifferenceEngine::DC_match) { + while (PI != PE && *PI == DC_match) { unify(&*LI, &*RI); ++PI, ++LI, ++RI; } for (; PI != PE; ++PI) { - switch (static_cast<DifferenceEngine::DiffChange>(*PI)) { - case DifferenceEngine::DC_match: + switch (static_cast<DiffChange>(*PI)) { + case DC_match: assert(LI != LE && RI != RE); { Instruction *L = &*LI, *R = &*RI; @@ -569,13 +569,13 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart, ++LI; ++RI; break; - case DifferenceEngine::DC_left: + case DC_left: assert(LI != LE); Diff.addLeft(&*LI); ++LI; break; - case DifferenceEngine::DC_right: + case DC_right: assert(RI != RE); Diff.addRight(&*RI); ++RI; diff --git a/tools/llvm-diff/DifferenceEngine.h b/tools/llvm-diff/DifferenceEngine.h index 6eefb06..5b4f80b 100644 --- a/tools/llvm-diff/DifferenceEngine.h +++ b/tools/llvm-diff/DifferenceEngine.h @@ -17,6 +17,8 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "DiffLog.h" +#include "DiffConsumer.h" #include <utility> @@ -32,95 +34,6 @@ namespace llvm { /// A class for performing structural comparisons of LLVM assembly. class DifferenceEngine { public: - /// A temporary-object class for building up log messages. - class LogBuilder { - DifferenceEngine &Engine; - - /// The use of a stored StringRef here is okay because - /// LogBuilder should be used only as a temporary, and as a - /// temporary it will be destructed before whatever temporary - /// might be initializing this format. - StringRef Format; - - SmallVector<Value*, 4> Arguments; - - public: - LogBuilder(DifferenceEngine &Engine, StringRef Format) - : Engine(Engine), Format(Format) {} - - LogBuilder &operator<<(Value *V) { - Arguments.push_back(V); - return *this; - } - - ~LogBuilder() { - Engine.consumer.logf(*this); - } - - StringRef getFormat() const { return Format; } - - unsigned getNumArguments() const { return Arguments.size(); } - Value *getArgument(unsigned I) const { return Arguments[I]; } - }; - - enum DiffChange { DC_match, DC_left, DC_right }; - - /// A temporary-object class for building up diff messages. - class DiffLogBuilder { - typedef std::pair<Instruction*,Instruction*> DiffRecord; - SmallVector<DiffRecord, 20> Diff; - - DifferenceEngine &Engine; - - public: - DiffLogBuilder(DifferenceEngine &Engine) : Engine(Engine) {} - ~DiffLogBuilder() { Engine.consumer.logd(*this); } - - void addMatch(Instruction *L, Instruction *R) { - Diff.push_back(DiffRecord(L, R)); - } - void addLeft(Instruction *L) { - // HACK: VS 2010 has a bug in the stdlib that requires this. - Diff.push_back(DiffRecord(L, DiffRecord::second_type(0))); - } - void addRight(Instruction *R) { - // HACK: VS 2010 has a bug in the stdlib that requires this. - Diff.push_back(DiffRecord(DiffRecord::first_type(0), R)); - } - - unsigned getNumLines() const { return Diff.size(); } - DiffChange getLineKind(unsigned I) const { - return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left) - : DC_right); - } - Instruction *getLeft(unsigned I) const { return Diff[I].first; } - Instruction *getRight(unsigned I) const { return Diff[I].second; } - }; - - /// The interface for consumers of difference data. - struct Consumer { - /// Record that a local context has been entered. Left and - /// Right are IR "containers" of some sort which are being - /// considered for structural equivalence: global variables, - /// functions, blocks, instructions, etc. - virtual void enterContext(Value *Left, Value *Right) = 0; - - /// Record that a local context has been exited. - virtual void exitContext() = 0; - - /// Record a difference within the current context. - virtual void log(StringRef Text) = 0; - - /// Record a formatted difference within the current context. - virtual void logf(const LogBuilder &Log) = 0; - - /// Record a line-by-line instruction diff. - virtual void logd(const DiffLogBuilder &Log) = 0; - - protected: - virtual ~Consumer() {} - }; - /// A RAII object for recording the current context. struct Context { Context(DifferenceEngine &Engine, Value *L, Value *R) : Engine(Engine) { @@ -149,14 +62,13 @@ namespace llvm { void diff(Module *L, Module *R); void diff(Function *L, Function *R); - void log(StringRef text) { consumer.log(text); } - LogBuilder logf(StringRef text) { - return LogBuilder(*this, text); + return LogBuilder(consumer, text); } + Consumer& getConsumer() const { return consumer; } /// Installs an oracle to decide whether two global values are /// equivalent as operands. Without an oracle, global values are diff --git a/tools/llvm-diff/llvm-diff.cpp b/tools/llvm-diff/llvm-diff.cpp index b932ccc..76853f1 100644 --- a/tools/llvm-diff/llvm-diff.cpp +++ b/tools/llvm-diff/llvm-diff.cpp @@ -11,9 +11,9 @@ // //===----------------------------------------------------------------------===// +#include "DiffLog.h" #include "DifferenceEngine.h" -#include "llvm/Instructions.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Type.h" @@ -21,7 +21,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" @@ -43,221 +42,6 @@ static Module *ReadModule(LLVMContext &Context, StringRef Name) { return M; } -namespace { - struct DiffContext { - DiffContext(Value *L, Value *R) - : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {} - Value *L; - Value *R; - bool Differences; - bool IsFunction; - DenseMap<Value*,unsigned> LNumbering; - DenseMap<Value*,unsigned> RNumbering; - }; -} - -static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){ - unsigned IN = 0; - - // Arguments get the first numbers. - for (Function::arg_iterator - AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) - if (!AI->hasName()) - Numbering[&*AI] = IN++; - - // Walk the basic blocks in order. - for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { - if (!FI->hasName()) - Numbering[&*FI] = IN++; - - // Walk the instructions in order. - for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) - // void instructions don't get numbers. - if (!BI->hasName() && !BI->getType()->isVoidTy()) - Numbering[&*BI] = IN++; - } - - assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); -} - -namespace { -class DiffConsumer : public DifferenceEngine::Consumer { -private: - raw_ostream &out; - Module *LModule; - Module *RModule; - SmallVector<DiffContext, 5> contexts; - bool Differences; - unsigned Indent; - - void printValue(Value *V, bool isL) { - if (V->hasName()) { - out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName(); - return; - } - if (V->getType()->isVoidTy()) { - if (isa<StoreInst>(V)) { - out << "store to "; - printValue(cast<StoreInst>(V)->getPointerOperand(), isL); - } else if (isa<CallInst>(V)) { - out << "call to "; - printValue(cast<CallInst>(V)->getCalledValue(), isL); - } else if (isa<InvokeInst>(V)) { - out << "invoke to "; - printValue(cast<InvokeInst>(V)->getCalledValue(), isL); - } else { - out << *V; - } - return; - } - - unsigned N = contexts.size(); - while (N > 0) { - --N; - DiffContext &ctxt = contexts[N]; - if (!ctxt.IsFunction) continue; - if (isL) { - if (ctxt.LNumbering.empty()) - ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering); - out << '%' << ctxt.LNumbering[V]; - return; - } else { - if (ctxt.RNumbering.empty()) - ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering); - out << '%' << ctxt.RNumbering[V]; - return; - } - } - - out << "<anonymous>"; - } - - void header() { - if (contexts.empty()) return; - for (SmallVectorImpl<DiffContext>::iterator - I = contexts.begin(), E = contexts.end(); I != E; ++I) { - if (I->Differences) continue; - if (isa<Function>(I->L)) { - // Extra newline between functions. - if (Differences) out << "\n"; - - Function *L = cast<Function>(I->L); - Function *R = cast<Function>(I->R); - if (L->getName() != R->getName()) - out << "in function " << L->getName() - << " / " << R->getName() << ":\n"; - else - out << "in function " << L->getName() << ":\n"; - } else if (isa<BasicBlock>(I->L)) { - BasicBlock *L = cast<BasicBlock>(I->L); - BasicBlock *R = cast<BasicBlock>(I->R); - if (L->hasName() && R->hasName() && L->getName() == R->getName()) - out << " in block %" << L->getName() << ":\n"; - else { - out << " in block "; - printValue(L, true); - out << " / "; - printValue(R, false); - out << ":\n"; - } - } else if (isa<Instruction>(I->L)) { - out << " in instruction "; - printValue(I->L, true); - out << " / "; - printValue(I->R, false); - out << ":\n"; - } - - I->Differences = true; - } - } - - void indent() { - unsigned N = Indent; - while (N--) out << ' '; - } - -public: - DiffConsumer(Module *L, Module *R) - : out(errs()), LModule(L), RModule(R), Differences(false), Indent(0) {} - - bool hadDifferences() const { return Differences; } - - void enterContext(Value *L, Value *R) { - contexts.push_back(DiffContext(L, R)); - Indent += 2; - } - void exitContext() { - Differences |= contexts.back().Differences; - contexts.pop_back(); - Indent -= 2; - } - - void log(StringRef text) { - header(); - indent(); - out << text << '\n'; - } - - void logf(const DifferenceEngine::LogBuilder &Log) { - header(); - indent(); - - unsigned arg = 0; - - StringRef format = Log.getFormat(); - while (true) { - size_t percent = format.find('%'); - if (percent == StringRef::npos) { - out << format; - break; - } - assert(format[percent] == '%'); - - if (percent > 0) out << format.substr(0, percent); - - switch (format[percent+1]) { - case '%': out << '%'; break; - case 'l': printValue(Log.getArgument(arg++), true); break; - case 'r': printValue(Log.getArgument(arg++), false); break; - default: llvm_unreachable("unknown format character"); - } - - format = format.substr(percent+2); - } - - out << '\n'; - } - - void logd(const DifferenceEngine::DiffLogBuilder &Log) { - header(); - - for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) { - indent(); - switch (Log.getLineKind(I)) { - case DifferenceEngine::DC_match: - out << " "; - Log.getLeft(I)->dump(); - //printValue(Log.getLeft(I), true); - break; - case DifferenceEngine::DC_left: - out << "< "; - Log.getLeft(I)->dump(); - //printValue(Log.getLeft(I), true); - break; - case DifferenceEngine::DC_right: - out << "> "; - Log.getRight(I)->dump(); - //printValue(Log.getRight(I), false); - break; - } - //out << "\n"; - } - } - -}; -} // end anonymous namespace - static void diffGlobal(DifferenceEngine &Engine, Module *L, Module *R, StringRef Name) { // Drop leading sigils from the global name. diff --git a/tools/llvm-dis/CMakeLists.txt b/tools/llvm-dis/CMakeLists.txt index d62a6b5..3125f8a 100644 --- a/tools/llvm-dis/CMakeLists.txt +++ b/tools/llvm-dis/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LLVM_LINK_COMPONENTS bitreader) +set(LLVM_LINK_COMPONENTS bitreader analysis) set(LLVM_REQUIRES_EH 1) add_llvm_tool(llvm-dis diff --git a/tools/llvm-dis/Makefile b/tools/llvm-dis/Makefile index 22c9ecc..be71100 100644 --- a/tools/llvm-dis/Makefile +++ b/tools/llvm-dis/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TOOLNAME = llvm-dis -LINK_COMPONENTS := bitreader +LINK_COMPONENTS := bitreader analysis # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index b4977ce..7453d9e 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -19,7 +19,9 @@ #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Type.h" +#include "llvm/IntrinsicInst.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/Assembly/AssemblyAnnotationWriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" @@ -50,6 +52,16 @@ ShowAnnotations("show-annotations", namespace { +static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { + OS << DL.getLine() << ":" << DL.getCol(); + if (MDNode *N = DL.getInlinedAt(getGlobalContext())) { + DebugLoc IDL = DebugLoc::getFromDILocation(N); + if (!IDL.isUnknown()) { + OS << "@"; + printDebugLoc(IDL,OS); + } + } +} class CommentWriter : public AssemblyAnnotationWriter { public: void emitFunctionAnnot(const Function *F, @@ -58,10 +70,43 @@ public: OS << '\n'; } void printInfoComment(const Value &V, formatted_raw_ostream &OS) { - if (V.getType()->isVoidTy()) return; - - OS.PadToColumn(50); - OS << "; [#uses=" << V.getNumUses() << ']'; // Output # uses + bool Padded = false; + if (!V.getType()->isVoidTy()) { + OS.PadToColumn(50); + Padded = true; + OS << "; [#uses=" << V.getNumUses() << " type=" << V.getType()->getDescription() << "]"; // Output # uses and type + } + if (const Instruction *I = dyn_cast<Instruction>(&V)) { + const DebugLoc &DL = I->getDebugLoc(); + if (!DL.isUnknown()) { + if (!Padded) { + OS.PadToColumn(50); + Padded = true; + OS << ";"; + } + OS << " [debug line = "; + printDebugLoc(DL,OS); + OS << "]"; + } + if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) { + DIVariable Var(DDI->getVariable()); + if (!Padded) { + OS.PadToColumn(50); + Padded = true; + OS << ";"; + } + OS << " [debug variable = " << Var.getName() << "]"; + } + else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) { + DIVariable Var(DVI->getVariable()); + if (!Padded) { + OS.PadToColumn(50); + Padded = true; + OS << ";"; + } + OS << " [debug variable = " << Var.getName() << "]"; + } + } } }; diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp index cd6ce25..6b4c3c7 100644 --- a/tools/llvm-ld/llvm-ld.cpp +++ b/tools/llvm-ld/llvm-ld.cpp @@ -552,12 +552,12 @@ int main(int argc, char **argv, char **envp) { } // Arrange for the bitcode output file to be deleted on any errors. - BitcodeOutputRemover.setFile(sys::Path(BitcodeOutputFilename)); + BitcodeOutputRemover.setFile(BitcodeOutputFilename); sys::RemoveFileOnSignal(sys::Path(BitcodeOutputFilename)); // Arrange for the output file to be deleted on any errors. if (!LinkAsLibrary) { - OutputRemover.setFile(sys::Path(OutputFilename)); + OutputRemover.setFile(OutputFilename); sys::RemoveFileOnSignal(sys::Path(OutputFilename)); } @@ -657,7 +657,7 @@ int main(int argc, char **argv, char **envp) { AssemblyFile.appendSuffix("s"); // Mark the output files for removal. - FileRemover AssemblyFileRemover(AssemblyFile); + FileRemover AssemblyFileRemover(AssemblyFile.str()); sys::RemoveFileOnSignal(AssemblyFile); // Determine the locations of the llc and gcc programs. @@ -684,7 +684,7 @@ int main(int argc, char **argv, char **envp) { CFile.appendSuffix("cbe.c"); // Mark the output files for removal. - FileRemover CFileRemover(CFile); + FileRemover CFileRemover(CFile.str()); sys::RemoveFileOnSignal(CFile); // Determine the locations of the llc and gcc programs. diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index d98b57e..41b92a1 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -127,7 +127,8 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray, return false; } -int Disassembler::disassemble(const Target &T, const std::string &Triple, +int Disassembler::disassemble(const Target &T, TargetMachine &TM, + const std::string &Triple, MemoryBuffer &Buffer, raw_ostream &Out) { // Set up disassembler. @@ -145,7 +146,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, } int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); - OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, + OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(TM, AsmPrinterVariant, *AsmInfo)); if (!IP) { errs() << "error: no instruction printer for target " << Triple << '\n'; diff --git a/tools/llvm-mc/Disassembler.h b/tools/llvm-mc/Disassembler.h index b56f2e9..aaf77b5 100644 --- a/tools/llvm-mc/Disassembler.h +++ b/tools/llvm-mc/Disassembler.h @@ -19,13 +19,15 @@ namespace llvm { -class Target; class MemoryBuffer; +class Target; +class TargetMachine; class raw_ostream; class Disassembler { public: - static int disassemble(const Target &target, + static int disassemble(const Target &target, + TargetMachine &TM, const std::string &tripleString, MemoryBuffer &buffer, raw_ostream &Out); diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 2c22bed..f76b6ed 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -113,6 +113,10 @@ static cl::opt<bool> NoInitialTextSection("n", cl::desc( "Don't assume assembly file starts in the text section")); +static cl::opt<bool> +SaveTempLabels("L", cl::desc( + "Don't discard temporary labels")); + enum ActionType { AC_AsLex, AC_Assemble, @@ -327,6 +331,8 @@ static int AssembleInput(const char *ProgName) { const TargetAsmInfo *tai = new TargetAsmInfo(*TM); MCContext Ctx(*MAI, tai); + if (SaveTempLabels) + Ctx.setAllowTemporaryLabels(false); OwningPtr<tool_output_file> Out(GetOutputStream()); if (!Out) @@ -342,7 +348,7 @@ static int AssembleInput(const char *ProgName) { // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (FileType == OFT_AssemblyFile) { MCInstPrinter *IP = - TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI); + TheTarget->createMCInstPrinter(*TM, OutputAsmVariant, *MAI); MCCodeEmitter *CE = 0; TargetAsmBackend *TAB = 0; if (ShowEncoding) { @@ -403,12 +409,34 @@ static int DisassembleInput(const char *ProgName, bool Enhanced) { return 1; int Res; - if (Enhanced) + if (Enhanced) { Res = Disassembler::disassembleEnhanced(TripleName, *Buffer.take(), Out->os()); - else - Res = Disassembler::disassemble(*TheTarget, TripleName, + } else { + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (MCPU.size()) { + SubtargetFeatures Features; + Features.setCPU(MCPU); + FeaturesStr = Features.getString(); + } + + // FIXME: We shouldn't need to do this (and link in codegen). + // When we split this out, we should do it in a way that makes + // it straightforward to switch subtargets on the fly (.e.g, + // the .cpu and .code16 directives). + OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(TripleName, + FeaturesStr)); + + if (!TM) { + errs() << ProgName << ": error: could not create target for triple '" + << TripleName << "'.\n"; + return 1; + } + + Res = Disassembler::disassemble(*TheTarget, *TM, TripleName, *Buffer.take(), Out->os()); + } // Keep output if no errors. if (Res == 0) Out->keep(); diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 1fef8b6..de01656 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -38,6 +38,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetSelect.h" #include <algorithm> @@ -182,9 +183,21 @@ static void DisassembleInput(const StringRef &Filename) { return; } + // FIXME: We shouldn't need to do this (and link in codegen). + // When we split this out, we should do it in a way that makes + // it straightforward to switch subtargets on the fly (.e.g, + // the .cpu and .code16 directives). + std::string FeaturesStr; + OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(TripleName, + FeaturesStr)); + if (!TM) { + errs() << "error: could not create target for triple " << TripleName << "\n"; + return; + } + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( - AsmPrinterVariant, *AsmInfo)); + *TM, AsmPrinterVariant, *AsmInfo)); if (!IP) { errs() << "error: no instruction printer for target " << TripleName << '\n'; return; diff --git a/tools/llvm-rtdyld/CMakeLists.txt b/tools/llvm-rtdyld/CMakeLists.txt new file mode 100644 index 0000000..17e2c3e --- /dev/null +++ b/tools/llvm-rtdyld/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT) + +add_llvm_tool(llvm-rtdyld + llvm-rtdyld.cpp + ) diff --git a/tools/llvm-rtdyld/Makefile b/tools/llvm-rtdyld/Makefile new file mode 100644 index 0000000..0d57277 --- /dev/null +++ b/tools/llvm-rtdyld/Makefile @@ -0,0 +1,23 @@ +##===- tools/llvm-rtdyld/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = llvm-rtdyld + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +# 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_COMPONENTS := $(TARGETS_TO_BUILD) support MC object RuntimeDyld JIT + +include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp new file mode 100644 index 0000000..ddd6683 --- /dev/null +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -0,0 +1,122 @@ +//===-- llvm-rtdyld.cpp - MCJIT Testing Tool ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a testing tool for use with the MC-JIT LLVM components. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/Object/MachOObject.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +using namespace llvm; +using namespace llvm::object; + +static cl::opt<std::string> +InputFile(cl::Positional, cl::desc("<input file>"), cl::init("-")); + +enum ActionType { + AC_Execute +}; + +static cl::opt<ActionType> +Action(cl::desc("Action to perform:"), + cl::init(AC_Execute), + cl::values(clEnumValN(AC_Execute, "execute", + "Load, link, and execute the inputs."), + clEnumValEnd)); + +/* *** */ + +// A trivial memory manager that doesn't do anything fancy, just uses the +// support library allocation routines directly. +class TrivialMemoryManager : public RTDyldMemoryManager { +public: + uint8_t *startFunctionBody(const char *Name, uintptr_t &Size); + void endFunctionBody(const char *Name, uint8_t *FunctionStart, + uint8_t *FunctionEnd) {} +}; + +uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name, + uintptr_t &Size) { + return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); +} + +static const char *ProgramName; + +static void Message(const char *Type, const Twine &Msg) { + errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; +} + +static int Error(const Twine &Msg) { + Message("error", Msg); + return 1; +} + +/* *** */ + +static int executeInput() { + // Load the input memory buffer. + OwningPtr<MemoryBuffer> InputBuffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer)) + return Error("unable to read input: '" + ec.message() + "'"); + + // Instantiate a dynamic linker. + RuntimeDyld Dyld(new TrivialMemoryManager); + + // Load the object file into it. + if (Dyld.loadObject(InputBuffer.take())) { + return Error(Dyld.getErrorString()); + } + + // Get the address of "_main". + uint64_t MainAddress = Dyld.getSymbolAddress("_main"); + if (MainAddress == 0) + return Error("no definition for '_main'"); + + // Invalidate the instruction cache. + sys::MemoryBlock Data = Dyld.getMemoryBlock(); + sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); + + // Make sure the memory is executable. + std::string ErrorStr; + if (!sys::Memory::setExecutable(Data, &ErrorStr)) + return Error("unable to mark function executable: '" + ErrorStr + "'"); + + // Dispatch to _main(). + errs() << "loaded '_main' at: " << (void*)MainAddress << "\n"; + + int (*Main)(int, const char**) = + (int(*)(int,const char**)) uintptr_t(MainAddress); + const char **Argv = new const char*[2]; + Argv[0] = InputFile.c_str(); + Argv[1] = 0; + return Main(1, Argv); +} + +int main(int argc, char **argv) { + ProgramName = argv[0]; + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n"); + + switch (Action) { + default: + case AC_Execute: + return executeInput(); + } + + return 0; +} diff --git a/tools/llvm-stub/llvm-stub.c b/tools/llvm-stub/llvm-stub.c index 31c2d09..69cd6ed 100644 --- a/tools/llvm-stub/llvm-stub.c +++ b/tools/llvm-stub/llvm-stub.c @@ -64,7 +64,7 @@ int main(int argc, char** argv) { memcpy((char **)Args+2, argv+1, sizeof(char*)*argc); /* Run the JIT. */ -#ifndef _WIN32 +#if !defined(_WIN32) || defined(__MINGW64__) execvp(Interp, (char **)Args); /* POSIX execvp takes a char *const[]. */ #else execvp(Interp, Args); /* windows execvp takes a const char *const *. */ diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt new file mode 100644 index 0000000..7e2c5f0 --- /dev/null +++ b/tools/lto/CMakeLists.txt @@ -0,0 +1,27 @@ +set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + ipo scalaropts linker bitreader bitwriter mcdisassembler) + +add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) + +set(SOURCES + LTOCodeGenerator.cpp + lto.cpp + LTOModule.cpp + ) + +if( NOT WIN32 AND LLVM_ENABLE_PIC ) + set(bsl ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS ON) + add_llvm_library(LTO ${SOURCES}) + set_property(TARGET LTO PROPERTY OUTPUT_NAME "LTO") + set(BUILD_SHARED_LIBS ${bsl}) + set(LTO_STATIC_TARGET_NAME LTO_static) +else() + set(LTO_STATIC_TARGET_NAME LTO) +endif() + +if( NOT BUILD_SHARED_LIBS ) + add_llvm_library(${LTO_STATIC_TARGET_NAME} ${SOURCES}) + set_property(TARGET ${LTO_STATIC_TARGET_NAME} PROPERTY OUTPUT_NAME "LTO") +endif() diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 6739e06..d95f354 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -87,6 +87,10 @@ LTOCodeGenerator::~LTOCodeGenerator() bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { + + if(mod->getLLVVMModule()->MaterializeAllPermanently(&errMsg)) + return true; + bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg); const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs(); @@ -172,51 +176,63 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, } -const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) +bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) { - // make unique temp .o file to put generated object file - sys::PathWithStatus uniqueObjPath("lto-llvm.o"); - if ( uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg) ) { - uniqueObjPath.eraseFromDisk(); - return NULL; - } - sys::RemoveFileOnSignal(uniqueObjPath); - - // generate object file - bool genResult = false; - tool_output_file objFile(uniqueObjPath.c_str(), errMsg); - if (!errMsg.empty()) - return NULL; - genResult = this->generateObjectFile(objFile.os(), errMsg); - objFile.os().close(); - if (objFile.os().has_error()) { - objFile.os().clear_error(); - return NULL; - } - objFile.keep(); - if ( genResult ) { - uniqueObjPath.eraseFromDisk(); - return NULL; - } + // make unique temp .o file to put generated object file + sys::PathWithStatus uniqueObjPath("lto-llvm.o"); + if ( uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg) ) { + uniqueObjPath.eraseFromDisk(); + return true; + } + sys::RemoveFileOnSignal(uniqueObjPath); + + // generate object file + bool genResult = false; + tool_output_file objFile(uniqueObjPath.c_str(), errMsg); + if (!errMsg.empty()) + return NULL; + genResult = this->generateObjectFile(objFile.os(), errMsg); + objFile.os().close(); + if (objFile.os().has_error()) { + objFile.os().clear_error(); + return true; + } + objFile.keep(); + if ( genResult ) { + uniqueObjPath.eraseFromDisk(); + return true; + } - const std::string& uniqueObjStr = uniqueObjPath.str(); - // remove old buffer if compile() called twice - delete _nativeObjectFile; + _nativeObjectPath = uniqueObjPath.str(); + *name = _nativeObjectPath.c_str(); + return false; +} - // read .o file into memory buffer - OwningPtr<MemoryBuffer> BuffPtr; - if (error_code ec = MemoryBuffer::getFile(uniqueObjStr.c_str(),BuffPtr)) - errMsg = ec.message(); - _nativeObjectFile = BuffPtr.take(); +const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) +{ + const char *name; + if (compile_to_file(&name, errMsg)) + return NULL; + + // remove old buffer if compile() called twice + delete _nativeObjectFile; + + // read .o file into memory buffer + OwningPtr<MemoryBuffer> BuffPtr; + if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) { + errMsg = ec.message(); + return NULL; + } + _nativeObjectFile = BuffPtr.take(); - // remove temp files - uniqueObjPath.eraseFromDisk(); + // remove temp files + sys::Path(_nativeObjectPath).eraseFromDisk(); - // return buffer, unless error - if ( _nativeObjectFile == NULL ) - return NULL; - *length = _nativeObjectFile->getBufferSize(); - return _nativeObjectFile->getBufferStart(); + // return buffer, unless error + if ( _nativeObjectFile == NULL ) + return NULL; + *length = _nativeObjectFile->getBufferSize(); + return _nativeObjectFile->getBufferStart(); } bool LTOCodeGenerator::determineTarget(std::string& errMsg) diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h index 7798db9..f8fd357 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -41,6 +41,7 @@ struct LTOCodeGenerator { void addMustPreserveSymbol(const char* sym); bool writeMergedModules(const char* path, std::string& errMsg); + bool compile_to_file(const char** name, std::string& errMsg); const void* compile(size_t* length, std::string& errMsg); void setCodeGenDebugOptions(const char *opts); private: @@ -66,6 +67,7 @@ private: llvm::MemoryBuffer* _nativeObjectFile; std::vector<const char*> _codegenOptions; std::string _mCpu; + std::string _nativeObjectPath; }; #endif // LTO_CODE_GENERATOR_H diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index bdea0c3..78e6f28 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -91,32 +91,33 @@ LTOModule *LTOModule::makeLTOModule(const char *path, errMsg = ec.message(); return NULL; } - return makeLTOModule(buffer.get(), errMsg); + return makeLTOModule(buffer.take(), errMsg); } LTOModule *LTOModule::makeLTOModule(int fd, const char *path, - off_t size, + size_t size, + std::string &errMsg) { + return makeLTOModule(fd, path, size, size, 0, errMsg); +} + +LTOModule *LTOModule::makeLTOModule(int fd, const char *path, + size_t file_size, + size_t map_size, + off_t offset, std::string &errMsg) { OwningPtr<MemoryBuffer> buffer; - if (error_code ec = MemoryBuffer::getOpenFile(fd, path, buffer, size)) { + if (error_code ec = MemoryBuffer::getOpenFile(fd, path, buffer, file_size, + map_size, offset, false)) { errMsg = ec.message(); return NULL; } - return makeLTOModule(buffer.get(), errMsg); + return makeLTOModule(buffer.take(), errMsg); } -/// makeBuffer - Create a MemoryBuffer from a memory range. MemoryBuffer -/// requires the byte past end of the buffer to be a zero. We might get lucky -/// and already be that way, otherwise make a copy. Also if next byte is on a -/// different page, don't assume it is readable. +/// makeBuffer - Create a MemoryBuffer from a memory range. 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(StringRef(startPtr, length)); - - return MemoryBuffer::getMemBuffer(StringRef(startPtr, length)); + return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); } @@ -125,7 +126,7 @@ LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length, OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length)); if (!buffer) return NULL; - return makeLTOModule(buffer.get(), errMsg); + return makeLTOModule(buffer.take(), errMsg); } LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, @@ -138,9 +139,12 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, } // parse bitcode buffer - OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), &errMsg)); - if (!m) + OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext(), + &errMsg)); + if (!m) { + delete buffer; return NULL; + } std::string Triple = m->getTargetTriple(); if (Triple.empty()) @@ -177,16 +181,6 @@ void LTOModule::setTargetTriple(const char *triple) { void LTOModule::addDefinedFunctionSymbol(Function *f, Mangler &mangler) { // add to list of defined symbols addDefinedSymbol(f, mangler, true); - - // add external symbols referenced by this function. - for (Function::iterator b = f->begin(); b != f->end(); ++b) { - for (BasicBlock::iterator i = b->begin(); i != b->end(); ++i) { - for (unsigned count = 0, total = i->getNumOperands(); - count != total; ++count) { - findExternalRefs(i->getOperand(count), mangler); - } - } - } } // Get string that data pointer points to. @@ -327,12 +321,6 @@ void LTOModule::addDefinedDataSymbol(GlobalValue *v, Mangler &mangler) { } } } - - // add external symbols referenced by this data. - for (unsigned count = 0, total = v->getNumOperands(); - count != total; ++count) { - findExternalRefs(v->getOperand(count), mangler); - } } @@ -342,10 +330,6 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, if (def->getName().startswith("llvm.")) return; - // ignore available_externally - if (def->hasAvailableExternallyLinkage()) - return; - // string is owned by _defines SmallString<64> Buffer; mangler.getNameWithPrefix(Buffer, def, false); @@ -470,28 +454,6 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, } - -// Find external symbols referenced by VALUE. This is a recursive function. -void LTOModule::findExternalRefs(Value *value, Mangler &mangler) { - if (GlobalValue *gv = dyn_cast<GlobalValue>(value)) { - if (!gv->hasExternalLinkage()) - addPotentialUndefinedSymbol(gv, mangler); - // If this is a variable definition, do not recursively process - // initializer. It might contain a reference to this variable - // and cause an infinite loop. The initializer will be - // processed in addDefinedDataSymbol(). - return; - } - - // GlobalValue, even with InternalLinkage type, may have operands with - // ExternalLinkage type. Do not ignore these operands. - if (Constant *c = dyn_cast<Constant>(value)) { - // Handle ConstantExpr, ConstantStruct, ConstantArry etc. - for (unsigned i = 0, e = c->getNumOperands(); i != e; ++i) - findExternalRefs(c->getOperand(i), mangler); - } -} - namespace { class RecordStreamer : public MCStreamer { public: @@ -679,6 +641,18 @@ bool LTOModule::addAsmGlobalSymbols(MCContext &Context) { return false; } +static bool isDeclaration(const GlobalValue &V) { + if (V.hasAvailableExternallyLinkage()) + return true; + if (V.isMaterializable()) + return false; + return V.isDeclaration(); +} + +static bool isAliasToDeclaration(const GlobalAlias &V) { + return isDeclaration(*V.getAliasedGlobal()); +} + bool LTOModule::ParseSymbols() { // Use mangler to add GlobalPrefix to names to match linker names. MCContext Context(*_target->getMCAsmInfo(), NULL); @@ -686,7 +660,7 @@ bool LTOModule::ParseSymbols() { // add functions for (Module::iterator f = _module->begin(); f != _module->end(); ++f) { - if (f->isDeclaration()) + if (isDeclaration(*f)) addPotentialUndefinedSymbol(f, mangler); else addDefinedFunctionSymbol(f, mangler); @@ -695,7 +669,7 @@ bool LTOModule::ParseSymbols() { // add data for (Module::global_iterator v = _module->global_begin(), e = _module->global_end(); v != e; ++v) { - if (v->isDeclaration()) + if (isDeclaration(*v)) addPotentialUndefinedSymbol(v, mangler); else addDefinedDataSymbol(v, mangler); @@ -708,7 +682,7 @@ bool LTOModule::ParseSymbols() { // add aliases for (Module::alias_iterator i = _module->alias_begin(), e = _module->alias_end(); i != e; ++i) { - if (i->isDeclaration()) + if (isAliasToDeclaration(*i)) addPotentialUndefinedSymbol(i, mangler); else addDefinedDataSymbol(i, mangler); diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h index 21e8475..0b64a90 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -52,7 +52,12 @@ struct LTOModule { static LTOModule* makeLTOModule(const char* path, std::string& errMsg); static LTOModule* makeLTOModule(int fd, const char *path, - off_t size, + size_t size, + std::string& errMsg); + static LTOModule* makeLTOModule(int fd, const char *path, + size_t file_size, + size_t map_size, + off_t offset, std::string& errMsg); static LTOModule* makeLTOModule(const void* mem, size_t length, std::string& errMsg); @@ -77,8 +82,6 @@ private: bool isFunction); void addPotentialUndefinedSymbol(llvm::GlobalValue* decl, llvm::Mangler &mangler); - void findExternalRefs(llvm::Value* value, - llvm::Mangler& mangler); void addDefinedFunctionSymbol(llvm::Function* f, llvm::Mangler &mangler); void addDefinedDataSymbol(llvm::GlobalValue* v, diff --git a/tools/lto/Makefile b/tools/lto/Makefile index 294c81b..46925e7 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -20,7 +20,8 @@ include $(LEVEL)/Makefile.config LINK_LIBS_IN_SHARED = 1 SHARED_LIBRARY = 1 -LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader bitwriter +LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader \ + bitwriter mcdisassembler include $(LEVEL)/Makefile.common diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index f48570c..fe19921 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -95,12 +95,25 @@ lto_module_t lto_module_create(const char* path) // loads an object file from disk // returns NULL on error (check lto_get_error_message() for details) // -lto_module_t lto_module_create_from_fd(int fd, const char *path, off_t size) +lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) { return LTOModule::makeLTOModule(fd, path, size, sLastErrorString); } // +// loads an object file from disk +// returns NULL on error (check lto_get_error_message() for details) +// +lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path, + size_t file_size, + size_t map_size, + off_t offset) +{ + return LTOModule::makeLTOModule(fd, path, file_size, map_size, + offset, sLastErrorString); +} + +// // loads an object file from memory // returns NULL on error (check lto_get_error_message() for details) // @@ -280,6 +293,12 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length) return cg->compile(length, sLastErrorString); } +extern bool +lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) +{ + return cg->compile_to_file(name, sLastErrorString); +} + // // Used to pass extra options to the code generator diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index a374091..b900bfb 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -2,6 +2,7 @@ lto_get_error_message lto_get_version lto_module_create lto_module_create_from_fd +lto_module_create_from_fd_at_offset lto_module_create_from_memory lto_module_get_num_symbols lto_module_get_symbol_attribute @@ -25,3 +26,7 @@ lto_codegen_debug_options lto_codegen_set_assembler_args lto_codegen_set_assembler_path lto_codegen_set_cpu +lto_codegen_compile_to_file +LLVMCreateDisasm +LLVMDisasmDispose +LLVMDisasmInstruction diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp index c4c558d..f324259 100644 --- a/tools/macho-dump/macho-dump.cpp +++ b/tools/macho-dump/macho-dump.cpp @@ -49,25 +49,6 @@ static void Warning(const Twine &Msg) { /// -static int DumpHeader(MachOObject &Obj) { - // Read the header. - const macho::Header &Hdr = Obj.getHeader(); - outs() << "('cputype', " << Hdr.CPUType << ")\n"; - outs() << "('cpusubtype', " << Hdr.CPUSubtype << ")\n"; - outs() << "('filetype', " << Hdr.FileType << ")\n"; - outs() << "('num_load_commands', " << Hdr.NumLoadCommands << ")\n"; - outs() << "('load_commands_size', " << Hdr.SizeOfLoadCommands << ")\n"; - outs() << "('flag', " << Hdr.Flags << ")\n"; - - // Print extended header if 64-bit. - if (Obj.is64Bit()) { - const macho::Header64Ext &Hdr64 = Obj.getHeader64Ext(); - outs() << "('reserved', " << Hdr64.Reserved << ")\n"; - } - - return 0; -} - static void DumpSegmentCommandData(StringRef Name, uint64_t VMAddr, uint64_t VMSize, uint64_t FileOffset, uint64_t FileSize, @@ -376,8 +357,8 @@ int main(int argc, char **argv) { if (!InputObject) return Error("unable to load object: '" + ErrorStr + "'"); - if (int Res = DumpHeader(*InputObject)) - return Res; + // Print the header + InputObject->printHeader(outs()); // Print the load commands. int Res = 0; diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp index 791caf5..30361f5 100644 --- a/tools/opt/GraphPrinters.cpp +++ b/tools/opt/GraphPrinters.cpp @@ -18,7 +18,7 @@ #include "llvm/Pass.h" #include "llvm/Value.h" #include "llvm/Analysis/CallGraph.h" -#include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Analysis/Dominators.h" #include "llvm/Support/ToolOutputFile.h" using namespace llvm; @@ -103,13 +103,11 @@ namespace { virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired<DominatorTree>(); - AU.addRequired<DominanceFrontier>(); } virtual bool runOnFunction(Function &F) { getAnalysis<DominatorTree>().dump(); - getAnalysis<DominanceFrontier>().dump(); return false; } }; diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index e55b4b3..25474c4 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -26,6 +26,7 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/PassNameParser.h" #include "llvm/Support/Signals.h" @@ -132,11 +133,11 @@ static cl::opt<bool> AnalyzeOnly("analyze", cl::desc("Only perform analysis, no optimization")); static cl::opt<bool> -PrintBreakpoints("print-breakpoints-for-testing", +PrintBreakpoints("print-breakpoints-for-testing", cl::desc("Print select breakpoints location for testing")); static cl::opt<std::string> -DefaultDataLayout("default-data-layout", +DefaultDataLayout("default-data-layout", cl::desc("data layout string to use if not specified by module"), cl::value_desc("layout-string"), cl::init("")); @@ -327,7 +328,7 @@ struct BasicBlockPassPrinter : public BasicBlockPass { << "': Pass " << PassToPrint->getPassName() << ":\n"; // Get and print pass... - getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out, + getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out, BB.getParent()->getParent()); return false; } @@ -342,28 +343,43 @@ struct BasicBlockPassPrinter : public BasicBlockPass { char BasicBlockPassPrinter::ID = 0; -struct BreakpointPrinter : public FunctionPass { +struct BreakpointPrinter : public ModulePass { raw_ostream &Out; static char ID; BreakpointPrinter(raw_ostream &out) - : FunctionPass(ID), Out(out) { + : ModulePass(ID), Out(out) { } - virtual bool runOnFunction(Function &F) { - BasicBlock &EntryBB = F.getEntryBlock(); - BasicBlock::const_iterator BI = EntryBB.end(); - --BI; - do { - const Instruction *In = BI; - const DebugLoc DL = In->getDebugLoc(); - if (!DL.isUnknown()) { - DIScope S(DL.getScope(getGlobalContext())); - Out << S.getFilename() << " " << DL.getLine() << "\n"; - break; + void getContextName(DIDescriptor Context, std::string &N) { + if (Context.isNameSpace()) { + DINameSpace NS(Context); + if (!NS.getName().empty()) { + getContextName(NS.getContext(), N); + N = N + NS.getName().str() + "::"; + } + } else if (Context.isType()) { + DIType TY(Context); + if (!TY.getName().empty()) { + getContextName(TY.getContext(), N); + N = N + TY.getName().str() + "::"; + } + } + } + + virtual bool runOnModule(Module &M) { + StringSet<> Processed; + if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + std::string Name; + DISubprogram SP(NMD->getOperand(i)); + if (SP.Verify()) + getContextName(SP.getContext(), Name); + Name = Name + SP.getDisplayName().str(); + if (!Name.empty() && Processed.insert(Name)) { + Out << Name << "\n"; + } } - --BI; - } while (BI != EntryBB.begin()); return false; } @@ -463,7 +479,7 @@ int main(int argc, char **argv) { llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); - + // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); @@ -475,7 +491,7 @@ int main(int argc, char **argv) { initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); - + cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); @@ -533,12 +549,12 @@ int main(int argc, char **argv) { // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple())); - + // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLI->disableAllFunctions(); Passes.add(TLI); - + // Add an appropriate TargetData instance for this module. TargetData *TD = 0; const std::string &ModuleDataLayout = M.get()->getDataLayout(); @@ -562,7 +578,7 @@ int main(int argc, char **argv) { if (!Out) { if (OutputFilename.empty()) OutputFilename = "-"; - + std::string ErrorInfo; Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, raw_fd_ostream::F_Binary)); @@ -685,6 +701,9 @@ int main(int argc, char **argv) { Passes.add(createBitcodeWriterPass(Out->os())); } + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + // Now that we have all of the passes ready, run them. Passes.run(*M.get()); |