summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/llvm-mc
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-02-05 23:56:22 +0000
committerdim <dim@FreeBSD.org>2012-02-05 23:56:22 +0000
commiteb8951e7f7015d193e6640deb0ebde32f01b72d8 (patch)
tree8052b8010f619e8d40e5e3b37482591f537e0ca0 /contrib/llvm/tools/llvm-mc
parent4de4d315e465f872a81f448b1788cc017f2d2033 (diff)
parent07637c87f826cdf411f0673595e9bc92ebd793f2 (diff)
downloadFreeBSD-src-eb8951e7f7015d193e6640deb0ebde32f01b72d8.zip
FreeBSD-src-eb8951e7f7015d193e6640deb0ebde32f01b72d8.tar.gz
Add a WITH_CLANG_EXTRAS option for src.conf(5), disabled by default,
that builds the following additional llvm/clang tools: - bugpoint - llc - lli - llvm-ar - llvm-as - llvm-bcanalyzer - llvm-diff - llvm-dis - llvm-extract - llvm-ld - llvm-link - llvm-mc - llvm-nm - llvm-objdump - llvm-prof - llvm-ranlib - llvm-rtdyld - llvm-stub - macho-dump - opt These tools are mainly useful for people that want to manipulate llvm bitcode (.bc) and llvm assembly language (.ll) files, or want to tinker with llvm and clang themselves. MFC after: 2 weeks
Diffstat (limited to 'contrib/llvm/tools/llvm-mc')
-rw-r--r--contrib/llvm/tools/llvm-mc/CMakeLists.txt6
-rw-r--r--contrib/llvm/tools/llvm-mc/Disassembler.cpp368
-rw-r--r--contrib/llvm/tools/llvm-mc/Disassembler.h42
-rw-r--r--contrib/llvm/tools/llvm-mc/Makefile24
-rw-r--r--contrib/llvm/tools/llvm-mc/llvm-mc.cpp517
5 files changed, 957 insertions, 0 deletions
diff --git a/contrib/llvm/tools/llvm-mc/CMakeLists.txt b/contrib/llvm/tools/llvm-mc/CMakeLists.txt
new file mode 100644
index 0000000..805caf4
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mc/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC MCParser MCDisassembler)
+
+add_llvm_tool(llvm-mc
+ llvm-mc.cpp
+ Disassembler.cpp
+ )
diff --git a/contrib/llvm/tools/llvm-mc/Disassembler.cpp b/contrib/llvm/tools/llvm-mc/Disassembler.cpp
new file mode 100644
index 0000000..a9381b5
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mc/Disassembler.cpp
@@ -0,0 +1,368 @@
+//===- Disassembler.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 "Disassembler.h"
+#include "../../lib/MC/MCDisassembler/EDDisassembler.h"
+#include "../../lib/MC/MCDisassembler/EDInst.h"
+#include "../../lib/MC/MCDisassembler/EDOperand.h"
+#include "../../lib/MC/MCDisassembler/EDToken.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
+
+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 PrintInsts(const MCDisassembler &DisAsm,
+ MCInstPrinter &Printer, const ByteArrayTy &Bytes,
+ SourceMgr &SM, raw_ostream &Out) {
+ // Wrap the vector in a MemoryObject.
+ VectorMemoryObject memoryObject(Bytes);
+
+ // Disassemble it to strings.
+ uint64_t Size;
+ uint64_t Index;
+
+ for (Index = 0; Index < Bytes.size(); Index += Size) {
+ MCInst Inst;
+
+ MCDisassembler::DecodeStatus S;
+ S = DisAsm.getInstruction(Inst, Size, memoryObject, Index,
+ /*REMOVE*/ nulls(), nulls());
+ switch (S) {
+ case MCDisassembler::Fail:
+ SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
+ "invalid instruction encoding", "warning");
+ if (Size == 0)
+ Size = 1; // skip illegible bytes
+ break;
+
+ case MCDisassembler::SoftFail:
+ SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
+ "potentially undefined instruction encoding", "warning");
+ // Fall through
+
+ case MCDisassembler::Success:
+ Printer.printInst(&Inst, Out, "");
+ Out << "\n";
+ break;
+ }
+ }
+
+ return false;
+}
+
+static bool ByteArrayFromString(ByteArrayTy &ByteArray,
+ StringRef &Str,
+ SourceMgr &SM) {
+ 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, remove the rest of
+ // the line.
+ if (Str[0] == '\n' || Str[0] == '#') {
+ // 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");
+ Str = Str.substr(Str.find('\n'));
+ ByteArray.clear();
+ continue;
+ }
+
+ ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data()));
+ Str = Str.substr(Next);
+ }
+
+ return false;
+}
+
+int Disassembler::disassemble(const Target &T,
+ const std::string &Triple,
+ const std::string &Cpu,
+ const std::string &FeaturesStr,
+ MemoryBuffer &Buffer,
+ raw_ostream &Out) {
+ // Set up disassembler.
+ OwningPtr<const MCAsmInfo> AsmInfo(T.createMCAsmInfo(Triple));
+
+ if (!AsmInfo) {
+ errs() << "error: no assembly info for target " << Triple << "\n";
+ return -1;
+ }
+
+ OwningPtr<const MCSubtargetInfo> STI(T.createMCSubtargetInfo(Triple, Cpu, FeaturesStr));
+ if (!STI) {
+ errs() << "error: no subtarget info for target " << Triple << "\n";
+ return -1;
+ }
+
+ OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(*STI));
+ if (!DisAsm) {
+ errs() << "error: no disassembler for target " << Triple << "\n";
+ return -1;
+ }
+
+ int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
+ OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant,
+ *AsmInfo, *STI));
+ if (!IP) {
+ 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();
+
+ ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
+
+ if (!ByteArray.empty())
+ ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM, Out);
+
+ return ErrorOccurred;
+}
+
+static int byteArrayReader(uint8_t *B, uint64_t A, void *Arg) {
+ ByteArrayTy &ByteArray = *((ByteArrayTy*)Arg);
+
+ if (A >= ByteArray.size())
+ return -1;
+
+ *B = ByteArray[A].first;
+
+ return 0;
+}
+
+static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) {
+ EDDisassembler &disassembler = *(EDDisassembler *)((void **)Arg)[0];
+ raw_ostream &Out = *(raw_ostream *)((void **)Arg)[1];
+
+ if (const char *regName = disassembler.nameWithRegisterID(R))
+ Out << "[" << regName << "/" << R << "]";
+
+ if (disassembler.registerIsStackPointer(R))
+ Out << "(sp)";
+ if (disassembler.registerIsProgramCounter(R))
+ Out << "(pc)";
+
+ *V = 0;
+ return 0;
+}
+
+int Disassembler::disassembleEnhanced(const std::string &TS,
+ MemoryBuffer &Buffer,
+ raw_ostream &Out) {
+ ByteArrayTy ByteArray;
+ StringRef Str = Buffer.getBuffer();
+ SourceMgr SM;
+
+ SM.AddNewSourceBuffer(&Buffer, SMLoc());
+
+ if (ByteArrayFromString(ByteArray, Str, SM)) {
+ return -1;
+ }
+
+ Triple T(TS);
+ EDDisassembler::AssemblySyntax AS;
+
+ switch (T.getArch()) {
+ default:
+ errs() << "error: no default assembly syntax for " << TS.c_str() << "\n";
+ return -1;
+ case Triple::arm:
+ case Triple::thumb:
+ AS = EDDisassembler::kEDAssemblySyntaxARMUAL;
+ break;
+ case Triple::x86:
+ case Triple::x86_64:
+ AS = EDDisassembler::kEDAssemblySyntaxX86ATT;
+ break;
+ }
+
+ EDDisassembler::initialize();
+ OwningPtr<EDDisassembler>
+ disassembler(EDDisassembler::getDisassembler(TS.c_str(), AS));
+
+ if (disassembler == 0) {
+ errs() << "error: couldn't get disassembler for " << TS << '\n';
+ return -1;
+ }
+
+ while (ByteArray.size()) {
+ OwningPtr<EDInst>
+ inst(disassembler->createInst(byteArrayReader, 0, &ByteArray));
+
+ if (inst == 0) {
+ errs() << "error: Didn't get an instruction\n";
+ return -1;
+ }
+
+ ByteArray.erase (ByteArray.begin(), ByteArray.begin() + inst->byteSize());
+
+ unsigned numTokens = inst->numTokens();
+ if ((int)numTokens < 0) {
+ errs() << "error: couldn't count the instruction's tokens\n";
+ return -1;
+ }
+
+ for (unsigned tokenIndex = 0; tokenIndex != numTokens; ++tokenIndex) {
+ EDToken *token;
+
+ if (inst->getToken(token, tokenIndex)) {
+ errs() << "error: Couldn't get token\n";
+ return -1;
+ }
+
+ const char *buf;
+ if (token->getString(buf)) {
+ errs() << "error: Couldn't get string for token\n";
+ return -1;
+ }
+
+ Out << '[';
+ int operandIndex = token->operandID();
+
+ if (operandIndex >= 0)
+ Out << operandIndex << "-";
+
+ switch (token->type()) {
+ default: Out << "?"; break;
+ case EDToken::kTokenWhitespace: Out << "w"; break;
+ case EDToken::kTokenPunctuation: Out << "p"; break;
+ case EDToken::kTokenOpcode: Out << "o"; break;
+ case EDToken::kTokenLiteral: Out << "l"; break;
+ case EDToken::kTokenRegister: Out << "r"; break;
+ }
+
+ Out << ":" << buf;
+
+ if (token->type() == EDToken::kTokenLiteral) {
+ Out << "=";
+ if (token->literalSign())
+ Out << "-";
+ uint64_t absoluteValue;
+ if (token->literalAbsoluteValue(absoluteValue)) {
+ errs() << "error: Couldn't get the value of a literal token\n";
+ return -1;
+ }
+ Out << absoluteValue;
+ } else if (token->type() == EDToken::kTokenRegister) {
+ Out << "=";
+ unsigned regID;
+ if (token->registerID(regID)) {
+ errs() << "error: Couldn't get the ID of a register token\n";
+ return -1;
+ }
+ Out << "r" << regID;
+ }
+
+ Out << "]";
+ }
+
+ Out << " ";
+
+ if (inst->isBranch())
+ Out << "<br> ";
+ if (inst->isMove())
+ Out << "<mov> ";
+
+ unsigned numOperands = inst->numOperands();
+
+ if ((int)numOperands < 0) {
+ errs() << "error: Couldn't count operands\n";
+ return -1;
+ }
+
+ for (unsigned operandIndex = 0; operandIndex != numOperands;
+ ++operandIndex) {
+ Out << operandIndex << ":";
+
+ EDOperand *operand;
+ if (inst->getOperand(operand, operandIndex)) {
+ errs() << "error: couldn't get operand\n";
+ return -1;
+ }
+
+ uint64_t evaluatedResult;
+ void *Arg[] = { disassembler.get(), &Out };
+ if (operand->evaluate(evaluatedResult, verboseEvaluator, Arg)) {
+ errs() << "error: Couldn't evaluate an operand\n";
+ return -1;
+ }
+ Out << "=" << evaluatedResult << " ";
+ }
+
+ Out << '\n';
+ }
+
+ return 0;
+}
+
diff --git a/contrib/llvm/tools/llvm-mc/Disassembler.h b/contrib/llvm/tools/llvm-mc/Disassembler.h
new file mode 100644
index 0000000..e8cd92d
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mc/Disassembler.h
@@ -0,0 +1,42 @@
+//===- Disassembler.h - Text File Disassembler ----------------------------===//
+//
+// 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 DISASSEMBLER_H
+#define DISASSEMBLER_H
+
+#include <string>
+
+namespace llvm {
+
+class MemoryBuffer;
+class Target;
+class raw_ostream;
+
+class Disassembler {
+public:
+ static int disassemble(const Target &target,
+ const std::string &tripleString,
+ const std::string &Cpu,
+ const std::string &FeaturesStr,
+ MemoryBuffer &buffer,
+ raw_ostream &Out);
+
+ static int disassembleEnhanced(const std::string &tripleString,
+ MemoryBuffer &buffer,
+ raw_ostream &Out);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/llvm-mc/Makefile b/contrib/llvm/tools/llvm-mc/Makefile
new file mode 100644
index 0000000..934a6e4
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mc/Makefile
@@ -0,0 +1,24 @@
+##===- tools/llvm-mc/Makefile ------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = llvm-mc
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+# Include this here so we can get the configuration of the targets
+# that have been configured for construction. We have to do this
+# early so we can set up LINK_COMPONENTS before including Makefile.rules
+include $(LEVEL)/Makefile.config
+
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) MCDisassembler MCParser MC support
+
+include $(LLVM_SRC_ROOT)/Makefile.rules
+
diff --git a/contrib/llvm/tools/llvm-mc/llvm-mc.cpp b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
new file mode 100644
index 0000000..5fb3fdf
--- /dev/null
+++ b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -0,0 +1,517 @@
+//===-- llvm-mc.cpp - Machine Code Hacking Driver -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility is a simple driver that allows command line hacking on machine
+// code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/AsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/system_error.h"
+#include "Disassembler.h"
+using namespace llvm;
+
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Output filename"),
+ cl::value_desc("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<bool>
+ShowInstOperands("show-inst-operands",
+ cl::desc("Show instructions operands as parsed"));
+
+static cl::opt<unsigned>
+OutputAsmVariant("output-asm-variant",
+ cl::desc("Syntax variant to use for output printing"));
+
+static cl::opt<bool>
+RelaxAll("mc-relax-all", cl::desc("Relax all fixups"));
+
+static cl::opt<bool>
+NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack"));
+
+static cl::opt<bool>
+EnableLogging("enable-api-logging", cl::desc("Enable MC API logging"));
+
+enum OutputFileType {
+ OFT_Null,
+ OFT_AssemblyFile,
+ OFT_ObjectFile
+};
+static cl::opt<OutputFileType>
+FileType("filetype", cl::init(OFT_AssemblyFile),
+ cl::desc("Choose an output file type:"),
+ cl::values(
+ clEnumValN(OFT_AssemblyFile, "asm",
+ "Emit an assembly ('.s') file"),
+ clEnumValN(OFT_Null, "null",
+ "Don't emit anything (for timing purposes)"),
+ clEnumValN(OFT_ObjectFile, "obj",
+ "Emit a native object ('.o') file"),
+ clEnumValEnd));
+
+static cl::list<std::string>
+IncludeDirs("I", cl::desc("Directory of include files"),
+ cl::value_desc("directory"), cl::Prefix);
+
+static cl::opt<std::string>
+ArchName("arch", cl::desc("Target arch to assemble for, "
+ "see -version for available targets"));
+
+static cl::opt<std::string>
+TripleName("triple", cl::desc("Target triple to assemble for, "
+ "see -version for available targets"));
+
+static cl::opt<std::string>
+MCPU("mcpu",
+ cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+ cl::value_desc("cpu-name"),
+ cl::init(""));
+
+static cl::list<std::string>
+MAttrs("mattr",
+ cl::CommaSeparated,
+ cl::desc("Target specific attributes (-mattr=help for details)"),
+ cl::value_desc("a1,+a2,-a3,..."));
+
+static cl::opt<Reloc::Model>
+RelocModel("relocation-model",
+ cl::desc("Choose relocation model"),
+ cl::init(Reloc::Default),
+ cl::values(
+ clEnumValN(Reloc::Default, "default",
+ "Target default relocation model"),
+ clEnumValN(Reloc::Static, "static",
+ "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+static cl::opt<llvm::CodeModel::Model>
+CMModel("code-model",
+ cl::desc("Choose code model"),
+ cl::init(CodeModel::Default),
+ cl::values(clEnumValN(CodeModel::Default, "default",
+ "Target default code model"),
+ clEnumValN(CodeModel::Small, "small",
+ "Small code model"),
+ clEnumValN(CodeModel::Kernel, "kernel",
+ "Kernel code model"),
+ clEnumValN(CodeModel::Medium, "medium",
+ "Medium code model"),
+ clEnumValN(CodeModel::Large, "large",
+ "Large code model"),
+ clEnumValEnd));
+
+static cl::opt<bool>
+NoInitialTextSection("n", cl::desc("Don't assume assembly file starts "
+ "in the text section"));
+
+static cl::opt<bool>
+SaveTempLabels("L", cl::desc("Don't discard temporary labels"));
+
+enum ActionType {
+ AC_AsLex,
+ AC_Assemble,
+ AC_Disassemble,
+ AC_EDisassemble
+};
+
+static cl::opt<ActionType>
+Action(cl::desc("Action to perform:"),
+ cl::init(AC_Assemble),
+ cl::values(clEnumValN(AC_AsLex, "as-lex",
+ "Lex tokens from a .s file"),
+ clEnumValN(AC_Assemble, "assemble",
+ "Assemble a .s file (default)"),
+ clEnumValN(AC_Disassemble, "disassemble",
+ "Disassemble strings of hex bytes"),
+ clEnumValN(AC_EDisassemble, "edis",
+ "Enhanced disassembly of strings of hex bytes"),
+ clEnumValEnd));
+
+static const Target *GetTarget(const char *ProgName) {
+ // Figure out the target triple.
+ if (TripleName.empty())
+ TripleName = sys::getHostTriple();
+ Triple TheTriple(Triple::normalize(TripleName));
+
+ const Target *TheTarget = 0;
+ if (!ArchName.empty()) {
+ for (TargetRegistry::iterator it = TargetRegistry::begin(),
+ ie = TargetRegistry::end(); it != ie; ++it) {
+ if (ArchName == it->getName()) {
+ TheTarget = &*it;
+ break;
+ }
+ }
+
+ if (!TheTarget) {
+ errs() << ProgName << ": error: invalid target '" << ArchName << "'.\n";
+ return 0;
+ }
+
+ // Adjust the triple to match (if known), otherwise stick with the
+ // module/host triple.
+ Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
+ if (Type != Triple::UnknownArch)
+ TheTriple.setArch(Type);
+ } else {
+ // Get the target specific parser.
+ std::string Error;
+ TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
+ if (TheTarget == 0) {
+ errs() << ProgName << ": error: unable to get target for '"
+ << TheTriple.getTriple()
+ << "', see --version and --triple.\n";
+ return 0;
+ }
+ }
+
+ TripleName = TheTriple.getTriple();
+ return TheTarget;
+}
+
+static tool_output_file *GetOutputStream() {
+ if (OutputFilename == "")
+ OutputFilename = "-";
+
+ std::string Err;
+ tool_output_file *Out = new tool_output_file(OutputFilename.c_str(), Err,
+ raw_fd_ostream::F_Binary);
+ if (!Err.empty()) {
+ errs() << Err << '\n';
+ delete Out;
+ return 0;
+ }
+
+ return Out;
+}
+
+static int AsLexInput(const char *ProgName) {
+ OwningPtr<MemoryBuffer> BufferPtr;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) {
+ errs() << ProgName << ": " << ec.message() << '\n';
+ return 1;
+ }
+ MemoryBuffer *Buffer = BufferPtr.take();
+
+ SourceMgr SrcMgr;
+
+ // Tell SrcMgr about this buffer, which is what TGParser will pick up.
+ SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
+
+ // Record the location of the include directories so that the lexer can find
+ // it later.
+ SrcMgr.setIncludeDirs(IncludeDirs);
+
+ const Target *TheTarget = GetTarget(ProgName);
+ if (!TheTarget)
+ return 1;
+
+ llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName));
+ assert(MAI && "Unable to create target asm info!");
+
+ AsmLexer Lexer(*MAI);
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(0));
+
+ OwningPtr<tool_output_file> Out(GetOutputStream());
+ if (!Out)
+ return 1;
+
+ bool Error = false;
+ while (Lexer.Lex().isNot(AsmToken::Eof)) {
+ AsmToken Tok = Lexer.getTok();
+
+ switch (Tok.getKind()) {
+ default:
+ SrcMgr.PrintMessage(Lexer.getLoc(), "unknown token", "warning");
+ Error = true;
+ break;
+ case AsmToken::Error:
+ Error = true; // error already printed.
+ break;
+ case AsmToken::Identifier:
+ Out->os() << "identifier: " << Lexer.getTok().getString();
+ break;
+ case AsmToken::Integer:
+ Out->os() << "int: " << Lexer.getTok().getString();
+ break;
+ case AsmToken::Real:
+ Out->os() << "real: " << Lexer.getTok().getString();
+ break;
+ case AsmToken::Register:
+ Out->os() << "register: " << Lexer.getTok().getRegVal();
+ break;
+ case AsmToken::String:
+ Out->os() << "string: " << Lexer.getTok().getString();
+ break;
+
+ case AsmToken::Amp: Out->os() << "Amp"; break;
+ case AsmToken::AmpAmp: Out->os() << "AmpAmp"; break;
+ case AsmToken::At: Out->os() << "At"; break;
+ case AsmToken::Caret: Out->os() << "Caret"; break;
+ case AsmToken::Colon: Out->os() << "Colon"; break;
+ case AsmToken::Comma: Out->os() << "Comma"; break;
+ case AsmToken::Dollar: Out->os() << "Dollar"; break;
+ case AsmToken::Dot: Out->os() << "Dot"; break;
+ case AsmToken::EndOfStatement: Out->os() << "EndOfStatement"; break;
+ case AsmToken::Eof: Out->os() << "Eof"; break;
+ case AsmToken::Equal: Out->os() << "Equal"; break;
+ case AsmToken::EqualEqual: Out->os() << "EqualEqual"; break;
+ case AsmToken::Exclaim: Out->os() << "Exclaim"; break;
+ case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual"; break;
+ case AsmToken::Greater: Out->os() << "Greater"; break;
+ case AsmToken::GreaterEqual: Out->os() << "GreaterEqual"; break;
+ case AsmToken::GreaterGreater: Out->os() << "GreaterGreater"; break;
+ case AsmToken::Hash: Out->os() << "Hash"; break;
+ case AsmToken::LBrac: Out->os() << "LBrac"; break;
+ case AsmToken::LCurly: Out->os() << "LCurly"; break;
+ case AsmToken::LParen: Out->os() << "LParen"; break;
+ case AsmToken::Less: Out->os() << "Less"; break;
+ case AsmToken::LessEqual: Out->os() << "LessEqual"; break;
+ case AsmToken::LessGreater: Out->os() << "LessGreater"; break;
+ case AsmToken::LessLess: Out->os() << "LessLess"; break;
+ case AsmToken::Minus: Out->os() << "Minus"; break;
+ case AsmToken::Percent: Out->os() << "Percent"; break;
+ case AsmToken::Pipe: Out->os() << "Pipe"; break;
+ case AsmToken::PipePipe: Out->os() << "PipePipe"; break;
+ case AsmToken::Plus: Out->os() << "Plus"; break;
+ case AsmToken::RBrac: Out->os() << "RBrac"; break;
+ case AsmToken::RCurly: Out->os() << "RCurly"; break;
+ case AsmToken::RParen: Out->os() << "RParen"; break;
+ case AsmToken::Slash: Out->os() << "Slash"; break;
+ case AsmToken::Star: Out->os() << "Star"; break;
+ case AsmToken::Tilde: Out->os() << "Tilde"; break;
+ }
+
+ // Print the token string.
+ Out->os() << " (\"";
+ Out->os().write_escaped(Tok.getString());
+ Out->os() << "\")\n";
+ }
+
+ // Keep output if no errors.
+ if (Error == 0) Out->keep();
+
+ return Error;
+}
+
+static int AssembleInput(const char *ProgName) {
+ const Target *TheTarget = GetTarget(ProgName);
+ if (!TheTarget)
+ return 1;
+
+ OwningPtr<MemoryBuffer> BufferPtr;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) {
+ errs() << ProgName << ": " << ec.message() << '\n';
+ return 1;
+ }
+ MemoryBuffer *Buffer = BufferPtr.take();
+
+ SourceMgr SrcMgr;
+
+ // Tell SrcMgr about this buffer, which is what the parser will pick up.
+ SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
+
+ // Record the location of the include directories so that the lexer can find
+ // it later.
+ SrcMgr.setIncludeDirs(IncludeDirs);
+
+
+ llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName));
+ assert(MAI && "Unable to create target asm info!");
+
+ llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ assert(MRI && "Unable to create target register info!");
+
+ // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
+ // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
+ OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
+ MCContext Ctx(*MAI, *MRI, MOFI.get());
+ MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx);
+
+ if (SaveTempLabels)
+ Ctx.setAllowTemporaryLabels(false);
+
+ // Package up features to be passed to target/subtarget
+ std::string FeaturesStr;
+ if (MAttrs.size()) {
+ SubtargetFeatures Features;
+ for (unsigned i = 0; i != MAttrs.size(); ++i)
+ Features.AddFeature(MAttrs[i]);
+ FeaturesStr = Features.getString();
+ }
+
+ OwningPtr<tool_output_file> Out(GetOutputStream());
+ if (!Out)
+ return 1;
+
+ formatted_raw_ostream FOS(Out->os());
+ OwningPtr<MCStreamer> Str;
+
+ OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
+ OwningPtr<MCSubtargetInfo>
+ STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
+
+ // FIXME: There is a bit of code duplication with addPassesToEmitFile.
+ if (FileType == OFT_AssemblyFile) {
+ MCInstPrinter *IP =
+ TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *STI);
+ MCCodeEmitter *CE = 0;
+ MCAsmBackend *MAB = 0;
+ if (ShowEncoding) {
+ CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx);
+ MAB = TheTarget->createMCAsmBackend(TripleName);
+ }
+ Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true,
+ /*useLoc*/ true,
+ /*useCFI*/ true, IP, CE, MAB,
+ ShowInst));
+ } else if (FileType == OFT_Null) {
+ Str.reset(createNullStreamer(Ctx));
+ } else {
+ assert(FileType == OFT_ObjectFile && "Invalid file type!");
+ MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx);
+ MCAsmBackend *MAB = TheTarget->createMCAsmBackend(TripleName);
+ Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB,
+ FOS, CE, RelaxAll,
+ NoExecStack));
+ }
+
+ if (EnableLogging) {
+ Str.reset(createLoggingStreamer(Str.take(), errs()));
+ }
+
+ OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx,
+ *Str.get(), *MAI));
+ OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser));
+ if (!TAP) {
+ errs() << ProgName
+ << ": error: this target does not support assembly parsing.\n";
+ return 1;
+ }
+
+ Parser->setShowParsedOperands(ShowInstOperands);
+ Parser->setTargetParser(*TAP.get());
+
+ int Res = Parser->Run(NoInitialTextSection);
+
+ // Keep output if no errors.
+ if (Res == 0) Out->keep();
+
+ return Res;
+}
+
+static int DisassembleInput(const char *ProgName, bool Enhanced) {
+ const Target *TheTarget = GetTarget(ProgName);
+ if (!TheTarget)
+ return 0;
+
+ OwningPtr<MemoryBuffer> Buffer;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, Buffer)) {
+ errs() << ProgName << ": " << ec.message() << '\n';
+ return 1;
+ }
+
+ OwningPtr<tool_output_file> Out(GetOutputStream());
+ if (!Out)
+ return 1;
+
+ int Res;
+ if (Enhanced) {
+ Res =
+ Disassembler::disassembleEnhanced(TripleName, *Buffer.take(), Out->os());
+ } else {
+ // Package up features to be passed to target/subtarget
+ std::string FeaturesStr;
+ if (MAttrs.size()) {
+ SubtargetFeatures Features;
+ for (unsigned i = 0; i != MAttrs.size(); ++i)
+ Features.AddFeature(MAttrs[i]);
+ FeaturesStr = Features.getString();
+ }
+
+ Res = Disassembler::disassemble(*TheTarget, TripleName, MCPU, FeaturesStr,
+ *Buffer.take(), Out->os());
+ }
+
+ // Keep output if no errors.
+ if (Res == 0) Out->keep();
+
+ return Res;
+}
+
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ // Initialize targets and assembly printers/parsers.
+ llvm::InitializeAllTargetInfos();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllAsmParsers();
+ llvm::InitializeAllDisassemblers();
+
+ cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
+ TripleName = Triple::normalize(TripleName);
+
+ switch (Action) {
+ default:
+ case AC_AsLex:
+ return AsLexInput(argv[0]);
+ case AC_Assemble:
+ return AssembleInput(argv[0]);
+ case AC_Disassemble:
+ return DisassembleInput(argv[0], false);
+ case AC_EDisassemble:
+ return DisassembleInput(argv[0], true);
+ }
+
+ return 0;
+}
+
OpenPOWER on IntegriCloud