Home | History | Annotate | Download | only in MCDisassembler
      1 //===-- EDToken.cpp - LLVM Enhanced Disassembler --------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements the Enhanced Disassembler library's token class.  The
     11 // token is responsible for vending information about the token, such as its
     12 // type and logical value.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "EDToken.h"
     17 #include "EDDisassembler.h"
     18 #include "llvm/MC/MCParser/MCAsmLexer.h"
     19 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
     20 #include "llvm/ADT/SmallVector.h"
     21 using namespace llvm;
     22 
     23 EDToken::EDToken(StringRef str,
     24                  enum tokenType type,
     25                  uint64_t localType,
     26                  EDDisassembler &disassembler) :
     27   Disassembler(disassembler),
     28   Str(str),
     29   Type(type),
     30   LocalType(localType),
     31   OperandID(-1) {
     32 }
     33 
     34 EDToken::~EDToken() {
     35 }
     36 
     37 void EDToken::makeLiteral(bool sign, uint64_t absoluteValue) {
     38   Type = kTokenLiteral;
     39   LiteralSign = sign;
     40   LiteralAbsoluteValue = absoluteValue;
     41 }
     42 
     43 void EDToken::makeRegister(unsigned registerID) {
     44   Type = kTokenRegister;
     45   RegisterID = registerID;
     46 }
     47 
     48 void EDToken::setOperandID(int operandID) {
     49   OperandID = operandID;
     50 }
     51 
     52 enum EDToken::tokenType EDToken::type() const {
     53   return Type;
     54 }
     55 
     56 uint64_t EDToken::localType() const {
     57   return LocalType;
     58 }
     59 
     60 StringRef EDToken::string() const {
     61   return Str;
     62 }
     63 
     64 int EDToken::operandID() const {
     65   return OperandID;
     66 }
     67 
     68 int EDToken::literalSign() const {
     69   if (Type != kTokenLiteral)
     70     return -1;
     71   return (LiteralSign ? 1 : 0);
     72 }
     73 
     74 int EDToken::literalAbsoluteValue(uint64_t &value) const {
     75   if (Type != kTokenLiteral)
     76     return -1;
     77   value = LiteralAbsoluteValue;
     78   return 0;
     79 }
     80 
     81 int EDToken::registerID(unsigned &registerID) const {
     82   if (Type != kTokenRegister)
     83     return -1;
     84   registerID = RegisterID;
     85   return 0;
     86 }
     87 
     88 int EDToken::tokenize(std::vector<EDToken*> &tokens,
     89                       std::string &str,
     90                       const signed char *operandOrder,
     91                       EDDisassembler &disassembler) {
     92   SmallVector<MCParsedAsmOperand*, 5> parsedOperands;
     93   SmallVector<AsmToken, 10> asmTokens;
     94 
     95   if (disassembler.parseInst(parsedOperands, asmTokens, str))
     96   {
     97     for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i)
     98       delete parsedOperands[i];
     99     return -1;
    100   }
    101 
    102   SmallVectorImpl<MCParsedAsmOperand*>::iterator operandIterator;
    103   unsigned int operandIndex;
    104   SmallVectorImpl<AsmToken>::iterator tokenIterator;
    105 
    106   operandIterator = parsedOperands.begin();
    107   operandIndex = 0;
    108 
    109   bool readOpcode = false;
    110 
    111   const char *wsPointer = asmTokens.begin()->getLoc().getPointer();
    112 
    113   for (tokenIterator = asmTokens.begin();
    114        tokenIterator != asmTokens.end();
    115        ++tokenIterator) {
    116     SMLoc tokenLoc = tokenIterator->getLoc();
    117 
    118     const char *tokenPointer = tokenLoc.getPointer();
    119 
    120     if (tokenPointer > wsPointer) {
    121       unsigned long wsLength = tokenPointer - wsPointer;
    122 
    123       EDToken *whitespaceToken = new EDToken(StringRef(wsPointer, wsLength),
    124                                              EDToken::kTokenWhitespace,
    125                                              0,
    126                                              disassembler);
    127 
    128       tokens.push_back(whitespaceToken);
    129     }
    130 
    131     wsPointer = tokenPointer + tokenIterator->getString().size();
    132 
    133     while (operandIterator != parsedOperands.end() &&
    134            tokenLoc.getPointer() >
    135            (*operandIterator)->getEndLoc().getPointer()) {
    136       ++operandIterator;
    137       ++operandIndex;
    138     }
    139 
    140     EDToken *token;
    141 
    142     switch (tokenIterator->getKind()) {
    143     case AsmToken::Identifier:
    144       if (!readOpcode) {
    145         token = new EDToken(tokenIterator->getString(),
    146                             EDToken::kTokenOpcode,
    147                             (uint64_t)tokenIterator->getKind(),
    148                             disassembler);
    149         readOpcode = true;
    150         break;
    151       }
    152       // any identifier that isn't an opcode is mere punctuation; so we fall
    153       // through
    154     default:
    155       token = new EDToken(tokenIterator->getString(),
    156                           EDToken::kTokenPunctuation,
    157                           (uint64_t)tokenIterator->getKind(),
    158                           disassembler);
    159       break;
    160     case AsmToken::Integer:
    161     {
    162       token = new EDToken(tokenIterator->getString(),
    163                           EDToken::kTokenLiteral,
    164                           (uint64_t)tokenIterator->getKind(),
    165                           disassembler);
    166 
    167       int64_t intVal = tokenIterator->getIntVal();
    168 
    169       if (intVal < 0)
    170         token->makeLiteral(true, -intVal);
    171       else
    172         token->makeLiteral(false, intVal);
    173       break;
    174     }
    175     case AsmToken::Register:
    176     {
    177       token = new EDToken(tokenIterator->getString(),
    178                           EDToken::kTokenLiteral,
    179                           (uint64_t)tokenIterator->getKind(),
    180                           disassembler);
    181 
    182       token->makeRegister((unsigned)tokenIterator->getRegVal());
    183       break;
    184     }
    185     }
    186 
    187     if (operandIterator != parsedOperands.end() &&
    188        tokenLoc.getPointer() >=
    189        (*operandIterator)->getStartLoc().getPointer()) {
    190       /// operandIndex == 0 means the operand is the instruction (which the
    191       /// AsmParser treats as an operand but edis does not).  We therefore skip
    192       /// operandIndex == 0 and subtract 1 from all other operand indices.
    193 
    194       if (operandIndex > 0)
    195         token->setOperandID(operandOrder[operandIndex - 1]);
    196     }
    197 
    198     tokens.push_back(token);
    199   }
    200 
    201   // Free any parsed operands.
    202   for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i)
    203     delete parsedOperands[i];
    204 
    205   return 0;
    206 }
    207 
    208 int EDToken::getString(const char*& buf) {
    209   if (PermStr.length() == 0) {
    210     PermStr = Str.str();
    211   }
    212   buf = PermStr.c_str();
    213   return 0;
    214 }
    215