215 lines
5.9 KiB
C++
215 lines
5.9 KiB
C++
//===-- 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;
|
|
}
|