• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EDToken(StringRef str,enum tokenType type,uint64_t localType,EDDisassembler & disassembler)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 
~EDToken()34 EDToken::~EDToken() {
35 }
36 
makeLiteral(bool sign,uint64_t absoluteValue)37 void EDToken::makeLiteral(bool sign, uint64_t absoluteValue) {
38   Type = kTokenLiteral;
39   LiteralSign = sign;
40   LiteralAbsoluteValue = absoluteValue;
41 }
42 
makeRegister(unsigned registerID)43 void EDToken::makeRegister(unsigned registerID) {
44   Type = kTokenRegister;
45   RegisterID = registerID;
46 }
47 
setOperandID(int operandID)48 void EDToken::setOperandID(int operandID) {
49   OperandID = operandID;
50 }
51 
type() const52 enum EDToken::tokenType EDToken::type() const {
53   return Type;
54 }
55 
localType() const56 uint64_t EDToken::localType() const {
57   return LocalType;
58 }
59 
string() const60 StringRef EDToken::string() const {
61   return Str;
62 }
63 
operandID() const64 int EDToken::operandID() const {
65   return OperandID;
66 }
67 
literalSign() const68 int EDToken::literalSign() const {
69   if (Type != kTokenLiteral)
70     return -1;
71   return (LiteralSign ? 1 : 0);
72 }
73 
literalAbsoluteValue(uint64_t & value) const74 int EDToken::literalAbsoluteValue(uint64_t &value) const {
75   if (Type != kTokenLiteral)
76     return -1;
77   value = LiteralAbsoluteValue;
78   return 0;
79 }
80 
registerID(unsigned & registerID) const81 int EDToken::registerID(unsigned &registerID) const {
82   if (Type != kTokenRegister)
83     return -1;
84   registerID = RegisterID;
85   return 0;
86 }
87 
tokenize(std::vector<EDToken * > & tokens,std::string & str,const signed char * operandOrder,EDDisassembler & disassembler)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 
getString(const char * & buf)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