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