| //===-- 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 "EDToken.h" |
| #include "EDDisassembler.h" |
| #include "llvm/MC/MCParser/MCAsmLexer.h" |
| #include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
| #include "llvm/ADT/SmallVector.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 ®isterID) const { |
| if (Type != kTokenRegister) |
| return -1; |
| registerID = RegisterID; |
| return 0; |
| } |
| |
| int EDToken::tokenize(std::vector<EDToken*> &tokens, |
| std::string &str, |
| const signed char *operandOrder, |
| EDDisassembler &disassembler) { |
| SmallVector<MCParsedAsmOperand*, 5> parsedOperands; |
| SmallVector<AsmToken, 10> asmTokens; |
| |
| if (disassembler.parseInst(parsedOperands, asmTokens, str)) |
| { |
| for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i) |
| delete parsedOperands[i]; |
| 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); |
| } |
| |
| // Free any parsed operands. |
| for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i) |
| delete parsedOperands[i]; |
| |
| return 0; |
| } |
| |
| int EDToken::getString(const char*& buf) { |
| if (PermStr.length() == 0) { |
| PermStr = Str.str(); |
| } |
| buf = PermStr.c_str(); |
| return 0; |
| } |