diff options
Diffstat (limited to 'tools')
116 files changed, 3843 insertions, 2743 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index e66648b..9668c76 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -11,11 +11,8 @@ if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/polly/CMakeLists.txt ) endif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/polly/CMakeLists.txt ) if( NOT WIN32 OR MSYS OR CYGWIN ) - # It is useful to build llvm-config before the other tools, so we - # have a fresh LibDeps.txt for regenerating the hard-coded library - # dependencies. llvm-config/CMakeLists.txt takes care of this but we - # must keep llvm-config as the first entry on the list of tools to - # be built. + # We currently require 'sed' to build llvm-config, so don't try to build it + # on pure Win32. add_subdirectory(llvm-config) endif() @@ -31,6 +28,7 @@ add_subdirectory(llvm-nm) add_subdirectory(llvm-size) add_subdirectory(llvm-ld) +add_subdirectory(llvm-cov) add_subdirectory(llvm-prof) add_subdirectory(llvm-link) add_subdirectory(lli) @@ -39,6 +37,7 @@ add_subdirectory(llvm-extract) add_subdirectory(llvm-diff) add_subdirectory(macho-dump) add_subdirectory(llvm-objdump) +add_subdirectory(llvm-readobj) add_subdirectory(llvm-rtdyld) add_subdirectory(llvm-dwarfdump) @@ -46,7 +45,7 @@ add_subdirectory(bugpoint) add_subdirectory(bugpoint-passes) add_subdirectory(llvm-bcanalyzer) add_subdirectory(llvm-stub) -add_subdirectory(edis) +add_subdirectory(llvm-stress) if( NOT WIN32 ) add_subdirectory(lto) @@ -59,11 +58,14 @@ if( LLVM_ENABLE_PIC ) endif() endif() -if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt ) +set(LLVM_CLANG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/clang" CACHE PATH "Path to Clang source directory") + +if (NOT ${LLVM_CLANG_SOURCE_DIR} STREQUAL "" + AND EXISTS ${LLVM_CLANG_SOURCE_DIR}/CMakeLists.txt) option(LLVM_BUILD_CLANG "Whether to build Clang as part of LLVM" ON) if (${LLVM_BUILD_CLANG}) - add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/clang ) + add_subdirectory(${LLVM_CLANG_SOURCE_DIR} clang) endif() -endif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt ) +endif () set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE) diff --git a/tools/LLVMBuild.txt b/tools/LLVMBuild.txt new file mode 100644 index 0000000..aba990f --- /dev/null +++ b/tools/LLVMBuild.txt @@ -0,0 +1,24 @@ +;===- ./tools/LLVMBuild.txt ------------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[common] +subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-ld llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-ranlib llvm-rtdyld llvm-size llvm-stub macho-dump opt + +[component_0] +type = Group +name = Tools +parent = $ROOT diff --git a/tools/Makefile b/tools/Makefile index 68ce314..8bf091a 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -9,8 +9,15 @@ LEVEL := .. +include $(LEVEL)/Makefile.config + # Build clang if present. -OPTIONAL_PARALLEL_DIRS := clang + +ifneq ($(CLANG_SRC_ROOT),) + OPTIONAL_PARALLEL_DIRS := $(CLANG_SRC_ROOT) +else + OPTIONAL_PARALLEL_DIRS := clang +endif # Build LLDB if present. Note LLDB must be built last as it depends on the # wider LLVM infrastructure (including Clang). @@ -25,9 +32,9 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \ llvm-ld llvm-prof llvm-link \ lli llvm-extract llvm-mc \ bugpoint llvm-bcanalyzer llvm-stub \ - llvm-diff macho-dump llvm-objdump \ + llvm-diff macho-dump llvm-objdump llvm-readobj \ llvm-rtdyld llvm-dwarfdump llvm-cov \ - llvm-size + llvm-size llvm-stress # Let users override the set of tools to build from the command line. ifdef ONLY_TOOLS @@ -36,9 +43,6 @@ ifdef ONLY_TOOLS PARALLEL_DIRS := $(filter-out lldb,$(ONLY_TOOLS)) endif -include $(LEVEL)/Makefile.config - - # These libraries build as dynamic libraries (.dylib /.so), they can only be # built if ENABLE_PIC is set. ifndef ONLY_TOOLS @@ -52,14 +56,6 @@ ifeq ($(ENABLE_PIC),1) endif PARALLEL_DIRS += bugpoint-passes - - # The edis library is only supported if ARM and/or X86 are enabled, and if - # LLVM is being built PIC on platforms that support dylibs. - ifneq ($(DISABLE_EDIS),1) - ifneq ($(filter $(TARGETS_TO_BUILD), X86 ARM),) - PARALLEL_DIRS += edis - endif - endif endif ifdef LLVM_HAS_POLLY diff --git a/tools/bugpoint-passes/Makefile b/tools/bugpoint-passes/Makefile index b4ad3e4..61f96bc 100644 --- a/tools/bugpoint-passes/Makefile +++ b/tools/bugpoint-passes/Makefile @@ -7,10 +7,10 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -LIBRARYNAME = BugpointPasses -LOADABLE_MODULE = 1 -USEDLIBS = +LEVEL := ../.. +LIBRARYNAME := BugpointPasses +LOADABLE_MODULE := 1 +USEDLIBS := # If we don't need RTTI or EH, there's no reason to export anything # from this plugin. diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index 677d178..6b219bf 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -87,7 +87,7 @@ Module *llvm::ParseInputFile(const std::string &Filename, SMDiagnostic Err; Module *Result = ParseIRFile(Filename, Err, Ctxt); if (!Result) - Err.Print("bugpoint", errs()); + Err.print("bugpoint", errs()); // If we don't have an override triple, use the first one to configure // bugpoint, or use the host triple if none provided. @@ -96,7 +96,7 @@ Module *llvm::ParseInputFile(const std::string &Filename, Triple TheTriple(Result->getTargetTriple()); if (TheTriple.getTriple().empty()) - TheTriple.setTriple(sys::getHostTriple()); + TheTriple.setTriple(sys::getDefaultTargetTriple()); TargetTriple.setTriple(TheTriple.getTriple()); } diff --git a/tools/bugpoint/CMakeLists.txt b/tools/bugpoint/CMakeLists.txt index e06feb1..ee2235b 100644 --- a/tools/bugpoint/CMakeLists.txt +++ b/tools/bugpoint/CMakeLists.txt @@ -1,5 +1,5 @@ set(LLVM_LINK_COMPONENTS asmparser instrumentation scalaropts ipo - linker bitreader bitwriter) + linker bitreader bitwriter vectorize) add_llvm_tool(bugpoint BugDriver.cpp diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index f19ef62..aed16f4 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -169,7 +169,7 @@ ReduceCrashingGlobalVariables::TestGlobalVariables( return false; } -namespace llvm { +namespace { /// ReduceCrashingFunctions reducer - This works by removing functions and /// seeing if the program still crashes. If it does, then keep the newer, /// smaller program. @@ -401,7 +401,8 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { Instruction *Inst = I++; - if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst)) { + if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst) && + !isa<LandingPadInst>(Inst)) { if (!Inst->getType()->isVoidTy()) Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); Inst->eraseFromParent(); @@ -568,12 +569,15 @@ static bool DebugACrash(BugDriver &BD, for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI) for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end(); - I != E; ++I, ++CurInstructionNum) + I != E; ++I, ++CurInstructionNum) { if (InstructionsToSkipBeforeDeleting) { --InstructionsToSkipBeforeDeleting; } else { if (BugpointIsInterrupted) goto ExitLoops; + if (isa<LandingPadInst>(I)) + continue; + outs() << "Checking instruction: " << *I; Module *M = BD.deleteInstructionFromProgram(I, Simplification); @@ -590,6 +594,7 @@ static bool DebugACrash(BugDriver &BD, // one. delete M; } + } if (InstructionsToSkipBeforeDeleting) { InstructionsToSkipBeforeDeleting = 0; diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index 77c01ac..218a559 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -28,8 +28,7 @@ namespace { // for miscompilation. // enum OutputType { - AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe, - CompileCustom, Custom + AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, LLC_Safe, CompileCustom, Custom }; cl::opt<double> @@ -48,8 +47,6 @@ namespace { 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"), clEnumValN(CompileCustom, "compile-custom", "Use -compile-command to define a command to " @@ -64,7 +61,6 @@ namespace { SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"), cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"), clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"), - clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"), clEnumValN(Custom, "safe-run-custom", "Use -exec-command to define a command to execute " "the bitcode. Useful for cross-compilation."), @@ -154,10 +150,6 @@ bool BugDriver::initializeExecutionEnvironment() { switch (InterpreterSel) { case AutoPick: - InterpreterSel = RunCBE; - Interpreter = - AbstractInterpreter::createCBE(getToolName(), Message, GCCBinary, - &ToolArgv, &GCCToolArgv); if (!Interpreter) { InterpreterSel = RunJIT; Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, @@ -195,12 +187,6 @@ bool BugDriver::initializeExecutionEnvironment() { Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, &ToolArgv); break; - case RunCBE: - case CBE_bug: - Interpreter = AbstractInterpreter::createCBE(getToolName(), Message, - GCCBinary, &ToolArgv, - &GCCToolArgv); - break; case CompileCustom: Interpreter = AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand); @@ -209,9 +195,6 @@ bool BugDriver::initializeExecutionEnvironment() { Interpreter = AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); break; - default: - Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; - break; } if (!Interpreter) errs() << Message; @@ -224,17 +207,6 @@ bool BugDriver::initializeExecutionEnvironment() { std::vector<std::string> SafeToolArgs = SafeToolArgv; switch (SafeInterpreterSel) { case AutoPick: - // In "cbe-bug" mode, default to using LLC as the "safe" backend. - if (!SafeInterpreter && - InterpreterSel == CBE_bug) { - SafeInterpreterSel = RunLLC; - SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, - &SafeToolArgs, - &GCCToolArgv); - } - // In "llc-safe" mode, default to using LLC as the "safe" backend. if (!SafeInterpreter && InterpreterSel == LLC_Safe) { @@ -246,17 +218,6 @@ bool BugDriver::initializeExecutionEnvironment() { &GCCToolArgv); } - // Pick a backend that's different from the test backend. The JIT and - // LLC backends share a lot of code, so prefer to use the CBE as the - // safe back-end when testing them. - if (!SafeInterpreter && - InterpreterSel != RunCBE) { - SafeInterpreterSel = RunCBE; - SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, - GCCBinary, - &SafeToolArgs, - &GCCToolArgv); - } if (!SafeInterpreter && InterpreterSel != RunLLC && InterpreterSel != RunJIT) { @@ -280,11 +241,6 @@ bool BugDriver::initializeExecutionEnvironment() { &GCCToolArgv, SafeInterpreterSel == RunLLCIA); break; - case RunCBE: - SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, - GCCBinary, &SafeToolArgs, - &GCCToolArgv); - break; case Custom: SafeInterpreter = AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); @@ -462,8 +418,8 @@ bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) { 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," - << " if CBE is being used as the \"safe\" backend), or fix the" + << " debug it (for example with the -run-jit bugpoint option," + << " if JIT is being used as the \"safe\" backend), or fix the" << " error some other way.\n"; } return false; diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 73b65ca..ac8e159 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -47,7 +47,39 @@ namespace { cl::opt<bool, true> NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG), cl::desc("Do not use the -simplifycfg pass to reduce testcases")); -} + + Function* globalInitUsesExternalBA(GlobalVariable* GV) { + if (!GV->hasInitializer()) + return 0; + + Constant *I = GV->getInitializer(); + + // walk the values used by the initializer + // (and recurse into things like ConstantExpr) + std::vector<Constant*> Todo; + std::set<Constant*> Done; + Todo.push_back(I); + + while (!Todo.empty()) { + Constant* V = Todo.back(); + Todo.pop_back(); + Done.insert(V); + + if (BlockAddress *BA = dyn_cast<BlockAddress>(V)) { + Function *F = BA->getFunction(); + if (F->isDeclaration()) + return F; + } + + for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) { + Constant *C = dyn_cast<Constant>(*i); + if (C && !isa<GlobalValue>(C) && !Done.count(C)) + Todo.push_back(C); + } + } + return 0; + } +} // end anonymous namespace /// deleteInstructionFromProgram - This method clones the current Program and /// deletes the specified instruction from the cloned module. It then runs a @@ -272,11 +304,6 @@ llvm::SplitFunctionsOutOfModule(Module *M, ValueToValueMapTy NewVMap; Module *New = CloneModule(M, NewVMap); - // Make sure global initializers exist only in the safe module (CBE->.so) - for (Module::global_iterator I = New->global_begin(), E = New->global_end(); - I != E; ++I) - I->setInitializer(0); // Delete the initializer to make it external - // Remove the Test functions from the Safe module std::set<Function *> TestFunctions; for (unsigned i = 0, e = F.size(); i != e; ++i) { @@ -295,6 +322,27 @@ llvm::SplitFunctionsOutOfModule(Module *M, DeleteFunctionBody(I); + // Try to split the global initializers evenly + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + GlobalVariable *GV = cast<GlobalVariable>(NewVMap[I]); + if (Function *TestFn = globalInitUsesExternalBA(I)) { + if (Function *SafeFn = globalInitUsesExternalBA(GV)) { + errs() << "*** Error: when reducing functions, encountered " + "the global '"; + WriteAsOperand(errs(), GV, false); + errs() << "' with an initializer that references blockaddresses " + "from safe function '" << SafeFn->getName() + << "' and from test function '" << TestFn->getName() << "'.\n"; + exit(1); + } + I->setInitializer(0); // Delete the initializer to make it external + } else { + // If we keep it in the safe module, then delete it in the test module + GV->setInitializer(0); + } + } + // Make sure that there is a global ctor/dtor array in both halves of the // module if they both have static ctor/dtor functions. SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap); @@ -340,7 +388,7 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const // If the BB doesn't have a name, give it one so we have something to key // off of. if (!BB->hasName()) BB->setName("tmpbb"); - BlocksToNotExtractFile.os() << BB->getParent()->getNameStr() << " " + BlocksToNotExtractFile.os() << BB->getParent()->getName() << " " << BB->getName() << "\n"; } BlocksToNotExtractFile.os().close(); diff --git a/tools/bugpoint/LLVMBuild.txt b/tools/bugpoint/LLVMBuild.txt new file mode 100644 index 0000000..549d9d0 --- /dev/null +++ b/tools/bugpoint/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/bugpoint/LLVMBuild.txt ---------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = bugpoint +parent = Tools +required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Linker Scalar diff --git a/tools/bugpoint/Makefile b/tools/bugpoint/Makefile index 5d287ef..34f4bdd 100644 --- a/tools/bugpoint/Makefile +++ b/tools/bugpoint/Makefile @@ -6,11 +6,10 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = bugpoint - -LINK_COMPONENTS := asmparser instrumentation scalaropts ipo \ - linker bitreader bitwriter +LEVEL := ../.. +TOOLNAME := bugpoint +LINK_COMPONENTS := asmparser instrumentation scalaropts ipo linker bitreader \ + bitwriter vectorize include $(LEVEL)/Makefile.common diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 7ff16db..82a3a86 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -820,7 +820,8 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Don't forward functions which are external in the test module too. if (TestFn && !TestFn->isDeclaration()) { // 1. Add a string constant with its name to the global file - Constant *InitArray = ConstantArray::get(F->getContext(), F->getName()); + Constant *InitArray = + ConstantDataArray::getString(F->getContext(), F->getName()); GlobalVariable *funcName = new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, GlobalValue::InternalLinkage, InitArray, diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index 336c83d..fb090ee 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -85,8 +85,11 @@ void BugDriver::EmitProgressBitcode(const Module *M, if (NoFlyer || PassesToRun.empty()) return; outs() << "\n*** You can reproduce the problem with: "; if (UseValgrind) outs() << "valgrind "; - outs() << "opt " << Filename << " "; - outs() << getPassesString(PassesToRun) << "\n"; + outs() << "opt " << Filename; + for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { + outs() << " -load " << PluginLoader::getPlugin(i); + } + outs() << " " << getPassesString(PassesToRun) << "\n"; } cl::opt<bool> SilencePasses("silence-passes", @@ -145,10 +148,9 @@ bool BugDriver::runPasses(Module *Program, return 1; } - sys::Path tool = PrependMainExecutablePath("opt", getToolName(), - (void*)"opt"); + sys::Path tool = sys::Program::FindProgramByName("opt"); if (tool.empty()) { - errs() << "Cannot find `opt' in executable directory!\n"; + errs() << "Cannot find `opt' in PATH!\n"; return 1; } diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 0d98262..25a2bae 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -234,6 +234,8 @@ int LLI::ExecuteProgram(const std::string &Bitcode, Timeout, MemoryLimit, Error); } +void AbstractInterpreter::anchor() { } + // LLI create method - Try to find the LLI executable AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, std::string &Message, @@ -621,94 +623,6 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, return 0; } -GCC::FileType CBE::OutputCode(const std::string &Bitcode, - sys::Path &OutputCFile, std::string &Error, - unsigned Timeout, unsigned MemoryLimit) { - sys::Path uniqueFile(Bitcode+".cbe.c"); - std::string ErrMsg; - if (uniqueFile.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; - exit(1); - } - OutputCFile = uniqueFile; - std::vector<const char *> LLCArgs; - 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(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) - errs() << " " << LLCArgs[i]; - errs() << "\n"; - ); - if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), - sys::Path(), Timeout, MemoryLimit)) - Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); - return GCC::CFile; -} - -void CBE::compileProgram(const std::string &Bitcode, std::string *Error, - unsigned Timeout, unsigned MemoryLimit) { - sys::Path OutputCFile; - OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); - OutputCFile.eraseFromDisk(); -} - -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, *Error, Timeout, MemoryLimit); - - FileRemover CFileRemove(OutputCFile.str(), !SaveTemps); - - std::vector<std::string> GCCArgs(ArgsForGCC); - GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); - - return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, - InputFile, OutputFile, Error, GCCArgs, - Timeout, MemoryLimit); -} - -/// createCBE - Try to find the 'llc' executable -/// -CBE *AbstractInterpreter::createCBE(const char *Argv0, - std::string &Message, - const std::string &GCCBinary, - const std::vector<std::string> *Args, - const std::vector<std::string> *GCCArgs) { - sys::Path LLCPath = - PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createCBE); - if (LLCPath.isEmpty()) { - Message = - "Cannot find `llc' in executable directory!\n"; - return 0; - } - - Message = "Found llc: " + LLCPath.str() + "\n"; - GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); - if (!gcc) { - errs() << Message << "\n"; - exit(1); - } - return new CBE(LLCPath, gcc, Args); -} - //===---------------------------------------------------------------------===// // GCC abstraction // @@ -920,8 +834,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, } else GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others - if ((TargetTriple.getArch() == Triple::alpha) || - (TargetTriple.getArch() == Triple::x86_64)) + if (TargetTriple.getArch() == Triple::x86_64) GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC if (TargetTriple.getArch() == Triple::sparc) diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index cfa8acf..7b93394 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -86,6 +86,7 @@ public: /// complexity behind a simple interface. /// class AbstractInterpreter { + virtual void anchor(); public: static CBE *createCBE(const char *Argv0, std::string &Message, const std::string &GCCBinary, diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index 6a87521..8f15b02 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -120,6 +120,7 @@ int main(int argc, char **argv) { PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); + initializeVectorization(Registry); initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); diff --git a/tools/edis/CMakeLists.txt b/tools/edis/CMakeLists.txt deleted file mode 100644 index 1e162f9..0000000 --- a/tools/edis/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -set(SOURCES - ../../include/llvm-c/EnhancedDisassembly.h - EDMain.cpp - ) - -set(EDIS_DEPENDS LLVMMCDisassembler LLVMMCParser) -if( LLVM_TARGETS_TO_BUILD MATCHES X86 ) - list(APPEND EDIS_DEPENDS LLVMX86AsmPrinter LLVMX86AsmParser LLVMX86Disassembler LLVMX86Desc) -endif() -if( LLVM_TARGETS_TO_BUILD MATCHES ARM ) - list(APPEND EDIS_DEPENDS LLVMARMAsmPrinter LLVMARMAsmParser LLVMARMDisassembler LLVMARMDesc) -endif() - -add_llvm_library(EnhancedDisassembly ${SOURCES}) -set_property(TARGET EnhancedDisassembly PROPERTY - OUTPUT_NAME "EnhancedDisassembly") - -add_llvm_library_dependencies(EnhancedDisassembly - ${EDIS_DEPENDS}) diff --git a/tools/edis/EDMain.cpp b/tools/edis/EDMain.cpp deleted file mode 100644 index 16855b3..0000000 --- a/tools/edis/EDMain.cpp +++ /dev/null @@ -1,284 +0,0 @@ -//===-- EDMain.cpp - LLVM Enhanced Disassembly C API ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the enhanced disassembler's public C API. -// -//===----------------------------------------------------------------------===// - -// FIXME: This code isn't layered right, the headers should be moved to -// include llvm/MC/MCDisassembler or something. -#include "../../lib/MC/MCDisassembler/EDDisassembler.h" -#include "../../lib/MC/MCDisassembler/EDInst.h" -#include "../../lib/MC/MCDisassembler/EDOperand.h" -#include "../../lib/MC/MCDisassembler/EDToken.h" -#include "llvm-c/EnhancedDisassembly.h" -using namespace llvm; - -int EDGetDisassembler(EDDisassemblerRef *disassembler, - const char *triple, - EDAssemblySyntax_t syntax) { - EDDisassembler::initialize(); - - EDDisassembler::AssemblySyntax Syntax; - switch (syntax) { - default: assert(0 && "Unknown assembly syntax!"); - case kEDAssemblySyntaxX86Intel: - Syntax = EDDisassembler::kEDAssemblySyntaxX86Intel; - break; - case kEDAssemblySyntaxX86ATT: - Syntax = EDDisassembler::kEDAssemblySyntaxX86ATT; - break; - case kEDAssemblySyntaxARMUAL: - Syntax = EDDisassembler::kEDAssemblySyntaxARMUAL; - break; - } - - EDDisassemblerRef ret = EDDisassembler::getDisassembler(triple, Syntax); - - if (!ret) - return -1; - *disassembler = ret; - return 0; -} - -int EDGetRegisterName(const char** regName, - EDDisassemblerRef disassembler, - unsigned regID) { - const char *name = ((EDDisassembler*)disassembler)->nameWithRegisterID(regID); - if (!name) - return -1; - *regName = name; - return 0; -} - -int EDRegisterIsStackPointer(EDDisassemblerRef disassembler, - unsigned regID) { - return ((EDDisassembler*)disassembler)->registerIsStackPointer(regID) ? 1 : 0; -} - -int EDRegisterIsProgramCounter(EDDisassemblerRef disassembler, - unsigned regID) { - return ((EDDisassembler*)disassembler)->registerIsProgramCounter(regID) ? 1:0; -} - -unsigned int EDCreateInsts(EDInstRef *insts, - unsigned int count, - EDDisassemblerRef disassembler, - ::EDByteReaderCallback byteReader, - uint64_t address, - void *arg) { - unsigned int index; - - for (index = 0; index < count; ++index) { - EDInst *inst = ((EDDisassembler*)disassembler)->createInst(byteReader, - address, arg); - - if (!inst) - return index; - - insts[index] = inst; - address += inst->byteSize(); - } - - return count; -} - -void EDReleaseInst(EDInstRef inst) { - delete ((EDInst*)inst); -} - -int EDInstByteSize(EDInstRef inst) { - return ((EDInst*)inst)->byteSize(); -} - -int EDGetInstString(const char **buf, - EDInstRef inst) { - return ((EDInst*)inst)->getString(*buf); -} - -int EDInstID(unsigned *instID, EDInstRef inst) { - *instID = ((EDInst*)inst)->instID(); - return 0; -} - -int EDInstIsBranch(EDInstRef inst) { - return ((EDInst*)inst)->isBranch(); -} - -int EDInstIsMove(EDInstRef inst) { - return ((EDInst*)inst)->isMove(); -} - -int EDBranchTargetID(EDInstRef inst) { - return ((EDInst*)inst)->branchTargetID(); -} - -int EDMoveSourceID(EDInstRef inst) { - return ((EDInst*)inst)->moveSourceID(); -} - -int EDMoveTargetID(EDInstRef inst) { - return ((EDInst*)inst)->moveTargetID(); -} - -int EDNumTokens(EDInstRef inst) { - return ((EDInst*)inst)->numTokens(); -} - -int EDGetToken(EDTokenRef *token, - EDInstRef inst, - int index) { - return ((EDInst*)inst)->getToken(*(EDToken**)token, index); -} - -int EDGetTokenString(const char **buf, - EDTokenRef token) { - return ((EDToken*)token)->getString(*buf); -} - -int EDOperandIndexForToken(EDTokenRef token) { - return ((EDToken*)token)->operandID(); -} - -int EDTokenIsWhitespace(EDTokenRef token) { - return ((EDToken*)token)->type() == EDToken::kTokenWhitespace; -} - -int EDTokenIsPunctuation(EDTokenRef token) { - return ((EDToken*)token)->type() == EDToken::kTokenPunctuation; -} - -int EDTokenIsOpcode(EDTokenRef token) { - return ((EDToken*)token)->type() == EDToken::kTokenOpcode; -} - -int EDTokenIsLiteral(EDTokenRef token) { - return ((EDToken*)token)->type() == EDToken::kTokenLiteral; -} - -int EDTokenIsRegister(EDTokenRef token) { - return ((EDToken*)token)->type() == EDToken::kTokenRegister; -} - -int EDTokenIsNegativeLiteral(EDTokenRef token) { - if (((EDToken*)token)->type() != EDToken::kTokenLiteral) - return -1; - - return ((EDToken*)token)->literalSign(); -} - -int EDLiteralTokenAbsoluteValue(uint64_t *value, EDTokenRef token) { - if (((EDToken*)token)->type() != EDToken::kTokenLiteral) - return -1; - - return ((EDToken*)token)->literalAbsoluteValue(*value); -} - -int EDRegisterTokenValue(unsigned *registerID, - EDTokenRef token) { - if (((EDToken*)token)->type() != EDToken::kTokenRegister) - return -1; - - return ((EDToken*)token)->registerID(*registerID); -} - -int EDNumOperands(EDInstRef inst) { - return ((EDInst*)inst)->numOperands(); -} - -int EDGetOperand(EDOperandRef *operand, - EDInstRef inst, - int index) { - return ((EDInst*)inst)->getOperand(*(EDOperand**)operand, index); -} - -int EDOperandIsRegister(EDOperandRef operand) { - return ((EDOperand*)operand)->isRegister(); -} - -int EDOperandIsImmediate(EDOperandRef operand) { - return ((EDOperand*)operand)->isImmediate(); -} - -int EDOperandIsMemory(EDOperandRef operand) { - return ((EDOperand*)operand)->isMemory(); -} - -int EDRegisterOperandValue(unsigned *value, EDOperandRef operand) { - if (!((EDOperand*)operand)->isRegister()) - return -1; - *value = ((EDOperand*)operand)->regVal(); - return 0; -} - -int EDImmediateOperandValue(uint64_t *value, EDOperandRef operand) { - if (!((EDOperand*)operand)->isImmediate()) - return -1; - *value = ((EDOperand*)operand)->immediateVal(); - return 0; -} - -int EDEvaluateOperand(uint64_t *result, EDOperandRef operand, - ::EDRegisterReaderCallback regReader, void *arg) { - return ((EDOperand*)operand)->evaluate(*result, regReader, arg); -} - -#ifdef __BLOCKS__ - -struct ByteReaderWrapper { - EDByteBlock_t byteBlock; -}; - -static int readerWrapperCallback(uint8_t *byte, - uint64_t address, - void *arg) { - struct ByteReaderWrapper *wrapper = (struct ByteReaderWrapper *)arg; - return wrapper->byteBlock(byte, address); -} - -unsigned int EDBlockCreateInsts(EDInstRef *insts, - int count, - EDDisassemblerRef disassembler, - EDByteBlock_t byteBlock, - uint64_t address) { - struct ByteReaderWrapper wrapper; - wrapper.byteBlock = byteBlock; - - return EDCreateInsts(insts, - count, - disassembler, - readerWrapperCallback, - address, - (void*)&wrapper); -} - -int EDBlockEvaluateOperand(uint64_t *result, EDOperandRef operand, - EDRegisterBlock_t regBlock) { - return ((EDOperand*)operand)->evaluate(*result, regBlock); -} - -int EDBlockVisitTokens(EDInstRef inst, ::EDTokenVisitor_t visitor) { - return ((EDInst*)inst)->visitTokens((llvm::EDTokenVisitor_t)visitor); -} - -#else - -extern "C" unsigned int EDBlockCreateInsts() { - return 0; -} - -extern "C" int EDBlockEvaluateOperand() { - return -1; -} - -extern "C" int EDBlockVisitTokens() { - return -1; -} - -#endif diff --git a/tools/edis/Makefile b/tools/edis/Makefile deleted file mode 100644 index 3fcb408..0000000 --- a/tools/edis/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -##===- tools/edis/Makefile -----------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = EnhancedDisassembly -LINK_LIBS_IN_SHARED = 1 - -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_COMPONENTS := mcdisassembler - -# If the X86 target is enabled, link in the asmprinter and disassembler. -ifneq ($(filter $(TARGETS_TO_BUILD), X86),) -LINK_COMPONENTS += x86asmprinter x86disassembler -endif - -# If the ARM target is enabled, link in the asmprinter and disassembler. -ifneq ($(filter $(TARGETS_TO_BUILD), ARM),) -LINK_COMPONENTS += armasmprinter armdisassembler -endif - -include $(LEVEL)/Makefile.common - -ifeq ($(HOST_OS),Darwin) - # extra options to override libtool defaults - LLVMLibsOptions := $(LLVMLibsOptions) \ - -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) \ - -Wl,-install_name \ - -Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)" - endif -endif - diff --git a/tools/gold/CMakeLists.txt b/tools/gold/CMakeLists.txt index eb4b6e6..2cc132f 100644 --- a/tools/gold/CMakeLists.txt +++ b/tools/gold/CMakeLists.txt @@ -40,6 +40,7 @@ else() set_property(SOURCE gold-plugin.cpp APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/exportsfile) - target_link_libraries(LLVMgold LTO -Wl,--version-script,exportsfile) + target_link_libraries(LLVMgold LTO + -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/exportsfile) add_dependencies(LLVMgold gold_exports) endif() diff --git a/tools/gold/Makefile b/tools/gold/Makefile index 759406f..02f66d7 100644 --- a/tools/gold/Makefile +++ b/tools/gold/Makefile @@ -7,8 +7,12 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -LIBRARYNAME = LLVMgold +LEVEL := ../.. +LIBRARYNAME := LLVMgold +LINK_COMPONENTS := support +LINK_LIBS_IN_SHARED := 1 +SHARED_LIBRARY := 1 +LOADABLE_MODULE := 1 EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/gold.exports @@ -17,15 +21,9 @@ EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/gold.exports # early so we can set up LINK_COMPONENTS before including Makefile.rules include $(LEVEL)/Makefile.config -LINK_LIBS_IN_SHARED=1 -SHARED_LIBRARY = 1 -LOADABLE_MODULE = 1 - -LINK_COMPONENTS := support - # Because off_t is used in the public API, the largefile parts are required for # ABI compatibility. -CXXFLAGS+=-I$(BINUTILS_INCDIR) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -CXXFLAGS+=$(SharedLibDir)/$(SharedPrefix)LTO$(SHLIBEXT) +CXXFLAGS += -I$(BINUTILS_INCDIR) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +CXXFLAGS += -L$(SharedLibDir)/$(SharedPrefix) -lLTO include $(LEVEL)/Makefile.common diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 6f547b3..cfd84c0 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Config/config.h" +#include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H #include "plugin-api.h" #include "llvm-c/lto.h" diff --git a/tools/llc/LLVMBuild.txt b/tools/llc/LLVMBuild.txt new file mode 100644 index 0000000..8c8794f --- /dev/null +++ b/tools/llc/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llc/LLVMBuild.txt --------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llc +parent = Tools +required_libraries = AsmParser BitReader all-targets diff --git a/tools/llc/Makefile b/tools/llc/Makefile index 7319aad..b32d557 100644 --- a/tools/llc/Makefile +++ b/tools/llc/Makefile @@ -7,15 +7,9 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llc +LEVEL := ../.. +TOOLNAME := llc +LINK_COMPONENTS := all-targets bitreader asmparser -# 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) bitreader asmparser - -include $(LLVM_SRC_ROOT)/Makefile.rules +include $(LEVEL)/Makefile.common diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index d29bd9b..9e30ac1 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -21,7 +21,6 @@ #include "llvm/Support/IRReader.h" #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" -#include "llvm/Config/config.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -133,11 +132,147 @@ cl::opt<bool> DisableDotLoc("disable-dot-loc", cl::Hidden, cl::opt<bool> DisableCFI("disable-cfi", cl::Hidden, cl::desc("Do not use .cfi_* directives")); +cl::opt<bool> EnableDwarfDirectory("enable-dwarf-directory", cl::Hidden, + cl::desc("Use .file directives with an explicit directory.")); + static cl::opt<bool> DisableRedZone("disable-red-zone", cl::desc("Do not emit code that uses the red zone."), cl::init(false)); +static cl::opt<bool> +EnableFPMAD("enable-fp-mad", + cl::desc("Enable less precise MAD instructions to be generated"), + cl::init(false)); + +static cl::opt<bool> +PrintCode("print-machineinstrs", + cl::desc("Print generated machine code"), + cl::init(false)); + +static cl::opt<bool> +DisableFPElim("disable-fp-elim", + cl::desc("Disable frame pointer elimination optimization"), + cl::init(false)); + +static cl::opt<bool> +DisableFPElimNonLeaf("disable-non-leaf-fp-elim", + cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"), + cl::init(false)); + +static cl::opt<bool> +DisableExcessPrecision("disable-excess-fp-precision", + cl::desc("Disable optimizations that may increase FP precision"), + cl::init(false)); + +static cl::opt<bool> +EnableUnsafeFPMath("enable-unsafe-fp-math", + cl::desc("Enable optimizations that may decrease FP precision"), + cl::init(false)); + +static cl::opt<bool> +EnableNoInfsFPMath("enable-no-infs-fp-math", + cl::desc("Enable FP math optimizations that assume no +-Infs"), + cl::init(false)); + +static cl::opt<bool> +EnableNoNaNsFPMath("enable-no-nans-fp-math", + cl::desc("Enable FP math optimizations that assume no NaNs"), + cl::init(false)); + +static cl::opt<bool> +EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", + cl::Hidden, + cl::desc("Force codegen to assume rounding mode can change dynamically"), + cl::init(false)); + +static cl::opt<bool> +GenerateSoftFloatCalls("soft-float", + cl::desc("Generate software floating point library calls"), + cl::init(false)); + +static cl::opt<llvm::FloatABI::ABIType> +FloatABIForCalls("float-abi", + cl::desc("Choose float ABI type"), + cl::init(FloatABI::Default), + cl::values( + clEnumValN(FloatABI::Default, "default", + "Target default float ABI type"), + clEnumValN(FloatABI::Soft, "soft", + "Soft float ABI (implied by -soft-float)"), + clEnumValN(FloatABI::Hard, "hard", + "Hard float ABI (uses FP registers)"), + clEnumValEnd)); + +static cl::opt<bool> +DontPlaceZerosInBSS("nozero-initialized-in-bss", + cl::desc("Don't place zero-initialized symbols into bss section"), + cl::init(false)); + +static cl::opt<bool> +EnableJITExceptionHandling("jit-enable-eh", + cl::desc("Emit exception handling information"), + cl::init(false)); + +// In debug builds, make this default to true. +#ifdef NDEBUG +#define EMIT_DEBUG false +#else +#define EMIT_DEBUG true +#endif +static cl::opt<bool> +EmitJitDebugInfo("jit-emit-debug", + cl::desc("Emit debug information to debugger"), + cl::init(EMIT_DEBUG)); +#undef EMIT_DEBUG + +static cl::opt<bool> +EmitJitDebugInfoToDisk("jit-emit-debug-to-disk", + cl::Hidden, + cl::desc("Emit debug info objfiles to disk"), + cl::init(false)); + +static cl::opt<bool> +EnableGuaranteedTailCallOpt("tailcallopt", + cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."), + cl::init(false)); + +static cl::opt<bool> +DisableTailCalls("disable-tail-calls", + cl::desc("Never emit tail calls"), + cl::init(false)); + +static cl::opt<unsigned> +OverrideStackAlignment("stack-alignment", + cl::desc("Override default stack alignment"), + cl::init(0)); + +static cl::opt<bool> +EnableRealignStack("realign-stack", + cl::desc("Realign stack if needed"), + cl::init(true)); + +static cl::opt<bool> +DisableSwitchTables(cl::Hidden, "disable-jump-tables", + cl::desc("Do not generate jump tables."), + cl::init(false)); + +static cl::opt<std::string> +TrapFuncName("trap-func", cl::Hidden, + cl::desc("Emit a call to trap function rather than a trap instruction"), + cl::init("")); + +static cl::opt<bool> +EnablePIE("enable-pie", + cl::desc("Assume the creation of a position independent executable."), + cl::init(false)); + +static cl::opt<bool> +SegmentedStacks("segmented-stacks", + cl::desc("Use segmented stacks if possible."), + cl::init(false)); + + // GetFileNameRoot - Helper function to get the basename of a filename. static inline std::string GetFileNameRoot(const std::string &InputFilename) { @@ -166,7 +301,6 @@ static tool_output_file *GetOutputStream(const char *TargetName, OutputFilename = GetFileNameRoot(InputFilename); switch (FileType) { - default: assert(0 && "Unknown file type"); case TargetMachine::CGFT_AssemblyFile: if (TargetName[0] == 'c') { if (TargetName[1] == 0) @@ -194,7 +328,6 @@ static tool_output_file *GetOutputStream(const char *TargetName, // Decide if we need "binary" output. bool Binary = false; switch (FileType) { - default: assert(0 && "Unknown file type"); case TargetMachine::CGFT_AssemblyFile: break; case TargetMachine::CGFT_ObjectFile: @@ -247,7 +380,7 @@ int main(int argc, char **argv) { M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { - Err.Print(argv[0], errs()); + Err.print(argv[0], errs()); return 1; } Module &mod = *M.get(); @@ -258,7 +391,7 @@ int main(int argc, char **argv) { Triple TheTriple(mod.getTargetTriple()); if (TheTriple.getTriple().empty()) - TheTriple.setTriple(sys::getHostTriple()); + TheTriple.setTriple(sys::getDefaultTargetTriple()); // Allocate target machine. First, check whether the user has explicitly // specified an architecture to compile for. If so we have to look it up by @@ -303,10 +436,49 @@ int main(int argc, char **argv) { FeaturesStr = Features.getString(); } + CodeGenOpt::Level OLvl = CodeGenOpt::Default; + switch (OptLevel) { + default: + errs() << argv[0] << ": invalid optimization level.\n"; + return 1; + case ' ': break; + case '0': OLvl = CodeGenOpt::None; break; + case '1': OLvl = CodeGenOpt::Less; break; + case '2': OLvl = CodeGenOpt::Default; break; + case '3': OLvl = CodeGenOpt::Aggressive; break; + } + + TargetOptions Options; + Options.LessPreciseFPMADOption = EnableFPMAD; + Options.PrintMachineCode = PrintCode; + Options.NoFramePointerElim = DisableFPElim; + Options.NoFramePointerElimNonLeaf = DisableFPElimNonLeaf; + Options.NoExcessFPPrecision = DisableExcessPrecision; + Options.UnsafeFPMath = EnableUnsafeFPMath; + Options.NoInfsFPMath = EnableNoInfsFPMath; + Options.NoNaNsFPMath = EnableNoNaNsFPMath; + Options.HonorSignDependentRoundingFPMathOption = + EnableHonorSignDependentRoundingFPMath; + Options.UseSoftFloat = GenerateSoftFloatCalls; + if (FloatABIForCalls != FloatABI::Default) + Options.FloatABIType = FloatABIForCalls; + Options.NoZerosInBSS = DontPlaceZerosInBSS; + Options.JITExceptionHandling = EnableJITExceptionHandling; + Options.JITEmitDebugInfo = EmitJitDebugInfo; + Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk; + Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; + Options.DisableTailCalls = DisableTailCalls; + Options.StackAlignmentOverride = OverrideStackAlignment; + Options.RealignStack = EnableRealignStack; + Options.DisableJumpTables = DisableSwitchTables; + Options.TrapFuncName = TrapFuncName; + Options.PositionIndependentExecutable = EnablePIE; + Options.EnableSegmentedStacks = SegmentedStacks; + std::auto_ptr<TargetMachine> target(TheTarget->createTargetMachine(TheTriple.getTriple(), - MCPU, FeaturesStr, - RelocModel, CMModel)); + MCPU, FeaturesStr, Options, + RelocModel, CMModel, OLvl)); assert(target.get() && "Could not allocate target machine!"); TargetMachine &Target = *target.get(); @@ -316,6 +488,12 @@ int main(int argc, char **argv) { if (DisableCFI) Target.setMCUseCFI(false); + if (EnableDwarfDirectory) + Target.setMCUseDwarfDirectory(true); + + if (GenerateSoftFloatCalls) + FloatABIForCalls = FloatABI::Soft; + // Disable .loc support for older OS X versions. if (TheTriple.isMacOSX() && TheTriple.isMacOSXVersionLT(10, 6)) @@ -326,18 +504,6 @@ int main(int argc, char **argv) { (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); if (!Out) return 1; - CodeGenOpt::Level OLvl = CodeGenOpt::Default; - switch (OptLevel) { - default: - errs() << argv[0] << ": invalid optimization level.\n"; - return 1; - case ' ': break; - case '0': OLvl = CodeGenOpt::None; break; - case '1': OLvl = CodeGenOpt::Less; break; - case '2': OLvl = CodeGenOpt::Default; break; - case '3': OLvl = CodeGenOpt::Aggressive; break; - } - // Build up all of the passes that we want to do to the module. PassManager PM; @@ -362,7 +528,7 @@ int main(int argc, char **argv) { formatted_raw_ostream FOS(Out->os()); // Ask the target to add backend passes as necessary. - if (Target.addPassesToEmitFile(PM, FOS, FileType, OLvl, NoVerify)) { + if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt index 9378ef2..a5d2e61 100644 --- a/tools/lli/CMakeLists.txt +++ b/tools/lli/CMakeLists.txt @@ -1,5 +1,22 @@ + +link_directories( ${LLVM_INTEL_JITEVENTS_LIBDIR} ) + set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser selectiondag) +if( LLVM_USE_OPROFILE ) + set(LLVM_LINK_COMPONENTS + ${LLVM_LINK_COMPONENTS} + OProfileJIT + ) +endif( LLVM_USE_OPROFILE ) + +if( LLVM_USE_INTEL_JITEVENTS ) + set(LLVM_LINK_COMPONENTS + ${LLVM_LINK_COMPONENTS} + IntelJITEvents + ) +endif( LLVM_USE_INTEL_JITEVENTS ) + add_llvm_tool(lli lli.cpp ) diff --git a/tools/lli/LLVMBuild.txt b/tools/lli/LLVMBuild.txt new file mode 100644 index 0000000..4eb82bd --- /dev/null +++ b/tools/lli/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/lli/LLVMBuild.txt --------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = lli +parent = Tools +required_libraries = AsmParser BitReader Interpreter JIT MCJIT NativeCodeGen SelectionDAG diff --git a/tools/lli/Makefile b/tools/lli/Makefile index 80aa82b..100fc2e 100644 --- a/tools/lli/Makefile +++ b/tools/lli/Makefile @@ -7,9 +7,23 @@ # ##===----------------------------------------------------------------------===## -LEVEL := ../.. +LEVEL := ../.. TOOLNAME := lli + +include $(LEVEL)/Makefile.config + LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selectiondag -# Enable JIT support -include $(LEVEL)/Makefile.common +# If Intel JIT Events support is confiured, link against the LLVM Intel JIT +# Events interface library +ifeq ($(USE_INTEL_JITEVENTS), 1) + LINK_COMPONENTS += inteljitevents +endif + +# If oprofile support is confiured, link against the LLVM oprofile interface +# library +ifeq ($(USE_OPROFILE), 1) + LINK_COMPONENTS += oprofilejit +endif + +include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 50c7a49..efcc1f5 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -23,6 +23,7 @@ #include "llvm/ExecutionEngine/Interpreter.h" #include "llvm/ExecutionEngine/JIT.h" #include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/IRReader.h" @@ -94,12 +95,12 @@ namespace { "of the executable"), cl::value_desc("function"), cl::init("main")); - + cl::opt<std::string> FakeArgv0("fake-argv0", cl::desc("Override the 'argv[0]' value passed into the executing" " program"), cl::value_desc("executable")); - + cl::opt<bool> DisableCoreFiles("disable-core-files", cl::Hidden, cl::desc("Disable emission of core files if possible")); @@ -158,7 +159,7 @@ static void do_shutdown() { int main(int argc, char **argv, char * const *envp) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); - + LLVMContext &Context = getGlobalContext(); atexit(do_shutdown); // Call llvm_shutdown() on exit. @@ -173,12 +174,12 @@ int main(int argc, char **argv, char * const *envp) { // If the user doesn't want core files, disable them. if (DisableCoreFiles) sys::Process::PreventCoreFiles(); - + // Load the bitcode... SMDiagnostic Err; Module *Mod = ParseIRFile(InputFile, Err, Context); if (!Mod) { - Err.Print(argv[0], errs()); + Err.print(argv[0], errs()); return 1; } @@ -199,6 +200,8 @@ int main(int argc, char **argv, char * const *envp) { builder.setRelocationModel(RelocModel); builder.setCodeModel(CMModel); builder.setErrorStr(&ErrorMsg); + builder.setJITMemoryManager(ForceInterpreter ? 0 : + JITMemoryManager::CreateDefaultMemManager()); builder.setEngineKind(ForceInterpreter ? EngineKind::Interpreter : EngineKind::JIT); @@ -207,9 +210,11 @@ int main(int argc, char **argv, char * const *envp) { if (!TargetTriple.empty()) Mod->setTargetTriple(Triple::normalize(TargetTriple)); - // Enable MCJIT, if desired. - if (UseMCJIT) + // Enable MCJIT if desired. + if (UseMCJIT && !ForceInterpreter) { builder.setUseMCJIT(true); + builder.setJITMemoryManager(JITMemoryManager::CreateDefaultMemManager()); + } CodeGenOpt::Level OLvl = CodeGenOpt::Default; switch (OptLevel) { @@ -233,7 +238,12 @@ int main(int argc, char **argv, char * const *envp) { exit(1); } - EE->RegisterJITEventListener(createOProfileJITEventListener()); + // The following functions have no effect if their respective profiling + // support wasn't enabled in the build configuration. + EE->RegisterJITEventListener( + JITEventListener::createOProfileJITEventListener()); + EE->RegisterJITEventListener( + JITEventListener::createIntelJITEventListener()); EE->DisableLazyCompilation(NoLazyCompilation); @@ -262,15 +272,15 @@ int main(int argc, char **argv, char * const *envp) { return -1; } - // If the program doesn't explicitly call exit, we will need the Exit - // function later on to make an explicit call, so get the function now. + // If the program doesn't explicitly call exit, we will need the Exit + // function later on to make an explicit call, so get the function now. Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context), Type::getInt32Ty(Context), NULL); - + // Reset errno to zero on entry to main. errno = 0; - + // Run static constructors. EE->runStaticConstructorsDestructors(false); @@ -287,8 +297,8 @@ int main(int argc, char **argv, char * const *envp) { // Run static destructors. EE->runStaticConstructorsDestructors(true); - - // If the program didn't call exit explicitly, we should call it now. + + // If the program didn't call exit explicitly, we should call it now. // This ensures that any atexit handlers get called correctly. if (Function *ExitF = dyn_cast<Function>(Exit)) { std::vector<GenericValue> Args; diff --git a/tools/llvm-ar/LLVMBuild.txt b/tools/llvm-ar/LLVMBuild.txt new file mode 100644 index 0000000..1f61a32 --- /dev/null +++ b/tools/llvm-ar/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-ar/LLVMBuild.txt ----------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-ar +parent = Tools +required_libraries = Archive diff --git a/tools/llvm-ar/Makefile b/tools/llvm-ar/Makefile index e4fe4e8..6ee6f34 100644 --- a/tools/llvm-ar/Makefile +++ b/tools/llvm-ar/Makefile @@ -6,20 +6,13 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-ar -LINK_COMPONENTS = archive +LEVEL := ../.. +TOOLNAME := llvm-ar +LINK_COMPONENTS := archive REQUIRES_EH := 1 # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common - -check-local:: - $(Echo) Checking llvm-ar - $(Verb) $(ToolDir)/llvm-ar zRrS nada.a . - $(Verb) $(ToolDir)/llvm-ar tv nada.a | \ - grep Debug/llvm-ar.d >/dev/null 2>&1 - $(Verb) $(RM) -f nada.a diff --git a/tools/llvm-as/LLVMBuild.txt b/tools/llvm-as/LLVMBuild.txt new file mode 100644 index 0000000..542470b --- /dev/null +++ b/tools/llvm-as/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-as/LLVMBuild.txt ----------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-as +parent = Tools +required_libraries = AsmParser BitWriter diff --git a/tools/llvm-as/Makefile b/tools/llvm-as/Makefile index e1e5853..dfd71b2 100644 --- a/tools/llvm-as/Makefile +++ b/tools/llvm-as/Makefile @@ -7,11 +7,11 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-as +LEVEL := ../.. +TOOLNAME := llvm-as LINK_COMPONENTS := asmparser bitwriter # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp index c1661cd..1def9a4 100644 --- a/tools/llvm-as/llvm-as.cpp +++ b/tools/llvm-as/llvm-as.cpp @@ -96,7 +96,7 @@ int main(int argc, char **argv) { SMDiagnostic Err; std::auto_ptr<Module> M(ParseAssemblyFile(InputFilename, Err, Context)); if (M.get() == 0) { - Err.Print(argv[0], errs()); + Err.print(argv[0], errs()); return 1; } diff --git a/tools/llvm-bcanalyzer/LLVMBuild.txt b/tools/llvm-bcanalyzer/LLVMBuild.txt new file mode 100644 index 0000000..ee77a7d --- /dev/null +++ b/tools/llvm-bcanalyzer/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-bcanalyzer/LLVMBuild.txt --------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-bcanalyzer +parent = Tools +required_libraries = BitReader diff --git a/tools/llvm-bcanalyzer/Makefile b/tools/llvm-bcanalyzer/Makefile index 488387d..2fc61db 100644 --- a/tools/llvm-bcanalyzer/Makefile +++ b/tools/llvm-bcanalyzer/Makefile @@ -6,12 +6,12 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-bcanalyzer +LEVEL := ../.. +TOOLNAME := llvm-bcanalyzer LINK_COMPONENTS := bitreader # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 4ada64a..d630087 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -102,14 +102,13 @@ static const char *GetBlockName(unsigned BlockID, default: return 0; case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK"; case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK"; - case bitc::TYPE_BLOCK_ID_OLD: return "TYPE_BLOCK_ID_OLD"; case bitc::TYPE_BLOCK_ID_NEW: return "TYPE_BLOCK_ID"; case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK"; case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK"; - case bitc::TYPE_SYMTAB_BLOCK_ID_OLD: return "TYPE_SYMTAB_OLD"; case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB"; case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK"; case bitc::METADATA_ATTACHMENT_ID: return "METADATA_ATTACHMENT_BLOCK"; + case bitc::USELIST_BLOCK_ID: return "USELIST_BLOCK_ID"; } } @@ -163,7 +162,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, default: return 0; case bitc::PARAMATTR_CODE_ENTRY: return "ENTRY"; } - case bitc::TYPE_BLOCK_ID_OLD: case bitc::TYPE_BLOCK_ID_NEW: switch (CodeID) { default: return 0; @@ -175,8 +173,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::TYPE_CODE_OPAQUE: return "OPAQUE"; case bitc::TYPE_CODE_INTEGER: return "INTEGER"; case bitc::TYPE_CODE_POINTER: return "POINTER"; - case bitc::TYPE_CODE_FUNCTION: return "FUNCTION"; - case bitc::TYPE_CODE_STRUCT_OLD: return "STRUCT_OLD"; case bitc::TYPE_CODE_ARRAY: return "ARRAY"; case bitc::TYPE_CODE_VECTOR: return "VECTOR"; case bitc::TYPE_CODE_X86_FP80: return "X86_FP80"; @@ -186,6 +182,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::TYPE_CODE_STRUCT_ANON: return "STRUCT_ANON"; case bitc::TYPE_CODE_STRUCT_NAME: return "STRUCT_NAME"; case bitc::TYPE_CODE_STRUCT_NAMED: return "STRUCT_NAMED"; + case bitc::TYPE_CODE_FUNCTION: return "FUNCTION"; } case bitc::CONSTANTS_BLOCK_ID: @@ -211,6 +208,8 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::CST_CODE_CE_CMP: return "CE_CMP"; case bitc::CST_CODE_INLINEASM: return "INLINEASM"; case bitc::CST_CODE_CE_SHUFVEC_EX: return "CE_SHUFVEC_EX"; + case bitc::CST_CODE_BLOCKADDRESS: return "CST_CODE_BLOCKADDRESS"; + case bitc::CST_CODE_DATA: return "DATA"; } case bitc::FUNCTION_BLOCK_ID: switch (CodeID) { @@ -231,7 +230,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::FUNC_CODE_INST_BR: return "INST_BR"; case bitc::FUNC_CODE_INST_SWITCH: return "INST_SWITCH"; case bitc::FUNC_CODE_INST_INVOKE: return "INST_INVOKE"; - case bitc::FUNC_CODE_INST_UNWIND: return "INST_UNWIND"; case bitc::FUNC_CODE_INST_UNREACHABLE: return "INST_UNREACHABLE"; case bitc::FUNC_CODE_INST_PHI: return "INST_PHI"; @@ -247,11 +245,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::FUNC_CODE_INST_CALL: return "INST_CALL"; case bitc::FUNC_CODE_DEBUG_LOC: return "DEBUG_LOC"; } - case bitc::TYPE_SYMTAB_BLOCK_ID_OLD: - switch (CodeID) { - default: return 0; - case bitc::TST_CODE_ENTRY: return "ENTRY"; - } case bitc::VALUE_SYMTAB_BLOCK_ID: switch (CodeID) { default: return 0; @@ -273,6 +266,11 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::METADATA_FN_NODE: return "METADATA_FN_NODE"; case bitc::METADATA_NAMED_NODE: return "METADATA_NAMED_NODE"; } + case bitc::USELIST_BLOCK_ID: + switch(CodeID) { + default:return 0; + case bitc::USELIST_CODE_ENTRY: return "USELIST_CODE_ENTRY"; + } } } @@ -333,7 +331,7 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { // BLOCKINFO is a special part of the stream. if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { - if (Dump) errs() << Indent << "<BLOCKINFO_BLOCK/>\n"; + if (Dump) outs() << Indent << "<BLOCKINFO_BLOCK/>\n"; if (Stream.ReadBlockInfoBlock()) return Error("Malformed BlockInfoBlock"); uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); @@ -347,16 +345,16 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { const char *BlockName = 0; if (Dump) { - errs() << Indent << "<"; + outs() << Indent << "<"; if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader()))) - errs() << BlockName; + outs() << BlockName; else - errs() << "UnknownBlock" << BlockID; + outs() << "UnknownBlock" << BlockID; if (NonSymbolic && BlockName) - errs() << " BlockID=" << BlockID; + outs() << " BlockID=" << BlockID; - errs() << " NumWords=" << NumWords + outs() << " NumWords=" << NumWords << " BlockCodeSize=" << Stream.GetAbbrevIDWidth() << ">\n"; } @@ -378,11 +376,11 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); BlockStats.NumBits += BlockBitEnd-BlockBitStart; if (Dump) { - errs() << Indent << "</"; + outs() << Indent << "</"; if (BlockName) - errs() << BlockName << ">\n"; + outs() << BlockName << ">\n"; else - errs() << "UnknownBlock" << BlockID << ">\n"; + outs() << "UnknownBlock" << BlockID << ">\n"; } return false; } @@ -424,25 +422,25 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { BlockStats.CodeFreq[Code].NumAbbrev++; if (Dump) { - errs() << Indent << " <"; + outs() << Indent << " <"; if (const char *CodeName = GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) - errs() << CodeName; + outs() << CodeName; else - errs() << "UnknownCode" << Code; + outs() << "UnknownCode" << Code; if (NonSymbolic && GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) - errs() << " codeid=" << Code; + outs() << " codeid=" << Code; if (AbbrevID != bitc::UNABBREV_RECORD) - errs() << " abbrevid=" << AbbrevID; + outs() << " abbrevid=" << AbbrevID; for (unsigned i = 0, e = Record.size(); i != e; ++i) - errs() << " op" << i << "=" << (int64_t)Record[i]; + outs() << " op" << i << "=" << (int64_t)Record[i]; - errs() << "/>"; + outs() << "/>"; if (BlobStart) { - errs() << " blob data = "; + outs() << " blob data = "; bool BlobIsPrintable = true; for (unsigned i = 0; i != BlobLen; ++i) if (!isprint(BlobStart[i])) { @@ -451,12 +449,12 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { } if (BlobIsPrintable) - errs() << "'" << std::string(BlobStart, BlobStart+BlobLen) <<"'"; + outs() << "'" << std::string(BlobStart, BlobStart+BlobLen) <<"'"; else - errs() << "unprintable, " << BlobLen << " bytes."; + outs() << "unprintable, " << BlobLen << " bytes."; } - errs() << "\n"; + outs() << "\n"; } break; @@ -485,13 +483,13 @@ static int AnalyzeBitcode() { if (MemBuf->getBufferSize() & 3) return Error("Bitcode stream should be a multiple of 4 bytes in length"); - unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart(); - unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize(); + const unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart(); + const unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize(); // If we have a wrapper header, parse it and ignore the non-bc file contents. // The magic number is 0x0B17C0DE stored in little endian. if (isBitcodeWrapper(BufPtr, EndBufPtr)) - if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr)) + if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true)) return Error("Invalid bitcode wrapper header"); BitstreamReader StreamFile(BufPtr, EndBufPtr); @@ -527,59 +525,58 @@ static int AnalyzeBitcode() { ++NumTopBlocks; } - if (Dump) errs() << "\n\n"; + if (Dump) outs() << "\n\n"; uint64_t BufferSizeBits = (EndBufPtr-BufPtr)*CHAR_BIT; // Print a summary of the read file. - errs() << "Summary of " << InputFilename << ":\n"; - errs() << " Total size: "; + outs() << "Summary of " << InputFilename << ":\n"; + outs() << " Total size: "; PrintSize(BufferSizeBits); - errs() << "\n"; - errs() << " Stream type: "; + outs() << "\n"; + outs() << " Stream type: "; switch (CurStreamType) { - default: assert(0 && "Unknown bitstream type"); - case UnknownBitstream: errs() << "unknown\n"; break; - case LLVMIRBitstream: errs() << "LLVM IR\n"; break; + case UnknownBitstream: outs() << "unknown\n"; break; + case LLVMIRBitstream: outs() << "LLVM IR\n"; break; } - errs() << " # Toplevel Blocks: " << NumTopBlocks << "\n"; - errs() << "\n"; + outs() << " # Toplevel Blocks: " << NumTopBlocks << "\n"; + outs() << "\n"; // Emit per-block stats. - errs() << "Per-block Summary:\n"; + outs() << "Per-block Summary:\n"; for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(), E = BlockIDStats.end(); I != E; ++I) { - errs() << " Block ID #" << I->first; + outs() << " Block ID #" << I->first; if (const char *BlockName = GetBlockName(I->first, StreamFile)) - errs() << " (" << BlockName << ")"; - errs() << ":\n"; + outs() << " (" << BlockName << ")"; + outs() << ":\n"; const PerBlockIDStats &Stats = I->second; - errs() << " Num Instances: " << Stats.NumInstances << "\n"; - errs() << " Total Size: "; + outs() << " Num Instances: " << Stats.NumInstances << "\n"; + outs() << " Total Size: "; PrintSize(Stats.NumBits); - errs() << "\n"; + outs() << "\n"; double pct = (Stats.NumBits * 100.0) / BufferSizeBits; errs() << " Percent of file: " << format("%2.4f%%", pct) << "\n"; if (Stats.NumInstances > 1) { - errs() << " Average Size: "; + outs() << " Average Size: "; PrintSize(Stats.NumBits/(double)Stats.NumInstances); - errs() << "\n"; - errs() << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/" + outs() << "\n"; + outs() << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/" << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n"; - errs() << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/" + outs() << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/" << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n"; - errs() << " Tot/Avg Records: " << Stats.NumRecords << "/" + outs() << " Tot/Avg Records: " << Stats.NumRecords << "/" << Stats.NumRecords/(double)Stats.NumInstances << "\n"; } else { - errs() << " Num SubBlocks: " << Stats.NumSubBlocks << "\n"; - errs() << " Num Abbrevs: " << Stats.NumAbbrevs << "\n"; - errs() << " Num Records: " << Stats.NumRecords << "\n"; + outs() << " Num SubBlocks: " << Stats.NumSubBlocks << "\n"; + outs() << " Num Abbrevs: " << Stats.NumAbbrevs << "\n"; + outs() << " Num Records: " << Stats.NumRecords << "\n"; } if (Stats.NumRecords) { double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords; - errs() << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n"; + outs() << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n"; } - errs() << "\n"; + outs() << "\n"; // Print a histogram of the codes we see. if (!NoHistogram && !Stats.CodeFreq.empty()) { @@ -590,7 +587,7 @@ static int AnalyzeBitcode() { std::stable_sort(FreqPairs.begin(), FreqPairs.end()); std::reverse(FreqPairs.begin(), FreqPairs.end()); - errs() << "\tRecord Histogram:\n"; + outs() << "\tRecord Histogram:\n"; fprintf(stderr, "\t\t Count # Bits %% Abv Record Kind\n"); for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) { const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second]; @@ -610,7 +607,7 @@ static int AnalyzeBitcode() { else fprintf(stderr, "UnknownCode%d\n", FreqPairs[i].second); } - errs() << "\n"; + outs() << "\n"; } } diff --git a/tools/llvm-config/BuildVariables.inc.in b/tools/llvm-config/BuildVariables.inc.in new file mode 100644 index 0000000..fe87afb --- /dev/null +++ b/tools/llvm-config/BuildVariables.inc.in @@ -0,0 +1,27 @@ +//===-- BuildVariables.inc.in - llvm-config build variables -*- C++ -*-----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is configured by the build system to define the variables +// llvm-config wants to report to the user, but which can only be determined at +// build time. +// +// The non .in variant of this file has been autogenerated by the LLVM build. Do +// not edit! +// +//===----------------------------------------------------------------------===// + +#define LLVM_SRC_ROOT "@LLVM_SRC_ROOT@" +#define LLVM_OBJ_ROOT "@LLVM_OBJ_ROOT@" +#define LLVM_CPPFLAGS "@LLVM_CPPFLAGS@" +#define LLVM_CFLAGS "@LLVM_CFLAGS@" +#define LLVM_LDFLAGS "@LLVM_LDFLAGS@" +#define LLVM_CXXFLAGS "@LLVM_CXXFLAGS@" +#define LLVM_BUILDMODE "@LLVM_BUILDMODE@" +#define LLVM_TARGETS_BUILT "@LLVM_TARGETS_BUILT@" +#define LLVM_SYSTEM_LIBS "@LLVM_SYSTEM_LIBS@" diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt index 6016862..5ad58bf 100644 --- a/tools/llvm-config/CMakeLists.txt +++ b/tools/llvm-config/CMakeLists.txt @@ -1,140 +1,42 @@ -include(TestBigEndian) +set(LLVM_LINK_COMPONENTS support) -include(FindPerl) -if( NOT PERL_FOUND ) - message(FATAL_ERROR "Perl required but not found!") -endif( NOT PERL_FOUND ) - -set(PERL ${PERL_EXECUTABLE}) -set(VERSION PACKAGE_VERSION) -set(PREFIX ${CMAKE_INSTALL_PREFIX}) -set(abs_top_srcdir ${LLVM_MAIN_SRC_DIR}) -set(abs_top_builddir ${LLVM_BINARY_DIR}) -execute_process(COMMAND date - OUTPUT_VARIABLE LLVM_CONFIGTIME - OUTPUT_STRIP_TRAILING_WHITESPACE) -# LLVM_ON_UNIX and LLVM_ON_WIN32 already set. -# those are set to blank by `autoconf' on MinGW, so it seems they are not required: -#set(LLVMGCCDIR "") -#set(LLVMGCC "") -#set(LLVMGXX "") -test_big_endian(IS_BIG_ENDIAN) -if( IS_BIG_ENDIAN ) - set(ENDIAN "big") -else( IS_BIG_ENDIAN ) - set(ENDIAN "little") -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}") +# We need to generate the BuildVariables.inc file containing values which are +# only defined when under certain build modes. Unfortunately, that precludes +# doing this inside CMake so we have to shell out to sed. For now, that means we +# can't expect to build llvm-config on Window.s +set(BUILDVARIABLES_SRCPATH ${CMAKE_CURRENT_SOURCE_DIR}/BuildVariables.inc.in) +set(BUILDVARIABLES_OBJPATH ${CMAKE_CURRENT_BINARY_DIR}/BuildVariables.inc) +set(SEDSCRIPT_OBJPATH ${CMAKE_CURRENT_BINARY_DIR}/BuildVariables.configure.sed) +# Compute the substitution values for various items. get_system_libs(LLVM_SYSTEM_LIBS_LIST) foreach(l ${LLVM_SYSTEM_LIBS_LIST}) - set(LLVM_SYSTEM_LIBS ${LLVM_SYSTEM_LIBS} "-l${l}") + set(SYSTEM_LIBS ${SYSTEM_LIBS} "-l${l}") endforeach() - -foreach(c ${LLVM_TARGETS_TO_BUILD}) - set(TARGETS_BUILT "${TARGETS_BUILT} ${c}") -endforeach(c) -set(TARGETS_TO_BUILD ${TARGETS_BUILT}) -set(TARGET_HAS_JIT "1") # TODO - -# Avoids replacement at config-time: -set(LLVM_CPPFLAGS "@LLVM_CPPFLAGS@") -set(LLVM_CFLAGS "@LLVM_CFLAGS@") -set(LLVM_CXXFLAGS "@LLVM_CXXFLAGS@") -set(LLVM_LDFLAGS "@LLVM_LDFLAGS@") -set(LIBS "@LIBS@") -set(LLVM_BUILDMODE "@LLVM_BUILDMODE@") - -configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/llvm-config.in.in - ${CMAKE_CURRENT_BINARY_DIR}/llvm-config.in - @ONLY -) - -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) - -if( CMAKE_CROSSCOMPILING ) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) -endif() - -find_program(NM_PATH nm PATH_SUFFIXES /bin) - -if( NOT NM_PATH ) - message(FATAL_ERROR "`nm' not found") -endif() - -get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS) - -add_custom_command(OUTPUT ${LIBDEPS_TMP} - COMMAND ${PERL_EXECUTABLE} ${LLVM_MAIN_SRC_DIR}/utils/GenLibDeps.pl -flat ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} ${NM_PATH} > ${LIBDEPS_TMP} - DEPENDS ${llvm_libs} - COMMENT "Regenerating ${LIBDEPS_TMP}") - -add_custom_command(OUTPUT ${LIBDEPS} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LIBDEPS_TMP} ${LIBDEPS} - DEPENDS ${LIBDEPS_TMP} - COMMENT "Updating ${LIBDEPS} if necessary...") - -# This must stop the build if find-cycles.pl returns error: -add_custom_command(OUTPUT ${FINAL_LIBDEPS} - COMMAND ${CMAKE_COMMAND} -E remove -f ${FINAL_LIBDEPS} ${FINAL_LIBDEPS}.tmp - COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/find-cycles.pl < ${LIBDEPS} > ${FINAL_LIBDEPS}.tmp - COMMAND ${CMAKE_COMMAND} -E copy ${FINAL_LIBDEPS}.tmp ${FINAL_LIBDEPS} - DEPENDS ${LIBDEPS} - COMMENT "Checking for cyclic dependencies between LLVM libraries.") - 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 -macro(remove_option_from_llvm_config option) - llvm_replace_compiler_option(C_FLGS "${option}" "") - llvm_replace_compiler_option(CXX_FLGS "${option}" "") - llvm_replace_compiler_option(CPP_FLGS "${option}" "") -endmacro(remove_option_from_llvm_config) -remove_option_from_llvm_config("-pedantic") -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 +add_custom_command(OUTPUT ${BUILDVARIABLES_OBJPATH} + COMMAND echo s!@LLVM_SRC_ROOT@!${LLVM_MAIN_SRC_DIR}! > ${SEDSCRIPT_OBJPATH} + COMMAND echo s!@LLVM_OBJ_ROOT@!${LLVM_BINARY_DIR}! >> ${SEDSCRIPT_OBJPATH} + COMMAND echo s!@LLVM_CPPFLAGS@!${CPP_FLGS}! >> ${SEDSCRIPT_OBJPATH} + COMMAND echo s!@LLVM_CFLAGS@!${C_FLGS}! >> ${SEDSCRIPT_OBJPATH} + COMMAND echo s!@LLVM_CXXFLAGS@!${CXX_FLGS}! >> ${SEDSCRIPT_OBJPATH} # 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 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} + COMMAND echo s!@LLVM_LDFLAGS@!${CMAKE_SHARED_LINKER_FLAGS}! >> ${SEDSCRIPT_OBJPATH} + COMMAND echo s!@LLVM_BUILDMODE@!${CMAKE_BUILD_TYPE}! >> ${SEDSCRIPT_OBJPATH} + COMMAND echo s!@LLVM_SYSTEM_LIBS@!${SYSTEM_LIBS}! >> ${SEDSCRIPT_OBJPATH} + COMMAND echo s!@LLVM_TARGETS_BUILT@!${LLVM_TARGETS_TO_BUILD}! >> ${SEDSCRIPT_OBJPATH} + COMMAND sed -f ${SEDSCRIPT_OBJPATH} < ${BUILDVARIABLES_SRCPATH} > ${BUILDVARIABLES_OBJPATH} VERBATIM - DEPENDS ${FINAL_LIBDEPS} ${LLVM_CONFIG_IN} - COMMENT "Building llvm-config script." + COMMENT "Building BuildVariables.inc include." ) -add_custom_target(llvm-config.target ALL - DEPENDS ${LLVM_CONFIG}) - -add_dependencies( llvm-config.target ${llvm_libs} ) - -# Make sure that llvm-config builds before the llvm tools, so we have -# LibDeps.txt and can use it for updating the hard-coded library -# dependencies on cmake/modules/LLVMLibDeps.cmake when the tools' -# build fail due to outdated dependencies: -set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} llvm-config.target) +# Add the llvm-config tool. +add_llvm_tool(llvm-config + llvm-config.cpp + ) -install(FILES ${LLVM_CONFIG} - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE - DESTINATION bin) +# Add the dependency on the generation step. +add_file_dependencies(${CMAKE_CURRENT_SOURCE_DIR}/llvm-config.cpp ${BUILDVARIABLES_OBJPATH}) diff --git a/tools/llvm-config/Makefile b/tools/llvm-config/Makefile index c7f7b32..3f11730 100644 --- a/tools/llvm-config/Makefile +++ b/tools/llvm-config/Makefile @@ -1,5 +1,5 @@ -##===- tools/llvm-config/Makefile --------------------------*- Makefile -*-===## -# +##===- tools/llvm-config/Makefile---------------------------*- Makefile -*-===## +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source @@ -7,97 +7,42 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. +LEVEL := ../.. +TOOLNAME := llvm-config +USEDLIBS := LLVMSupport.a -EXTRA_DIST = LibDeps.txt FinalLibDeps.txt llvm-config.in.in find-cycles.pl +# We generate sources in the build directory, make sure it is in the include +# paths. +INCLUDE_BUILD_DIR := 1 -include $(LEVEL)/Makefile.common +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS := 1 -# If we don't have Perl, we can't generate the library dependencies upon which -# llvm-config depends. Therefore, only if we detect perl will we do anything -# useful. -ifeq ($(HAVE_PERL),1) +# Note that we have to use lazy expansion here. +BUILDVARIABLES_SRCPATH = $(PROJ_SRC_ROOT)/tools/$(TOOLNAME)/BuildVariables.inc.in +BUILDVARIABLES_OBJPATH = $(ObjDir)/BuildVariables.inc +BUILT_SOURCES = $(BUILDVARIABLES_OBJPATH) + +include $(LEVEL)/Makefile.common # Combine preprocessor flags (except for -I) and CXX flags. -SUB_CPPFLAGS = ${CPP.BaseFlags} -SUB_CFLAGS = ${CPP.BaseFlags} ${C.Flags} -SUB_CXXFLAGS = ${CPP.BaseFlags} ${CXX.Flags} +SUB_CPPFLAGS := ${CPP.BaseFlags} +SUB_CFLAGS := ${CPP.BaseFlags} ${C.Flags} +SUB_CXXFLAGS := ${CPP.BaseFlags} ${CXX.Flags} # This is blank for now. We need to be careful about adding stuff here: # LDFLAGS tend not to be portable, and we don't currently require the # user to use libtool when linking against LLVM. -SUB_LDFLAGS = - -FinalLibDeps = $(PROJ_OBJ_DIR)/FinalLibDeps.txt -LibDeps = $(PROJ_OBJ_DIR)/LibDeps.txt -LibDepsTemp = $(PROJ_OBJ_DIR)/LibDeps.txt.tmp -GenLibDeps = $(PROJ_SRC_ROOT)/utils/GenLibDeps.pl - -$(LibDepsTemp): $(GenLibDeps) $(LibDir) $(wildcard $(LibDir)/*.a $(LibDir)/*.o) - $(Echo) "Regenerating LibDeps.txt.tmp" - $(Verb) $(PERL) $(GenLibDeps) -flat $(LibDir) "$(NM_PATH)" > $(LibDepsTemp) - -$(LibDeps): $(LibDepsTemp) - $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \ - $(EchoCmd) Updated LibDeps.txt because dependencies changed ) - -# Find all the cyclic dependencies between various LLVM libraries, so we -# don't have to process them at runtime. -$(FinalLibDeps): find-cycles.pl $(LibDeps) - $(Echo) "Checking for cyclic dependencies between LLVM libraries." - $(Verb) $(PERL) $< < $(LibDeps) > $@ || rm -f $@ - -# Rerun our configure substitutions as needed. -ConfigInIn = $(PROJ_SRC_DIR)/llvm-config.in.in -llvm-config.in: $(ConfigInIn) $(ConfigStatusScript) - $(Verb) cd $(PROJ_OBJ_ROOT) ; \ - $(ConfigStatusScript) tools/llvm-config/llvm-config.in - -llvm-config-perobj: llvm-config.in $(GenLibDeps) $(LibDir) $(wildcard $(LibDir)/*.a) - $(Echo) "Generating llvm-config-perobj" - $(Verb) $(PERL) $(GenLibDeps) -perobj -flat $(LibDir) "$(NM_PATH)" >PerobjDeps.txt - $(Echo) "Checking for cyclic dependencies between LLVM objects." - $(Verb) $(PERL) $(PROJ_SRC_DIR)/find-cycles.pl < PerobjDepsIncl.txt > PerobjDepsInclFinal.txt || rm -f $@ - $(Verb) $(ECHO) 's/@LLVM_CPPFLAGS@/$(subst /,\/,$(SUB_CPPFLAGS))/' \ - > temp.sed - $(Verb) $(ECHO) 's/@LLVM_CFLAGS@/$(subst /,\/,$(SUB_CFLAGS))/' \ - >> temp.sed - $(Verb) $(ECHO) 's/@LLVM_CXXFLAGS@/$(subst /,\/,$(SUB_CXXFLAGS))/' \ - >> temp.sed - $(Verb) $(ECHO) 's/@LLVM_LDFLAGS@/$(subst /,\/,$(SUB_LDFLAGS))/' \ - >> temp.sed - $(Verb) $(ECHO) 's/@LLVM_BUILDMODE@/$(subst /,\/,$(BuildMode))/' \ - >> temp.sed - $(Verb) $(SED) -f temp.sed < $< > $@ - $(Verb) $(RM) temp.sed - $(Verb) cat PerobjDepsFinal.txt >> $@ - $(Verb) chmod +x $@ +SUB_LDFLAGS := -llvm-config-perobjincl: llvm-config.in $(GenLibDeps) $(LibDir) $(wildcard $(LibDir)/*.a) - $(Echo) "Generating llvm-config-perobjincl" - $(Verb) $(PERL) $(GenLibDeps) -perobj -perobjincl -flat $(LibDir) "$(NM_PATH)" >PerobjDepsIncl.txt - $(Echo) "Checking for cyclic dependencies between LLVM objects." - $(Verb) $(PERL) $(PROJ_SRC_DIR)/find-cycles.pl < PerobjDepsIncl.txt > PerobjDepsInclFinal.txt - $(Verb) $(ECHO) 's/@LLVM_CPPFLAGS@/$(subst /,\/,$(SUB_CPPFLAGS))/' \ - > temp.sed - $(Verb) $(ECHO) 's/@LLVM_CFLAGS@/$(subst /,\/,$(SUB_CFLAGS))/' \ - >> temp.sed - $(Verb) $(ECHO) 's/@LLVM_CXXFLAGS@/$(subst /,\/,$(SUB_CXXFLAGS))/' \ - >> temp.sed - $(Verb) $(ECHO) 's/@LLVM_LDFLAGS@/$(subst /,\/,$(SUB_LDFLAGS))/' \ - >> temp.sed - $(Verb) $(ECHO) 's/@LLVM_BUILDMODE@/$(subst /,\/,$(BuildMode))/' \ - >> temp.sed - $(Verb) $(SED) -f temp.sed < $< > $@ - $(Verb) $(RM) temp.sed - $(Verb) cat PerobjDepsInclFinal.txt >> $@ - $(Verb) chmod +x $@ - -# Build our final script. -$(ToolDir)/llvm-config: llvm-config.in $(FinalLibDeps) - $(Echo) "Building llvm-config script." - $(Verb) $(ECHO) 's/@LLVM_CPPFLAGS@/$(subst /,\/,$(SUB_CPPFLAGS))/' \ +$(ObjDir)/BuildVariables.inc: $(BUILDVARIABLES_SRCPATH) Makefile $(ObjDir)/.dir + $(Echo) "Building llvm-config BuildVariables.inc file." + $(Verb) $(ECHO) 's/@LLVM_SRC_ROOT@/$(subst /,\/,$(LLVM_SRC_ROOT))/' \ > temp.sed + $(Verb) $(ECHO) 's/@LLVM_OBJ_ROOT@/$(subst /,\/,$(LLVM_OBJ_ROOT))/' \ + >> temp.sed + $(Verb) $(ECHO) 's/@LLVM_CPPFLAGS@/$(subst /,\/,$(SUB_CPPFLAGS))/' \ + >> temp.sed $(Verb) $(ECHO) 's/@LLVM_CFLAGS@/$(subst /,\/,$(SUB_CFLAGS))/' \ >> temp.sed $(Verb) $(ECHO) 's/@LLVM_CXXFLAGS@/$(subst /,\/,$(SUB_CXXFLAGS))/' \ @@ -106,26 +51,9 @@ $(ToolDir)/llvm-config: llvm-config.in $(FinalLibDeps) >> temp.sed $(Verb) $(ECHO) 's/@LLVM_BUILDMODE@/$(subst /,\/,$(BuildMode))/' \ >> temp.sed + $(Verb) $(ECHO) 's/@LLVM_SYSTEM_LIBS@/$(subst /,\/,$(LIBS))/' \ + >> temp.sed + $(Verb) $(ECHO) 's/@LLVM_TARGETS_BUILT@/$(subst /,\/,$(TARGETS_TO_BUILD))/' \ + >> temp.sed $(Verb) $(SED) -f temp.sed < $< > $@ $(Verb) $(RM) temp.sed - $(Verb) cat $(FinalLibDeps) >> $@ - $(Verb) chmod +x $@ - -else -# We don't have perl, just generate a dummy llvm-config -$(ToolDir)/llvm-config: - $(Echo) "Building place holder llvm-config script." - $(Verb) $(ECHO) 'echo llvm-config: Perl not found so llvm-config could not be generated' >> $@ - $(Verb) chmod +x $@ - -endif -# Hook into the standard Makefile rules. -all-local:: $(ToolDir)/llvm-config -clean-local:: - $(Verb) $(RM) -f $(ToolDir)/llvm-config llvm-config.in $(FinalLibDeps) \ - $(LibDeps) GenLibDeps.out -install-local:: all-local - $(Echo) Installing llvm-config - $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_bindir) - $(Verb) $(ScriptInstall) $(ToolDir)/llvm-config $(DESTDIR)$(PROJ_bindir) - diff --git a/tools/llvm-config/find-cycles.pl b/tools/llvm-config/find-cycles.pl deleted file mode 100755 index 5cbf5b4..0000000 --- a/tools/llvm-config/find-cycles.pl +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/perl -# -# Program: find-cycles.pl -# -# Synopsis: Given a list of possibly cyclic dependencies, merge all the -# cycles. This makes it possible to topologically sort the -# dependencies between different parts of LLVM. -# -# Syntax: find-cycles.pl < LibDeps.txt > FinalLibDeps.txt -# -# Input: cycmem1: cycmem2 dep1 dep2 -# cycmem2: cycmem1 dep3 dep4 -# boring: dep4 -# -# Output: cycmem1 cycmem2: dep1 dep2 dep3 dep4 -# boring: dep4 -# -# This file was written by Eric Kidd, and is placed into the public domain. -# - -use 5.006; -use strict; -use warnings; - -my %DEPS; -my @CYCLES; -sub find_all_cycles; - -# Read our dependency information. -while (<>) { - chomp; - my ($module, $dependency_str) = /^\s*([^:]+):\s*(.*)\s*$/; - die "Malformed data: $_" unless defined $dependency_str; - my @dependencies = split(/ /, $dependency_str); - $DEPS{$module} = \@dependencies; -} - -# Partition our raw dependencies into sets of cyclically-connected nodes. -find_all_cycles(); - -# Print out the finished cycles, with their dependencies. -my @output; -my $cycles_found = 0; -foreach my $cycle (@CYCLES) { - my @modules = sort keys %{$cycle}; - - # Merge the dependencies of all modules in this cycle. - my %dependencies; - foreach my $module (@modules) { - @dependencies{@{$DEPS{$module}}} = 1; - } - - # Prune the known cyclic dependencies. - foreach my $module (@modules) { - delete $dependencies{$module}; - } - - # Warn about possible linker problems. - my @archives = grep(/\.a$/, @modules); - if (@archives > 1) { - $cycles_found = $cycles_found + 1; - print STDERR "find-cycles.pl: Circular dependency between *.a files:\n"; - print STDERR "find-cycles.pl: ", join(' ', @archives), "\n"; - push @modules, @archives; # WORKAROUND: Duplicate *.a files. Ick. - } elsif (@modules > 1) { - $cycles_found = $cycles_found + 1; - print STDERR "find-cycles.pl: Circular dependency between *.o files:\n"; - print STDERR "find-cycles.pl: ", join(' ', @modules), "\n"; - push @modules, @modules; # WORKAROUND: Duplicate *.o files. Ick. - } - - # Add to our output. (@modules is already as sorted as we need it to be.) - push @output, (join(' ', @modules) . ': ' . - join(' ', sort keys %dependencies) . "\n"); -} -print sort @output; - -exit $cycles_found; - -#========================================================================== -# Depedency Cycle Support -#========================================================================== -# For now, we have cycles in our dependency graph. Ideally, each cycle -# would be collapsed down to a single *.a file, saving us all this work. -# -# To understand this code, you'll need a working knowledge of Perl 5, -# and possibly some quality time with 'man perlref'. - -my %SEEN; -my %CYCLES; -sub find_cycles ($@); -sub found_cycles ($@); - -sub find_all_cycles { - # Find all multi-item cycles. - my @modules = sort keys %DEPS; - foreach my $module (@modules) { find_cycles($module); } - - # Build fake one-item "cycles" for the remaining modules, so we can - # treat them uniformly. - foreach my $module (@modules) { - unless (defined $CYCLES{$module}) { - my %cycle = ($module, 1); - $CYCLES{$module} = \%cycle; - } - } - - # Find all our unique cycles. We have to do this the hard way because - # we apparently can't store hash references as hash keys without making - # 'strict refs' sad. - my %seen; - foreach my $cycle (values %CYCLES) { - unless ($seen{$cycle}) { - $seen{$cycle} = 1; - push @CYCLES, $cycle; - } - } -} - -# Walk through our graph depth-first (keeping a trail in @path), and report -# any cycles we find. -sub find_cycles ($@) { - my ($module, @path) = @_; - if (str_in_list($module, @path)) { - found_cycle($module, @path); - } else { - return if defined $SEEN{$module}; - $SEEN{$module} = 1; - foreach my $dep (@{$DEPS{$module}}) { - find_cycles($dep, @path, $module); - } - } -} - -# Give a cycle, attempt to merge it with pre-existing cycle data. -sub found_cycle ($@) { - my ($module, @path) = @_; - - # Pop any modules which aren't part of our cycle. - while ($path[0] ne $module) { shift @path; } - #print join("->", @path, $module) . "\n"; - - # Collect the modules in our cycle into a hash. - my %cycle; - foreach my $item (@path) { - $cycle{$item} = 1; - if (defined $CYCLES{$item}) { - # Looks like we intersect with an existing cycle, so merge - # all those in, too. - foreach my $old_item (keys %{$CYCLES{$item}}) { - $cycle{$old_item} = 1; - } - } - } - - # Update our global cycle table. - my $cycle_ref = \%cycle; - foreach my $item (keys %cycle) { - $CYCLES{$item} = $cycle_ref; - } - #print join(":", sort keys %cycle) . "\n"; -} - -sub str_in_list ($@) { - my ($str, @list) = @_; - foreach my $item (@list) { - return 1 if ($item eq $str); - } - return 0; -} diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp new file mode 100644 index 0000000..79fd7f8 --- /dev/null +++ b/tools/llvm-config/llvm-config.cpp @@ -0,0 +1,342 @@ +//===-- llvm-config.cpp - LLVM project configuration utility --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tool encapsulates information about an LLVM project configuration for +// use by other project's build environments (to determine installed path, +// available features, required libraries, etc.). +// +// Note that although this tool *may* be used by some parts of LLVM's build +// itself (i.e., the Makefiles use it to compute required libraries when linking +// tools), this tool is primarily designed to support external projects. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdlib> +#include <set> +#include <vector> + +using namespace llvm; + +// Include the build time variables we can report to the user. This is generated +// at build time from the BuildVariables.inc.in file by the build system. +#include "BuildVariables.inc" + +// Include the component table. This creates an array of struct +// AvailableComponent entries, which record the component name, library name, +// and required components for all of the available libraries. +// +// Not all components define a library, we also use "library groups" as a way to +// create entries for pseudo groups like x86 or all-targets. +#include "LibraryDependencies.inc" + +/// \brief Traverse a single component adding to the topological ordering in +/// \arg RequiredLibs. +/// +/// \param Name - The component to traverse. +/// \param ComponentMap - A prebuilt map of component names to descriptors. +/// \param VisitedComponents [in] [out] - The set of already visited components. +/// \param RequiredLibs [out] - The ordered list of required libraries. +static void VisitComponent(StringRef Name, + const StringMap<AvailableComponent*> &ComponentMap, + std::set<AvailableComponent*> &VisitedComponents, + std::vector<StringRef> &RequiredLibs) { + // Lookup the component. + AvailableComponent *AC = ComponentMap.lookup(Name); + assert(AC && "Invalid component name!"); + + // Add to the visited table. + if (!VisitedComponents.insert(AC).second) { + // We are done if the component has already been visited. + return; + } + + // Otherwise, visit all the dependencies. + for (unsigned i = 0; AC->RequiredLibraries[i]; ++i) { + VisitComponent(AC->RequiredLibraries[i], ComponentMap, VisitedComponents, + RequiredLibs); + } + + // Add to the required library list. + if (AC->Library) + RequiredLibs.push_back(AC->Library); +} + +/// \brief Compute the list of required libraries for a given list of +/// components, in an order suitable for passing to a linker (that is, libraries +/// appear prior to their dependencies). +/// +/// \param Components - The names of the components to find libraries for. +/// \param RequiredLibs [out] - On return, the ordered list of libraries that +/// are required to link the given components. +void ComputeLibsForComponents(const std::vector<StringRef> &Components, + std::vector<StringRef> &RequiredLibs) { + std::set<AvailableComponent*> VisitedComponents; + + // Build a map of component names to information. + StringMap<AvailableComponent*> ComponentMap; + for (unsigned i = 0; i != array_lengthof(AvailableComponents); ++i) { + AvailableComponent *AC = &AvailableComponents[i]; + ComponentMap[AC->Name] = AC; + } + + // Visit the components. + for (unsigned i = 0, e = Components.size(); i != e; ++i) { + // Users are allowed to provide mixed case component names. + std::string ComponentLower = Components[i].lower(); + + // Validate that the user supplied a valid component name. + if (!ComponentMap.count(ComponentLower)) { + llvm::errs() << "llvm-config: unknown component name: " << Components[i] + << "\n"; + exit(1); + } + + VisitComponent(ComponentLower, ComponentMap, VisitedComponents, + RequiredLibs); + } + + // The list is now ordered with leafs first, we want the libraries to printed + // in the reverse order of dependency. + std::reverse(RequiredLibs.begin(), RequiredLibs.end()); +} + +/* *** */ + +void usage() { + errs() << "\ +usage: llvm-config <OPTION>... [<COMPONENT>...]\n\ +\n\ +Get various configuration information needed to compile programs which use\n\ +LLVM. Typically called from 'configure' scripts. Examples:\n\ + llvm-config --cxxflags\n\ + llvm-config --ldflags\n\ + llvm-config --libs engine bcreader scalaropts\n\ +\n\ +Options:\n\ + --version Print LLVM version.\n\ + --prefix Print the installation prefix.\n\ + --src-root Print the source root LLVM was built from.\n\ + --obj-root Print the object root used to build LLVM.\n\ + --bindir Directory containing LLVM executables.\n\ + --includedir Directory containing LLVM headers.\n\ + --libdir Directory containing LLVM libraries.\n\ + --cppflags C preprocessor flags for files that include LLVM headers.\n\ + --cflags C compiler flags for files that include LLVM headers.\n\ + --cxxflags C++ compiler flags for files that include LLVM headers.\n\ + --ldflags Print Linker flags.\n\ + --libs Libraries needed to link against LLVM components.\n\ + --libnames Bare library names for in-tree builds.\n\ + --libfiles Fully qualified library filenames for makefile depends.\n\ + --components List of all possible components.\n\ + --targets-built List of all targets currently built.\n\ + --host-target Target triple used to configure LLVM.\n\ + --build-mode Print build mode of LLVM tree (e.g. Debug or Release).\n\ +Typical components:\n\ + all All LLVM libraries (default).\n\ + engine Either a native JIT or a bitcode interpreter.\n"; + exit(1); +} + +/// \brief Compute the path to the main executable. +llvm::sys::Path GetExecutablePath(const char *Argv0) { + // This just needs to be some symbol in the binary; C++ doesn't + // allow taking the address of ::main however. + void *P = (void*) (intptr_t) GetExecutablePath; + return llvm::sys::Path::GetMainExecutable(Argv0, P); +} + +int main(int argc, char **argv) { + std::vector<StringRef> Components; + bool PrintLibs = false, PrintLibNames = false, PrintLibFiles = false; + bool HasAnyOption = false; + + // llvm-config is designed to support being run both from a development tree + // and from an installed path. We try and auto-detect which case we are in so + // that we can report the correct information when run from a development + // tree. + bool IsInDevelopmentTree; + enum { MakefileStyle, CMakeStyle, CMakeBuildModeStyle } DevelopmentTreeLayout; + llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]).str()); + std::string CurrentExecPrefix; + std::string ActiveObjRoot; + + // Create an absolute path, and pop up one directory (we expect to be inside a + // bin dir). + sys::fs::make_absolute(CurrentPath); + CurrentExecPrefix = sys::path::parent_path( + sys::path::parent_path(CurrentPath)).str(); + + // Check to see if we are inside a development tree by comparing to possible + // locations (prefix style or CMake style). This could be wrong in the face of + // symbolic links, but is good enough. + if (CurrentExecPrefix == std::string(LLVM_OBJ_ROOT) + "/" + LLVM_BUILDMODE) { + IsInDevelopmentTree = true; + DevelopmentTreeLayout = MakefileStyle; + + // If we are in a development tree, then check if we are in a BuildTools + // directory. This indicates we are built for the build triple, but we + // always want to provide information for the host triple. + if (sys::path::filename(LLVM_OBJ_ROOT) == "BuildTools") { + ActiveObjRoot = sys::path::parent_path(LLVM_OBJ_ROOT); + } else { + ActiveObjRoot = LLVM_OBJ_ROOT; + } + } else if (CurrentExecPrefix == std::string(LLVM_OBJ_ROOT)) { + IsInDevelopmentTree = true; + DevelopmentTreeLayout = CMakeStyle; + ActiveObjRoot = LLVM_OBJ_ROOT; + } else if (CurrentExecPrefix == std::string(LLVM_OBJ_ROOT) + "/bin") { + IsInDevelopmentTree = true; + DevelopmentTreeLayout = CMakeBuildModeStyle; + ActiveObjRoot = LLVM_OBJ_ROOT; + } else { + IsInDevelopmentTree = false; + DevelopmentTreeLayout = MakefileStyle; // Initialized to avoid warnings. + } + + // Compute various directory locations based on the derived location + // information. + std::string ActivePrefix, ActiveBinDir, ActiveIncludeDir, ActiveLibDir; + std::string ActiveIncludeOption; + if (IsInDevelopmentTree) { + ActiveIncludeDir = std::string(LLVM_SRC_ROOT) + "/include"; + ActivePrefix = CurrentExecPrefix; + + // CMake organizes the products differently than a normal prefix style + // layout. + switch (DevelopmentTreeLayout) { + case MakefileStyle: + ActiveBinDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/bin"; + ActiveLibDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/lib"; + break; + case CMakeStyle: + ActiveBinDir = ActiveObjRoot + "/bin"; + ActiveLibDir = ActiveObjRoot + "/lib"; + break; + case CMakeBuildModeStyle: + ActiveBinDir = ActiveObjRoot + "/bin/" + LLVM_BUILDMODE; + ActiveLibDir = ActiveObjRoot + "/lib/" + LLVM_BUILDMODE; + break; + } + + // We need to include files from both the source and object trees. + ActiveIncludeOption = ("-I" + ActiveIncludeDir + " " + + "-I" + ActiveObjRoot + "/include"); + } else { + ActivePrefix = CurrentExecPrefix; + ActiveIncludeDir = ActivePrefix + "/include"; + ActiveBinDir = ActivePrefix + "/bin"; + ActiveLibDir = ActivePrefix + "/lib"; + ActiveIncludeOption = "-I" + ActiveIncludeDir; + } + + raw_ostream &OS = outs(); + for (int i = 1; i != argc; ++i) { + StringRef Arg = argv[i]; + + if (Arg.startswith("-")) { + HasAnyOption = true; + if (Arg == "--version") { + OS << PACKAGE_VERSION << '\n'; + } else if (Arg == "--prefix") { + OS << ActivePrefix << '\n'; + } else if (Arg == "--bindir") { + OS << ActiveBinDir << '\n'; + } else if (Arg == "--includedir") { + OS << ActiveIncludeDir << '\n'; + } else if (Arg == "--libdir") { + OS << ActiveLibDir << '\n'; + } else if (Arg == "--cppflags") { + OS << ActiveIncludeOption << ' ' << LLVM_CPPFLAGS << '\n'; + } else if (Arg == "--cflags") { + OS << ActiveIncludeOption << ' ' << LLVM_CFLAGS << '\n'; + } else if (Arg == "--cxxflags") { + OS << ActiveIncludeOption << ' ' << LLVM_CXXFLAGS << '\n'; + } else if (Arg == "--ldflags") { + OS << "-L" << ActiveLibDir << ' ' << LLVM_LDFLAGS + << ' ' << LLVM_SYSTEM_LIBS << '\n'; + } else if (Arg == "--libs") { + PrintLibs = true; + } else if (Arg == "--libnames") { + PrintLibNames = true; + } else if (Arg == "--libfiles") { + PrintLibFiles = true; + } else if (Arg == "--components") { + for (unsigned j = 0; j != array_lengthof(AvailableComponents); ++j) { + OS << ' '; + OS << AvailableComponents[j].Name; + } + OS << '\n'; + } else if (Arg == "--targets-built") { + OS << LLVM_TARGETS_BUILT << '\n'; + } else if (Arg == "--host-target") { + OS << LLVM_DEFAULT_TARGET_TRIPLE << '\n'; + } else if (Arg == "--build-mode") { + OS << LLVM_BUILDMODE << '\n'; + } else if (Arg == "--obj-root") { + OS << LLVM_OBJ_ROOT << '\n'; + } else if (Arg == "--src-root") { + OS << LLVM_SRC_ROOT << '\n'; + } else { + usage(); + } + } else { + Components.push_back(Arg); + } + } + + if (!HasAnyOption) + usage(); + + if (PrintLibs || PrintLibNames || PrintLibFiles) { + // If no components were specified, default to "all". + if (Components.empty()) + Components.push_back("all"); + + // Construct the list of all the required libraries. + std::vector<StringRef> RequiredLibs; + ComputeLibsForComponents(Components, RequiredLibs); + + for (unsigned i = 0, e = RequiredLibs.size(); i != e; ++i) { + StringRef Lib = RequiredLibs[i]; + if (i) + OS << ' '; + + if (PrintLibNames) { + OS << Lib; + } else if (PrintLibFiles) { + OS << ActiveLibDir << '/' << Lib; + } else if (PrintLibs) { + // If this is a typical library name, include it using -l. + if (Lib.startswith("lib") && Lib.endswith(".a")) { + OS << "-l" << Lib.slice(3, Lib.size()-2); + continue; + } + + // Otherwise, print the full path. + OS << ActiveLibDir << '/' << Lib; + } + } + OS << '\n'; + } else if (!Components.empty()) { + errs() << "llvm-config: error: components given, but unused\n\n"; + usage(); + } + + return 0; +} diff --git a/tools/llvm-config/llvm-config.in.in b/tools/llvm-config/llvm-config.in.in deleted file mode 100644 index 840a10e..0000000 --- a/tools/llvm-config/llvm-config.in.in +++ /dev/null @@ -1,463 +0,0 @@ -#!@PERL@ -##===- tools/llvm-config ---------------------------------------*- perl -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# Synopsis: Prints out compiler options needed to build against an installed -# copy of LLVM. -# -# Syntax: llvm-config OPTIONS... [COMPONENTS...] -# -##===----------------------------------------------------------------------===## - -use 5.006; -use strict; -use warnings; -use Cwd 'abs_path'; - -#---- begin autoconf values ---- -my $PACKAGE_NAME = q{@PACKAGE_NAME@}; -my $VERSION = q{@PACKAGE_VERSION@}; -my $PREFIX = q{@LLVM_PREFIX@}; -my $LLVM_CONFIGTIME = q{@LLVM_CONFIGTIME@}; -my $LLVM_SRC_ROOT = q{@abs_top_srcdir@}; -my $LLVM_OBJ_ROOT = q{@abs_top_builddir@}; -my $ARCH = lc(q{@ARCH@}); -my $TARGET_TRIPLE = q{@target@}; -my $TARGETS_TO_BUILD = q{@TARGETS_TO_BUILD@}; -my $TARGET_HAS_JIT = q{@TARGET_HAS_JIT@}; -my @TARGETS_BUILT = map { lc($_) } qw{@TARGETS_TO_BUILD@}; -#---- end autoconf values ---- - -# Must pretend x86_64 architecture is really x86, otherwise the native backend -# won't get linked in. -$ARCH = "x86" if $ARCH eq "x86_64"; - -#---- begin Makefile values ---- -my $CPPFLAGS = q{@LLVM_CPPFLAGS@}; -my $CFLAGS = q{@LLVM_CFLAGS@}; -my $CXXFLAGS = q{@LLVM_CXXFLAGS@}; -my $LDFLAGS = q{@LLVM_LDFLAGS@}; -my $SYSTEM_LIBS = q{@LIBS@}; -my $LLVM_BUILDMODE = q{@LLVM_BUILDMODE@}; -#---- end Makefile values ---- - -# Figure out where llvm-config is being run from. Primarily, we care if it has -# been installed, or is running from the build directory, which changes the -# locations of some files. - -# Convert the current executable name into its directory (e.g. "."). -my ($RUN_DIR) = ($0 =~ /^(.*)\/.*$/); - -# Turn the directory into an absolute directory on the file system, also pop up -# from "bin" into the build or prefix dir. -my $ABS_RUN_DIR = abs_path("$RUN_DIR/.."); -chomp($ABS_RUN_DIR); - -# Compute the absolute object directory build, e.g. "foo/llvm/Debug". -my $ABS_OBJ_ROOT = "$LLVM_OBJ_ROOT/$LLVM_BUILDMODE"; -$ABS_OBJ_ROOT = abs_path("$ABS_OBJ_ROOT") if (-d $ABS_OBJ_ROOT); -chomp($ABS_OBJ_ROOT); - -my $INCLUDEDIR = "$ABS_RUN_DIR/include"; -my $INCLUDEOPTION = "-I$INCLUDEDIR"; -my $LIBDIR = "$ABS_RUN_DIR/lib"; -my $BINDIR = "$ABS_RUN_DIR/bin"; -if ($ABS_RUN_DIR eq $ABS_OBJ_ROOT) { - # If we are running out of the build directory, the include dir is in the - # srcdir. - $INCLUDEDIR = "$LLVM_SRC_ROOT/include"; - # We need include files from both the srcdir and objdir. - $INCLUDEOPTION = "-I$INCLUDEDIR -I$LLVM_OBJ_ROOT/include" -} else { - # If installed, ignore the prefix the tree was configured with, use the - # current prefix. - $PREFIX = $ABS_RUN_DIR; -} - -sub usage; -sub fix_library_names (@); -sub fix_library_files (@); -sub expand_dependencies (@); -sub name_map_entries; - -# Parse our command-line arguments. -usage if @ARGV == 0; -my @components; -my $has_opt = 0; -my $want_libs = 0; -my $want_libnames = 0; -my $want_libfiles = 0; -my $want_components = 0; -foreach my $arg (@ARGV) { - if ($arg =~ /^-/) { - if ($arg eq "--version") { - $has_opt = 1; print "$VERSION\n"; - } elsif ($arg eq "--prefix") { - $has_opt = 1; print "$PREFIX\n"; - } elsif ($arg eq "--bindir") { - $has_opt = 1; print "$BINDIR\n"; - } elsif ($arg eq "--includedir") { - $has_opt = 1; print "$INCLUDEDIR\n"; - } elsif ($arg eq "--libdir") { - $has_opt = 1; print "$LIBDIR\n"; - } elsif ($arg eq "--cppflags") { - $has_opt = 1; print "$INCLUDEOPTION $CPPFLAGS\n"; - } elsif ($arg eq "--cflags") { - $has_opt = 1; print "$INCLUDEOPTION $CFLAGS\n"; - } elsif ($arg eq "--cxxflags") { - $has_opt = 1; print "$INCLUDEOPTION $CXXFLAGS\n"; - } elsif ($arg eq "--ldflags") { - $has_opt = 1; print "-L$LIBDIR $LDFLAGS $SYSTEM_LIBS\n"; - } elsif ($arg eq "--libs") { - $has_opt = 1; $want_libs = 1; - } elsif ($arg eq "--libnames") { - $has_opt = 1; $want_libnames = 1; - } elsif ($arg eq "--libfiles") { - $has_opt = 1; $want_libfiles = 1; - } elsif ($arg eq "--components") { - $has_opt = 1; print join(' ', name_map_entries), "\n"; - } elsif ($arg eq "--targets-built") { - $has_opt = 1; print join(' ', @TARGETS_BUILT), "\n"; - } elsif ($arg eq "--host-target") { - $has_opt = 1; print "$TARGET_TRIPLE\n"; - } elsif ($arg eq "--build-mode") { - $has_opt = 1; print "$LLVM_BUILDMODE\n"; - } elsif ($arg eq "--obj-root") { - $has_opt = 1; print abs_path("$LLVM_OBJ_ROOT/"); - } elsif ($arg eq "--src-root") { - $has_opt = 1; print abs_path("$LLVM_SRC_ROOT/"); - } else { - usage(); - } - } else { - push @components, $arg; - } -} - -# If no options were specified, fail. -usage unless $has_opt; - -# If no components were specified, default to 'all'. -if (@components == 0) { - push @components, 'all'; -} - -# Force component names to lower case. -@components = map lc, @components; - -# Handle any arguments which require building our dependency graph. -if ($want_libs || $want_libnames || $want_libfiles) { - my @libs = expand_dependencies(@components); - print join(' ', fix_library_names(@libs)), "\n" if ($want_libs); - print join(' ', @libs), "\n" if ($want_libnames); - print join(' ', fix_library_files(@libs)), "\n" if ($want_libfiles); -} - -exit 0; - -#========================================================================== -# Support Routines -#========================================================================== - -sub usage { - print STDERR <<__EOD__; -Usage: llvm-config <OPTION>... [<COMPONENT>...] - -Get various configuration information needed to compile programs which use -LLVM. Typically called from 'configure' scripts. Examples: - llvm-config --cxxflags - llvm-config --ldflags - llvm-config --libs engine bcreader scalaropts - -Options: - --version Print LLVM version. - --prefix Print the installation prefix. - --src-root Print the source root LLVM was built from. - --obj-root Print the object root used to build LLVM. - --bindir Directory containing LLVM executables. - --includedir Directory containing LLVM headers. - --libdir Directory containing LLVM libraries. - --cppflags C preprocessor flags for files that include LLVM headers. - --cflags C compiler flags for files that include LLVM headers. - --cxxflags C++ compiler flags for files that include LLVM headers. - --ldflags Print Linker flags. - --libs Libraries needed to link against LLVM components. - --libnames Bare library names for in-tree builds. - --libfiles Fully qualified library filenames for makefile depends. - --components List of all possible components. - --targets-built List of all targets currently built. - --host-target Target triple used to configure LLVM. - --build-mode Print build mode of LLVM tree (e.g. Debug or Release). -Typical components: - all All LLVM libraries (default). - backend Either a native backend or the C backend. - engine Either a native JIT or a bitcode interpreter. -__EOD__ - exit(1); -} - -# Use -lfoo instead of libfoo.a whenever possible, and add directories to -# files which can't be found using -L. -sub fix_library_names (@) { - my @libs = @_; - my @result; - foreach my $lib (@libs) { - # Transform the bare library name appropriately. - my ($basename) = ($lib =~ /^lib([^.]*)\.a/); - if (defined $basename) { - push @result, "-l$basename"; - } else { - push @result, "$LIBDIR/$lib"; - } - } - return @result; -} - -# Turn the list of libraries into a list of files. -sub fix_library_files(@) { - my @libs = @_; - my @result; - foreach my $lib (@libs) { - # Transform the bare library name into a filename. - push @result, "$LIBDIR/$lib"; - } - return @result; -} - -#========================================================================== -# Library Dependency Analysis -#========================================================================== -# Given a few human-readable library names, find all their dependencies -# and sort them into an order which the linker will like. If we packed -# our libraries into fewer archives, we could make the linker do much -# of this work for us. -# -# Libraries have two different types of names in this code: Human-friendly -# "component" names entered on the command-line, and the raw file names -# we use internally (and ultimately pass to the linker). -# -# To understand this code, you'll need a working knowledge of Perl 5, -# and possibly some quality time with 'man perlref'. - -sub load_dependencies; -sub build_name_map; -sub have_native_backend; -sub find_best_engine; -sub expand_names (@); -sub find_all_required_sets (@); -sub find_all_required_sets_helper ($$@); - -# Each "set" contains one or more libraries which must be included as a -# group (due to cyclic dependencies). Sets are represented as a Perl array -# reference pointing to a list of internal library names. -my @SETS; - -# Various mapping tables. -my %LIB_TO_SET_MAP; # Maps internal library names to their sets. -my %SET_DEPS; # Maps sets to a list of libraries they depend on. -my %NAME_MAP; # Maps human-entered names to internal names. - -# Have our dependencies been loaded yet? -my $DEPENDENCIES_LOADED = 0; - -# Given a list of human-friendly component names, translate them into a -# complete set of linker arguments. -sub expand_dependencies (@) { - my @libs = @_; - load_dependencies; - my @required_sets = find_all_required_sets(expand_names(@libs)); - my @sorted_sets = topologically_sort_sets(@required_sets); - - # Expand the library sets into libraries. - my @result; - foreach my $set (@sorted_sets) { push @result, @{$set}; } - return @result; -} - -# Load in the raw dependency data stored at the end of this file. -sub load_dependencies { - return if $DEPENDENCIES_LOADED; - $DEPENDENCIES_LOADED = 1; - while (<DATA>) { - # Parse our line. - my ($libs, $deps) = /^\s*([^:]+):\s*(.*)\s*$/; - die "Malformed dependency data" unless defined $deps; - my @libs = split(' ', $libs); - my @deps = split(' ', $deps); - - # Record our dependency data. - my $set = \@libs; - push @SETS, $set; - foreach my $lib (@libs) { $LIB_TO_SET_MAP{$lib} = $set; } - $SET_DEPS{$set} = \@deps; - } - build_name_map; -} - -# Build a map converting human-friendly component names into internal -# library names. -sub build_name_map { - # Add entries for all the actual libraries. - foreach my $set (@SETS) { - foreach my $lib (sort @$set) { - my $short_name = $lib; - $short_name =~ s/^(lib)?LLVM([^.]*)\..*$/$2/; - $short_name =~ tr/A-Z/a-z/; - $NAME_MAP{$short_name} = [$lib]; - } - } - - # Add target-specific entries - foreach my $target (@TARGETS_BUILT) { - # FIXME: Temporary, until we don't switch all targets - if (defined $NAME_MAP{$target.'asmprinter'}) { - $NAME_MAP{$target} = [$target.'info', - $target.'asmprinter', - $target.'codegen'] - } elsif (defined $NAME_MAP{$target.'codegen'}) { - $NAME_MAP{$target} = [$target.'info', - $target.'codegen'] - } else { - $NAME_MAP{$target} = [$target.'info', - $NAME_MAP{$target}[0]] - } - - if (defined $NAME_MAP{$target.'asmparser'}) { - push @{$NAME_MAP{$target}},$target.'asmparser' - } - - if (defined $NAME_MAP{$target.'disassembler'}) { - push @{$NAME_MAP{$target}},$target.'disassembler' - } - } - - # Add virtual entries. - $NAME_MAP{'native'} = have_native_backend() ? [$ARCH] : []; - $NAME_MAP{'nativecodegen'} = have_native_backend() ? [$ARCH.'codegen'] : []; - $NAME_MAP{'backend'} = have_native_backend() ? ['native'] : ['cbackend']; - $NAME_MAP{'engine'} = find_best_engine; - $NAME_MAP{'all'} = [name_map_entries]; # Must be last. -} - -# Return true if we have a native backend to use. -sub have_native_backend { - my %BUILT; - foreach my $target (@TARGETS_BUILT) { $BUILT{$target} = 1; } - return defined $NAME_MAP{$ARCH} && defined $BUILT{$ARCH}; -} - -# Find a working subclass of ExecutionEngine for this platform. -sub find_best_engine { - if (have_native_backend && $TARGET_HAS_JIT) { - return ['jit', 'native']; - } else { - return ['interpreter']; - } -} - -# Get all the human-friendly component names. -sub name_map_entries { - load_dependencies; - return sort keys %NAME_MAP; -} - -# Map human-readable names to internal library names. -sub expand_names (@) { - my @names = @_; - my @result; - foreach my $name (@names) { - if (defined $LIB_TO_SET_MAP{$name}) { - # We've hit bottom: An actual library name. - push @result, $name; - } elsif (defined $NAME_MAP{$name}) { - # We've found a short name to expand. - push @result, expand_names(@{$NAME_MAP{$name}}); - } else { - print STDERR "llvm-config: unknown component name: $name\n"; - exit(1); - } - } - return @result; -} - -# Given a list of internal library names, return all sets of libraries which -# will need to be included by the linker (in no particular order). -sub find_all_required_sets (@) { - my @libs = @_; - my %sets_added; - my @result; - find_all_required_sets_helper(\%sets_added, \@result, @libs); - return @result; -} - -# Recursive closures are pretty broken in Perl, so we're going to separate -# this function from find_all_required_sets and pass in the state we need -# manually, as references. Yes, this is fairly unpleasant. -sub find_all_required_sets_helper ($$@) { - my ($sets_added, $result, @libs) = @_; - foreach my $lib (@libs) { - my $set = $LIB_TO_SET_MAP{$lib}; - next if defined $$sets_added{$set}; - $$sets_added{$set} = 1; - push @$result, $set; - find_all_required_sets_helper($sets_added, $result, @{$SET_DEPS{$set}}); - } -} - -# Print a list of sets, with a label. Used for debugging. -sub print_sets ($@) { - my ($label, @sets) = @_; - my @output; - foreach my $set (@sets) { push @output, join(',', @$set); } - print "$label: ", join(';', @output), "\n"; -} - -# Returns true if $lib is a key in $added. -sub has_lib_been_added ($$) { - my ($added, $lib) = @_; - return defined $$added{$LIB_TO_SET_MAP{$lib}}; -} - -# Returns true if all the dependencies of $set appear in $added. -sub have_all_deps_been_added ($$) { - my ($added, $set) = @_; - #print_sets(" Checking", $set); - #print_sets(" Wants", $SET_DEPS{$set}); - foreach my $lib (@{$SET_DEPS{$set}}) { - return 0 unless has_lib_been_added($added, $lib); - } - return 1; -} - -# Given a list of sets, topologically sort them using dependencies. -sub topologically_sort_sets (@) { - my @sets = @_; - my %added; - my @result; - SCAN: while (@sets) { # We'll delete items from @sets as we go. - #print_sets("So far", reverse(@result)); - #print_sets("Remaining", @sets); - for (my $i = 0; $i < @sets; ++$i) { - my $set = $sets[$i]; - if (have_all_deps_been_added(\%added, $set)) { - push @result, $set; - $added{$set} = 1; - #print "Removing $i.\n"; - splice(@sets, $i, 1); - next SCAN; # Restart our scan. - } - } - die "Can't find a library with no dependencies"; - } - return reverse(@result); -} - -# Our library dependency data will be added after the '__END__' token, and will -# be read through the magic <DATA> filehandle. -__END__ diff --git a/tools/llvm-cov/LLVMBuild.txt b/tools/llvm-cov/LLVMBuild.txt new file mode 100644 index 0000000..87e00d1 --- /dev/null +++ b/tools/llvm-cov/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-cov/LLVMBuild.txt ---------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-cov +parent = Tools +required_libraries = Instrumentation diff --git a/tools/llvm-cov/Makefile b/tools/llvm-cov/Makefile index bd9fa2a..2d47ce4 100644 --- a/tools/llvm-cov/Makefile +++ b/tools/llvm-cov/Makefile @@ -7,12 +7,11 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. - -TOOLNAME = llvm-cov +LEVEL := ../.. +TOOLNAME := llvm-cov LINK_COMPONENTS := instrumentation # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-diff/DiffConsumer.cpp b/tools/llvm-diff/DiffConsumer.cpp index c23e8fb..0528039 100644 --- a/tools/llvm-diff/DiffConsumer.cpp +++ b/tools/llvm-diff/DiffConsumer.cpp @@ -44,6 +44,8 @@ static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){ } +void Consumer::anchor() { } + void DiffConsumer::printValue(Value *V, bool isL) { if (V->hasName()) { out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName(); @@ -64,6 +66,10 @@ void DiffConsumer::printValue(Value *V, bool isL) { } return; } + if (isa<Constant>(V)) { + out << *V; + return; + } unsigned N = contexts.size(); while (N > 0) { diff --git a/tools/llvm-diff/DiffConsumer.h b/tools/llvm-diff/DiffConsumer.h index b95d427..2060fe1 100644 --- a/tools/llvm-diff/DiffConsumer.h +++ b/tools/llvm-diff/DiffConsumer.h @@ -29,6 +29,7 @@ namespace llvm { /// The interface for consumers of difference data. class Consumer { + virtual void anchor(); public: /// Record that a local context has been entered. Left and /// Right are IR "containers" of some sort which are being diff --git a/tools/llvm-diff/DifferenceEngine.cpp b/tools/llvm-diff/DifferenceEngine.cpp index b240d8c..a5a99f5 100644 --- a/tools/llvm-diff/DifferenceEngine.cpp +++ b/tools/llvm-diff/DifferenceEngine.cpp @@ -319,15 +319,19 @@ class FunctionDifferenceEngine { bool Difference = false; DenseMap<ConstantInt*,BasicBlock*> LCases; - for (unsigned I = 1, E = LI->getNumCases(); I != E; ++I) - LCases[LI->getCaseValue(I)] = LI->getSuccessor(I); - for (unsigned I = 1, E = RI->getNumCases(); I != E; ++I) { - ConstantInt *CaseValue = RI->getCaseValue(I); + + for (SwitchInst::CaseIt I = LI->case_begin(), E = LI->case_end(); + I != E; ++I) + LCases[I.getCaseValue()] = I.getCaseSuccessor(); + + for (SwitchInst::CaseIt I = RI->case_begin(), E = RI->case_end(); + I != E; ++I) { + ConstantInt *CaseValue = I.getCaseValue(); BasicBlock *LCase = LCases[CaseValue]; if (LCase) { - if (TryUnify) tryUnify(LCase, RI->getSuccessor(I)); + if (TryUnify) tryUnify(LCase, I.getCaseSuccessor()); LCases.erase(CaseValue); - } else if (!Difference) { + } else if (Complain || !Difference) { if (Complain) Engine.logf("right switch has extra case %r") << CaseValue; Difference = true; @@ -628,6 +632,8 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart, } +void DifferenceEngine::Oracle::anchor() { } + void DifferenceEngine::diff(Function *L, Function *R) { Context C(*this, L, R); diff --git a/tools/llvm-diff/DifferenceEngine.h b/tools/llvm-diff/DifferenceEngine.h index 5b4f80b..7ea79e4 100644 --- a/tools/llvm-diff/DifferenceEngine.h +++ b/tools/llvm-diff/DifferenceEngine.h @@ -50,7 +50,9 @@ namespace llvm { /// An oracle for answering whether two values are equivalent as /// operands. - struct Oracle { + class Oracle { + virtual void anchor(); + public: virtual bool operator()(Value *L, Value *R) = 0; protected: diff --git a/tools/llvm-diff/LLVMBuild.txt b/tools/llvm-diff/LLVMBuild.txt new file mode 100644 index 0000000..fa06a03 --- /dev/null +++ b/tools/llvm-diff/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-diff/LLVMBuild.txt --------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-diff +parent = Tools +required_libraries = AsmParser BitReader diff --git a/tools/llvm-diff/Makefile b/tools/llvm-diff/Makefile index 58e49fa..f7fa715 100644 --- a/tools/llvm-diff/Makefile +++ b/tools/llvm-diff/Makefile @@ -7,11 +7,11 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-diff +LEVEL := ../.. +TOOLNAME := llvm-diff LINK_COMPONENTS := asmparser bitreader # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-diff/llvm-diff.cpp b/tools/llvm-diff/llvm-diff.cpp index 76853f1..774169b 100644 --- a/tools/llvm-diff/llvm-diff.cpp +++ b/tools/llvm-diff/llvm-diff.cpp @@ -38,7 +38,7 @@ static Module *ReadModule(LLVMContext &Context, StringRef Name) { SMDiagnostic Diag; Module *M = ParseIRFile(Name, Diag, Context); if (!M) - Diag.Print("llvmdiff", errs()); + Diag.print("llvm-diff", errs()); return M; } diff --git a/tools/llvm-dis/LLVMBuild.txt b/tools/llvm-dis/LLVMBuild.txt new file mode 100644 index 0000000..4525010 --- /dev/null +++ b/tools/llvm-dis/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-dis/LLVMBuild.txt ---------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-dis +parent = Tools +required_libraries = Analysis BitReader diff --git a/tools/llvm-dis/Makefile b/tools/llvm-dis/Makefile index be71100..aeeeed0 100644 --- a/tools/llvm-dis/Makefile +++ b/tools/llvm-dis/Makefile @@ -6,12 +6,12 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-dis +LEVEL := ../.. +TOOLNAME := llvm-dis LINK_COMPONENTS := bitreader analysis # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index 9020a52..6450ea6 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -24,6 +24,7 @@ #include "llvm/Analysis/DebugInfo.h" #include "llvm/Assembly/AssemblyAnnotationWriter.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/DataStream.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" @@ -126,12 +127,19 @@ int main(int argc, char **argv) { std::string ErrorMessage; std::auto_ptr<Module> M; - { - OwningPtr<MemoryBuffer> BufferPtr; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) - ErrorMessage = ec.message(); + // Use the bitcode streaming interface + DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage); + if (streamer) { + std::string DisplayFilename; + if (InputFilename == "-") + DisplayFilename = "<stdin>"; else - M.reset(ParseBitcodeFile(BufferPtr.get(), Context, &ErrorMessage)); + DisplayFilename = InputFilename; + M.reset(getStreamedBitcodeModule(DisplayFilename, streamer, Context, + &ErrorMessage)); + if(M.get() != 0 && M->MaterializeAllPermanently(&ErrorMessage)) { + M.reset(); + } } if (M.get() == 0) { @@ -183,4 +191,3 @@ int main(int argc, char **argv) { return 0; } - diff --git a/tools/llvm-dwarfdump/LLVMBuild.txt b/tools/llvm-dwarfdump/LLVMBuild.txt new file mode 100644 index 0000000..28b7c4c --- /dev/null +++ b/tools/llvm-dwarfdump/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-dwarfdump/LLVMBuild.txt ---------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-dwarfdump +parent = Tools +required_libraries = DebugInfo Object diff --git a/tools/llvm-dwarfdump/Makefile b/tools/llvm-dwarfdump/Makefile index e61f27d..7ca1a8d 100644 --- a/tools/llvm-dwarfdump/Makefile +++ b/tools/llvm-dwarfdump/Makefile @@ -6,12 +6,12 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-dwarfdump -LINK_COMPONENTS = DebugInfo Object +LEVEL := ../.. +TOOLNAME := llvm-dwarfdump +LINK_COMPONENTS := DebugInfo Object # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-extract/LLVMBuild.txt b/tools/llvm-extract/LLVMBuild.txt new file mode 100644 index 0000000..1b1a4c3 --- /dev/null +++ b/tools/llvm-extract/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-extract/LLVMBuild.txt -----------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-extract +parent = Tools +required_libraries = AsmParser BitReader BitWriter IPO diff --git a/tools/llvm-extract/Makefile b/tools/llvm-extract/Makefile index 5672aa3..a1e93f5 100644 --- a/tools/llvm-extract/Makefile +++ b/tools/llvm-extract/Makefile @@ -7,12 +7,11 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. - -TOOLNAME = llvm-extract +LEVEL := ../.. +TOOLNAME := llvm-extract LINK_COMPONENTS := ipo bitreader bitwriter asmparser # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index f6227ee..2ed11c5 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -90,7 +90,7 @@ int main(int argc, char **argv) { M.reset(getLazyIRFileModule(InputFilename, Err, Context)); if (M.get() == 0) { - Err.Print(argv[0], errs()); + Err.print(argv[0], errs()); return 1; } @@ -99,7 +99,7 @@ int main(int argc, char **argv) { // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { - GlobalValue *GV = M.get()->getNamedGlobal(ExtractGlobals[i]); + GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; @@ -117,8 +117,8 @@ int main(int argc, char **argv) { "invalid regex: " << Error; } bool match = false; - for (Module::global_iterator GV = M.get()->global_begin(), - E = M.get()->global_end(); GV != E; GV++) { + for (Module::global_iterator GV = M->global_begin(), + E = M->global_end(); GV != E; GV++) { if (RegEx.match(GV->getName())) { GVs.insert(&*GV); match = true; @@ -133,7 +133,7 @@ int main(int argc, char **argv) { // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { - GlobalValue *GV = M.get()->getFunction(ExtractFuncs[i]); + GlobalValue *GV = M->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; @@ -151,7 +151,7 @@ int main(int argc, char **argv) { "invalid regex: " << Error; } bool match = false; - for (Module::iterator F = M.get()->begin(), E = M.get()->end(); F != E; + for (Module::iterator F = M->begin(), E = M->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); diff --git a/tools/llvm-ld/CMakeLists.txt b/tools/llvm-ld/CMakeLists.txt index 370bcb4..d328a04 100644 --- a/tools/llvm-ld/CMakeLists.txt +++ b/tools/llvm-ld/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LLVM_LINK_COMPONENTS ipo scalaropts linker archive bitwriter) +set(LLVM_LINK_COMPONENTS ipo scalaropts linker archive bitwriter vectorize) add_llvm_tool(llvm-ld Optimize.cpp diff --git a/tools/llvm-ld/LLVMBuild.txt b/tools/llvm-ld/LLVMBuild.txt new file mode 100644 index 0000000..eed0452 --- /dev/null +++ b/tools/llvm-ld/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-ld/LLVMBuild.txt ----------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-ld +parent = Tools +required_libraries = Archive BitWriter IPO Linker Scalar diff --git a/tools/llvm-ld/Makefile b/tools/llvm-ld/Makefile index 1ef9bf1..8793ca9 100644 --- a/tools/llvm-ld/Makefile +++ b/tools/llvm-ld/Makefile @@ -7,9 +7,8 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. - -TOOLNAME = llvm-ld -LINK_COMPONENTS = ipo scalaropts linker archive bitwriter +LEVEL := ../.. +TOOLNAME := llvm-ld +LINK_COMPONENTS := ipo scalaropts linker archive bitwriter vectorize include $(LEVEL)/Makefile.common diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp index 6b4c3c7..ecf0476 100644 --- a/tools/llvm-ld/llvm-ld.cpp +++ b/tools/llvm-ld/llvm-ld.cpp @@ -37,7 +37,6 @@ #include "llvm/Support/SystemUtils.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Signals.h" -#include "llvm/Config/config.h" #include <memory> #include <cstring> using namespace llvm; @@ -424,7 +423,7 @@ static void EmitShellScript(char **argv, Module *M) { PrintAndExit(ErrMsg, M); return; -#endif +#else // Output the script to start the program... std::string ErrorInfo; @@ -470,6 +469,7 @@ static void EmitShellScript(char **argv, Module *M) { } Out2.os() << " " << BitcodeOutputFilename << " ${1+\"$@\"}\n"; Out2.keep(); +#endif } // BuildLinkItems -- This function generates a LinkItemList for the LinkItems diff --git a/tools/llvm-link/LLVMBuild.txt b/tools/llvm-link/LLVMBuild.txt new file mode 100644 index 0000000..6399ded --- /dev/null +++ b/tools/llvm-link/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-link/LLVMBuild.txt --------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-link +parent = Tools +required_libraries = AsmParser BitReader BitWriter Linker diff --git a/tools/llvm-link/Makefile b/tools/llvm-link/Makefile index 2637018..2553db0 100644 --- a/tools/llvm-link/Makefile +++ b/tools/llvm-link/Makefile @@ -6,12 +6,12 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-link -LINK_COMPONENTS = linker bitreader bitwriter asmparser +LEVEL := ../.. +TOOLNAME := llvm-link +LINK_COMPONENTS := linker bitreader bitwriter asmparser # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 95ad1ca..378a833 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -69,7 +69,7 @@ static inline std::auto_ptr<Module> LoadFile(const char *argv0, Result = ParseIRFile(FNStr, Err, Context); if (Result) return std::auto_ptr<Module>(Result); // Load successful! - Err.Print(argv0, errs()); + Err.print(argv0, errs()); return std::auto_ptr<Module>(); } diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index a9381b5..a8cd7c1 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -21,6 +21,8 @@ #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Triple.h" @@ -72,14 +74,16 @@ static bool PrintInsts(const MCDisassembler &DisAsm, switch (S) { case MCDisassembler::Fail: SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), - "invalid instruction encoding", "warning"); + SourceMgr::DK_Warning, + "invalid instruction encoding"); if (Size == 0) Size = 1; // skip illegible bytes break; case MCDisassembler::SoftFail: SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), - "potentially undefined instruction encoding", "warning"); + SourceMgr::DK_Warning, + "potentially undefined instruction encoding"); // Fall through case MCDisassembler::Success: @@ -125,8 +129,8 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray, unsigned ByteVal; 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"); + SM.PrintMessage(SMLoc::getFromPointer(Value.data()), SourceMgr::DK_Error, + "invalid input token"); Str = Str.substr(Str.find('\n')); ByteArray.clear(); continue; @@ -153,21 +157,34 @@ int Disassembler::disassemble(const Target &T, return -1; } - OwningPtr<const MCSubtargetInfo> STI(T.createMCSubtargetInfo(Triple, Cpu, FeaturesStr)); + OwningPtr<const MCSubtargetInfo> STI(T.createMCSubtargetInfo(Triple, Cpu, + FeaturesStr)); if (!STI) { errs() << "error: no subtarget info for target " << Triple << "\n"; return -1; } - + OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(*STI)); if (!DisAsm) { errs() << "error: no disassembler for target " << Triple << "\n"; return -1; } + OwningPtr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple)); + if (!MRI) { + errs() << "error: no register info for target " << Triple << "\n"; + return -1; + } + + OwningPtr<const MCInstrInfo> MII(T.createMCInstrInfo()); + if (!MII) { + errs() << "error: no instruction info for target " << Triple << "\n"; + return -1; + } + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); - OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, - *AsmInfo, *STI)); + OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, *AsmInfo, + *MII, *MRI, *STI)); if (!IP) { errs() << "error: no instruction printer for target " << Triple << '\n'; return -1; @@ -247,7 +264,6 @@ int Disassembler::disassembleEnhanced(const std::string &TS, break; } - EDDisassembler::initialize(); OwningPtr<EDDisassembler> disassembler(EDDisassembler::getDisassembler(TS.c_str(), AS)); @@ -294,7 +310,6 @@ int Disassembler::disassembleEnhanced(const std::string &TS, Out << operandIndex << "-"; switch (token->type()) { - default: Out << "?"; break; case EDToken::kTokenWhitespace: Out << "w"; break; case EDToken::kTokenPunctuation: Out << "p"; break; case EDToken::kTokenOpcode: Out << "o"; break; @@ -365,4 +380,3 @@ int Disassembler::disassembleEnhanced(const std::string &TS, return 0; } - diff --git a/tools/llvm-mc/LLVMBuild.txt b/tools/llvm-mc/LLVMBuild.txt new file mode 100644 index 0000000..dff5358 --- /dev/null +++ b/tools/llvm-mc/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-mc/LLVMBuild.txt ----------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-mc +parent = Tools +required_libraries = MC MCDisassembler MCParser Support all-targets diff --git a/tools/llvm-mc/Makefile b/tools/llvm-mc/Makefile index 934a6e4..b147fad 100644 --- a/tools/llvm-mc/Makefile +++ b/tools/llvm-mc/Makefile @@ -7,18 +7,11 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-mc +LEVEL := ../.. +TOOLNAME := llvm-mc +LINK_COMPONENTS := all-targets MCDisassembler MCParser MC support # 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) MCDisassembler MCParser MC support - -include $(LLVM_SRC_ROOT)/Makefile.rules +TOOL_NO_EXPORTS := 1 +include $(LEVEL)/Makefile.common diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 5fb3fdf..d882e01 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -70,9 +70,6 @@ RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); static cl::opt<bool> NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack")); -static cl::opt<bool> -EnableLogging("enable-api-logging", cl::desc("Enable MC API logging")); - enum OutputFileType { OFT_Null, OFT_AssemblyFile, @@ -152,6 +149,10 @@ NoInitialTextSection("n", cl::desc("Don't assume assembly file starts " static cl::opt<bool> SaveTempLabels("L", cl::desc("Don't discard temporary labels")); +static cl::opt<bool> +GenDwarfForAssembly("g", cl::desc("Generate dwarf debugging info for assembly " + "source files")); + enum ActionType { AC_AsLex, AC_Assemble, @@ -175,7 +176,7 @@ Action(cl::desc("Action to perform:"), static const Target *GetTarget(const char *ProgName) { // Figure out the target triple. if (TripleName.empty()) - TripleName = sys::getHostTriple(); + TripleName = sys::getDefaultTargetTriple(); Triple TheTriple(Triple::normalize(TripleName)); const Target *TheTarget = 0; @@ -230,6 +231,17 @@ static tool_output_file *GetOutputStream() { return Out; } +static std::string DwarfDebugFlags; +static void setDwarfDebugFlags(int argc, char **argv) { + if (!getenv("RC_DEBUG_OPTIONS")) + return; + for (int i = 0; i < argc; i++) { + DwarfDebugFlags += argv[i]; + if (i + 1 < argc) + DwarfDebugFlags += " "; + } +} + static int AsLexInput(const char *ProgName) { OwningPtr<MemoryBuffer> BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { @@ -267,7 +279,8 @@ static int AsLexInput(const char *ProgName) { switch (Tok.getKind()) { default: - SrcMgr.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); + SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning, + "unknown token"); Error = true; break; case AsmToken::Error: @@ -370,12 +383,16 @@ static int AssembleInput(const char *ProgName) { // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); - MCContext Ctx(*MAI, *MRI, MOFI.get()); + MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx); if (SaveTempLabels) Ctx.setAllowTemporaryLabels(false); + Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); + if (!DwarfDebugFlags.empty()) + Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); + // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { @@ -399,7 +416,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, *STI); + TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { @@ -408,8 +425,10 @@ static int AssembleInput(const char *ProgName) { } Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true, /*useLoc*/ true, - /*useCFI*/ true, IP, CE, MAB, - ShowInst)); + /*useCFI*/ true, + /*useDwarfDirectory*/ true, + IP, CE, MAB, ShowInst)); + } else if (FileType == OFT_Null) { Str.reset(createNullStreamer(Ctx)); } else { @@ -421,10 +440,6 @@ static int AssembleInput(const char *ProgName) { NoExecStack)); } - if (EnableLogging) { - Str.reset(createLoggingStreamer(Str.take(), errs())); - } - OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser)); @@ -497,11 +512,14 @@ int main(int argc, char **argv) { llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); + // Register the target printer for --version. + cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); + cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); TripleName = Triple::normalize(TripleName); + setDwarfDebugFlags(argc, argv); switch (Action) { - default: case AC_AsLex: return AsLexInput(argv[0]); case AC_Assemble: @@ -511,7 +529,4 @@ int main(int argc, char **argv) { case AC_EDisassemble: return DisassembleInput(argv[0], true); } - - return 0; } - diff --git a/tools/llvm-nm/LLVMBuild.txt b/tools/llvm-nm/LLVMBuild.txt new file mode 100644 index 0000000..38ecbfd --- /dev/null +++ b/tools/llvm-nm/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-nm/LLVMBuild.txt ----------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-nm +parent = Tools +required_libraries = Archive BitReader Object diff --git a/tools/llvm-nm/Makefile b/tools/llvm-nm/Makefile index 6bb4cd4..d9cee98 100644 --- a/tools/llvm-nm/Makefile +++ b/tools/llvm-nm/Makefile @@ -6,12 +6,12 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-nm -LINK_COMPONENTS = archive bitreader object +LEVEL := ../.. +TOOLNAME := llvm-nm +LINK_COMPONENTS := archive bitreader object # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index e79d72d..8d9e51e 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" #include "llvm/Support/Format.h" @@ -60,6 +61,12 @@ namespace { cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), cl::aliasopt(UndefinedOnly)); + cl::opt<bool> DynamicSyms("dynamic", + cl::desc("Display the dynamic symbols instead " + "of normal symbols.")); + cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"), + cl::aliasopt(DynamicSyms)); + cl::opt<bool> DefinedOnly("defined-only", cl::desc("Show only defined symbols")); @@ -110,6 +117,19 @@ namespace { std::string ToolName; } + +static void error(Twine message, Twine path = Twine()) { + errs() << ToolName << ": " << path << ": " << message << ".\n"; +} + +static bool error(error_code ec, Twine path = Twine()) { + if (ec) { + error(ec.message(), path); + return true; + } + return false; +} + namespace { struct NMSymbol { uint64_t Address; @@ -144,14 +164,6 @@ namespace { StringRef CurrentFilename; typedef std::vector<NMSymbol> SymbolListT; SymbolListT SymbolList; - - bool error(error_code ec) { - if (!ec) return false; - - outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; - outs().flush(); - return true; - } } static void SortAndPrintSymbolList() { @@ -192,9 +204,10 @@ static void SortAndPrintSymbolList() { strcpy(SymbolSizeStr, " "); if (i->Address != object::UnknownAddressOrSize) - format("%08"PRIx64, i->Address).print(SymbolAddrStr, sizeof(SymbolAddrStr)); + format("%08" PRIx64, i->Address).print(SymbolAddrStr, + sizeof(SymbolAddrStr)); if (i->Size != object::UnknownAddressOrSize) - format("%08"PRIx64, i->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); + format("%08" PRIx64, i->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); if (OutputFormat == posix) { outs() << i->Name << " " << i->TypeChar << " " @@ -271,13 +284,17 @@ static void DumpSymbolNamesFromModule(Module *M) { static void DumpSymbolNamesFromObject(ObjectFile *obj) { error_code ec; - for (symbol_iterator i = obj->begin_symbols(), - e = obj->end_symbols(); - i != e; i.increment(ec)) { + symbol_iterator ibegin = obj->begin_symbols(); + symbol_iterator iend = obj->end_symbols(); + if (DynamicSyms) { + ibegin = obj->begin_dynamic_symbols(); + iend = obj->end_dynamic_symbols(); + } + for (symbol_iterator i = ibegin; i != iend; i.increment(ec)) { if (error(ec)) break; - bool internal; - if (error(i->isInternal(internal))) break; - if (!DebugSyms && internal) + uint32_t symflags; + if (error(i->getFlags(symflags))) break; + if (!DebugSyms && (symflags & SymbolRef::SF_FormatSpecific)) continue; NMSymbol s; s.Size = object::UnknownAddressOrSize; @@ -286,7 +303,7 @@ static void DumpSymbolNamesFromObject(ObjectFile *obj) { if (error(i->getSize(s.Size))) break; } if (PrintAddress) - if (error(i->getOffset(s.Address))) break; + if (error(i->getAddress(s.Address))) break; if (error(i->getNMTypeChar(s.TypeChar))) break; if (error(i->getName(s.Name))) break; SymbolList.push_back(s); @@ -297,38 +314,39 @@ static void DumpSymbolNamesFromObject(ObjectFile *obj) { } static void DumpSymbolNamesFromFile(std::string &Filename) { + if (Filename != "-" && !sys::fs::exists(Filename)) { + errs() << ToolName << ": '" << Filename << "': " << "No such file\n"; + return; + } + + OwningPtr<MemoryBuffer> Buffer; + if (error(MemoryBuffer::getFileOrSTDIN(Filename, Buffer), Filename)) + return; + + sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer()); + LLVMContext &Context = getGlobalContext(); std::string ErrorMessage; - sys::Path aPath(Filename); - bool exists; - if (sys::fs::exists(aPath.str(), exists) || !exists) - errs() << ToolName << ": '" << Filename << "': " << "No such file\n"; - // Note: Currently we do not support reading an archive from stdin. - if (Filename == "-" || aPath.isBitcodeFile()) { - OwningPtr<MemoryBuffer> Buffer; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buffer)) - ErrorMessage = ec.message(); + if (magic == sys::fs::file_magic::bitcode) { Module *Result = 0; - if (Buffer.get()) - Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); - + Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); if (Result) { DumpSymbolNamesFromModule(Result); delete Result; - } else - errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; - - } else if (aPath.isArchive()) { - OwningPtr<Binary> arch; - if (error_code ec = object::createBinary(aPath.str(), arch)) { - errs() << ToolName << ": " << Filename << ": " << ec.message() << ".\n"; + } else { + error(ErrorMessage, Filename); return; } + } else if (magic == sys::fs::file_magic::archive) { + OwningPtr<Binary> arch; + if (error(object::createBinary(Buffer.take(), arch), Filename)) + return; + if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) { for (object::Archive::child_iterator i = a->begin_children(), e = a->end_children(); i != e; ++i) { OwningPtr<Binary> child; - if (error_code ec = i->getAsBinary(child)) { + if (i->getAsBinary(child)) { // Try opening it as a bitcode file. OwningPtr<MemoryBuffer> buff(i->getBuffer()); Module *Result = 0; @@ -347,12 +365,10 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { } } } - } else if (aPath.isObjectFile()) { + } else if (magic.is_object()) { OwningPtr<Binary> obj; - if (error_code ec = object::createBinary(aPath.str(), obj)) { - errs() << ToolName << ": " << Filename << ": " << ec.message() << ".\n"; + if (error(object::createBinary(Buffer.take(), obj), Filename)) return; - } if (object::ObjectFile *o = dyn_cast<ObjectFile>(obj.get())) DumpSymbolNamesFromObject(o); } else { @@ -370,6 +386,10 @@ int main(int argc, char **argv) { llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n"); + // llvm-nm only reads binary files. + if (error(sys::Program::ChangeStdinToBinary())) + return 1; + ToolName = argv[0]; if (BSDFormat) OutputFormat = bsd; if (POSIXFormat) OutputFormat = posix; diff --git a/tools/llvm-objdump/LLVMBuild.txt b/tools/llvm-objdump/LLVMBuild.txt new file mode 100644 index 0000000..d16c501 --- /dev/null +++ b/tools/llvm-objdump/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-objdump/LLVMBuild.txt -----------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-objdump +parent = Tools +required_libraries = DebugInfo MC MCDisassembler MCParser Object all-targets diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 3f44b29..0e7f3fd 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -14,7 +14,7 @@ #include "llvm-objdump.h" #include "MCFunction.h" #include "llvm/Support/MachO.h" -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachO.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/STLExtras.h" @@ -26,6 +26,7 @@ #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -53,27 +54,28 @@ static cl::opt<std::string> static const Target *GetTarget(const MachOObject *MachOObj) { // Figure out the target triple. - llvm::Triple TT("unknown-unknown-unknown"); - switch (MachOObj->getHeader().CPUType) { - case llvm::MachO::CPUTypeI386: - TT.setArch(Triple::ArchType(Triple::x86)); - break; - case llvm::MachO::CPUTypeX86_64: - TT.setArch(Triple::ArchType(Triple::x86_64)); - break; - case llvm::MachO::CPUTypeARM: - TT.setArch(Triple::ArchType(Triple::arm)); - break; - case llvm::MachO::CPUTypePowerPC: - TT.setArch(Triple::ArchType(Triple::ppc)); - break; - case llvm::MachO::CPUTypePowerPC64: - TT.setArch(Triple::ArchType(Triple::ppc64)); - break; + if (TripleName.empty()) { + llvm::Triple TT("unknown-unknown-unknown"); + switch (MachOObj->getHeader().CPUType) { + case llvm::MachO::CPUTypeI386: + TT.setArch(Triple::ArchType(Triple::x86)); + break; + case llvm::MachO::CPUTypeX86_64: + TT.setArch(Triple::ArchType(Triple::x86_64)); + break; + case llvm::MachO::CPUTypeARM: + TT.setArch(Triple::ArchType(Triple::arm)); + break; + case llvm::MachO::CPUTypePowerPC: + TT.setArch(Triple::ArchType(Triple::ppc)); + break; + case llvm::MachO::CPUTypePowerPC64: + TT.setArch(Triple::ArchType(Triple::ppc64)); + break; + } + TripleName = TT.str(); } - TripleName = TT.str(); - // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); @@ -85,57 +87,43 @@ static const Target *GetTarget(const MachOObject *MachOObj) { return 0; } -struct Section { - char Name[16]; - uint64_t Address; - uint64_t Size; - uint32_t Offset; - uint32_t NumRelocs; - uint64_t RelocTableOffset; -}; - -struct Symbol { - uint64_t Value; - uint32_t StringIndex; - uint8_t SectionIndex; - bool operator<(const Symbol &RHS) const { return Value < RHS.Value; } +struct SymbolSorter { + bool operator()(const SymbolRef &A, const SymbolRef &B) { + SymbolRef::Type AType, BType; + A.getType(AType); + B.getType(BType); + + uint64_t AAddr, BAddr; + if (AType != SymbolRef::ST_Function) + AAddr = 0; + else + A.getAddress(AAddr); + if (BType != SymbolRef::ST_Function) + BAddr = 0; + else + B.getAddress(BAddr); + return AAddr < BAddr; + } }; -template <typename T> -static Section copySection(const T &Sect) { - Section S; - memcpy(S.Name, Sect->Name, 16); - S.Address = Sect->Address; - S.Size = Sect->Size; - S.Offset = Sect->Offset; - S.NumRelocs = Sect->NumRelocationTableEntries; - S.RelocTableOffset = Sect->RelocationTableOffset; - return S; -} - -template <typename T> -static Symbol copySymbol(const T &STE) { - Symbol S; - S.StringIndex = STE->StringIndex; - S.SectionIndex = STE->SectionIndex; - S.Value = STE->Value; - return S; -} - // Print additional information about an address, if available. -static void DumpAddress(uint64_t Address, ArrayRef<Section> Sections, +static void DumpAddress(uint64_t Address, ArrayRef<SectionRef> Sections, MachOObject *MachOObj, raw_ostream &OS) { for (unsigned i = 0; i != Sections.size(); ++i) { - uint64_t addr = Address-Sections[i].Address; - if (Sections[i].Address <= Address && - Sections[i].Address + Sections[i].Size > Address) { - StringRef bytes = MachOObj->getData(Sections[i].Offset, - Sections[i].Size); + uint64_t SectAddr = 0, SectSize = 0; + Sections[i].getAddress(SectAddr); + Sections[i].getSize(SectSize); + uint64_t addr = SectAddr; + if (SectAddr <= Address && + SectAddr + SectSize > Address) { + StringRef bytes, name; + Sections[i].getContents(bytes); + Sections[i].getName(name); // Print constant strings. - if (!strcmp(Sections[i].Name, "__cstring")) + if (!name.compare("__cstring")) OS << '"' << bytes.substr(addr, bytes.find('\0', addr)) << '"'; // Print constant CFStrings. - if (!strcmp(Sections[i].Name, "__cfstring")) + if (!name.compare("__cfstring")) OS << "@\"" << bytes.substr(addr, bytes.find('\0', addr)) << '"'; } } @@ -212,59 +200,34 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, } static void getSectionsAndSymbols(const macho::Header &Header, - MachOObject *MachOObj, + MachOObjectFile *MachOObj, InMemoryStruct<macho::SymtabLoadCommand> *SymtabLC, - std::vector<Section> &Sections, - std::vector<Symbol> &Symbols, + std::vector<SectionRef> &Sections, + std::vector<SymbolRef> &Symbols, SmallVectorImpl<uint64_t> &FoundFns) { - // Make a list of all symbols in the object file. - for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { - const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); - if (LCI.Command.Type == macho::LCT_Segment) { - InMemoryStruct<macho::SegmentLoadCommand> SegmentLC; - MachOObj->ReadSegmentLoadCommand(LCI, SegmentLC); - - // Store the sections in this segment. - for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) { - InMemoryStruct<macho::Section> Sect; - MachOObj->ReadSection(LCI, SectNum, Sect); - Sections.push_back(copySection(Sect)); + error_code ec; + for (symbol_iterator SI = MachOObj->begin_symbols(), + SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec)) + Symbols.push_back(*SI); + + for (section_iterator SI = MachOObj->begin_sections(), + SE = MachOObj->end_sections(); SI != SE; SI.increment(ec)) { + SectionRef SR = *SI; + StringRef SectName; + SR.getName(SectName); + Sections.push_back(*SI); + } - } - } else if (LCI.Command.Type == macho::LCT_Segment64) { - InMemoryStruct<macho::Segment64LoadCommand> Segment64LC; - MachOObj->ReadSegment64LoadCommand(LCI, Segment64LC); - - // Store the sections in this segment. - for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections; - ++SectNum) { - InMemoryStruct<macho::Section64> Sect64; - MachOObj->ReadSection64(LCI, SectNum, Sect64); - Sections.push_back(copySection(Sect64)); - } - } else if (LCI.Command.Type == macho::LCT_FunctionStarts) { + for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + const MachOObject::LoadCommandInfo &LCI = + MachOObj->getObject()->getLoadCommandInfo(i); + if (LCI.Command.Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. InMemoryStruct<macho::LinkeditDataLoadCommand> LLC; - MachOObj->ReadLinkeditDataLoadCommand(LCI, LLC); + MachOObj->getObject()->ReadLinkeditDataLoadCommand(LCI, LLC); - MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); - } - } - // Store the symbols. - if (SymtabLC) { - for (unsigned i = 0; i != (*SymtabLC)->NumSymbolTableEntries; ++i) { - if (MachOObj->is64Bit()) { - InMemoryStruct<macho::Symbol64TableEntry> STE; - MachOObj->ReadSymbol64TableEntry((*SymtabLC)->SymbolTableOffset, i, - STE); - Symbols.push_back(copySymbol(STE)); - } else { - InMemoryStruct<macho::SymbolTableEntry> STE; - MachOObj->ReadSymbolTableEntry((*SymtabLC)->SymbolTableOffset, i, - STE); - Symbols.push_back(copySymbol(STE)); - } + MachOObj->getObject()->ReadULEB128s(LLC->DataOffset, FoundFns); } } } @@ -277,9 +240,11 @@ void llvm::DisassembleInputMachO(StringRef Filename) { return; } - OwningPtr<MachOObject> MachOObj(MachOObject::LoadFromBuffer(Buff.take())); + OwningPtr<MachOObjectFile> MachOOF(static_cast<MachOObjectFile*>( + ObjectFile::createMachOObjectFile(Buff.take()))); + MachOObject *MachOObj = MachOOF->getObject(); - const Target *TheTarget = GetTarget(MachOObj.get()); + const Target *TheTarget = GetTarget(MachOObj); if (!TheTarget) { // GetTarget prints out stuff. return; @@ -293,9 +258,11 @@ void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr<const MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, "", "")); OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); + OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); - OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( - AsmPrinterVariant, *AsmInfo, *STI)); + OwningPtr<MCInstPrinter> + IP(TheTarget->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *InstrInfo, + *MRI, *STI)); if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) { errs() << "error: couldn't initialize disassembler for target " @@ -322,17 +289,17 @@ void llvm::DisassembleInputMachO(StringRef Filename) { MachOObj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC); MachOObj->RegisterStringTable(*SymtabLC); - std::vector<Section> Sections; - std::vector<Symbol> Symbols; + std::vector<SectionRef> Sections; + std::vector<SymbolRef> Symbols; SmallVector<uint64_t, 8> FoundFns; - getSectionsAndSymbols(Header, MachOObj.get(), &SymtabLC, Sections, Symbols, + getSectionsAndSymbols(Header, MachOOF.get(), &SymtabLC, Sections, Symbols, FoundFns); // Make a copy of the unsorted symbol list. FIXME: duplication - std::vector<Symbol> UnsortedSymbols(Symbols); + std::vector<SymbolRef> UnsortedSymbols(Symbols); // Sort the symbols by address, just in case they didn't come in that way. - array_pod_sort(Symbols.begin(), Symbols.end()); + std::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); #ifndef NDEBUG raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); @@ -343,12 +310,12 @@ void llvm::DisassembleInputMachO(StringRef Filename) { StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection, DebugLineSection, DebugStrSection; OwningPtr<DIContext> diContext; - OwningPtr<MachOObject> DSYMObj; - MachOObject *DbgInfoObj = MachOObj.get(); + OwningPtr<MachOObjectFile> DSYMObj; + MachOObject *DbgInfoObj = MachOObj; // Try to find debug info and set up the DIContext for it. if (UseDbg) { - ArrayRef<Section> DebugSections = Sections; - std::vector<Section> DSYMSections; + ArrayRef<SectionRef> DebugSections = Sections; + std::vector<SectionRef> DSYMSections; // A separate DSym file path was specified, parse it as a macho file, // get the sections and supply it to the section name parsing machinery. @@ -358,34 +325,33 @@ void llvm::DisassembleInputMachO(StringRef Filename) { errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n'; return; } - DSYMObj.reset(MachOObject::LoadFromBuffer(Buf.take())); - const macho::Header &Header = DSYMObj->getHeader(); + DSYMObj.reset(static_cast<MachOObjectFile*>( + ObjectFile::createMachOObjectFile(Buf.take()))); + const macho::Header &Header = DSYMObj->getObject()->getHeader(); - std::vector<Symbol> Symbols; + std::vector<SymbolRef> Symbols; SmallVector<uint64_t, 8> FoundFns; getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols, FoundFns); DebugSections = DSYMSections; - DbgInfoObj = DSYMObj.get(); + DbgInfoObj = DSYMObj.get()->getObject(); } // Find the named debug info sections. for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) { - if (!strcmp(DebugSections[SectIdx].Name, "__debug_abbrev")) - DebugAbbrevSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, - DebugSections[SectIdx].Size); - else if (!strcmp(DebugSections[SectIdx].Name, "__debug_info")) - DebugInfoSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, - DebugSections[SectIdx].Size); - else if (!strcmp(DebugSections[SectIdx].Name, "__debug_aranges")) - DebugArangesSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, - DebugSections[SectIdx].Size); - else if (!strcmp(DebugSections[SectIdx].Name, "__debug_line")) - DebugLineSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, - DebugSections[SectIdx].Size); - else if (!strcmp(DebugSections[SectIdx].Name, "__debug_str")) - DebugStrSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, - DebugSections[SectIdx].Size); + StringRef SectName; + if (!DebugSections[SectIdx].getName(SectName)) { + if (SectName.equals("__DWARF,__debug_abbrev")) + DebugSections[SectIdx].getContents(DebugAbbrevSection); + else if (SectName.equals("__DWARF,__debug_info")) + DebugSections[SectIdx].getContents(DebugInfoSection); + else if (SectName.equals("__DWARF,__debug_aranges")) + DebugSections[SectIdx].getContents(DebugArangesSection); + else if (SectName.equals("__DWARF,__debug_line")) + DebugSections[SectIdx].getContents(DebugLineSection); + else if (SectName.equals("__DWARF,__debug_str")) + DebugSections[SectIdx].getContents(DebugStrSection); + } } // Setup the DIContext. @@ -401,68 +367,115 @@ void llvm::DisassembleInputMachO(StringRef Filename) { FunctionListTy Functions; for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { - if (strcmp(Sections[SectIdx].Name, "__text")) + StringRef SectName; + if (Sections[SectIdx].getName(SectName) || + SectName.compare("__TEXT,__text")) continue; // Skip non-text sections // Insert the functions from the function starts segment into our map. - uint64_t VMAddr = Sections[SectIdx].Address - Sections[SectIdx].Offset; - for (unsigned i = 0, e = FoundFns.size(); i != e; ++i) - FunctionMap.insert(std::make_pair(FoundFns[i]+VMAddr, (MCFunction*)0)); + uint64_t VMAddr; + Sections[SectIdx].getAddress(VMAddr); + for (unsigned i = 0, e = FoundFns.size(); i != e; ++i) { + StringRef SectBegin; + Sections[SectIdx].getContents(SectBegin); + uint64_t Offset = (uint64_t)SectBegin.data(); + FunctionMap.insert(std::make_pair(VMAddr + FoundFns[i]-Offset, + (MCFunction*)0)); + } - StringRef Bytes = MachOObj->getData(Sections[SectIdx].Offset, - Sections[SectIdx].Size); + StringRef Bytes; + Sections[SectIdx].getContents(Bytes); StringRefMemoryObject memoryObject(Bytes); bool symbolTableWorked = false; // Parse relocations. - std::vector<std::pair<uint64_t, uint32_t> > Relocs; - for (unsigned j = 0; j != Sections[SectIdx].NumRelocs; ++j) { - InMemoryStruct<macho::RelocationEntry> RE; - MachOObj->ReadRelocationEntry(Sections[SectIdx].RelocTableOffset, j, RE); - Relocs.push_back(std::make_pair(RE->Word0, RE->Word1 & 0xffffff)); + std::vector<std::pair<uint64_t, SymbolRef> > Relocs; + error_code ec; + for (relocation_iterator RI = Sections[SectIdx].begin_relocations(), + RE = Sections[SectIdx].end_relocations(); RI != RE; RI.increment(ec)) { + uint64_t RelocOffset, SectionAddress; + RI->getAddress(RelocOffset); + Sections[SectIdx].getAddress(SectionAddress); + RelocOffset -= SectionAddress; + + SymbolRef RelocSym; + RI->getSymbol(RelocSym); + + Relocs.push_back(std::make_pair(RelocOffset, RelocSym)); } array_pod_sort(Relocs.begin(), Relocs.end()); // Disassemble symbol by symbol. for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { + StringRef SymName; + Symbols[SymIdx].getName(SymName); + + SymbolRef::Type ST; + Symbols[SymIdx].getType(ST); + if (ST != SymbolRef::ST_Function) + continue; + // Make sure the symbol is defined in this section. - if ((unsigned)Symbols[SymIdx].SectionIndex - 1 != SectIdx) + bool containsSym = false; + Sections[SectIdx].containsSymbol(Symbols[SymIdx], containsSym); + if (!containsSym) continue; // Start at the address of the symbol relative to the section's address. - uint64_t Start = Symbols[SymIdx].Value - Sections[SectIdx].Address; + uint64_t SectionAddress = 0; + uint64_t Start = 0; + Sections[SectIdx].getAddress(SectionAddress); + Symbols[SymIdx].getAddress(Start); + Start -= SectionAddress; + // Stop disassembling either at the beginning of the next symbol or at // the end of the section. - uint64_t End = (SymIdx+1 == Symbols.size() || - Symbols[SymIdx].SectionIndex != Symbols[SymIdx+1].SectionIndex) ? - Sections[SectIdx].Size : - Symbols[SymIdx+1].Value - Sections[SectIdx].Address; - uint64_t Size; + bool containsNextSym = true; + uint64_t NextSym = 0; + uint64_t NextSymIdx = SymIdx+1; + while (Symbols.size() > NextSymIdx) { + SymbolRef::Type NextSymType; + Symbols[NextSymIdx].getType(NextSymType); + if (NextSymType == SymbolRef::ST_Function) { + Sections[SectIdx].containsSymbol(Symbols[NextSymIdx], + containsNextSym); + Symbols[NextSymIdx].getAddress(NextSym); + NextSym -= SectionAddress; + break; + } + ++NextSymIdx; + } - if (Start >= End) - continue; + uint64_t SectSize; + Sections[SectIdx].getSize(SectSize); + uint64_t End = containsNextSym ? NextSym : SectSize; + uint64_t Size; symbolTableWorked = true; if (!CFG) { // Normal disassembly, print addresses, bytes and mnemonic form. - outs() << MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex) - << ":\n"; + StringRef SymName; + Symbols[SymIdx].getName(SymName); + + outs() << SymName << ":\n"; DILineInfo lastLine; for (uint64_t Index = Start; Index < End; Index += Size) { MCInst Inst; if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut, nulls())) { - outs() << format("%8llx:\t", Sections[SectIdx].Address + Index); + uint64_t SectAddress = 0; + Sections[SectIdx].getAddress(SectAddress); + outs() << format("%8" PRIx64 ":\t", SectAddress + Index); + DumpBytes(StringRef(Bytes.data() + Index, Size)); IP->printInst(&Inst, outs(), ""); // Print debug info. if (diContext) { DILineInfo dli = - diContext->getLineInfoForAddress(Sections[SectIdx].Address + - Index); + diContext->getLineInfoForAddress(SectAddress + Index); // Print valid line info if it changed. if (dli != lastLine && dli.getLine() != 0) outs() << "\t## " << dli.getFileName() << ':' @@ -478,20 +491,24 @@ void llvm::DisassembleInputMachO(StringRef Filename) { } } else { // Create CFG and use it for disassembly. + StringRef SymName; + Symbols[SymIdx].getName(SymName); createMCFunctionAndSaveCalls( - MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex), - DisAsm.get(), memoryObject, Start, End, InstrAnalysis.get(), - Start, DebugOut, FunctionMap, Functions); + SymName, DisAsm.get(), memoryObject, Start, End, + InstrAnalysis.get(), Start, DebugOut, FunctionMap, Functions); } } if (CFG) { if (!symbolTableWorked) { // Reading the symbol table didn't work, create a big __TEXT symbol. + uint64_t SectSize = 0, SectAddress = 0; + Sections[SectIdx].getSize(SectSize); + Sections[SectIdx].getAddress(SectAddress); createMCFunctionAndSaveCalls("__TEXT", DisAsm.get(), memoryObject, - 0, Sections[SectIdx].Size, + 0, SectSize, InstrAnalysis.get(), - Sections[SectIdx].Offset, DebugOut, + SectAddress, DebugOut, FunctionMap, Functions); } for (std::map<uint64_t, MCFunction*>::iterator mi = FunctionMap.begin(), @@ -499,11 +516,14 @@ void llvm::DisassembleInputMachO(StringRef Filename) { if (mi->second == 0) { // Create functions for the remaining callees we have gathered, // but we didn't find a name for them. + uint64_t SectSize = 0; + Sections[SectIdx].getSize(SectSize); + SmallVector<uint64_t, 16> Calls; MCFunction f = MCFunction::createFunctionFromMC("unknown", DisAsm.get(), memoryObject, mi->first, - Sections[SectIdx].Size, + SectSize, InstrAnalysis.get(), DebugOut, Calls); Functions.push_back(f); @@ -535,13 +555,17 @@ void llvm::DisassembleInputMachO(StringRef Filename) { break; } + uint64_t SectSize = 0, SectAddress; + Sections[SectIdx].getSize(SectSize); + Sections[SectIdx].getAddress(SectAddress); + // No predecessors, this is a data block. Print as .byte directives. if (!hasPreds) { - uint64_t End = llvm::next(fi) == fe ? Sections[SectIdx].Size : + uint64_t End = llvm::next(fi) == fe ? SectSize : llvm::next(fi)->first; outs() << "# " << End-fi->first << " bytes of data:\n"; for (unsigned pos = fi->first; pos != End; ++pos) { - outs() << format("%8x:\t", Sections[SectIdx].Address + pos); + outs() << format("%8x:\t", SectAddress + pos); DumpBytes(StringRef(Bytes.data() + pos, 1)); outs() << format("\t.byte 0x%02x\n", (uint8_t)Bytes[pos]); } @@ -558,13 +582,12 @@ void llvm::DisassembleInputMachO(StringRef Filename) { const MCDecodedInst &Inst = fi->second.getInsts()[ii]; // If there's a symbol at this address, print its name. - if (FunctionMap.find(Sections[SectIdx].Address + Inst.Address) != + if (FunctionMap.find(SectAddress + Inst.Address) != FunctionMap.end()) - outs() << FunctionMap[Sections[SectIdx].Address + Inst.Address]-> - getName() << ":\n"; + outs() << FunctionMap[SectAddress + Inst.Address]-> getName() + << ":\n"; - outs() << format("%8llx:\t", Sections[SectIdx].Address + - Inst.Address); + outs() << format("%8" PRIx64 ":\t", SectAddress + Inst.Address); DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size)); if (fi->second.contains(fi->first)) // Indent simple loops. @@ -575,15 +598,15 @@ void llvm::DisassembleInputMachO(StringRef Filename) { // Look for relocations inside this instructions, if there is one // print its target and additional information if available. for (unsigned j = 0; j != Relocs.size(); ++j) - if (Relocs[j].first >= Sections[SectIdx].Address + Inst.Address && - Relocs[j].first < Sections[SectIdx].Address + Inst.Address + - Inst.Size) { - outs() << "\t# " - << MachOObj->getStringAtIndex( - UnsortedSymbols[Relocs[j].second].StringIndex) - << ' '; - DumpAddress(UnsortedSymbols[Relocs[j].second].Value, Sections, - MachOObj.get(), outs()); + if (Relocs[j].first >= SectAddress + Inst.Address && + Relocs[j].first < SectAddress + Inst.Address + Inst.Size) { + StringRef SymName; + uint64_t Addr; + Relocs[j].second.getAddress(Addr); + Relocs[j].second.getName(SymName); + + outs() << "\t# " << SymName << ' '; + DumpAddress(Addr, Sections, MachOObj, outs()); } // If this instructions contains an address, see if we can evaluate @@ -592,13 +615,12 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Inst.Address, Inst.Size); if (targ != -1ULL) - DumpAddress(targ, Sections, MachOObj.get(), outs()); + DumpAddress(targ, Sections, MachOObj, outs()); // Print debug info. if (diContext) { DILineInfo dli = - diContext->getLineInfoForAddress(Sections[SectIdx].Address + - Inst.Address); + diContext->getLineInfoForAddress(SectAddress + Inst.Address); // Print valid line info if it changed. if (dli != lastLine && dli.getLine() != 0) outs() << "\t## " << dli.getFileName() << ':' diff --git a/tools/llvm-objdump/Makefile b/tools/llvm-objdump/Makefile index 703bf6c..4616b78 100644 --- a/tools/llvm-objdump/Makefile +++ b/tools/llvm-objdump/Makefile @@ -6,13 +6,12 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-objdump -LINK_COMPONENTS = $(TARGETS_TO_BUILD) DebugInfo MC MCParser MCDisassembler \ - Object +LEVEL := ../.. +TOOLNAME := llvm-objdump +LINK_COMPONENTS := all-targets DebugInfo MC MCParser MCDisassembler Object # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 40c59bd..5a6f94a 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -16,14 +16,18 @@ #include "llvm-objdump.h" #include "MCFunction.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -43,6 +47,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include <algorithm> +#include <cctype> #include <cstring> using namespace llvm; using namespace object; @@ -61,6 +66,12 @@ static cl::opt<bool> Relocations("r", cl::desc("Display the relocation entries in the file")); static cl::opt<bool> +SectionContents("s", cl::desc("Display the content of each section")); + +static cl::opt<bool> +SymbolTable("t", cl::desc("Display the symbol table")); + +static cl::opt<bool> MachO("macho", cl::desc("Use MachO specific object file parser")); static cl::alias MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachO)); @@ -118,6 +129,8 @@ static const Target *GetTarget(const ObjectFile *Obj = NULL) { return 0; } +void llvm::StringRefMemoryObject::anchor() { } + void llvm::DumpBytes(StringRef bytes) { static const char hex_rep[] = "0123456789abcdef"; // FIXME: The real way to do this is to figure out the longest instruction @@ -158,10 +171,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { return; } - outs() << '\n'; - outs() << Obj->getFileName() - << ":\tfile format " << Obj->getFileFormatName() << "\n\n"; - error_code ec; for (section_iterator i = Obj->begin_sections(), e = Obj->end_sections(); @@ -182,7 +191,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { bool contains; if (!error(i->containsSymbol(*si, contains)) && contains) { uint64_t Address; - if (error(si->getOffset(Address))) break; + if (error(si->getAddress(Address))) break; + Address -= SectionAddr; + StringRef Name; if (error(si->getName(Name))) break; Symbols.push_back(std::make_pair(Address, Name)); @@ -238,9 +249,21 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { return; } + OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); + if (!MRI) { + errs() << "error: no register info for target " << TripleName << "\n"; + return; + } + + OwningPtr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); + if (!MII) { + errs() << "error: no instruction info for target " << TripleName << "\n"; + return; + } + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( - AsmPrinterVariant, *AsmInfo, *STI)); + AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); if (!IP) { errs() << "error: no instruction printer for target " << TripleName << '\n'; @@ -285,7 +308,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut, nulls())) { - outs() << format("%8"PRIx64":\t", SectionAddr + Index); + outs() << format("%8" PRIx64 ":\t", SectionAddr + Index); DumpBytes(StringRef(Bytes.data() + Index, Size)); IP->printInst(&Inst, outs(), ""); outs() << "\n"; @@ -297,17 +320,23 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // Print relocation for instruction. while (rel_cur != rel_end) { + bool hidden = false; uint64_t addr; SmallString<16> name; SmallString<32> val; + + // If this relocation is hidden, skip it. + if (error(rel_cur->getHidden(hidden))) goto skip_print_rel; + if (hidden) goto skip_print_rel; + if (error(rel_cur->getAddress(addr))) goto skip_print_rel; // Stop when rel_cur's address is past the current instruction. - if (addr > Index + Size) break; + if (addr >= Index + Size) break; if (error(rel_cur->getTypeName(name))) goto skip_print_rel; if (error(rel_cur->getValueString(val))) goto skip_print_rel; - outs() << format("\t\t\t%8"PRIx64": ", SectionAddr + addr) << name << "\t" - << val << "\n"; + outs() << format("\t\t\t%8" PRIx64 ": ", SectionAddr + addr) << name + << "\t" << val << "\n"; skip_print_rel: ++rel_cur; @@ -332,9 +361,12 @@ static void PrintRelocations(const ObjectFile *o) { ri != re; ri.increment(ec)) { if (error(ec)) return; + bool hidden; uint64_t address; SmallString<32> relocname; SmallString<32> valuestr; + if (error(ri->getHidden(hidden))) continue; + if (hidden) continue; if (error(ri->getTypeName(relocname))) continue; if (error(ri->getAddress(address))) continue; if (error(ri->getValueString(valuestr))) continue; @@ -364,19 +396,179 @@ static void PrintSectionHeaders(const ObjectFile *o) { if (error(si->isBSS(BSS))) return; std::string Type = (std::string(Text ? "TEXT " : "") + (Data ? "DATA " : "") + (BSS ? "BSS" : "")); - outs() << format("%3d %-13s %09"PRIx64" %017"PRIx64" %s\n", i, Name.str().c_str(), Size, - Address, Type.c_str()); + outs() << format("%3d %-13s %09" PRIx64 " %017" PRIx64 " %s\n", + i, Name.str().c_str(), Size, Address, Type.c_str()); ++i; } } +static void PrintSectionContents(const ObjectFile *o) { + error_code ec; + for (section_iterator si = o->begin_sections(), + se = o->end_sections(); + si != se; si.increment(ec)) { + if (error(ec)) return; + StringRef Name; + StringRef Contents; + uint64_t BaseAddr; + if (error(si->getName(Name))) continue; + if (error(si->getContents(Contents))) continue; + if (error(si->getAddress(BaseAddr))) continue; + + outs() << "Contents of section " << Name << ":\n"; + + // Dump out the content as hex and printable ascii characters. + for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) { + outs() << format(" %04" PRIx64 " ", BaseAddr + addr); + // Dump line of hex. + for (std::size_t i = 0; i < 16; ++i) { + if (i != 0 && i % 4 == 0) + outs() << ' '; + if (addr + i < end) + outs() << hexdigit((Contents[addr + i] >> 4) & 0xF, true) + << hexdigit(Contents[addr + i] & 0xF, true); + else + outs() << " "; + } + // Print ascii. + outs() << " "; + for (std::size_t i = 0; i < 16 && addr + i < end; ++i) { + if (std::isprint(Contents[addr + i] & 0xFF)) + outs() << Contents[addr + i]; + else + outs() << "."; + } + outs() << "\n"; + } + } +} + +static void PrintCOFFSymbolTable(const COFFObjectFile *coff) { + const coff_file_header *header; + if (error(coff->getHeader(header))) return; + int aux_count = 0; + const coff_symbol *symbol = 0; + for (int i = 0, e = header->NumberOfSymbols; i != e; ++i) { + if (aux_count--) { + // Figure out which type of aux this is. + if (symbol->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC + && symbol->Value == 0) { // Section definition. + const coff_aux_section_definition *asd; + if (error(coff->getAuxSymbol<coff_aux_section_definition>(i, asd))) + return; + outs() << "AUX " + << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x " + , unsigned(asd->Length) + , unsigned(asd->NumberOfRelocations) + , unsigned(asd->NumberOfLinenumbers) + , unsigned(asd->CheckSum)) + << format("assoc %d comdat %d\n" + , unsigned(asd->Number) + , unsigned(asd->Selection)); + } else { + outs() << "AUX Unknown\n"; + } + } else { + StringRef name; + if (error(coff->getSymbol(i, symbol))) return; + if (error(coff->getSymbolName(symbol, name))) return; + outs() << "[" << format("%2d", i) << "]" + << "(sec " << format("%2d", int(symbol->SectionNumber)) << ")" + << "(fl 0x00)" // Flag bits, which COFF doesn't have. + << "(ty " << format("%3x", unsigned(symbol->Type)) << ")" + << "(scl " << format("%3x", unsigned(symbol->StorageClass)) << ") " + << "(nx " << unsigned(symbol->NumberOfAuxSymbols) << ") " + << "0x" << format("%08x", unsigned(symbol->Value)) << " " + << name << "\n"; + aux_count = symbol->NumberOfAuxSymbols; + } + } +} + +static void PrintSymbolTable(const ObjectFile *o) { + outs() << "SYMBOL TABLE:\n"; + + if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) + PrintCOFFSymbolTable(coff); + else { + error_code ec; + for (symbol_iterator si = o->begin_symbols(), + se = o->end_symbols(); si != se; si.increment(ec)) { + if (error(ec)) return; + StringRef Name; + uint64_t Address; + SymbolRef::Type Type; + uint64_t Size; + uint32_t Flags; + section_iterator Section = o->end_sections(); + if (error(si->getName(Name))) continue; + if (error(si->getAddress(Address))) continue; + if (error(si->getFlags(Flags))) continue; + if (error(si->getType(Type))) continue; + if (error(si->getSize(Size))) continue; + if (error(si->getSection(Section))) continue; + + bool Global = Flags & SymbolRef::SF_Global; + bool Weak = Flags & SymbolRef::SF_Weak; + bool Absolute = Flags & SymbolRef::SF_Absolute; + + if (Address == UnknownAddressOrSize) + Address = 0; + if (Size == UnknownAddressOrSize) + Size = 0; + char GlobLoc = ' '; + if (Type != SymbolRef::ST_Unknown) + GlobLoc = Global ? 'g' : 'l'; + char Debug = (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File) + ? 'd' : ' '; + char FileFunc = ' '; + if (Type == SymbolRef::ST_File) + FileFunc = 'f'; + else if (Type == SymbolRef::ST_Function) + FileFunc = 'F'; + + outs() << format("%08" PRIx64, Address) << " " + << GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' ' + << (Weak ? 'w' : ' ') // Weak? + << ' ' // Constructor. Not supported yet. + << ' ' // Warning. Not supported yet. + << ' ' // Indirect reference to another symbol. + << Debug // Debugging (d) or dynamic (D) symbol. + << FileFunc // Name of function (F), file (f) or object (O). + << ' '; + if (Absolute) + outs() << "*ABS*"; + else if (Section == o->end_sections()) + outs() << "*UND*"; + else { + StringRef SectionName; + if (error(Section->getName(SectionName))) + SectionName = ""; + outs() << SectionName; + } + outs() << '\t' + << format("%08" PRIx64 " ", Size) + << Name + << '\n'; + } + } +} + static void DumpObject(const ObjectFile *o) { + outs() << '\n'; + outs() << o->getFileName() + << ":\tfile format " << o->getFileFormatName() << "\n\n"; + if (Disassemble) DisassembleObject(o, Relocations); if (Relocations && !Disassemble) PrintRelocations(o); if (SectionHeaders) PrintSectionHeaders(o); + if (SectionContents) + PrintSectionContents(o); + if (SymbolTable) + PrintSymbolTable(o); } /// @brief Dump each object file in \a a; @@ -385,8 +577,10 @@ static void DumpArchive(const Archive *a) { e = a->end_children(); i != e; ++i) { OwningPtr<Binary> child; if (error_code ec = i->getAsBinary(child)) { - errs() << ToolName << ": '" << a->getFileName() << "': " << ec.message() - << ".\n"; + // Ignore non-object files. + if (ec != object_error::invalid_file_type) + errs() << ToolName << ": '" << a->getFileName() << "': " << ec.message() + << ".\n"; continue; } if (ObjectFile *o = dyn_cast<ObjectFile>(child.get())) @@ -447,7 +641,11 @@ int main(int argc, char **argv) { if (InputFilenames.size() == 0) InputFilenames.push_back("a.out"); - if (!Disassemble && !Relocations && !SectionHeaders) { + if (!Disassemble + && !Relocations + && !SectionHeaders + && !SectionContents + && !SymbolTable) { cl::PrintHelpMessage(); return 2; } diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h index 75f852a..aa71b77 100644 --- a/tools/llvm-objdump/llvm-objdump.h +++ b/tools/llvm-objdump/llvm-objdump.h @@ -25,7 +25,7 @@ void DumpBytes(StringRef bytes); void DisassembleInputMachO(StringRef Filename); class StringRefMemoryObject : public MemoryObject { -private: + virtual void anchor(); StringRef Bytes; public: StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {} diff --git a/tools/llvm-prof/LLVMBuild.txt b/tools/llvm-prof/LLVMBuild.txt new file mode 100644 index 0000000..d59127c --- /dev/null +++ b/tools/llvm-prof/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-prof/LLVMBuild.txt --------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-prof +parent = Tools +required_libraries = Analysis BitReader diff --git a/tools/llvm-prof/Makefile b/tools/llvm-prof/Makefile index 86eb54d..f829786 100644 --- a/tools/llvm-prof/Makefile +++ b/tools/llvm-prof/Makefile @@ -6,10 +6,10 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-prof -LINK_COMPONENTS = bitreader analysis +LEVEL := ../.. +TOOLNAME := llvm-prof +LINK_COMPONENTS := bitreader analysis # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp index 9d0b468..d9b6713 100644 --- a/tools/llvm-prof/llvm-prof.cpp +++ b/tools/llvm-prof/llvm-prof.cpp @@ -200,9 +200,9 @@ bool ProfileInfoPrinterPass::runOnModule(Module &M) { } outs() << format("%3d", i+1) << ". " - << format("%5.2g", FunctionCounts[i].second) << "/" - << format("%g", TotalExecutions) << " " - << FunctionCounts[i].first->getNameStr() << "\n"; + << format("%5.2g", FunctionCounts[i].second) << "/" + << format("%g", TotalExecutions) << " " + << FunctionCounts[i].first->getName() << "\n"; } std::set<Function*> FunctionsToPrint; @@ -225,12 +225,12 @@ bool ProfileInfoPrinterPass::runOnModule(Module &M) { for (unsigned i = 0; i != BlocksToPrint; ++i) { if (Counts[i].second == 0) break; Function *F = Counts[i].first->getParent(); - outs() << format("%3d", i+1) << ". " - << format("%5g", Counts[i].second/(double)TotalExecutions*100) << "% " - << format("%5.0f", Counts[i].second) << "/" - << format("%g", TotalExecutions) << "\t" - << F->getNameStr() << "() - " - << Counts[i].first->getNameStr() << "\n"; + outs() << format("%3d", i+1) << ". " + << format("%5g", Counts[i].second/(double)TotalExecutions*100)<<"% " + << format("%5.0f", Counts[i].second) << "/" + << format("%g", TotalExecutions) << "\t" + << F->getName() << "() - " + << Counts[i].first->getName() << "\n"; FunctionsToPrint.insert(F); } diff --git a/tools/llvm-ranlib/LLVMBuild.txt b/tools/llvm-ranlib/LLVMBuild.txt new file mode 100644 index 0000000..23015c5 --- /dev/null +++ b/tools/llvm-ranlib/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-ranlib/LLVMBuild.txt ------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-ranlib +parent = Tools +required_libraries = Archive diff --git a/tools/llvm-ranlib/Makefile b/tools/llvm-ranlib/Makefile index 46a10e6..36195f4 100644 --- a/tools/llvm-ranlib/Makefile +++ b/tools/llvm-ranlib/Makefile @@ -7,12 +7,12 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-ranlib -LINK_COMPONENTS = archive +LEVEL := ../.. +TOOLNAME := llvm-ranlib +LINK_COMPONENTS := archive REQUIRES_EH := 1 # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +TOOL_NO_EXPORTS := 1 include $(LEVEL)/Makefile.common diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt new file mode 100644 index 0000000..be80469 --- /dev/null +++ b/tools/llvm-readobj/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS archive bitreader object) + +add_llvm_tool(llvm-readobj + llvm-readobj.cpp + ) diff --git a/tools/llvm-readobj/LLVMBuild.txt b/tools/llvm-readobj/LLVMBuild.txt new file mode 100644 index 0000000..c9f934f --- /dev/null +++ b/tools/llvm-readobj/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-readobj/LLVMBuild.txt ---------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-readobj +parent = Tools +required_libraries = Archive BitReader Object diff --git a/tools/llvm-readobj/Makefile b/tools/llvm-readobj/Makefile new file mode 100644 index 0000000..a7a7de3 --- /dev/null +++ b/tools/llvm-readobj/Makefile @@ -0,0 +1,18 @@ +##===- tools/llvm-readobj/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-readobj +LINK_COMPONENTS := archive bitreader object + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS := 1 + +include $(LEVEL)/Makefile.common + diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp new file mode 100644 index 0000000..3be1289 --- /dev/null +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -0,0 +1,218 @@ +//===- llvm-readobj.cpp - Dump contents of an Object File -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program is a utility that works like traditional Unix "readelf", +// except that it can handle any type of object file recognized by lib/Object. +// +// It makes use of the generic ObjectFile interface. +// +// Caution: This utility is new, experimental, unsupported, and incomplete. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELF.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; +using namespace llvm::object; + +static cl::opt<std::string> +InputFilename(cl::Positional, cl::desc("<input object>"), cl::init("")); + +void DumpSymbolHeader() { + outs() << format(" %-32s", (const char*)"Name") + << format(" %-4s", (const char*)"Type") + << format(" %-16s", (const char*)"Address") + << format(" %-16s", (const char*)"Size") + << format(" %-16s", (const char*)"FileOffset") + << format(" %-26s", (const char*)"Flags") + << "\n"; +} + +const char *GetTypeStr(SymbolRef::Type Type) { + switch (Type) { + case SymbolRef::ST_Unknown: return "?"; + case SymbolRef::ST_Data: return "DATA"; + case SymbolRef::ST_Debug: return "DBG"; + case SymbolRef::ST_File: return "FILE"; + case SymbolRef::ST_Function: return "FUNC"; + case SymbolRef::ST_Other: return "-"; + } + return "INV"; +} + +std::string GetFlagStr(uint32_t Flags) { + std::string result; + if (Flags & SymbolRef::SF_Undefined) + result += "undef,"; + if (Flags & SymbolRef::SF_Global) + result += "global,"; + if (Flags & SymbolRef::SF_Weak) + result += "weak,"; + if (Flags & SymbolRef::SF_Absolute) + result += "absolute,"; + if (Flags & SymbolRef::SF_ThreadLocal) + result += "threadlocal,"; + if (Flags & SymbolRef::SF_Common) + result += "common,"; + if (Flags & SymbolRef::SF_FormatSpecific) + result += "formatspecific,"; + + // Remove trailing comma + if (result.size() > 0) { + result.erase(result.size() - 1); + } + return result; +} + +void DumpSymbol(const SymbolRef &Sym, const ObjectFile *obj, bool IsDynamic) { + StringRef Name; + SymbolRef::Type Type; + uint32_t Flags; + uint64_t Address; + uint64_t Size; + uint64_t FileOffset; + Sym.getName(Name); + Sym.getAddress(Address); + Sym.getSize(Size); + Sym.getFileOffset(FileOffset); + Sym.getType(Type); + Sym.getFlags(Flags); + std::string FullName = Name; + + // If this is a dynamic symbol from an ELF object, append + // the symbol's version to the name. + if (IsDynamic && obj->isELF()) { + StringRef Version; + bool IsDefault; + GetELFSymbolVersion(obj, Sym, Version, IsDefault); + if (!Version.empty()) { + FullName += (IsDefault ? "@@" : "@"); + FullName += Version; + } + } + + // format() can't handle StringRefs + outs() << format(" %-32s", FullName.c_str()) + << format(" %-4s", GetTypeStr(Type)) + << format(" %16" PRIx64, Address) + << format(" %16" PRIx64, Size) + << format(" %16" PRIx64, FileOffset) + << " " << GetFlagStr(Flags) + << "\n"; +} + + +// Iterate through the normal symbols in the ObjectFile +void DumpSymbols(const ObjectFile *obj) { + error_code ec; + uint32_t count = 0; + outs() << "Symbols:\n"; + symbol_iterator it = obj->begin_symbols(); + symbol_iterator ie = obj->end_symbols(); + while (it != ie) { + DumpSymbol(*it, obj, false); + it.increment(ec); + if (ec) + report_fatal_error("Symbol iteration failed"); + ++count; + } + outs() << " Total: " << count << "\n\n"; +} + +// Iterate through the dynamic symbols in the ObjectFile. +void DumpDynamicSymbols(const ObjectFile *obj) { + error_code ec; + uint32_t count = 0; + outs() << "Dynamic Symbols:\n"; + symbol_iterator it = obj->begin_dynamic_symbols(); + symbol_iterator ie = obj->end_dynamic_symbols(); + while (it != ie) { + DumpSymbol(*it, obj, true); + it.increment(ec); + if (ec) + report_fatal_error("Symbol iteration failed"); + ++count; + } + outs() << " Total: " << count << "\n\n"; +} + +void DumpLibrary(const LibraryRef &lib) { + StringRef path; + lib.getPath(path); + outs() << " " << path << "\n"; +} + +// Iterate through needed libraries +void DumpLibrariesNeeded(const ObjectFile *obj) { + error_code ec; + uint32_t count = 0; + library_iterator it = obj->begin_libraries_needed(); + library_iterator ie = obj->end_libraries_needed(); + outs() << "Libraries needed:\n"; + while (it != ie) { + DumpLibrary(*it); + it.increment(ec); + if (ec) + report_fatal_error("Needed libraries iteration failed"); + ++count; + } + outs() << " Total: " << count << "\n\n"; +} + +void DumpHeaders(const ObjectFile *obj) { + outs() << "File Format : " << obj->getFileFormatName() << "\n"; + outs() << "Arch : " + << Triple::getArchTypeName((llvm::Triple::ArchType)obj->getArch()) + << "\n"; + outs() << "Address Size: " << (8*obj->getBytesInAddress()) << " bits\n"; + outs() << "Load Name : " << obj->getLoadName() << "\n"; + outs() << "\n"; +} + +int main(int argc, char** argv) { + error_code ec; + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + cl::ParseCommandLineOptions(argc, argv, + "LLVM Object Reader\n"); + + if (InputFilename.empty()) { + errs() << "Please specify an input filename\n"; + return 1; + } + + // Open the object file + OwningPtr<MemoryBuffer> File; + if (MemoryBuffer::getFile(InputFilename, File)) { + errs() << InputFilename << ": Open failed\n"; + return 1; + } + + ObjectFile *obj = ObjectFile::createObjectFile(File.take()); + if (!obj) { + errs() << InputFilename << ": Object type not recognized\n"; + } + + DumpHeaders(obj); + DumpSymbols(obj); + DumpDynamicSymbols(obj); + DumpLibrariesNeeded(obj); + return 0; +} + diff --git a/tools/llvm-rtdyld/LLVMBuild.txt b/tools/llvm-rtdyld/LLVMBuild.txt new file mode 100644 index 0000000..b36d13c --- /dev/null +++ b/tools/llvm-rtdyld/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-rtdyld/LLVMBuild.txt ------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-rtdyld +parent = Tools +required_libraries = JIT MC Object RuntimeDyld Support all-targets diff --git a/tools/llvm-rtdyld/Makefile b/tools/llvm-rtdyld/Makefile index 0d57277..30fbee0 100644 --- a/tools/llvm-rtdyld/Makefile +++ b/tools/llvm-rtdyld/Makefile @@ -7,17 +7,11 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-rtdyld +LEVEL := ../.. +TOOLNAME := llvm-rtdyld +LINK_COMPONENTS := all-targets support MC object RuntimeDyld JIT # This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 +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 +include $(LEVEL)/Makefile.common diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index ec9d652..01a7d15 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -51,22 +51,30 @@ EntryPoint("entry", class TrivialMemoryManager : public RTDyldMemoryManager { public: SmallVector<sys::MemoryBlock, 16> FunctionMemory; + SmallVector<sys::MemoryBlock, 16> DataMemory; + + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) { + return 0; + } - 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) { +uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID) { return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); } -void TrivialMemoryManager::endFunctionBody(const char *Name, - uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - uintptr_t Size = FunctionEnd - FunctionStart + 1; - FunctionMemory.push_back(sys::MemoryBlock(FunctionStart, Size)); +uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID) { + return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); } static const char *ProgramName; @@ -142,10 +150,7 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n"); switch (Action) { - default: case AC_Execute: return executeInput(); } - - return 0; } diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile index 0695c00..2d2e2c5 100644 --- a/tools/llvm-shlib/Makefile +++ b/tools/llvm-shlib/Makefile @@ -7,13 +7,13 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. +LEVEL := ../.. LIBRARYNAME = LLVM-$(LLVMVersion) -NO_BUILD_ARCHIVE = 1 -LINK_LIBS_IN_SHARED = 1 -SHARED_LIBRARY = 1 +NO_BUILD_ARCHIVE := 1 +LINK_LIBS_IN_SHARED := 1 +SHARED_LIBRARY := 1 include $(LEVEL)/Makefile.config @@ -63,13 +63,15 @@ ifeq ($(HOST_OS),Darwin) endif endif -ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD OpenBSD)) +ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD OpenBSD GNU)) # Include everything from the .a's into the shared library. LLVMLibsOptions := -Wl,--whole-archive $(LLVMLibsOptions) \ -Wl,--no-whole-archive + # Add soname to the library. + LLVMLibsOptions += -Wl,--soname,lib$(LIBRARYNAME)$(SHLIBEXT) endif -ifeq ($(HOST_OS),Linux) +ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux GNU)) # Don't allow unresolved symbols. LLVMLibsOptions += -Wl,--no-undefined endif diff --git a/tools/llvm-size/LLVMBuild.txt b/tools/llvm-size/LLVMBuild.txt new file mode 100644 index 0000000..b4c538a --- /dev/null +++ b/tools/llvm-size/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-size/LLVMBuild.txt --------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-size +parent = Tools +required_libraries = Object diff --git a/tools/llvm-size/Makefile b/tools/llvm-size/Makefile index 5d0e27e..0622eb1 100644 --- a/tools/llvm-size/Makefile +++ b/tools/llvm-size/Makefile @@ -6,10 +6,10 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-size -LINK_COMPONENTS = object +LEVEL := ../.. +TOOLNAME := llvm-size +LINK_COMPONENTS := object # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-size/llvm-size.cpp b/tools/llvm-size/llvm-size.cpp index 70e5cb9..462da40 100644 --- a/tools/llvm-size/llvm-size.cpp +++ b/tools/llvm-size/llvm-size.cpp @@ -96,13 +96,13 @@ static void PrintObjectSectionSizes(ObjectFile *o) { const char *radix_fmt = 0; switch (Radix) { case octal: - radix_fmt = "llo"; + radix_fmt = PRIo64; break; case decimal: - radix_fmt = "llu"; + radix_fmt = PRIu64; break; case hexadecimal: - radix_fmt = "llx"; + radix_fmt = PRIx64; break; } if (OutputFormat == sysv) { @@ -223,8 +223,8 @@ static void PrintObjectSectionSizes(ObjectFile *o) { total_data, total_bss); fmtbuf.clear(); - fmt << "%7" << (Radix == octal ? "llo" : "llu") << " " - << "%7llx "; + fmt << "%7" << (Radix == octal ? PRIo64 : PRIu64) << " " + << "%7" PRIx64 " "; outs() << format(fmt.str().c_str(), total, total); diff --git a/tools/llvm-stress/CMakeLists.txt b/tools/llvm-stress/CMakeLists.txt new file mode 100644 index 0000000..e2d07a5 --- /dev/null +++ b/tools/llvm-stress/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS bitreader asmparser bitwriter instrumentation scalaropts ipo) + +add_llvm_tool(llvm-stress + llvm-stress.cpp + ) diff --git a/tools/llvm-stress/LLVMBuild.txt b/tools/llvm-stress/LLVMBuild.txt new file mode 100644 index 0000000..f383d35 --- /dev/null +++ b/tools/llvm-stress/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-stress/LLVMBuild.txt -------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-stress +parent = Tools +required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Scalar diff --git a/tools/llvm-stress/Makefile b/tools/llvm-stress/Makefile new file mode 100644 index 0000000..90d57c3 --- /dev/null +++ b/tools/llvm-stress/Makefile @@ -0,0 +1,18 @@ +##===- tools/llvm-stress/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-stress +LINK_COMPONENTS := object +LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp new file mode 100644 index 0000000..d284ea5 --- /dev/null +++ b/tools/llvm-stress/llvm-stress.cpp @@ -0,0 +1,702 @@ +//===-- llvm-stress.cpp - Generate random LL files to stress-test LLVM ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program is a utility that generates random .ll files to stress-test +// different components in LLVM. +// +//===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Constants.h" +#include "llvm/Instruction.h" +#include "llvm/CallGraphSCCPass.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Support/PassNameParser.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/ToolOutputFile.h" +#include <memory> +#include <sstream> +#include <set> +#include <vector> +#include <algorithm> +using namespace llvm; + +static cl::opt<unsigned> SeedCL("seed", + cl::desc("Seed used for randomness"), cl::init(0)); +static cl::opt<unsigned> SizeCL("size", + cl::desc("The estimated size of the generated function (# of instrs)"), + cl::init(100)); +static cl::opt<std::string> +OutputFilename("o", cl::desc("Override output filename"), + cl::value_desc("filename")); + +static cl::opt<bool> GenHalfFloat("generate-half-float", + cl::desc("Generate half-length floating-point values"), cl::init(false)); +static cl::opt<bool> GenX86FP80("generate-x86-fp80", + cl::desc("Generate 80-bit X86 floating-point values"), cl::init(false)); +static cl::opt<bool> GenFP128("generate-fp128", + cl::desc("Generate 128-bit floating-point values"), cl::init(false)); +static cl::opt<bool> GenPPCFP128("generate-ppc-fp128", + cl::desc("Generate 128-bit PPC floating-point values"), cl::init(false)); +static cl::opt<bool> GenX86MMX("generate-x86-mmx", + cl::desc("Generate X86 MMX floating-point values"), cl::init(false)); + +/// A utility class to provide a pseudo-random number generator which is +/// the same across all platforms. This is somewhat close to the libc +/// implementation. Note: This is not a cryptographically secure pseudorandom +/// number generator. +class Random { +public: + /// C'tor + Random(unsigned _seed):Seed(_seed) {} + + /// Return a random integer, up to a + /// maximum of 2**19 - 1. + uint32_t Rand() { + uint32_t Val = Seed + 0x000b07a1; + Seed = (Val * 0x3c7c0ac1); + // Only lowest 19 bits are random-ish. + return Seed & 0x7ffff; + } + + /// Return a random 32 bit integer. + uint32_t Rand32() { + uint32_t Val = Rand(); + Val &= 0xffff; + return Val | (Rand() << 16); + } + + /// Return a random 64 bit integer. + uint64_t Rand64() { + uint64_t Val = Rand32(); + return Val | (uint64_t(Rand32()) << 32); + } +private: + unsigned Seed; +}; + +/// Generate an empty function with a default argument list. +Function *GenEmptyFunction(Module *M) { + // Type Definitions + std::vector<Type*> ArgsTy; + // Define a few arguments + LLVMContext &Context = M->getContext(); + ArgsTy.push_back(PointerType::get(IntegerType::getInt8Ty(Context), 0)); + ArgsTy.push_back(PointerType::get(IntegerType::getInt32Ty(Context), 0)); + ArgsTy.push_back(PointerType::get(IntegerType::getInt64Ty(Context), 0)); + ArgsTy.push_back(IntegerType::getInt32Ty(Context)); + ArgsTy.push_back(IntegerType::getInt64Ty(Context)); + ArgsTy.push_back(IntegerType::getInt8Ty(Context)); + + FunctionType *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, 0); + // Pick a unique name to describe the input parameters + std::stringstream ss; + ss<<"autogen_SD"<<SeedCL; + Function *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, + ss.str(), M); + + Func->setCallingConv(CallingConv::C); + return Func; +} + +/// A base class, implementing utilities needed for +/// modifying and adding new random instructions. +struct Modifier { + /// Used to store the randomly generated values. + typedef std::vector<Value*> PieceTable; + +public: + /// C'tor + Modifier(BasicBlock *Block, PieceTable *PT, Random *R): + BB(Block),PT(PT),Ran(R),Context(BB->getContext()) {} + /// Add a new instruction. + virtual void Act() = 0; + /// Add N new instructions, + virtual void ActN(unsigned n) { + for (unsigned i=0; i<n; ++i) + Act(); + } + +protected: + /// Return a random value from the list of known values. + Value *getRandomVal() { + assert(PT->size()); + return PT->at(Ran->Rand() % PT->size()); + } + + Constant *getRandomConstant(Type *Tp) { + if (Tp->isIntegerTy()) { + if (Ran->Rand() & 1) + return ConstantInt::getAllOnesValue(Tp); + return ConstantInt::getNullValue(Tp); + } else if (Tp->isFloatingPointTy()) { + if (Ran->Rand() & 1) + return ConstantFP::getAllOnesValue(Tp); + return ConstantFP::getNullValue(Tp); + } + return UndefValue::get(Tp); + } + + /// Return a random value with a known type. + Value *getRandomValue(Type *Tp) { + unsigned index = Ran->Rand(); + for (unsigned i=0; i<PT->size(); ++i) { + Value *V = PT->at((index + i) % PT->size()); + if (V->getType() == Tp) + return V; + } + + // If the requested type was not found, generate a constant value. + if (Tp->isIntegerTy()) { + if (Ran->Rand() & 1) + return ConstantInt::getAllOnesValue(Tp); + return ConstantInt::getNullValue(Tp); + } else if (Tp->isFloatingPointTy()) { + if (Ran->Rand() & 1) + return ConstantFP::getAllOnesValue(Tp); + return ConstantFP::getNullValue(Tp); + } else if (Tp->isVectorTy()) { + VectorType *VTp = cast<VectorType>(Tp); + + std::vector<Constant*> TempValues; + TempValues.reserve(VTp->getNumElements()); + for (unsigned i = 0; i < VTp->getNumElements(); ++i) + TempValues.push_back(getRandomConstant(VTp->getScalarType())); + + ArrayRef<Constant*> VectorValue(TempValues); + return ConstantVector::get(VectorValue); + } + + return UndefValue::get(Tp); + } + + /// Return a random value of any pointer type. + Value *getRandomPointerValue() { + unsigned index = Ran->Rand(); + for (unsigned i=0; i<PT->size(); ++i) { + Value *V = PT->at((index + i) % PT->size()); + if (V->getType()->isPointerTy()) + return V; + } + return UndefValue::get(pickPointerType()); + } + + /// Return a random value of any vector type. + Value *getRandomVectorValue() { + unsigned index = Ran->Rand(); + for (unsigned i=0; i<PT->size(); ++i) { + Value *V = PT->at((index + i) % PT->size()); + if (V->getType()->isVectorTy()) + return V; + } + return UndefValue::get(pickVectorType()); + } + + /// Pick a random type. + Type *pickType() { + return (Ran->Rand() & 1 ? pickVectorType() : pickScalarType()); + } + + /// Pick a random pointer type. + Type *pickPointerType() { + Type *Ty = pickType(); + return PointerType::get(Ty, 0); + } + + /// Pick a random vector type. + Type *pickVectorType(unsigned len = (unsigned)-1) { + // Pick a random vector width in the range 2**0 to 2**4. + // by adding two randoms we are generating a normal-like distribution + // around 2**3. + unsigned width = 1<<((Ran->Rand() % 3) + (Ran->Rand() % 3)); + Type *Ty; + + // Vectors of x86mmx are illegal; keep trying till we get something else. + do { + Ty = pickScalarType(); + } while (Ty->isX86_MMXTy()); + + if (len != (unsigned)-1) + width = len; + return VectorType::get(Ty, width); + } + + /// Pick a random scalar type. + Type *pickScalarType() { + Type *t = 0; + do { + switch (Ran->Rand() % 30) { + case 0: t = Type::getInt1Ty(Context); break; + case 1: t = Type::getInt8Ty(Context); break; + case 2: t = Type::getInt16Ty(Context); break; + case 3: case 4: + case 5: t = Type::getFloatTy(Context); break; + case 6: case 7: + case 8: t = Type::getDoubleTy(Context); break; + case 9: case 10: + case 11: t = Type::getInt32Ty(Context); break; + case 12: case 13: + case 14: t = Type::getInt64Ty(Context); break; + case 15: case 16: + case 17: if (GenHalfFloat) t = Type::getHalfTy(Context); break; + case 18: case 19: + case 20: if (GenX86FP80) t = Type::getX86_FP80Ty(Context); break; + case 21: case 22: + case 23: if (GenFP128) t = Type::getFP128Ty(Context); break; + case 24: case 25: + case 26: if (GenPPCFP128) t = Type::getPPC_FP128Ty(Context); break; + case 27: case 28: + case 29: if (GenX86MMX) t = Type::getX86_MMXTy(Context); break; + default: llvm_unreachable("Invalid scalar value"); + } + } while (t == 0); + + return t; + } + + /// Basic block to populate + BasicBlock *BB; + /// Value table + PieceTable *PT; + /// Random number generator + Random *Ran; + /// Context + LLVMContext &Context; +}; + +struct LoadModifier: public Modifier { + LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} + virtual void Act() { + // Try to use predefined pointers. If non exist, use undef pointer value; + Value *Ptr = getRandomPointerValue(); + Value *V = new LoadInst(Ptr, "L", BB->getTerminator()); + PT->push_back(V); + } +}; + +struct StoreModifier: public Modifier { + StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} + virtual void Act() { + // Try to use predefined pointers. If non exist, use undef pointer value; + Value *Ptr = getRandomPointerValue(); + Type *Tp = Ptr->getType(); + Value *Val = getRandomValue(Tp->getContainedType(0)); + Type *ValTy = Val->getType(); + + // Do not store vectors of i1s because they are unsupported + // by the codegen. + if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1) + return; + + new StoreInst(Val, Ptr, BB->getTerminator()); + } +}; + +struct BinModifier: public Modifier { + BinModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} + + virtual void Act() { + Value *Val0 = getRandomVal(); + Value *Val1 = getRandomValue(Val0->getType()); + + // Don't handle pointer types. + if (Val0->getType()->isPointerTy() || + Val1->getType()->isPointerTy()) + return; + + // Don't handle i1 types. + if (Val0->getType()->getScalarSizeInBits() == 1) + return; + + + bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy(); + Instruction* Term = BB->getTerminator(); + unsigned R = Ran->Rand() % (isFloat ? 7 : 13); + Instruction::BinaryOps Op; + + switch (R) { + default: llvm_unreachable("Invalid BinOp"); + case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; } + case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; } + case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; } + case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; } + case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; } + case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; } + case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; } + case 7: {Op = Instruction::Shl; break; } + case 8: {Op = Instruction::LShr; break; } + case 9: {Op = Instruction::AShr; break; } + case 10:{Op = Instruction::And; break; } + case 11:{Op = Instruction::Or; break; } + case 12:{Op = Instruction::Xor; break; } + } + + PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term)); + } +}; + +/// Generate constant values. +struct ConstModifier: public Modifier { + ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} + virtual void Act() { + Type *Ty = pickType(); + + if (Ty->isVectorTy()) { + switch (Ran->Rand() % 2) { + case 0: if (Ty->getScalarType()->isIntegerTy()) + return PT->push_back(ConstantVector::getAllOnesValue(Ty)); + case 1: if (Ty->getScalarType()->isIntegerTy()) + return PT->push_back(ConstantVector::getNullValue(Ty)); + } + } + + if (Ty->isFloatingPointTy()) { + // Generate 128 random bits, the size of the (currently) + // largest floating-point types. + uint64_t RandomBits[2]; + for (unsigned i = 0; i < 2; ++i) + RandomBits[i] = Ran->Rand64(); + + APInt RandomInt(Ty->getPrimitiveSizeInBits(), makeArrayRef(RandomBits)); + + bool isIEEE = !Ty->isX86_FP80Ty() && !Ty->isPPC_FP128Ty(); + APFloat RandomFloat(RandomInt, isIEEE); + + if (Ran->Rand() & 1) + return PT->push_back(ConstantFP::getNullValue(Ty)); + return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat)); + } + + if (Ty->isIntegerTy()) { + switch (Ran->Rand() % 7) { + case 0: if (Ty->isIntegerTy()) + return PT->push_back(ConstantInt::get(Ty, + APInt::getAllOnesValue(Ty->getPrimitiveSizeInBits()))); + case 1: if (Ty->isIntegerTy()) + return PT->push_back(ConstantInt::get(Ty, + APInt::getNullValue(Ty->getPrimitiveSizeInBits()))); + case 2: case 3: case 4: case 5: + case 6: if (Ty->isIntegerTy()) + PT->push_back(ConstantInt::get(Ty, Ran->Rand())); + } + } + + } +}; + +struct AllocaModifier: public Modifier { + AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R){} + + virtual void Act() { + Type *Tp = pickType(); + PT->push_back(new AllocaInst(Tp, "A", BB->getFirstNonPHI())); + } +}; + +struct ExtractElementModifier: public Modifier { + ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R): + Modifier(BB, PT, R) {} + + virtual void Act() { + Value *Val0 = getRandomVectorValue(); + Value *V = ExtractElementInst::Create(Val0, + ConstantInt::get(Type::getInt32Ty(BB->getContext()), + Ran->Rand() % cast<VectorType>(Val0->getType())->getNumElements()), + "E", BB->getTerminator()); + return PT->push_back(V); + } +}; + +struct ShuffModifier: public Modifier { + ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} + virtual void Act() { + + Value *Val0 = getRandomVectorValue(); + Value *Val1 = getRandomValue(Val0->getType()); + + unsigned Width = cast<VectorType>(Val0->getType())->getNumElements(); + std::vector<Constant*> Idxs; + + Type *I32 = Type::getInt32Ty(BB->getContext()); + for (unsigned i=0; i<Width; ++i) { + Constant *CI = ConstantInt::get(I32, Ran->Rand() % (Width*2)); + // Pick some undef values. + if (!(Ran->Rand() % 5)) + CI = UndefValue::get(I32); + Idxs.push_back(CI); + } + + Constant *Mask = ConstantVector::get(Idxs); + + Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff", + BB->getTerminator()); + PT->push_back(V); + } +}; + +struct InsertElementModifier: public Modifier { + InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R): + Modifier(BB, PT, R) {} + + virtual void Act() { + Value *Val0 = getRandomVectorValue(); + Value *Val1 = getRandomValue(Val0->getType()->getScalarType()); + + Value *V = InsertElementInst::Create(Val0, Val1, + ConstantInt::get(Type::getInt32Ty(BB->getContext()), + Ran->Rand() % cast<VectorType>(Val0->getType())->getNumElements()), + "I", BB->getTerminator()); + return PT->push_back(V); + } + +}; + +struct CastModifier: public Modifier { + CastModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} + virtual void Act() { + + Value *V = getRandomVal(); + Type *VTy = V->getType(); + Type *DestTy = pickScalarType(); + + // Handle vector casts vectors. + if (VTy->isVectorTy()) { + VectorType *VecTy = cast<VectorType>(VTy); + DestTy = pickVectorType(VecTy->getNumElements()); + } + + // no need to casr. + if (VTy == DestTy) return; + + // Pointers: + if (VTy->isPointerTy()) { + if (!DestTy->isPointerTy()) + DestTy = PointerType::get(DestTy, 0); + return PT->push_back( + new BitCastInst(V, DestTy, "PC", BB->getTerminator())); + } + + // Generate lots of bitcasts. + if ((Ran->Rand() & 1) && + VTy->getPrimitiveSizeInBits() == DestTy->getPrimitiveSizeInBits()) { + return PT->push_back( + new BitCastInst(V, DestTy, "BC", BB->getTerminator())); + } + + // Both types are integers: + if (VTy->getScalarType()->isIntegerTy() && + DestTy->getScalarType()->isIntegerTy()) { + if (VTy->getScalarType()->getPrimitiveSizeInBits() > + DestTy->getScalarType()->getPrimitiveSizeInBits()) { + return PT->push_back( + new TruncInst(V, DestTy, "Tr", BB->getTerminator())); + } else { + if (Ran->Rand() & 1) + return PT->push_back( + new ZExtInst(V, DestTy, "ZE", BB->getTerminator())); + return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator())); + } + } + + // Fp to int. + if (VTy->getScalarType()->isFloatingPointTy() && + DestTy->getScalarType()->isIntegerTy()) { + if (Ran->Rand() & 1) + return PT->push_back( + new FPToSIInst(V, DestTy, "FC", BB->getTerminator())); + return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator())); + } + + // Int to fp. + if (VTy->getScalarType()->isIntegerTy() && + DestTy->getScalarType()->isFloatingPointTy()) { + if (Ran->Rand() & 1) + return PT->push_back( + new SIToFPInst(V, DestTy, "FC", BB->getTerminator())); + return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator())); + + } + + // Both floats. + if (VTy->getScalarType()->isFloatingPointTy() && + DestTy->getScalarType()->isFloatingPointTy()) { + if (VTy->getScalarType()->getPrimitiveSizeInBits() > + DestTy->getScalarType()->getPrimitiveSizeInBits()) { + return PT->push_back( + new FPTruncInst(V, DestTy, "Tr", BB->getTerminator())); + } else { + return PT->push_back( + new FPExtInst(V, DestTy, "ZE", BB->getTerminator())); + } + } + } + +}; + +struct SelectModifier: public Modifier { + SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R): + Modifier(BB, PT, R) {} + + virtual void Act() { + // Try a bunch of different select configuration until a valid one is found. + Value *Val0 = getRandomVal(); + Value *Val1 = getRandomValue(Val0->getType()); + + Type *CondTy = Type::getInt1Ty(Context); + + // If the value type is a vector, and we allow vector select, then in 50% + // of the cases generate a vector select. + if (Val0->getType()->isVectorTy() && (Ran->Rand() % 1)) { + unsigned NumElem = cast<VectorType>(Val0->getType())->getNumElements(); + CondTy = VectorType::get(CondTy, NumElem); + } + + Value *Cond = getRandomValue(CondTy); + Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator()); + return PT->push_back(V); + } +}; + + +struct CmpModifier: public Modifier { + CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} + virtual void Act() { + + Value *Val0 = getRandomVal(); + Value *Val1 = getRandomValue(Val0->getType()); + + if (Val0->getType()->isPointerTy()) return; + bool fp = Val0->getType()->getScalarType()->isFloatingPointTy(); + + int op; + if (fp) { + op = Ran->Rand() % + (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) + + CmpInst::FIRST_FCMP_PREDICATE; + } else { + op = Ran->Rand() % + (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) + + CmpInst::FIRST_ICMP_PREDICATE; + } + + Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp, + op, Val0, Val1, "Cmp", BB->getTerminator()); + return PT->push_back(V); + } +}; + +void FillFunction(Function *F) { + // Create a legal entry block. + BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F); + ReturnInst::Create(F->getContext(), BB); + + // Create the value table. + Modifier::PieceTable PT; + // Pick an initial seed value + Random R(SeedCL); + + // Consider arguments as legal values. + for (Function::arg_iterator it = F->arg_begin(), e = F->arg_end(); + it != e; ++it) + PT.push_back(it); + + // List of modifiers which add new random instructions. + std::vector<Modifier*> Modifiers; + std::auto_ptr<Modifier> LM(new LoadModifier(BB, &PT, &R)); + std::auto_ptr<Modifier> SM(new StoreModifier(BB, &PT, &R)); + std::auto_ptr<Modifier> EE(new ExtractElementModifier(BB, &PT, &R)); + std::auto_ptr<Modifier> SHM(new ShuffModifier(BB, &PT, &R)); + std::auto_ptr<Modifier> IE(new InsertElementModifier(BB, &PT, &R)); + std::auto_ptr<Modifier> BM(new BinModifier(BB, &PT, &R)); + std::auto_ptr<Modifier> CM(new CastModifier(BB, &PT, &R)); + std::auto_ptr<Modifier> SLM(new SelectModifier(BB, &PT, &R)); + std::auto_ptr<Modifier> PM(new CmpModifier(BB, &PT, &R)); + Modifiers.push_back(LM.get()); + Modifiers.push_back(SM.get()); + Modifiers.push_back(EE.get()); + Modifiers.push_back(SHM.get()); + Modifiers.push_back(IE.get()); + Modifiers.push_back(BM.get()); + Modifiers.push_back(CM.get()); + Modifiers.push_back(SLM.get()); + Modifiers.push_back(PM.get()); + + // Generate the random instructions + AllocaModifier AM(BB, &PT, &R); AM.ActN(5); // Throw in a few allocas + ConstModifier COM(BB, &PT, &R); COM.ActN(40); // Throw in a few constants + + for (unsigned i=0; i< SizeCL / Modifiers.size(); ++i) + for (std::vector<Modifier*>::iterator it = Modifiers.begin(), + e = Modifiers.end(); it != e; ++it) { + (*it)->Act(); + } + + SM->ActN(5); // Throw in a few stores. +} + +void IntroduceControlFlow(Function *F) { + std::set<Instruction*> BoolInst; + for (BasicBlock::iterator it = F->begin()->begin(), + e = F->begin()->end(); it != e; ++it) { + if (it->getType() == IntegerType::getInt1Ty(F->getContext())) + BoolInst.insert(it); + } + + for (std::set<Instruction*>::iterator it = BoolInst.begin(), + e = BoolInst.end(); it != e; ++it) { + Instruction *Instr = *it; + BasicBlock *Curr = Instr->getParent(); + BasicBlock::iterator Loc= Instr; + BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF"); + Instr->moveBefore(Curr->getTerminator()); + if (Curr != &F->getEntryBlock()) { + BranchInst::Create(Curr, Next, Instr, Curr->getTerminator()); + Curr->getTerminator()->eraseFromParent(); + } + } +} + +int main(int argc, char **argv) { + // Init LLVM, call llvm_shutdown() on exit, parse args, etc. + llvm::PrettyStackTraceProgram X(argc, argv); + cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); + llvm_shutdown_obj Y; + + std::auto_ptr<Module> M(new Module("/tmp/autogen.bc", getGlobalContext())); + Function *F = GenEmptyFunction(M.get()); + FillFunction(F); + IntroduceControlFlow(F); + + // Figure out what stream we are supposed to write to... + OwningPtr<tool_output_file> Out; + // Default to standard output. + if (OutputFilename.empty()) + OutputFilename = "-"; + + std::string ErrorInfo; + Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary)); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << '\n'; + return 1; + } + + PassManager Passes; + Passes.add(createVerifierPass()); + Passes.add(createPrintModulePass(&Out->os())); + Passes.run(*M.get()); + Out->keep(); + + return 0; +} diff --git a/tools/llvm-stub/LLVMBuild.txt b/tools/llvm-stub/LLVMBuild.txt new file mode 100644 index 0000000..5c3534c --- /dev/null +++ b/tools/llvm-stub/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-stub/LLVMBuild.txt --------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-stub +parent = Tools +required_libraries = diff --git a/tools/llvm-stub/Makefile b/tools/llvm-stub/Makefile index 7ffe149..077efa2 100644 --- a/tools/llvm-stub/Makefile +++ b/tools/llvm-stub/Makefile @@ -7,7 +7,9 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = llvm-stub +LEVEL := ../.. +TOOLNAME := llvm-stub +LINK_COMPONENTS := object + include $(LEVEL)/Makefile.common diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt index 7e2c5f0..9112976 100644 --- a/tools/lto/CMakeLists.txt +++ b/tools/lto/CMakeLists.txt @@ -1,6 +1,6 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} - ipo scalaropts linker bitreader bitwriter mcdisassembler) + ipo scalaropts linker bitreader bitwriter mcdisassembler vectorize) add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 6c8dbad..77c06a6 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -4,27 +4,26 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file implements the Link Time Optimization library. This library is +// This file implements the Link Time Optimization library. This library is // intended to be used by linker to optimize code at link time. // //===----------------------------------------------------------------------===// -#include "LTOModule.h" #include "LTOCodeGenerator.h" +#include "LTOModule.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Linker.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Triple.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Config/config.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/SubtargetFeature.h" @@ -33,67 +32,55 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SystemUtils.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Host.h" -#include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/system_error.h" -#include "llvm/Config/config.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include <cstdlib> -#include <unistd.h> -#include <fcntl.h> - - +#include "llvm/ADT/StringExtras.h" using namespace llvm; -static cl::opt<bool> DisableInline("disable-inlining", +static cl::opt<bool> DisableInline("disable-inlining", cl::init(false), cl::desc("Do not run the inliner pass")); +static cl::opt<bool> DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), + cl::desc("Do not run the GVN load PRE pass")); -const char* LTOCodeGenerator::getVersionString() -{ +const char* LTOCodeGenerator::getVersionString() { #ifdef LLVM_VERSION_INFO - return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO; + return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO; #else - return PACKAGE_NAME " version " PACKAGE_VERSION; + return PACKAGE_NAME " version " PACKAGE_VERSION; #endif } - -LTOCodeGenerator::LTOCodeGenerator() - : _context(getGlobalContext()), - _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL), - _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false), - _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), - _nativeObjectFile(NULL) -{ - InitializeAllTargets(); - InitializeAllTargetMCs(); - InitializeAllAsmPrinters(); -} - -LTOCodeGenerator::~LTOCodeGenerator() -{ - delete _target; - delete _nativeObjectFile; +LTOCodeGenerator::LTOCodeGenerator() + : _context(getGlobalContext()), + _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL), + _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false), + _runInternalizePass(false), _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), + _nativeObjectFile(NULL) { + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); } +LTOCodeGenerator::~LTOCodeGenerator() { + delete _target; + delete _nativeObjectFile; + for (std::vector<char*>::iterator I = _codegenOptions.begin(), + E = _codegenOptions.end(); I != E; ++I) + free(*I); +} -bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) -{ - - if(mod->getLLVVMModule()->MaterializeAllPermanently(&errMsg)) - return true; - +bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg); const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs(); @@ -102,55 +89,39 @@ bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) return ret; } - - -bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, std::string& errMsg) -{ - switch (debug) { - case LTO_DEBUG_MODEL_NONE: - _emitDwarfDebugInfo = false; - return false; - - case LTO_DEBUG_MODEL_DWARF: - _emitDwarfDebugInfo = true; - return false; - } - errMsg = "unknown debug format"; - return true; -} +bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, + std::string& errMsg) { + switch (debug) { + case LTO_DEBUG_MODEL_NONE: + _emitDwarfDebugInfo = false; + return false; -bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, - std::string& errMsg) -{ - switch (model) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - _codeModel = model; - return false; - } - errMsg = "unknown pic model"; - return true; -} - -void LTOCodeGenerator::setCpu(const char* mCpu) -{ - _mCpu = mCpu; + case LTO_DEBUG_MODEL_DWARF: + _emitDwarfDebugInfo = true; + return false; + } + llvm_unreachable("Unknown debug format!"); } -void LTOCodeGenerator::addMustPreserveSymbol(const char* sym) -{ - _mustPreserveSymbols[sym] = 1; +bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, + std::string& errMsg) { + switch (model) { + case LTO_CODEGEN_PIC_MODEL_STATIC: + case LTO_CODEGEN_PIC_MODEL_DYNAMIC: + case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: + _codeModel = model; + return false; + } + llvm_unreachable("Unknown PIC model!"); } - bool LTOCodeGenerator::writeMergedModules(const char *path, std::string &errMsg) { if (determineTarget(errMsg)) return true; - // mark which symbols can not be internalized + // mark which symbols can not be internalized applyScopeRestrictions(); // create output file @@ -162,7 +133,7 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, errMsg += path; return true; } - + // write bitcode to it WriteBitcodeToFile(_linker.getModule(), Out.os()); Out.os().close(); @@ -173,14 +144,12 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, Out.os().clear_error(); return true; } - + Out.keep(); return false; } - -bool LTOCodeGenerator::compile_to_file(const char** name, 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) ) { @@ -194,12 +163,14 @@ bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) tool_output_file objFile(uniqueObjPath.c_str(), errMsg); if (!errMsg.empty()) return true; + 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(); @@ -211,8 +182,7 @@ bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) return false; } -const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) -{ +const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) { const char *name; if (compile_to_file(&name, errMsg)) return NULL; @@ -238,47 +208,48 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) return _nativeObjectFile->getBufferStart(); } -bool LTOCodeGenerator::determineTarget(std::string& errMsg) -{ - if ( _target == NULL ) { - std::string Triple = _linker.getModule()->getTargetTriple(); - if (Triple.empty()) - Triple = sys::getHostTriple(); - - // create target machine from info for merged modules - const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); - if ( march == NULL ) - return true; - - // The relocation model is actually a static member of TargetMachine - // and needs to be set before the TargetMachine is instantiated. - Reloc::Model RelocModel = Reloc::Default; - switch( _codeModel ) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - RelocModel = Reloc::Static; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - RelocModel = Reloc::PIC_; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - RelocModel = Reloc::DynamicNoPIC; - break; - } - - // construct LTOModule, hand over ownership of module and target - SubtargetFeatures Features; - Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); - std::string FeatureStr = Features.getString(); - _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, - RelocModel); +bool LTOCodeGenerator::determineTarget(std::string& errMsg) { + if ( _target == NULL ) { + std::string Triple = _linker.getModule()->getTargetTriple(); + if (Triple.empty()) + Triple = sys::getDefaultTargetTriple(); + + // create target machine from info for merged modules + const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); + if ( march == NULL ) + return true; + + // The relocation model is actually a static member of TargetMachine and + // needs to be set before the TargetMachine is instantiated. + Reloc::Model RelocModel = Reloc::Default; + switch( _codeModel ) { + case LTO_CODEGEN_PIC_MODEL_STATIC: + RelocModel = Reloc::Static; + break; + case LTO_CODEGEN_PIC_MODEL_DYNAMIC: + RelocModel = Reloc::PIC_; + break; + case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: + RelocModel = Reloc::DynamicNoPIC; + break; } - return false; + + // construct LTOModule, hand over ownership of module and target + SubtargetFeatures Features; + Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); + std::string FeatureStr = Features.getString(); + TargetOptions Options; + _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, Options, + RelocModel); + } + return false; } -void LTOCodeGenerator::applyRestriction(GlobalValue &GV, - std::vector<const char*> &mustPreserveList, - SmallPtrSet<GlobalValue*, 8> &asmUsed, - Mangler &mangler) { +void LTOCodeGenerator:: +applyRestriction(GlobalValue &GV, + std::vector<const char*> &mustPreserveList, + SmallPtrSet<GlobalValue*, 8> &asmUsed, + Mangler &mangler) { SmallString<64> Buffer; mangler.getNameWithPrefix(Buffer, &GV, false); @@ -298,8 +269,8 @@ static void findUsedValues(GlobalVariable *LLVMUsed, if (Inits == 0) return; for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) - if (GlobalValue *GV = - dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) + if (GlobalValue *GV = + dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) UsedValues.insert(GV); } @@ -311,8 +282,8 @@ void LTOCodeGenerator::applyScopeRestrictions() { PassManager passes; passes.add(createVerifierPass()); - // mark which symbols can not be internalized - MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL); + // mark which symbols can not be internalized + MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL); Mangler mangler(Context, *_target->getTargetData()); std::vector<const char*> mustPreserveList; SmallPtrSet<GlobalValue*, 8> asmUsed; @@ -320,7 +291,7 @@ void LTOCodeGenerator::applyScopeRestrictions() { for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) applyRestriction(*f, mustPreserveList, asmUsed, mangler); - for (Module::global_iterator v = mergedModule->global_begin(), + for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) applyRestriction(*v, mustPreserveList, asmUsed, mangler); for (Module::alias_iterator a = mergedModule->alias_begin(), @@ -355,81 +326,82 @@ void LTOCodeGenerator::applyScopeRestrictions() { // apply scope restrictions passes.run(*mergedModule); - + _scopeRestrictionsDone = true; } /// Optimize merged modules using various IPO passes bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, std::string &errMsg) { - if ( this->determineTarget(errMsg) ) - return true; + if ( this->determineTarget(errMsg) ) + return true; - // mark which symbols can not be internalized - this->applyScopeRestrictions(); + Module* mergedModule = _linker.getModule(); - Module* mergedModule = _linker.getModule(); + // if options were requested, set them + if ( !_codegenOptions.empty() ) + cl::ParseCommandLineOptions(_codegenOptions.size(), + const_cast<char **>(&_codegenOptions[0])); - // if options were requested, set them - if ( !_codegenOptions.empty() ) - cl::ParseCommandLineOptions(_codegenOptions.size(), - const_cast<char **>(&_codegenOptions[0])); + // mark which symbols can not be internalized + this->applyScopeRestrictions(); - // Instantiate the pass manager to organize the passes. - PassManager passes; + // Instantiate the pass manager to organize the passes. + PassManager passes; - // Start off with a verification pass. - passes.add(createVerifierPass()); + // Start off with a verification pass. + passes.add(createVerifierPass()); - // Add an appropriate TargetData instance for this module... - passes.add(new TargetData(*_target->getTargetData())); - - PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/ false, - !DisableInline); + // Add an appropriate TargetData instance for this module... + passes.add(new TargetData(*_target->getTargetData())); - // Make sure everything is still good. - passes.add(createVerifierPass()); + PassManagerBuilder().populateLTOPassManager(passes, + _runInternalizePass, + !DisableInline, + DisableGVNLoadPRE); - FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule); + // Make sure everything is still good. + passes.add(createVerifierPass()); - codeGenPasses->add(new TargetData(*_target->getTargetData())); + FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule); - formatted_raw_ostream Out(out); + codeGenPasses->add(new TargetData(*_target->getTargetData())); - if (_target->addPassesToEmitFile(*codeGenPasses, Out, - TargetMachine::CGFT_ObjectFile, - CodeGenOpt::Aggressive)) { - errMsg = "target file type not supported"; - return true; - } + formatted_raw_ostream Out(out); - // Run our queue of passes all at once now, efficiently. - passes.run(*mergedModule); + if (_target->addPassesToEmitFile(*codeGenPasses, Out, + TargetMachine::CGFT_ObjectFile, + CodeGenOpt::Aggressive)) { + errMsg = "target file type not supported"; + return true; + } + + // Run our queue of passes all at once now, efficiently. + passes.run(*mergedModule); - // Run the code generator, and write assembly file - codeGenPasses->doInitialization(); + // Run the code generator, and write assembly file + codeGenPasses->doInitialization(); - for (Module::iterator - it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it) - if (!it->isDeclaration()) - codeGenPasses->run(*it); + for (Module::iterator + it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it) + if (!it->isDeclaration()) + codeGenPasses->run(*it); - codeGenPasses->doFinalization(); - delete codeGenPasses; + codeGenPasses->doFinalization(); + delete codeGenPasses; - return false; // success + return false; // success } - -/// Optimize merged modules using various IPO passes -void LTOCodeGenerator::setCodeGenDebugOptions(const char* options) -{ - for (std::pair<StringRef, StringRef> o = getToken(options); - !o.first.empty(); o = getToken(o.second)) { - // ParseCommandLineOptions() expects argv[0] to be program name. - // Lazily add that. - if ( _codegenOptions.empty() ) - _codegenOptions.push_back("libLTO"); - _codegenOptions.push_back(strdup(o.first.str().c_str())); - } +/// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging +/// LTO problems. +void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) { + for (std::pair<StringRef, StringRef> o = getToken(options); + !o.first.empty(); o = getToken(o.second)) { + // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add + // that. + if ( _codegenOptions.empty() ) + _codegenOptions.push_back(strdup("libLTO")); + _codegenOptions.push_back(strdup(o.first.str().c_str())); + } } diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h index f8fd357..bac3e6e 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -4,71 +4,82 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file declares the LTOCodeGenerator class. +// This file declares the LTOCodeGenerator class. // //===----------------------------------------------------------------------===// - #ifndef LTO_CODE_GENERATOR_H #define LTO_CODE_GENERATOR_H #include "llvm/Linker.h" -#include "llvm/LLVMContext.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" - +#include "llvm-c/lto.h" #include <string> +namespace llvm { + class LLVMContext; + class GlobalValue; + class Mangler; + class MemoryBuffer; + class TargetMachine; + class raw_ostream; +} -// -// C++ class which implements the opaque lto_code_gen_t -// - +//===----------------------------------------------------------------------===// +/// LTOCodeGenerator - C++ class which implements the opaque lto_code_gen_t +/// type. +/// struct LTOCodeGenerator { - static const char* getVersionString(); - - LTOCodeGenerator(); - ~LTOCodeGenerator(); - - bool addModule(struct LTOModule*, std::string& errMsg); - bool setDebugInfo(lto_debug_model, std::string& errMsg); - bool setCodePICModel(lto_codegen_model, std::string& errMsg); - void setCpu(const char *cpu); - 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); + static const char *getVersionString(); + + LTOCodeGenerator(); + ~LTOCodeGenerator(); + + bool addModule(struct LTOModule*, std::string &errMsg); + bool setDebugInfo(lto_debug_model, std::string &errMsg); + bool setCodePICModel(lto_codegen_model, std::string &errMsg); + + void setCpu(const char* mCpu) { _mCpu = mCpu; } + + void addMustPreserveSymbol(const char* sym) { + _mustPreserveSymbols[sym] = 1; + } + + 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); + + void enableInternalizePass() { _runInternalizePass = true; } + private: - bool generateObjectFile(llvm::raw_ostream& out, - std::string& errMsg); - void applyScopeRestrictions(); - void applyRestriction(llvm::GlobalValue &GV, - std::vector<const char*> &mustPreserveList, + bool generateObjectFile(llvm::raw_ostream &out, std::string &errMsg); + void applyScopeRestrictions(); + void applyRestriction(llvm::GlobalValue &GV, + std::vector<const char*> &mustPreserveList, llvm::SmallPtrSet<llvm::GlobalValue*, 8> &asmUsed, - llvm::Mangler &mangler); - bool determineTarget(std::string& errMsg); - - typedef llvm::StringMap<uint8_t> StringSet; + llvm::Mangler &mangler); + bool determineTarget(std::string &errMsg); - llvm::LLVMContext& _context; - llvm::Linker _linker; - llvm::TargetMachine* _target; - bool _emitDwarfDebugInfo; - bool _scopeRestrictionsDone; - lto_codegen_model _codeModel; - StringSet _mustPreserveSymbols; - StringSet _asmUndefinedRefs; - llvm::MemoryBuffer* _nativeObjectFile; - std::vector<const char*> _codegenOptions; - std::string _mCpu; - std::string _nativeObjectPath; + typedef llvm::StringMap<uint8_t> StringSet; + + llvm::LLVMContext& _context; + llvm::Linker _linker; + llvm::TargetMachine* _target; + bool _emitDwarfDebugInfo; + bool _scopeRestrictionsDone; + bool _runInternalizePass; + lto_codegen_model _codeModel; + StringSet _mustPreserveSymbols; + StringSet _asmUndefinedRefs; + llvm::MemoryBuffer* _nativeObjectFile; + std::vector<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 4ba8985..1dbd64b 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -13,39 +13,37 @@ //===----------------------------------------------------------------------===// #include "LTOModule.h" - #include "llvm/Constants.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/Triple.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Support/SystemUtils.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Process.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/system_error.h" -#include "llvm/Target/Mangler.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/Target/TargetMachine.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/Target/TargetRegisterInfo.h" - +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/system_error.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" using namespace llvm; +LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t) + : _module(m), _target(t), + _context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL), + _mangler(_context, *_target->getTargetData()) {} + +/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM +/// bitcode. bool LTOModule::isBitcodeFile(const void *mem, size_t length) { return llvm::sys::IdentifyFileType((char*)mem, length) == llvm::sys::Bitcode_FileType; @@ -55,6 +53,8 @@ bool LTOModule::isBitcodeFile(const char *path) { return llvm::sys::Path(path).isBitcodeFile(); } +/// isBitcodeFileForTarget - Returns 'true' if the file (or memory contents) is +/// LLVM bitcode for the specified triple. bool LTOModule::isBitcodeFileForTarget(const void *mem, size_t length, const char *triplePrefix) { MemoryBuffer *buffer = makeBuffer(mem, length); @@ -63,7 +63,6 @@ bool LTOModule::isBitcodeFileForTarget(const void *mem, size_t length, return isTargetMatch(buffer, triplePrefix); } - bool LTOModule::isBitcodeFileForTarget(const char *path, const char *triplePrefix) { OwningPtr<MemoryBuffer> buffer; @@ -72,22 +71,17 @@ bool LTOModule::isBitcodeFileForTarget(const char *path, return isTargetMatch(buffer.take(), triplePrefix); } -// Takes ownership of buffer. +/// isTargetMatch - Returns 'true' if the memory buffer is for the specified +/// target triple. bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) { std::string Triple = getBitcodeTargetTriple(buffer, getGlobalContext()); delete buffer; - return (strncmp(Triple.c_str(), triplePrefix, - strlen(triplePrefix)) == 0); + return strncmp(Triple.c_str(), triplePrefix, strlen(triplePrefix)) == 0; } - -LTOModule::LTOModule(Module *m, TargetMachine *t) - : _module(m), _target(t) -{ -} - -LTOModule *LTOModule::makeLTOModule(const char *path, - std::string &errMsg) { +/// makeLTOModule - Create an LTOModule. N.B. These methods take ownership of +/// the buffer. +LTOModule *LTOModule::makeLTOModule(const char *path, std::string &errMsg) { OwningPtr<MemoryBuffer> buffer; if (error_code ec = MemoryBuffer::getFile(path, buffer)) { errMsg = ec.message(); @@ -97,8 +91,7 @@ LTOModule *LTOModule::makeLTOModule(const char *path, } LTOModule *LTOModule::makeLTOModule(int fd, const char *path, - size_t size, - std::string &errMsg) { + size_t size, std::string &errMsg) { return makeLTOModule(fd, path, size, size, 0, errMsg); } @@ -116,13 +109,6 @@ LTOModule *LTOModule::makeLTOModule(int fd, const char *path, return makeLTOModule(buffer.take(), errMsg); } -/// makeBuffer - Create a MemoryBuffer from a memory range. -MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { - const char *startPtr = (char*)mem; - return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); -} - - LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length, std::string &errMsg) { OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length)); @@ -151,7 +137,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, std::string Triple = m->getTargetTriple(); if (Triple.empty()) - Triple = sys::getHostTriple(); + Triple = sys::getDefaultTargetTriple(); // find machine architecture for this module const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); @@ -163,39 +149,33 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); std::string FeatureStr = Features.getString(); std::string CPU; - TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr); + TargetOptions Options; + TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr, + Options); LTOModule *Ret = new LTOModule(m.take(), target); - bool Err = Ret->ParseSymbols(errMsg); - if (Err) { + if (Ret->parseSymbols(errMsg)) { delete Ret; return NULL; } - return Ret; -} - -const char *LTOModule::getTargetTriple() { - return _module->getTargetTriple().c_str(); -} - -void LTOModule::setTargetTriple(const char *triple) { - _module->setTargetTriple(triple); + return Ret; } -void LTOModule::addDefinedFunctionSymbol(Function *f, Mangler &mangler) { - // add to list of defined symbols - addDefinedSymbol(f, mangler, true); +/// makeBuffer - Create a MemoryBuffer from a memory range. +MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { + const char *startPtr = (char*)mem; + return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); } -// Get string that data pointer points to. +/// objcClassNameFromExpression - Get string that the data pointer points to. bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) { if (ConstantExpr *ce = dyn_cast<ConstantExpr>(c)) { Constant *op = ce->getOperand(0); if (GlobalVariable *gvn = dyn_cast<GlobalVariable>(op)) { Constant *cn = gvn->getInitializer(); - if (ConstantArray *ca = dyn_cast<ConstantArray>(cn)) { + if (ConstantDataArray *ca = dyn_cast<ConstantDataArray>(cn)) { if (ca->isCString()) { - name = ".objc_class_name_" + ca->getAsCString(); + name = ".objc_class_name_" + ca->getAsCString().str(); return true; } } @@ -204,85 +184,92 @@ bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) { return false; } -// Parse i386/ppc ObjC class data structure. +/// addObjCClass - Parse i386/ppc ObjC class data structure. void LTOModule::addObjCClass(GlobalVariable *clgv) { - if (ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer())) { - // second slot in __OBJC,__class is pointer to superclass name - std::string superclassName; - if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { - NameAndAttributes info; - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(superclassName); - if (!entry.getValue().name) { - const char *symbolName = entry.getKey().data(); - info.name = symbolName; - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - entry.setValue(info); - } - } - // third slot in __OBJC,__class is pointer to class name - std::string className; - if (objcClassNameFromExpression(c->getOperand(2), className)) { - StringSet::value_type &entry = - _defines.GetOrCreateValue(className); - entry.setValue(1); - NameAndAttributes info; - info.name = entry.getKey().data(); - info.attributes = (lto_symbol_attributes) - (LTO_SYMBOL_PERMISSIONS_DATA | - LTO_SYMBOL_DEFINITION_REGULAR | - LTO_SYMBOL_SCOPE_DEFAULT); - _symbols.push_back(info); - } - } -} - - -// Parse i386/ppc ObjC category data structure. -void LTOModule::addObjCCategory(GlobalVariable *clgv) { - if (ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer())) { - // second slot in __OBJC,__category is pointer to target class name - std::string targetclassName; - if (objcClassNameFromExpression(c->getOperand(1), targetclassName)) { - NameAndAttributes info; - - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); - - if (entry.getValue().name) - return; + ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); + if (!c) return; + // second slot in __OBJC,__class is pointer to superclass name + std::string superclassName; + if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { + NameAndAttributes info; + StringMap<NameAndAttributes>::value_type &entry = + _undefines.GetOrCreateValue(superclassName); + if (!entry.getValue().name) { const char *symbolName = entry.getKey().data(); info.name = symbolName; info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; entry.setValue(info); } } + + // third slot in __OBJC,__class is pointer to class name + std::string className; + if (objcClassNameFromExpression(c->getOperand(2), className)) { + StringSet::value_type &entry = _defines.GetOrCreateValue(className); + entry.setValue(1); + + NameAndAttributes info; + info.name = entry.getKey().data(); + info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | + LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT; + info.isFunction = false; + info.symbol = clgv; + _symbols.push_back(info); + } } +/// addObjCCategory - Parse i386/ppc ObjC category data structure. +void LTOModule::addObjCCategory(GlobalVariable *clgv) { + ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); + if (!c) return; -// Parse i386/ppc ObjC class list data structure. -void LTOModule::addObjCClassRef(GlobalVariable *clgv) { + // second slot in __OBJC,__category is pointer to target class name std::string targetclassName; - if (objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) { - NameAndAttributes info; + if (!objcClassNameFromExpression(c->getOperand(1), targetclassName)) + return; - StringMap<NameAndAttributes>::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); - if (entry.getValue().name) - return; + NameAndAttributes info; + StringMap<NameAndAttributes>::value_type &entry = + _undefines.GetOrCreateValue(targetclassName); - const char *symbolName = entry.getKey().data(); - info.name = symbolName; - info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; - entry.setValue(info); - } + if (entry.getValue().name) + return; + + const char *symbolName = entry.getKey().data(); + info.name = symbolName; + info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; + entry.setValue(info); } +/// addObjCClassRef - Parse i386/ppc ObjC class list data structure. +void LTOModule::addObjCClassRef(GlobalVariable *clgv) { + std::string targetclassName; + if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) + return; + + NameAndAttributes info; + StringMap<NameAndAttributes>::value_type &entry = + _undefines.GetOrCreateValue(targetclassName); + if (entry.getValue().name) + return; + + const char *symbolName = entry.getKey().data(); + info.name = symbolName; + info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; + entry.setValue(info); +} -void LTOModule::addDefinedDataSymbol(GlobalValue *v, Mangler &mangler) { +/// addDefinedDataSymbol - Add a data symbol as defined to the list. +void LTOModule::addDefinedDataSymbol(GlobalValue *v) { // Add to list of defined symbols. - addDefinedSymbol(v, mangler, false); + addDefinedSymbol(v, false); // Special case i386/ppc ObjC data structures in magic sections: // The issue is that the old ObjC object format did some strange @@ -327,25 +314,30 @@ void LTOModule::addDefinedDataSymbol(GlobalValue *v, Mangler &mangler) { } } +/// addDefinedFunctionSymbol - Add a function symbol as defined to the list. +void LTOModule::addDefinedFunctionSymbol(Function *f) { + // add to list of defined symbols + addDefinedSymbol(f, true); +} -void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, - bool isFunction) { +/// addDefinedSymbol - Add a defined symbol to the list. +void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { // ignore all llvm.* symbols if (def->getName().startswith("llvm.")) return; // string is owned by _defines SmallString<64> Buffer; - mangler.getNameWithPrefix(Buffer, def, false); + _mangler.getNameWithPrefix(Buffer, def, false); // set alignment part log2() can have rounding errors uint32_t align = def->getAlignment(); uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0; // set permissions part - if (isFunction) + if (isFunction) { attr |= LTO_SYMBOL_PERMISSIONS_CODE; - else { + } else { GlobalVariable *gv = dyn_cast<GlobalVariable>(def); if (gv && gv->isConstant()) attr |= LTO_SYMBOL_PERMISSIONS_RODATA; @@ -377,18 +369,24 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, else attr |= LTO_SYMBOL_SCOPE_INTERNAL; - // add to table of symbols - NameAndAttributes info; StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer); entry.setValue(1); + // fill information structure + NameAndAttributes info; StringRef Name = entry.getKey(); info.name = Name.data(); assert(info.name[Name.size()] == '\0'); - info.attributes = (lto_symbol_attributes)attr; + info.attributes = attr; + info.isFunction = isFunction; + info.symbol = def; + + // add to table of symbols _symbols.push_back(info); } +/// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the +/// defined list. void LTOModule::addAsmGlobalSymbol(const char *name, lto_symbol_attributes scope) { StringSet::value_type &entry = _defines.GetOrCreateValue(name); @@ -398,15 +396,41 @@ void LTOModule::addAsmGlobalSymbol(const char *name, return; entry.setValue(1); - const char *symbolName = entry.getKey().data(); - uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR; - attr |= scope; - NameAndAttributes info; - info.name = symbolName; - info.attributes = (lto_symbol_attributes)attr; - _symbols.push_back(info); + + NameAndAttributes &info = _undefines[entry.getKey().data()]; + + if (info.symbol == 0) { + // FIXME: This is trying to take care of module ASM like this: + // + // module asm ".zerofill __FOO, __foo, _bar_baz_qux, 0" + // + // but is gross and its mother dresses it funny. Have the ASM parser give us + // more details for this type of situation so that we're not guessing so + // much. + + // fill information structure + info.name = name; + info.attributes = + LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope; + info.isFunction = false; + info.symbol = 0; + + // add to table of symbols + _symbols.push_back(info); + return; + } + + if (info.isFunction) + addDefinedFunctionSymbol(cast<Function>(info.symbol)); + else + addDefinedDataSymbol(info.symbol); + + _symbols.back().attributes &= ~LTO_SYMBOL_SCOPE_MASK; + _symbols.back().attributes |= scope; } +/// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to the +/// undefined list. void LTOModule::addAsmGlobalSymbolUndef(const char *name) { StringMap<NameAndAttributes>::value_type &entry = _undefines.GetOrCreateValue(name); @@ -421,13 +445,16 @@ void LTOModule::addAsmGlobalSymbolUndef(const char *name) { attr |= LTO_SYMBOL_SCOPE_DEFAULT; NameAndAttributes info; info.name = entry.getKey().data(); - info.attributes = (lto_symbol_attributes)attr; + info.attributes = attr; + info.isFunction = false; + info.symbol = 0; entry.setValue(info); } -void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, - Mangler &mangler) { +/// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet to a +/// list to be resolved later. +void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, bool isFunc) { // ignore all llvm.* symbols if (decl->getName().startswith("llvm.")) return; @@ -437,7 +464,7 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, return; SmallString<64> name; - mangler.getNameWithPrefix(name, decl, false); + _mangler.getNameWithPrefix(name, decl, false); StringMap<NameAndAttributes>::value_type &entry = _undefines.GetOrCreateValue(name); @@ -449,19 +476,22 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, NameAndAttributes info; info.name = entry.getKey().data(); + if (decl->hasExternalWeakLinkage()) info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF; else info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = isFunc; + info.symbol = decl; + entry.setValue(info); } - namespace { class RecordStreamer : public MCStreamer { public: - enum State { NeverSeen, Global, Defined, DefinedGlobal, Used}; + enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; private: StringMap<State> Symbols; @@ -550,14 +580,16 @@ namespace { RecordStreamer(MCContext &Context) : MCStreamer(Context) {} - virtual void ChangeSection(const MCSection *Section) {} - virtual void InitSections() {} + virtual void EmitInstruction(const MCInst &Inst) { + // Scan for values. + for (unsigned i = Inst.getNumOperands(); i--; ) + if (Inst.getOperand(i).isExpr()) + AddValueSymbols(Inst.getOperand(i).getExpr()); + } virtual void EmitLabel(MCSymbol *Symbol) { Symbol->setSection(*getCurrentSection()); markDefined(*Symbol); } - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} - virtual void EmitThumbFunc(MCSymbol *Func) {} virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { // FIXME: should we handle aliases? markDefined(*Symbol); @@ -566,20 +598,26 @@ namespace { if (Attribute == MCSA_Global) markGlobal(*Symbol); } - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {} - virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, unsigned Size , unsigned ByteAlignment) { markDefined(*Symbol); } - virtual void EmitCOFFSymbolType(int Type) {} - virtual void EndCOFFSymbolDef() {} virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { markDefined(*Symbol); } + + // Noop calls. + virtual void ChangeSection(const MCSection *Section) {} + virtual void InitSections() {} + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} + virtual void EmitThumbFunc(MCSymbol *Func) {} + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {} + virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} + virtual void EmitCOFFSymbolType(int Type) {} + virtual void EndCOFFSymbolDef() {} virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) {} @@ -595,35 +633,30 @@ namespace { unsigned MaxBytesToEmit) {} virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit) {} - virtual void EmitValueToOffset(const MCExpr *Offset, - unsigned char Value ) {} + virtual bool EmitValueToOffset(const MCExpr *Offset, + unsigned char Value ) { return false; } virtual void EmitFileDirective(StringRef Filename) {} virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, unsigned PointerSize) {} - - virtual void EmitInstruction(const MCInst &Inst) { - // Scan for values. - for (unsigned i = Inst.getNumOperands(); i--; ) - if (Inst.getOperand(i).isExpr()) - AddValueSymbols(Inst.getOperand(i).getExpr()); - } - virtual void Finish() {} + virtual void FinishImpl() {} }; -} +} // end anonymous namespace -bool LTOModule::addAsmGlobalSymbols(MCContext &Context, std::string &errMsg) { +/// addAsmGlobalSymbols - Add global symbols from module-level ASM to the +/// defined or undefined lists. +bool LTOModule::addAsmGlobalSymbols(std::string &errMsg) { const std::string &inlineAsm = _module->getModuleInlineAsm(); if (inlineAsm.empty()) return false; - OwningPtr<RecordStreamer> Streamer(new RecordStreamer(Context)); + OwningPtr<RecordStreamer> Streamer(new RecordStreamer(_context)); MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm); SourceMgr SrcMgr; SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, - Context, *Streamer, + _context, *Streamer, *_target->getMCAsmInfo())); OwningPtr<MCSubtargetInfo> STI(_target->getTarget(). createMCSubtargetInfo(_target->getTargetTriple(), @@ -657,6 +690,7 @@ bool LTOModule::addAsmGlobalSymbols(MCContext &Context, std::string &errMsg) { return false; } +/// isDeclaration - Return 'true' if the global value is a declaration. static bool isDeclaration(const GlobalValue &V) { if (V.hasAvailableExternallyLinkage()) return true; @@ -665,74 +699,49 @@ static bool isDeclaration(const GlobalValue &V) { return V.isDeclaration(); } -static bool isAliasToDeclaration(const GlobalAlias &V) { - return isDeclaration(*V.getAliasedGlobal()); -} - -bool LTOModule::ParseSymbols(std::string &errMsg) { - // Use mangler to add GlobalPrefix to names to match linker names. - MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL); - Mangler mangler(Context, *_target->getTargetData()); - +/// parseSymbols - Parse the symbols from the module and model-level ASM and add +/// them to either the defined or undefined lists. +bool LTOModule::parseSymbols(std::string &errMsg) { // add functions - for (Module::iterator f = _module->begin(); f != _module->end(); ++f) { + for (Module::iterator f = _module->begin(), e = _module->end(); f != e; ++f) { if (isDeclaration(*f)) - addPotentialUndefinedSymbol(f, mangler); + addPotentialUndefinedSymbol(f, true); else - addDefinedFunctionSymbol(f, mangler); + addDefinedFunctionSymbol(f); } // add data for (Module::global_iterator v = _module->global_begin(), e = _module->global_end(); v != e; ++v) { if (isDeclaration(*v)) - addPotentialUndefinedSymbol(v, mangler); + addPotentialUndefinedSymbol(v, false); else - addDefinedDataSymbol(v, mangler); + addDefinedDataSymbol(v); } // add asm globals - if (addAsmGlobalSymbols(Context, errMsg)) + if (addAsmGlobalSymbols(errMsg)) return true; // add aliases - for (Module::alias_iterator i = _module->alias_begin(), - e = _module->alias_end(); i != e; ++i) { - if (isAliasToDeclaration(*i)) - addPotentialUndefinedSymbol(i, mangler); + for (Module::alias_iterator a = _module->alias_begin(), + e = _module->alias_end(); a != e; ++a) { + if (isDeclaration(*a->getAliasedGlobal())) + // Is an alias to a declaration. + addPotentialUndefinedSymbol(a, false); else - addDefinedDataSymbol(i, mangler); + addDefinedDataSymbol(a); } // make symbols for all undefines - for (StringMap<NameAndAttributes>::iterator it=_undefines.begin(); - it != _undefines.end(); ++it) { - // if this symbol also has a definition, then don't make an undefine - // because it is a tentative definition - if (_defines.count(it->getKey()) == 0) { - NameAndAttributes info = it->getValue(); - _symbols.push_back(info); - } + for (StringMap<NameAndAttributes>::iterator u =_undefines.begin(), + e = _undefines.end(); u != e; ++u) { + // If this symbol also has a definition, then don't make an undefine because + // it is a tentative definition. + if (_defines.count(u->getKey())) continue; + NameAndAttributes info = u->getValue(); + _symbols.push_back(info); } - return false; -} - -uint32_t LTOModule::getSymbolCount() { - return _symbols.size(); -} - - -lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index) { - if (index < _symbols.size()) - return _symbols[index].attributes; - else - return lto_symbol_attributes(0); -} - -const char *LTOModule::getSymbolName(uint32_t index) { - if (index < _symbols.size()) - return _symbols[index].name; - else - return NULL; + return false; } diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h index ca08aea..cafb927 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -4,10 +4,10 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file declares the LTOModule class. +// This file declares the LTOModule class. // //===----------------------------------------------------------------------===// @@ -15,110 +15,172 @@ #define LTO_MODULE_H #include "llvm/Module.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" - #include "llvm-c/lto.h" - #include <vector> #include <string> - -// forward references to llvm classes +// Forward references to llvm classes. namespace llvm { - class Mangler; - class MemoryBuffer; - class GlobalValue; - class Value; - class Function; + class Function; + class GlobalValue; + class MemoryBuffer; + class Value; } - -// -// C++ class which implements the opaque lto_module_t -// +//===----------------------------------------------------------------------===// +/// LTOModule - C++ class which implements the opaque lto_module_t type. +/// struct LTOModule { - - static bool isBitcodeFile(const void* mem, size_t length); - static bool isBitcodeFile(const char* path); - - static bool isBitcodeFileForTarget(const void* mem, - size_t length, const char* triplePrefix); - - static bool isBitcodeFileForTarget(const char* path, - const char* triplePrefix); - - static LTOModule* makeLTOModule(const char* path, - std::string& errMsg); - static LTOModule* makeLTOModule(int fd, const char *path, - 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); - - const char* getTargetTriple(); - void setTargetTriple(const char*); - uint32_t getSymbolCount(); - lto_symbol_attributes getSymbolAttributes(uint32_t index); - const char* getSymbolName(uint32_t index); - - llvm::Module * getLLVVMModule() { return _module.get(); } - const std::vector<const char*> &getAsmUndefinedRefs() { - return _asm_undefines; - } +private: + typedef llvm::StringMap<uint8_t> StringSet; + + struct NameAndAttributes { + const char *name; + uint32_t attributes; + bool isFunction; + llvm::GlobalValue *symbol; + }; + + llvm::OwningPtr<llvm::Module> _module; + llvm::OwningPtr<llvm::TargetMachine> _target; + std::vector<NameAndAttributes> _symbols; + + // _defines and _undefines only needed to disambiguate tentative definitions + StringSet _defines; + llvm::StringMap<NameAndAttributes> _undefines; + std::vector<const char*> _asm_undefines; + llvm::MCContext _context; + + // Use mangler to add GlobalPrefix to names to match linker names. + llvm::Mangler _mangler; + + LTOModule(llvm::Module *m, llvm::TargetMachine *t); +public: + /// isBitcodeFile - Returns 'true' if the file or memory contents is LLVM + /// bitcode. + static bool isBitcodeFile(const void *mem, size_t length); + static bool isBitcodeFile(const char *path); + + /// isBitcodeFileForTarget - Returns 'true' if the file or memory contents + /// is LLVM bitcode for the specified triple. + static bool isBitcodeFileForTarget(const void *mem, + size_t length, + const char *triplePrefix); + static bool isBitcodeFileForTarget(const char *path, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule. N.B. These methods take ownership + /// of the buffer. + static LTOModule *makeLTOModule(const char* path, + std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + 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); + + /// getTargetTriple - Return the Module's target triple. + const char *getTargetTriple() { + return _module->getTargetTriple().c_str(); + } + + /// setTargetTriple - Set the Module's target triple. + void setTargetTriple(const char *triple) { + _module->setTargetTriple(triple); + } + + /// getSymbolCount - Get the number of symbols + uint32_t getSymbolCount() { + return _symbols.size(); + } + + /// getSymbolAttributes - Get the attributes for a symbol at the specified + /// index. + lto_symbol_attributes getSymbolAttributes(uint32_t index) { + if (index < _symbols.size()) + return lto_symbol_attributes(_symbols[index].attributes); + return lto_symbol_attributes(0); + } + + /// getSymbolName - Get the name of the symbol at the specified index. + const char *getSymbolName(uint32_t index) { + if (index < _symbols.size()) + return _symbols[index].name; + return NULL; + } + + /// getLLVVMModule - Return the Module. + llvm::Module *getLLVVMModule() { return _module.get(); } + + /// getAsmUndefinedRefs - + const std::vector<const char*> &getAsmUndefinedRefs() { + return _asm_undefines; + } private: - LTOModule(llvm::Module* m, llvm::TargetMachine* t); - - bool ParseSymbols(std::string &errMsg); - void addDefinedSymbol(llvm::GlobalValue* def, - llvm::Mangler& mangler, - bool isFunction); - void addPotentialUndefinedSymbol(llvm::GlobalValue* decl, - llvm::Mangler &mangler); - void addDefinedFunctionSymbol(llvm::Function* f, - llvm::Mangler &mangler); - void addDefinedDataSymbol(llvm::GlobalValue* v, - llvm::Mangler &mangler); - bool addAsmGlobalSymbols(llvm::MCContext &Context, - std::string &errMsg); - void addAsmGlobalSymbol(const char *, - lto_symbol_attributes scope); - void addAsmGlobalSymbolUndef(const char *); - void addObjCClass(llvm::GlobalVariable* clgv); - void addObjCCategory(llvm::GlobalVariable* clgv); - void addObjCClassRef(llvm::GlobalVariable* clgv); - bool objcClassNameFromExpression(llvm::Constant* c, - std::string& name); - - static bool isTargetMatch(llvm::MemoryBuffer* memBuffer, - const char* triplePrefix); - - static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer, - std::string& errMsg); - static llvm::MemoryBuffer* makeBuffer(const void* mem, size_t length); - - typedef llvm::StringMap<uint8_t> StringSet; - - struct NameAndAttributes { - const char* name; - lto_symbol_attributes attributes; - }; - - llvm::OwningPtr<llvm::Module> _module; - llvm::OwningPtr<llvm::TargetMachine> _target; - std::vector<NameAndAttributes> _symbols; - // _defines and _undefines only needed to disambiguate tentative definitions - StringSet _defines; - llvm::StringMap<NameAndAttributes> _undefines; - std::vector<const char*> _asm_undefines; + /// parseSymbols - Parse the symbols from the module and model-level ASM and + /// add them to either the defined or undefined lists. + bool parseSymbols(std::string &errMsg); + + /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet + /// to a list to be resolved later. + void addPotentialUndefinedSymbol(llvm::GlobalValue *dcl, bool isFunc); + + /// addDefinedSymbol - Add a defined symbol to the list. + void addDefinedSymbol(llvm::GlobalValue *def, bool isFunction); + + /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. + void addDefinedFunctionSymbol(llvm::Function *f); + + /// addDefinedDataSymbol - Add a data symbol as defined to the list. + void addDefinedDataSymbol(llvm::GlobalValue *v); + + /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the + /// defined or undefined lists. + bool addAsmGlobalSymbols(std::string &errMsg); + + /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the + /// defined list. + void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope); + + /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to + /// the undefined list. + void addAsmGlobalSymbolUndef(const char *); + + /// addObjCClass - Parse i386/ppc ObjC class data structure. + void addObjCClass(llvm::GlobalVariable *clgv); + + /// addObjCCategory - Parse i386/ppc ObjC category data structure. + void addObjCCategory(llvm::GlobalVariable *clgv); + + /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. + void addObjCClassRef(llvm::GlobalVariable *clgv); + + /// objcClassNameFromExpression - Get string that the data pointer points + /// to. + bool objcClassNameFromExpression(llvm::Constant* c, std::string &name); + + /// isTargetMatch - Returns 'true' if the memory buffer is for the specified + /// target triple. + static bool isTargetMatch(llvm::MemoryBuffer *memBuffer, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule (private version). N.B. This + /// method takes ownership of the buffer. + static LTOModule *makeLTOModule(llvm::MemoryBuffer *buffer, + std::string &errMsg); + + /// makeBuffer - Create a MemoryBuffer from a memory range. + static llvm::MemoryBuffer *makeBuffer(const void *mem, size_t length); }; #endif // LTO_MODULE_H - diff --git a/tools/lto/Makefile b/tools/lto/Makefile index 46925e7..153fa03 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -7,22 +7,15 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -LIBRARYNAME = LTO +LEVEL := ../.. +LIBRARYNAME := LTO +LINK_COMPONENTS := all-targets ipo scalaropts linker bitreader bitwriter \ + mcdisassembler vectorize +LINK_LIBS_IN_SHARED := 1 +SHARED_LIBRARY := 1 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 -include $(LEVEL)/Makefile.config - -LINK_LIBS_IN_SHARED = 1 -SHARED_LIBRARY = 1 - -LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader \ - bitwriter mcdisassembler - include $(LEVEL)/Makefile.common ifdef LLVM_VERSION_INFO diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index dd658d1..addf787 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -4,10 +4,10 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file implements the Link Time Optimization library. This library is +// This file implements the Link Time Optimization library. This library is // intended to be used by linker to optimize code at link time. // //===----------------------------------------------------------------------===// @@ -19,292 +19,202 @@ #include "LTOCodeGenerator.h" -// holds most recent error string -// *** not thread safe *** +// Holds most recent error string. +// *** Not thread safe *** static std::string sLastErrorString; - - -// -// returns a printable string -// -extern const char* lto_get_version() -{ - return LTOCodeGenerator::getVersionString(); +/// lto_get_version - Returns a printable string. +extern const char* lto_get_version() { + return LTOCodeGenerator::getVersionString(); } -// -// returns the last error string or NULL if last operation was successful -// -const char* lto_get_error_message() -{ - return sLastErrorString.c_str(); +/// lto_get_error_message - Returns the last error string or NULL if last +/// operation was successful. +const char* lto_get_error_message() { + return sLastErrorString.c_str(); } - - -// -// validates if a file is a loadable object file -// -bool lto_module_is_object_file(const char* path) -{ - return LTOModule::isBitcodeFile(path); +/// lto_module_is_object_file - Validates if a file is a loadable object file. +bool lto_module_is_object_file(const char* path) { + return LTOModule::isBitcodeFile(path); } - -// -// validates if a file is a loadable object file compilable for requested target -// -bool lto_module_is_object_file_for_target(const char* path, - const char* target_triplet_prefix) -{ - return LTOModule::isBitcodeFileForTarget(path, target_triplet_prefix); +/// lto_module_is_object_file_for_target - Validates if a file is a loadable +/// object file compilable for requested target. +bool lto_module_is_object_file_for_target(const char* path, + const char* target_triplet_prefix) { + return LTOModule::isBitcodeFileForTarget(path, target_triplet_prefix); } - -// -// validates if a buffer is a loadable object file -// -bool lto_module_is_object_file_in_memory(const void* mem, size_t length) -{ - return LTOModule::isBitcodeFile(mem, length); +/// lto_module_is_object_file_in_memory - Validates if a buffer is a loadable +/// object file. +bool lto_module_is_object_file_in_memory(const void* mem, size_t length) { + return LTOModule::isBitcodeFile(mem, length); } - -// -// validates if a buffer is a loadable object file compilable for the target -// -bool lto_module_is_object_file_in_memory_for_target(const void* mem, - size_t length, const char* target_triplet_prefix) -{ - return LTOModule::isBitcodeFileForTarget(mem, length, target_triplet_prefix); +/// lto_module_is_object_file_in_memory_for_target - Validates if a buffer is a +/// loadable object file compilable for the target. +bool +lto_module_is_object_file_in_memory_for_target(const void* mem, + size_t length, + const char* target_triplet_prefix) { + return LTOModule::isBitcodeFileForTarget(mem, length, target_triplet_prefix); } - - -// -// loads an object file from disk -// returns NULL on error (check lto_get_error_message() for details) -// -lto_module_t lto_module_create(const char* path) -{ - return LTOModule::makeLTOModule(path, sLastErrorString); +/// lto_module_create - Loads an object file from disk. Returns NULL on error +/// (check lto_get_error_message() for details). +lto_module_t lto_module_create(const char* path) { + return LTOModule::makeLTOModule(path, 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(int fd, const char *path, size_t size) -{ - return LTOModule::makeLTOModule(fd, path, size, sLastErrorString); +/// lto_module_create_from_fd - 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, 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_create_from_fd_at_offset - 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); + 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) -// -lto_module_t lto_module_create_from_memory(const void* mem, size_t length) -{ - return LTOModule::makeLTOModule(mem, length, sLastErrorString); +/// lto_module_create_from_memory - Loads an object file from memory. Returns +/// NULL on error (check lto_get_error_message() for details). +lto_module_t lto_module_create_from_memory(const void* mem, size_t length) { + return LTOModule::makeLTOModule(mem, length, sLastErrorString); } - -// -// frees all memory for a module -// upon return the lto_module_t is no longer valid -// -void lto_module_dispose(lto_module_t mod) -{ - delete mod; +/// lto_module_dispose - Frees all memory for a module. Upon return the +/// lto_module_t is no longer valid. +void lto_module_dispose(lto_module_t mod) { + delete mod; } - -// -// returns triplet string which the object module was compiled under -// -const char* lto_module_get_target_triple(lto_module_t mod) -{ - return mod->getTargetTriple(); +/// lto_module_get_target_triple - Returns triplet string which the object +/// module was compiled under. +const char* lto_module_get_target_triple(lto_module_t mod) { + return mod->getTargetTriple(); } -// -// sets triple string with which the object will be codegened. -// -void lto_module_set_target_triple(lto_module_t mod, const char *triple) -{ - return mod->setTargetTriple(triple); +/// lto_module_set_target_triple - Sets triple string with which the object will +/// be codegened. +void lto_module_set_target_triple(lto_module_t mod, const char *triple) { + return mod->setTargetTriple(triple); } - -// -// returns the number of symbols in the object module -// -unsigned int lto_module_get_num_symbols(lto_module_t mod) -{ - return mod->getSymbolCount(); +/// lto_module_get_num_symbols - Returns the number of symbols in the object +/// module. +unsigned int lto_module_get_num_symbols(lto_module_t mod) { + return mod->getSymbolCount(); } -// -// returns the name of the ith symbol in the object module -// -const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) -{ - return mod->getSymbolName(index); +/// lto_module_get_symbol_name - Returns the name of the ith symbol in the +/// object module. +const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) { + return mod->getSymbolName(index); } - -// -// returns the attributes of the ith symbol in the object module -// -lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, - unsigned int index) -{ - return mod->getSymbolAttributes(index); +/// lto_module_get_symbol_attribute - Returns the attributes of the ith symbol +/// in the object module. +lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, + unsigned int index) { + return mod->getSymbolAttributes(index); } - - - - -// -// instantiates a code generator -// returns NULL if there is an error -// -lto_code_gen_t lto_codegen_create(void) -{ - return new LTOCodeGenerator(); +/// lto_codegen_create - Instantiates a code generator. Returns NULL if there +/// is an error. +lto_code_gen_t lto_codegen_create(void) { + return new LTOCodeGenerator(); } - - -// -// frees all memory for a code generator -// upon return the lto_code_gen_t is no longer valid -// -void lto_codegen_dispose(lto_code_gen_t cg) -{ - delete cg; +/// lto_codegen_dispose - Frees all memory for a code generator. Upon return the +/// lto_code_gen_t is no longer valid. +void lto_codegen_dispose(lto_code_gen_t cg) { + delete cg; } - - -// -// add an object module to the set of modules for which code will be generated -// returns true on error (check lto_get_error_message() for details) -// -bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) -{ - return cg->addModule(mod, sLastErrorString); +/// lto_codegen_add_module - Add an object module to the set of modules for +/// which code will be generated. Returns true on error (check +/// lto_get_error_message() for details). +bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) { + return cg->addModule(mod, sLastErrorString); } - -// -// sets what if any format of debug info should be generated -// returns true on error (check lto_get_error_message() for details) -// -bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) -{ - return cg->setDebugInfo(debug, sLastErrorString); +/// lto_codegen_set_debug_model - Sets what if any format of debug info should +/// be generated. Returns true on error (check lto_get_error_message() for +/// details). +bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) { + return cg->setDebugInfo(debug, sLastErrorString); } - -// -// sets what code model to generated -// returns true on error (check lto_get_error_message() for details) -// -bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) -{ +/// lto_codegen_set_pic_model - Sets what code model to generated. Returns true +/// on error (check lto_get_error_message() for details). +bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) { return cg->setCodePICModel(model, sLastErrorString); } -// -// sets the cpu to generate code for -// -void lto_codegen_set_cpu(lto_code_gen_t cg, const char* cpu) -{ +/// lto_codegen_set_cpu - Sets the cpu to generate code for. +void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) { return cg->setCpu(cpu); } -// -// sets the path to the assembler tool -// -void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path) -{ +/// lto_codegen_set_assembler_path - Sets the path to the assembler tool. +void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) { // In here only for backwards compatibility. We use MC now. } - -// -// sets extra arguments that libLTO should pass to the assembler -// -void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char** args, - int nargs) -{ +/// lto_codegen_set_assembler_args - Sets extra arguments that libLTO should +/// pass to the assembler. +void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, + int nargs) { // In here only for backwards compatibility. We use MC now. } -// -// adds to a list of all global symbols that must exist in the final -// generated code. If a function is not listed there, it might be -// inlined into every usage and optimized away. -// -void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol) -{ +/// lto_codegen_add_must_preserve_symbol - Adds to a list of all global symbols +/// that must exist in the final generated code. If a function is not listed +/// there, it might be inlined into every usage and optimized away. +void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, + const char *symbol) { cg->addMustPreserveSymbol(symbol); } +/// lto_codegen_set_whole_program_optimization - Enable the internalize pass +/// during LTO optimizations. +void lto_codegen_set_whole_program_optimization(lto_code_gen_t cg) { + cg->enableInternalizePass(); +} -// -// writes a new file at the specified path that contains the -// merged contents of all modules added so far. -// returns true on error (check lto_get_error_message() for details) -// -bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path) -{ +/// lto_codegen_write_merged_modules - Writes a new file at the specified path +/// that contains the merged contents of all modules added so far. Returns true +/// on error (check lto_get_error_message() for details). +bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) { return cg->writeMergedModules(path, sLastErrorString); } - -// -// Generates code for all added modules into one native object file. -// On success returns a pointer to a generated mach-o/ELF buffer and -// length set to the buffer size. The buffer is owned by the -// lto_code_gen_t and will be freed when lto_codegen_dispose() -// is called, or lto_codegen_compile() is called again. -// On failure, returns NULL (check lto_get_error_message() for details). -// -extern const void* -lto_codegen_compile(lto_code_gen_t cg, size_t* length) -{ +/// lto_codegen_compile - Generates code for all added modules into one native +/// object file. On success returns a pointer to a generated mach-o/ELF buffer +/// and length set to the buffer size. The buffer is owned by the lto_code_gen_t +/// object and will be freed when lto_codegen_dispose() is called, or +/// lto_codegen_compile() is called again. On failure, returns NULL (check +/// lto_get_error_message() for details). +const void *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) -{ +/// lto_codegen_compile_to_file - Generates code for all added modules into one +/// native object file. The name of the file is written to name. Returns true on +/// error. +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 -// -extern void -lto_codegen_debug_options(lto_code_gen_t cg, const char * opt) -{ +/// lto_codegen_debug_options - Used to pass extra options to the code +/// generator. +void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) { cg->setCodeGenDebugOptions(opt); } diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index b900bfb..f471f1a 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -27,6 +27,7 @@ lto_codegen_set_assembler_args lto_codegen_set_assembler_path lto_codegen_set_cpu lto_codegen_compile_to_file +lto_codegen_set_whole_program_optimization LLVMCreateDisasm LLVMDisasmDispose LLVMDisasmInstruction diff --git a/tools/macho-dump/LLVMBuild.txt b/tools/macho-dump/LLVMBuild.txt new file mode 100644 index 0000000..1ad9b84 --- /dev/null +++ b/tools/macho-dump/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/macho-dump/LLVMBuild.txt -------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = macho-dump +parent = Tools +required_libraries = Object Support diff --git a/tools/macho-dump/Makefile b/tools/macho-dump/Makefile index 638015e..0843e98 100644 --- a/tools/macho-dump/Makefile +++ b/tools/macho-dump/Makefile @@ -7,17 +7,11 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = macho-dump +LEVEL := ../.. +TOOLNAME := macho-dump +LINK_COMPONENTS := support object # 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 := support object +TOOL_NO_EXPORTS := 1 -include $(LLVM_SRC_ROOT)/Makefile.rules +include $(LEVEL)/Makefile.common diff --git a/tools/opt/CMakeLists.txt b/tools/opt/CMakeLists.txt index 0570d0e..7daf22a 100644 --- a/tools/opt/CMakeLists.txt +++ b/tools/opt/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LLVM_LINK_COMPONENTS bitreader asmparser bitwriter instrumentation scalaropts ipo) +set(LLVM_LINK_COMPONENTS bitreader asmparser bitwriter instrumentation scalaropts ipo vectorize) add_llvm_tool(opt AnalysisWrappers.cpp diff --git a/tools/opt/LLVMBuild.txt b/tools/opt/LLVMBuild.txt new file mode 100644 index 0000000..4de99f5 --- /dev/null +++ b/tools/opt/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/opt/LLVMBuild.txt --------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = opt +parent = Tools +required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Scalar diff --git a/tools/opt/Makefile b/tools/opt/Makefile index 726cad8..16d116d 100644 --- a/tools/opt/Makefile +++ b/tools/opt/Makefile @@ -6,9 +6,9 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## -LEVEL = ../.. -TOOLNAME = opt -LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo +LEVEL := ../.. +TOOLNAME := opt +LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo vectorize include $(LEVEL)/Makefile.common diff --git a/tools/opt/PrintSCC.cpp b/tools/opt/PrintSCC.cpp index 533f49e..11efdcd 100644 --- a/tools/opt/PrintSCC.cpp +++ b/tools/opt/PrintSCC.cpp @@ -101,8 +101,8 @@ bool CallGraphSCC::runOnModule(Module &M) { errs() << "\nSCC #" << ++sccNum << " : "; for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(), E = nextSCC.end(); I != E; ++I) - errs() << ((*I)->getFunction() ? (*I)->getFunction()->getNameStr() - : std::string("external node")) << ", "; + errs() << ((*I)->getFunction() ? (*I)->getFunction()->getName() + : "external node") << ", "; if (nextSCC.size() == 1 && SCCI.hasLoop()) errs() << " (Has self-loop)."; } diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index ffd2c21..30da863 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -291,8 +291,8 @@ struct RegionPassPrinter : public RegionPass { virtual bool runOnRegion(Region *R, RGPassManager &RGM) { if (!Quiet) { Out << "Printing analysis '" << PassToPrint->getPassName() << "' for " - << "region: '" << R->getNameStr() << "' in function '" - << R->getEntry()->getParent()->getNameStr() << "':\n"; + << "region: '" << R->getNameStr() << "' in function '" + << R->getEntry()->getParent()->getName() << "':\n"; } // Get and print pass... getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out, @@ -407,6 +407,8 @@ static inline void addPass(PassManagerBase &PM, Pass *P) { /// OptLevel - Optimization Level static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM, unsigned OptLevel) { + FPM.add(createVerifierPass()); // Verify that input is correct + PassManagerBuilder Builder; Builder.OptLevel = OptLevel; @@ -478,6 +480,7 @@ int main(int argc, char **argv) { PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); + initializeVectorization(Registry); initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); @@ -505,7 +508,7 @@ int main(int argc, char **argv) { M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { - Err.Print(argv[0], errs()); + Err.print(argv[0], errs()); return 1; } |