blob: cd79152e35946d092d9aaa34081bd124f47d9f87 [file] [log] [blame]
Sean Callananee5dfd42010-02-01 08:49:35 +00001//===-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
23using namespace llvm;
24
25EDToken::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
36EDToken::~EDToken() {
37}
38
39void EDToken::makeLiteral(bool sign, uint64_t absoluteValue) {
40 Type = kTokenLiteral;
41 LiteralSign = sign;
42 LiteralAbsoluteValue = absoluteValue;
43}
44
45void EDToken::makeRegister(unsigned registerID) {
46 Type = kTokenRegister;
47 RegisterID = registerID;
48}
49
50void EDToken::setOperandID(int operandID) {
51 OperandID = operandID;
52}
53
54enum EDToken::tokenType EDToken::type() const {
55 return Type;
56}
57
58uint64_t EDToken::localType() const {
59 return LocalType;
60}
61
62StringRef EDToken::string() const {
63 return Str;
64}
65
66int EDToken::operandID() const {
67 return OperandID;
68}
69
70int EDToken::literalSign() const {
71 if(Type != kTokenLiteral)
72 return -1;
73 return (LiteralSign ? 1 : 0);
74}
75
76int EDToken::literalAbsoluteValue(uint64_t &value) const {
77 if(Type != kTokenLiteral)
78 return -1;
79 value = LiteralAbsoluteValue;
80 return 0;
81}
82
83int EDToken::registerID(unsigned &registerID) const {
84 if(Type != kTokenRegister)
85 return -1;
86 registerID = RegisterID;
87 return 0;
88}
89
90int 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
Sean Callanande5dac12010-02-09 01:00:18 +000097 if(disassembler.parseInst(parsedOperands, asmTokens, str))
98 return -1;
Sean Callananee5dfd42010-02-01 08:49:35 +000099
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
Sean Callanan2d581472010-02-09 01:50:54 +0000109 const char *wsPointer = asmTokens.begin()->getLoc().getPointer();
110
Sean Callananee5dfd42010-02-01 08:49:35 +0000111 for (tokenIterator = asmTokens.begin();
112 tokenIterator != asmTokens.end();
113 ++tokenIterator) {
114 SMLoc tokenLoc = tokenIterator->getLoc();
115
Sean Callanan2d581472010-02-09 01:50:54 +0000116 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
Sean Callananee5dfd42010-02-01 08:49:35 +0000131 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()) {
Sean Callanande5dac12010-02-09 01:00:18 +0000188 /// 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]);
Sean Callananee5dfd42010-02-01 08:49:35 +0000194 }
195
196 tokens.push_back(token);
197 }
198
199 return 0;
200}
201
202int EDToken::getString(const char*& buf) {
203 if(PermStr.length() == 0) {
204 PermStr = Str.str();
205 }
206 buf = PermStr.c_str();
207 return 0;
208}