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