1320013Sdim//===- llvm/MC/MCInst.h - MCInst class --------------------------*- C++ -*-===//
2320013Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6320013Sdim//
7320013Sdim//===----------------------------------------------------------------------===//
8320013Sdim//
9320013Sdim// This file contains the declaration of the MCInst and MCOperand classes, which
10320013Sdim// is the basic representation used to represent low-level machine code
11320013Sdim// instructions.
12320013Sdim//
13320013Sdim//===----------------------------------------------------------------------===//
14320013Sdim
15320013Sdim#ifndef LLVM_MC_MCINST_H
16320013Sdim#define LLVM_MC_MCINST_H
17320013Sdim
18320013Sdim#include "llvm/ADT/SmallVector.h"
19320013Sdim#include "llvm/ADT/StringRef.h"
20320013Sdim#include "llvm/Support/SMLoc.h"
21341825Sdim#include <cassert>
22320013Sdim#include <cstddef>
23320013Sdim#include <cstdint>
24320013Sdim
25320013Sdimnamespace llvm {
26327952Sdim
27320013Sdimclass MCExpr;
28327952Sdimclass MCInst;
29341825Sdimclass MCInstPrinter;
30341825Sdimclass raw_ostream;
31341825Sdim
32341825Sdim/// Instances of this class represent operands of the MCInst class.
33341825Sdim/// This is a simple discriminated union.
34341825Sdimclass MCOperand {
35320013Sdim  enum MachineOperandType : unsigned char {
36320013Sdim    kInvalid,     ///< Uninitialized.
37320572Sdim    kRegister,    ///< Register operand.
38320013Sdim    kImmediate,   ///< Immediate operand.
39320013Sdim    kFPImmediate, ///< Floating-point immediate operand.
40341825Sdim    kExpr,        ///< Relocatable immediate operand.
41341825Sdim    kInst         ///< Sub-instruction operand.
42320013Sdim  };
43320013Sdim  MachineOperandType Kind = kInvalid;
44320013Sdim
45320013Sdim  union {
46320013Sdim    unsigned RegVal;
47320013Sdim    int64_t ImmVal;
48320013Sdim    double FPImmVal;
49327952Sdim    const MCExpr *ExprVal;
50327952Sdim    const MCInst *InstVal;
51320013Sdim  };
52327952Sdim
53320013Sdimpublic:
54320013Sdim  MCOperand() : FPImmVal(0.0) {}
55344779Sdim
56344779Sdim  bool isValid() const { return Kind != kInvalid; }
57344779Sdim  bool isReg() const { return Kind == kRegister; }
58344779Sdim  bool isImm() const { return Kind == kImmediate; }
59344779Sdim  bool isFPImm() const { return Kind == kFPImmediate; }
60327952Sdim  bool isExpr() const { return Kind == kExpr; }
61341825Sdim  bool isInst() const { return Kind == kInst; }
62327952Sdim
63320013Sdim  /// Returns the register number.
64320013Sdim  unsigned getReg() const {
65320013Sdim    assert(isReg() && "This is not a register operand!");
66320013Sdim    return RegVal;
67320013Sdim  }
68344779Sdim
69  /// Set the register number.
70  void setReg(unsigned Reg) {
71    assert(isReg() && "This is not a register operand!");
72    RegVal = Reg;
73  }
74
75  int64_t getImm() const {
76    assert(isImm() && "This is not an immediate");
77    return ImmVal;
78  }
79
80  void setImm(int64_t Val) {
81    assert(isImm() && "This is not an immediate");
82    ImmVal = Val;
83  }
84
85  double getFPImm() const {
86    assert(isFPImm() && "This is not an FP immediate");
87    return FPImmVal;
88  }
89
90  void setFPImm(double Val) {
91    assert(isFPImm() && "This is not an FP immediate");
92    FPImmVal = Val;
93  }
94
95  const MCExpr *getExpr() const {
96    assert(isExpr() && "This is not an expression");
97    return ExprVal;
98  }
99
100  void setExpr(const MCExpr *Val) {
101    assert(isExpr() && "This is not an expression");
102    ExprVal = Val;
103  }
104
105  const MCInst *getInst() const {
106    assert(isInst() && "This is not a sub-instruction");
107    return InstVal;
108  }
109
110  void setInst(const MCInst *Val) {
111    assert(isInst() && "This is not a sub-instruction");
112    InstVal = Val;
113  }
114
115  static MCOperand createReg(unsigned Reg) {
116    MCOperand Op;
117    Op.Kind = kRegister;
118    Op.RegVal = Reg;
119    return Op;
120  }
121
122  static MCOperand createImm(int64_t Val) {
123    MCOperand Op;
124    Op.Kind = kImmediate;
125    Op.ImmVal = Val;
126    return Op;
127  }
128
129  static MCOperand createFPImm(double Val) {
130    MCOperand Op;
131    Op.Kind = kFPImmediate;
132    Op.FPImmVal = Val;
133    return Op;
134  }
135
136  static MCOperand createExpr(const MCExpr *Val) {
137    MCOperand Op;
138    Op.Kind = kExpr;
139    Op.ExprVal = Val;
140    return Op;
141  }
142
143  static MCOperand createInst(const MCInst *Val) {
144    MCOperand Op;
145    Op.Kind = kInst;
146    Op.InstVal = Val;
147    return Op;
148  }
149
150  void print(raw_ostream &OS) const;
151  void dump() const;
152  bool isBareSymbolRef() const;
153  bool evaluateAsConstantImm(int64_t &Imm) const;
154};
155
156/// Instances of this class represent a single low-level machine
157/// instruction.
158class MCInst {
159  unsigned Opcode = 0;
160  // These flags could be used to pass some info from one target subcomponent
161  // to another, for example, from disassembler to asm printer. The values of
162  // the flags have any sense on target level only (e.g. prefixes on x86).
163  unsigned Flags = 0;
164
165  SMLoc Loc;
166  SmallVector<MCOperand, 8> Operands;
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  void erase(iterator First, iterator Last) { Operands.erase(First, Last); }
192  size_t size() const { return Operands.size(); }
193  iterator begin() { return Operands.begin(); }
194  const_iterator begin() const { return Operands.begin(); }
195  iterator end() { return Operands.end(); }
196  const_iterator end() const { return Operands.end(); }
197
198  iterator insert(iterator I, const MCOperand &Op) {
199    return Operands.insert(I, Op);
200  }
201
202  void print(raw_ostream &OS) const;
203  void dump() const;
204
205  /// Dump the MCInst as prettily as possible using the additional MC
206  /// structures, if given. Operators are separated by the \p Separator
207  /// string.
208  void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr,
209                   StringRef Separator = " ") const;
210  void dump_pretty(raw_ostream &OS, StringRef Name,
211                   StringRef Separator = " ") const;
212};
213
214inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) {
215  MO.print(OS);
216  return OS;
217}
218
219inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) {
220  MI.print(OS);
221  return OS;
222}
223
224} // end namespace llvm
225
226#endif // LLVM_MC_MCINST_H
227