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