summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2009-07-04 13:58:26 +0000
committered <ed@FreeBSD.org>2009-07-04 13:58:26 +0000
commit72621d11de5b873f1695f391eb95f0b336c3d2d4 (patch)
tree84360c8989c912127a383af37c4b1aa5767bd16e /tools
parentcf5cd875b51255602afaed29deb636b66b295671 (diff)
downloadFreeBSD-src-72621d11de5b873f1695f391eb95f0b336c3d2d4.zip
FreeBSD-src-72621d11de5b873f1695f391eb95f0b336c3d2d4.tar.gz
Import LLVM 74788.
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile4
-rw-r--r--tools/bugpoint/BugDriver.cpp25
-rw-r--r--tools/bugpoint/BugDriver.h9
-rw-r--r--tools/bugpoint/CrashDebugger.cpp2
-rw-r--r--tools/bugpoint/Miscompilation.cpp2
-rw-r--r--tools/bugpoint/OptimizerDriver.cpp2
-rw-r--r--tools/bugpoint/bugpoint.cpp6
-rw-r--r--tools/gold/gold-plugin.cpp5
-rw-r--r--tools/llc/llc.cpp4
-rw-r--r--tools/lli/lli.cpp8
-rw-r--r--tools/llvm-ar/llvm-ar.cpp6
-rw-r--r--tools/llvm-as/llvm-as.cpp9
-rw-r--r--tools/llvm-db/CLIDebugger.cpp5
-rw-r--r--tools/llvm-db/CLIDebugger.h5
-rw-r--r--tools/llvm-db/Commands.cpp4
-rw-r--r--tools/llvm-db/llvm-db.cpp4
-rw-r--r--tools/llvm-dis/llvm-dis.cpp4
-rw-r--r--tools/llvm-extract/llvm-extract.cpp6
-rw-r--r--tools/llvm-ld/llvm-ld.cpp6
-rw-r--r--tools/llvm-link/llvm-link.cpp11
-rw-r--r--tools/llvm-mc/AsmExpr.cpp162
-rw-r--r--tools/llvm-mc/AsmExpr.h179
-rw-r--r--tools/llvm-mc/AsmLexer.cpp60
-rw-r--r--tools/llvm-mc/AsmLexer.h12
-rw-r--r--tools/llvm-mc/AsmParser.cpp419
-rw-r--r--tools/llvm-mc/AsmParser.h63
-rw-r--r--tools/llvm-mc/CMakeLists.txt1
-rw-r--r--tools/llvm-mc/MC-X86Specific.cpp176
-rw-r--r--tools/llvm-mc/llvm-mc.cpp41
-rw-r--r--tools/llvm-nm/llvm-nm.cpp7
-rw-r--r--tools/llvm-prof/llvm-prof.cpp12
-rw-r--r--tools/llvm-ranlib/llvm-ranlib.cpp6
-rw-r--r--tools/llvmc/doc/LLVMC-Reference.rst27
-rw-r--r--tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td29
-rw-r--r--tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp60
-rw-r--r--tools/lto/LTOCodeGenerator.cpp4
-rw-r--r--tools/lto/LTOCodeGenerator.h2
-rw-r--r--tools/lto/LTOModule.cpp12
-rw-r--r--tools/lto/LTOModule.h9
-rw-r--r--tools/lto/Makefile4
-rw-r--r--tools/lto/lto.cpp3
-rw-r--r--tools/opt/opt.cpp4
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;
}
OpenPOWER on IntegriCloud