//===- llvm/MC/MCInst.h - MCInst class --------------------------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
// This file contains the declaration of the MCInst and MCOperand classes, which
 
// is the basic representation used to represent low-level machine code
 
// instructions.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_MC_MCINST_H
 
#define LLVM_MC_MCINST_H
 
 
 
#include "llvm/ADT/SmallVector.h"
 
#include "llvm/ADT/StringRef.h"
 
#include "llvm/ADT/bit.h"
 
#include "llvm/Support/SMLoc.h"
 
#include <cassert>
 
#include <cstddef>
 
#include <cstdint>
 
 
 
namespace llvm {
 
 
 
class MCExpr;
 
class MCInst;
 
class MCInstPrinter;
 
class MCRegisterInfo;
 
class raw_ostream;
 
 
 
/// Instances of this class represent operands of the MCInst class.
 
/// This is a simple discriminated union.
 
class MCOperand {
 
  enum MachineOperandType : unsigned char {
 
    kInvalid,      ///< Uninitialized.
 
    kRegister,     ///< Register operand.
 
    kImmediate,    ///< Immediate operand.
 
    kSFPImmediate, ///< Single-floating-point immediate operand.
 
    kDFPImmediate, ///< Double-Floating-point immediate operand.
 
    kExpr,         ///< Relocatable immediate operand.
 
    kInst          ///< Sub-instruction operand.
 
  };
 
  MachineOperandType Kind = kInvalid;
 
 
 
  union {
 
    unsigned RegVal;
 
    int64_t ImmVal;
 
    uint32_t SFPImmVal;
 
    uint64_t FPImmVal;
 
    const MCExpr *ExprVal;
 
    const MCInst *InstVal;
 
  };
 
 
 
public:
 
  MCOperand() : FPImmVal(0) {}
 
 
 
  bool isValid() const { return Kind != kInvalid; }
 
  bool isReg() const { return Kind == kRegister; }
 
  bool isImm() const { return Kind == kImmediate; }
 
  bool isSFPImm() const { return Kind == kSFPImmediate; }
 
  bool isDFPImm() const { return Kind == kDFPImmediate; }
 
  bool isExpr() const { return Kind == kExpr; }
 
  bool isInst() const { return Kind == kInst; }
 
 
 
  /// Returns the register number.
 
  unsigned getReg() const {
 
    assert(isReg() && "This is not a register operand!");
 
    return RegVal;
 
  }
 
 
 
  /// Set the register number.
 
  void setReg(unsigned Reg) {
 
    assert(isReg() && "This is not a register operand!");
 
    RegVal = Reg;
 
  }
 
 
 
  int64_t getImm() const {
 
    assert(isImm() && "This is not an immediate");
 
    return ImmVal;
 
  }
 
 
 
  void setImm(int64_t Val) {
 
    assert(isImm() && "This is not an immediate");
 
    ImmVal = Val;
 
  }
 
 
 
  uint32_t getSFPImm() const {
 
    assert(isSFPImm() && "This is not an SFP immediate");
 
    return SFPImmVal;
 
  }
 
 
 
  void setSFPImm(uint32_t Val) {
 
    assert(isSFPImm() && "This is not an SFP immediate");
 
    SFPImmVal = Val;
 
  }
 
 
 
  uint64_t getDFPImm() const {
 
    assert(isDFPImm() && "This is not an FP immediate");
 
    return FPImmVal;
 
  }
 
 
 
  void setDFPImm(uint64_t Val) {
 
    assert(isDFPImm() && "This is not an FP immediate");
 
    FPImmVal = Val;
 
  }
 
  void setFPImm(double Val) {
 
    assert(isDFPImm() && "This is not an FP immediate");
 
    FPImmVal = bit_cast<uint64_t>(Val);
 
  }
 
 
 
  const MCExpr *getExpr() const {
 
    assert(isExpr() && "This is not an expression");
 
    return ExprVal;
 
  }
 
 
 
  void setExpr(const MCExpr *Val) {
 
    assert(isExpr() && "This is not an expression");
 
    ExprVal = Val;
 
  }
 
 
 
  const MCInst *getInst() const {
 
    assert(isInst() && "This is not a sub-instruction");
 
    return InstVal;
 
  }
 
 
 
  void setInst(const MCInst *Val) {
 
    assert(isInst() && "This is not a sub-instruction");
 
    InstVal = Val;
 
  }
 
 
 
  static MCOperand createReg(unsigned Reg) {
 
    MCOperand Op;
 
    Op.Kind = kRegister;
 
    Op.RegVal = Reg;
 
    return Op;
 
  }
 
 
 
  static MCOperand createImm(int64_t Val) {
 
    MCOperand Op;
 
    Op.Kind = kImmediate;
 
    Op.ImmVal = Val;
 
    return Op;
 
  }
 
 
 
  static MCOperand createSFPImm(uint32_t Val) {
 
    MCOperand Op;
 
    Op.Kind = kSFPImmediate;
 
    Op.SFPImmVal = Val;
 
    return Op;
 
  }
 
 
 
  static MCOperand createDFPImm(uint64_t Val) {
 
    MCOperand Op;
 
    Op.Kind = kDFPImmediate;
 
    Op.FPImmVal = Val;
 
    return Op;
 
  }
 
 
 
  static MCOperand createExpr(const MCExpr *Val) {
 
    MCOperand Op;
 
    Op.Kind = kExpr;
 
    Op.ExprVal = Val;
 
    return Op;
 
  }
 
 
 
  static MCOperand createInst(const MCInst *Val) {
 
    MCOperand Op;
 
    Op.Kind = kInst;
 
    Op.InstVal = Val;
 
    return Op;
 
  }
 
 
 
  void print(raw_ostream &OS, const MCRegisterInfo *RegInfo = nullptr) const;
 
  void dump() const;
 
  bool isBareSymbolRef() const;
 
  bool evaluateAsConstantImm(int64_t &Imm) const;
 
};
 
 
 
/// Instances of this class represent a single low-level machine
 
/// instruction.
 
class MCInst {
 
  unsigned Opcode = 0;
 
  // These flags could be used to pass some info from one target subcomponent
 
  // to another, for example, from disassembler to asm printer. The values of
 
  // the flags have any sense on target level only (e.g. prefixes on x86).
 
  unsigned Flags = 0;
 
 
 
  SMLoc Loc;
 
  SmallVector<MCOperand, 10> Operands;
 
 
 
public:
 
  MCInst() = default;
 
 
 
  void setOpcode(unsigned Op) { Opcode = Op; }
 
  unsigned getOpcode() const { return Opcode; }
 
 
 
  void setFlags(unsigned F) { Flags = F; }
 
  unsigned getFlags() const { return Flags; }
 
 
 
  void setLoc(SMLoc loc) { Loc = loc; }
 
  SMLoc getLoc() const { return Loc; }
 
 
 
  const MCOperand &getOperand(unsigned i) const { return Operands[i]; }
 
  MCOperand &getOperand(unsigned i) { return Operands[i]; }
 
  unsigned getNumOperands() const { return Operands.size(); }
 
 
 
  void addOperand(const MCOperand Op) { Operands.push_back(Op); }
 
 
 
  using iterator = SmallVectorImpl<MCOperand>::iterator;
 
  using const_iterator = SmallVectorImpl<MCOperand>::const_iterator;
 
 
 
  void clear() { Operands.clear(); }
 
  void erase(iterator I) { Operands.erase(I); }
 
  void erase(iterator First, iterator Last) { Operands.erase(First, Last); }
 
  size_t size() const { return Operands.size(); }
 
  iterator begin() { return Operands.begin(); }
 
  const_iterator begin() const { return Operands.begin(); }
 
  iterator end() { return Operands.end(); }
 
  const_iterator end() const { return Operands.end(); }
 
 
 
  iterator insert(iterator I, const MCOperand &Op) {
 
    return Operands.insert(I, Op);
 
  }
 
 
 
  void print(raw_ostream &OS, const MCRegisterInfo *RegInfo = nullptr) const;
 
  void dump() const;
 
 
 
  /// Dump the MCInst as prettily as possible using the additional MC
 
  /// structures, if given. Operators are separated by the \p Separator
 
  /// string.
 
  void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr,
 
                   StringRef Separator = " ",
 
                   const MCRegisterInfo *RegInfo = nullptr) const;
 
  void dump_pretty(raw_ostream &OS, StringRef Name, StringRef Separator = " ",
 
                   const MCRegisterInfo *RegInfo = nullptr) const;
 
};
 
 
 
inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) {
 
  MO.print(OS);
 
  return OS;
 
}
 
 
 
inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) {
 
  MI.print(OS);
 
  return OS;
 
}
 
 
 
} // end namespace llvm
 
 
 
#endif // LLVM_MC_MCINST_H