1//=- SPIRVMCInstLower.cpp - Convert SPIR-V MachineInstr to MCInst -*- 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 code to lower SPIR-V MachineInstrs to their corresponding
10// MCInst records.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRVMCInstLower.h"
15#include "SPIRVModuleAnalysis.h"
16#include "SPIRVSubtarget.h"
17#include "SPIRVUtils.h"
18#include "llvm/CodeGen/MachineInstr.h"
19#include "llvm/IR/Constants.h"
20
21using namespace llvm;
22
23void SPIRVMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI,
24 SPIRV::ModuleAnalysisInfo *MAI) const {
25 OutMI.setOpcode(MI->isPHI() ? SPIRV::OpPhi : MI->getOpcode());
26 // Propagate previously set flags
27 if (MI->getAsmPrinterFlags() & SPIRV::ASM_PRINTER_WIDTH16)
28 OutMI.setFlags(SPIRV::INST_PRINTER_WIDTH16);
29 if (MI->getAsmPrinterFlags() & SPIRV::ASM_PRINTER_WIDTH64)
30 OutMI.setFlags(SPIRV::INST_PRINTER_WIDTH64);
31 const MachineFunction *MF = MI->getMF();
32 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
33 const MachineOperand &MO = MI->getOperand(i);
34 MCOperand MCOp;
35 switch (MO.getType()) {
36 default:
37 llvm_unreachable("unknown operand type");
38 case MachineOperand::MO_GlobalAddress: {
39 MCRegister Reg =
40 MAI->getGlobalObjReg(GO: dyn_cast<GlobalObject>(Val: MO.getGlobal()));
41 if (!Reg.isValid()) {
42 std::string DiagMsg;
43 raw_string_ostream OS(DiagMsg);
44 MI->print(OS);
45 DiagMsg = "Unknown global object in:" + DiagMsg;
46 report_fatal_error(reason: DiagMsg.c_str());
47 }
48 MCOp = MCOperand::createReg(Reg);
49 break;
50 }
51 case MachineOperand::MO_MachineBasicBlock:
52 MCOp = MCOperand::createReg(Reg: MAI->getOrCreateMBBRegister(MBB: *MO.getMBB()));
53 break;
54 case MachineOperand::MO_Register: {
55 MCRegister NewReg = MAI->getRegisterAlias(MF, Reg: MO.getReg());
56 MCOp = MCOperand::createReg(Reg: NewReg.isValid() ? NewReg
57 : MO.getReg().asMCReg());
58 break;
59 }
60 case MachineOperand::MO_Immediate:
61 if (MI->getOpcode() == SPIRV::OpExtInst && i == 2) {
62 MCRegister Reg = MAI->getExtInstSetReg(SetNum: MO.getImm());
63 MCOp = MCOperand::createReg(Reg);
64 } else {
65 MCOp = MCOperand::createImm(Val: MO.getImm());
66 }
67 break;
68 case MachineOperand::MO_FPImmediate:
69 MCOp = MCOperand::createDFPImm(
70 Val: MO.getFPImm()->getValueAPF().convertToFloat());
71 break;
72 }
73
74 OutMI.addOperand(Op: MCOp);
75
76 // OpPhi takes the result type right after the result.
77 if (i == 0 && MI->isPHI()) {
78 SPIRVGlobalRegistry *GR =
79 MF->getSubtarget<SPIRVSubtarget>().getSPIRVGlobalRegistry();
80 Register TypeReg =
81 GR->getSPIRVTypeID(SpirvType: GR->getSPIRVTypeForVReg(VReg: MO.getReg(), MF));
82 MCRegister TypeAlias = MAI->getRegisterAlias(MF, Reg: TypeReg);
83 assert(TypeAlias.isValid() && "OpPhi result type has no global ID");
84 OutMI.addOperand(Op: MCOperand::createReg(Reg: TypeAlias));
85 }
86 }
87}
88