diff options
author | Shih-wei Liao <sliao@google.com> | 2012-04-24 11:26:46 -0700 |
---|---|---|
committer | Shih-wei Liao <sliao@google.com> | 2012-04-24 11:26:46 -0700 |
commit | cf5a1461acaace0f3e7d11fbbcfbf635b8c8ea9d (patch) | |
tree | 557137810ae9efc96147d672d372e4dabd0a2440 /tools | |
parent | 4c8fab82874a29dcd2b242533af3ebe7f66bfd74 (diff) | |
parent | fc728fbdc2631ce8f343cf9b7292d218fde7419f (diff) | |
download | external_llvm-cf5a1461acaace0f3e7d11fbbcfbf635b8c8ea9d.zip external_llvm-cf5a1461acaace0f3e7d11fbbcfbf635b8c8ea9d.tar.gz external_llvm-cf5a1461acaace0f3e7d11fbbcfbf635b8c8ea9d.tar.bz2 |
Merge with LLVM upstream r155090.
Conflicts:
lib/Support/Unix/PathV2.inc
Change-Id: I7b89833849f6cbcfa958a33a971d0f7754c9cb2c
Diffstat (limited to 'tools')
-rw-r--r-- | tools/bugpoint/ExecutionDriver.cpp | 47 | ||||
-rw-r--r-- | tools/bugpoint/ToolRunner.cpp | 88 | ||||
-rw-r--r-- | tools/llc/llc.cpp | 32 | ||||
-rw-r--r-- | tools/lli/lli.cpp | 28 | ||||
-rw-r--r-- | tools/llvm-mc/Disassembler.cpp | 59 | ||||
-rw-r--r-- | tools/llvm-mc/Disassembler.h | 15 | ||||
-rw-r--r-- | tools/llvm-mc/llvm-mc.cpp | 175 | ||||
-rw-r--r-- | tools/llvm-objdump/MachODump.cpp | 5 | ||||
-rw-r--r-- | tools/llvm-objdump/llvm-objdump.cpp | 10 | ||||
-rw-r--r-- | tools/llvm-shlib/Makefile | 6 | ||||
-rw-r--r-- | tools/llvm-stress/llvm-stress.cpp | 63 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.cpp | 338 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.h | 103 | ||||
-rw-r--r-- | tools/lto/LTOModule.cpp | 279 | ||||
-rw-r--r-- | tools/lto/LTOModule.h | 243 | ||||
-rw-r--r-- | tools/lto/lto.cpp | 344 | ||||
-rw-r--r-- | tools/opt/opt.cpp | 7 |
17 files changed, 831 insertions, 1011 deletions
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index adf5587..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); @@ -221,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) { @@ -243,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) { @@ -277,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); @@ -459,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/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index b80a5b4..25a2bae 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -623,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 // diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 191b649..ceff8a6 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -210,29 +210,6 @@ DontPlaceZerosInBSS("nozero-initialized-in-bss", 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)); @@ -263,6 +240,11 @@ TrapFuncName("trap-func", cl::Hidden, 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)); @@ -458,15 +440,13 @@ int main(int argc, char **argv) { 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> diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index efcc1f5..2e2bf7d 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -141,6 +141,28 @@ namespace { "Large code model"), clEnumValEnd)); + cl::opt<bool> + EnableJITExceptionHandling("jit-enable-eh", + cl::desc("Emit exception handling information"), + cl::init(false)); + + cl::opt<bool> +// In debug builds, make this default to true. +#ifdef NDEBUG +#define EMIT_DEBUG false +#else +#define EMIT_DEBUG true +#endif + 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 ExecutionEngine *EE = 0; @@ -229,6 +251,12 @@ int main(int argc, char **argv, char * const *envp) { } builder.setOptLevel(OLvl); + TargetOptions Options; + Options.JITExceptionHandling = EnableJITExceptionHandling; + Options.JITEmitDebugInfo = EmitJitDebugInfo; + Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk; + builder.setTargetOptions(Options); + EE = builder.create(); if (!EE) { if (!ErrorMsg.empty()) diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index 6793d7e..5f2fdb8 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -17,20 +17,18 @@ #include "../../lib/MC/MCDisassembler/EDInst.h" #include "../../lib/MC/MCDisassembler/EDOperand.h" #include "../../lib/MC/MCDisassembler/EDToken.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy; @@ -55,8 +53,9 @@ public: } static bool PrintInsts(const MCDisassembler &DisAsm, - MCInstPrinter &Printer, const ByteArrayTy &Bytes, - SourceMgr &SM, raw_ostream &Out) { + const ByteArrayTy &Bytes, + SourceMgr &SM, raw_ostream &Out, + MCStreamer &Streamer) { // Wrap the vector in a MemoryObject. VectorMemoryObject memoryObject(Bytes); @@ -86,8 +85,7 @@ static bool PrintInsts(const MCDisassembler &DisAsm, // Fall through case MCDisassembler::Success: - Printer.printInst(&Inst, Out, ""); - Out << "\n"; + Streamer.EmitInstruction(Inst); break; } } @@ -144,49 +142,22 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray, int Disassembler::disassemble(const Target &T, const std::string &Triple, - const std::string &Cpu, - const std::string &FeaturesStr, + MCSubtargetInfo &STI, + MCStreamer &Streamer, MemoryBuffer &Buffer, + SourceMgr &SM, raw_ostream &Out) { - // Set up disassembler. - OwningPtr<const MCAsmInfo> AsmInfo(T.createMCAsmInfo(Triple)); - - if (!AsmInfo) { - errs() << "error: no assembly info for target " << Triple << "\n"; - return -1; - } - - 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)); + 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; - } - - int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); - OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, - *AsmInfo, *MRI, *STI)); - if (!IP) { - errs() << "error: no instruction printer for target " << Triple << '\n'; - return -1; - } + // Set up initial section manually here + Streamer.InitSections(); bool ErrorOccurred = false; - SourceMgr SM; - SM.AddNewSourceBuffer(&Buffer, SMLoc()); - // Convert the input to a vector for disassembly. ByteArrayTy ByteArray; StringRef Str = Buffer.getBuffer(); @@ -194,7 +165,7 @@ int Disassembler::disassemble(const Target &T, ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); if (!ByteArray.empty()) - ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM, Out); + ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer); return ErrorOccurred; } @@ -228,12 +199,10 @@ static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) { int Disassembler::disassembleEnhanced(const std::string &TS, MemoryBuffer &Buffer, + SourceMgr &SM, raw_ostream &Out) { ByteArrayTy ByteArray; StringRef Str = Buffer.getBuffer(); - SourceMgr SM; - - SM.AddNewSourceBuffer(&Buffer, SMLoc()); if (ByteArrayFromString(ByteArray, Str, SM)) { return -1; diff --git a/tools/llvm-mc/Disassembler.h b/tools/llvm-mc/Disassembler.h index e8cd92d..17d622f 100644 --- a/tools/llvm-mc/Disassembler.h +++ b/tools/llvm-mc/Disassembler.h @@ -22,18 +22,23 @@ namespace llvm { class MemoryBuffer; class Target; class raw_ostream; +class SourceMgr; +class MCSubtargetInfo; +class MCStreamer; class Disassembler { public: - static int disassemble(const Target &target, - const std::string &tripleString, - const std::string &Cpu, - const std::string &FeaturesStr, - MemoryBuffer &buffer, + static int disassemble(const Target &T, + const std::string &Triple, + MCSubtargetInfo &STI, + MCStreamer &Streamer, + MemoryBuffer &Buffer, + SourceMgr &SM, raw_ostream &Out); static int disassembleEnhanced(const std::string &tripleString, MemoryBuffer &buffer, + SourceMgr &SM, raw_ostream &Out); }; diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index ceed2d6..36a482e 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -15,6 +15,7 @@ #include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCInstPrinter.h" @@ -242,37 +243,11 @@ static void setDwarfDebugFlags(int argc, char **argv) { } } -static int AsLexInput(const char *ProgName) { - OwningPtr<MemoryBuffer> BufferPtr; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { - errs() << ProgName << ": " << ec.message() << '\n'; - return 1; - } - MemoryBuffer *Buffer = BufferPtr.take(); - - SourceMgr SrcMgr; - - // Tell SrcMgr about this buffer, which is what TGParser will pick up. - SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); - - // Record the location of the include directories so that the lexer can find - // it later. - SrcMgr.setIncludeDirs(IncludeDirs); - - const Target *TheTarget = GetTarget(ProgName); - if (!TheTarget) - return 1; - - llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName)); - assert(MAI && "Unable to create target asm info!"); +static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) { - AsmLexer Lexer(*MAI); + AsmLexer Lexer(MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); - OwningPtr<tool_output_file> Out(GetOutputStream()); - if (!Out) - return 1; - bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { AsmToken Tok = Lexer.getTok(); @@ -346,13 +321,49 @@ static int AsLexInput(const char *ProgName) { Out->os() << "\")\n"; } - // Keep output if no errors. - if (Error == 0) Out->keep(); - return Error; } -static int AssembleInput(const char *ProgName) { +static int AssembleInput(const char *ProgName, const Target *TheTarget, + SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str, + MCAsmInfo &MAI, MCSubtargetInfo &STI) { + OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, + Str, MAI)); + OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(STI, *Parser)); + if (!TAP) { + errs() << ProgName + << ": error: this target does not support assembly parsing.\n"; + return 1; + } + + Parser->setShowParsedOperands(ShowInstOperands); + Parser->setTargetParser(*TAP.get()); + + int Res = Parser->Run(NoInitialTextSection); + + return Res; +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + 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); + + const char *ProgName = argv[0]; const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; @@ -413,10 +424,9 @@ static int AssembleInput(const char *ProgName) { OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); - // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (FileType == OFT_AssemblyFile) { MCInstPrinter *IP = - TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MRI, *STI); + TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { @@ -440,93 +450,24 @@ static int AssembleInput(const char *ProgName) { NoExecStack)); } - OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, - *Str.get(), *MAI)); - OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser)); - if (!TAP) { - errs() << ProgName - << ": error: this target does not support assembly parsing.\n"; - return 1; - } - - Parser->setShowParsedOperands(ShowInstOperands); - Parser->setTargetParser(*TAP.get()); - - int Res = Parser->Run(NoInitialTextSection); - - // Keep output if no errors. - if (Res == 0) Out->keep(); - - return Res; -} - -static int DisassembleInput(const char *ProgName, bool Enhanced) { - const Target *TheTarget = GetTarget(ProgName); - if (!TheTarget) - return 0; - - OwningPtr<MemoryBuffer> Buffer; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, Buffer)) { - errs() << ProgName << ": " << ec.message() << '\n'; - return 1; - } - - OwningPtr<tool_output_file> Out(GetOutputStream()); - if (!Out) - return 1; - - int Res; - if (Enhanced) { - Res = - Disassembler::disassembleEnhanced(TripleName, *Buffer.take(), Out->os()); - } else { - // Package up features to be passed to target/subtarget - std::string FeaturesStr; - if (MAttrs.size()) { - SubtargetFeatures Features; - for (unsigned i = 0; i != MAttrs.size(); ++i) - Features.AddFeature(MAttrs[i]); - FeaturesStr = Features.getString(); - } - - Res = Disassembler::disassemble(*TheTarget, TripleName, MCPU, FeaturesStr, - *Buffer.take(), Out->os()); - } - - // Keep output if no errors. - if (Res == 0) Out->keep(); - - return Res; -} - - -int main(int argc, char **argv) { - // Print a stack trace if we signal out. - sys::PrintStackTraceOnErrorSignal(); - PrettyStackTraceProgram X(argc, argv); - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - // Initialize targets and assembly printers/parsers. - llvm::InitializeAllTargetInfos(); - llvm::InitializeAllTargetMCs(); - 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); - + int Res = 1; switch (Action) { case AC_AsLex: - return AsLexInput(argv[0]); + Res = AsLexInput(SrcMgr, *MAI, Out.get()); + break; case AC_Assemble: - return AssembleInput(argv[0]); + Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI); + break; case AC_Disassemble: - return DisassembleInput(argv[0], false); + Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, + *Buffer, SrcMgr, Out->os()); + break; case AC_EDisassemble: - return DisassembleInput(argv[0], true); + Res = Disassembler::disassembleEnhanced(TripleName, *Buffer, SrcMgr, Out->os()); + break; } + + // Keep output if no errors. + if (Res == 0) Out->keep(); + return Res; } diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index b9ea041..0e7f3fd 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -260,8 +260,9 @@ void llvm::DisassembleInputMachO(StringRef Filename) { 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, *MRI, *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 " diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 94becae..5a6f94a 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -26,6 +26,7 @@ #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" @@ -46,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; @@ -253,9 +255,15 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { 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, *MRI, *STI)); + AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); if (!IP) { errs() << "error: no instruction printer for target " << TripleName << '\n'; diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile index 1d35670..2d2e2c5 100644 --- a/tools/llvm-shlib/Makefile +++ b/tools/llvm-shlib/Makefile @@ -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-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp index c095059..fb05a58 100644 --- a/tools/llvm-stress/llvm-stress.cpp +++ b/tools/llvm-stress/llvm-stress.cpp @@ -60,14 +60,28 @@ class Random { public: /// C'tor Random(unsigned _seed):Seed(_seed) {} - /// Return the next random value. - unsigned Rand() { - unsigned Val = Seed + 0x000b07a1; + + /// 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; }; @@ -202,11 +216,17 @@ protected: /// Pick a random vector type. Type *pickVectorType(unsigned len = (unsigned)-1) { - Type *Ty = pickScalarType(); // 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); @@ -342,10 +362,20 @@ struct ConstModifier: public Modifier { } 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, - static_cast<double>(1)/Ran->Rand())); + return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat)); } if (Ty->isIntegerTy()) { @@ -382,7 +412,7 @@ struct ExtractElementModifier: public Modifier { Value *Val0 = getRandomVectorValue(); Value *V = ExtractElementInst::Create(Val0, ConstantInt::get(Type::getInt32Ty(BB->getContext()), - Ran->Rand() % cast<VectorType>(Val0->getType())->getNumElements()), + Ran->Rand() % cast<VectorType>(Val0->getType())->getNumElements()), "E", BB->getTerminator()); return PT->push_back(V); } @@ -446,7 +476,7 @@ struct CastModifier: public Modifier { DestTy = pickVectorType(VecTy->getNumElements()); } - // no need to casr. + // no need to cast. if (VTy == DestTy) return; // Pointers: @@ -457,9 +487,11 @@ struct CastModifier: public Modifier { new BitCastInst(V, DestTy, "PC", BB->getTerminator())); } + unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits(); + unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits(); + // Generate lots of bitcasts. - if ((Ran->Rand() & 1) && - VTy->getPrimitiveSizeInBits() == DestTy->getPrimitiveSizeInBits()) { + if ((Ran->Rand() & 1) && VSize == DestSize) { return PT->push_back( new BitCastInst(V, DestTy, "BC", BB->getTerminator())); } @@ -467,11 +499,11 @@ struct CastModifier: public Modifier { // Both types are integers: if (VTy->getScalarType()->isIntegerTy() && DestTy->getScalarType()->isIntegerTy()) { - if (VTy->getScalarType()->getPrimitiveSizeInBits() > - DestTy->getScalarType()->getPrimitiveSizeInBits()) { + if (VSize > DestSize) { return PT->push_back( new TruncInst(V, DestTy, "Tr", BB->getTerminator())); } else { + assert(VSize < DestSize && "Different int types with the same size?"); if (Ran->Rand() & 1) return PT->push_back( new ZExtInst(V, DestTy, "ZE", BB->getTerminator())); @@ -501,14 +533,15 @@ struct CastModifier: public Modifier { // Both floats. if (VTy->getScalarType()->isFloatingPointTy() && DestTy->getScalarType()->isFloatingPointTy()) { - if (VTy->getScalarType()->getPrimitiveSizeInBits() > - DestTy->getScalarType()->getPrimitiveSizeInBits()) { + if (VSize > DestSize) { return PT->push_back( new FPTruncInst(V, DestTy, "Tr", BB->getTerminator())); - } else { + } else if (VSize < DestSize) { return PT->push_back( new FPExtInst(V, DestTy, "ZE", BB->getTerminator())); } + // If VSize == DestSize, then the two types must be fp128 and ppc_fp128, + // for which there is no defined conversion. So do nothing. } } diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 111f8c8..6382a3f 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,64 +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/ErrorHandling.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), + _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) -{ +bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg); const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs(); @@ -99,53 +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; - } - llvm_unreachable("Unknown debug format!"); -} - -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::setDebugInfo(lto_debug_model debug, + std::string& errMsg) { + switch (debug) { + case LTO_DEBUG_MODEL_NONE: + _emitDwarfDebugInfo = false; + return false; -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 @@ -157,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(); @@ -168,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) ) { @@ -189,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(); @@ -206,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; @@ -233,48 +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::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; - } - - // 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); +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); @@ -294,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); } @@ -307,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; @@ -316,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(), @@ -351,81 +326,84 @@ 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()); + // Enabling internalize here would use its AllButMain variant. It + // keeps only main if it exists and does nothing for libraries. Instead + // we create the pass ourselves with the symbol list provided by the linker. + PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/false, + !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); + + 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 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..032dc37 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -4,71 +4,80 @@ // // 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); + 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); + + typedef llvm::StringMap<uint8_t> StringSet; - 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; + 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 8ce8cd2..1dbd64b 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -13,37 +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/MC/MCAsmInfo.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; @@ -53,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); @@ -69,23 +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; } - -LTOModule::LTOModule(Module *m, TargetMachine *t) - : _module(m), _target(t), - _context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL), - _mangler(_context, *_target->getTargetData()) -{ -} - -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(); @@ -113,12 +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)); @@ -163,7 +153,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr, Options); LTOModule *Ret = new LTOModule(m.take(), target); - if (Ret->ParseSymbols(errMsg)) { + if (Ret->parseSymbols(errMsg)) { delete Ret; return NULL; } @@ -171,20 +161,13 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, return Ret; } -const char *LTOModule::getTargetTriple() { - return _module->getTargetTriple().c_str(); -} - -void LTOModule::setTargetTriple(const char *triple) { - _module->setTargetTriple(triple); -} - -void LTOModule::addDefinedFunctionSymbol(Function *f) { - // add to list of defined symbols - addDefinedSymbol(f, 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); @@ -201,7 +184,7 @@ 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) { ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); if (!c) return; @@ -216,6 +199,8 @@ void LTOModule::addObjCClass(GlobalVariable *clgv) { const char *symbolName = entry.getKey().data(); info.name = symbolName; info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; entry.setValue(info); } } @@ -225,17 +210,18 @@ void LTOModule::addObjCClass(GlobalVariable *clgv) { 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); + info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | + LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT; + info.isFunction = false; + info.symbol = clgv; _symbols.push_back(info); } } - -// Parse i386/ppc ObjC category data structure. +/// addObjCCategory - Parse i386/ppc ObjC category data structure. void LTOModule::addObjCCategory(GlobalVariable *clgv) { ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); if (!c) return; @@ -255,11 +241,12 @@ void LTOModule::addObjCCategory(GlobalVariable *clgv) { const char *symbolName = entry.getKey().data(); info.name = symbolName; info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; entry.setValue(info); } - -// Parse i386/ppc ObjC class list data structure. +/// addObjCClassRef - Parse i386/ppc ObjC class list data structure. void LTOModule::addObjCClassRef(GlobalVariable *clgv) { std::string targetclassName; if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) @@ -274,10 +261,12 @@ void LTOModule::addObjCClassRef(GlobalVariable *clgv) { const char *symbolName = entry.getKey().data(); info.name = symbolName; info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + info.isFunction = false; + info.symbol = clgv; entry.setValue(info); } - +/// addDefinedDataSymbol - Add a data symbol as defined to the list. void LTOModule::addDefinedDataSymbol(GlobalValue *v) { // Add to list of defined symbols. addDefinedSymbol(v, false); @@ -325,6 +314,13 @@ void LTOModule::addDefinedDataSymbol(GlobalValue *v) { } } +/// addDefinedFunctionSymbol - Add a function symbol as defined to the list. +void LTOModule::addDefinedFunctionSymbol(Function *f) { + // add to list of defined symbols + addDefinedSymbol(f, true); +} + +/// addDefinedSymbol - Add a defined symbol to the list. void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { // ignore all llvm.* symbols if (def->getName().startswith("llvm.")) @@ -339,9 +335,9 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { 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; @@ -373,18 +369,24 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { 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); @@ -394,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); @@ -417,12 +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) { +/// 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; @@ -444,18 +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; @@ -544,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); @@ -560,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) {} @@ -596,17 +640,12 @@ namespace { 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 FinishImpl() {} }; -} +} // end anonymous namespace +/// 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()) @@ -651,6 +690,7 @@ bool LTOModule::addAsmGlobalSymbols(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; @@ -659,15 +699,13 @@ 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) { +/// 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); + addPotentialUndefinedSymbol(f, true); else addDefinedFunctionSymbol(f); } @@ -676,7 +714,7 @@ bool LTOModule::ParseSymbols(std::string &errMsg) { for (Module::global_iterator v = _module->global_begin(), e = _module->global_end(); v != e; ++v) { if (isDeclaration(*v)) - addPotentialUndefinedSymbol(v); + addPotentialUndefinedSymbol(v, false); else addDefinedDataSymbol(v); } @@ -686,41 +724,24 @@ bool LTOModule::ParseSymbols(std::string &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); + 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); + 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 35a0935..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. // //===----------------------------------------------------------------------===// @@ -20,104 +20,167 @@ #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 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, - bool isFunction); - void addPotentialUndefinedSymbol(llvm::GlobalValue* decl); - void addDefinedFunctionSymbol(llvm::Function* f); - void addDefinedDataSymbol(llvm::GlobalValue* v); - bool addAsmGlobalSymbols(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; - llvm::MCContext _context; - // Use mangler to add GlobalPrefix to names to match linker names. - llvm::Mangler _mangler; + /// 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/lto.cpp b/tools/lto/lto.cpp index dd658d1..a7e633d 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,196 @@ #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); } - -// -// 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/opt/opt.cpp b/tools/opt/opt.cpp index 30da863..a5b0511 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -114,6 +114,9 @@ static cl::opt<bool> OptLevelO3("O3", cl::desc("Optimization level 3. Similar to llvm-gcc -O3")); +static cl::opt<std::string> +TargetTriple("mtriple", cl::desc("Override target triple for module")); + static cl::opt<bool> UnitAtATime("funit-at-a-time", cl::desc("Enable IPO. This is same as llvm-gcc's -funit-at-a-time"), @@ -512,6 +515,10 @@ int main(int argc, char **argv) { return 1; } + // If we are supposed to override the target triple, do so now. + if (!TargetTriple.empty()) + M->setTargetTriple(Triple::normalize(TargetTriple)); + // Figure out what stream we are supposed to write to... OwningPtr<tool_output_file> Out; if (NoOutput) { |