1f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===- AMDGPUMCInstLower.cpp - Lower AMDGPU MachineInstr to an MCInst -----===// 2f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// 3f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// The LLVM Compiler Infrastructure 4f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// 5f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// This file is distributed under the University of Illinois Open Source 6f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// License. See LICENSE.TXT for details. 7f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// 8f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===// 9f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// 10f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// \file 11f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// \brief Code to lower AMDGPU MachineInstrs to their corresponding MCInst. 12f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// 13f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===// 14f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// 15f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 16f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "AMDGPUMCInstLower.h" 17f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "AMDGPUAsmPrinter.h" 18cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "AMDGPUTargetMachine.h" 19f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include "InstPrinter/AMDGPUInstPrinter.h" 20f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "R600InstrInfo.h" 21dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "SIInstrInfo.h" 22f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/CodeGen/MachineBasicBlock.h" 23f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/CodeGen/MachineInstr.h" 240b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h" 25f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include "llvm/MC/MCCodeEmitter.h" 2658a2cbef4aac9ee7d530dfb690c78d6fc11a2371Chandler Carruth#include "llvm/MC/MCExpr.h" 27f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/MC/MCInst.h" 28f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include "llvm/MC/MCObjectStreamer.h" 29f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/MC/MCStreamer.h" 30f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/Support/ErrorHandling.h" 31f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include "llvm/Support/Format.h" 32f9318673178309288f9320efe02d529419ac32a2Tom Stellard#include <algorithm> 33f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 34f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardusing namespace llvm; 35f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 36dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAMDGPUMCInstLower::AMDGPUMCInstLower(MCContext &ctx, const AMDGPUSubtarget &st): 37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Ctx(ctx), ST(st) 383ee6391e0cddf8d94e2fa441d661c23e494a8489Tom Stellard{ } 39f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesenum AMDGPUMCInstLower::SISubtarget 41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAMDGPUMCInstLower::AMDGPUSubtargetToSISubtarget(unsigned) const { 42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return AMDGPUMCInstLower::SI; 43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 45dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesunsigned AMDGPUMCInstLower::getMCOpcode(unsigned MIOpcode) const { 46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines int MCOpcode = AMDGPU::getMCOpcode(MIOpcode, 48dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines AMDGPUSubtargetToSISubtarget(ST.getGeneration())); 49dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (MCOpcode == -1) 50dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCOpcode = MIOpcode; 51dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 52dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return MCOpcode; 53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 54dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 55f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { 56f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 57dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines OutMI.setOpcode(getMCOpcode(MI->getOpcode())); 58f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 59dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (const MachineOperand &MO : MI->explicit_operands()) { 60f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard MCOperand MCOp; 61f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard switch (MO.getType()) { 62f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard default: 63f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard llvm_unreachable("unknown operand type"); 64f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard case MachineOperand::MO_FPImmediate: { 65f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard const APFloat &FloatValue = MO.getFPImm()->getValueAPF(); 66f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard assert(&FloatValue.getSemantics() == &APFloat::IEEEsingle && 67f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard "Only floating point immediates are supported at the moment."); 68f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard MCOp = MCOperand::CreateFPImm(FloatValue.convertToFloat()); 69f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard break; 70f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 71f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard case MachineOperand::MO_Immediate: 72f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard MCOp = MCOperand::CreateImm(MO.getImm()); 73f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard break; 74f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard case MachineOperand::MO_Register: 75f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard MCOp = MCOperand::CreateReg(MO.getReg()); 76f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard break; 773ee6391e0cddf8d94e2fa441d661c23e494a8489Tom Stellard case MachineOperand::MO_MachineBasicBlock: 783ee6391e0cddf8d94e2fa441d661c23e494a8489Tom Stellard MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( 793ee6391e0cddf8d94e2fa441d661c23e494a8489Tom Stellard MO.getMBB()->getSymbol(), Ctx)); 80f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 81f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard OutMI.addOperand(MCOp); 82f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 83f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard} 84f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 85f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) { 86dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines AMDGPUMCInstLower MCInstLowering(OutContext, 87dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MF->getTarget().getSubtarget<AMDGPUSubtarget>()); 88f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#ifdef _DEBUG 9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef Err; 9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!TM.getInstrInfo()->verifyInstruction(MI, Err)) { 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines errs() << "Warning: Illegal instruction detected: " << Err << "\n"; 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MI->dump(); 9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#endif 96f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (MI->isBundle()) { 97f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard const MachineBasicBlock *MBB = MI->getParent(); 98f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard MachineBasicBlock::const_instr_iterator I = MI; 99f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard ++I; 100f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard while (I != MBB->end() && I->isInsideBundle()) { 101f9318673178309288f9320efe02d529419ac32a2Tom Stellard EmitInstruction(I); 102f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard ++I; 103f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 104f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } else { 105f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard MCInst TmpInst; 106f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard MCInstLowering.lower(MI, TmpInst); 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EmitToStreamer(OutStreamer, TmpInst); 108f9318673178309288f9320efe02d529419ac32a2Tom Stellard 109f9318673178309288f9320efe02d529419ac32a2Tom Stellard if (DisasmEnabled) { 110f9318673178309288f9320efe02d529419ac32a2Tom Stellard // Disassemble instruction/operands to text. 111f9318673178309288f9320efe02d529419ac32a2Tom Stellard DisasmLines.resize(DisasmLines.size() + 1); 112f9318673178309288f9320efe02d529419ac32a2Tom Stellard std::string &DisasmLine = DisasmLines.back(); 113f9318673178309288f9320efe02d529419ac32a2Tom Stellard raw_string_ostream DisasmStream(DisasmLine); 114f9318673178309288f9320efe02d529419ac32a2Tom Stellard 115f9318673178309288f9320efe02d529419ac32a2Tom Stellard AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *TM.getInstrInfo(), 116f9318673178309288f9320efe02d529419ac32a2Tom Stellard *TM.getRegisterInfo()); 117f9318673178309288f9320efe02d529419ac32a2Tom Stellard InstPrinter.printInst(&TmpInst, DisasmStream, StringRef()); 118f9318673178309288f9320efe02d529419ac32a2Tom Stellard 119f9318673178309288f9320efe02d529419ac32a2Tom Stellard // Disassemble instruction/operands to hex representation. 120f9318673178309288f9320efe02d529419ac32a2Tom Stellard SmallVector<MCFixup, 4> Fixups; 121f9318673178309288f9320efe02d529419ac32a2Tom Stellard SmallVector<char, 16> CodeBytes; 122f9318673178309288f9320efe02d529419ac32a2Tom Stellard raw_svector_ostream CodeStream(CodeBytes); 123f9318673178309288f9320efe02d529419ac32a2Tom Stellard 124f9318673178309288f9320efe02d529419ac32a2Tom Stellard MCObjectStreamer &ObjStreamer = (MCObjectStreamer &)OutStreamer; 125f9318673178309288f9320efe02d529419ac32a2Tom Stellard MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter(); 12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines InstEmitter.EncodeInstruction(TmpInst, CodeStream, Fixups, 12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines TM.getSubtarget<MCSubtargetInfo>()); 128f9318673178309288f9320efe02d529419ac32a2Tom Stellard CodeStream.flush(); 129f9318673178309288f9320efe02d529419ac32a2Tom Stellard 130f9318673178309288f9320efe02d529419ac32a2Tom Stellard HexLines.resize(HexLines.size() + 1); 131f9318673178309288f9320efe02d529419ac32a2Tom Stellard std::string &HexLine = HexLines.back(); 132f9318673178309288f9320efe02d529419ac32a2Tom Stellard raw_string_ostream HexStream(HexLine); 133f9318673178309288f9320efe02d529419ac32a2Tom Stellard 134f9318673178309288f9320efe02d529419ac32a2Tom Stellard for (size_t i = 0; i < CodeBytes.size(); i += 4) { 135f9318673178309288f9320efe02d529419ac32a2Tom Stellard unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i]; 136f9318673178309288f9320efe02d529419ac32a2Tom Stellard HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord); 137f9318673178309288f9320efe02d529419ac32a2Tom Stellard } 138f9318673178309288f9320efe02d529419ac32a2Tom Stellard 139f9318673178309288f9320efe02d529419ac32a2Tom Stellard DisasmStream.flush(); 140f9318673178309288f9320efe02d529419ac32a2Tom Stellard DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size()); 141f9318673178309288f9320efe02d529419ac32a2Tom Stellard } 142f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 143f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard} 144