LLVM  16.0.0git
SPIRVMCCodeEmitter.cpp
Go to the documentation of this file.
1 //===-- SPIRVMCCodeEmitter.cpp - Emit SPIR-V machine code -------*- 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 implements the SPIRVMCCodeEmitter class.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "llvm/CodeGen/Register.h"
15 #include "llvm/MC/MCCodeEmitter.h"
16 #include "llvm/MC/MCFixup.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCInstrInfo.h"
19 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/Endian.h"
24 
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "spirv-mccodeemitter"
28 
29 namespace {
30 
31 class SPIRVMCCodeEmitter : public MCCodeEmitter {
32  const MCInstrInfo &MCII;
33 
34 public:
35  SPIRVMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {}
36  SPIRVMCCodeEmitter(const SPIRVMCCodeEmitter &) = delete;
37  void operator=(const SPIRVMCCodeEmitter &) = delete;
38  ~SPIRVMCCodeEmitter() override = default;
39 
40  // getBinaryCodeForInstr - TableGen'erated function for getting the
41  // binary encoding for an instruction.
42  uint64_t getBinaryCodeForInstr(const MCInst &MI,
44  const MCSubtargetInfo &STI) const;
45 
46  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
48  const MCSubtargetInfo &STI) const override;
49 };
50 
51 } // end anonymous namespace
52 
54  MCContext &Ctx) {
55  return new SPIRVMCCodeEmitter(MCII);
56 }
57 
59 
60 // Check if the instruction has a type argument for operand 1, and defines an ID
61 // output register in operand 0. If so, we need to swap operands 0 and 1 so the
62 // type comes first in the output, despide coming second in the MCInst.
63 static bool hasType(const MCInst &MI, const MCInstrInfo &MII) {
64  MCInstrDesc MCDesc = MII.get(MI.getOpcode());
65  // If we define an output, and have at least one other argument.
66  if (MCDesc.getNumDefs() == 1 && MCDesc.getNumOperands() >= 2) {
67  // Check if we define an ID, and take a type as operand 1.
68  auto DefOpInfo = MCDesc.opInfo_begin();
69  auto FirstArgOpInfo = MCDesc.opInfo_begin() + 1;
70  return (DefOpInfo->RegClass == SPIRV::IDRegClassID ||
71  DefOpInfo->RegClass == SPIRV::ANYIDRegClassID) &&
72  FirstArgOpInfo->RegClass == SPIRV::TYPERegClassID;
73  }
74  return false;
75 }
76 
77 static void emitOperand(const MCOperand &Op, EndianWriter &OSE) {
78  if (Op.isReg()) {
79  // Emit the id index starting at 1 (0 is an invalid index).
80  OSE.write<uint32_t>(Register::virtReg2Index(Op.getReg()) + 1);
81  } else if (Op.isImm()) {
82  OSE.write<uint32_t>(Op.getImm());
83  } else {
84  llvm_unreachable("Unexpected operand type in VReg");
85  }
86 }
87 
88 // Emit the type in operand 1 before the ID in operand 0 it defines, and all
89 // remaining operands in the order they come naturally.
90 static void emitTypedInstrOperands(const MCInst &MI, EndianWriter &OSE) {
91  unsigned NumOps = MI.getNumOperands();
92  emitOperand(MI.getOperand(1), OSE);
93  emitOperand(MI.getOperand(0), OSE);
94  for (unsigned i = 2; i < NumOps; ++i)
95  emitOperand(MI.getOperand(i), OSE);
96 }
97 
98 // Emit operands in the order they come naturally.
99 static void emitUntypedInstrOperands(const MCInst &MI, EndianWriter &OSE) {
100  for (const auto &Op : MI)
101  emitOperand(Op, OSE);
102 }
103 
104 void SPIRVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
106  const MCSubtargetInfo &STI) const {
107  EndianWriter OSE(OS, support::little);
108 
109  // Encode the first 32 SPIR-V bytes with the number of args and the opcode.
110  const uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
111  const uint32_t NumWords = MI.getNumOperands() + 1;
112  const uint32_t FirstWord = (NumWords << 16) | OpCode;
113  OSE.write<uint32_t>(FirstWord);
114 
115  // Emit the instruction arguments (emitting the output type first if present).
116  if (hasType(MI, MCII))
118  else
120 }
121 
122 #include "SPIRVGenMCCodeEmitter.inc"
i
i
Definition: README.txt:29
llvm::MCInstrDesc::getNumDefs
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Definition: MCInstrDesc.h:245
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:109
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
emitTypedInstrOperands
static void emitTypedInstrOperands(const MCInst &MI, EndianWriter &OSE)
Definition: SPIRVMCCodeEmitter.cpp:90
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:77
MCCodeEmitter.h
SPIRVMCTargetDesc.h
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::support::endian::Writer
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:52
llvm::createSPIRVMCCodeEmitter
MCCodeEmitter * createSPIRVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
Definition: SPIRVMCCodeEmitter.cpp:53
llvm::support::little
@ little
Definition: Endian.h:27
MCInstrInfo.h
MCInst.h
llvm::MCInstrDesc
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:197
llvm::AArch64::Fixups
Fixups
Definition: AArch64FixupKinds.h:17
MCSubtargetInfo.h
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::MCOperandInfo::RegClass
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition: MCInstrDesc.h:90
uint64_t
MCRegisterInfo.h
emitUntypedInstrOperands
static void emitUntypedInstrOperands(const MCInst &MI, EndianWriter &OSE)
Definition: SPIRVMCCodeEmitter.cpp:99
llvm::support::endian::Writer::write
void write(ArrayRef< value_type > Val)
Definition: EndianStream.h:56
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
uint32_t
MCFixup.h
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
EndianStream.h
llvm::MCCodeEmitter
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:348
llvm::MCInstrDesc::opInfo_begin
const_opInfo_iterator opInfo_begin() const
Definition: MCInstrDesc.h:234
hasType
static bool hasType(const MCInst &MI, const MCInstrInfo &MII)
Definition: SPIRVMCCodeEmitter.cpp:63
emitOperand
static void emitOperand(const MCOperand &Op, EndianWriter &OSE)
Definition: SPIRVMCCodeEmitter.cpp:77
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
llvm::MCOperand
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
Register.h
llvm::MCInstrInfo::get
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
llvm::Register::virtReg2Index
static unsigned virtReg2Index(Register Reg)
Convert a virtual register number to a 0-based index.
Definition: Register.h:77
Endian.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:77
llvm::MCInstrDesc::getNumOperands
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:230
Debug.h