1//===- llvm/MC/MCInst.h - MCInst class --------------------------*- C++ -*-===//
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 contains the declaration of the MCInst and MCOperand classes, which
11// is the basic representation used to represent low-level machine code
12// instructions.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_MC_MCINST_H
17#define LLVM_MC_MCINST_H
18
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/SMLoc.h"
22#include <cassert>
23#include <cstddef>
24#include <cstdint>
25
26namespace llvm {
27
28class MCExpr;
29class MCInst;
30class MCInstPrinter;
31class raw_ostream;
32
33/// \brief Instances of this class represent operands of the MCInst class.
34/// This is a simple discriminated union.
35class MCOperand {
36  enum MachineOperandType : unsigned char {
37    kInvalid,     ///< Uninitialized.
38    kRegister,    ///< Register operand.
39    kImmediate,   ///< Immediate operand.
40    kFPImmediate, ///< Floating-point immediate operand.
41    kExpr,        ///< Relocatable immediate operand.
42    kInst         ///< Sub-instruction operand.
43  };
44  MachineOperandType Kind = kInvalid;
45
46  union {
47    unsigned RegVal;
48    int64_t ImmVal;
49    double FPImmVal;
50    const MCExpr *ExprVal;
51    const MCInst *InstVal;
52  };
53
54public:
55  MCOperand() : FPImmVal(0.0) {}
56
57  bool isValid() const { return Kind != kInvalid; }
58  bool isReg() const { return Kind == kRegister; }
59  bool isImm() const { return Kind == kImmediate; }
60  bool isFPImm() const { return Kind == kFPImmediate; }
61  bool isExpr() const { return Kind == kExpr; }
62  bool isInst() const { return Kind == kInst; }
63
64  /// \brief Returns the register number.
65  unsigned getReg() const {
66    assert(isReg() && "This is not a register operand!");
67    return RegVal;
68  }
69
70  /// \brief Set the register number.
71  void setReg(unsigned Reg) {
72    assert(isReg() && "This is not a register operand!");
73    RegVal = Reg;
74  }
75
76  int64_t getImm() const {
77    assert(isImm() && "This is not an immediate");
78    return ImmVal;
79  }
80
81  void setImm(int64_t Val) {
82    assert(isImm() && "This is not an immediate");
83    ImmVal = Val;
84  }
85
86  double getFPImm() const {
87    assert(isFPImm() && "This is not an FP immediate");
88    return FPImmVal;
89  }
90
91  void setFPImm(double Val) {
92    assert(isFPImm() && "This is not an FP immediate");
93    FPImmVal = Val;
94  }
95
96  const MCExpr *getExpr() const {
97    assert(isExpr() && "This is not an expression");
98    return ExprVal;
99  }
100
101  void setExpr(const MCExpr *Val) {
102    assert(isExpr() && "This is not an expression");
103    ExprVal = Val;
104  }
105
106  const MCInst *getInst() const {
107    assert(isInst() && "This is not a sub-instruction");
108    return InstVal;
109  }
110
111  void setInst(const MCInst *Val) {
112    assert(isInst() && "This is not a sub-instruction");
113    InstVal = Val;
114  }
115
116  static MCOperand createReg(unsigned Reg) {
117    MCOperand Op;
118    Op.Kind = kRegister;
119    Op.RegVal = Reg;
120    return Op;
121  }
122
123  static MCOperand createImm(int64_t Val) {
124    MCOperand Op;
125    Op.Kind = kImmediate;
126    Op.ImmVal = Val;
127    return Op;
128  }
129
130  static MCOperand createFPImm(double Val) {
131    MCOperand Op;
132    Op.Kind = kFPImmediate;
133    Op.FPImmVal = Val;
134    return Op;
135  }
136
137  static MCOperand createExpr(const MCExpr *Val) {
138    MCOperand Op;
139    Op.Kind = kExpr;
140    Op.ExprVal = Val;
141    return Op;
142  }
143
144  static MCOperand createInst(const MCInst *Val) {
145    MCOperand Op;
146    Op.Kind = kInst;
147    Op.InstVal = Val;
148    return Op;
149  }
150
151  void print(raw_ostream &OS) const;
152  void dump() const;
153};
154
155template <> struct isPodLike<MCOperand> { static const bool value = true; };
156
157/// \brief Instances of this class represent a single low-level machine
158/// instruction.
159class MCInst {
160  unsigned Opcode = 0;
161  SMLoc Loc;
162  SmallVector<MCOperand, 8> Operands;
163  // These flags could be used to pass some info from one target subcomponent
164  // to another, for example, from disassembler to asm printer. The values of
165  // the flags have any sense on target level only (e.g. prefixes on x86).
166  unsigned Flags = 0;
167
168public:
169  MCInst() = default;
170
171  void setOpcode(unsigned Op) { Opcode = Op; }
172  unsigned getOpcode() const { return Opcode; }
173
174  void setFlags(unsigned F) { Flags = F; }
175  unsigned getFlags() const { return Flags; }
176
177  void setLoc(SMLoc loc) { Loc = loc; }
178  SMLoc getLoc() const { return Loc; }
179
180  const MCOperand &getOperand(unsigned i) const { return Operands[i]; }
181  MCOperand &getOperand(unsigned i) { return Operands[i]; }
182  unsigned getNumOperands() const { return Operands.size(); }
183
184  void addOperand(const MCOperand &Op) { Operands.push_back(Op); }
185
186  using iterator = SmallVectorImpl<MCOperand>::iterator;
187  using const_iterator = SmallVectorImpl<MCOperand>::const_iterator;
188
189  void clear() { Operands.clear(); }
190  void erase(iterator I) { Operands.erase(I); }
191  size_t size() const { return Operands.size(); }
192  iterator begin() { return Operands.begin(); }
193  const_iterator begin() const { return Operands.begin(); }
194  iterator end() { return Operands.end(); }
195  const_iterator end() const { return Operands.end(); }
196
197  iterator insert(iterator I, const MCOperand &Op) {
198    return Operands.insert(I, Op);
199  }
200
201  void print(raw_ostream &OS) const;
202  void dump() const;
203
204  /// \brief Dump the MCInst as prettily as possible using the additional MC
205  /// structures, if given. Operators are separated by the \p Separator
206  /// string.
207  void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr,
208                   StringRef Separator = " ") const;
209};
210
211inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) {
212  MO.print(OS);
213  return OS;
214}
215
216inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) {
217  MI.print(OS);
218  return OS;
219}
220
221} // end namespace llvm
222
223#endif // LLVM_MC_MCINST_H
224