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