diff options
Diffstat (limited to 'tools')
42 files changed, 1169 insertions, 250 deletions
diff --git a/tools/Makefile b/tools/Makefile index 5ed090e..4f0f54b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -20,8 +20,8 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \ llc llvm-ranlib llvm-ar llvm-nm \ llvm-ld llvm-prof llvm-link \ lli gccas gccld llvm-extract llvm-db \ - bugpoint llvm-bcanalyzer llvm-stub llvmc \ - llvm-mc + bugpoint llvm-bcanalyzer llvm-stub \ + llvm-mc llvmc # Let users override the set of tools to build from the command line. ifdef ONLY_TOOLS diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index d050b59..aab5072 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include <iostream> #include <memory> @@ -64,25 +65,27 @@ std::string llvm::getPassesString(const std::vector<const PassInfo*> &Passes) { } BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs, - unsigned timeout, unsigned memlimit) - : ToolName(toolname), ReferenceOutputFile(OutputFile), + unsigned timeout, unsigned memlimit, + LLVMContext& ctxt) + : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), Program(0), Interpreter(0), SafeInterpreter(0), gcc(0), - run_as_child(as_child), - run_find_bugs(find_bugs), Timeout(timeout), MemoryLimit(memlimit) {} + run_as_child(as_child), run_find_bugs(find_bugs), Timeout(timeout), + MemoryLimit(memlimit) {} /// ParseInputFile - Given a bitcode or assembly input filename, parse and /// return it, or return null if not possible. /// -Module *llvm::ParseInputFile(const std::string &Filename) { +Module *llvm::ParseInputFile(const std::string &Filename, + LLVMContext& Ctxt) { std::auto_ptr<MemoryBuffer> Buffer(MemoryBuffer::getFileOrSTDIN(Filename)); Module *Result = 0; if (Buffer.get()) - Result = ParseBitcodeFile(Buffer.get()); + Result = ParseBitcodeFile(Buffer.get(), Ctxt); - ParseError Err; - if (!Result && !(Result = ParseAssemblyFile(Filename, Err))) { - Err.PrintError("bugpoint", errs()); + SMDiagnostic Err; + if (!Result && !(Result = ParseAssemblyFile(Filename, Err, Ctxt))) { + Err.Print("bugpoint", errs()); Result = 0; } @@ -100,14 +103,14 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) { try { // Load the first input file. - Program = ParseInputFile(Filenames[0]); + Program = ParseInputFile(Filenames[0], Context); if (Program == 0) return true; if (!run_as_child) std::cout << "Read input file : '" << Filenames[0] << "'\n"; for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { - std::auto_ptr<Module> M(ParseInputFile(Filenames[i])); + std::auto_ptr<Module> M(ParseInputFile(Filenames[i], Context)); if (M.get() == 0) return true; if (!run_as_child) diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index 96e9fb9..d637c24 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -30,6 +30,7 @@ class Function; class BasicBlock; class AbstractInterpreter; class Instruction; +class LLVMContext; class DebugCrashes; @@ -42,6 +43,7 @@ extern bool DisableSimplifyCFG; extern bool BugpointIsInterrupted; class BugDriver { + LLVMContext& Context; const std::string ToolName; // Name of bugpoint std::string ReferenceOutputFile; // Name of `good' output file Module *Program; // The raw program, linked together @@ -60,10 +62,12 @@ class BugDriver { public: BugDriver(const char *toolname, bool as_child, bool find_bugs, - unsigned timeout, unsigned memlimit); + unsigned timeout, unsigned memlimit, LLVMContext& ctxt); const std::string &getToolName() const { return ToolName; } + LLVMContext& getContext() { return Context; } + // Set up methods... these methods are used to copy information about the // command line arguments into instance variables of BugDriver. // @@ -290,7 +294,8 @@ private: /// ParseInputFile - Given a bitcode or assembly input filename, parse and /// return it, or return null if not possible. /// -Module *ParseInputFile(const std::string &InputFilename); +Module *ParseInputFile(const std::string &InputFilename, + LLVMContext& ctxt); /// getPassesString - Turn a list of passes into a string which indicates the diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index 7daf57c..9697b34 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -73,7 +73,7 @@ ReducePassList::doTest(std::vector<const PassInfo*> &Prefix, PrefixOutput.set(PfxOutput); OrigProgram = BD.Program; - BD.Program = ParseInputFile(PrefixOutput.toString()); + BD.Program = ParseInputFile(PrefixOutput.toString(), BD.getContext()); if (BD.Program == 0) { std::cerr << BD.getToolName() << ": Error reading bitcode file '" << PrefixOutput << "'!\n"; diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 7e8ff78..b3260e1 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -112,7 +112,7 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, // Ok, so now we know that the prefix passes work, try running the suffix // passes on the result of the prefix passes. // - Module *PrefixOutput = ParseInputFile(BitcodeResult); + Module *PrefixOutput = ParseInputFile(BitcodeResult, BD.getContext()); if (PrefixOutput == 0) { std::cerr << BD.getToolName() << ": Error reading bitcode file '" << BitcodeResult << "'!\n"; diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index 3ded5e8..741be24 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -255,7 +255,7 @@ Module *BugDriver::runPassesOn(Module *M, // Restore the current program. swapProgramIn(OldProgram); - Module *Ret = ParseInputFile(BitcodeResult); + Module *Ret = ParseInputFile(BitcodeResult, Context); if (Ret == 0) { cerr << getToolName() << ": Error reading bitcode file '" << BitcodeResult << "'!\n"; diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index 20f0e99..3365b22 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -16,6 +16,7 @@ #include "BugDriver.h" #include "ToolRunner.h" #include "llvm/LinkAllPasses.h" +#include "llvm/LLVMContext.h" #include "llvm/Support/PassNameParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" @@ -73,8 +74,9 @@ int main(int argc, char **argv) { "llvm.org/cmds/bugpoint.html" " for more information.\n"); sys::SetInterruptFunction(BugpointInterruptFunction); - - BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit); + + LLVMContext Context; + BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit, Context); if (D.addSources(InputFilenames)) return 1; D.addPasses(PassList.begin(), PassList.end()); diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 8d8fcd2..146c53f 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -17,6 +17,7 @@ #include "llvm-c/lto.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/System/Errno.h" #include "llvm/System/Path.h" #include "llvm/System/Program.h" @@ -183,7 +184,7 @@ ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, (*message)(LDPL_ERROR, "Failed to seek to archive member of %s at offset %d: %s\n", file->name, - file->offset, strerror(errno)); + file->offset, sys::StrError(errno).c_str()); return LDPS_ERR; } buf = malloc(file->filesize); @@ -198,7 +199,7 @@ ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, "Failed to read archive member of %s at offset %d: %s\n", file->name, file->offset, - strerror(errno)); + sys::StrError(errno).c_str()); free(buf); return LDPS_ERR; } diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index e71b378..ae03c1e 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -22,6 +22,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachineRegistry.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/PassManager.h" @@ -212,6 +213,7 @@ static raw_ostream *GetOutputStream(const char *ProgName) { int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); @@ -225,7 +227,7 @@ int main(int argc, char **argv) { std::auto_ptr<MemoryBuffer> Buffer( MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)); if (Buffer.get()) - M.reset(ParseBitcodeFile(Buffer.get(), &ErrorMessage)); + M.reset(ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage)); if (M.get() == 0) { std::cerr << argv[0] << ": bitcode didn't read correctly.\n"; std::cerr << "Reason: " << ErrorMessage << "\n"; diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 2553674..a01b0d6 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -9,10 +9,11 @@ // // This utility provides a simple wrapper around the LLVM Execution Engines, // which allow the direct execution of LLVM programs through a Just-In-Time -// compiler, or through an intepreter if no JIT is available for this platform. +// compiler, or through an interpreter if no JIT is available for this platform. // //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/Type.h" @@ -93,6 +94,7 @@ int main(int argc, char **argv, char * const *envp) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); + LLVMContext Context; atexit(do_shutdown); // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm interpreter & dynamic compiler\n"); @@ -104,8 +106,8 @@ int main(int argc, char **argv, char * const *envp) { // Load the bitcode... std::string ErrorMsg; ModuleProvider *MP = NULL; - if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFile,&ErrorMsg)) { - MP = getBitcodeModuleProvider(Buffer, &ErrorMsg); + if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFile,&ErrorMsg)){ + MP = getBitcodeModuleProvider(Buffer, Context, &ErrorMsg); if (!MP) delete Buffer; } diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 5d81fc7..fe58db1 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Bitcode/Archive.h" #include "llvm/Support/CommandLine.h" @@ -690,6 +691,7 @@ int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Have the command line options parsed and handle things @@ -717,11 +719,11 @@ int main(int argc, char **argv) { // Produce a warning if we should and we're creating the archive if (!Create) std::cerr << argv[0] << ": creating " << ArchivePath.toString() << "\n"; - TheArchive = Archive::CreateEmpty(ArchivePath); + TheArchive = Archive::CreateEmpty(ArchivePath, Context); TheArchive->writeToDisk(); } else { std::string Error; - TheArchive = Archive::OpenAndLoad(ArchivePath, &Error); + TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); if (TheArchive == 0) { std::cerr << argv[0] << ": error loading '" << ArchivePath << "': " << Error << "!\n"; diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp index 79ece8f..eccabd5 100644 --- a/tools/llvm-as/llvm-as.cpp +++ b/tools/llvm-as/llvm-as.cpp @@ -15,6 +15,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Assembly/Parser.h" #include "llvm/Analysis/Verifier.h" @@ -22,6 +23,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/Streams.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/raw_ostream.h" @@ -55,6 +57,7 @@ int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n"); @@ -62,10 +65,10 @@ int main(int argc, char **argv) { std::ostream *Out = 0; try { // Parse the file now... - ParseError Err; - std::auto_ptr<Module> M(ParseAssemblyFile(InputFilename, Err)); + SMDiagnostic Err; + std::auto_ptr<Module> M(ParseAssemblyFile(InputFilename, Err, Context)); if (M.get() == 0) { - Err.PrintError(argv[0], errs()); + Err.Print(argv[0], errs()); return 1; } diff --git a/tools/llvm-db/CLIDebugger.cpp b/tools/llvm-db/CLIDebugger.cpp index 1d2a838..31476f7 100644 --- a/tools/llvm-db/CLIDebugger.cpp +++ b/tools/llvm-db/CLIDebugger.cpp @@ -22,8 +22,9 @@ using namespace llvm; /// CLIDebugger constructor - This initializes the debugger to its default /// state, and initializes the command table. /// -CLIDebugger::CLIDebugger() - : TheProgramInfo(0), TheRuntimeInfo(0), Prompt("(llvm-db) "), ListSize(10) { +CLIDebugger::CLIDebugger(LLVMContext& ctxt) + : Context(ctxt), TheProgramInfo(0), TheRuntimeInfo(0), + Prompt("(llvm-db) "), ListSize(10) { // Initialize instance variables CurrentFile = 0; LineListedStart = 1; diff --git a/tools/llvm-db/CLIDebugger.h b/tools/llvm-db/CLIDebugger.h index 56ea14d..9904559 100644 --- a/tools/llvm-db/CLIDebugger.h +++ b/tools/llvm-db/CLIDebugger.h @@ -24,10 +24,13 @@ namespace llvm { class SourceLanguage; class ProgramInfo; class RuntimeInfo; + class LLVMContext; /// CLIDebugger - This class implements the command line interface for the /// LLVM debugger. class CLIDebugger { + LLVMContext& Context; + /// Dbg - The low-level LLVM debugger object that we use to do our dirty /// work. Debugger Dbg; @@ -79,7 +82,7 @@ namespace llvm { const SourceLanguage *CurrentLanguage; public: - CLIDebugger(); + CLIDebugger(LLVMContext& ctxt); /// getDebugger - Return the current LLVM debugger implementation being /// used. diff --git a/tools/llvm-db/Commands.cpp b/tools/llvm-db/Commands.cpp index ffebdd5..4c916f4 100644 --- a/tools/llvm-db/Commands.cpp +++ b/tools/llvm-db/Commands.cpp @@ -64,7 +64,7 @@ void CLIDebugger::startProgramRunning() { TheProgramInfo = 0; CurrentFile = 0; - Dbg.loadProgram(Program.toString()); + Dbg.loadProgram(Program.toString(), Context); TheProgramInfo = new ProgramInfo(Dbg.getProgram()); } @@ -244,7 +244,7 @@ void CLIDebugger::fileCommand(std::string &Options) { std::cout << "Unloaded program.\n"; } else { std::cout << "Loading program... " << std::flush; - Dbg.loadProgram(Prog); + Dbg.loadProgram(Prog, Context); assert(Dbg.isProgramLoaded() && "loadProgram succeeded, but not program loaded!"); TheProgramInfo = new ProgramInfo(Dbg.getProgram()); diff --git a/tools/llvm-db/llvm-db.cpp b/tools/llvm-db/llvm-db.cpp index 04e6162..78dbf71 100644 --- a/tools/llvm-db/llvm-db.cpp +++ b/tools/llvm-db/llvm-db.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "CLIDebugger.h" +#include "llvm/LLVMContext.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" @@ -54,6 +55,7 @@ int main(int argc, char **argv, char * const *envp) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. std::cout << "NOTE: llvm-db is known useless right now.\n"; try { @@ -68,7 +70,7 @@ int main(int argc, char **argv, char * const *envp) { InputArgs.push_back(InputFile); // Create the CLI debugger... - CLIDebugger D; + CLIDebugger D(Context); // Initialize the debugger with the command line options we read... Debugger &Dbg = D.getDebugger(); diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index 471e5e2..901c8e9 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -16,6 +16,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Bitcode/ReaderWriter.h" @@ -50,6 +51,7 @@ int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. try { cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); @@ -61,7 +63,7 @@ int main(int argc, char **argv) { if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) { - M.reset(ParseBitcodeFile(Buffer, &ErrorMessage)); + M.reset(ParseBitcodeFile(Buffer, Context, &ErrorMessage)); delete Buffer; } diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index 46840f2..af0cf07 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Bitcode/ReaderWriter.h" @@ -60,7 +61,8 @@ int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); - + + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); @@ -71,7 +73,7 @@ int main(int argc, char **argv) { cerr << argv[0] << ": Error reading file '" + InputFilename + "'\n"; return 1; } else { - M.reset(ParseBitcodeFile(Buffer)); + M.reset(ParseBitcodeFile(Buffer, Context)); } delete Buffer; diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp index fd2e0f7..2b9d255 100644 --- a/tools/llvm-ld/llvm-ld.cpp +++ b/tools/llvm-ld/llvm-ld.cpp @@ -22,6 +22,7 @@ #include "llvm/LinkAllVMCore.h" #include "llvm/Linker.h" +#include "llvm/LLVMContext.h" #include "llvm/System/Program.h" #include "llvm/Module.h" #include "llvm/PassManager.h" @@ -505,7 +506,8 @@ int main(int argc, char **argv, char **envp) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); - + + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. try { // Initial global variable above for convenience printing of program name. @@ -515,7 +517,7 @@ int main(int argc, char **argv, char **envp) { cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); // Construct a Linker (now that Verbose is set) - Linker TheLinker(progname, OutputFilename, Verbose); + Linker TheLinker(progname, OutputFilename, Context, Verbose); // Keep track of the native link items (versus the bitcode items) Linker::ItemList NativeLinkItems; diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 15850f4..f65e602 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Linker.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" @@ -47,7 +48,8 @@ DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden); // LoadFile - Read the specified bitcode file in and return it. This routine // searches the link path for the specified file to try to find it... // -static inline std::auto_ptr<Module> LoadFile(const std::string &FN) { +static inline std::auto_ptr<Module> LoadFile(const std::string &FN, + LLVMContext& Context) { sys::Path Filename; if (!Filename.set(FN)) { cerr << "Invalid file name: '" << FN << "'\n"; @@ -62,7 +64,7 @@ static inline std::auto_ptr<Module> LoadFile(const std::string &FN) { const std::string &FNStr = Filename.toString(); if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(FNStr, &ErrorMessage)) { - Result = ParseBitcodeFile(Buffer, &ErrorMessage); + Result = ParseBitcodeFile(Buffer, Context, &ErrorMessage); delete Buffer; } if (Result) return std::auto_ptr<Module>(Result); // Load successful! @@ -84,13 +86,14 @@ int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); unsigned BaseArg = 0; std::string ErrorMessage; - std::auto_ptr<Module> Composite(LoadFile(InputFilenames[BaseArg])); + std::auto_ptr<Module> Composite(LoadFile(InputFilenames[BaseArg], Context)); if (Composite.get() == 0) { cerr << argv[0] << ": error loading file '" << InputFilenames[BaseArg] << "'\n"; @@ -98,7 +101,7 @@ int main(int argc, char **argv) { } for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) { - std::auto_ptr<Module> M(LoadFile(InputFilenames[i])); + std::auto_ptr<Module> M(LoadFile(InputFilenames[i], Context)); if (M.get() == 0) { cerr << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n"; return 1; diff --git a/tools/llvm-mc/AsmExpr.cpp b/tools/llvm-mc/AsmExpr.cpp new file mode 100644 index 0000000..c3362e4 --- /dev/null +++ b/tools/llvm-mc/AsmExpr.cpp @@ -0,0 +1,162 @@ +//===- AsmExpr.cpp - Assembly file expressions ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AsmExpr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +using namespace llvm; + +AsmExpr::~AsmExpr() { +} + +bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const { + MCValue Value; + + if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isAbsolute()) + return false; + + Res = Value.getConstant(); + return true; +} + +static bool EvaluateSymbolicAdd(const MCValue &LHS, MCSymbol *RHS_A, + MCSymbol *RHS_B, int64_t RHS_Cst, + MCValue &Res) { + // We can't add or subtract two symbols. + if ((LHS.getSymA() && RHS_A) || + (LHS.getSymB() && RHS_B)) + return false; + + MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A; + MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B; + if (B) { + // If we have a negated symbol, then we must have also have a non-negated + // symbol in order to encode the expression. We can do this check later to + // permit expressions which eventually fold to a representable form -- such + // as (a + (0 - b)) -- if necessary. + if (!A) + return false; + } + Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst); + return true; +} + +bool AsmExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const { + switch (getKind()) { + default: + assert(0 && "Invalid assembly expression kind!"); + + case Constant: + Res = MCValue::get(cast<AsmConstantExpr>(this)->getValue()); + return true; + + case SymbolRef: { + MCSymbol *Sym = cast<AsmSymbolRefExpr>(this)->getSymbol(); + if (const MCValue *Value = Ctx.GetSymbolValue(Sym)) + Res = *Value; + else + Res = MCValue::get(Sym, 0, 0); + return true; + } + + case Unary: { + const AsmUnaryExpr *AUE = cast<AsmUnaryExpr>(this); + MCValue Value; + + if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value)) + return false; + + switch (AUE->getOpcode()) { + case AsmUnaryExpr::LNot: + if (!Value.isAbsolute()) + return false; + Res = MCValue::get(!Value.getConstant()); + break; + case AsmUnaryExpr::Minus: + /// -(a - b + const) ==> (b - a - const) + if (Value.getSymA() && !Value.getSymA()) + return false; + Res = MCValue::get(Value.getSymB(), Value.getSymA(), + -Value.getConstant()); + break; + case AsmUnaryExpr::Not: + if (!Value.isAbsolute()) + return false; + Res = MCValue::get(~Value.getConstant()); + break; + case AsmUnaryExpr::Plus: + Res = Value; + break; + } + + return true; + } + + case Binary: { + const AsmBinaryExpr *ABE = cast<AsmBinaryExpr>(this); + MCValue LHSValue, RHSValue; + + if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) || + !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue)) + return false; + + // We only support a few operations on non-constant expressions, handle + // those first. + if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { + switch (ABE->getOpcode()) { + default: + return false; + case AsmBinaryExpr::Sub: + // Negate RHS and add. + return EvaluateSymbolicAdd(LHSValue, + RHSValue.getSymB(), RHSValue.getSymA(), + -RHSValue.getConstant(), + Res); + + case AsmBinaryExpr::Add: + return EvaluateSymbolicAdd(LHSValue, + RHSValue.getSymA(), RHSValue.getSymB(), + RHSValue.getConstant(), + Res); + } + } + + // FIXME: We need target hooks for the evaluation. It may be limited in + // width, and gas defines the result of comparisons differently from Apple + // as (the result is sign extended). + int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); + int64_t Result = 0; + switch (ABE->getOpcode()) { + case AsmBinaryExpr::Add: Result = LHS + RHS; break; + case AsmBinaryExpr::And: Result = LHS & RHS; break; + case AsmBinaryExpr::Div: Result = LHS / RHS; break; + case AsmBinaryExpr::EQ: Result = LHS == RHS; break; + case AsmBinaryExpr::GT: Result = LHS > RHS; break; + case AsmBinaryExpr::GTE: Result = LHS >= RHS; break; + case AsmBinaryExpr::LAnd: Result = LHS && RHS; break; + case AsmBinaryExpr::LOr: Result = LHS || RHS; break; + case AsmBinaryExpr::LT: Result = LHS < RHS; break; + case AsmBinaryExpr::LTE: Result = LHS <= RHS; break; + case AsmBinaryExpr::Mod: Result = LHS % RHS; break; + case AsmBinaryExpr::Mul: Result = LHS * RHS; break; + case AsmBinaryExpr::NE: Result = LHS != RHS; break; + case AsmBinaryExpr::Or: Result = LHS | RHS; break; + case AsmBinaryExpr::Shl: Result = LHS << RHS; break; + case AsmBinaryExpr::Shr: Result = LHS >> RHS; break; + case AsmBinaryExpr::Sub: Result = LHS - RHS; break; + case AsmBinaryExpr::Xor: Result = LHS ^ RHS; break; + } + + Res = MCValue::get(Result); + return true; + } + } +} + diff --git a/tools/llvm-mc/AsmExpr.h b/tools/llvm-mc/AsmExpr.h new file mode 100644 index 0000000..84e58ff --- /dev/null +++ b/tools/llvm-mc/AsmExpr.h @@ -0,0 +1,179 @@ +//===- AsmExpr.h - Assembly file expressions --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMEXPR_H +#define ASMEXPR_H + +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class MCContext; +class MCSymbol; +class MCValue; + +/// AsmExpr - Base class for the full range of assembler expressions which are +/// needed for parsing. +class AsmExpr { +public: + enum AsmExprKind { + Binary, ///< Binary expressions. + Constant, ///< Constant expressions. + SymbolRef, ///< References to labels and assigned expressions. + Unary ///< Unary expressions. + }; + +private: + AsmExprKind Kind; + +protected: + AsmExpr(AsmExprKind _Kind) : Kind(_Kind) {} + +public: + virtual ~AsmExpr(); + + AsmExprKind getKind() const { return Kind; } + + /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value. + /// + /// @param Res - The absolute value, if evaluation succeeds. + /// @result - True on success. + bool EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const; + + /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable + /// value, i.e. an expression of the fixed form (a - b + constant). + /// + /// @param Res - The relocatable value, if evaluation succeeds. + /// @result - True on success. + bool EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const; + + static bool classof(const AsmExpr *) { return true; } +}; + +//// AsmConstantExpr - Represent a constant integer expression. +class AsmConstantExpr : public AsmExpr { + int64_t Value; + +public: + AsmConstantExpr(int64_t _Value) + : AsmExpr(AsmExpr::Constant), Value(_Value) {} + + int64_t getValue() const { return Value; } + + static bool classof(const AsmExpr *E) { + return E->getKind() == AsmExpr::Constant; + } + static bool classof(const AsmConstantExpr *) { return true; } +}; + +/// AsmSymbolRefExpr - Represent a reference to a symbol from inside an +/// expression. +/// +/// A symbol reference in an expression may be a use of a label, a use of an +/// assembler variable (defined constant), or constitute an implicit definition +/// of the symbol as external. +class AsmSymbolRefExpr : public AsmExpr { + MCSymbol *Symbol; + +public: + AsmSymbolRefExpr(MCSymbol *_Symbol) + : AsmExpr(AsmExpr::SymbolRef), Symbol(_Symbol) {} + + MCSymbol *getSymbol() const { return Symbol; } + + static bool classof(const AsmExpr *E) { + return E->getKind() == AsmExpr::SymbolRef; + } + static bool classof(const AsmSymbolRefExpr *) { return true; } +}; + +/// AsmUnaryExpr - Unary assembler expressions. +class AsmUnaryExpr : public AsmExpr { +public: + enum Opcode { + LNot, ///< Logical negation. + Minus, ///< Unary minus. + Not, ///< Bitwise negation. + Plus ///< Unary plus. + }; + +private: + Opcode Op; + AsmExpr *Expr; + +public: + AsmUnaryExpr(Opcode _Op, AsmExpr *_Expr) + : AsmExpr(AsmExpr::Unary), Op(_Op), Expr(_Expr) {} + ~AsmUnaryExpr() { + delete Expr; + } + + Opcode getOpcode() const { return Op; } + + AsmExpr *getSubExpr() const { return Expr; } + + static bool classof(const AsmExpr *E) { + return E->getKind() == AsmExpr::Unary; + } + static bool classof(const AsmUnaryExpr *) { return true; } +}; + +/// AsmBinaryExpr - Binary assembler expressions. +class AsmBinaryExpr : public AsmExpr { +public: + enum Opcode { + Add, ///< Addition. + And, ///< Bitwise and. + Div, ///< Division. + EQ, ///< Equality comparison. + GT, ///< Greater than comparison. + GTE, ///< Greater than or equal comparison. + LAnd, ///< Logical and. + LOr, ///< Logical or. + LT, ///< Less than comparison. + LTE, ///< Less than or equal comparison. + Mod, ///< Modulus. + Mul, ///< Multiplication. + NE, ///< Inequality comparison. + Or, ///< Bitwise or. + Shl, ///< Bitwise shift left. + Shr, ///< Bitwise shift right. + Sub, ///< Subtraction. + Xor ///< Bitwise exclusive or. + }; + +private: + Opcode Op; + AsmExpr *LHS, *RHS; + +public: + AsmBinaryExpr(Opcode _Op, AsmExpr *_LHS, AsmExpr *_RHS) + : AsmExpr(AsmExpr::Binary), Op(_Op), LHS(_LHS), RHS(_RHS) {} + ~AsmBinaryExpr() { + delete LHS; + delete RHS; + } + + Opcode getOpcode() const { return Op; } + + /// getLHS - Get the left-hand side expression of the binary operator. + AsmExpr *getLHS() const { return LHS; } + + /// getRHS - Get the right-hand side expression of the binary operator. + AsmExpr *getRHS() const { return RHS; } + + static bool classof(const AsmExpr *E) { + return E->getKind() == AsmExpr::Binary; + } + static bool classof(const AsmBinaryExpr *) { return true; } +}; + +} // end namespace llvm + +#endif diff --git a/tools/llvm-mc/AsmLexer.cpp b/tools/llvm-mc/AsmLexer.cpp index db86825..7b744fb 100644 --- a/tools/llvm-mc/AsmLexer.cpp +++ b/tools/llvm-mc/AsmLexer.cpp @@ -42,14 +42,15 @@ SMLoc AsmLexer::getLoc() const { return SMLoc::getFromPointer(TokStart); } -void AsmLexer::PrintMessage(SMLoc Loc, const std::string &Msg) const { - SrcMgr.PrintMessage(Loc, Msg); +void AsmLexer::PrintMessage(SMLoc Loc, const std::string &Msg, + const char *Type) const { + SrcMgr.PrintMessage(Loc, Msg, Type); } /// ReturnError - Set the error to the specified string at the specified /// location. This is defined to always return asmtok::Error. asmtok::TokKind AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { - SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg); + SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); return asmtok::Error; } @@ -109,8 +110,11 @@ asmtok::TokKind AsmLexer::LexPercent() { /// LexSlash: Slash: / /// C-Style Comment: /* ... */ asmtok::TokKind AsmLexer::LexSlash() { - if (*CurPtr != '*') - return asmtok::Slash; + switch (*CurPtr) { + case '*': break; // C style comment. + case '/': return ++CurPtr, LexLineComment(); + default: return asmtok::Slash; + } // C Style comment. ++CurPtr; // skip the star. @@ -129,8 +133,9 @@ asmtok::TokKind AsmLexer::LexSlash() { } } -/// LexHash: Comment: #[^\n]* -asmtok::TokKind AsmLexer::LexHash() { +/// LexLineComment: Comment: #[^\n]* +/// : //[^\n]* +asmtok::TokKind AsmLexer::LexLineComment() { int CurChar = getNextChar(); while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF) CurChar = getNextChar(); @@ -262,32 +267,43 @@ asmtok::TokKind AsmLexer::LexToken() { case '*': return asmtok::Star; case ',': return asmtok::Comma; case '$': return asmtok::Dollar; - case '=': return asmtok::Equal; - case '|': return asmtok::Pipe; + case '=': + if (*CurPtr == '=') + return ++CurPtr, asmtok::EqualEqual; + return asmtok::Equal; + case '|': + if (*CurPtr == '|') + return ++CurPtr, asmtok::PipePipe; + return asmtok::Pipe; case '^': return asmtok::Caret; - case '&': return asmtok::Amp; - case '!': return asmtok::Exclaim; + case '&': + if (*CurPtr == '&') + return ++CurPtr, asmtok::AmpAmp; + return asmtok::Amp; + case '!': + if (*CurPtr == '=') + return ++CurPtr, asmtok::ExclaimEqual; + return asmtok::Exclaim; case '%': return LexPercent(); case '/': return LexSlash(); - case '#': return LexHash(); + case '#': return LexLineComment(); case '"': return LexQuote(); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return LexDigit(); case '<': - if (*CurPtr == '<') { - ++CurPtr; - return asmtok::LessLess; + switch (*CurPtr) { + case '<': return ++CurPtr, asmtok::LessLess; + case '=': return ++CurPtr, asmtok::LessEqual; + case '>': return ++CurPtr, asmtok::LessGreater; + default: return asmtok::Less; } - // Don't have any use for bare '<' yet. - return ReturnError(TokStart, "invalid character in input"); case '>': - if (*CurPtr == '>') { - ++CurPtr; - return asmtok::GreaterGreater; + switch (*CurPtr) { + case '>': return ++CurPtr, asmtok::GreaterGreater; + case '=': return ++CurPtr, asmtok::GreaterEqual; + default: return asmtok::Greater; } - // Don't have any use for bare '>' yet. - return ReturnError(TokStart, "invalid character in input"); // TODO: Quoted identifiers (objc methods etc) // local labels: [0-9][:] diff --git a/tools/llvm-mc/AsmLexer.h b/tools/llvm-mc/AsmLexer.h index 19a1b38..6360b12 100644 --- a/tools/llvm-mc/AsmLexer.h +++ b/tools/llvm-mc/AsmLexer.h @@ -42,10 +42,12 @@ namespace asmtok { Plus, Minus, Tilde, Slash, // '/' LParen, RParen, - Star, Comma, Dollar, Equal, + Star, Comma, Dollar, Equal, EqualEqual, - Pipe, Caret, Amp, Exclaim, - Percent, LessLess, GreaterGreater + Pipe, PipePipe, Caret, + Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, + Less, LessEqual, LessLess, LessGreater, + Greater, GreaterEqual, GreaterGreater }; } @@ -95,7 +97,7 @@ public: SMLoc getLoc() const; - void PrintMessage(SMLoc Loc, const std::string &Msg) const; + void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const; private: int getNextChar(); @@ -106,7 +108,7 @@ private: asmtok::TokKind LexIdentifier(); asmtok::TokKind LexPercent(); asmtok::TokKind LexSlash(); - asmtok::TokKind LexHash(); + asmtok::TokKind LexLineComment(); asmtok::TokKind LexDigit(); asmtok::TokKind LexQuote(); }; diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp index 2b697a6..f5bf589 100644 --- a/tools/llvm-mc/AsmParser.cpp +++ b/tools/llvm-mc/AsmParser.cpp @@ -12,20 +12,27 @@ //===----------------------------------------------------------------------===// #include "AsmParser.h" + +#include "AsmExpr.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +void AsmParser::Warning(SMLoc L, const char *Msg) { + Lexer.PrintMessage(L, Msg, "warning"); +} + bool AsmParser::Error(SMLoc L, const char *Msg) { - Lexer.PrintMessage(L, Msg); + Lexer.PrintMessage(L, Msg, "error"); return true; } bool AsmParser::TokError(const char *Msg) { - Lexer.PrintMessage(Lexer.getLoc(), Msg); + Lexer.PrintMessage(Lexer.getLoc(), Msg, "error"); return true; } @@ -33,11 +40,18 @@ bool AsmParser::Run() { // Prime the lexer. Lexer.Lex(); - while (Lexer.isNot(asmtok::Eof)) - if (ParseStatement()) - return true; + bool HadError = false; - return false; + // While we have input, parse each statement. + while (Lexer.isNot(asmtok::Eof)) { + if (!ParseStatement()) continue; + + // If we had an error, remember it and recover by skipping to the next line. + HadError = true; + EatToEndOfStatement(); + } + + return HadError; } /// EatToEndOfStatement - Throw away the rest of the line for testing purposes. @@ -57,7 +71,7 @@ void AsmParser::EatToEndOfStatement() { /// /// parenexpr ::= expr) /// -bool AsmParser::ParseParenExpr(int64_t &Res) { +bool AsmParser::ParseParenExpr(AsmExpr *&Res) { if (ParseExpression(Res)) return true; if (Lexer.isNot(asmtok::RParen)) return TokError("expected ')' in parentheses expression"); @@ -70,28 +84,54 @@ bool AsmParser::ParseParenExpr(int64_t &Res) { /// primaryexpr ::= symbol /// primaryexpr ::= number /// primaryexpr ::= ~,+,- primaryexpr -bool AsmParser::ParsePrimaryExpr(int64_t &Res) { +bool AsmParser::ParsePrimaryExpr(AsmExpr *&Res) { switch (Lexer.getKind()) { default: return TokError("unknown token in expression"); - case asmtok::Identifier: + case asmtok::Exclaim: + Lexer.Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res)) + return true; + Res = new AsmUnaryExpr(AsmUnaryExpr::LNot, Res); + return false; + case asmtok::Identifier: { // This is a label, this should be parsed as part of an expression, to - // handle things like LFOO+4 - Res = 0; // FIXME. + // handle things like LFOO+4. + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal()); + + // If this is use of an undefined symbol then mark it external. + if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym)) + Sym->setExternal(true); + + Res = new AsmSymbolRefExpr(Sym); Lexer.Lex(); // Eat identifier. return false; + } case asmtok::IntVal: - Res = Lexer.getCurIntVal(); + Res = new AsmConstantExpr(Lexer.getCurIntVal()); Lexer.Lex(); // Eat identifier. return false; case asmtok::LParen: Lexer.Lex(); // Eat the '('. return ParseParenExpr(Res); - case asmtok::Tilde: - case asmtok::Plus: case asmtok::Minus: Lexer.Lex(); // Eat the operator. - return ParsePrimaryExpr(Res); + if (ParsePrimaryExpr(Res)) + return true; + Res = new AsmUnaryExpr(AsmUnaryExpr::Minus, Res); + return false; + case asmtok::Plus: + Lexer.Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res)) + return true; + Res = new AsmUnaryExpr(AsmUnaryExpr::Plus, Res); + return false; + case asmtok::Tilde: + Lexer.Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res)) + return true; + Res = new AsmUnaryExpr(AsmUnaryExpr::Not, Res); + return false; } } @@ -102,59 +142,152 @@ bool AsmParser::ParsePrimaryExpr(int64_t &Res) { /// expr ::= expr *,/,%,<<,>> expr -> highest. /// expr ::= primaryexpr /// -bool AsmParser::ParseExpression(int64_t &Res) { +bool AsmParser::ParseExpression(AsmExpr *&Res) { + Res = 0; return ParsePrimaryExpr(Res) || ParseBinOpRHS(1, Res); } -static unsigned getBinOpPrecedence(asmtok::TokKind K) { +bool AsmParser::ParseAbsoluteExpression(int64_t &Res) { + AsmExpr *Expr; + + SMLoc StartLoc = Lexer.getLoc(); + if (ParseExpression(Expr)) + return true; + + if (!Expr->EvaluateAsAbsolute(Ctx, Res)) + return Error(StartLoc, "expected absolute expression"); + + return false; +} + +bool AsmParser::ParseRelocatableExpression(MCValue &Res) { + AsmExpr *Expr; + + SMLoc StartLoc = Lexer.getLoc(); + if (ParseExpression(Expr)) + return true; + + if (!Expr->EvaluateAsRelocatable(Ctx, Res)) + return Error(StartLoc, "expected relocatable expression"); + + return false; +} + +bool AsmParser::ParseParenRelocatableExpression(MCValue &Res) { + AsmExpr *Expr; + + SMLoc StartLoc = Lexer.getLoc(); + if (ParseParenExpr(Expr)) + return true; + + if (!Expr->EvaluateAsRelocatable(Ctx, Res)) + return Error(StartLoc, "expected relocatable expression"); + + return false; +} + +static unsigned getBinOpPrecedence(asmtok::TokKind K, + AsmBinaryExpr::Opcode &Kind) { switch (K) { default: return 0; // not a binop. + + // Lowest Precedence: &&, || + case asmtok::AmpAmp: + Kind = AsmBinaryExpr::LAnd; + return 1; + case asmtok::PipePipe: + Kind = AsmBinaryExpr::LOr; + return 1; + + // Low Precedence: +, -, ==, !=, <>, <, <=, >, >= case asmtok::Plus: + Kind = AsmBinaryExpr::Add; + return 2; case asmtok::Minus: - return 1; + Kind = AsmBinaryExpr::Sub; + return 2; + case asmtok::EqualEqual: + Kind = AsmBinaryExpr::EQ; + return 2; + case asmtok::ExclaimEqual: + case asmtok::LessGreater: + Kind = AsmBinaryExpr::NE; + return 2; + case asmtok::Less: + Kind = AsmBinaryExpr::LT; + return 2; + case asmtok::LessEqual: + Kind = AsmBinaryExpr::LTE; + return 2; + case asmtok::Greater: + Kind = AsmBinaryExpr::GT; + return 2; + case asmtok::GreaterEqual: + Kind = AsmBinaryExpr::GTE; + return 2; + + // Intermediate Precedence: |, &, ^ + // + // FIXME: gas seems to support '!' as an infix operator? case asmtok::Pipe: + Kind = AsmBinaryExpr::Or; + return 3; case asmtok::Caret: + Kind = AsmBinaryExpr::Xor; + return 3; case asmtok::Amp: - case asmtok::Exclaim: - return 2; + Kind = AsmBinaryExpr::And; + return 3; + + // Highest Precedence: *, /, %, <<, >> case asmtok::Star: + Kind = AsmBinaryExpr::Mul; + return 4; case asmtok::Slash: + Kind = AsmBinaryExpr::Div; + return 4; case asmtok::Percent: + Kind = AsmBinaryExpr::Mod; + return 4; case asmtok::LessLess: + Kind = AsmBinaryExpr::Shl; + return 4; case asmtok::GreaterGreater: - return 3; + Kind = AsmBinaryExpr::Shr; + return 4; } } /// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'. /// Res contains the LHS of the expression on input. -bool AsmParser::ParseBinOpRHS(unsigned Precedence, int64_t &Res) { +bool AsmParser::ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res) { while (1) { - unsigned TokPrec = getBinOpPrecedence(Lexer.getKind()); + AsmBinaryExpr::Opcode Kind = AsmBinaryExpr::Add; + unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); // If the next token is lower precedence than we are allowed to eat, return // successfully with what we ate already. if (TokPrec < Precedence) return false; - //asmtok::TokKind BinOp = Lexer.getKind(); Lexer.Lex(); // Eat the next primary expression. - int64_t RHS; + AsmExpr *RHS; if (ParsePrimaryExpr(RHS)) return true; // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. - unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind()); + AsmBinaryExpr::Opcode Dummy; + unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); if (TokPrec < NextTokPrec) { if (ParseBinOpRHS(Precedence+1, RHS)) return true; } - // Merge LHS/RHS: fixme use the right operator etc. - Res += RHS; + // Merge LHS and RHS according to operator. + Res = new AsmBinaryExpr(Kind, Res, RHS); } } @@ -183,16 +316,28 @@ bool AsmParser::ParseStatement() { // Consume the identifier, see what is after it. switch (Lexer.Lex()) { - case asmtok::Colon: + case asmtok::Colon: { // identifier ':' -> Label. Lexer.Lex(); + + // Diagnose attempt to use a variable as a label. + // + // FIXME: Diagnostics. Note the location of the definition as a label. + // FIXME: This doesn't diagnose assignment to a symbol which has been + // implicitly marked as external. + MCSymbol *Sym = Ctx.GetOrCreateSymbol(IDVal); + if (Sym->getSection()) + return Error(IDLoc, "invalid symbol redefinition"); + if (Ctx.GetSymbolValue(Sym)) + return Error(IDLoc, "symbol already used as assembler variable"); // Since we saw a label, create a symbol and emit it. // FIXME: If the label starts with L it is an assembler temporary label. // Why does the client of this api need to know this? - Out.EmitLabel(Ctx.GetOrCreateSymbol(IDVal)); - + Out.EmitLabel(Sym); + return ParseStatement(); + } case asmtok::Equal: // identifier '=' ... -> assignment statement @@ -322,20 +467,66 @@ bool AsmParser::ParseStatement() { return ParseDirectiveValue(4); if (!strcmp(IDVal, ".quad")) return ParseDirectiveValue(8); - if (!strcmp(IDVal, ".fill")) - return ParseDirectiveFill(); + + // FIXME: Target hooks for IsPow2. + if (!strcmp(IDVal, ".align")) + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); + if (!strcmp(IDVal, ".align32")) + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); + if (!strcmp(IDVal, ".balign")) + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1); + if (!strcmp(IDVal, ".balignw")) + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2); + if (!strcmp(IDVal, ".balignl")) + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4); + if (!strcmp(IDVal, ".p2align")) + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); + if (!strcmp(IDVal, ".p2alignw")) + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); + if (!strcmp(IDVal, ".p2alignl")) + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); + if (!strcmp(IDVal, ".org")) return ParseDirectiveOrg(); + + if (!strcmp(IDVal, ".fill")) + return ParseDirectiveFill(); if (!strcmp(IDVal, ".space")) return ParseDirectiveSpace(); - Lexer.PrintMessage(IDLoc, "warning: ignoring directive for now"); + // Symbol attribute directives + if (!strcmp(IDVal, ".globl") || !strcmp(IDVal, ".global")) + return ParseDirectiveSymbolAttribute(MCStreamer::Global); + if (!strcmp(IDVal, ".hidden")) + return ParseDirectiveSymbolAttribute(MCStreamer::Hidden); + if (!strcmp(IDVal, ".indirect_symbol")) + return ParseDirectiveSymbolAttribute(MCStreamer::IndirectSymbol); + if (!strcmp(IDVal, ".internal")) + return ParseDirectiveSymbolAttribute(MCStreamer::Internal); + if (!strcmp(IDVal, ".lazy_reference")) + return ParseDirectiveSymbolAttribute(MCStreamer::LazyReference); + if (!strcmp(IDVal, ".no_dead_strip")) + return ParseDirectiveSymbolAttribute(MCStreamer::NoDeadStrip); + if (!strcmp(IDVal, ".private_extern")) + return ParseDirectiveSymbolAttribute(MCStreamer::PrivateExtern); + if (!strcmp(IDVal, ".protected")) + return ParseDirectiveSymbolAttribute(MCStreamer::Protected); + if (!strcmp(IDVal, ".reference")) + return ParseDirectiveSymbolAttribute(MCStreamer::Reference); + if (!strcmp(IDVal, ".weak")) + return ParseDirectiveSymbolAttribute(MCStreamer::Weak); + if (!strcmp(IDVal, ".weak_definition")) + return ParseDirectiveSymbolAttribute(MCStreamer::WeakDefinition); + if (!strcmp(IDVal, ".weak_reference")) + return ParseDirectiveSymbolAttribute(MCStreamer::WeakReference); + + Warning(IDLoc, "ignoring directive for now"); EatToEndOfStatement(); return false; } MCInst Inst; - if (ParseX86InstOperands(Inst)) + if (ParseX86InstOperands(IDVal, Inst)) return true; if (Lexer.isNot(asmtok::EndOfStatement)) @@ -345,16 +536,18 @@ bool AsmParser::ParseStatement() { Lexer.Lex(); // Instruction is good, process it. - outs() << "Found instruction: " << IDVal << " with " << Inst.getNumOperands() - << " operands.\n"; + Out.EmitInstruction(Inst); // Skip to end of line for now. return false; } bool AsmParser::ParseAssignment(const char *Name, bool IsDotSet) { - int64_t Value; - if (ParseExpression(Value)) + // FIXME: Use better location, we should use proper tokens. + SMLoc EqualLoc = Lexer.getLoc(); + + MCValue Value; + if (ParseRelocatableExpression(Value)) return true; if (Lexer.isNot(asmtok::EndOfStatement)) @@ -363,10 +556,21 @@ bool AsmParser::ParseAssignment(const char *Name, bool IsDotSet) { // Eat the end of statement marker. Lexer.Lex(); - // Get the symbol for this name. + // Diagnose assignment to a label. + // + // FIXME: Diagnostics. Note the location of the definition as a label. + // FIXME: This doesn't diagnose assignment to a symbol which has been + // implicitly marked as external. // FIXME: Handle '.'. + // FIXME: Diagnose assignment to protected identifier (e.g., register name). MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); - Out.EmitAssignment(Sym, MCValue::get(Value), IsDotSet); + if (Sym->getSection()) + return Error(EqualLoc, "invalid assignment to symbol emitted as a label"); + if (Sym->isExternal()) + return Error(EqualLoc, "invalid assignment to external symbol"); + + // Do the assignment. + Out.EmitAssignment(Sym, Value, IsDotSet); return false; } @@ -433,7 +637,7 @@ bool AsmParser::ParseDirectiveSectionSwitch(const char *Section, } /// ParseDirectiveAscii: -/// ::= ( .ascii | .asciiz ) [ "string" ( , "string" )* ] +/// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ] bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) { if (Lexer.isNot(asmtok::EndOfStatement)) { for (;;) { @@ -468,11 +672,11 @@ bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) { bool AsmParser::ParseDirectiveValue(unsigned Size) { if (Lexer.isNot(asmtok::EndOfStatement)) { for (;;) { - int64_t Expr; - if (ParseExpression(Expr)) + MCValue Expr; + if (ParseRelocatableExpression(Expr)) return true; - Out.EmitValue(MCValue::get(Expr), Size); + Out.EmitValue(Expr, Size); if (Lexer.is(asmtok::EndOfStatement)) break; @@ -492,7 +696,7 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) { /// ::= .space expression [ , expression ] bool AsmParser::ParseDirectiveSpace() { int64_t NumBytes; - if (ParseExpression(NumBytes)) + if (ParseAbsoluteExpression(NumBytes)) return true; int64_t FillExpr = 0; @@ -502,7 +706,7 @@ bool AsmParser::ParseDirectiveSpace() { return TokError("unexpected token in '.space' directive"); Lexer.Lex(); - if (ParseExpression(FillExpr)) + if (ParseAbsoluteExpression(FillExpr)) return true; HasFillExpr = true; @@ -527,7 +731,7 @@ bool AsmParser::ParseDirectiveSpace() { /// ::= .fill expression , expression , expression bool AsmParser::ParseDirectiveFill() { int64_t NumValues; - if (ParseExpression(NumValues)) + if (ParseAbsoluteExpression(NumValues)) return true; if (Lexer.isNot(asmtok::Comma)) @@ -535,7 +739,7 @@ bool AsmParser::ParseDirectiveFill() { Lexer.Lex(); int64_t FillSize; - if (ParseExpression(FillSize)) + if (ParseAbsoluteExpression(FillSize)) return true; if (Lexer.isNot(asmtok::Comma)) @@ -543,7 +747,7 @@ bool AsmParser::ParseDirectiveFill() { Lexer.Lex(); int64_t FillExpr; - if (ParseExpression(FillExpr)) + if (ParseAbsoluteExpression(FillExpr)) return true; if (Lexer.isNot(asmtok::EndOfStatement)) @@ -563,8 +767,8 @@ bool AsmParser::ParseDirectiveFill() { /// ParseDirectiveOrg /// ::= .org expression [ , expression ] bool AsmParser::ParseDirectiveOrg() { - int64_t Offset; - if (ParseExpression(Offset)) + MCValue Offset; + if (ParseRelocatableExpression(Offset)) return true; // Parse optional fill expression. @@ -574,7 +778,7 @@ bool AsmParser::ParseDirectiveOrg() { return TokError("unexpected token in '.org' directive"); Lexer.Lex(); - if (ParseExpression(FillExpr)) + if (ParseAbsoluteExpression(FillExpr)) return true; if (Lexer.isNot(asmtok::EndOfStatement)) @@ -582,8 +786,113 @@ bool AsmParser::ParseDirectiveOrg() { } Lexer.Lex(); - - Out.EmitValueToOffset(MCValue::get(Offset), FillExpr); + + // FIXME: Only limited forms of relocatable expressions are accepted here, it + // has to be relative to the current section. + Out.EmitValueToOffset(Offset, FillExpr); + + return false; +} + +/// ParseDirectiveAlign +/// ::= {.align, ...} expression [ , expression [ , expression ]] +bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { + int64_t Alignment; + if (ParseAbsoluteExpression(Alignment)) + return true; + + SMLoc MaxBytesLoc; + bool HasFillExpr = false; + int64_t FillExpr = 0; + int64_t MaxBytesToFill = 0; + if (Lexer.isNot(asmtok::EndOfStatement)) { + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in directive"); + Lexer.Lex(); + + // The fill expression can be omitted while specifying a maximum number of + // alignment bytes, e.g: + // .align 3,,4 + if (Lexer.isNot(asmtok::Comma)) { + HasFillExpr = true; + if (ParseAbsoluteExpression(FillExpr)) + return true; + } + + if (Lexer.isNot(asmtok::EndOfStatement)) { + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in directive"); + Lexer.Lex(); + + MaxBytesLoc = Lexer.getLoc(); + if (ParseAbsoluteExpression(MaxBytesToFill)) + return true; + + if (Lexer.isNot(asmtok::EndOfStatement)) + return TokError("unexpected token in directive"); + } + } + + Lexer.Lex(); + + if (!HasFillExpr) { + // FIXME: Sometimes fill with nop. + FillExpr = 0; + } + + // Compute alignment in bytes. + if (IsPow2) { + // FIXME: Diagnose overflow. + Alignment = 1 << Alignment; + } + + // Diagnose non-sensical max bytes to fill. + if (MaxBytesLoc.isValid()) { + if (MaxBytesToFill < 1) { + Warning(MaxBytesLoc, "alignment directive can never be satisfied in this " + "many bytes, ignoring"); + return false; + } + + if (MaxBytesToFill >= Alignment) { + Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and " + "has no effect"); + MaxBytesToFill = 0; + } + } + + // FIXME: Target specific behavior about how the "extra" bytes are filled. + Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill); return false; } + +/// ParseDirectiveSymbolAttribute +/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] +bool AsmParser::ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr) { + if (Lexer.isNot(asmtok::EndOfStatement)) { + for (;;) { + if (Lexer.isNot(asmtok::Identifier)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal()); + Lexer.Lex(); + + // If this is use of an undefined symbol then mark it external. + if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym)) + Sym->setExternal(true); + + Out.EmitSymbolAttribute(Sym, Attr); + + if (Lexer.is(asmtok::EndOfStatement)) + break; + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in directive"); + Lexer.Lex(); + } + } + + Lexer.Lex(); + return false; +} diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h index da256c2..333b284 100644 --- a/tools/llvm-mc/AsmParser.h +++ b/tools/llvm-mc/AsmParser.h @@ -15,19 +15,24 @@ #define ASMPARSER_H #include "AsmLexer.h" +#include "llvm/MC/MCStreamer.h" namespace llvm { +class AsmExpr; class MCContext; class MCInst; class MCStreamer; - +class MCValue; + class AsmParser { +public: + struct X86Operand; + +private: AsmLexer Lexer; MCContext &Ctx; MCStreamer &Out; - struct X86Operand; - public: AsmParser(SourceMgr &SM, MCContext &ctx, MCStreamer &OutStr) : Lexer(SM), Ctx(ctx), Out(OutStr) {} @@ -37,22 +42,56 @@ public: private: bool ParseStatement(); - + + void Warning(SMLoc L, const char *Msg); bool Error(SMLoc L, const char *Msg); bool TokError(const char *Msg); void EatToEndOfStatement(); bool ParseAssignment(const char *Name, bool IsDotSet); - bool ParseExpression(int64_t &Res); - bool ParsePrimaryExpr(int64_t &Res); - bool ParseBinOpRHS(unsigned Precedence, int64_t &Res); - bool ParseParenExpr(int64_t &Res); + + /// ParseExpression - Parse a general assembly expression. + /// + /// @param Res - The resulting expression. The pointer value is null on error. + /// @result - False on success. + bool ParseExpression(AsmExpr *&Res); + + /// ParseAbsoluteExpression - Parse an expression which must evaluate to an + /// absolute value. + /// + /// @param Res - The value of the absolute expression. The result is undefined + /// on error. + /// @result - False on success. + bool ParseAbsoluteExpression(int64_t &Res); + + /// ParseRelocatableExpression - Parse an expression which must be + /// relocatable. + /// + /// @param Res - The relocatable expression value. The result is undefined on + /// error. + /// @result - False on success. + bool ParseRelocatableExpression(MCValue &Res); + + /// ParseParenRelocatableExpression - Parse an expression which must be + /// relocatable, assuming that an initial '(' has already been consumed. + /// + /// @param Res - The relocatable expression value. The result is undefined on + /// error. + /// @result - False on success. + /// + /// @see ParseRelocatableExpression, ParseParenExpr. + bool ParseParenRelocatableExpression(MCValue &Res); + + bool ParsePrimaryExpr(AsmExpr *&Res); + bool ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res); + bool ParseParenExpr(AsmExpr *&Res); // X86 specific. - bool ParseX86InstOperands(MCInst &Inst); + bool ParseX86InstOperands(const char *InstName, MCInst &Inst); bool ParseX86Operand(X86Operand &Op); bool ParseX86MemOperand(X86Operand &Op); + bool ParseX86Register(X86Operand &Op); // Directive Parsing. bool ParseDirectiveDarwinSection(); // Darwin specific ".section". @@ -64,6 +103,12 @@ private: bool ParseDirectiveSpace(); // ".space" bool ParseDirectiveSet(); // ".set" bool ParseDirectiveOrg(); // ".org" + // ".align{,32}", ".p2align{,w,l}" + bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize); + + /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which + /// accepts a single symbol (which should be a label or an external). + bool ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr); }; diff --git a/tools/llvm-mc/CMakeLists.txt b/tools/llvm-mc/CMakeLists.txt index 2dd878d..b21a4b1 100644 --- a/tools/llvm-mc/CMakeLists.txt +++ b/tools/llvm-mc/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS support MC) add_llvm_tool(llvm-mc llvm-mc.cpp + AsmExpr.cpp AsmLexer.cpp AsmParser.cpp MC-X86Specific.cpp diff --git a/tools/llvm-mc/MC-X86Specific.cpp b/tools/llvm-mc/MC-X86Specific.cpp index 45774cf..fec13ce 100644 --- a/tools/llvm-mc/MC-X86Specific.cpp +++ b/tools/llvm-mc/MC-X86Specific.cpp @@ -14,6 +14,7 @@ #include "AsmParser.h" #include "llvm/MC/MCInst.h" +#include "llvm/Support/SourceMgr.h" using namespace llvm; /// X86Operand - Instances of this class represent one X86 machine instruction. @@ -30,78 +31,91 @@ struct AsmParser::X86Operand { } Reg; struct { - // FIXME: Should be a general expression. - int64_t Val; + MCValue Val; } Imm; struct { unsigned SegReg; - int64_t Disp; // FIXME: Should be a general expression. + MCValue Disp; unsigned BaseReg; + unsigned IndexReg; unsigned Scale; - unsigned ScaleReg; } Mem; }; + unsigned getReg() const { + assert(Kind == Register && "Invalid access!"); + return Reg.RegNo; + } + static X86Operand CreateReg(unsigned RegNo) { X86Operand Res; Res.Kind = Register; Res.Reg.RegNo = RegNo; return Res; } - static X86Operand CreateImm(int64_t Val) { + static X86Operand CreateImm(MCValue Val) { X86Operand Res; Res.Kind = Immediate; Res.Imm.Val = Val; return Res; } - static X86Operand CreateMem(unsigned SegReg, int64_t Disp, unsigned BaseReg, - unsigned Scale, unsigned ScaleReg) { + static X86Operand CreateMem(unsigned SegReg, MCValue Disp, unsigned BaseReg, + unsigned IndexReg, unsigned Scale) { + // If there is no index register, we should never have a scale, and we + // should always have a scale (in {1,2,4,8}) if we do. + assert(((Scale == 0 && !IndexReg) || + (IndexReg && (Scale == 1 || Scale == 2 || + Scale == 4 || Scale == 8))) && + "Invalid scale!"); X86Operand Res; Res.Kind = Memory; Res.Mem.SegReg = SegReg; Res.Mem.Disp = Disp; Res.Mem.BaseReg = BaseReg; + Res.Mem.IndexReg = IndexReg; Res.Mem.Scale = Scale; - Res.Mem.ScaleReg = ScaleReg; return Res; } - - void AddToMCInst(MCInst &I) { - // FIXME: Add in x86 order here. - } }; +bool AsmParser::ParseX86Register(X86Operand &Op) { + assert(Lexer.getKind() == asmtok::Register && "Invalid token kind!"); + + // FIXME: Decode register number. + Op = X86Operand::CreateReg(123); + Lexer.Lex(); // Eat register token. + + return false; +} + bool AsmParser::ParseX86Operand(X86Operand &Op) { switch (Lexer.getKind()) { default: return ParseX86MemOperand(Op); case asmtok::Register: - // FIXME: Decode reg #. // FIXME: if a segment register, this could either be just the seg reg, or // the start of a memory operand. - Op = X86Operand::CreateReg(123); - Lexer.Lex(); // Eat register. - return false; + return ParseX86Register(Op); case asmtok::Dollar: { // $42 -> immediate. Lexer.Lex(); - int64_t Val; - if (ParseExpression(Val)) - return TokError("expected integer constant"); - Op = X86Operand::CreateReg(Val); + MCValue Val; + if (ParseRelocatableExpression(Val)) + return true; + Op = X86Operand::CreateImm(Val); return false; - case asmtok::Star: + } + case asmtok::Star: { Lexer.Lex(); // Eat the star. if (Lexer.is(asmtok::Register)) { - Op = X86Operand::CreateReg(123); - Lexer.Lex(); // Eat register. + if (ParseX86Register(Op)) + return true; } else if (ParseX86MemOperand(Op)) return true; - // FIXME: Note that these are 'dereferenced' so that clients know the '*' is - // there. + // FIXME: Note the '*' in the operand for use by the matcher. return false; } } @@ -116,9 +130,9 @@ bool AsmParser::ParseX86MemOperand(X86Operand &Op) { // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The // only way to do this without lookahead is to eat the ( and see what is after // it. - int64_t Disp = 0; + MCValue Disp = MCValue::get(0, 0, 0); if (Lexer.isNot(asmtok::LParen)) { - if (ParseExpression(Disp)) return true; + if (ParseRelocatableExpression(Disp)) return true; // After parsing the base expression we could either have a parenthesized // memory address or not. If not, return now. If so, eat the (. @@ -139,8 +153,7 @@ bool AsmParser::ParseX86MemOperand(X86Operand &Op) { // memory operand consumed. } else { // It must be an parenthesized expression, parse it now. - if (ParseParenExpr(Disp) || - ParseBinOpRHS(1, Disp)) + if (ParseParenRelocatableExpression(Disp)) return true; // After parsing the base expression we could either have a parenthesized @@ -157,33 +170,57 @@ bool AsmParser::ParseX86MemOperand(X86Operand &Op) { // If we reached here, then we just ate the ( of the memory operand. Process // the rest of the memory operand. - unsigned BaseReg = 0, ScaleReg = 0, Scale = 0; + unsigned BaseReg = 0, IndexReg = 0, Scale = 0; if (Lexer.is(asmtok::Register)) { - BaseReg = 123; // FIXME: decode reg # - Lexer.Lex(); // eat the register. + if (ParseX86Register(Op)) + return true; + BaseReg = Op.getReg(); } if (Lexer.is(asmtok::Comma)) { - Lexer.Lex(); // eat the comma. - + Lexer.Lex(); // Eat the comma. + + // Following the comma we should have either an index register, or a scale + // value. We don't support the later form, but we want to parse it + // correctly. + // + // Not that even though it would be completely consistent to support syntax + // like "1(%eax,,1)", the assembler doesn't. if (Lexer.is(asmtok::Register)) { - ScaleReg = 123; // FIXME: decode reg # - Lexer.Lex(); // eat the register. + if (ParseX86Register(Op)) + return true; + IndexReg = Op.getReg(); Scale = 1; // If not specified, the scale defaults to 1. - } - if (Lexer.is(asmtok::Comma)) { - Lexer.Lex(); // eat the comma. - - // If present, get and validate scale amount. - if (Lexer.is(asmtok::IntVal)) { - int64_t ScaleVal = Lexer.getCurIntVal(); - if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8) - return TokError("scale factor in address must be 1, 2, 4 or 8"); - Lexer.Lex(); // eat the scale. - Scale = (unsigned)ScaleVal; + if (Lexer.isNot(asmtok::RParen)) { + // Parse the scale amount: + // ::= ',' [scale-expression] + if (Lexer.isNot(asmtok::Comma)) + return true; + Lexer.Lex(); // Eat the comma. + + if (Lexer.isNot(asmtok::RParen)) { + int64_t ScaleVal; + if (ParseAbsoluteExpression(ScaleVal)) + return true; + + // Validate the scale amount. + if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8) + return TokError("scale factor in address must be 1, 2, 4 or 8"); + Scale = (unsigned)ScaleVal; + } } + } else if (Lexer.isNot(asmtok::RParen)) { + // Otherwise we have the unsupported form of a scale amount without an + // index. + SMLoc Loc = Lexer.getLoc(); + + int64_t Value; + if (ParseAbsoluteExpression(Value)) + return true; + + return Error(Loc, "cannot have scale factor without index register"); } } @@ -192,31 +229,38 @@ bool AsmParser::ParseX86MemOperand(X86Operand &Op) { return TokError("unexpected token in memory operand"); Lexer.Lex(); // Eat the ')'. - Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, Scale, ScaleReg); + Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale); + return false; +} + +/// MatchX86Inst - Convert a parsed instruction name and operand list into a +/// concrete instruction. +static bool MatchX86Inst(const char *Name, + llvm::SmallVector<AsmParser::X86Operand, 3> &Operands, + MCInst &Inst) { return false; } /// ParseX86InstOperands - Parse the operands of an X86 instruction and return /// them as the operands of an MCInst. -bool AsmParser::ParseX86InstOperands(MCInst &Inst) { - // If no operands are present, just return. - if (Lexer.is(asmtok::EndOfStatement)) - return false; +bool AsmParser::ParseX86InstOperands(const char *InstName, MCInst &Inst) { + llvm::SmallVector<X86Operand, 3> Operands; - // Read the first operand. - X86Operand Op; - if (ParseX86Operand(Op)) - return true; - Op.AddToMCInst(Inst); - - while (Lexer.is(asmtok::Comma)) { - Lexer.Lex(); // Eat the comma. - - // Parse and remember the operand. - Op = X86Operand(); - if (ParseX86Operand(Op)) + if (Lexer.isNot(asmtok::EndOfStatement)) { + // Read the first operand. + Operands.push_back(X86Operand()); + if (ParseX86Operand(Operands.back())) return true; - Op.AddToMCInst(Inst); + + while (Lexer.is(asmtok::Comma)) { + Lexer.Lex(); // Eat the comma. + + // Parse and remember the operand. + Operands.push_back(X86Operand()); + if (ParseX86Operand(Operands.back())) + return true; + } } - return false; + + return MatchX86Inst(InstName, Operands, Inst); } diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 4100cb1..b52edd1 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -80,7 +80,7 @@ static int AsLexInput(const char *ProgName) { while (Tok != asmtok::Eof) { switch (Tok) { default: - Lexer.PrintMessage(Lexer.getLoc(), "driver: unknown token"); + Lexer.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); Error = true; break; case asmtok::Error: @@ -98,17 +98,36 @@ static int AsLexInput(const char *ProgName) { case asmtok::IntVal: outs() << "int: " << Lexer.getCurIntVal() << '\n'; break; + + case asmtok::Amp: outs() << "Amp\n"; break; + case asmtok::AmpAmp: outs() << "AmpAmp\n"; break; + case asmtok::Caret: outs() << "Caret\n"; break; + case asmtok::Colon: outs() << "Colon\n"; break; + case asmtok::Comma: outs() << "Comma\n"; break; + case asmtok::Dollar: outs() << "Dollar\n"; break; case asmtok::EndOfStatement: outs() << "EndOfStatement\n"; break; - case asmtok::Colon: outs() << "Colon\n"; break; - case asmtok::Plus: outs() << "Plus\n"; break; - case asmtok::Minus: outs() << "Minus\n"; break; - case asmtok::Tilde: outs() << "Tilde\n"; break; - case asmtok::Slash: outs() << "Slash\n"; break; - case asmtok::LParen: outs() << "LParen\n"; break; - case asmtok::RParen: outs() << "RParen\n"; break; - case asmtok::Star: outs() << "Star\n"; break; - case asmtok::Comma: outs() << "Comma\n"; break; - case asmtok::Dollar: outs() << "Dollar\n"; break; + case asmtok::Eof: outs() << "Eof\n"; break; + case asmtok::Equal: outs() << "Equal\n"; break; + case asmtok::EqualEqual: outs() << "EqualEqual\n"; break; + case asmtok::Exclaim: outs() << "Exclaim\n"; break; + case asmtok::ExclaimEqual: outs() << "ExclaimEqual\n"; break; + case asmtok::Greater: outs() << "Greater\n"; break; + case asmtok::GreaterEqual: outs() << "GreaterEqual\n"; break; + case asmtok::GreaterGreater: outs() << "GreaterGreater\n"; break; + case asmtok::LParen: outs() << "LParen\n"; break; + case asmtok::Less: outs() << "Less\n"; break; + case asmtok::LessEqual: outs() << "LessEqual\n"; break; + case asmtok::LessGreater: outs() << "LessGreater\n"; break; + case asmtok::LessLess: outs() << "LessLess\n"; break; + case asmtok::Minus: outs() << "Minus\n"; break; + case asmtok::Percent: outs() << "Percent\n"; break; + case asmtok::Pipe: outs() << "Pipe\n"; break; + case asmtok::PipePipe: outs() << "PipePipe\n"; break; + case asmtok::Plus: outs() << "Plus\n"; break; + case asmtok::RParen: outs() << "RParen\n"; break; + case asmtok::Slash: outs() << "Slash\n"; break; + case asmtok::Star: outs() << "Star\n"; break; + case asmtok::Tilde: outs() << "Tilde\n"; break; } Tok = Lexer.Lex(); diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 324e0f6..4e01180 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -16,6 +16,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Bitcode/Archive.h" @@ -132,6 +133,7 @@ static void DumpSymbolNamesFromModule(Module *M) { } static void DumpSymbolNamesFromFile(std::string &Filename) { + LLVMContext Context; std::string ErrorMessage; sys::Path aPath(Filename); // Note: Currently we do not support reading an archive from stdin. @@ -140,7 +142,7 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { MemoryBuffer::getFileOrSTDIN(Filename, &ErrorMessage)); Module *Result = 0; if (Buffer.get()) - Result = ParseBitcodeFile(Buffer.get(), &ErrorMessage); + Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); if (Result) DumpSymbolNamesFromModule(Result); @@ -151,7 +153,8 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { } else if (aPath.isArchive()) { std::string ErrMsg; - Archive* archive = Archive::OpenAndLoad(sys::Path(Filename), &ErrorMessage); + Archive* archive = Archive::OpenAndLoad(sys::Path(Filename), Context, + &ErrorMessage); if (!archive) std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; std::vector<Module *> Modules; diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp index 119dc1a..2cff296 100644 --- a/tools/llvm-prof/llvm-prof.cpp +++ b/tools/llvm-prof/llvm-prof.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "llvm/InstrTypes.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Assembly/AsmAnnotationWriter.h" #include "llvm/Analysis/ProfileInfoLoader.h" @@ -80,8 +81,10 @@ namespace { virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, raw_ostream &OS) { if (BlockFreqs.empty()) return; - if (unsigned Count = BlockFreqs[BB]) - OS << "\t;;; Basic block executed " << Count << " times.\n"; + std::map<const BasicBlock *, unsigned>::const_iterator I = + BlockFreqs.find(BB); + if (I != BlockFreqs.end()) + OS << "\t;;; Basic block executed " << I->second << " times.\n"; else OS << "\t;;; Never executed!\n"; } @@ -115,7 +118,8 @@ int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); - + + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. try { cl::ParseCommandLineOptions(argc, argv, "llvm profile dump decoder\n"); @@ -125,7 +129,7 @@ int main(int argc, char **argv) { Module *M = 0; if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(BitcodeFile, &ErrorMessage)) { - M = ParseBitcodeFile(Buffer, &ErrorMessage); + M = ParseBitcodeFile(Buffer, Context, &ErrorMessage); delete Buffer; } if (M == 0) { diff --git a/tools/llvm-ranlib/llvm-ranlib.cpp b/tools/llvm-ranlib/llvm-ranlib.cpp index 7210610..d9bcc48 100644 --- a/tools/llvm-ranlib/llvm-ranlib.cpp +++ b/tools/llvm-ranlib/llvm-ranlib.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Bitcode/Archive.h" #include "llvm/Support/CommandLine.h" @@ -46,7 +47,8 @@ int main(int argc, char **argv) { // Print a stack trace if we signal out. llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); - + + LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Have the command line options parsed and handle things @@ -73,7 +75,7 @@ int main(int argc, char **argv) { std::string err_msg; std::auto_ptr<Archive> - AutoArchive(Archive::OpenAndLoad(ArchivePath,&err_msg)); + AutoArchive(Archive::OpenAndLoad(ArchivePath, Context, &err_msg)); Archive* TheArchive = AutoArchive.get(); if (!TheArchive) throw err_msg; diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst index 329f9ea..b43c3e3 100644 --- a/tools/llvmc/doc/LLVMC-Reference.rst +++ b/tools/llvmc/doc/LLVMC-Reference.rst @@ -71,9 +71,8 @@ impossible for LLVMC to choose the right linker in that case:: $ ./a.out hello -By default, LLVMC uses ``llvm-gcc`` to compile the source code. It is -also possible to choose the work-in-progress ``clang`` compiler with -the ``-clang`` option. +By default, LLVMC uses ``llvm-gcc`` to compile the source code. It is also +possible to choose the ``clang`` compiler with the ``-clang`` option. Predefined options @@ -678,6 +677,28 @@ errors as its status code. .. _Graphviz: http://www.graphviz.org/ .. _Ghostview: http://pages.cs.wisc.edu/~ghost/ +Conditioning on the executable name +----------------------------------- + +For now, the executable name (the value passed to the driver in ``argv[0]``) is +accessible only in the C++ code (i.e. hooks). Use the following code:: + + namespace llvmc { + extern const char* ProgramName; + } + + std::string MyHook() { + //... + if (strcmp(ProgramName, "mydriver") == 0) { + //... + + } + +In general, you're encouraged not to make the behaviour dependent on the +executable file name, and use command-line switches instead. See for example how +the ``Base`` plugin behaves when it needs to choose the correct linker options +(think ``g++`` vs. ``gcc``). + .. raw:: html <hr /> diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td b/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td index 0b8a22b..de85fa9 100644 --- a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td +++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td @@ -10,9 +10,11 @@ include "llvm/CompilerDriver/Common.td" def OptionList : OptionList<[ (switch_option "g", - (help "Disable optimizations")), + (help "Enable Debugging")), (switch_option "S", (help "Stop after compilation, do not assemble")), + (switch_option "c", + (help "Stop after assemble, do not link")), (parameter_option "I", (help "Add a directory to include path")), (parameter_option "pre-RA-sched", @@ -33,7 +35,7 @@ def clang_cc : Tool<[ (in_language "c"), (out_language "llvm-bitcode"), (output_suffix "bc"), - (cmd_line "clang-cc $INFILE -o $OUTFILE"), + (cmd_line "$CALL(GetBinDir)clang-cc -I $CALL(GetStdHeadersDir) -triple=pic16- -emit-llvm-bc $INFILE -o $OUTFILE"), (actions (case (not_empty "I"), (forward "I"))), (sink) @@ -43,7 +45,7 @@ def llvm_ld : Tool<[ (in_language "llvm-bitcode"), (out_language "llvm-bitcode"), (output_suffix "bc"), - (cmd_line "llvm-ld $INFILE -o $OUTFILE"), + (cmd_line "$CALL(GetBinDir)llvm-ld -link-as-library $INFILE -o $OUTFILE"), (actions (case (switch_on "g"), (append_cmd "-disable-opt"), (not_empty "Wo,"), (unpack_values "Wo,"))) @@ -53,7 +55,7 @@ def llvm_ld_lto : Tool<[ (in_language "llvm-bitcode"), (out_language "llvm-bitcode"), (output_suffix "bc"), - (cmd_line "llvm-ld $INFILE -o $OUTFILE"), + (cmd_line "$CALL(GetBinDir)llvm-ld -link-as-library $INFILE -o $OUTFILE"), (actions (case (switch_on "g"), (append_cmd "-disable-opt"), (not_empty "Wo,"), (unpack_values "Wo,"))), @@ -64,27 +66,28 @@ def llc : Tool<[ (in_language "llvm-bitcode"), (out_language "assembler"), (output_suffix "s"), - (cmd_line "llc -f $INFILE -o $OUTFILE"), + (cmd_line "$CALL(GetBinDir)llc -march=pic16 -f $INFILE -o $OUTFILE"), (actions (case (switch_on "S"), (stop_compilation), (not_empty "Wllc,"), (unpack_values "Wllc,"), (not_empty "pre-RA-sched"), (forward "pre-RA-sched"))) ]>; -def native_as : Tool<[ +def gpasm : Tool<[ (in_language "assembler"), (out_language "object-code"), (output_suffix "o"), - (cmd_line "native-as $INFILE -o $OUTFILE"), + (cmd_line "$CALL(GetBinDir)gpasm -r decimal -p p16F1937 -I $CALL(GetStdAsmHeadersDir) -C -c $INFILE -o $OUTFILE"), (actions (case + (switch_on "c"), (stop_compilation), (not_empty "Wa,"), (unpack_values "Wa,"))) ]>; -def native_ld : Tool<[ +def mplink : Tool<[ (in_language "object-code"), (out_language "executable"), (output_suffix "out"), - (cmd_line "native-ld $INFILE -o $OUTFILE"), + (cmd_line "$CALL(GetBinDir)mplink.exe /k $CALL(GetStdLinkerScriptsDir) /l $CALL(GetStdLibsDir) 16f1937.lkr intrinsics.lib std.lib $INFILE -o $OUTFILE"), (actions (case (not_empty "Wl,"), (unpack_values "Wl,"))), (join) @@ -109,8 +112,10 @@ def CompilationGraph : CompilationGraph<[ Edge<"root", "clang_cc">, Edge<"clang_cc", "llvm_ld_lto">, Edge<"llvm_ld_lto", "llc">, - OptionalEdge<"clang_cc", "llvm_ld", (case (switch_on "S"), (inc_weight))>, + OptionalEdge<"clang_cc", "llvm_ld", (case + (switch_on "S"), (inc_weight), + (switch_on "c"), (inc_weight))>, Edge<"llvm_ld", "llc">, - Edge<"llc", "native_as">, - Edge<"native_as", "native_ld"> + Edge<"llc", "gpasm">, + Edge<"gpasm", "mplink"> ]>; diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp b/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp index add8acb..21a25b3 100644 --- a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp +++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp @@ -1 +1,61 @@ #include "AutoGenerated.inc" + +#include "llvm/System/Path.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace llvmc { + extern char *ProgramName; +} + +// Returns the platform specific directory separator via #ifdefs. +static std::string GetDirSeparator(void) { + return "/"; +} + +namespace hooks { +// Get the dir where c16 executables reside. +std::string GetBinDir (void) { + // Construct a Path object from the program name. + void *P = (void*) (intptr_t) GetBinDir; + sys::Path ProgramFullPath + = sys::Path::GetMainExecutable(llvmc::ProgramName, P); + + // Get the dir name for the program. It's last component should be 'bin'. + std::string BinDir = ProgramFullPath.getDirname(); + + // llvm::errs() << "BinDir: " << BinDir << '\n'; + return BinDir + GetDirSeparator(); +} + +// Get the Top-level Installation dir for c16. +std::string GetInstallDir (void) { + sys::Path BinDirPath = sys::Path(GetBinDir()); + + // Go one more level up to get the install dir. + std::string InstallDir = BinDirPath.getDirname(); + + return InstallDir + GetDirSeparator(); +} + +// Get the dir where the c16 header files reside. +std::string GetStdHeadersDir (void) { + return GetInstallDir() + "include"; +} + +// Get the dir where the assembler header files reside. +std::string GetStdAsmHeadersDir (void) { + return GetInstallDir() + "inc"; +} + +// Get the dir where the linker scripts reside. +std::string GetStdLinkerScriptsDir (void) { + return GetInstallDir() + "lkr"; +} + +// Get the dir where startup code, intrinsics and lib reside. +std::string GetStdLibsDir (void) { + return GetInstallDir() + "lib"; +} +} diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 52624eb..1a21132 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -19,6 +19,7 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Linker.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/PassManager.h" @@ -70,7 +71,8 @@ const char* LTOCodeGenerator::getVersionString() LTOCodeGenerator::LTOCodeGenerator() - : _linker("LinkTimeOptimizer", "ld-temp.o"), _target(NULL), + : _context(getGlobalContext()), + _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL), _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false), _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC), _nativeObjectFile(NULL), _gccPath(NULL), _assemblerPath(NULL) diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h index e02a7ab..5548050 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -16,6 +16,7 @@ #define LTO_CODE_GENERATOR_H #include "llvm/Linker.h" +#include "llvm/LLVMContext.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/SmallVector.h" @@ -53,6 +54,7 @@ private: typedef llvm::StringMap<uint8_t> StringSet; + llvm::LLVMContext& _context; llvm::Linker _linker; llvm::TargetMachine* _target; bool _emitDwarfDebugInfo; diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 939d0ea..9c8baef 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -15,6 +15,7 @@ #include "LTOModule.h" #include "llvm/Constants.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/ADT/OwningPtr.h" @@ -67,7 +68,8 @@ bool LTOModule::isBitcodeFileForTarget(const char* path, // takes ownership of buffer bool LTOModule::isTargetMatch(MemoryBuffer* buffer, const char* triplePrefix) { - OwningPtr<ModuleProvider> mp(getBitcodeModuleProvider(buffer)); + OwningPtr<ModuleProvider> mp(getBitcodeModuleProvider(buffer, + getGlobalContext())); // on success, mp owns buffer and both are deleted at end of this method if ( !mp ) { delete buffer; @@ -84,7 +86,8 @@ LTOModule::LTOModule(Module* m, TargetMachine* t) { } -LTOModule* LTOModule::makeLTOModule(const char* path, std::string& errMsg) +LTOModule* LTOModule::makeLTOModule(const char* path, + std::string& errMsg) { OwningPtr<MemoryBuffer> buffer(MemoryBuffer::getFile(path, &errMsg)); if ( !buffer ) @@ -136,10 +139,11 @@ std::string getFeatureString(const char *TargetTriple) { return Features.getString(); } -LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer, std::string& errMsg) +LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer, + std::string& errMsg) { // parse bitcode buffer - OwningPtr<Module> m(ParseBitcodeFile(buffer, &errMsg)); + OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), &errMsg)); if ( !m ) return NULL; // find machine architecture for this module diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h index 9de02a2..8fd3915 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -50,9 +50,10 @@ public: static bool isBitcodeFileForTarget(const char* path, const char* triplePrefix); - static LTOModule* makeLTOModule(const char* path, std::string& errMsg); + static LTOModule* makeLTOModule(const char* path, + std::string& errMsg); static LTOModule* makeLTOModule(const void* mem, size_t length, - std::string& errMsg); + std::string& errMsg); const char* getTargetTriple(); uint32_t getSymbolCount(); @@ -83,10 +84,10 @@ private: bool objcClassNameFromExpression(llvm::Constant* c, std::string& name); - static bool isTargetMatch(llvm::MemoryBuffer* memBuffer, + static bool isTargetMatch(llvm::MemoryBuffer* memBuffer, const char* triplePrefix); - static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer, + static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer, std::string& errMsg); static llvm::MemoryBuffer* makeBuffer(const void* mem, size_t length); diff --git a/tools/lto/Makefile b/tools/lto/Makefile index de885d9..c8ad9fe 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -31,7 +31,7 @@ ifeq ($(OS),Darwin) endif # extra options to override libtool defaults LLVMLibsOptions := $(LLVMLibsOptions) \ - -no-undefined -avoid-version \ + -avoid-version \ -Wl,-exported_symbols_list -Wl,$(PROJ_SRC_DIR)/lto.exports \ -Wl,-dead_strip \ -Wl,-seg1addr -Wl,0xE0000000 @@ -40,7 +40,7 @@ ifeq ($(OS),Darwin) DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/') ifneq ($(DARWIN_VERS),8) LLVMLibsOptions := $(LLVMLibsOptions) \ - -Wl,-install_name \ + -no-undefined -Wl,-install_name \ -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)" endif endif diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index a0f67b4..936aeae 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm-c/lto.h" +#include "llvm-c/Core.h" #include "LTOModule.h" #include "LTOCodeGenerator.h" @@ -154,7 +155,7 @@ lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, // instantiates a code generator // returns NULL if there is an error // -lto_code_gen_t lto_codegen_create() +lto_code_gen_t lto_codegen_create(void) { return new LTOCodeGenerator(); } diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 0c36e21..6891619 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/PassManager.h" @@ -310,6 +311,7 @@ void AddStandardCompilePasses(PassManager &PM) { // int main(int argc, char **argv) { llvm_shutdown_obj X; // Call llvm_shutdown() on exit. + LLVMContext Context; try { cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); @@ -325,7 +327,7 @@ int main(int argc, char **argv) { std::auto_ptr<Module> M; if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) { - M.reset(ParseBitcodeFile(Buffer, &ErrorMessage)); + M.reset(ParseBitcodeFile(Buffer, Context, &ErrorMessage)); delete Buffer; } |