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