summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-02-16 09:30:23 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-02-16 09:30:23 +0000
commitf25ddd991a5601d0101602c4c263a58c7af4b8a2 (patch)
tree4cfca640904d1896e25032757a61f8959c066919 /tools
parent3fd58f91dd318518f7daa4ba64c0aaf31799d89b (diff)
downloadFreeBSD-src-f25ddd991a5601d0101602c4c263a58c7af4b8a2.zip
FreeBSD-src-f25ddd991a5601d0101602c4c263a58c7af4b8a2.tar.gz
Update LLVM to r96341.
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile3
-rw-r--r--tools/bugpoint/ExtractFunction.cpp8
-rw-r--r--tools/edis/EDDisassembler.cpp386
-rw-r--r--tools/edis/EDDisassembler.h248
-rw-r--r--tools/edis/EDInst.cpp205
-rw-r--r--tools/edis/EDInst.h171
-rw-r--r--tools/edis/EDMain.cpp293
-rw-r--r--tools/edis/EDOperand.cpp168
-rw-r--r--tools/edis/EDOperand.h78
-rw-r--r--tools/edis/EDToken.cpp208
-rw-r--r--tools/edis/EDToken.h135
-rw-r--r--tools/edis/EnhancedDisassembly.exports36
-rw-r--r--tools/edis/Makefile55
-rw-r--r--tools/gold/Makefile1
-rw-r--r--tools/llc/Makefile1
-rw-r--r--tools/llc/llc.cpp50
-rw-r--r--tools/lli/Makefile1
-rw-r--r--tools/lli/lli.cpp44
-rw-r--r--tools/llvm-ar/Makefile1
-rw-r--r--tools/llvm-as/Makefile1
-rw-r--r--tools/llvm-config/Makefile40
-rwxr-xr-xtools/llvm-config/find-cycles.pl5
-rw-r--r--tools/llvm-dis/Makefile1
-rw-r--r--tools/llvm-extract/Makefile1
-rw-r--r--tools/llvm-extract/llvm-extract.cpp52
-rw-r--r--tools/llvm-ld/Makefile1
-rw-r--r--tools/llvm-ld/llvm-ld.cpp5
-rw-r--r--tools/llvm-link/Makefile1
-rw-r--r--tools/llvm-mc/AsmCond.h40
-rw-r--r--tools/llvm-mc/AsmLexer.cpp311
-rw-r--r--tools/llvm-mc/AsmLexer.h72
-rw-r--r--tools/llvm-mc/AsmParser.cpp1782
-rw-r--r--tools/llvm-mc/AsmParser.h178
-rw-r--r--tools/llvm-mc/Disassembler.cpp48
-rw-r--r--tools/llvm-mc/HexDisassembler.cpp169
-rw-r--r--tools/llvm-mc/HexDisassembler.h34
-rw-r--r--tools/llvm-mc/Makefile1
-rw-r--r--tools/llvm-mc/llvm-mc.cpp10
-rw-r--r--tools/llvm-nm/Makefile1
-rw-r--r--tools/llvm-prof/Makefile1
-rw-r--r--tools/llvmc/Makefile1
-rw-r--r--tools/llvmc/example/mcc16/driver/Main.cpp10
-rw-r--r--tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td69
-rw-r--r--tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp39
-rw-r--r--tools/llvmc/plugins/Base/Base.td.in40
-rw-r--r--tools/lto/LTOCodeGenerator.cpp32
-rw-r--r--tools/lto/LTOModule.cpp10
-rw-r--r--tools/lto/Makefile1
-rw-r--r--tools/opt/Makefile1
-rw-r--r--tools/opt/opt.cpp3
50 files changed, 2280 insertions, 2772 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 0340c7f..c9b9ff2 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -21,7 +21,8 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \
llvm-ld llvm-prof llvm-link \
lli llvm-extract \
bugpoint llvm-bcanalyzer llvm-stub \
- llvm-mc llvmc
+ llvm-mc llvmc \
+ edis
# Let users override the set of tools to build from the command line.
ifdef ONLY_TOOLS
diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp
index 918d6a6a..70011a7 100644
--- a/tools/bugpoint/ExtractFunction.cpp
+++ b/tools/bugpoint/ExtractFunction.cpp
@@ -323,8 +323,6 @@ llvm::SplitFunctionsOutOfModule(Module *M,
Module *BugDriver::ExtractMappedBlocksFromModule(const
std::vector<BasicBlock*> &BBs,
Module *M) {
- char *ExtraArg = NULL;
-
sys::Path uniqueFilename(OutputPrefix + "-extractblocks");
std::string ErrMsg;
if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) {
@@ -359,9 +357,8 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
}
BlocksToNotExtractFile.close();
- const char *uniqueFN = uniqueFilename.c_str();
- ExtraArg = (char*)malloc(23 + strlen(uniqueFN));
- strcat(strcpy(ExtraArg, "--extract-blocks-file="), uniqueFN);
+ std::string uniqueFN = "--extract-blocks-file=" + uniqueFilename.str();
+ const char *ExtraArg = uniqueFN.c_str();
std::vector<const PassInfo*> PI;
std::vector<BasicBlock *> EmptyBBs; // This parameter is ignored.
@@ -370,7 +367,6 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
if (uniqueFilename.exists())
uniqueFilename.eraseFromDisk(); // Free disk space
- free(ExtraArg);
if (Ret == 0) {
outs() << "*** Basic Block extraction failed, please report a bug!\n";
diff --git a/tools/edis/EDDisassembler.cpp b/tools/edis/EDDisassembler.cpp
new file mode 100644
index 0000000..99864fb
--- /dev/null
+++ b/tools/edis/EDDisassembler.cpp
@@ -0,0 +1,386 @@
+//===-EDDisassembler.cpp - LLVM Enhanced Disassembler ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Enhanced Disassembly library's disassembler class.
+// The disassembler is responsible for vending individual instructions according
+// to a given architecture and disassembly syntax.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCParser/AsmLexer.h"
+#include "llvm/MC/MCParser/AsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Target/TargetAsmLexer.h"
+#include "llvm/Target/TargetAsmParser.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSelect.h"
+
+#include "EDDisassembler.h"
+#include "EDInst.h"
+
+#include "../../lib/Target/X86/X86GenEDInfo.inc"
+
+using namespace llvm;
+
+bool EDDisassembler::sInitialized = false;
+EDDisassembler::DisassemblerMap_t EDDisassembler::sDisassemblers;
+
+struct InfoMap {
+ Triple::ArchType Arch;
+ const char *String;
+ const InstInfo *Info;
+};
+
+static struct InfoMap infomap[] = {
+ { Triple::x86, "i386-unknown-unknown", instInfoX86 },
+ { Triple::x86_64, "x86_64-unknown-unknown", instInfoX86 },
+ { Triple::InvalidArch, NULL, NULL }
+};
+
+/// infoFromArch - Returns the InfoMap corresponding to a given architecture,
+/// or NULL if there is an error
+///
+/// @arg arch - The Triple::ArchType for the desired architecture
+static const InfoMap *infoFromArch(Triple::ArchType arch) {
+ unsigned int infoIndex;
+
+ for (infoIndex = 0; infomap[infoIndex].String != NULL; ++infoIndex) {
+ if(arch == infomap[infoIndex].Arch)
+ return &infomap[infoIndex];
+ }
+
+ return NULL;
+}
+
+/// getLLVMSyntaxVariant - gets the constant to use to get an assembly printer
+/// for the desired assembly syntax, suitable for passing to
+/// Target::createMCInstPrinter()
+///
+/// @arg arch - The target architecture
+/// @arg syntax - The assembly syntax in sd form
+static int getLLVMSyntaxVariant(Triple::ArchType arch,
+ EDAssemblySyntax_t syntax) {
+ switch (syntax) {
+ default:
+ return -1;
+ // Mappings below from X86AsmPrinter.cpp
+ case kEDAssemblySyntaxX86ATT:
+ if (arch == Triple::x86 || arch == Triple::x86_64)
+ return 0;
+ else
+ return -1;
+ case kEDAssemblySyntaxX86Intel:
+ if (arch == Triple::x86 || arch == Triple::x86_64)
+ return 1;
+ else
+ return -1;
+ }
+}
+
+#define BRINGUP_TARGET(tgt) \
+ LLVMInitialize##tgt##TargetInfo(); \
+ LLVMInitialize##tgt##Target(); \
+ LLVMInitialize##tgt##AsmPrinter(); \
+ LLVMInitialize##tgt##AsmParser(); \
+ LLVMInitialize##tgt##Disassembler();
+
+void EDDisassembler::initialize() {
+ if (sInitialized)
+ return;
+
+ sInitialized = true;
+
+ BRINGUP_TARGET(X86)
+}
+
+#undef BRINGUP_TARGET
+
+EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch,
+ EDAssemblySyntax_t syntax) {
+ CPUKey key;
+ key.Arch = arch;
+ key.Syntax = syntax;
+
+ EDDisassembler::DisassemblerMap_t::iterator i = sDisassemblers.find(key);
+
+ if (i != sDisassemblers.end()) {
+ return i->second;
+ }
+ else {
+ EDDisassembler* sdd = new EDDisassembler(key);
+ if(!sdd->valid()) {
+ delete sdd;
+ return NULL;
+ }
+
+ sDisassemblers[key] = sdd;
+
+ return sdd;
+ }
+
+ return NULL;
+}
+
+EDDisassembler *EDDisassembler::getDisassembler(StringRef str,
+ EDAssemblySyntax_t syntax) {
+ Triple triple(str);
+
+ return getDisassembler(triple.getArch(), syntax);
+}
+
+EDDisassembler::EDDisassembler(CPUKey &key) :
+ Valid(false), ErrorString(), ErrorStream(ErrorString), Key(key) {
+ const InfoMap *infoMap = infoFromArch(key.Arch);
+
+ if (!infoMap)
+ return;
+
+ const char *triple = infoMap->String;
+
+ int syntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax);
+
+ if (syntaxVariant < 0)
+ return;
+
+ std::string tripleString(triple);
+ std::string errorString;
+
+ Tgt = TargetRegistry::lookupTarget(tripleString,
+ errorString);
+
+ if (!Tgt)
+ return;
+
+ std::string featureString;
+
+ OwningPtr<const TargetMachine>
+ targetMachine(Tgt->createTargetMachine(tripleString,
+ featureString));
+
+ const TargetRegisterInfo *registerInfo = targetMachine->getRegisterInfo();
+
+ if (!registerInfo)
+ return;
+
+ AsmInfo.reset(Tgt->createAsmInfo(tripleString));
+
+ if (!AsmInfo)
+ return;
+
+ Disassembler.reset(Tgt->createMCDisassembler());
+
+ if (!Disassembler)
+ return;
+
+ InstString.reset(new std::string);
+ InstStream.reset(new raw_string_ostream(*InstString));
+
+ InstPrinter.reset(Tgt->createMCInstPrinter(syntaxVariant,
+ *AsmInfo,
+ *InstStream));
+
+ if (!InstPrinter)
+ return;
+
+ GenericAsmLexer.reset(new AsmLexer(*AsmInfo));
+ SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo));
+ SpecificAsmLexer->InstallLexer(*GenericAsmLexer);
+
+ InstInfos = infoMap->Info;
+
+ initMaps(*targetMachine->getRegisterInfo());
+
+ Valid = true;
+}
+
+EDDisassembler::~EDDisassembler() {
+ if(!valid())
+ return;
+}
+
+namespace {
+ /// EDMemoryObject - a subclass of MemoryObject that allows use of a callback
+ /// as provided by the sd interface. See MemoryObject.
+ class EDMemoryObject : public llvm::MemoryObject {
+ private:
+ EDByteReaderCallback Callback;
+ void *Arg;
+ public:
+ EDMemoryObject(EDByteReaderCallback callback,
+ void *arg) : Callback(callback), Arg(arg) { }
+ ~EDMemoryObject() { }
+ uint64_t getBase() const { return 0x0; }
+ uint64_t getExtent() const { return (uint64_t)-1; }
+ int readByte(uint64_t address, uint8_t *ptr) const {
+ if(!Callback)
+ return -1;
+
+ if(Callback(ptr, address, Arg))
+ return -1;
+
+ return 0;
+ }
+ };
+}
+
+EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader,
+ uint64_t address,
+ void *arg) {
+ EDMemoryObject memoryObject(byteReader, arg);
+
+ MCInst* inst = new MCInst;
+ uint64_t byteSize;
+
+ if (!Disassembler->getInstruction(*inst,
+ byteSize,
+ memoryObject,
+ address,
+ ErrorStream)) {
+ delete inst;
+ return NULL;
+ }
+ else {
+ const InstInfo *thisInstInfo = &InstInfos[inst->getOpcode()];
+
+ EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo);
+ return sdInst;
+ }
+}
+
+void EDDisassembler::initMaps(const TargetRegisterInfo &registerInfo) {
+ unsigned numRegisters = registerInfo.getNumRegs();
+ unsigned registerIndex;
+
+ for (registerIndex = 0; registerIndex < numRegisters; ++registerIndex) {
+ const char* registerName = registerInfo.get(registerIndex).Name;
+
+ RegVec.push_back(registerName);
+ RegRMap[registerName] = registerIndex;
+ }
+
+ if (Key.Arch == Triple::x86 ||
+ Key.Arch == Triple::x86_64) {
+ stackPointers.insert(registerIDWithName("SP"));
+ stackPointers.insert(registerIDWithName("ESP"));
+ stackPointers.insert(registerIDWithName("RSP"));
+
+ programCounters.insert(registerIDWithName("IP"));
+ programCounters.insert(registerIDWithName("EIP"));
+ programCounters.insert(registerIDWithName("RIP"));
+ }
+}
+
+const char *EDDisassembler::nameWithRegisterID(unsigned registerID) const {
+ if (registerID >= RegVec.size())
+ return NULL;
+ else
+ return RegVec[registerID].c_str();
+}
+
+unsigned EDDisassembler::registerIDWithName(const char *name) const {
+ regrmap_t::const_iterator iter = RegRMap.find(std::string(name));
+ if (iter == RegRMap.end())
+ return 0;
+ else
+ return (*iter).second;
+}
+
+bool EDDisassembler::registerIsStackPointer(unsigned registerID) {
+ return (stackPointers.find(registerID) != stackPointers.end());
+}
+
+bool EDDisassembler::registerIsProgramCounter(unsigned registerID) {
+ return (programCounters.find(registerID) != programCounters.end());
+}
+
+int EDDisassembler::printInst(std::string& str,
+ MCInst& inst) {
+ PrinterMutex.acquire();
+
+ InstPrinter->printInst(&inst);
+ InstStream->flush();
+ str = *InstString;
+ InstString->clear();
+
+ PrinterMutex.release();
+
+ return 0;
+}
+
+int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands,
+ SmallVectorImpl<AsmToken> &tokens,
+ const std::string &str) {
+ int ret = 0;
+
+ const char *cStr = str.c_str();
+ MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr));
+
+ StringRef instName;
+ SMLoc instLoc;
+
+ SourceMgr sourceMgr;
+ sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over
+ MCContext context;
+ OwningPtr<MCStreamer> streamer
+ (createNullStreamer(context));
+ AsmParser genericParser(sourceMgr, context, *streamer, *AsmInfo);
+ OwningPtr<TargetAsmParser> specificParser
+ (Tgt->createAsmParser(genericParser));
+
+ AsmToken OpcodeToken = genericParser.Lex();
+
+ if(OpcodeToken.is(AsmToken::Identifier)) {
+ instName = OpcodeToken.getString();
+ instLoc = OpcodeToken.getLoc();
+ if (specificParser->ParseInstruction(instName, instLoc, operands))
+ ret = -1;
+ }
+ else {
+ ret = -1;
+ }
+
+ ParserMutex.acquire();
+
+ if (!ret) {
+ GenericAsmLexer->setBuffer(buf);
+
+ while (SpecificAsmLexer->Lex(),
+ SpecificAsmLexer->isNot(AsmToken::Eof) &&
+ SpecificAsmLexer->isNot(AsmToken::EndOfStatement)) {
+ if (SpecificAsmLexer->is(AsmToken::Error)) {
+ ret = -1;
+ break;
+ }
+ tokens.push_back(SpecificAsmLexer->getTok());
+ }
+ }
+
+ ParserMutex.release();
+
+ return ret;
+}
+
+int EDDisassembler::llvmSyntaxVariant() const {
+ return LLVMSyntaxVariant;
+}
diff --git a/tools/edis/EDDisassembler.h b/tools/edis/EDDisassembler.h
new file mode 100644
index 0000000..6be9152
--- /dev/null
+++ b/tools/edis/EDDisassembler.h
@@ -0,0 +1,248 @@
+//===-EDDisassembler.h - LLVM Enhanced Disassembler -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for the Enhanced Disassembly library's
+// disassembler class. The disassembler is responsible for vending individual
+// instructions according to a given architecture and disassembly syntax.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EDDisassembler_
+#define EDDisassembler_
+
+#include "EDInfo.inc"
+
+#include "llvm-c/EnhancedDisassembly.h"
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Mutex.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+namespace llvm {
+class AsmLexer;
+class AsmToken;
+class MCContext;
+class MCAsmInfo;
+class MCAsmLexer;
+class AsmParser;
+class TargetAsmLexer;
+class TargetAsmParser;
+class MCDisassembler;
+class MCInstPrinter;
+class MCInst;
+class MCParsedAsmOperand;
+class MCStreamer;
+template <typename T> class SmallVectorImpl;
+class SourceMgr;
+class Target;
+class TargetRegisterInfo;
+}
+
+/// EDDisassembler - Encapsulates a disassembler for a single architecture and
+/// disassembly syntax. Also manages the static disassembler registry.
+struct EDDisassembler {
+ ////////////////////
+ // Static members //
+ ////////////////////
+
+ /// CPUKey - Encapsulates the descriptor of an architecture/disassembly-syntax
+ /// pair
+ struct CPUKey {
+ /// The architecture type
+ llvm::Triple::ArchType Arch;
+
+ /// The assembly syntax
+ EDAssemblySyntax_t Syntax;
+
+ /// operator== - Equality operator
+ bool operator==(const CPUKey &key) const {
+ return (Arch == key.Arch &&
+ Syntax == key.Syntax);
+ }
+
+ /// operator< - Less-than operator
+ bool operator<(const CPUKey &key) const {
+ if(Arch > key.Arch)
+ return false;
+ if(Syntax >= key.Syntax)
+ return false;
+ return true;
+ }
+ };
+
+ typedef std::map<CPUKey, EDDisassembler*> DisassemblerMap_t;
+
+ /// True if the disassembler registry has been initialized; false if not
+ static bool sInitialized;
+ /// A map from disassembler specifications to disassemblers. Populated
+ /// lazily.
+ static DisassemblerMap_t sDisassemblers;
+
+ /// getDisassembler - Returns the specified disassemble, or NULL on failure
+ ///
+ /// @arg arch - The desired architecture
+ /// @arg syntax - The desired disassembly syntax
+ static EDDisassembler *getDisassembler(llvm::Triple::ArchType arch,
+ EDAssemblySyntax_t syntax);
+
+ /// getDisassembler - Returns the disassembler for a given combination of
+ /// CPU type, CPU subtype, and assembly syntax, or NULL on failure
+ ///
+ /// @arg str - The string representation of the architecture triple, e.g.,
+ /// "x86_64-apple-darwin"
+ /// @arg syntax - The disassembly syntax for the required disassembler
+ static EDDisassembler *getDisassembler(llvm::StringRef str,
+ EDAssemblySyntax_t syntax);
+
+ /// initialize - Initializes the disassembler registry and the LLVM backend
+ static void initialize();
+
+ ////////////////////////
+ // Per-object members //
+ ////////////////////////
+
+ /// True only if the object has been fully and successfully initialized
+ bool Valid;
+
+ /// The string that stores disassembler errors from the backend
+ std::string ErrorString;
+ /// The stream that wraps the ErrorString
+ llvm::raw_string_ostream ErrorStream;
+
+ /// The architecture/syntax pair for the current architecture
+ CPUKey Key;
+ /// The LLVM target corresponding to the disassembler
+ const llvm::Target *Tgt;
+ /// The assembly information for the target architecture
+ llvm::OwningPtr<const llvm::MCAsmInfo> AsmInfo;
+ /// The disassembler for the target architecture
+ llvm::OwningPtr<const llvm::MCDisassembler> Disassembler;
+ /// The output string for the instruction printer; must be guarded with
+ /// PrinterMutex
+ llvm::OwningPtr<std::string> InstString;
+ /// The output stream for the disassembler; must be guarded with
+ /// PrinterMutex
+ llvm::OwningPtr<llvm::raw_string_ostream> InstStream;
+ /// The instruction printer for the target architecture; must be guarded with
+ /// PrinterMutex when printing
+ llvm::OwningPtr<llvm::MCInstPrinter> InstPrinter;
+ /// The mutex that guards the instruction printer's printing functions, which
+ /// use a shared stream
+ llvm::sys::Mutex PrinterMutex;
+ /// The array of instruction information provided by the TableGen backend for
+ /// the target architecture
+ const InstInfo *InstInfos;
+ /// The target-specific lexer for use in tokenizing strings, in
+ /// target-independent and target-specific portions
+ llvm::OwningPtr<llvm::AsmLexer> GenericAsmLexer;
+ llvm::OwningPtr<llvm::TargetAsmLexer> SpecificAsmLexer;
+ /// The guard for the above
+ llvm::sys::Mutex ParserMutex;
+ /// The LLVM number used for the target disassembly syntax variant
+ int LLVMSyntaxVariant;
+
+ typedef std::vector<std::string> regvec_t;
+ typedef std::map<std::string, unsigned> regrmap_t;
+
+ /// A vector of registers for quick mapping from LLVM register IDs to names
+ regvec_t RegVec;
+ /// A map of registers for quick mapping from register names to LLVM IDs
+ regrmap_t RegRMap;
+
+ /// A set of register IDs for aliases of the stack pointer for the current
+ /// architecture
+ std::set<unsigned> stackPointers;
+ /// A set of register IDs for aliases of the program counter for the current
+ /// architecture
+ std::set<unsigned> programCounters;
+
+ /// Constructor - initializes a disassembler with all the necessary objects,
+ /// which come pre-allocated from the registry accessor function
+ ///
+ /// @arg key - the architecture and disassembly syntax for the
+ /// disassembler
+ EDDisassembler(CPUKey& key);
+
+ /// valid - reports whether there was a failure in the constructor.
+ bool valid() {
+ return Valid;
+ }
+
+ ~EDDisassembler();
+
+ /// createInst - creates and returns an instruction given a callback and
+ /// memory address, or NULL on failure
+ ///
+ /// @arg byteReader - A callback function that provides machine code bytes
+ /// @arg address - The address of the first byte of the instruction,
+ /// suitable for passing to byteReader
+ /// @arg arg - An opaque argument for byteReader
+ EDInst *createInst(EDByteReaderCallback byteReader,
+ uint64_t address,
+ void *arg);
+
+ /// initMaps - initializes regVec and regRMap using the provided register
+ /// info
+ ///
+ /// @arg registerInfo - the register information to use as a source
+ void initMaps(const llvm::TargetRegisterInfo &registerInfo);
+ /// nameWithRegisterID - Returns the name (owned by the EDDisassembler) of a
+ /// register for a given register ID, or NULL on failure
+ ///
+ /// @arg registerID - the ID of the register to be queried
+ const char *nameWithRegisterID(unsigned registerID) const;
+ /// registerIDWithName - Returns the ID of a register for a given register
+ /// name, or (unsigned)-1 on failure
+ ///
+ /// @arg name - The name of the register
+ unsigned registerIDWithName(const char *name) const;
+
+ /// registerIsStackPointer - reports whether a register ID is an alias for the
+ /// stack pointer register
+ ///
+ /// @arg registerID - The LLVM register ID
+ bool registerIsStackPointer(unsigned registerID);
+ /// registerIsStackPointer - reports whether a register ID is an alias for the
+ /// stack pointer register
+ ///
+ /// @arg registerID - The LLVM register ID
+ bool registerIsProgramCounter(unsigned registerID);
+
+ /// printInst - prints an MCInst to a string, returning 0 on success, or -1
+ /// otherwise
+ ///
+ /// @arg str - A reference to a string which is filled in with the string
+ /// representation of the instruction
+ /// @arg inst - A reference to the MCInst to be printed
+ int printInst(std::string& str,
+ llvm::MCInst& inst);
+
+ /// parseInst - extracts operands and tokens from a string for use in
+ /// tokenizing the string. Returns 0 on success, or -1 otherwise.
+ ///
+ /// @arg operands - A reference to a vector that will be filled in with the
+ /// parsed operands
+ /// @arg tokens - A reference to a vector that will be filled in with the
+ /// tokens
+ /// @arg str - The string representation of the instruction
+ int parseInst(llvm::SmallVectorImpl<llvm::MCParsedAsmOperand*> &operands,
+ llvm::SmallVectorImpl<llvm::AsmToken> &tokens,
+ const std::string &str);
+
+ /// llvmSyntaxVariant - returns the LLVM syntax variant for this disassembler
+ int llvmSyntaxVariant() const;
+};
+
+#endif
diff --git a/tools/edis/EDInst.cpp b/tools/edis/EDInst.cpp
new file mode 100644
index 0000000..9ed2700
--- /dev/null
+++ b/tools/edis/EDInst.cpp
@@ -0,0 +1,205 @@
+//===-EDInst.cpp - LLVM Enhanced Disassembler -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Enhanced Disassembly library's instruction class.
+// The instruction is responsible for vending the string representation,
+// individual tokens, and operands for a single instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EDDisassembler.h"
+#include "EDInst.h"
+#include "EDOperand.h"
+#include "EDToken.h"
+
+#include "llvm/MC/MCInst.h"
+
+using namespace llvm;
+
+EDInst::EDInst(llvm::MCInst *inst,
+ uint64_t byteSize,
+ EDDisassembler &disassembler,
+ const InstInfo *info) :
+ Disassembler(disassembler),
+ Inst(inst),
+ ThisInstInfo(info),
+ ByteSize(byteSize),
+ BranchTarget(-1),
+ MoveSource(-1),
+ MoveTarget(-1) {
+}
+
+EDInst::~EDInst() {
+ unsigned int index;
+ unsigned int numOperands = Operands.size();
+
+ for (index = 0; index < numOperands; ++index)
+ delete Operands[index];
+
+ unsigned int numTokens = Tokens.size();
+
+ for (index = 0; index < numTokens; ++index)
+ delete Tokens[index];
+
+ delete Inst;
+}
+
+uint64_t EDInst::byteSize() {
+ return ByteSize;
+}
+
+int EDInst::stringify() {
+ if (StringifyResult.valid())
+ return StringifyResult.result();
+
+ if (Disassembler.printInst(String, *Inst))
+ return StringifyResult.setResult(-1);
+
+ OperandOrder = ThisInstInfo->operandOrders[Disassembler.llvmSyntaxVariant()];
+
+ return StringifyResult.setResult(0);
+}
+
+int EDInst::getString(const char*& str) {
+ if (stringify())
+ return -1;
+
+ str = String.c_str();
+
+ return 0;
+}
+
+unsigned EDInst::instID() {
+ return Inst->getOpcode();
+}
+
+bool EDInst::isBranch() {
+ if (ThisInstInfo)
+ return ThisInstInfo->instructionFlags & kInstructionFlagBranch;
+ else
+ return false;
+}
+
+bool EDInst::isMove() {
+ if (ThisInstInfo)
+ return ThisInstInfo->instructionFlags & kInstructionFlagMove;
+ else
+ return false;
+}
+
+int EDInst::parseOperands() {
+ if (ParseResult.valid())
+ return ParseResult.result();
+
+ if (!ThisInstInfo)
+ return ParseResult.setResult(-1);
+
+ unsigned int opIndex;
+ unsigned int mcOpIndex = 0;
+
+ for (opIndex = 0; opIndex < ThisInstInfo->numOperands; ++opIndex) {
+ if (isBranch() &&
+ (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)) {
+ BranchTarget = opIndex;
+ }
+ else if (isMove()) {
+ if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagSource)
+ MoveSource = opIndex;
+ else if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)
+ MoveTarget = opIndex;
+ }
+
+ EDOperand *operand = new EDOperand(Disassembler, *this, opIndex, mcOpIndex);
+
+ Operands.push_back(operand);
+ }
+
+ return ParseResult.setResult(0);
+}
+
+int EDInst::branchTargetID() {
+ if (parseOperands())
+ return -1;
+ return BranchTarget;
+}
+
+int EDInst::moveSourceID() {
+ if (parseOperands())
+ return -1;
+ return MoveSource;
+}
+
+int EDInst::moveTargetID() {
+ if (parseOperands())
+ return -1;
+ return MoveTarget;
+}
+
+int EDInst::numOperands() {
+ if (parseOperands())
+ return -1;
+ return Operands.size();
+}
+
+int EDInst::getOperand(EDOperand *&operand, unsigned int index) {
+ if (parseOperands())
+ return -1;
+
+ if (index >= Operands.size())
+ return -1;
+
+ operand = Operands[index];
+ return 0;
+}
+
+int EDInst::tokenize() {
+ if (TokenizeResult.valid())
+ return TokenizeResult.result();
+
+ if (stringify())
+ return TokenizeResult.setResult(-1);
+
+ return TokenizeResult.setResult(EDToken::tokenize(Tokens,
+ String,
+ OperandOrder,
+ Disassembler));
+
+}
+
+int EDInst::numTokens() {
+ if (tokenize())
+ return -1;
+ return Tokens.size();
+}
+
+int EDInst::getToken(EDToken *&token, unsigned int index) {
+ if (tokenize())
+ return -1;
+ token = Tokens[index];
+ return 0;
+}
+
+#ifdef __BLOCKS__
+int EDInst::visitTokens(EDTokenVisitor_t visitor) {
+ if (tokenize())
+ return -1;
+
+ tokvec_t::iterator iter;
+
+ for (iter = Tokens.begin(); iter != Tokens.end(); ++iter) {
+ int ret = visitor(*iter);
+ if (ret == 1)
+ return 0;
+ if (ret != 0)
+ return -1;
+ }
+
+ return 0;
+}
+#endif
diff --git a/tools/edis/EDInst.h b/tools/edis/EDInst.h
new file mode 100644
index 0000000..db03a78
--- /dev/null
+++ b/tools/edis/EDInst.h
@@ -0,0 +1,171 @@
+//===-EDInst.h - LLVM Enhanced Disassembler ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for the Enhanced Disassembly library's
+// instruction class. The instruction is responsible for vending the string
+// representation, individual tokens and operands for a single instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EDInst_
+#define EDInst_
+
+#include "llvm-c/EnhancedDisassembly.h"
+
+#include "llvm/ADT/SmallVector.h"
+
+#include <string>
+#include <vector>
+
+/// CachedResult - Encapsulates the result of a function along with the validity
+/// of that result, so that slow functions don't need to run twice
+struct CachedResult {
+ /// True if the result has been obtained by executing the function
+ bool Valid;
+ /// The result last obtained from the function
+ int Result;
+
+ /// Constructor - Initializes an invalid result
+ CachedResult() : Valid(false) { }
+ /// valid - Returns true if the result has been obtained by executing the
+ /// function and false otherwise
+ bool valid() { return Valid; }
+ /// result - Returns the result of the function or an undefined value if
+ /// valid() is false
+ int result() { return Result; }
+ /// setResult - Sets the result of the function and declares it valid
+ /// returning the result (so that setResult() can be called from inside a
+ /// return statement)
+ /// @arg result - The result of the function
+ int setResult(int result) { Result = result; Valid = true; return result; }
+};
+
+/// EDInst - Encapsulates a single instruction, which can be queried for its
+/// string representation, as well as its operands and tokens
+struct EDInst {
+ /// The parent disassembler
+ EDDisassembler &Disassembler;
+ /// The containing MCInst
+ llvm::MCInst *Inst;
+ /// The instruction information provided by TableGen for this instruction
+ const InstInfo *ThisInstInfo;
+ /// The number of bytes for the machine code representation of the instruction
+ uint64_t ByteSize;
+
+ /// The result of the stringify() function
+ CachedResult StringifyResult;
+ /// The string representation of the instruction
+ std::string String;
+ /// The order in which operands from the InstInfo's operand information appear
+ /// in String
+ const char* OperandOrder;
+
+ /// The result of the parseOperands() function
+ CachedResult ParseResult;
+ typedef llvm::SmallVector<EDOperand*, 5> opvec_t;
+ /// The instruction's operands
+ opvec_t Operands;
+ /// The operand corresponding to the target, if the instruction is a branch
+ int BranchTarget;
+ /// The operand corresponding to the source, if the instruction is a move
+ int MoveSource;
+ /// The operand corresponding to the target, if the instruction is a move
+ int MoveTarget;
+
+ /// The result of the tokenize() function
+ CachedResult TokenizeResult;
+ typedef std::vector<EDToken*> tokvec_t;
+ /// The instruction's tokens
+ tokvec_t Tokens;
+
+ /// Constructor - initializes an instruction given the output of the LLVM
+ /// C++ disassembler
+ ///
+ /// @arg inst - The MCInst, which will now be owned by this object
+ /// @arg byteSize - The size of the consumed instruction, in bytes
+ /// @arg disassembler - The parent disassembler
+ /// @arg instInfo - The instruction information produced by the table
+ /// generator for this instruction
+ EDInst(llvm::MCInst *inst,
+ uint64_t byteSize,
+ EDDisassembler &disassembler,
+ const InstInfo *instInfo);
+ ~EDInst();
+
+ /// byteSize - returns the number of bytes consumed by the machine code
+ /// representation of the instruction
+ uint64_t byteSize();
+ /// instID - returns the LLVM instruction ID of the instruction
+ unsigned instID();
+
+ /// stringify - populates the String and AsmString members of the instruction,
+ /// returning 0 on success or -1 otherwise
+ int stringify();
+ /// getString - retrieves a pointer to the string representation of the
+ /// instructinon, returning 0 on success or -1 otherwise
+ ///
+ /// @arg str - A reference to a pointer that, on success, is set to point to
+ /// the string representation of the instruction; this string is still owned
+ /// by the instruction and will be deleted when it is
+ int getString(const char *&str);
+
+ /// isBranch - Returns true if the instruction is a branch
+ bool isBranch();
+ /// isMove - Returns true if the instruction is a move
+ bool isMove();
+
+ /// parseOperands - populates the Operands member of the instruction,
+ /// returning 0 on success or -1 otherwise
+ int parseOperands();
+ /// branchTargetID - returns the ID (suitable for use with getOperand()) of
+ /// the target operand if the instruction is a branch, or -1 otherwise
+ int branchTargetID();
+ /// moveSourceID - returns the ID of the source operand if the instruction
+ /// is a move, or -1 otherwise
+ int moveSourceID();
+ /// moveTargetID - returns the ID of the target operand if the instruction
+ /// is a move, or -1 otherwise
+ int moveTargetID();
+
+ /// numOperands - returns the number of operands available to retrieve, or -1
+ /// on error
+ int numOperands();
+ /// getOperand - retrieves an operand from the instruction's operand list by
+ /// index, returning 0 on success or -1 on error
+ ///
+ /// @arg operand - A reference whose target is pointed at the operand on
+ /// success, although the operand is still owned by the EDInst
+ /// @arg index - The index of the operand in the instruction
+ int getOperand(EDOperand *&operand, unsigned int index);
+
+ /// tokenize - populates the Tokens member of the instruction, returning 0 on
+ /// success or -1 otherwise
+ int tokenize();
+ /// numTokens - returns the number of tokens in the instruction, or -1 on
+ /// error
+ int numTokens();
+ /// getToken - retrieves a token from the instruction's token list by index,
+ /// returning 0 on success or -1 on error
+ ///
+ /// @arg token - A reference whose target is pointed at the token on success,
+ /// although the token is still owned by the EDInst
+ /// @arg index - The index of the token in the instrcutino
+ int getToken(EDToken *&token, unsigned int index);
+
+#ifdef __BLOCKS__
+ /// visitTokens - Visits each token in turn and applies a block to it,
+ /// returning 0 if all blocks are visited and/or the block signals
+ /// termination by returning 1; returns -1 on error
+ ///
+ /// @arg visitor - The visitor block to apply to all tokens.
+ int visitTokens(EDTokenVisitor_t visitor);
+#endif
+};
+
+#endif
diff --git a/tools/edis/EDMain.cpp b/tools/edis/EDMain.cpp
new file mode 100644
index 0000000..3585657
--- /dev/null
+++ b/tools/edis/EDMain.cpp
@@ -0,0 +1,293 @@
+//===-EDMain.cpp - LLVM Enhanced Disassembly C API ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the enhanced disassembler's public C API.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EDDisassembler.h"
+#include "EDInst.h"
+#include "EDOperand.h"
+#include "EDToken.h"
+
+#include "llvm-c/EnhancedDisassembly.h"
+
+int EDGetDisassembler(EDDisassemblerRef *disassembler,
+ const char *triple,
+ EDAssemblySyntax_t syntax) {
+ EDDisassembler::initialize();
+
+ EDDisassemblerRef ret = EDDisassembler::getDisassembler(triple,
+ syntax);
+
+ if (ret) {
+ *disassembler = ret;
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+int EDGetRegisterName(const char** regName,
+ EDDisassemblerRef disassembler,
+ unsigned regID) {
+ const char* name = disassembler->nameWithRegisterID(regID);
+ if(!name)
+ return -1;
+ *regName = name;
+ return 0;
+}
+
+int EDRegisterIsStackPointer(EDDisassemblerRef disassembler,
+ unsigned regID) {
+ return disassembler->registerIsStackPointer(regID) ? 1 : 0;
+}
+
+int EDRegisterIsProgramCounter(EDDisassemblerRef disassembler,
+ unsigned regID) {
+ return disassembler->registerIsProgramCounter(regID) ? 1 : 0;
+}
+
+unsigned int EDCreateInsts(EDInstRef *insts,
+ unsigned int count,
+ EDDisassemblerRef disassembler,
+ EDByteReaderCallback byteReader,
+ uint64_t address,
+ void *arg) {
+ unsigned int index;
+
+ for (index = 0; index < count; index++) {
+ EDInst *inst = disassembler->createInst(byteReader, address, arg);
+
+ if(!inst)
+ return index;
+
+ insts[index] = inst;
+ address += inst->byteSize();
+ }
+
+ return count;
+}
+
+void EDReleaseInst(EDInstRef inst) {
+ delete inst;
+}
+
+int EDInstByteSize(EDInstRef inst) {
+ return inst->byteSize();
+}
+
+int EDGetInstString(const char **buf,
+ EDInstRef inst) {
+ return inst->getString(*buf);
+}
+
+int EDInstID(unsigned *instID, EDInstRef inst) {
+ *instID = inst->instID();
+ return 0;
+}
+
+int EDInstIsBranch(EDInstRef inst) {
+ return inst->isBranch();
+}
+
+int EDInstIsMove(EDInstRef inst) {
+ return inst->isMove();
+}
+
+int EDBranchTargetID(EDInstRef inst) {
+ return inst->branchTargetID();
+}
+
+int EDMoveSourceID(EDInstRef inst) {
+ return inst->moveSourceID();
+}
+
+int EDMoveTargetID(EDInstRef inst) {
+ return inst->moveTargetID();
+}
+
+int EDNumTokens(EDInstRef inst) {
+ return inst->numTokens();
+}
+
+int EDGetToken(EDTokenRef *token,
+ EDInstRef inst,
+ int index) {
+ return inst->getToken(*token, index);
+}
+
+int EDGetTokenString(const char **buf,
+ EDTokenRef token) {
+ return token->getString(*buf);
+}
+
+int EDOperandIndexForToken(EDTokenRef token) {
+ return token->operandID();
+}
+
+int EDTokenIsWhitespace(EDTokenRef token) {
+ if(token->type() == EDToken::kTokenWhitespace)
+ return 1;
+ else
+ return 0;
+}
+
+int EDTokenIsPunctuation(EDTokenRef token) {
+ if(token->type() == EDToken::kTokenPunctuation)
+ return 1;
+ else
+ return 0;
+}
+
+int EDTokenIsOpcode(EDTokenRef token) {
+ if(token->type() == EDToken::kTokenOpcode)
+ return 1;
+ else
+ return 0;
+}
+
+int EDTokenIsLiteral(EDTokenRef token) {
+ if(token->type() == EDToken::kTokenLiteral)
+ return 1;
+ else
+ return 0;
+}
+
+int EDTokenIsRegister(EDTokenRef token) {
+ if(token->type() == EDToken::kTokenRegister)
+ return 1;
+ else
+ return 0;
+}
+
+int EDTokenIsNegativeLiteral(EDTokenRef token) {
+ if(token->type() != EDToken::kTokenLiteral)
+ return -1;
+
+ return token->literalSign();
+}
+
+int EDLiteralTokenAbsoluteValue(uint64_t *value,
+ EDTokenRef token) {
+ if(token->type() != EDToken::kTokenLiteral)
+ return -1;
+
+ return token->literalAbsoluteValue(*value);
+}
+
+int EDRegisterTokenValue(unsigned *registerID,
+ EDTokenRef token) {
+ if(token->type() != EDToken::kTokenRegister)
+ return -1;
+
+ return token->registerID(*registerID);
+}
+
+int EDNumOperands(EDInstRef inst) {
+ return inst->numOperands();
+}
+
+int EDGetOperand(EDOperandRef *operand,
+ EDInstRef inst,
+ int index) {
+ return inst->getOperand(*operand, index);
+}
+
+int EDOperandIsRegister(EDOperandRef operand) {
+ return operand->isRegister();
+}
+
+int EDOperandIsImmediate(EDOperandRef operand) {
+ return operand->isImmediate();
+}
+
+int EDOperandIsMemory(EDOperandRef operand) {
+ return operand->isMemory();
+}
+
+int EDRegisterOperandValue(unsigned *value,
+ EDOperandRef operand) {
+ if(!operand->isRegister())
+ return -1;
+ *value = operand->regVal();
+ return 0;
+}
+
+int EDImmediateOperandValue(uint64_t *value,
+ EDOperandRef operand) {
+ if(!operand->isImmediate())
+ return -1;
+ *value = operand->immediateVal();
+ return 0;
+}
+
+int EDEvaluateOperand(uint64_t *result,
+ EDOperandRef operand,
+ EDRegisterReaderCallback regReader,
+ void *arg) {
+ return operand->evaluate(*result, regReader, arg);
+}
+
+#ifdef __BLOCKS__
+
+struct ByteReaderWrapper {
+ EDByteBlock_t byteBlock;
+};
+
+static int readerWrapperCallback(uint8_t *byte,
+ uint64_t address,
+ void *arg) {
+ struct ByteReaderWrapper *wrapper = (struct ByteReaderWrapper *)arg;
+ return wrapper->byteBlock(byte, address);
+}
+
+unsigned int EDBlockCreateInsts(EDInstRef *insts,
+ int count,
+ EDDisassemblerRef disassembler,
+ EDByteBlock_t byteBlock,
+ uint64_t address) {
+ struct ByteReaderWrapper wrapper;
+ wrapper.byteBlock = byteBlock;
+
+ return EDCreateInsts(insts,
+ count,
+ disassembler,
+ readerWrapperCallback,
+ address,
+ (void*)&wrapper);
+}
+
+int EDBlockEvaluateOperand(uint64_t *result,
+ EDOperandRef operand,
+ EDRegisterBlock_t regBlock) {
+ return operand->evaluate(*result, regBlock);
+}
+
+int EDBlockVisitTokens(EDInstRef inst,
+ EDTokenVisitor_t visitor) {
+ return inst->visitTokens(visitor);
+}
+
+#else
+
+extern "C" unsigned int EDBlockCreateInsts() {
+ return 0;
+}
+
+extern "C" int EDBlockEvaluateOperand() {
+ return -1;
+}
+
+extern "C" int EDBlockVisitTokens() {
+ return -1;
+}
+
+#endif
diff --git a/tools/edis/EDOperand.cpp b/tools/edis/EDOperand.cpp
new file mode 100644
index 0000000..da6797e
--- /dev/null
+++ b/tools/edis/EDOperand.cpp
@@ -0,0 +1,168 @@
+//===-EDOperand.cpp - LLVM Enhanced Disassembler --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Enhanced Disassembly library's operand class. The
+// operand is responsible for allowing evaluation given a particular register
+// context.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EDDisassembler.h"
+#include "EDInst.h"
+#include "EDOperand.h"
+
+#include "llvm/MC/MCInst.h"
+
+using namespace llvm;
+
+EDOperand::EDOperand(const EDDisassembler &disassembler,
+ const EDInst &inst,
+ unsigned int opIndex,
+ unsigned int &mcOpIndex) :
+ Disassembler(disassembler),
+ Inst(inst),
+ OpIndex(opIndex),
+ MCOpIndex(mcOpIndex) {
+ unsigned int numMCOperands = 0;
+
+ if(Disassembler.Key.Arch == Triple::x86 ||
+ Disassembler.Key.Arch == Triple::x86_64) {
+ uint8_t operandFlags = inst.ThisInstInfo->operandFlags[opIndex];
+
+ if (operandFlags & kOperandFlagImmediate) {
+ numMCOperands = 1;
+ }
+ else if (operandFlags & kOperandFlagRegister) {
+ numMCOperands = 1;
+ }
+ else if (operandFlags & kOperandFlagMemory) {
+ if (operandFlags & kOperandFlagPCRelative) {
+ numMCOperands = 1;
+ }
+ else {
+ numMCOperands = 5;
+ }
+ }
+ else if (operandFlags & kOperandFlagEffectiveAddress) {
+ numMCOperands = 4;
+ }
+ }
+
+ mcOpIndex += numMCOperands;
+}
+
+EDOperand::~EDOperand() {
+}
+
+int EDOperand::evaluate(uint64_t &result,
+ EDRegisterReaderCallback callback,
+ void *arg) {
+ if (Disassembler.Key.Arch == Triple::x86 ||
+ Disassembler.Key.Arch == Triple::x86_64) {
+ uint8_t operandFlags = Inst.ThisInstInfo->operandFlags[OpIndex];
+
+ if (operandFlags & kOperandFlagImmediate) {
+ result = Inst.Inst->getOperand(MCOpIndex).getImm();
+ return 0;
+ }
+ if (operandFlags & kOperandFlagRegister) {
+ unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
+ return callback(&result, reg, arg);
+ }
+ if (operandFlags & kOperandFlagMemory ||
+ operandFlags & kOperandFlagEffectiveAddress){
+ if(operandFlags & kOperandFlagPCRelative) {
+ int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
+
+ uint64_t ripVal;
+
+ // TODO fix how we do this
+
+ if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
+ return -1;
+
+ result = ripVal + displacement;
+ return 0;
+ }
+ else {
+ unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
+ uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
+ unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
+ int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
+ //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
+
+ uint64_t addr = 0;
+
+ if(baseReg) {
+ uint64_t baseVal;
+ if (callback(&baseVal, baseReg, arg))
+ return -1;
+ addr += baseVal;
+ }
+
+ if(indexReg) {
+ uint64_t indexVal;
+ if (callback(&indexVal, indexReg, arg))
+ return -1;
+ addr += (scaleAmount * indexVal);
+ }
+
+ addr += displacement;
+
+ result = addr;
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ return -1;
+}
+
+int EDOperand::isRegister() {
+ return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagRegister);
+}
+
+unsigned EDOperand::regVal() {
+ return Inst.Inst->getOperand(MCOpIndex).getReg();
+}
+
+int EDOperand::isImmediate() {
+ return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagImmediate);
+}
+
+uint64_t EDOperand::immediateVal() {
+ return Inst.Inst->getOperand(MCOpIndex).getImm();
+}
+
+int EDOperand::isMemory() {
+ return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagMemory);
+}
+
+#ifdef __BLOCKS__
+struct RegisterReaderWrapper {
+ EDRegisterBlock_t regBlock;
+};
+
+int readerWrapperCallback(uint64_t *value,
+ unsigned regID,
+ void *arg) {
+ struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
+ return wrapper->regBlock(value, regID);
+}
+
+int EDOperand::evaluate(uint64_t &result,
+ EDRegisterBlock_t regBlock) {
+ struct RegisterReaderWrapper wrapper;
+ wrapper.regBlock = regBlock;
+ return evaluate(result,
+ readerWrapperCallback,
+ (void*)&wrapper);
+}
+#endif
diff --git a/tools/edis/EDOperand.h b/tools/edis/EDOperand.h
new file mode 100644
index 0000000..ad9345b
--- /dev/null
+++ b/tools/edis/EDOperand.h
@@ -0,0 +1,78 @@
+//===-EDOperand.h - LLVM Enhanced Disassembler ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for the Enhanced Disassembly library's
+// operand class. The operand is responsible for allowing evaluation given a
+// particular register context.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EDOperand_
+#define EDOperand_
+
+#include "llvm-c/EnhancedDisassembly.h"
+
+/// EDOperand - Encapsulates a single operand, which can be evaluated by the
+/// client
+struct EDOperand {
+ /// The parent disassembler
+ const EDDisassembler &Disassembler;
+ /// The parent instruction
+ const EDInst &Inst;
+
+ /// The index of the operand in the EDInst
+ unsigned int OpIndex;
+ /// The index of the first component of the operand in the MCInst
+ unsigned int MCOpIndex;
+
+ /// Constructor - Initializes an EDOperand
+ ///
+ /// @arg disassembler - The disassembler responsible for the operand
+ /// @arg inst - The instruction containing this operand
+ /// @arg opIndex - The index of the operand in inst
+ /// @arg mcOpIndex - The index of the operand in the original MCInst
+ EDOperand(const EDDisassembler &disassembler,
+ const EDInst &inst,
+ unsigned int opIndex,
+ unsigned int &mcOpIndex);
+ ~EDOperand();
+
+ /// evaluate - Returns the numeric value of an operand to the extent possible,
+ /// returning 0 on success or -1 if there was some problem (such as a
+ /// register not being readable)
+ ///
+ /// @arg result - A reference whose target is filled in with the value of
+ /// the operand (the address if it is a memory operand)
+ /// @arg callback - A function to call to obtain register values
+ /// @arg arg - An opaque argument to pass to callback
+ int evaluate(uint64_t &result,
+ EDRegisterReaderCallback callback,
+ void *arg);
+
+ /// isRegister - Returns 1 if the operand is a register or 0 otherwise
+ int isRegister();
+ /// regVal - Returns the register value.
+ unsigned regVal();
+
+ /// isImmediate - Returns 1 if the operand is an immediate or 0 otherwise
+ int isImmediate();
+ /// immediateVal - Returns the immediate value.
+ uint64_t immediateVal();
+
+ /// isMemory - Returns 1 if the operand is a memory location or 0 otherwise
+ int isMemory();
+
+#ifdef __BLOCKS__
+ /// evaluate - Like evaluate for a callback, but uses a block instead
+ int evaluate(uint64_t &result,
+ EDRegisterBlock_t regBlock);
+#endif
+};
+
+#endif
diff --git a/tools/edis/EDToken.cpp b/tools/edis/EDToken.cpp
new file mode 100644
index 0000000..cd79152
--- /dev/null
+++ b/tools/edis/EDToken.cpp
@@ -0,0 +1,208 @@
+//===-EDToken.cpp - LLVM Enhanced Disassembler ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Enhanced Disassembler library's token class. The
+// token is responsible for vending information about the token, such as its
+// type and logical value.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EDDisassembler.h"
+#include "EDToken.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+
+using namespace llvm;
+
+EDToken::EDToken(StringRef str,
+ enum tokenType type,
+ uint64_t localType,
+ EDDisassembler &disassembler) :
+ Disassembler(disassembler),
+ Str(str),
+ Type(type),
+ LocalType(localType),
+ OperandID(-1) {
+}
+
+EDToken::~EDToken() {
+}
+
+void EDToken::makeLiteral(bool sign, uint64_t absoluteValue) {
+ Type = kTokenLiteral;
+ LiteralSign = sign;
+ LiteralAbsoluteValue = absoluteValue;
+}
+
+void EDToken::makeRegister(unsigned registerID) {
+ Type = kTokenRegister;
+ RegisterID = registerID;
+}
+
+void EDToken::setOperandID(int operandID) {
+ OperandID = operandID;
+}
+
+enum EDToken::tokenType EDToken::type() const {
+ return Type;
+}
+
+uint64_t EDToken::localType() const {
+ return LocalType;
+}
+
+StringRef EDToken::string() const {
+ return Str;
+}
+
+int EDToken::operandID() const {
+ return OperandID;
+}
+
+int EDToken::literalSign() const {
+ if(Type != kTokenLiteral)
+ return -1;
+ return (LiteralSign ? 1 : 0);
+}
+
+int EDToken::literalAbsoluteValue(uint64_t &value) const {
+ if(Type != kTokenLiteral)
+ return -1;
+ value = LiteralAbsoluteValue;
+ return 0;
+}
+
+int EDToken::registerID(unsigned &registerID) const {
+ if(Type != kTokenRegister)
+ return -1;
+ registerID = RegisterID;
+ return 0;
+}
+
+int EDToken::tokenize(std::vector<EDToken*> &tokens,
+ std::string &str,
+ const char *operandOrder,
+ EDDisassembler &disassembler) {
+ SmallVector<MCParsedAsmOperand*, 5> parsedOperands;
+ SmallVector<AsmToken, 10> asmTokens;
+
+ if(disassembler.parseInst(parsedOperands, asmTokens, str))
+ return -1;
+
+ SmallVectorImpl<MCParsedAsmOperand*>::iterator operandIterator;
+ unsigned int operandIndex;
+ SmallVectorImpl<AsmToken>::iterator tokenIterator;
+
+ operandIterator = parsedOperands.begin();
+ operandIndex = 0;
+
+ bool readOpcode = false;
+
+ const char *wsPointer = asmTokens.begin()->getLoc().getPointer();
+
+ for (tokenIterator = asmTokens.begin();
+ tokenIterator != asmTokens.end();
+ ++tokenIterator) {
+ SMLoc tokenLoc = tokenIterator->getLoc();
+
+ const char *tokenPointer = tokenLoc.getPointer();
+
+ if(tokenPointer > wsPointer) {
+ unsigned long wsLength = tokenPointer - wsPointer;
+
+ EDToken *whitespaceToken = new EDToken(StringRef(wsPointer, wsLength),
+ EDToken::kTokenWhitespace,
+ 0,
+ disassembler);
+
+ tokens.push_back(whitespaceToken);
+ }
+
+ wsPointer = tokenPointer + tokenIterator->getString().size();
+
+ while (operandIterator != parsedOperands.end() &&
+ tokenLoc.getPointer() >
+ (*operandIterator)->getEndLoc().getPointer()) {
+ ++operandIterator;
+ ++operandIndex;
+ }
+
+ EDToken *token;
+
+ switch (tokenIterator->getKind()) {
+ case AsmToken::Identifier:
+ if (!readOpcode) {
+ token = new EDToken(tokenIterator->getString(),
+ EDToken::kTokenOpcode,
+ (uint64_t)tokenIterator->getKind(),
+ disassembler);
+ readOpcode = true;
+ break;
+ }
+ // any identifier that isn't an opcode is mere punctuation; so we fall
+ // through
+ default:
+ token = new EDToken(tokenIterator->getString(),
+ EDToken::kTokenPunctuation,
+ (uint64_t)tokenIterator->getKind(),
+ disassembler);
+ break;
+ case AsmToken::Integer:
+ {
+ token = new EDToken(tokenIterator->getString(),
+ EDToken::kTokenLiteral,
+ (uint64_t)tokenIterator->getKind(),
+ disassembler);
+
+ int64_t intVal = tokenIterator->getIntVal();
+
+ if(intVal < 0)
+ token->makeLiteral(true, -intVal);
+ else
+ token->makeLiteral(false, intVal);
+ break;
+ }
+ case AsmToken::Register:
+ {
+ token = new EDToken(tokenIterator->getString(),
+ EDToken::kTokenLiteral,
+ (uint64_t)tokenIterator->getKind(),
+ disassembler);
+
+ token->makeRegister((unsigned)tokenIterator->getRegVal());
+ break;
+ }
+ }
+
+ if(operandIterator != parsedOperands.end() &&
+ tokenLoc.getPointer() >=
+ (*operandIterator)->getStartLoc().getPointer()) {
+ /// operandIndex == 0 means the operand is the instruction (which the
+ /// AsmParser treats as an operand but edis does not). We therefore skip
+ /// operandIndex == 0 and subtract 1 from all other operand indices.
+
+ if(operandIndex > 0)
+ token->setOperandID(operandOrder[operandIndex - 1]);
+ }
+
+ tokens.push_back(token);
+ }
+
+ return 0;
+}
+
+int EDToken::getString(const char*& buf) {
+ if(PermStr.length() == 0) {
+ PermStr = Str.str();
+ }
+ buf = PermStr.c_str();
+ return 0;
+}
diff --git a/tools/edis/EDToken.h b/tools/edis/EDToken.h
new file mode 100644
index 0000000..e4ae91f
--- /dev/null
+++ b/tools/edis/EDToken.h
@@ -0,0 +1,135 @@
+//===-EDToken.h - LLVM Enhanced Disassembler --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for the Enhanced Disassembly library's token
+// class. The token is responsible for vending information about the token,
+// such as its type and logical value.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EDToken_
+#define EDToken_
+
+#include "llvm-c/EnhancedDisassembly.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <string>
+#include <vector>
+
+/// EDToken - Encapsulates a single token, which can provide a string
+/// representation of itself or interpret itself in various ways, depending
+/// on the token type.
+struct EDToken {
+ enum tokenType {
+ kTokenWhitespace,
+ kTokenOpcode,
+ kTokenLiteral,
+ kTokenRegister,
+ kTokenPunctuation
+ };
+
+ /// The parent disassembler
+ EDDisassembler &Disassembler;
+
+ /// The token's string representation
+ llvm::StringRef Str;
+ /// The token's string representation, but in a form suitable for export
+ std::string PermStr;
+ /// The type of the token, as exposed through the external API
+ enum tokenType Type;
+ /// The type of the token, as recorded by the syntax-specific tokenizer
+ uint64_t LocalType;
+ /// The operand corresponding to the token, or (unsigned int)-1 if not
+ /// part of an operand.
+ int OperandID;
+
+ /// The sign if the token is a literal (1 if negative, 0 otherwise)
+ bool LiteralSign;
+ /// The absolute value if the token is a literal
+ uint64_t LiteralAbsoluteValue;
+ /// The LLVM register ID if the token is a register name
+ unsigned RegisterID;
+
+ /// Constructor - Initializes an EDToken with the information common to all
+ /// tokens
+ ///
+ /// @arg str - The string corresponding to the token
+ /// @arg type - The token's type as exposed through the public API
+ /// @arg localType - The token's type as recorded by the tokenizer
+ /// @arg disassembler - The disassembler responsible for the token
+ EDToken(llvm::StringRef str,
+ enum tokenType type,
+ uint64_t localType,
+ EDDisassembler &disassembler);
+
+ /// makeLiteral - Adds the information specific to a literal
+ /// @arg sign - The sign of the literal (1 if negative, 0
+ /// otherwise)
+ ///
+ /// @arg absoluteValue - The absolute value of the literal
+ void makeLiteral(bool sign, uint64_t absoluteValue);
+ /// makeRegister - Adds the information specific to a register
+ ///
+ /// @arg registerID - The LLVM register ID
+ void makeRegister(unsigned registerID);
+
+ /// setOperandID - Links the token to a numbered operand
+ ///
+ /// @arg operandID - The operand ID to link to
+ void setOperandID(int operandID);
+
+ ~EDToken();
+
+ /// type - Returns the public type of the token
+ enum tokenType type() const;
+ /// localType - Returns the tokenizer-specific type of the token
+ uint64_t localType() const;
+ /// string - Returns the string representation of the token
+ llvm::StringRef string() const;
+ /// operandID - Returns the operand ID of the token
+ int operandID() const;
+
+ /// literalSign - Returns the sign of the token
+ /// (1 if negative, 0 if positive or unsigned, -1 if it is not a literal)
+ int literalSign() const;
+ /// literalAbsoluteValue - Retrieves the absolute value of the token, and
+ /// returns -1 if the token is not a literal
+ /// @arg value - A reference to a value that is filled in with the absolute
+ /// value, if it is valid
+ int literalAbsoluteValue(uint64_t &value) const;
+ /// registerID - Retrieves the register ID of the token, and returns -1 if the
+ /// token is not a register
+ ///
+ /// @arg registerID - A reference to a value that is filled in with the
+ /// register ID, if it is valid
+ int registerID(unsigned &registerID) const;
+
+ /// tokenize - Tokenizes a string using the platform- and syntax-specific
+ /// tokenizer, and returns 0 on success (-1 on failure)
+ ///
+ /// @arg tokens - A vector that will be filled in with pointers to
+ /// allocated tokens
+ /// @arg str - The string, as outputted by the AsmPrinter
+ /// @arg operandOrder - The order of the operands from the operandFlags array
+ /// as they appear in str
+ /// @arg disassembler - The disassembler for the desired target and
+ // assembly syntax
+ static int tokenize(std::vector<EDToken*> &tokens,
+ std::string &str,
+ const char *operandOrder,
+ EDDisassembler &disassembler);
+
+ /// getString - Directs a character pointer to the string, returning 0 on
+ /// success (-1 on failure)
+ /// @arg buf - A reference to a pointer that is set to point to the string.
+ /// The string is still owned by the token.
+ int getString(const char*& buf);
+};
+
+#endif
diff --git a/tools/edis/EnhancedDisassembly.exports b/tools/edis/EnhancedDisassembly.exports
new file mode 100644
index 0000000..d3f8743
--- /dev/null
+++ b/tools/edis/EnhancedDisassembly.exports
@@ -0,0 +1,36 @@
+_EDGetDisassembler
+_EDGetRegisterName
+_EDRegisterIsStackPointer
+_EDRegisterIsProgramCounter
+_EDCreateInsts
+_EDReleaseInst
+_EDInstByteSize
+_EDGetInstString
+_EDInstIsBranch
+_EDInstIsMove
+_EDBranchTargetID
+_EDMoveSourceID
+_EDMoveTargetID
+_EDNumTokens
+_EDGetToken
+_EDGetTokenString
+_EDOperandIndexForToken
+_EDTokenIsWhitespace
+_EDTokenIsPunctuation
+_EDTokenIsOpcode
+_EDTokenIsLiteral
+_EDTokenIsRegister
+_EDTokenIsNegativeLiteral
+_EDLiteralTokenAbsoluteValue
+_EDRegisterTokenValue
+_EDNumOperands
+_EDGetOperand
+_EDOperandIsRegister
+_EDOperandIsImmediate
+_EDOperandIsMemory
+_EDRegisterOperandValue
+_EDImmediateOperandValue
+_EDEvaluateOperand
+_EDBlockCreateInsts
+_EDBlockEvaluateOperand
+_EDBlockVisitTokens
diff --git a/tools/edis/Makefile b/tools/edis/Makefile
new file mode 100644
index 0000000..a3c5879
--- /dev/null
+++ b/tools/edis/Makefile
@@ -0,0 +1,55 @@
+##===- tools/ed/Makefile -----------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+LIBRARYNAME = EnhancedDisassembly
+
+BUILT_SOURCES = EDInfo.inc
+
+# Include this here so we can get the configuration of the targets
+# that have been configured for construction. We have to do this
+# early so we can set up LINK_COMPONENTS before including Makefile.rules
+include $(LEVEL)/Makefile.config
+
+LINK_LIBS_IN_SHARED = 1
+SHARED_LIBRARY = 1
+
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) x86asmprinter x86disassembler
+
+include $(LEVEL)/Makefile.common
+
+ifeq ($(HOST_OS),Darwin)
+ # set dylib internal version number to llvmCore submission number
+ ifdef LLVM_SUBMIT_VERSION
+ LLVMLibsOptions := $(LLVMLibsOptions) -Wl,-current_version \
+ -Wl,$(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION) \
+ -Wl,-compatibility_version -Wl,1
+ endif
+ # extra options to override libtool defaults
+ LLVMLibsOptions := $(LLVMLibsOptions) \
+ -avoid-version \
+ -Wl,-exported_symbols_list -Wl,$(PROJ_SRC_DIR)/EnhancedDisassembly.exports \
+ -Wl,-dead_strip \
+ -Wl,-seg1addr -Wl,0xE0000000
+
+ # Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line
+ DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
+ ifneq ($(DARWIN_VERS),8)
+ LLVMLibsOptions := $(LLVMLibsOptions) \
+ -no-undefined -Wl,-install_name \
+ -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)"
+ endif
+endif
+
+EDInfo.inc: $(TBLGEN)
+ $(Echo) "Building semantic information header"
+ $(Verb) $(TableGen) -o $(call SYSPATH, $@) -gen-enhanced-disassembly-header /dev/null
+
+clean::
+ -$(Verb) $(RM) -f EDInfo.inc
diff --git a/tools/gold/Makefile b/tools/gold/Makefile
index 3f77229..7bac4ec 100644
--- a/tools/gold/Makefile
+++ b/tools/gold/Makefile
@@ -19,7 +19,6 @@ LINK_LIBS_IN_SHARED=1
SHARED_LIBRARY = 1
BUILD_ARCHIVE = 0
LOADABLE_MODULE = 1
-CXXFLAGS = -fno-rtti
LINK_COMPONENTS := support system
LIBS += -llto
diff --git a/tools/llc/Makefile b/tools/llc/Makefile
index 6b5b125..7319aad 100644
--- a/tools/llc/Makefile
+++ b/tools/llc/Makefile
@@ -9,7 +9,6 @@
LEVEL = ../..
TOOLNAME = llc
-CXXFLAGS = -fno-rtti
# Include this here so we can get the configuration of the targets
# that have been configured for construction. We have to do this
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index 4f93a43..fe34bd1 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -15,16 +15,13 @@
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
-#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/IRReader.h"
-#include "llvm/CodeGen/FileWriters.h"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
-#include "llvm/CodeGen/ObjectCodeEmitter.h"
#include "llvm/Config/config.h"
#include "llvm/LinkAllVMCore.h"
#include "llvm/Support/CommandLine.h"
@@ -87,16 +84,15 @@ MAttrs("mattr",
cl::value_desc("a1,+a2,-a3,..."));
cl::opt<TargetMachine::CodeGenFileType>
-FileType("filetype", cl::init(TargetMachine::AssemblyFile),
+FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
cl::desc("Choose a file type (not all types are supported by all targets):"),
cl::values(
- clEnumValN(TargetMachine::AssemblyFile, "asm",
+ clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm",
"Emit an assembly ('.s') file"),
- clEnumValN(TargetMachine::ObjectFile, "obj",
+ clEnumValN(TargetMachine::CGFT_ObjectFile, "obj",
"Emit a native object ('.o') file [experimental]"),
- clEnumValN(TargetMachine::DynamicLibrary, "dynlib",
- "Emit a native dynamic library ('.so') file"
- " [experimental]"),
+ clEnumValN(TargetMachine::CGFT_Null, "null",
+ "Emit nothing, for performance testing"),
clEnumValEnd));
cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
@@ -164,7 +160,8 @@ static formatted_raw_ostream *GetOutputStream(const char *TargetName,
bool Binary = false;
switch (FileType) {
- case TargetMachine::AssemblyFile:
+ default: assert(0 && "Unknown file type");
+ case TargetMachine::CGFT_AssemblyFile:
if (TargetName[0] == 'c') {
if (TargetName[1] == 0)
OutputFilename += ".cbe.c";
@@ -175,12 +172,12 @@ static formatted_raw_ostream *GetOutputStream(const char *TargetName,
} else
OutputFilename += ".s";
break;
- case TargetMachine::ObjectFile:
+ case TargetMachine::CGFT_ObjectFile:
OutputFilename += ".o";
Binary = true;
break;
- case TargetMachine::DynamicLibrary:
- OutputFilename += LTDL_SHLIB_EXT;
+ case TargetMachine::CGFT_Null:
+ OutputFilename += ".null";
Binary = true;
break;
}
@@ -334,8 +331,7 @@ int main(int argc, char **argv) {
PM.run(mod);
} else {
// Build up all of the passes that we want to do to the module.
- ExistingModuleProvider Provider(M.release());
- FunctionPassManager Passes(&Provider);
+ FunctionPassManager Passes(M.get());
// Add the target data from the target machine, if it exists, or the module.
if (const TargetData *TD = Target.getTargetData())
@@ -348,32 +344,10 @@ int main(int argc, char **argv) {
Passes.add(createVerifierPass());
#endif
- // Ask the target to add backend passes as necessary.
- ObjectCodeEmitter *OCE = 0;
-
// Override default to generate verbose assembly.
Target.setAsmVerbosityDefault(true);
- switch (Target.addPassesToEmitFile(Passes, *Out, FileType, OLvl)) {
- default:
- assert(0 && "Invalid file model!");
- return 1;
- case FileModel::Error:
- errs() << argv[0] << ": target does not support generation of this"
- << " file type!\n";
- if (Out != &fouts()) delete Out;
- // And the Out file is empty and useless, so remove it now.
- sys::Path(OutputFilename).eraseFromDisk();
- return 1;
- case FileModel::AsmFile:
- case FileModel::MachOFile:
- break;
- case FileModel::ElfFile:
- OCE = AddELFWriter(Passes, *Out, Target);
- break;
- }
-
- if (Target.addPassesToEmitFileFinish(Passes, OCE, OLvl)) {
+ if (Target.addPassesToEmitFile(Passes, *Out, FileType, OLvl)) {
errs() << argv[0] << ": target does not support generation of this"
<< " file type!\n";
if (Out != &fouts()) delete Out;
diff --git a/tools/lli/Makefile b/tools/lli/Makefile
index 2341bed..8f6eeed 100644
--- a/tools/lli/Makefile
+++ b/tools/lli/Makefile
@@ -9,7 +9,6 @@
LEVEL := ../..
TOOLNAME := lli
-CXXFLAGS = -fno-rtti
LINK_COMPONENTS := jit interpreter nativecodegen bitreader selectiondag
# Enable JIT support
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index 218bb93..81c17cd 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -15,7 +15,6 @@
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
-#include "llvm/ModuleProvider.h"
#include "llvm/Type.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
@@ -59,6 +58,22 @@ namespace {
TargetTriple("mtriple", cl::desc("Override target triple for module"));
cl::opt<std::string>
+ MArch("march",
+ cl::desc("Architecture to generate assembly for (see --version)"));
+
+ cl::opt<std::string>
+ MCPU("mcpu",
+ cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+ cl::value_desc("cpu-name"),
+ cl::init(""));
+
+ cl::list<std::string>
+ MAttrs("mattr",
+ cl::CommaSeparated,
+ cl::desc("Target specific attributes (-mattr=help for details)"),
+ cl::value_desc("a1,+a2,-a3,..."));
+
+ cl::opt<std::string>
EntryFunc("entry-function",
cl::desc("Specify the entry function (default = 'main') "
"of the executable"),
@@ -110,28 +125,31 @@ int main(int argc, char **argv, char * const *envp) {
// Load the bitcode...
std::string ErrorMsg;
- ModuleProvider *MP = NULL;
+ Module *Mod = NULL;
if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFile,&ErrorMsg)){
- MP = getBitcodeModuleProvider(Buffer, Context, &ErrorMsg);
- if (!MP) delete Buffer;
+ Mod = getLazyBitcodeModule(Buffer, Context, &ErrorMsg);
+ if (!Mod) delete Buffer;
}
- if (!MP) {
+ if (!Mod) {
errs() << argv[0] << ": error loading program '" << InputFile << "': "
<< ErrorMsg << "\n";
exit(1);
}
- // Get the module as the MP could go away once EE takes over.
- Module *Mod = NoLazyCompilation
- ? MP->materializeModule(&ErrorMsg) : MP->getModule();
- if (!Mod) {
- errs() << argv[0] << ": bitcode didn't read correctly.\n";
- errs() << "Reason: " << ErrorMsg << "\n";
- exit(1);
+ // If not jitting lazily, load the whole bitcode file eagerly too.
+ if (NoLazyCompilation) {
+ if (Mod->MaterializeAllPermanently(&ErrorMsg)) {
+ errs() << argv[0] << ": bitcode didn't read correctly.\n";
+ errs() << "Reason: " << ErrorMsg << "\n";
+ exit(1);
+ }
}
- EngineBuilder builder(MP);
+ EngineBuilder builder(Mod);
+ builder.setMArch(MArch);
+ builder.setMCPU(MCPU);
+ builder.setMAttrs(MAttrs);
builder.setErrorStr(&ErrorMsg);
builder.setEngineKind(ForceInterpreter
? EngineKind::Interpreter
diff --git a/tools/llvm-ar/Makefile b/tools/llvm-ar/Makefile
index 3db7964..e4fe4e8 100644
--- a/tools/llvm-ar/Makefile
+++ b/tools/llvm-ar/Makefile
@@ -11,7 +11,6 @@ LEVEL = ../..
TOOLNAME = llvm-ar
LINK_COMPONENTS = archive
REQUIRES_EH := 1
-#CXXFLAGS = -fno-rtti
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/llvm-as/Makefile b/tools/llvm-as/Makefile
index d6fbd71..e1e5853 100644
--- a/tools/llvm-as/Makefile
+++ b/tools/llvm-as/Makefile
@@ -10,7 +10,6 @@
LEVEL = ../..
TOOLNAME = llvm-as
LINK_COMPONENTS := asmparser bitwriter
-CXXFLAGS = -fno-rtti
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/llvm-config/Makefile b/tools/llvm-config/Makefile
index e5bdc04..cc5cf43 100644
--- a/tools/llvm-config/Makefile
+++ b/tools/llvm-config/Makefile
@@ -53,6 +53,46 @@ llvm-config.in: $(ConfigInIn) $(ConfigStatusScript)
$(Verb) cd $(PROJ_OBJ_ROOT) ; \
$(ConfigStatusScript) tools/llvm-config/llvm-config.in
+llvm-config-perobj: llvm-config.in $(GenLibDeps) $(LibDir) $(wildcard $(LibDir)/*.a)
+ $(Echo) "Generating llvm-config-perobj"
+ $(Verb) $(PERL) $(GenLibDeps) -perobj -flat $(LibDir) "$(NM_PATH)" >PerobjDeps.txt
+ $(Echo) "Checking for cyclic dependencies between LLVM objects."
+ $(Verb) $(PERL) $(PROJ_SRC_DIR)/find-cycles.pl < PerobjDepsIncl.txt > PerobjDepsInclFinal.txt || rm -f $@
+ $(Verb) $(ECHO) 's/@LLVM_CPPFLAGS@/$(subst /,\/,$(SUB_CPPFLAGS))/' \
+ > temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_CFLAGS@/$(subst /,\/,$(SUB_CFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_CXXFLAGS@/$(subst /,\/,$(SUB_CXXFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_LDFLAGS@/$(subst /,\/,$(SUB_LDFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_BUILDMODE@/$(subst /,\/,$(BuildMode))/' \
+ >> temp.sed
+ $(Verb) $(SED) -f temp.sed < $< > $@
+ $(Verb) $(RM) temp.sed
+ $(Verb) cat PerobjDepsFinal.txt >> $@
+ $(Verb) chmod +x $@
+
+llvm-config-perobjincl: llvm-config.in $(GenLibDeps) $(LibDir) $(wildcard $(LibDir)/*.a)
+ $(Echo) "Generating llvm-config-perobjincl"
+ $(Verb) $(PERL) $(GenLibDeps) -perobj -perobjincl -flat $(LibDir) "$(NM_PATH)" >PerobjDepsIncl.txt
+ $(Echo) "Checking for cyclic dependencies between LLVM objects."
+ $(Verb) $(PERL) $(PROJ_SRC_DIR)/find-cycles.pl < PerobjDepsIncl.txt > PerobjDepsInclFinal.txt
+ $(Verb) $(ECHO) 's/@LLVM_CPPFLAGS@/$(subst /,\/,$(SUB_CPPFLAGS))/' \
+ > temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_CFLAGS@/$(subst /,\/,$(SUB_CFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_CXXFLAGS@/$(subst /,\/,$(SUB_CXXFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_LDFLAGS@/$(subst /,\/,$(SUB_LDFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_BUILDMODE@/$(subst /,\/,$(BuildMode))/' \
+ >> temp.sed
+ $(Verb) $(SED) -f temp.sed < $< > $@
+ $(Verb) $(RM) temp.sed
+ $(Verb) cat PerobjDepsInclFinal.txt >> $@
+ $(Verb) chmod +x $@
+
# Build our final script.
$(ToolDir)/llvm-config: llvm-config.in $(FinalLibDeps)
$(Echo) "Building llvm-config script."
diff --git a/tools/llvm-config/find-cycles.pl b/tools/llvm-config/find-cycles.pl
index 8156abd..5cbf5b4 100755
--- a/tools/llvm-config/find-cycles.pl
+++ b/tools/llvm-config/find-cycles.pl
@@ -62,6 +62,11 @@ foreach my $cycle (@CYCLES) {
print STDERR "find-cycles.pl: Circular dependency between *.a files:\n";
print STDERR "find-cycles.pl: ", join(' ', @archives), "\n";
push @modules, @archives; # WORKAROUND: Duplicate *.a files. Ick.
+ } elsif (@modules > 1) {
+ $cycles_found = $cycles_found + 1;
+ print STDERR "find-cycles.pl: Circular dependency between *.o files:\n";
+ print STDERR "find-cycles.pl: ", join(' ', @modules), "\n";
+ push @modules, @modules; # WORKAROUND: Duplicate *.o files. Ick.
}
# Add to our output. (@modules is already as sorted as we need it to be.)
diff --git a/tools/llvm-dis/Makefile b/tools/llvm-dis/Makefile
index 96f3cbb..22c9ecc 100644
--- a/tools/llvm-dis/Makefile
+++ b/tools/llvm-dis/Makefile
@@ -10,7 +10,6 @@ LEVEL = ../..
TOOLNAME = llvm-dis
LINK_COMPONENTS := bitreader
-CXXFLAGS = -fno-rtti
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/llvm-extract/Makefile b/tools/llvm-extract/Makefile
index dee0572..5672aa3 100644
--- a/tools/llvm-extract/Makefile
+++ b/tools/llvm-extract/Makefile
@@ -11,7 +11,6 @@ LEVEL = ../..
TOOLNAME = llvm-extract
LINK_COMPONENTS := ipo bitreader bitwriter asmparser
-CXXFLAGS = -fno-rtti
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp
index 517244f..231634c 100644
--- a/tools/llvm-extract/llvm-extract.cpp
+++ b/tools/llvm-extract/llvm-extract.cpp
@@ -49,15 +49,15 @@ static cl::opt<bool>
Relink("relink",
cl::desc("Turn external linkage for callees of function to delete"));
-// ExtractFunc - The function to extract from the module...
-static cl::opt<std::string>
-ExtractFunc("func", cl::desc("Specify function to extract"), cl::init(""),
- cl::value_desc("function"));
+// ExtractFuncs - The functions to extract from the module...
+static cl::list<std::string>
+ExtractFuncs("func", cl::desc("Specify function to extract"),
+ cl::ZeroOrMore, cl::value_desc("function"));
-// ExtractGlobal - The global to extract from the module...
-static cl::opt<std::string>
-ExtractGlobal("glob", cl::desc("Specify global to extract"), cl::init(""),
- cl::value_desc("global"));
+// ExtractGlobals - The globals to extract from the module...
+static cl::list<std::string>
+ExtractGlobals("glob", cl::desc("Specify global to extract"),
+ cl::ZeroOrMore, cl::value_desc("global"));
static cl::opt<bool>
OutputAssembly("S",
@@ -81,28 +81,34 @@ int main(int argc, char **argv) {
return 1;
}
- // Figure out which function we should extract
- GlobalVariable *G = !ExtractGlobal.empty() ?
- M.get()->getNamedGlobal(ExtractGlobal) : 0;
-
- // Figure out which function we should extract
- if (ExtractFunc.empty() && ExtractGlobal.empty()) ExtractFunc = "main";
- Function *F = M.get()->getFunction(ExtractFunc);
+ std::vector<GlobalValue *> GVs;
+
+ // Figure out which globals we should extract.
+ for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) {
+ GlobalValue *GV = M.get()->getNamedGlobal(ExtractGlobals[i]);
+ if (!GV) {
+ errs() << argv[0] << ": program doesn't contain global named '"
+ << ExtractGlobals[i] << "'!\n";
+ return 1;
+ }
+ GVs.push_back(GV);
+ }
- if (F == 0 && G == 0) {
- errs() << argv[0] << ": program doesn't contain function named '"
- << ExtractFunc << "' or a global named '" << ExtractGlobal << "'!\n";
- return 1;
+ // Figure out which functions we should extract.
+ for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) {
+ GlobalValue *GV = M.get()->getFunction(ExtractFuncs[i]);
+ if (!GV) {
+ errs() << argv[0] << ": program doesn't contain function named '"
+ << ExtractFuncs[i] << "'!\n";
+ return 1;
+ }
+ GVs.push_back(GV);
}
// In addition to deleting all other functions, we also want to spiff it
// up a little bit. Do this now.
PassManager Passes;
Passes.add(new TargetData(M.get())); // Use correct TargetData
- // Either isolate the function or delete it from the Module
- std::vector<GlobalValue*> GVs;
- if (F) GVs.push_back(F);
- if (G) GVs.push_back(G);
Passes.add(createGVExtractionPass(GVs, DeleteFn, Relink));
if (!DeleteFn)
diff --git a/tools/llvm-ld/Makefile b/tools/llvm-ld/Makefile
index 1da1966..1ef9bf1 100644
--- a/tools/llvm-ld/Makefile
+++ b/tools/llvm-ld/Makefile
@@ -11,6 +11,5 @@ LEVEL = ../..
TOOLNAME = llvm-ld
LINK_COMPONENTS = ipo scalaropts linker archive bitwriter
-CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp
index e71aefc..118f6b7 100644
--- a/tools/llvm-ld/llvm-ld.cpp
+++ b/tools/llvm-ld/llvm-ld.cpp
@@ -179,8 +179,9 @@ static char ** CopyEnv(char ** const envp) {
// Make a copy of the list. Don't forget the NULL that ends the list.
entries = 0;
while (envp[entries] != NULL) {
- newenv[entries] = new char[strlen (envp[entries]) + 1];
- strcpy (newenv[entries], envp[entries]);
+ size_t len = strlen(envp[entries]) + 1;
+ newenv[entries] = new char[len];
+ memcpy(newenv[entries], envp[entries], len);
++entries;
}
newenv[entries] = NULL;
diff --git a/tools/llvm-link/Makefile b/tools/llvm-link/Makefile
index de592aa..2637018 100644
--- a/tools/llvm-link/Makefile
+++ b/tools/llvm-link/Makefile
@@ -10,7 +10,6 @@ LEVEL = ../..
TOOLNAME = llvm-link
LINK_COMPONENTS = linker bitreader bitwriter asmparser
-CXXFLAGS = -fno-rtti
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/llvm-mc/AsmCond.h b/tools/llvm-mc/AsmCond.h
deleted file mode 100644
index 92a115e..0000000
--- a/tools/llvm-mc/AsmCond.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- AsmCond.h - Assembly file conditional assembly ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ASMCOND_H
-#define ASMCOND_H
-
-namespace llvm {
-
-/// AsmCond - Class to support conditional assembly
-///
-/// The conditional assembly feature (.if, .else, .elseif and .endif) is
-/// implemented with AsmCond that tells us what we are in the middle of
-/// processing. Ignore can be either true or false. When true we are ignoring
-/// the block of code in the middle of a conditional.
-
-class AsmCond {
-public:
- enum ConditionalAssemblyType {
- NoCond, // no conditional is being processed
- IfCond, // inside if conditional
- ElseIfCond, // inside elseif conditional
- ElseCond // inside else conditional
- };
-
- ConditionalAssemblyType TheCond;
- bool CondMet;
- bool Ignore;
-
- AsmCond() : TheCond(NoCond), CondMet(false), Ignore(false) {}
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/tools/llvm-mc/AsmLexer.cpp b/tools/llvm-mc/AsmLexer.cpp
deleted file mode 100644
index 234b8f3..0000000
--- a/tools/llvm-mc/AsmLexer.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the lexer for assembly files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AsmLexer.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Config/config.h" // for strtoull.
-#include "llvm/MC/MCAsmInfo.h"
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-using namespace llvm;
-
-AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) {
- CurBuf = NULL;
- CurPtr = NULL;
- TokStart = 0;
-}
-
-AsmLexer::~AsmLexer() {
-}
-
-void AsmLexer::setBuffer(const MemoryBuffer *buf, const char *ptr) {
- CurBuf = buf;
-
- if (ptr)
- CurPtr = ptr;
- else
- CurPtr = CurBuf->getBufferStart();
-
- TokStart = 0;
-}
-
-SMLoc AsmLexer::getLoc() const {
- return SMLoc::getFromPointer(TokStart);
-}
-
-/// ReturnError - Set the error to the specified string at the specified
-/// location. This is defined to always return AsmToken::Error.
-AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
- SetError(SMLoc::getFromPointer(Loc), Msg);
-
- return AsmToken(AsmToken::Error, StringRef(Loc, 0));
-}
-
-int AsmLexer::getNextChar() {
- char CurChar = *CurPtr++;
- switch (CurChar) {
- default:
- return (unsigned char)CurChar;
- case 0:
- // A nul character in the stream is either the end of the current buffer or
- // a random nul in the file. Disambiguate that here.
- if (CurPtr-1 != CurBuf->getBufferEnd())
- return 0; // Just whitespace.
-
- // Otherwise, return end of file.
- --CurPtr; // Another call to lex will return EOF again.
- return EOF;
- }
-}
-
-/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
-AsmToken AsmLexer::LexIdentifier() {
- while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' ||
- *CurPtr == '.' || *CurPtr == '@')
- ++CurPtr;
- return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
-}
-
-/// LexSlash: Slash: /
-/// C-Style Comment: /* ... */
-AsmToken AsmLexer::LexSlash() {
- switch (*CurPtr) {
- case '*': break; // C style comment.
- case '/': return ++CurPtr, LexLineComment();
- default: return AsmToken(AsmToken::Slash, StringRef(CurPtr, 1));
- }
-
- // C Style comment.
- ++CurPtr; // skip the star.
- while (1) {
- int CurChar = getNextChar();
- switch (CurChar) {
- case EOF:
- return ReturnError(TokStart, "unterminated comment");
- case '*':
- // End of the comment?
- if (CurPtr[0] != '/') break;
-
- ++CurPtr; // End the */.
- return LexToken();
- }
- }
-}
-
-/// LexLineComment: Comment: #[^\n]*
-/// : //[^\n]*
-AsmToken AsmLexer::LexLineComment() {
- // FIXME: This is broken if we happen to a comment at the end of a file, which
- // was .included, and which doesn't end with a newline.
- int CurChar = getNextChar();
- while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF)
- CurChar = getNextChar();
-
- if (CurChar == EOF)
- return AsmToken(AsmToken::Eof, StringRef(CurPtr, 0));
- return AsmToken(AsmToken::EndOfStatement, StringRef(CurPtr, 0));
-}
-
-
-/// LexDigit: First character is [0-9].
-/// Local Label: [0-9][:]
-/// Forward/Backward Label: [0-9][fb]
-/// Binary integer: 0b[01]+
-/// Octal integer: 0[0-7]+
-/// Hex integer: 0x[0-9a-fA-F]+
-/// Decimal integer: [1-9][0-9]*
-/// TODO: FP literal.
-AsmToken AsmLexer::LexDigit() {
- if (*CurPtr == ':')
- return ReturnError(TokStart, "FIXME: local label not implemented");
- if (*CurPtr == 'f' || *CurPtr == 'b')
- return ReturnError(TokStart, "FIXME: directional label not implemented");
-
- // Decimal integer: [1-9][0-9]*
- if (CurPtr[-1] != '0') {
- while (isdigit(*CurPtr))
- ++CurPtr;
- return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
- strtoll(TokStart, 0, 10));
- }
-
- if (*CurPtr == 'b') {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (CurPtr[0] == '0' || CurPtr[0] == '1')
- ++CurPtr;
-
- // Requires at least one binary digit.
- if (CurPtr == NumStart)
- return ReturnError(CurPtr-2, "Invalid binary number");
- return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
- strtoll(NumStart, 0, 2));
- }
-
- if (*CurPtr == 'x') {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (isxdigit(CurPtr[0]))
- ++CurPtr;
-
- // Requires at least one hex digit.
- if (CurPtr == NumStart)
- return ReturnError(CurPtr-2, "Invalid hexadecimal number");
-
- errno = 0;
- if (errno == EINVAL)
- return ReturnError(CurPtr-2, "Invalid hexadecimal number");
- if (errno == ERANGE) {
- errno = 0;
- if (errno == EINVAL)
- return ReturnError(CurPtr-2, "Invalid hexadecimal number");
- if (errno == ERANGE)
- return ReturnError(CurPtr-2, "Hexadecimal number out of range");
- }
- return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
- (int64_t) strtoull(NumStart, 0, 16));
- }
-
- // Must be an octal number, it starts with 0.
- while (*CurPtr >= '0' && *CurPtr <= '7')
- ++CurPtr;
- return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
- strtoll(TokStart, 0, 8));
-}
-
-/// LexQuote: String: "..."
-AsmToken AsmLexer::LexQuote() {
- int CurChar = getNextChar();
- // TODO: does gas allow multiline string constants?
- while (CurChar != '"') {
- if (CurChar == '\\') {
- // Allow \", etc.
- CurChar = getNextChar();
- }
-
- if (CurChar == EOF)
- return ReturnError(TokStart, "unterminated string constant");
-
- CurChar = getNextChar();
- }
-
- return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
-}
-
-StringRef AsmLexer::LexUntilEndOfStatement() {
- TokStart = CurPtr;
-
- while (!isAtStartOfComment(*CurPtr) && // Start of line comment.
- *CurPtr != ';' && // End of statement marker.
- *CurPtr != '\n' &&
- *CurPtr != '\r' &&
- (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) {
- ++CurPtr;
- }
- return StringRef(TokStart, CurPtr-TokStart);
-}
-
-bool AsmLexer::isAtStartOfComment(char Char) {
- // FIXME: This won't work for multi-character comment indicators like "//".
- return Char == *MAI.getCommentString();
-}
-
-AsmToken AsmLexer::LexToken() {
- TokStart = CurPtr;
- // This always consumes at least one character.
- int CurChar = getNextChar();
-
- if (isAtStartOfComment(CurChar))
- return LexLineComment();
-
- switch (CurChar) {
- default:
- // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
- if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
- return LexIdentifier();
-
- // Unknown character, emit an error.
- return ReturnError(TokStart, "invalid character in input");
- case EOF: return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
- case 0:
- case ' ':
- case '\t':
- // Ignore whitespace.
- return LexToken();
- case '\n': // FALL THROUGH.
- case '\r': // FALL THROUGH.
- case ';': return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
- case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
- case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
- case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
- case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
- case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
- case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
- case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
- case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
- case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
- case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
- case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
- case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
- case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
- case '=':
- if (*CurPtr == '=')
- return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
- return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
- case '|':
- if (*CurPtr == '|')
- return ++CurPtr, AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
- return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
- case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
- case '&':
- if (*CurPtr == '&')
- return ++CurPtr, AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
- return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
- case '!':
- if (*CurPtr == '=')
- return ++CurPtr, AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
- return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
- case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
- case '/': return LexSlash();
- case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
- 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 '<':
- switch (*CurPtr) {
- case '<': return ++CurPtr, AsmToken(AsmToken::LessLess,
- StringRef(TokStart, 2));
- case '=': return ++CurPtr, AsmToken(AsmToken::LessEqual,
- StringRef(TokStart, 2));
- case '>': return ++CurPtr, AsmToken(AsmToken::LessGreater,
- StringRef(TokStart, 2));
- default: return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
- }
- case '>':
- switch (*CurPtr) {
- case '>': return ++CurPtr, AsmToken(AsmToken::GreaterGreater,
- StringRef(TokStart, 2));
- case '=': return ++CurPtr, AsmToken(AsmToken::GreaterEqual,
- StringRef(TokStart, 2));
- default: return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
- }
-
- // TODO: Quoted identifiers (objc methods etc)
- // local labels: [0-9][:]
- // Forward/backward labels: [0-9][fb]
- // Integers, fp constants, character constants.
- }
-}
diff --git a/tools/llvm-mc/AsmLexer.h b/tools/llvm-mc/AsmLexer.h
deleted file mode 100644
index 1d49e4b..0000000
--- a/tools/llvm-mc/AsmLexer.h
+++ /dev/null
@@ -1,72 +0,0 @@
-//===- AsmLexer.h - Lexer for Assembly Files --------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class declares the lexer for assembly files.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ASMLEXER_H
-#define ASMLEXER_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/MC/MCAsmLexer.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/System/DataTypes.h"
-#include <string>
-#include <cassert>
-
-namespace llvm {
-class MemoryBuffer;
-class SMLoc;
-class MCAsmInfo;
-
-/// AsmLexer - Lexer class for assembly files.
-class AsmLexer : public MCAsmLexer {
- const MCAsmInfo &MAI;
-
- const char *CurPtr;
- const MemoryBuffer *CurBuf;
-
- const char *TokStart;
-
- void operator=(const AsmLexer&); // DO NOT IMPLEMENT
- AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT
-
-protected:
- /// LexToken - Read the next token and return its code.
- virtual AsmToken LexToken();
-
-public:
- AsmLexer(const MCAsmInfo &MAI);
- ~AsmLexer();
-
- void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL);
-
- SMLoc getLoc() const;
-
- StringRef LexUntilEndOfStatement();
-
- bool isAtStartOfComment(char Char);
-
- const MCAsmInfo &getMAI() const { return MAI; }
-
-private:
- int getNextChar();
- AsmToken ReturnError(const char *Loc, const std::string &Msg);
-
- AsmToken LexIdentifier();
- AsmToken LexSlash();
- AsmToken LexLineComment();
- AsmToken LexDigit();
- AsmToken LexQuote();
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp
deleted file mode 100644
index 068e506..0000000
--- a/tools/llvm-mc/AsmParser.cpp
+++ /dev/null
@@ -1,1782 +0,0 @@
-//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the parser for assembly files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AsmParser.h"
-
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCParsedAsmOperand.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetAsmParser.h"
-using namespace llvm;
-
-
-enum { DEFAULT_ADDRSPACE = 0 };
-
-// Mach-O section uniquing.
-//
-// FIXME: Figure out where this should live, it should be shared by
-// TargetLoweringObjectFile.
-typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy;
-
-AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out,
- const MCAsmInfo &_MAI)
- : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), TargetParser(0),
- CurBuffer(0), SectionUniquingMap(0) {
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
-
- // Debugging directives.
- AddDirectiveHandler(".file", &AsmParser::ParseDirectiveFile);
- AddDirectiveHandler(".line", &AsmParser::ParseDirectiveLine);
- AddDirectiveHandler(".loc", &AsmParser::ParseDirectiveLoc);
-}
-
-
-
-AsmParser::~AsmParser() {
- // If we have the MachO uniquing map, free it.
- delete (MachOUniqueMapTy*)SectionUniquingMap;
-}
-
-const MCSection *AsmParser::getMachOSection(const StringRef &Segment,
- const StringRef &Section,
- unsigned TypeAndAttributes,
- unsigned Reserved2,
- SectionKind Kind) const {
- // We unique sections by their segment/section pair. The returned section
- // may not have the same flags as the requested section, if so this should be
- // diagnosed by the client as an error.
-
- // Create the map if it doesn't already exist.
- if (SectionUniquingMap == 0)
- SectionUniquingMap = new MachOUniqueMapTy();
- MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)SectionUniquingMap;
-
- // Form the name to look up.
- SmallString<64> Name;
- Name += Segment;
- Name.push_back(',');
- Name += Section;
-
- // Do the lookup, if we have a hit, return it.
- const MCSectionMachO *&Entry = Map[Name.str()];
-
- // FIXME: This should validate the type and attributes.
- if (Entry) return Entry;
-
- // Otherwise, return a new section.
- return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes,
- Reserved2, Kind, Ctx);
-}
-
-void AsmParser::Warning(SMLoc L, const Twine &Msg) {
- PrintMessage(L, Msg.str(), "warning");
-}
-
-bool AsmParser::Error(SMLoc L, const Twine &Msg) {
- PrintMessage(L, Msg.str(), "error");
- return true;
-}
-
-bool AsmParser::TokError(const char *Msg) {
- PrintMessage(Lexer.getLoc(), Msg, "error");
- return true;
-}
-
-void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg,
- const char *Type) const {
- SrcMgr.PrintMessage(Loc, Msg, Type);
-}
-
-bool AsmParser::EnterIncludeFile(const std::string &Filename) {
- int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc());
- if (NewBuf == -1)
- return true;
-
- CurBuffer = NewBuf;
-
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
-
- return false;
-}
-
-const AsmToken &AsmParser::Lex() {
- const AsmToken *tok = &Lexer.Lex();
-
- if (tok->is(AsmToken::Eof)) {
- // If this is the end of an included file, pop the parent file off the
- // include stack.
- SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
- if (ParentIncludeLoc != SMLoc()) {
- CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer),
- ParentIncludeLoc.getPointer());
- tok = &Lexer.Lex();
- }
- }
-
- if (tok->is(AsmToken::Error))
- PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error");
-
- return *tok;
-}
-
-bool AsmParser::Run() {
- // Create the initial section.
- //
- // FIXME: Support -n.
- // FIXME: Target hook & command line option for initial section.
- Out.SwitchSection(getMachOSection("__TEXT", "__text",
- MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
- 0, SectionKind()));
-
-
- // Prime the lexer.
- Lex();
-
- bool HadError = false;
-
- AsmCond StartingCondState = TheCondState;
-
- // While we have input, parse each statement.
- while (Lexer.isNot(AsmToken::Eof)) {
- // Handle conditional assembly here before calling ParseStatement()
- if (Lexer.getKind() == AsmToken::Identifier) {
- // If we have an identifier, handle it as the key symbol.
- AsmToken ID = getTok();
- SMLoc IDLoc = ID.getLoc();
- StringRef IDVal = ID.getString();
-
- if (IDVal == ".if" ||
- IDVal == ".elseif" ||
- IDVal == ".else" ||
- IDVal == ".endif") {
- if (!ParseConditionalAssemblyDirectives(IDVal, IDLoc))
- continue;
- HadError = true;
- EatToEndOfStatement();
- continue;
- }
- }
- if (TheCondState.Ignore) {
- EatToEndOfStatement();
- continue;
- }
-
- if (!ParseStatement()) continue;
-
- // We had an error, remember it and recover by skipping to the next line.
- HadError = true;
- EatToEndOfStatement();
- }
-
- if (TheCondState.TheCond != StartingCondState.TheCond ||
- TheCondState.Ignore != StartingCondState.Ignore)
- return TokError("unmatched .ifs or .elses");
-
- if (!HadError)
- Out.Finish();
-
- return HadError;
-}
-
-/// ParseConditionalAssemblyDirectives - parse the conditional assembly
-/// directives
-bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive,
- SMLoc DirectiveLoc) {
- if (Directive == ".if")
- return ParseDirectiveIf(DirectiveLoc);
- if (Directive == ".elseif")
- return ParseDirectiveElseIf(DirectiveLoc);
- if (Directive == ".else")
- return ParseDirectiveElse(DirectiveLoc);
- if (Directive == ".endif")
- return ParseDirectiveEndIf(DirectiveLoc);
- return true;
-}
-
-/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
-void AsmParser::EatToEndOfStatement() {
- while (Lexer.isNot(AsmToken::EndOfStatement) &&
- Lexer.isNot(AsmToken::Eof))
- Lex();
-
- // Eat EOL.
- if (Lexer.is(AsmToken::EndOfStatement))
- Lex();
-}
-
-
-/// ParseParenExpr - Parse a paren expression and return it.
-/// NOTE: This assumes the leading '(' has already been consumed.
-///
-/// parenexpr ::= expr)
-///
-bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (ParseExpression(Res)) return true;
- if (Lexer.isNot(AsmToken::RParen))
- return TokError("expected ')' in parentheses expression");
- EndLoc = Lexer.getLoc();
- Lex();
- return false;
-}
-
-MCSymbol *AsmParser::CreateSymbol(StringRef Name) {
- if (MCSymbol *S = Ctx.LookupSymbol(Name))
- return S;
-
- // If the label starts with L it is an assembler temporary label.
- if (Name.startswith("L"))
- return Ctx.CreateTemporarySymbol(Name);
-
- return Ctx.CreateSymbol(Name);
-}
-
-/// ParsePrimaryExpr - Parse a primary expression and return it.
-/// primaryexpr ::= (parenexpr
-/// primaryexpr ::= symbol
-/// primaryexpr ::= number
-/// primaryexpr ::= ~,+,- primaryexpr
-bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- switch (Lexer.getKind()) {
- default:
- return TokError("unknown token in expression");
- case AsmToken::Exclaim:
- Lex(); // Eat the operator.
- if (ParsePrimaryExpr(Res, EndLoc))
- return true;
- Res = MCUnaryExpr::CreateLNot(Res, getContext());
- return false;
- case AsmToken::String:
- case AsmToken::Identifier: {
- // This is a symbol reference.
- MCSymbol *Sym = CreateSymbol(getTok().getIdentifier());
- EndLoc = Lexer.getLoc();
- Lex(); // Eat identifier.
-
- // If this is an absolute variable reference, substitute it now to preserve
- // semantics in the face of reassignment.
- if (Sym->getValue() && isa<MCConstantExpr>(Sym->getValue())) {
- Res = Sym->getValue();
- return false;
- }
-
- // Otherwise create a symbol ref.
- Res = MCSymbolRefExpr::Create(Sym, getContext());
- return false;
- }
- case AsmToken::Integer:
- Res = MCConstantExpr::Create(getTok().getIntVal(), getContext());
- EndLoc = Lexer.getLoc();
- Lex(); // Eat token.
- return false;
- case AsmToken::LParen:
- Lex(); // Eat the '('.
- return ParseParenExpr(Res, EndLoc);
- case AsmToken::Minus:
- Lex(); // Eat the operator.
- if (ParsePrimaryExpr(Res, EndLoc))
- return true;
- Res = MCUnaryExpr::CreateMinus(Res, getContext());
- return false;
- case AsmToken::Plus:
- Lex(); // Eat the operator.
- if (ParsePrimaryExpr(Res, EndLoc))
- return true;
- Res = MCUnaryExpr::CreatePlus(Res, getContext());
- return false;
- case AsmToken::Tilde:
- Lex(); // Eat the operator.
- if (ParsePrimaryExpr(Res, EndLoc))
- return true;
- Res = MCUnaryExpr::CreateNot(Res, getContext());
- return false;
- }
-}
-
-bool AsmParser::ParseExpression(const MCExpr *&Res) {
- SMLoc EndLoc;
- return ParseExpression(Res, EndLoc);
-}
-
-/// ParseExpression - Parse an expression and return it.
-///
-/// expr ::= expr +,- expr -> lowest.
-/// expr ::= expr |,^,&,! expr -> middle.
-/// expr ::= expr *,/,%,<<,>> expr -> highest.
-/// expr ::= primaryexpr
-///
-bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- Res = 0;
- return ParsePrimaryExpr(Res, EndLoc) ||
- ParseBinOpRHS(1, Res, EndLoc);
-}
-
-bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- if (ParseParenExpr(Res, EndLoc))
- return true;
-
- return false;
-}
-
-bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
- const MCExpr *Expr;
-
- SMLoc StartLoc = Lexer.getLoc();
- if (ParseExpression(Expr))
- return true;
-
- if (!Expr->EvaluateAsAbsolute(Res))
- return Error(StartLoc, "expected absolute expression");
-
- return false;
-}
-
-static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind) {
- switch (K) {
- default:
- return 0; // not a binop.
-
- // Lowest Precedence: &&, ||
- case AsmToken::AmpAmp:
- Kind = MCBinaryExpr::LAnd;
- return 1;
- case AsmToken::PipePipe:
- Kind = MCBinaryExpr::LOr;
- return 1;
-
- // Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
- case AsmToken::Plus:
- Kind = MCBinaryExpr::Add;
- return 2;
- case AsmToken::Minus:
- Kind = MCBinaryExpr::Sub;
- return 2;
- case AsmToken::EqualEqual:
- Kind = MCBinaryExpr::EQ;
- return 2;
- case AsmToken::ExclaimEqual:
- case AsmToken::LessGreater:
- Kind = MCBinaryExpr::NE;
- return 2;
- case AsmToken::Less:
- Kind = MCBinaryExpr::LT;
- return 2;
- case AsmToken::LessEqual:
- Kind = MCBinaryExpr::LTE;
- return 2;
- case AsmToken::Greater:
- Kind = MCBinaryExpr::GT;
- return 2;
- case AsmToken::GreaterEqual:
- Kind = MCBinaryExpr::GTE;
- return 2;
-
- // Intermediate Precedence: |, &, ^
- //
- // FIXME: gas seems to support '!' as an infix operator?
- case AsmToken::Pipe:
- Kind = MCBinaryExpr::Or;
- return 3;
- case AsmToken::Caret:
- Kind = MCBinaryExpr::Xor;
- return 3;
- case AsmToken::Amp:
- Kind = MCBinaryExpr::And;
- return 3;
-
- // Highest Precedence: *, /, %, <<, >>
- case AsmToken::Star:
- Kind = MCBinaryExpr::Mul;
- return 4;
- case AsmToken::Slash:
- Kind = MCBinaryExpr::Div;
- return 4;
- case AsmToken::Percent:
- Kind = MCBinaryExpr::Mod;
- return 4;
- case AsmToken::LessLess:
- Kind = MCBinaryExpr::Shl;
- return 4;
- case AsmToken::GreaterGreater:
- Kind = MCBinaryExpr::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, const MCExpr *&Res,
- SMLoc &EndLoc) {
- while (1) {
- MCBinaryExpr::Opcode Kind = MCBinaryExpr::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;
-
- Lex();
-
- // Eat the next primary expression.
- const MCExpr *RHS;
- if (ParsePrimaryExpr(RHS, EndLoc)) return true;
-
- // If BinOp binds less tightly with RHS than the operator after RHS, let
- // the pending operator take RHS as its LHS.
- MCBinaryExpr::Opcode Dummy;
- unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
- if (TokPrec < NextTokPrec) {
- if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true;
- }
-
- // Merge LHS and RHS according to operator.
- Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
- }
-}
-
-
-
-
-/// ParseStatement:
-/// ::= EndOfStatement
-/// ::= Label* Directive ...Operands... EndOfStatement
-/// ::= Label* Identifier OperandList* EndOfStatement
-bool AsmParser::ParseStatement() {
- if (Lexer.is(AsmToken::EndOfStatement)) {
- Lex();
- return false;
- }
-
- // Statements always start with an identifier.
- AsmToken ID = getTok();
- SMLoc IDLoc = ID.getLoc();
- StringRef IDVal;
- if (ParseIdentifier(IDVal))
- return TokError("unexpected token at start of statement");
-
- // FIXME: Recurse on local labels?
-
- // See what kind of statement we have.
- switch (Lexer.getKind()) {
- case AsmToken::Colon: {
- // identifier ':' -> Label.
- 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 = CreateSymbol(IDVal);
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- // Emit the label.
- Out.EmitLabel(Sym);
-
- return ParseStatement();
- }
-
- case AsmToken::Equal:
- // identifier '=' ... -> assignment statement
- Lex();
-
- return ParseAssignment(IDVal);
-
- default: // Normal instruction or directive.
- break;
- }
-
- // Otherwise, we have a normal instruction or directive.
- if (IDVal[0] == '.') {
- // FIXME: This should be driven based on a hash lookup and callback.
- if (IDVal == ".section")
- return ParseDirectiveDarwinSection();
- if (IDVal == ".text")
- // FIXME: This changes behavior based on the -static flag to the
- // assembler.
- return ParseDirectiveSectionSwitch("__TEXT", "__text",
- MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
- if (IDVal == ".const")
- return ParseDirectiveSectionSwitch("__TEXT", "__const");
- if (IDVal == ".static_const")
- return ParseDirectiveSectionSwitch("__TEXT", "__static_const");
- if (IDVal == ".cstring")
- return ParseDirectiveSectionSwitch("__TEXT","__cstring",
- MCSectionMachO::S_CSTRING_LITERALS);
- if (IDVal == ".literal4")
- return ParseDirectiveSectionSwitch("__TEXT", "__literal4",
- MCSectionMachO::S_4BYTE_LITERALS,
- 4);
- if (IDVal == ".literal8")
- return ParseDirectiveSectionSwitch("__TEXT", "__literal8",
- MCSectionMachO::S_8BYTE_LITERALS,
- 8);
- if (IDVal == ".literal16")
- return ParseDirectiveSectionSwitch("__TEXT","__literal16",
- MCSectionMachO::S_16BYTE_LITERALS,
- 16);
- if (IDVal == ".constructor")
- return ParseDirectiveSectionSwitch("__TEXT","__constructor");
- if (IDVal == ".destructor")
- return ParseDirectiveSectionSwitch("__TEXT","__destructor");
- if (IDVal == ".fvmlib_init0")
- return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0");
- if (IDVal == ".fvmlib_init1")
- return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1");
-
- // FIXME: The assembler manual claims that this has the self modify code
- // flag, at least on x86-32, but that does not appear to be correct.
- if (IDVal == ".symbol_stub")
- return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub",
- MCSectionMachO::S_SYMBOL_STUBS |
- MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
- // FIXME: Different on PPC and ARM.
- 0, 16);
- // FIXME: PowerPC only?
- if (IDVal == ".picsymbol_stub")
- return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub",
- MCSectionMachO::S_SYMBOL_STUBS |
- MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
- 0, 26);
- if (IDVal == ".data")
- return ParseDirectiveSectionSwitch("__DATA", "__data");
- if (IDVal == ".static_data")
- return ParseDirectiveSectionSwitch("__DATA", "__static_data");
-
- // FIXME: The section names of these two are misspelled in the assembler
- // manual.
- if (IDVal == ".non_lazy_symbol_pointer")
- return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr",
- MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
- 4);
- if (IDVal == ".lazy_symbol_pointer")
- return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr",
- MCSectionMachO::S_LAZY_SYMBOL_POINTERS,
- 4);
-
- if (IDVal == ".dyld")
- return ParseDirectiveSectionSwitch("__DATA", "__dyld");
- if (IDVal == ".mod_init_func")
- return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func",
- MCSectionMachO::S_MOD_INIT_FUNC_POINTERS,
- 4);
- if (IDVal == ".mod_term_func")
- return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func",
- MCSectionMachO::S_MOD_TERM_FUNC_POINTERS,
- 4);
- if (IDVal == ".const_data")
- return ParseDirectiveSectionSwitch("__DATA", "__const");
-
-
- if (IDVal == ".objc_class")
- return ParseDirectiveSectionSwitch("__OBJC", "__class",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_meta_class")
- return ParseDirectiveSectionSwitch("__OBJC", "__meta_class",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_cat_cls_meth")
- return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_cat_inst_meth")
- return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_protocol")
- return ParseDirectiveSectionSwitch("__OBJC", "__protocol",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_string_object")
- return ParseDirectiveSectionSwitch("__OBJC", "__string_object",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_cls_meth")
- return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_inst_meth")
- return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_cls_refs")
- return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
- MCSectionMachO::S_LITERAL_POINTERS,
- 4);
- if (IDVal == ".objc_message_refs")
- return ParseDirectiveSectionSwitch("__OBJC", "__message_refs",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
- MCSectionMachO::S_LITERAL_POINTERS,
- 4);
- if (IDVal == ".objc_symbols")
- return ParseDirectiveSectionSwitch("__OBJC", "__symbols",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_category")
- return ParseDirectiveSectionSwitch("__OBJC", "__category",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_class_vars")
- return ParseDirectiveSectionSwitch("__OBJC", "__class_vars",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_instance_vars")
- return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_module_info")
- return ParseDirectiveSectionSwitch("__OBJC", "__module_info",
- MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
- if (IDVal == ".objc_class_names")
- return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
- MCSectionMachO::S_CSTRING_LITERALS);
- if (IDVal == ".objc_meth_var_types")
- return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
- MCSectionMachO::S_CSTRING_LITERALS);
- if (IDVal == ".objc_meth_var_names")
- return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
- MCSectionMachO::S_CSTRING_LITERALS);
- if (IDVal == ".objc_selector_strs")
- return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs",
- MCSectionMachO::S_CSTRING_LITERALS);
-
- // Assembler features
- if (IDVal == ".set")
- return ParseDirectiveSet();
-
- // Data directives
-
- if (IDVal == ".ascii")
- return ParseDirectiveAscii(false);
- if (IDVal == ".asciz")
- return ParseDirectiveAscii(true);
-
- if (IDVal == ".byte")
- return ParseDirectiveValue(1);
- if (IDVal == ".short")
- return ParseDirectiveValue(2);
- if (IDVal == ".long")
- return ParseDirectiveValue(4);
- if (IDVal == ".quad")
- return ParseDirectiveValue(8);
-
- // FIXME: Target hooks for IsPow2.
- if (IDVal == ".align")
- return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
- if (IDVal == ".align32")
- return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
- if (IDVal == ".balign")
- return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
- if (IDVal == ".balignw")
- return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
- if (IDVal == ".balignl")
- return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
- if (IDVal == ".p2align")
- return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
- if (IDVal == ".p2alignw")
- return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
- if (IDVal == ".p2alignl")
- return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
-
- if (IDVal == ".org")
- return ParseDirectiveOrg();
-
- if (IDVal == ".fill")
- return ParseDirectiveFill();
- if (IDVal == ".space")
- return ParseDirectiveSpace();
-
- // Symbol attribute directives
-
- if (IDVal == ".globl" || IDVal == ".global")
- return ParseDirectiveSymbolAttribute(MCStreamer::Global);
- if (IDVal == ".hidden")
- return ParseDirectiveSymbolAttribute(MCStreamer::Hidden);
- if (IDVal == ".indirect_symbol")
- return ParseDirectiveSymbolAttribute(MCStreamer::IndirectSymbol);
- if (IDVal == ".internal")
- return ParseDirectiveSymbolAttribute(MCStreamer::Internal);
- if (IDVal == ".lazy_reference")
- return ParseDirectiveSymbolAttribute(MCStreamer::LazyReference);
- if (IDVal == ".no_dead_strip")
- return ParseDirectiveSymbolAttribute(MCStreamer::NoDeadStrip);
- if (IDVal == ".private_extern")
- return ParseDirectiveSymbolAttribute(MCStreamer::PrivateExtern);
- if (IDVal == ".protected")
- return ParseDirectiveSymbolAttribute(MCStreamer::Protected);
- if (IDVal == ".reference")
- return ParseDirectiveSymbolAttribute(MCStreamer::Reference);
- if (IDVal == ".weak")
- return ParseDirectiveSymbolAttribute(MCStreamer::Weak);
- if (IDVal == ".weak_definition")
- return ParseDirectiveSymbolAttribute(MCStreamer::WeakDefinition);
- if (IDVal == ".weak_reference")
- return ParseDirectiveSymbolAttribute(MCStreamer::WeakReference);
-
- if (IDVal == ".comm")
- return ParseDirectiveComm(/*IsLocal=*/false);
- if (IDVal == ".lcomm")
- return ParseDirectiveComm(/*IsLocal=*/true);
- if (IDVal == ".zerofill")
- return ParseDirectiveDarwinZerofill();
- if (IDVal == ".desc")
- return ParseDirectiveDarwinSymbolDesc();
- if (IDVal == ".lsym")
- return ParseDirectiveDarwinLsym();
-
- if (IDVal == ".subsections_via_symbols")
- return ParseDirectiveDarwinSubsectionsViaSymbols();
- if (IDVal == ".abort")
- return ParseDirectiveAbort();
- if (IDVal == ".include")
- return ParseDirectiveInclude();
- if (IDVal == ".dump")
- return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsDump=*/true);
- if (IDVal == ".load")
- return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsLoad=*/false);
-
- // Look up the handler in the handler table,
- bool(AsmParser::*Handler)(StringRef, SMLoc) = DirectiveMap[IDVal];
- if (Handler)
- return (this->*Handler)(IDVal, IDLoc);
-
- // Target hook for parsing target specific directives.
- if (!getTargetParser().ParseDirective(ID))
- return false;
-
- Warning(IDLoc, "ignoring directive for now");
- EatToEndOfStatement();
- return false;
- }
-
-
- SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
- if (getTargetParser().ParseInstruction(IDVal, IDLoc, ParsedOperands))
- // FIXME: Leaking ParsedOperands on failure.
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- // FIXME: Leaking ParsedOperands on failure.
- return TokError("unexpected token in argument list");
-
- // Eat the end of statement marker.
- Lex();
-
-
- MCInst Inst;
-
- bool MatchFail = getTargetParser().MatchInstruction(ParsedOperands, Inst);
-
- // Free any parsed operands.
- for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
- delete ParsedOperands[i];
-
- if (MatchFail) {
- // FIXME: We should give nicer diagnostics about the exact failure.
- Error(IDLoc, "unrecognized instruction");
- return true;
- }
-
- // Instruction is good, process it.
- Out.EmitInstruction(Inst);
-
- // Skip to end of line for now.
- return false;
-}
-
-bool AsmParser::ParseAssignment(const StringRef &Name) {
- // FIXME: Use better location, we should use proper tokens.
- SMLoc EqualLoc = Lexer.getLoc();
-
- const MCExpr *Value;
- SMLoc StartLoc = Lexer.getLoc();
- if (ParseExpression(Value))
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in assignment");
-
- // Eat the end of statement marker.
- Lex();
-
- // Validate that the LHS is allowed to be a variable (either it has not been
- // used as a symbol, or it is an absolute symbol).
- MCSymbol *Sym = getContext().LookupSymbol(Name);
- if (Sym) {
- // Diagnose assignment to a label.
- //
- // FIXME: Diagnostics. Note the location of the definition as a label.
- // FIXME: Diagnose assignment to protected identifier (e.g., register name).
- if (!Sym->isUndefined() && !Sym->isAbsolute())
- return Error(EqualLoc, "redefinition of '" + Name + "'");
- else if (!Sym->isVariable())
- return Error(EqualLoc, "invalid assignment to '" + Name + "'");
- else if (!isa<MCConstantExpr>(Sym->getValue()))
- return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
- Name + "'");
- } else
- Sym = CreateSymbol(Name);
-
- // FIXME: Handle '.'.
-
- // Do the assignment.
- Out.EmitAssignment(Sym, Value);
-
- return false;
-}
-
-/// ParseIdentifier:
-/// ::= identifier
-/// ::= string
-bool AsmParser::ParseIdentifier(StringRef &Res) {
- if (Lexer.isNot(AsmToken::Identifier) &&
- Lexer.isNot(AsmToken::String))
- return true;
-
- Res = getTok().getIdentifier();
-
- Lex(); // Consume the identifier token.
-
- return false;
-}
-
-/// ParseDirectiveSet:
-/// ::= .set identifier ',' expression
-bool AsmParser::ParseDirectiveSet() {
- StringRef Name;
-
- if (ParseIdentifier(Name))
- return TokError("expected identifier after '.set' directive");
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in '.set'");
- Lex();
-
- return ParseAssignment(Name);
-}
-
-/// ParseDirectiveSection:
-/// ::= .section identifier (',' identifier)*
-/// FIXME: This should actually parse out the segment, section, attributes and
-/// sizeof_stub fields.
-bool AsmParser::ParseDirectiveDarwinSection() {
- SMLoc Loc = Lexer.getLoc();
-
- StringRef SectionName;
- if (ParseIdentifier(SectionName))
- return Error(Loc, "expected identifier after '.section' directive");
-
- // Verify there is a following comma.
- if (!Lexer.is(AsmToken::Comma))
- return TokError("unexpected token in '.section' directive");
-
- std::string SectionSpec = SectionName;
- SectionSpec += ",";
-
- // Add all the tokens until the end of the line, ParseSectionSpecifier will
- // handle this.
- StringRef EOL = Lexer.LexUntilEndOfStatement();
- SectionSpec.append(EOL.begin(), EOL.end());
-
- Lex();
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.section' directive");
- Lex();
-
-
- StringRef Segment, Section;
- unsigned TAA, StubSize;
- std::string ErrorStr =
- MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
- TAA, StubSize);
-
- if (!ErrorStr.empty())
- return Error(Loc, ErrorStr.c_str());
-
- // FIXME: Arch specific.
- Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize,
- SectionKind()));
- return false;
-}
-
-/// ParseDirectiveSectionSwitch -
-bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment,
- const char *Section,
- unsigned TAA, unsigned Align,
- unsigned StubSize) {
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in section switching directive");
- Lex();
-
- // FIXME: Arch specific.
- Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize,
- SectionKind()));
-
- // Set the implicit alignment, if any.
- //
- // FIXME: This isn't really what 'as' does; I think it just uses the implicit
- // alignment on the section (e.g., if one manually inserts bytes into the
- // section, then just issueing the section switch directive will not realign
- // the section. However, this is arguably more reasonable behavior, and there
- // is no good reason for someone to intentionally emit incorrectly sized
- // values into the implicitly aligned sections.
- if (Align)
- Out.EmitValueToAlignment(Align, 0, 1, 0);
-
- return false;
-}
-
-bool AsmParser::ParseEscapedString(std::string &Data) {
- assert(Lexer.is(AsmToken::String) && "Unexpected current token!");
-
- Data = "";
- StringRef Str = getTok().getStringContents();
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- if (Str[i] != '\\') {
- Data += Str[i];
- continue;
- }
-
- // Recognize escaped characters. Note that this escape semantics currently
- // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
- ++i;
- if (i == e)
- return TokError("unexpected backslash at end of string");
-
- // Recognize octal sequences.
- if ((unsigned) (Str[i] - '0') <= 7) {
- // Consume up to three octal characters.
- unsigned Value = Str[i] - '0';
-
- if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
- ++i;
- Value = Value * 8 + (Str[i] - '0');
-
- if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
- ++i;
- Value = Value * 8 + (Str[i] - '0');
- }
- }
-
- if (Value > 255)
- return TokError("invalid octal escape sequence (out of range)");
-
- Data += (unsigned char) Value;
- continue;
- }
-
- // Otherwise recognize individual escapes.
- switch (Str[i]) {
- default:
- // Just reject invalid escape sequences for now.
- return TokError("invalid escape sequence (unrecognized character)");
-
- case 'b': Data += '\b'; break;
- case 'f': Data += '\f'; break;
- case 'n': Data += '\n'; break;
- case 'r': Data += '\r'; break;
- case 't': Data += '\t'; break;
- case '"': Data += '"'; break;
- case '\\': Data += '\\'; break;
- }
- }
-
- return false;
-}
-
-/// ParseDirectiveAscii:
-/// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
-bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- for (;;) {
- if (Lexer.isNot(AsmToken::String))
- return TokError("expected string in '.ascii' or '.asciz' directive");
-
- std::string Data;
- if (ParseEscapedString(Data))
- return true;
-
- Out.EmitBytes(Data, DEFAULT_ADDRSPACE);
- if (ZeroTerminated)
- Out.EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE);
-
- Lex();
-
- if (Lexer.is(AsmToken::EndOfStatement))
- break;
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in '.ascii' or '.asciz' directive");
- Lex();
- }
- }
-
- Lex();
- return false;
-}
-
-/// ParseDirectiveValue
-/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
-bool AsmParser::ParseDirectiveValue(unsigned Size) {
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- for (;;) {
- const MCExpr *Value;
- SMLoc ATTRIBUTE_UNUSED StartLoc = Lexer.getLoc();
- if (ParseExpression(Value))
- return true;
-
- Out.EmitValue(Value, Size, DEFAULT_ADDRSPACE);
-
- if (Lexer.is(AsmToken::EndOfStatement))
- break;
-
- // FIXME: Improve diagnostic.
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
- }
- }
-
- Lex();
- return false;
-}
-
-/// ParseDirectiveSpace
-/// ::= .space expression [ , expression ]
-bool AsmParser::ParseDirectiveSpace() {
- int64_t NumBytes;
- if (ParseAbsoluteExpression(NumBytes))
- return true;
-
- int64_t FillExpr = 0;
- bool HasFillExpr = false;
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in '.space' directive");
- Lex();
-
- if (ParseAbsoluteExpression(FillExpr))
- return true;
-
- HasFillExpr = true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.space' directive");
- }
-
- Lex();
-
- if (NumBytes <= 0)
- return TokError("invalid number of bytes in '.space' directive");
-
- // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
- Out.EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE);
-
- return false;
-}
-
-/// ParseDirectiveFill
-/// ::= .fill expression , expression , expression
-bool AsmParser::ParseDirectiveFill() {
- int64_t NumValues;
- if (ParseAbsoluteExpression(NumValues))
- return true;
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in '.fill' directive");
- Lex();
-
- int64_t FillSize;
- if (ParseAbsoluteExpression(FillSize))
- return true;
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in '.fill' directive");
- Lex();
-
- int64_t FillExpr;
- if (ParseAbsoluteExpression(FillExpr))
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.fill' directive");
-
- Lex();
-
- if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
- return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
-
- for (uint64_t i = 0, e = NumValues; i != e; ++i)
- Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), FillSize,
- DEFAULT_ADDRSPACE);
-
- return false;
-}
-
-/// ParseDirectiveOrg
-/// ::= .org expression [ , expression ]
-bool AsmParser::ParseDirectiveOrg() {
- const MCExpr *Offset;
- SMLoc StartLoc = Lexer.getLoc();
- if (ParseExpression(Offset))
- return true;
-
- // Parse optional fill expression.
- int64_t FillExpr = 0;
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in '.org' directive");
- Lex();
-
- if (ParseAbsoluteExpression(FillExpr))
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.org' directive");
- }
-
- Lex();
-
- // 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) {
- SMLoc AlignmentLoc = Lexer.getLoc();
- int64_t Alignment;
- if (ParseAbsoluteExpression(Alignment))
- return true;
-
- SMLoc MaxBytesLoc;
- bool HasFillExpr = false;
- int64_t FillExpr = 0;
- int64_t MaxBytesToFill = 0;
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- // The fill expression can be omitted while specifying a maximum number of
- // alignment bytes, e.g:
- // .align 3,,4
- if (Lexer.isNot(AsmToken::Comma)) {
- HasFillExpr = true;
- if (ParseAbsoluteExpression(FillExpr))
- return true;
- }
-
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- MaxBytesLoc = Lexer.getLoc();
- if (ParseAbsoluteExpression(MaxBytesToFill))
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
- }
- }
-
- Lex();
-
- if (!HasFillExpr) {
- // FIXME: Sometimes fill with nop.
- FillExpr = 0;
- }
-
- // Compute alignment in bytes.
- if (IsPow2) {
- // FIXME: Diagnose overflow.
- if (Alignment >= 32) {
- Error(AlignmentLoc, "invalid alignment value");
- Alignment = 31;
- }
-
- Alignment = 1ULL << Alignment;
- }
-
- // Diagnose non-sensical max bytes to align.
- if (MaxBytesLoc.isValid()) {
- if (MaxBytesToFill < 1) {
- Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
- "many bytes, ignoring maximum bytes expression");
- MaxBytesToFill = 0;
- }
-
- 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(AsmToken::EndOfStatement)) {
- for (;;) {
- StringRef Name;
-
- if (ParseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- MCSymbol *Sym = CreateSymbol(Name);
-
- Out.EmitSymbolAttribute(Sym, Attr);
-
- if (Lexer.is(AsmToken::EndOfStatement))
- break;
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
- }
- }
-
- Lex();
- return false;
-}
-
-/// ParseDirectiveDarwinSymbolDesc
-/// ::= .desc identifier , expression
-bool AsmParser::ParseDirectiveDarwinSymbolDesc() {
- StringRef Name;
- if (ParseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = CreateSymbol(Name);
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in '.desc' directive");
- Lex();
-
- SMLoc DescLoc = Lexer.getLoc();
- int64_t DescValue;
- if (ParseAbsoluteExpression(DescValue))
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.desc' directive");
-
- Lex();
-
- // Set the n_desc field of this Symbol to this DescValue
- Out.EmitSymbolDesc(Sym, DescValue);
-
- return false;
-}
-
-/// ParseDirectiveComm
-/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
-bool AsmParser::ParseDirectiveComm(bool IsLocal) {
- SMLoc IDLoc = Lexer.getLoc();
- StringRef Name;
- if (ParseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = CreateSymbol(Name);
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = Lexer.getLoc();
- if (ParseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (Lexer.is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = Lexer.getLoc();
- if (ParseAbsoluteExpression(Pow2Alignment))
- return true;
-
- // If this target takes alignments in bytes (not log) validate and convert.
- if (Lexer.getMAI().getAlignmentIsInBytes()) {
- if (!isPowerOf2_64(Pow2Alignment))
- return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
- Pow2Alignment = Log2_64(Pow2Alignment);
- }
- }
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.comm' or '.lcomm' directive");
-
- Lex();
-
- // NOTE: a size of zero for a .comm should create a undefined symbol
- // but a size of .lcomm creates a bss symbol of size zero.
- if (Size < 0)
- return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
- "be less than zero");
-
- // NOTE: The alignment in the directive is a power of 2 value, the assember
- // may internally end up wanting an alignment in bytes.
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
- "alignment, can't be less than zero");
-
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- // '.lcomm' is equivalent to '.zerofill'.
- // Create the Symbol as a common or local common with Size and Pow2Alignment
- if (IsLocal) {
- Out.EmitZerofill(getMachOSection("__DATA", "__bss",
- MCSectionMachO::S_ZEROFILL, 0,
- SectionKind()),
- Sym, Size, 1 << Pow2Alignment);
- return false;
- }
-
- Out.EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
- return false;
-}
-
-/// ParseDirectiveDarwinZerofill
-/// ::= .zerofill segname , sectname [, identifier , size_expression [
-/// , align_expression ]]
-bool AsmParser::ParseDirectiveDarwinZerofill() {
- // FIXME: Handle quoted names here.
-
- if (Lexer.isNot(AsmToken::Identifier))
- return TokError("expected segment name after '.zerofill' directive");
- StringRef Segment = getTok().getString();
- Lex();
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- if (Lexer.isNot(AsmToken::Identifier))
- return TokError("expected section name after comma in '.zerofill' "
- "directive");
- StringRef Section = getTok().getString();
- Lex();
-
- // If this is the end of the line all that was wanted was to create the
- // the section but with no symbol.
- if (Lexer.is(AsmToken::EndOfStatement)) {
- // Create the zerofill section but no symbol
- Out.EmitZerofill(getMachOSection(Segment, Section,
- MCSectionMachO::S_ZEROFILL, 0,
- SectionKind()));
- return false;
- }
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- if (Lexer.isNot(AsmToken::Identifier))
- return TokError("expected identifier in directive");
-
- // handle the identifier as the key symbol.
- SMLoc IDLoc = Lexer.getLoc();
- MCSymbol *Sym = CreateSymbol(getTok().getString());
- Lex();
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = Lexer.getLoc();
- if (ParseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (Lexer.is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = Lexer.getLoc();
- if (ParseAbsoluteExpression(Pow2Alignment))
- return true;
- }
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.zerofill' directive");
-
- Lex();
-
- if (Size < 0)
- return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
- "than zero");
-
- // NOTE: The alignment in the directive is a power of 2 value, the assember
- // may internally end up wanting an alignment in bytes.
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
- "can't be less than zero");
-
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- // Create the zerofill Symbol with Size and Pow2Alignment
- //
- // FIXME: Arch specific.
- Out.EmitZerofill(getMachOSection(Segment, Section,
- MCSectionMachO::S_ZEROFILL, 0,
- SectionKind()),
- Sym, Size, 1 << Pow2Alignment);
-
- return false;
-}
-
-/// ParseDirectiveDarwinSubsectionsViaSymbols
-/// ::= .subsections_via_symbols
-bool AsmParser::ParseDirectiveDarwinSubsectionsViaSymbols() {
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.subsections_via_symbols' directive");
-
- Lex();
-
- Out.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
-
- return false;
-}
-
-/// ParseDirectiveAbort
-/// ::= .abort [ "abort_string" ]
-bool AsmParser::ParseDirectiveAbort() {
- // FIXME: Use loc from directive.
- SMLoc Loc = Lexer.getLoc();
-
- StringRef Str = "";
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::String))
- return TokError("expected string in '.abort' directive");
-
- Str = getTok().getString();
-
- Lex();
- }
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.abort' directive");
-
- Lex();
-
- // FIXME: Handle here.
- if (Str.empty())
- Error(Loc, ".abort detected. Assembly stopping.");
- else
- Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
-
- return false;
-}
-
-/// ParseDirectiveLsym
-/// ::= .lsym identifier , expression
-bool AsmParser::ParseDirectiveDarwinLsym() {
- StringRef Name;
- if (ParseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = CreateSymbol(Name);
-
- if (Lexer.isNot(AsmToken::Comma))
- return TokError("unexpected token in '.lsym' directive");
- Lex();
-
- const MCExpr *Value;
- SMLoc StartLoc = Lexer.getLoc();
- if (ParseExpression(Value))
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.lsym' directive");
-
- Lex();
-
- // We don't currently support this directive.
- //
- // FIXME: Diagnostic location!
- (void) Sym;
- return TokError("directive '.lsym' is unsupported");
-}
-
-/// ParseDirectiveInclude
-/// ::= .include "filename"
-bool AsmParser::ParseDirectiveInclude() {
- if (Lexer.isNot(AsmToken::String))
- return TokError("expected string in '.include' directive");
-
- std::string Filename = getTok().getString();
- SMLoc IncludeLoc = Lexer.getLoc();
- Lex();
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.include' directive");
-
- // Strip the quotes.
- Filename = Filename.substr(1, Filename.size()-2);
-
- // Attempt to switch the lexer to the included file before consuming the end
- // of statement to avoid losing it when we switch.
- if (EnterIncludeFile(Filename)) {
- PrintMessage(IncludeLoc,
- "Could not find include file '" + Filename + "'",
- "error");
- return true;
- }
-
- return false;
-}
-
-/// ParseDirectiveDarwinDumpOrLoad
-/// ::= ( .dump | .load ) "filename"
-bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) {
- if (Lexer.isNot(AsmToken::String))
- return TokError("expected string in '.dump' or '.load' directive");
-
- Lex();
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.dump' or '.load' directive");
-
- Lex();
-
- // FIXME: If/when .dump and .load are implemented they will be done in the
- // the assembly parser and not have any need for an MCStreamer API.
- if (IsDump)
- Warning(IDLoc, "ignoring directive .dump for now");
- else
- Warning(IDLoc, "ignoring directive .load for now");
-
- return false;
-}
-
-/// ParseDirectiveIf
-/// ::= .if expression
-bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
- // Consume the identifier that was the .if directive
- Lex();
-
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
- if(TheCondState.Ignore) {
- EatToEndOfStatement();
- }
- else {
- int64_t ExprValue;
- if (ParseAbsoluteExpression(ExprValue))
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.if' directive");
-
- Lex();
-
- TheCondState.CondMet = ExprValue;
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// ParseDirectiveElseIf
-/// ::= .elseif expression
-bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
- " an .elseif");
- TheCondState.TheCond = AsmCond::ElseIfCond;
-
- // Consume the identifier that was the .elseif directive
- Lex();
-
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet) {
- TheCondState.Ignore = true;
- EatToEndOfStatement();
- }
- else {
- int64_t ExprValue;
- if (ParseAbsoluteExpression(ExprValue))
- return true;
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.elseif' directive");
-
- Lex();
- TheCondState.CondMet = ExprValue;
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// ParseDirectiveElse
-/// ::= .else
-bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
- // Consume the identifier that was the .else directive
- Lex();
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.else' directive");
-
- Lex();
-
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
- ".elseif");
- TheCondState.TheCond = AsmCond::ElseCond;
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet)
- TheCondState.Ignore = true;
- else
- TheCondState.Ignore = false;
-
- return false;
-}
-
-/// ParseDirectiveEndIf
-/// ::= .endif
-bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
- // Consume the identifier that was the .endif directive
- Lex();
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.endif' directive");
-
- Lex();
-
- if ((TheCondState.TheCond == AsmCond::NoCond) ||
- TheCondStack.empty())
- Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
- ".else");
- if (!TheCondStack.empty()) {
- TheCondState = TheCondStack.back();
- TheCondStack.pop_back();
- }
-
- return false;
-}
-
-/// ParseDirectiveFile
-/// ::= .file [number] string
-bool AsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) {
- // FIXME: I'm not sure what this is.
- int64_t FileNumber = -1;
- if (Lexer.is(AsmToken::Integer)) {
- FileNumber = getTok().getIntVal();
- Lex();
-
- if (FileNumber < 1)
- return TokError("file number less than one");
- }
-
- if (Lexer.isNot(AsmToken::String))
- return TokError("unexpected token in '.file' directive");
-
- StringRef ATTRIBUTE_UNUSED FileName = getTok().getString();
- Lex();
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.file' directive");
-
- // FIXME: Do something with the .file.
-
- return false;
-}
-
-/// ParseDirectiveLine
-/// ::= .line [number]
-bool AsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) {
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::Integer))
- return TokError("unexpected token in '.line' directive");
-
- int64_t LineNumber = getTok().getIntVal();
- (void) LineNumber;
- Lex();
-
- // FIXME: Do something with the .line.
- }
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.file' directive");
-
- return false;
-}
-
-
-/// ParseDirectiveLoc
-/// ::= .loc number [number [number]]
-bool AsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
- if (Lexer.isNot(AsmToken::Integer))
- return TokError("unexpected token in '.loc' directive");
-
- // FIXME: What are these fields?
- int64_t FileNumber = getTok().getIntVal();
- (void) FileNumber;
- // FIXME: Validate file.
-
- Lex();
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::Integer))
- return TokError("unexpected token in '.loc' directive");
-
- int64_t Param2 = getTok().getIntVal();
- (void) Param2;
- Lex();
-
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::Integer))
- return TokError("unexpected token in '.loc' directive");
-
- int64_t Param3 = getTok().getIntVal();
- (void) Param3;
- Lex();
-
- // FIXME: Do something with the .loc.
- }
- }
-
- if (Lexer.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.file' directive");
-
- return false;
-}
-
diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h
deleted file mode 100644
index 9336d35..0000000
--- a/tools/llvm-mc/AsmParser.h
+++ /dev/null
@@ -1,178 +0,0 @@
-//===- AsmParser.h - Parser for Assembly Files ------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class declares the parser for assembly files.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ASMPARSER_H
-#define ASMPARSER_H
-
-#include <vector>
-#include "AsmLexer.h"
-#include "AsmCond.h"
-#include "llvm/MC/MCAsmParser.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/ADT/StringMap.h"
-
-namespace llvm {
-class AsmCond;
-class AsmToken;
-class MCContext;
-class MCExpr;
-class MCInst;
-class MCStreamer;
-class MCAsmInfo;
-class MCValue;
-class SourceMgr;
-class TargetAsmParser;
-class Twine;
-
-class AsmParser : public MCAsmParser {
-private:
- AsmLexer Lexer;
- MCContext &Ctx;
- MCStreamer &Out;
- SourceMgr &SrcMgr;
- TargetAsmParser *TargetParser;
-
- /// This is the current buffer index we're lexing from as managed by the
- /// SourceMgr object.
- int CurBuffer;
-
- AsmCond TheCondState;
- std::vector<AsmCond> TheCondStack;
-
- // FIXME: Figure out where this should leave, the code is a copy of that which
- // is also used by TargetLoweringObjectFile.
- mutable void *SectionUniquingMap;
-
- /// DirectiveMap - This is a table handlers for directives. Each handler is
- /// invoked after the directive identifier is read and is responsible for
- /// parsing and validating the rest of the directive. The handler is passed
- /// in the directive name and the location of the directive keyword.
- StringMap<bool(AsmParser::*)(StringRef, SMLoc)> DirectiveMap;
-public:
- AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out,
- const MCAsmInfo &_MAI);
- ~AsmParser();
-
- bool Run();
-
-
- void AddDirectiveHandler(StringRef Directive,
- bool (AsmParser::*Handler)(StringRef, SMLoc)) {
- DirectiveMap[Directive] = Handler;
- }
-public:
- TargetAsmParser &getTargetParser() const { return *TargetParser; }
- void setTargetParser(TargetAsmParser &P) { TargetParser = &P; }
-
- /// @name MCAsmParser Interface
- /// {
-
- virtual MCAsmLexer &getLexer() { return Lexer; }
- virtual MCContext &getContext() { return Ctx; }
- virtual MCStreamer &getStreamer() { return Out; }
-
- virtual void Warning(SMLoc L, const Twine &Meg);
- virtual bool Error(SMLoc L, const Twine &Msg);
-
- const AsmToken &Lex();
-
- bool ParseExpression(const MCExpr *&Res);
- virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc);
- virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc);
- virtual bool ParseAbsoluteExpression(int64_t &Res);
-
- /// }
-
-private:
- MCSymbol *CreateSymbol(StringRef Name);
-
- // FIXME: See comment on SectionUniquingMap.
- const MCSection *getMachOSection(const StringRef &Segment,
- const StringRef &Section,
- unsigned TypeAndAttributes,
- unsigned Reserved2,
- SectionKind Kind) const;
-
- bool ParseStatement();
-
- bool TokError(const char *Msg);
-
- void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const;
-
- /// EnterIncludeFile - Enter the specified file. This returns true on failure.
- bool EnterIncludeFile(const std::string &Filename);
-
- bool ParseConditionalAssemblyDirectives(StringRef Directive,
- SMLoc DirectiveLoc);
- void EatToEndOfStatement();
-
- bool ParseAssignment(const StringRef &Name);
-
- bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc);
- bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
- bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
-
- /// ParseIdentifier - Parse an identifier or string (as a quoted identifier)
- /// and set \arg Res to the identifier contents.
- bool ParseIdentifier(StringRef &Res);
-
- // Directive Parsing.
- bool ParseDirectiveDarwinSection(); // Darwin specific ".section".
- bool ParseDirectiveSectionSwitch(const char *Segment, const char *Section,
- unsigned TAA = 0, unsigned ImplicitAlign = 0,
- unsigned StubSize = 0);
- bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz"
- bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ...
- bool ParseDirectiveFill(); // ".fill"
- 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);
- bool ParseDirectiveDarwinSymbolDesc(); // Darwin specific ".desc"
- bool ParseDirectiveDarwinLsym(); // Darwin specific ".lsym"
-
- bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
- bool ParseDirectiveDarwinZerofill(); // Darwin specific ".zerofill"
-
- // Darwin specific ".subsections_via_symbols"
- bool ParseDirectiveDarwinSubsectionsViaSymbols();
- // Darwin specific .dump and .load
- bool ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump);
-
- bool ParseDirectiveAbort(); // ".abort"
- bool ParseDirectiveInclude(); // ".include"
-
- bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if"
- bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
- bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else"
- bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
-
- bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc); // ".file"
- bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); // ".line"
- bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); // ".loc"
-
- /// ParseEscapedString - Parse the current token as a string which may include
- /// escaped characters and return the string contents.
- bool ParseEscapedString(std::string &Data);
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp
index 5fde712..dbfe7a5 100644
--- a/tools/llvm-mc/Disassembler.cpp
+++ b/tools/llvm-mc/Disassembler.cpp
@@ -47,32 +47,30 @@ public:
};
}
-static bool PrintInst(const llvm::MCDisassembler &DisAsm,
+static bool PrintInsts(const llvm::MCDisassembler &DisAsm,
llvm::MCInstPrinter &Printer, const ByteArrayTy &Bytes,
SourceMgr &SM) {
// Wrap the vector in a MemoryObject.
VectorMemoryObject memoryObject(Bytes);
- // Disassemble it to a string and get the size of the instruction.
- MCInst Inst;
+ // Disassemble it to strings.
uint64_t Size;
+ uint64_t Index;
- if (!DisAsm.getInstruction(Inst, Size, memoryObject, 0,
- /*REMOVE*/ nulls())) {
- SM.PrintMessage(SMLoc::getFromPointer(Bytes[0].second),
- "invalid instruction encoding", "error");
- return true;
- }
-
- Printer.printInst(&Inst);
- outs() << "\n";
-
- // If the disassembled instruction was smaller than the number of bytes we
- // read, reject the excess bytes.
- if (Bytes.size() != Size) {
- SM.PrintMessage(SMLoc::getFromPointer(Bytes[Size].second),
- "excess data detected in input", "error");
- return true;
+ for (Index = 0; Index < Bytes.size(); Index += Size) {
+ MCInst Inst;
+
+ if (DisAsm.getInstruction(Inst, Size, memoryObject, Index,
+ /*REMOVE*/ nulls())) {
+ Printer.printInst(&Inst);
+ outs() << "\n";
+ }
+ else {
+ SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
+ "invalid instruction encoding", "warning");
+ if (Size == 0)
+ Size = 1; // skip illegible bytes
+ }
}
return false;
@@ -117,15 +115,9 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
continue;
}
- // If this is the end of a line or start of a comment, process the
- // instruction we have so far.
+ // If this is the end of a line or start of a comment, remove the rest of
+ // the line.
if (Str[0] == '\n' || Str[0] == '#') {
- // If we have bytes to process, do so.
- if (!ByteArray.empty()) {
- ErrorOccurred |= PrintInst(*DisAsm, *InstPrinter, ByteArray, SM);
- ByteArray.clear();
- }
-
// Strip to the end of line if we already processed any bytes on this
// line. This strips the comment and/or the \n.
if (Str[0] == '\n')
@@ -159,7 +151,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
}
if (!ByteArray.empty())
- ErrorOccurred |= PrintInst(*DisAsm, *InstPrinter, ByteArray, SM);
+ ErrorOccurred |= PrintInsts(*DisAsm, *InstPrinter, ByteArray, SM);
return ErrorOccurred;
}
diff --git a/tools/llvm-mc/HexDisassembler.cpp b/tools/llvm-mc/HexDisassembler.cpp
deleted file mode 100644
index 7435c10..0000000
--- a/tools/llvm-mc/HexDisassembler.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-//===- HexDisassembler.cpp - Disassembler for hex strings -----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the disassembler of strings of bytes written in
-// hexadecimal, from standard input or from a file.
-//
-//===----------------------------------------------------------------------===//
-
-#include "HexDisassembler.h"
-
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCDisassembler.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/MemoryObject.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/SourceMgr.h"
-using namespace llvm;
-
-typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
-
-namespace {
-class VectorMemoryObject : public MemoryObject {
-private:
- const ByteArrayTy &Bytes;
-public:
- VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {}
-
- uint64_t getBase() const { return 0; }
- uint64_t getExtent() const { return Bytes.size(); }
-
- int readByte(uint64_t Addr, uint8_t *Byte) const {
- if (Addr > getExtent())
- return -1;
- *Byte = Bytes[Addr].first;
- return 0;
- }
-};
-}
-
-static bool PrintInst(const llvm::MCDisassembler &DisAsm,
- llvm::MCInstPrinter &Printer, const ByteArrayTy &Bytes,
- SourceMgr &SM) {
- // Wrap the vector in a MemoryObject.
- VectorMemoryObject memoryObject(Bytes);
-
- // Disassemble it to a string and get the size of the instruction.
- MCInst Inst;
- uint64_t Size;
-
- std::string verboseOStr;
- llvm::raw_string_ostream verboseOS(verboseOStr);
-
- if (!DisAsm.getInstruction(Inst, Size, memoryObject, 0, verboseOS)) {
- SM.PrintMessage(SMLoc::getFromPointer(Bytes[0].second),
- "invalid instruction encoding", "error");
- errs() << "Diagnostic log:" << '\n';
- errs() << verboseOS.str() << '\n';
- return true;
- }
-
- Printer.printInst(&Inst);
- outs() << "\n";
-
- // If the disassembled instruction was smaller than the number of bytes we
- // read, reject the excess bytes.
- if (Bytes.size() != Size) {
- SM.PrintMessage(SMLoc::getFromPointer(Bytes[Size].second),
- "excess data detected in input", "error");
- return true;
- }
-
- return false;
-}
-
-int HexDisassembler::disassemble(const Target &T, const std::string &Triple,
- MemoryBuffer &Buffer) {
- // Set up disassembler.
- llvm::OwningPtr<const llvm::MCAsmInfo> AsmInfo(T.createAsmInfo(Triple));
-
- if (!AsmInfo) {
- errs() << "error: no assembly info for target " << Triple << "\n";
- return -1;
- }
-
- llvm::OwningPtr<const llvm::MCDisassembler> DisAsm(T.createMCDisassembler());
- if (!DisAsm) {
- errs() << "error: no disassembler for target " << Triple << "\n";
- return -1;
- }
-
- llvm::MCInstPrinter *InstPrinter = T.createMCInstPrinter(0, *AsmInfo, outs());
-
- if (!InstPrinter) {
- errs() << "error: no instruction printer for target " << Triple << '\n';
- return -1;
- }
-
- bool ErrorOccurred = false;
-
- SourceMgr SM;
- SM.AddNewSourceBuffer(&Buffer, SMLoc());
-
- // Convert the input to a vector for disassembly.
- ByteArrayTy ByteArray;
-
- StringRef Str = Buffer.getBuffer();
- while (!Str.empty()) {
- // Strip horizontal whitespace.
- if (size_t Pos = Str.find_first_not_of(" \t\r")) {
- Str = Str.substr(Pos);
- continue;
- }
-
- // If this is the end of a line or start of a comment, process the
- // instruction we have so far.
- if (Str[0] == '\n' || Str[0] == '#') {
- // If we have bytes to process, do so.
- if (!ByteArray.empty()) {
- ErrorOccurred |= PrintInst(*DisAsm, *InstPrinter, ByteArray, SM);
- ByteArray.clear();
- }
-
- // Strip to the end of line if we already processed any bytes on this
- // line. This strips the comment and/or the \n.
- if (Str[0] == '\n')
- Str = Str.substr(1);
- else {
- Str = Str.substr(Str.find_first_of('\n'));
- if (!Str.empty())
- Str = Str.substr(1);
- }
- continue;
- }
-
- // Get the current token.
- size_t Next = Str.find_first_of(" \t\n\r#");
- StringRef Value = Str.substr(0, Next);
-
- // Convert to a byte and add to the byte vector.
- unsigned ByteVal;
- if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) {
- // If we have an error, print it and skip to the end of line.
- SM.PrintMessage(SMLoc::getFromPointer(Value.data()),
- "invalid input token", "error");
- ErrorOccurred = true;
- Str = Str.substr(Str.find('\n'));
- ByteArray.clear();
- continue;
- }
-
- ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data()));
- Str = Str.substr(Next);
- }
-
- if (!ByteArray.empty())
- ErrorOccurred |= PrintInst(*DisAsm, *InstPrinter, ByteArray, SM);
-
- return ErrorOccurred;
-}
diff --git a/tools/llvm-mc/HexDisassembler.h b/tools/llvm-mc/HexDisassembler.h
deleted file mode 100644
index d197aea..0000000
--- a/tools/llvm-mc/HexDisassembler.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- HexDisassembler.h - Disassembler for hex strings -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the disassembler of strings of bytes written in
-// hexadecimal, from standard input or from a file.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef HEXDISASSEMBLER_H
-#define HEXDISASSEMBLER_H
-
-#include <string>
-
-namespace llvm {
-
-class Target;
-class MemoryBuffer;
-
-class HexDisassembler {
-public:
- static int disassemble(const Target &target,
- const std::string &tripleString,
- MemoryBuffer &buffer);
-};
-
-} // namespace llvm
-
-#endif
diff --git a/tools/llvm-mc/Makefile b/tools/llvm-mc/Makefile
index 5ce1a8f..5b0fe3f 100644
--- a/tools/llvm-mc/Makefile
+++ b/tools/llvm-mc/Makefile
@@ -13,7 +13,6 @@ TOOLNAME = llvm-mc
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
NO_INSTALL = 1
-CXXFLAGS = -fno-rtti
# Include this here so we can get the configuration of the targets
# that have been configured for construction. We have to do this
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index 342ae99..76ce080 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -46,6 +46,9 @@ OutputFilename("o", cl::desc("Output filename"),
static cl::opt<bool>
ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
+static cl::opt<bool>
+ShowInst("show-inst", cl::desc("Show internal instruction representation"));
+
static cl::opt<unsigned>
OutputAsmVariant("output-asm-variant",
cl::desc("Syntax variant to use for output printing"));
@@ -263,13 +266,14 @@ static int AssembleInput(const char *ProgName) {
if (FileType == OFT_AssemblyFile) {
IP.reset(TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *Out));
if (ShowEncoding)
- CE.reset(TheTarget->createCodeEmitter(*TM));
+ CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
Str.reset(createAsmStreamer(Ctx, *Out, *MAI,
TM->getTargetData()->isLittleEndian(),
- /*asmverbose*/true, IP.get(), CE.get()));
+ /*asmverbose*/true, IP.get(), CE.get(),
+ ShowInst));
} else {
assert(FileType == OFT_ObjectFile && "Invalid file type!");
- CE.reset(TheTarget->createCodeEmitter(*TM));
+ CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
Str.reset(createMachOStreamer(Ctx, *Out, CE.get()));
}
diff --git a/tools/llvm-nm/Makefile b/tools/llvm-nm/Makefile
index bdefaa6..ecf5f8c 100644
--- a/tools/llvm-nm/Makefile
+++ b/tools/llvm-nm/Makefile
@@ -13,6 +13,5 @@ LINK_COMPONENTS = archive bitreader
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
-CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-prof/Makefile b/tools/llvm-prof/Makefile
index b1fd330..86eb54d 100644
--- a/tools/llvm-prof/Makefile
+++ b/tools/llvm-prof/Makefile
@@ -13,6 +13,5 @@ LINK_COMPONENTS = bitreader analysis
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
-CXXFLAGS = -fno-rtti
include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/Makefile b/tools/llvmc/Makefile
index df91728..8f99526 100644
--- a/tools/llvmc/Makefile
+++ b/tools/llvmc/Makefile
@@ -11,6 +11,7 @@ LEVEL = ../..
export LLVMC_BASED_DRIVER_NAME = llvmc
export LLVMC_BUILTIN_PLUGINS = Base Clang
+REQUIRES_RTTI = 1
DIRS = plugins driver
diff --git a/tools/llvmc/example/mcc16/driver/Main.cpp b/tools/llvmc/example/mcc16/driver/Main.cpp
index 5d50f9d..e66e2f9 100644
--- a/tools/llvmc/example/mcc16/driver/Main.cpp
+++ b/tools/llvmc/example/mcc16/driver/Main.cpp
@@ -37,11 +37,15 @@ int main(int argc, char** argv) {
DryRun.setHiddenFlag(llvm::cl::Hidden);
llvm::cl::SetVersionPrinter(PIC16VersionPrinter);
-
- TempDirname = "tmp-objs";
- // Remove the temp dir if already exists.
+ // Ask for a standard temp dir, but just cache its basename., and delete it.
llvm::sys::Path tempDir;
+ tempDir = llvm::sys::Path::GetTemporaryDirectory();
+ TempDirname = tempDir.getBasename();
+ tempDir.eraseFromDisk(true);
+
+ // We are creating a temp dir in current dir, with the cached name.
+ // But before that remove if one already exists with that name..
tempDir = TempDirname;
tempDir.eraseFromDisk(true);
diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td b/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td
index 717e95e..f13b9f8 100644
--- a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td
+++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td
@@ -47,15 +47,24 @@ def OptionList : OptionList<[
(help "Optimization Level 3.")),
(switch_option "Od",
(help "Perform Debug-safe Optimizations only.")),
- (switch_option "r",
- (help "Use resource file for part info"),
- (really_hidden)),
+ (switch_option "w",
+ (help "Disable all warnings.")),
+// (switch_option "O1",
+// (help "Optimization level 1")),
+// (switch_option "O2",
+// (help "Optimization level 2. (Default)")),
+// (parameter_option "pre-RA-sched",
+// (help "Example of an option that is passed to llc")),
(parameter_option "regalloc",
- (help "Register allocator to use.(possible values: simple, linearscan, pbqp, local. default = pbqp)")),
- (prefix_list_option "Wa,",
+ (help "Register allocator to use.(possible values: simple, linearscan, pbqp, local. default = linearscan)")),
+ (prefix_list_option "Wa,", (comma_separated),
(help "Pass options to assembler (Run 'gpasm -help' for assembler options)")),
- (prefix_list_option "Wl,",
+ (prefix_list_option "Wl,", (comma_separated),
(help "Pass options to linker (Run 'mplink -help' for linker options)"))
+// (prefix_list_option "Wllc,",
+// (help "Pass options to llc")),
+// (prefix_list_option "Wo,",
+// (help "Pass options to llvm-ld"))
]>;
// Tools
@@ -75,6 +84,7 @@ class clang_based<string language, string cmd, string ext_E> : Tool<
(switch_on "E"), [(stop_compilation), (output_suffix ext_E)],
(switch_on "bc"),[(stop_compilation), (output_suffix "bc")],
(switch_on "g"), (append_cmd "-g"),
+ (switch_on "w"), (append_cmd "-w"),
(switch_on "O1"), (append_cmd ""),
(switch_on "O2"), (append_cmd ""),
(switch_on "O3"), (append_cmd ""),
@@ -83,9 +93,22 @@ class clang_based<string language, string cmd, string ext_E> : Tool<
(not_empty "I"), (forward "I"),
(switch_on "O0"), (append_cmd "-O0"),
(default), (append_cmd "-O1")))
+// (sink)
]>;
-def clang_cc : clang_based<"c", "$CALL(GetBinDir)clang -cc1 -I $CALL(GetStdHeadersDir) -triple=pic16- -emit-llvm-bc ", "i">;
+def clang_cc : clang_based<"c", "$CALL(GetBinDir)clang -cc1 -I $CALL(GetStdHeadersDir) -D $CALL(GetLowerCasePartDefine) -D $CALL(GetUpperCasePartDefine) -triple=pic16- -emit-llvm-bc ", "i">;
+
+//def clang_cc : Tool<[
+// (in_language "c"),
+// (out_language "llvm-bitcode"),
+// (output_suffix "bc"),
+// (cmd_line "$CALL(GetBinDir)clang-cc -I $CALL(GetStdHeadersDir) -triple=pic16- -emit-llvm-bc "),
+// (cmd_line kkkkk
+// (actions (case
+// (switch_on "g"), (append_cmd "g"),
+// (not_empty "I"), (forward "I"))),
+// (sink)
+//]>;
// pre-link-and-lto step.
@@ -93,12 +116,12 @@ def llvm_ld : Tool<[
(in_language "llvm-bitcode"),
(out_language "llvm-bitcode"),
(output_suffix "bc"),
- (cmd_line "$CALL(GetBinDir)llvm-ld -L $CALL(GetStdLibsDir) -instcombine -disable-licm-promotion $INFILE -b $OUTFILE -l std"),
+ (cmd_line "$CALL(GetBinDir)llvm-ld -L $CALL(GetStdLibsDir) -disable-gvn -disable-licm-promotion -disable-mem2reg $INFILE -b $OUTFILE -l std"),
(actions (case
(switch_on "O0"), (append_cmd "-disable-opt"),
(switch_on "O1"), (append_cmd "-disable-opt"),
- (switch_on "O2"), (append_cmd ""),
// Whenever O3 is not specified on the command line, default i.e. disable-inlining will always be added.
+ (switch_on "O2"), (append_cmd ""),
(switch_on "O3"), (append_cmd ""),
(default), (append_cmd "-disable-inlining"))),
(join)
@@ -109,9 +132,16 @@ def llvm_ld_optimizer : Tool<[
(in_language "llvm-bitcode"),
(out_language "llvm-bitcode"),
(output_suffix "bc"),
- (cmd_line "$CALL(GetBinDir)llvm-ld -instcombine -disable-inlining $INFILE -b $OUTFILE"),
+// FIXME: we are still not disabling licm-promotion.
+// -disable-licm-promotion and building stdn library causes c16-71 to fail.
+ (cmd_line "$CALL(GetBinDir)llvm-ld -disable-gvn -disable-mem2reg $INFILE -b $OUTFILE"),
(actions (case
- (switch_on "O0"), (append_cmd "-disable-opt")))
+ (switch_on "O0"), (append_cmd "-disable-opt"),
+ (switch_on "O1"), (append_cmd "-disable-opt"),
+// Whenever O3 is not specified on the command line, default i.e. disable-inlining will always be added.
+ (switch_on "O2"), (append_cmd ""),
+ (switch_on "O3"), (append_cmd ""),
+ (default), (append_cmd "-disable-inlining")))
]>;
// optimizer step.
@@ -119,7 +149,7 @@ def pic16passes : Tool<[
(in_language "llvm-bitcode"),
(out_language "llvm-bitcode"),
(output_suffix "obc"),
- (cmd_line "$CALL(GetBinDir)opt -pic16overlay $INFILE -f -o $OUTFILE"),
+ (cmd_line "$CALL(GetBinDir)opt -pic16cg -pic16overlay $INFILE -f -o $OUTFILE"),
(actions (case
(switch_on "O0"), (append_cmd "-disable-opt")))
]>;
@@ -131,19 +161,20 @@ def llc : Tool<[
(cmd_line "$CALL(GetBinDir)llc -march=pic16 -disable-jump-tables -pre-RA-sched=list-burr -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")))
(not_empty "regalloc"), (forward "regalloc"),
- (empty "regalloc"), (append_cmd "-regalloc=pbqp")))
+ (empty "regalloc"), (append_cmd "-regalloc=linearscan")))
]>;
def gpasm : Tool<[
(in_language "assembler"),
(out_language "object-code"),
(output_suffix "o"),
- (cmd_line "$CALL(GetBinDir)gpasm -r decimal -I $CALL(GetStdAsmHeadersDir) -C -c -w 2 $INFILE -o $OUTFILE"),
+ (cmd_line "$CALL(GetBinDir)gpasm -z -r decimal -I $CALL(GetStdAsmHeadersDir) -C -c -w 2 $INFILE -o $OUTFILE"),
(actions (case
(switch_on "c"), (stop_compilation),
(switch_on "g"), (append_cmd "-g"),
- (switch_on "r"), (append_cmd "-z"),
(not_empty "p"), (forward "p"),
(empty "p"), (append_cmd "-p 16f1xxx"),
(not_empty "Wa,"), (forward_value "Wa,")))
@@ -153,18 +184,18 @@ def mplink : Tool<[
(in_language "object-code"),
(out_language "executable"),
(output_suffix "cof"),
- (cmd_line "$CALL(GetBinDir)mplink -k $CALL(GetStdLinkerScriptsDir) -l $CALL(GetStdLibsDir) intrinsics.lib stdn.lib $INFILE -o $OUTFILE"),
+ (cmd_line "$CALL(GetBinDir)mplink -e -k $CALL(GetStdLinkerScriptsDir) -l $CALL(GetStdLibsDir) intrinsics.lib stdn.lib $INFILE -o $OUTFILE"),
(actions (case
(not_empty "Wl,"), (forward_value "Wl,"),
- (switch_on "r"), (append_cmd "-e"),
(switch_on "X"), (append_cmd "-x"),
(not_empty "L"), (forward_as "L", "-l"),
(not_empty "K"), (forward_as "K", "-k"),
(not_empty "m"), (forward "m"),
(not_empty "p"), [(forward "p"), (append_cmd "-c")],
(empty "p"), (append_cmd "-p 16f1xxx -c"),
- (not_empty "k"), (forward_value "k"),
- (not_empty "l"), (forward_value "l"))),
+// (not_empty "l"), [(unpack_values "l"),(append_cmd ".lib")])),
+ (not_empty "k"), (forward "k"),
+ (not_empty "l"), (forward "l"))),
(join)
]>;
diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp b/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp
index a6d2ff6..9b2f9fc5 100644
--- a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp
+++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp
@@ -9,6 +9,8 @@ namespace llvmc {
extern char *ProgramName;
}
+
+
// Returns the platform specific directory separator via #ifdefs.
// FIXME: This currently work on linux and windows only. It does not
// work on other unices.
@@ -21,6 +23,43 @@ static std::string GetDirSeparator() {
}
namespace hooks {
+// Get preprocessor define for the part.
+// It is __partname format in lower case.
+std::string
+GetLowerCasePartDefine(void) {
+ std::string Partname;
+ if (AutoGeneratedParameter_p.empty()) {
+ Partname = "16f1xxx";
+ } else {
+ Partname = AutoGeneratedParameter_p;
+ }
+
+ std::string LowerCase;
+ for (unsigned i = 0; i <= Partname.size(); i++) {
+ LowerCase.push_back(std::tolower(Partname[i]));
+ }
+
+ return "__" + LowerCase;
+}
+
+std::string
+GetUpperCasePartDefine(void) {
+ std::string Partname;
+ if (AutoGeneratedParameter_p.empty()) {
+ Partname = "16f1xxx";
+ } else {
+ Partname = AutoGeneratedParameter_p;
+ }
+
+ std::string UpperCase;
+ for (unsigned i = 0; i <= Partname.size(); i++) {
+ UpperCase.push_back(std::toupper(Partname[i]));
+ }
+
+ return "__" + UpperCase;
+}
+
+
// Get the dir where c16 executables reside.
std::string GetBinDir() {
// Construct a Path object from the program name.
diff --git a/tools/llvmc/plugins/Base/Base.td.in b/tools/llvmc/plugins/Base/Base.td.in
index cf0ff68..1acd969 100644
--- a/tools/llvmc/plugins/Base/Base.td.in
+++ b/tools/llvmc/plugins/Base/Base.td.in
@@ -50,10 +50,18 @@ def OptList : OptionList<[
(help "Choose linker (possible values: gcc, g++)")),
(parameter_option "mtune",
(help "Target a specific CPU type"), (hidden)),
+
+ // TODO: Add a conditional compilation mechanism to make Darwin-only options
+ // like '-arch' really Darwin-only.
+
+ (parameter_option "arch",
+ (help "Compile for the specified target architecture"), (hidden)),
(parameter_option "march",
(help "A synonym for -mtune"), (hidden)),
(parameter_option "mcpu",
(help "A deprecated synonym for -mtune"), (hidden)),
+ (switch_option "mfix-and-continue",
+ (help "Needed by gdb to load .o files dynamically"), (hidden)),
(parameter_option "MF",
(help "Specify a file to write dependencies to"), (hidden)),
(parameter_list_option "MT",
@@ -61,6 +69,9 @@ def OptList : OptionList<[
(hidden)),
(parameter_list_option "include",
(help "Include the named file prior to preprocessing")),
+ (parameter_list_option "iquote",
+ (help "Search dir only for files requested with #inlcude \"file\""),
+ (hidden)),
(parameter_list_option "framework",
(help "Specifies a framework to link against")),
(parameter_list_option "weak_framework",
@@ -85,7 +96,19 @@ def OptList : OptionList<[
(help "Pass options to opt")),
(prefix_list_option "m",
(help "Enable or disable various extensions (-mmmx, -msse, etc.)"),
- (hidden))
+ (hidden)),
+ (switch_option "dynamiclib", (hidden),
+ (help "Produce a dynamic library")),
+ (switch_option "prebind", (hidden),
+ (help "Prebind all undefined symbols")),
+ (switch_option "dead_strip", (hidden),
+ (help "Remove unreachable blocks of code")),
+ (switch_option "single_module", (hidden),
+ (help "Build the library so it contains only one module")),
+ (parameter_option "compatibility_version", (hidden),
+ (help "Compatibility version number")),
+ (parameter_option "current_version", (hidden),
+ (help "Current version number"))
]>;
// Option preprocessor.
@@ -129,14 +152,17 @@ class llvm_gcc_based <string cmd_prefix, string in_lang, string E_ext> : Tool<
(switch_on ["emit-llvm", "c"]), (stop_compilation),
(switch_on "fsyntax-only"), (stop_compilation),
(not_empty "include"), (forward "include"),
+ (not_empty "iquote"), (forward "iquote"),
(not_empty "save-temps"), (append_cmd "-save-temps"),
(not_empty "I"), (forward "I"),
(not_empty "F"), (forward "F"),
(not_empty "D"), (forward "D"),
+ (not_empty "arch"), (forward "arch"),
(not_empty "march"), (forward "march"),
(not_empty "mtune"), (forward "mtune"),
(not_empty "mcpu"), (forward "mcpu"),
(not_empty "m"), (forward "m"),
+ (switch_on "mfix-and-continue"), (forward "mfix-and-continue"),
(switch_on "m32"), (forward "m32"),
(switch_on "m64"), (forward "m64"),
(switch_on "O0"), (forward "O0"),
@@ -183,6 +209,7 @@ def llvm_gcc_assembler : Tool<
(cmd_line "@LLVMGCCCOMMAND@ -c -x assembler $INFILE -o $OUTFILE"),
(actions (case
(switch_on "c"), (stop_compilation),
+ (not_empty "arch"), (forward "arch"),
(not_empty "Wa,"), (forward_value "Wa,")))
]>;
@@ -218,12 +245,21 @@ class llvm_gcc_based_linker <string cmd_prefix> : Tool<
(switch_on "pthread"), (append_cmd "-lpthread"),
(not_empty "L"), (forward "L"),
(not_empty "F"), (forward "F"),
+ (not_empty "arch"), (forward "arch"),
(not_empty "framework"), (forward "framework"),
(not_empty "weak_framework"), (forward "weak_framework"),
(switch_on "m32"), (forward "m32"),
(switch_on "m64"), (forward "m64"),
(not_empty "l"), (forward "l"),
- (not_empty "Wl,"), (forward "Wl,")))
+ (not_empty "Wl,"), (forward "Wl,"),
+ (switch_on "dynamiclib"), (forward "dynamiclib"),
+ (switch_on "prebind"), (forward "prebind"),
+ (switch_on "dead_strip"), (forward "dead_strip"),
+ (switch_on "single_module"), (forward "single_module"),
+ (not_empty "compatibility_version"),
+ (forward "compatibility_version"),
+ (not_empty "current_version"),
+ (forward "current_version")))
]>;
// Default linker
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
index 46e967a..0a58aa7 100644
--- a/tools/lto/LTOCodeGenerator.cpp
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -15,13 +15,11 @@
#include "LTOModule.h"
#include "LTOCodeGenerator.h"
-
#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"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
@@ -29,7 +27,6 @@
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/CodeGen/FileWriters.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -392,32 +389,15 @@ bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out,
// Make sure everything is still good.
passes.add(createVerifierPass());
- FunctionPassManager* codeGenPasses =
- new FunctionPassManager(new ExistingModuleProvider(mergedModule));
+ FunctionPassManager* codeGenPasses = new FunctionPassManager(mergedModule);
codeGenPasses->add(new TargetData(*_target->getTargetData()));
- ObjectCodeEmitter* oce = NULL;
-
- switch (_target->addPassesToEmitFile(*codeGenPasses, out,
- TargetMachine::AssemblyFile,
- CodeGenOpt::Aggressive)) {
- case FileModel::ElfFile:
- oce = AddELFWriter(*codeGenPasses, out, *_target);
- break;
- case FileModel::AsmFile:
- break;
- case FileModel::MachOFile:
- case FileModel::Error:
- case FileModel::None:
- errMsg = "target file type not supported";
- return true;
- }
-
- if (_target->addPassesToEmitFileFinish(*codeGenPasses, oce,
- CodeGenOpt::Aggressive)) {
- errMsg = "target does not support generation of this file type";
- return true;
+ if (_target->addPassesToEmitFile(*codeGenPasses, out,
+ TargetMachine::CGFT_AssemblyFile,
+ CodeGenOpt::Aggressive)) {
+ errMsg = "target file type not supported";
+ return true;
}
// Run our queue of passes all at once now, efficiently.
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index 64de668..15fb3f5 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -17,7 +17,6 @@
#include "llvm/Constants.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
-#include "llvm/ModuleProvider.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/ReaderWriter.h"
@@ -69,14 +68,13 @@ bool LTOModule::isBitcodeFileForTarget(const char* path,
// takes ownership of buffer
bool LTOModule::isTargetMatch(MemoryBuffer* buffer, const char* triplePrefix)
{
- OwningPtr<ModuleProvider> mp(getBitcodeModuleProvider(buffer,
- getGlobalContext()));
- // on success, mp owns buffer and both are deleted at end of this method
- if (!mp) {
+ OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext()));
+ // on success, m owns buffer and both are deleted at end of this method
+ if (!m) {
delete buffer;
return false;
}
- std::string actualTarget = mp->getModule()->getTargetTriple();
+ std::string actualTarget = m->getTargetTriple();
return (strncmp(actualTarget.c_str(), triplePrefix,
strlen(triplePrefix)) == 0);
}
diff --git a/tools/lto/Makefile b/tools/lto/Makefile
index f0bc67c..3120aa5 100644
--- a/tools/lto/Makefile
+++ b/tools/lto/Makefile
@@ -17,7 +17,6 @@ include $(LEVEL)/Makefile.config
LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
-CXXFLAGS = -fno-rtti
LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader bitwriter
diff --git a/tools/opt/Makefile b/tools/opt/Makefile
index 2f184a6..726cad8 100644
--- a/tools/opt/Makefile
+++ b/tools/opt/Makefile
@@ -8,7 +8,6 @@
##===----------------------------------------------------------------------===##
LEVEL = ../..
TOOLNAME = opt
-CXXFLAGS = -fno-rtti
LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 6ed8c9d..5200180 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -14,7 +14,6 @@
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
-#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/Bitcode/ReaderWriter.h"
@@ -427,7 +426,7 @@ int main(int argc, char **argv) {
FunctionPassManager *FPasses = NULL;
if (OptLevelO1 || OptLevelO2 || OptLevelO3) {
- FPasses = new FunctionPassManager(new ExistingModuleProvider(M.get()));
+ FPasses = new FunctionPassManager(M.get());
if (TD)
FPasses->add(new TargetData(*TD));
}
OpenPOWER on IntegriCloud