LLVM 19.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
16#include "llvm/MC/MCFixup.h"
17#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCInstrInfo.h"
21#include "llvm/Support/Debug.h"
22#include "llvm/Support/Endian.h"
24
25using namespace llvm;
26
27#define DEBUG_TYPE "spirv-mccodeemitter"
28
29namespace {
30
31class SPIRVMCCodeEmitter : public MCCodeEmitter {
32 const MCInstrInfo &MCII;
33
34public:
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
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.
63static bool hasType(const MCInst &MI, const MCInstrInfo &MII) {
64 const 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.operands()[0];
69 auto &FirstArgOpInfo = MCDesc.operands()[1];
70 return (DefOpInfo.RegClass == SPIRV::IDRegClassID ||
71 DefOpInfo.RegClass == SPIRV::ANYIDRegClassID) &&
72 FirstArgOpInfo.RegClass == SPIRV::TYPERegClassID;
73 }
74 return false;
75}
76
78 if (Op.isReg()) {
79 // Emit the id index starting at 1 (0 is an invalid index).
80 support::endian::write<uint32_t>(
82 } else if (Op.isImm()) {
83 support::endian::write(CB, static_cast<uint32_t>(Op.getImm()),
85 } else {
86 llvm_unreachable("Unexpected operand type in VReg");
87 }
88}
89
90// Emit the type in operand 1 before the ID in operand 0 it defines, and all
91// remaining operands in the order they come naturally.
92static void emitTypedInstrOperands(const MCInst &MI,
94 unsigned NumOps = MI.getNumOperands();
95 emitOperand(MI.getOperand(1), CB);
96 emitOperand(MI.getOperand(0), CB);
97 for (unsigned i = 2; i < NumOps; ++i)
98 emitOperand(MI.getOperand(i), CB);
99}
100
101// Emit operands in the order they come naturally.
104 for (const auto &Op : MI)
105 emitOperand(Op, CB);
106}
107
108void SPIRVMCCodeEmitter::encodeInstruction(const MCInst &MI,
111 const MCSubtargetInfo &STI) const {
112 // Encode the first 32 SPIR-V bytes with the number of args and the opcode.
113 const uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
114 const uint32_t NumWords = MI.getNumOperands() + 1;
115 const uint32_t FirstWord = (NumWords << 16) | OpCode;
117
118 // Emit the instruction arguments (emitting the output type first if present).
119 if (hasType(MI, MCII))
121 else
123}
124
125#include "SPIRVGenMCCodeEmitter.inc"
IRTranslator LLVM IR MI
static void emitUntypedInstrOperands(const MCInst &MI, SmallVectorImpl< char > &CB)
static void emitOperand(const MCOperand &Op, SmallVectorImpl< char > &CB)
static void emitTypedInstrOperands(const MCInst &MI, SmallVectorImpl< char > &CB)
static bool hasType(const MCInst &MI, const MCInstrInfo &MII)
This class represents an Operation in the Expression.
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
MCCodeEmitter & operator=(const MCCodeEmitter &)=delete
Context object for machine code objects.
Definition: MCContext.h:81
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:237
ArrayRef< MCOperandInfo > operands() const
Definition: MCInstrDesc.h:239
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Definition: MCInstrDesc.h:248
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
Generic base class for all target subtargets.
static unsigned virtReg2Index(Register Reg)
Convert a virtual register number to a 0-based index.
Definition: Register.h:77
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:91
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MCCodeEmitter * createSPIRVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:67