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, 6> 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