blob: 2ce2ee063daa7a8603ccbf8b20b9f03609b4d0d1 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/MC/MCInst.h - MCInst class --------------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the declaration of the MCInst and MCOperand classes, which
10// is the basic representation used to represent low-level machine code
11// instructions.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_MC_MCINST_H
16#define LLVM_MC_MCINST_H
17
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/Support/SMLoc.h"
21#include <cassert>
22#include <cstddef>
23#include <cstdint>
24
25namespace llvm {
26
27class MCExpr;
28class MCInst;
29class MCInstPrinter;
30class raw_ostream;
31
Andrew Scullcdfcccc2018-10-05 20:58:37 +010032/// Instances of this class represent operands of the MCInst class.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010033/// This is a simple discriminated union.
34class MCOperand {
35 enum MachineOperandType : unsigned char {
36 kInvalid, ///< Uninitialized.
37 kRegister, ///< Register operand.
38 kImmediate, ///< Immediate operand.
39 kFPImmediate, ///< Floating-point immediate operand.
40 kExpr, ///< Relocatable immediate operand.
41 kInst ///< Sub-instruction operand.
42 };
43 MachineOperandType Kind = kInvalid;
44
45 union {
46 unsigned RegVal;
47 int64_t ImmVal;
48 double FPImmVal;
49 const MCExpr *ExprVal;
50 const MCInst *InstVal;
51 };
52
53public:
54 MCOperand() : FPImmVal(0.0) {}
55
56 bool isValid() const { return Kind != kInvalid; }
57 bool isReg() const { return Kind == kRegister; }
58 bool isImm() const { return Kind == kImmediate; }
59 bool isFPImm() const { return Kind == kFPImmediate; }
60 bool isExpr() const { return Kind == kExpr; }
61 bool isInst() const { return Kind == kInst; }
62
Andrew Scullcdfcccc2018-10-05 20:58:37 +010063 /// Returns the register number.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010064 unsigned getReg() const {
65 assert(isReg() && "This is not a register operand!");
66 return RegVal;
67 }
68
Andrew Scullcdfcccc2018-10-05 20:58:37 +010069 /// Set the register number.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010070 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;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100152 bool isBareSymbolRef() const;
153 bool evaluateAsConstantImm(int64_t &Imm) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100154};
155
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100156/// Instances of this class represent a single low-level machine
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100157/// instruction.
158class MCInst {
159 unsigned Opcode = 0;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100160 // 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
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200165 SMLoc Loc;
166 SmallVector<MCOperand, 8> Operands;
167
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100168public:
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
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200184 void addOperand(const MCOperand Op) { Operands.push_back(Op); }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100185
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); }
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100191 void erase(iterator First, iterator Last) { Operands.erase(First, Last); }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100192 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100205 /// Dump the MCInst as prettily as possible using the additional MC
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100206 /// 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;
Andrew Walbran16937d02019-10-22 13:54:20 +0100210 void dump_pretty(raw_ostream &OS, StringRef Name,
211 StringRef Separator = " ") const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100212};
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