Let's get those buildbots green: #include is needed in the header, not just the imple...
[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 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 char *operandOrder,
91                       EDDisassembler &disassembler) {
92   SmallVector<MCParsedAsmOperand*, 5> parsedOperands;
93   SmallVector<AsmToken, 10> asmTokens;
94   
95   if (disassembler.parseInst(parsedOperands, asmTokens, str))
96     return -1;
97   
98   SmallVectorImpl<MCParsedAsmOperand*>::iterator operandIterator;
99   unsigned int operandIndex;
100   SmallVectorImpl<AsmToken>::iterator tokenIterator;
101   
102   operandIterator = parsedOperands.begin();
103   operandIndex = 0;
104   
105   bool readOpcode = false;
106   
107   const char *wsPointer = asmTokens.begin()->getLoc().getPointer();
108   
109   for (tokenIterator = asmTokens.begin();
110        tokenIterator != asmTokens.end();
111        ++tokenIterator) {
112     SMLoc tokenLoc = tokenIterator->getLoc();
113     
114     const char *tokenPointer = tokenLoc.getPointer();
115     
116     if (tokenPointer > wsPointer) {
117       unsigned long wsLength = tokenPointer - wsPointer;
118       
119       EDToken *whitespaceToken = new EDToken(StringRef(wsPointer, wsLength),
120                                              EDToken::kTokenWhitespace,
121                                              0,
122                                              disassembler);
123       
124       tokens.push_back(whitespaceToken);
125     }
126     
127     wsPointer = tokenPointer + tokenIterator->getString().size();
128     
129     while (operandIterator != parsedOperands.end() &&
130            tokenLoc.getPointer() > 
131            (*operandIterator)->getEndLoc().getPointer()) {
132       ++operandIterator;
133       ++operandIndex;
134     }
135     
136     EDToken *token;
137     
138     switch (tokenIterator->getKind()) {
139     case AsmToken::Identifier:
140       if (!readOpcode) {
141         token = new EDToken(tokenIterator->getString(),
142                             EDToken::kTokenOpcode,
143                             (uint64_t)tokenIterator->getKind(),
144                             disassembler);
145         readOpcode = true;
146         break;
147       }
148       // any identifier that isn't an opcode is mere punctuation; so we fall
149       // through
150     default:
151       token = new EDToken(tokenIterator->getString(),
152                           EDToken::kTokenPunctuation,
153                           (uint64_t)tokenIterator->getKind(),
154                           disassembler);
155       break;
156     case AsmToken::Integer:
157     {
158       token = new EDToken(tokenIterator->getString(),
159                           EDToken::kTokenLiteral,
160                           (uint64_t)tokenIterator->getKind(),
161                           disassembler);
162         
163       int64_t intVal = tokenIterator->getIntVal();
164       
165       if (intVal < 0)  
166         token->makeLiteral(true, -intVal);
167       else
168         token->makeLiteral(false, intVal);
169       break;
170     }
171     case AsmToken::Register:
172     {
173       token = new EDToken(tokenIterator->getString(),
174                           EDToken::kTokenLiteral,
175                           (uint64_t)tokenIterator->getKind(),
176                           disassembler);
177       
178       token->makeRegister((unsigned)tokenIterator->getRegVal());
179       break;
180     }
181     }
182     
183     if (operandIterator != parsedOperands.end() &&
184        tokenLoc.getPointer() >= 
185        (*operandIterator)->getStartLoc().getPointer()) {
186       /// operandIndex == 0 means the operand is the instruction (which the
187       /// AsmParser treats as an operand but edis does not).  We therefore skip
188       /// operandIndex == 0 and subtract 1 from all other operand indices.
189       
190       if (operandIndex > 0)
191         token->setOperandID(operandOrder[operandIndex - 1]);
192     }
193     
194     tokens.push_back(token);
195   }
196   
197   return 0;
198 }
199
200 int EDToken::getString(const char*& buf) {
201   if (PermStr.length() == 0) {
202     PermStr = Str.str();
203   }
204   buf = PermStr.c_str();
205   return 0;
206 }