1//===-EDInst.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 Disassembly library's instruction class.
11// The instruction is responsible for vending the string representation,
12// individual tokens, and operands for a single instruction.
13//
14//===----------------------------------------------------------------------===//
15
16#include "EDInst.h"
17#include "EDDisassembler.h"
18#include "EDOperand.h"
19#include "EDToken.h"
20
21#include "llvm/MC/EDInstInfo.h"
22#include "llvm/MC/MCInst.h"
23
24using namespace llvm;
25
26EDInst::EDInst(llvm::MCInst *inst,
27               uint64_t byteSize,
28               EDDisassembler &disassembler,
29               const llvm::EDInstInfo *info) :
30  Disassembler(disassembler),
31  Inst(inst),
32  ThisInstInfo(info),
33  ByteSize(byteSize),
34  BranchTarget(-1),
35  MoveSource(-1),
36  MoveTarget(-1) {
37  OperandOrder = ThisInstInfo->operandOrders[Disassembler.llvmSyntaxVariant()];
38}
39
40EDInst::~EDInst() {
41  unsigned int index;
42  unsigned int numOperands = Operands.size();
43
44  for (index = 0; index < numOperands; ++index)
45    delete Operands[index];
46
47  unsigned int numTokens = Tokens.size();
48
49  for (index = 0; index < numTokens; ++index)
50    delete Tokens[index];
51
52  delete Inst;
53}
54
55uint64_t EDInst::byteSize() {
56  return ByteSize;
57}
58
59int EDInst::stringify() {
60  if (StringifyResult.valid())
61    return StringifyResult.result();
62
63  if (Disassembler.printInst(String, *Inst))
64    return StringifyResult.setResult(-1);
65
66  String.push_back('\n');
67
68  return StringifyResult.setResult(0);
69}
70
71int EDInst::getString(const char*& str) {
72  if (stringify())
73    return -1;
74
75  str = String.c_str();
76
77  return 0;
78}
79
80unsigned EDInst::instID() {
81  return Inst->getOpcode();
82}
83
84bool EDInst::isBranch() {
85  if (ThisInstInfo)
86    return
87      ThisInstInfo->instructionType == kInstructionTypeBranch ||
88      ThisInstInfo->instructionType == kInstructionTypeCall;
89  else
90    return false;
91}
92
93bool EDInst::isMove() {
94  if (ThisInstInfo)
95    return ThisInstInfo->instructionType == kInstructionTypeMove;
96  else
97    return false;
98}
99
100int EDInst::parseOperands() {
101  if (ParseResult.valid())
102    return ParseResult.result();
103
104  if (!ThisInstInfo)
105    return ParseResult.setResult(-1);
106
107  unsigned int opIndex;
108  unsigned int mcOpIndex = 0;
109
110  for (opIndex = 0; opIndex < ThisInstInfo->numOperands; ++opIndex) {
111    if (isBranch() &&
112        (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)) {
113      BranchTarget = opIndex;
114    }
115    else if (isMove()) {
116      if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagSource)
117        MoveSource = opIndex;
118      else if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)
119        MoveTarget = opIndex;
120    }
121
122    EDOperand *operand = new EDOperand(Disassembler, *this, opIndex, mcOpIndex);
123
124    Operands.push_back(operand);
125  }
126
127  return ParseResult.setResult(0);
128}
129
130int EDInst::branchTargetID() {
131  if (parseOperands())
132    return -1;
133  return BranchTarget;
134}
135
136int EDInst::moveSourceID() {
137  if (parseOperands())
138    return -1;
139  return MoveSource;
140}
141
142int EDInst::moveTargetID() {
143  if (parseOperands())
144    return -1;
145  return MoveTarget;
146}
147
148int EDInst::numOperands() {
149  if (parseOperands())
150    return -1;
151  return Operands.size();
152}
153
154int EDInst::getOperand(EDOperand *&operand, unsigned int index) {
155  if (parseOperands())
156    return -1;
157
158  if (index >= Operands.size())
159    return -1;
160
161  operand = Operands[index];
162  return 0;
163}
164
165int EDInst::tokenize() {
166  if (TokenizeResult.valid())
167    return TokenizeResult.result();
168
169  if (ThisInstInfo == NULL)
170    return TokenizeResult.setResult(-1);
171
172  if (stringify())
173    return TokenizeResult.setResult(-1);
174
175  return TokenizeResult.setResult(EDToken::tokenize(Tokens,
176                                                    String,
177                                                    OperandOrder,
178                                                    Disassembler));
179
180}
181
182int EDInst::numTokens() {
183  if (tokenize())
184    return -1;
185  return Tokens.size();
186}
187
188int EDInst::getToken(EDToken *&token, unsigned int index) {
189  if (tokenize())
190    return -1;
191  token = Tokens[index];
192  return 0;
193}
194
195#ifdef __BLOCKS__
196int EDInst::visitTokens(EDTokenVisitor_t visitor) {
197  if (tokenize())
198    return -1;
199
200  tokvec_t::iterator iter;
201
202  for (iter = Tokens.begin(); iter != Tokens.end(); ++iter) {
203    int ret = visitor(*iter);
204    if (ret == 1)
205      return 0;
206    if (ret != 0)
207      return -1;
208  }
209
210  return 0;
211}
212#endif
213