From: Sean Callanan Date: Mon, 12 Apr 2010 19:43:00 +0000 (+0000) Subject: Second try at integrating the edis tester. This X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=668b15467be158a5f0e0c4a5e1ec232da021892c;p=oota-llvm.git Second try at integrating the edis tester. This time I use the LIBS variable, which is not subject to a %.a -> -l% transformation, to link llvm-mc against libEnhancedDisassembly. llvm-mc -edis works the same as llvm-mc -disassemble, but outputs tokens and operands. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101058 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/Makefile b/tools/Makefile index 8205568c2f5..c2b12e72117 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -36,6 +36,8 @@ include $(LEVEL)/Makefile.config ifeq ($(ENABLE_PIC),1) # No support for dynamic libraries on windows targets. ifneq ($(TARGET_OS), $(filter $(TARGET_OS), Cygwin MingW)) + # libEnhancedDisassembly must be built ahead of llvm-mc + # because llvm-mc links against libEnhancedDisassembly DIRS += edis # gold only builds if binutils is around. It requires "lto" to build before diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index 9fe07909284..4a63e99a6e7 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -15,6 +15,7 @@ #include "Disassembler.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" @@ -24,6 +25,9 @@ #include "llvm/Support/MemoryObject.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/SourceMgr.h" + +#include "llvm-c/EnhancedDisassembly.h" + using namespace llvm; typedef std::vector > ByteArrayTy; @@ -64,8 +68,7 @@ static bool PrintInsts(const MCDisassembler &DisAsm, /*REMOVE*/ nulls())) { Printer.printInst(&Inst, outs()); outs() << "\n"; - } - else { + } else { SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), "invalid instruction encoding", "warning"); if (Size == 0) @@ -76,37 +79,9 @@ static bool PrintInsts(const MCDisassembler &DisAsm, return false; } -int Disassembler::disassemble(const Target &T, const std::string &Triple, - MemoryBuffer &Buffer) { - // Set up disassembler. - OwningPtr AsmInfo(T.createAsmInfo(Triple)); - - if (!AsmInfo) { - errs() << "error: no assembly info for target " << Triple << "\n"; - return -1; - } - - OwningPtr DisAsm(T.createMCDisassembler()); - if (!DisAsm) { - errs() << "error: no disassembler for target " << Triple << "\n"; - return -1; - } - - OwningPtr IP(T.createMCInstPrinter(0, *AsmInfo)); - 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(); +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")) { @@ -119,9 +94,9 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, 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') + if (Str[0] == '\n') { Str = Str.substr(1); - else { + } else { Str = Str.substr(Str.find_first_of('\n')); if (!Str.empty()) Str = Str.substr(1); @@ -138,8 +113,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, 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; + "invalid input token", "error"); Str = Str.substr(Str.find('\n')); ByteArray.clear(); continue; @@ -149,8 +123,229 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple, Str = Str.substr(Next); } + return false; +} + +int Disassembler::disassemble(const Target &T, const std::string &Triple, + MemoryBuffer &Buffer) { + // Set up disassembler. + OwningPtr AsmInfo(T.createAsmInfo(Triple)); + + if (!AsmInfo) { + errs() << "error: no assembly info for target " << Triple << "\n"; + return -1; + } + + OwningPtr DisAsm(T.createMCDisassembler()); + if (!DisAsm) { + errs() << "error: no disassembler for target " << Triple << "\n"; + return -1; + } + + OwningPtr IP(T.createMCInstPrinter(0, *AsmInfo)); + 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); 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) { + EDDisassemblerRef &disassembler = *((EDDisassemblerRef*)Arg); + + const char *regName; + + if (!EDGetRegisterName(®Name, + disassembler, + R)) + outs() << "[" << regName << "/" << R << "]"; + if (EDRegisterIsStackPointer(disassembler, R)) + outs() << "(sp)"; + if (EDRegisterIsProgramCounter(disassembler, R)) + outs() << "(pc)"; + + *V = 0; + + return 0; +} + +int Disassembler::disassembleEnhanced(const std::string &TS, + MemoryBuffer &Buffer) { + ByteArrayTy ByteArray; + StringRef Str = Buffer.getBuffer(); + SourceMgr SM; + + SM.AddNewSourceBuffer(&Buffer, SMLoc()); + + if (ByteArrayFromString(ByteArray, Str, SM)) { + return -1; + } + + EDDisassemblerRef disassembler; + + Triple T(TS); + EDAssemblySyntax_t 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 = kEDAssemblySyntaxARMUAL; + break; + case Triple::x86: + case Triple::x86_64: + AS = kEDAssemblySyntaxX86ATT; + break; + } + + if (EDGetDisassembler(&disassembler, + TS.c_str(), + AS)) { + errs() << "error: couldn't get disassembler for " << TS.c_str() << "\n"; + return -1; + } + + EDInstRef inst; + + if (EDCreateInsts(&inst, 1, disassembler, byteArrayReader, 0,&ByteArray) + != 1) { + errs() << "error: Didn't get an instruction\n"; + return -1; + } + + int numTokens = EDNumTokens(inst); + + if (numTokens < 0) { + errs() << "error: Couldn't count the instruction's tokens\n"; + return -1; + } + + int tokenIndex; + + for (tokenIndex = 0; tokenIndex < numTokens; ++tokenIndex) { + EDTokenRef token; + + if (EDGetToken(&token, inst, tokenIndex)) { + errs() << "error: Couldn't get token\n"; + return -1; + } + + const char *buf; + + if (EDGetTokenString(&buf, token)) { + errs() << "error: Couldn't get string for token\n"; + return -1; + } + + outs() << "["; + + int operandIndex = EDOperandIndexForToken(token); + + if (operandIndex >= 0) + outs() << operandIndex << "-"; + + if (EDTokenIsWhitespace(token)) { + outs() << "w"; + } else if (EDTokenIsPunctuation(token)) { + outs() << "p"; + } else if (EDTokenIsOpcode(token)) { + outs() << "o"; + } else if (EDTokenIsLiteral(token)) { + outs() << "l"; + } else if (EDTokenIsRegister(token)) { + outs() << "r"; + } else { + outs() << "?"; + } + + outs() << ":" << buf; + + if (EDTokenIsLiteral(token)) { + outs() << "="; + if (EDTokenIsNegativeLiteral(token)) + outs() << "-"; + uint64_t absoluteValue; + if (EDLiteralTokenAbsoluteValue(&absoluteValue, token)) { + errs() << "error: Couldn't get the value of a literal token\n"; + return -1; + } + outs() << absoluteValue; + } else if (EDTokenIsRegister(token)) { + outs() << "="; + unsigned regID; + if (EDRegisterTokenValue(®ID, token)) { + errs() << "error: Couldn't get the ID of a register token\n"; + return -1; + } + outs() << "r" << regID; + } + + outs() << "]"; + } + + outs() << " "; + + int numOperands = EDNumOperands(inst); + + if (numOperands < 0) { + errs() << "error: Couldn't count operands\n"; + return -1; + } + + int operandIndex; + + for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + outs() << operandIndex << ":"; + + EDOperandRef operand; + + if (EDGetOperand(&operand, + inst, + operandIndex)) { + errs() << "error: Couldn't get operand\n"; + return -1; + } + + uint64_t evaluatedResult; + + EDEvaluateOperand(&evaluatedResult, + operand, + verboseEvaluator, + &disassembler); + + outs() << " "; + } + + outs() << "\n"; + + return 0; +} + diff --git a/tools/llvm-mc/Disassembler.h b/tools/llvm-mc/Disassembler.h index 78c2f854946..3da23965bdb 100644 --- a/tools/llvm-mc/Disassembler.h +++ b/tools/llvm-mc/Disassembler.h @@ -27,6 +27,9 @@ public: static int disassemble(const Target &target, const std::string &tripleString, MemoryBuffer &buffer); + + static int disassembleEnhanced(const std::string &tripleString, + MemoryBuffer &buffer); }; } // namespace llvm diff --git a/tools/llvm-mc/Makefile b/tools/llvm-mc/Makefile index 5b0fe3f5446..f92e643c332 100644 --- a/tools/llvm-mc/Makefile +++ b/tools/llvm-mc/Makefile @@ -22,3 +22,6 @@ include $(LEVEL)/Makefile.config LINK_COMPONENTS := $(TARGETS_TO_BUILD) MCParser MC support include $(LLVM_SRC_ROOT)/Makefile.rules + +# Using LIBS instead of USEDLIBS to force static linking +LIBS += $(LLVMLibDir)/libEnhancedDisassembly.a diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index c6657f5d3e7..47f67c5e1bb 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -97,7 +97,8 @@ NoInitialTextSection("n", cl::desc( enum ActionType { AC_AsLex, AC_Assemble, - AC_Disassemble + AC_Disassemble, + AC_EDisassemble }; static cl::opt @@ -109,6 +110,8 @@ Action(cl::desc("Action to perform:"), "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) { @@ -325,7 +328,7 @@ static int AssembleInput(const char *ProgName) { return Res; } -static int DisassembleInput(const char *ProgName) { +static int DisassembleInput(const char *ProgName, bool Enhanced) { const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 0; @@ -344,7 +347,10 @@ static int DisassembleInput(const char *ProgName) { return 1; } - return Disassembler::disassemble(*TheTarget, TripleName, *Buffer); + if (Enhanced) + return Disassembler::disassembleEnhanced(TripleName, *Buffer); + else + return Disassembler::disassemble(*TheTarget, TripleName, *Buffer); } @@ -371,7 +377,9 @@ int main(int argc, char **argv) { case AC_Assemble: return AssembleInput(argv[0]); case AC_Disassemble: - return DisassembleInput(argv[0]); + return DisassembleInput(argv[0], false); + case AC_EDisassemble: + return DisassembleInput(argv[0], true); } return 0;