1284677Sdim//===- AMDGPUMCInstLower.cpp - Lower AMDGPU MachineInstr to an MCInst -----===// 2284677Sdim// 3284677Sdim// The LLVM Compiler Infrastructure 4284677Sdim// 5284677Sdim// This file is distributed under the University of Illinois Open Source 6284677Sdim// License. See LICENSE.TXT for details. 7284677Sdim// 8284677Sdim//===----------------------------------------------------------------------===// 9284677Sdim// 10284677Sdim/// \file 11284677Sdim/// \brief Code to lower AMDGPU MachineInstrs to their corresponding MCInst. 12284677Sdim// 13284677Sdim//===----------------------------------------------------------------------===// 14284677Sdim// 15284677Sdim 16284677Sdim#include "AMDGPUMCInstLower.h" 17284677Sdim#include "AMDGPUAsmPrinter.h" 18284677Sdim#include "AMDGPUTargetMachine.h" 19284677Sdim#include "InstPrinter/AMDGPUInstPrinter.h" 20284677Sdim#include "R600InstrInfo.h" 21284677Sdim#include "SIInstrInfo.h" 22284677Sdim#include "llvm/CodeGen/MachineBasicBlock.h" 23284677Sdim#include "llvm/CodeGen/MachineInstr.h" 24284677Sdim#include "llvm/IR/Constants.h" 25284677Sdim#include "llvm/IR/Function.h" 26284677Sdim#include "llvm/IR/GlobalVariable.h" 27284677Sdim#include "llvm/MC/MCCodeEmitter.h" 28284677Sdim#include "llvm/MC/MCContext.h" 29284677Sdim#include "llvm/MC/MCExpr.h" 30284677Sdim#include "llvm/MC/MCInst.h" 31284677Sdim#include "llvm/MC/MCObjectStreamer.h" 32284677Sdim#include "llvm/MC/MCStreamer.h" 33284677Sdim#include "llvm/Support/ErrorHandling.h" 34284677Sdim#include "llvm/Support/Format.h" 35284677Sdim#include <algorithm> 36284677Sdim 37284677Sdimusing namespace llvm; 38284677Sdim 39284677SdimAMDGPUMCInstLower::AMDGPUMCInstLower(MCContext &ctx, const AMDGPUSubtarget &st): 40284677Sdim Ctx(ctx), ST(st) 41284677Sdim{ } 42284677Sdim 43284677Sdimvoid AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { 44284677Sdim 45284677Sdim int MCOpcode = ST.getInstrInfo()->pseudoToMCOpcode(MI->getOpcode()); 46284677Sdim 47284677Sdim if (MCOpcode == -1) { 48284677Sdim LLVMContext &C = MI->getParent()->getParent()->getFunction()->getContext(); 49284677Sdim C.emitError("AMDGPUMCInstLower::lower - Pseudo instruction doesn't have " 50284677Sdim "a target-specific version: " + Twine(MI->getOpcode())); 51284677Sdim } 52284677Sdim 53284677Sdim OutMI.setOpcode(MCOpcode); 54284677Sdim 55284677Sdim for (const MachineOperand &MO : MI->explicit_operands()) { 56284677Sdim MCOperand MCOp; 57284677Sdim switch (MO.getType()) { 58284677Sdim default: 59284677Sdim llvm_unreachable("unknown operand type"); 60284677Sdim case MachineOperand::MO_Immediate: 61284677Sdim MCOp = MCOperand::createImm(MO.getImm()); 62284677Sdim break; 63284677Sdim case MachineOperand::MO_Register: 64296417Sdim MCOp = MCOperand::createReg(AMDGPU::getMCReg(MO.getReg(), ST)); 65284677Sdim break; 66284677Sdim case MachineOperand::MO_MachineBasicBlock: 67284677Sdim MCOp = MCOperand::createExpr(MCSymbolRefExpr::create( 68284677Sdim MO.getMBB()->getSymbol(), Ctx)); 69284677Sdim break; 70284677Sdim case MachineOperand::MO_GlobalAddress: { 71284677Sdim const GlobalValue *GV = MO.getGlobal(); 72284677Sdim MCSymbol *Sym = Ctx.getOrCreateSymbol(StringRef(GV->getName())); 73284677Sdim MCOp = MCOperand::createExpr(MCSymbolRefExpr::create(Sym, Ctx)); 74284677Sdim break; 75284677Sdim } 76284677Sdim case MachineOperand::MO_ExternalSymbol: { 77284677Sdim MCSymbol *Sym = Ctx.getOrCreateSymbol(StringRef(MO.getSymbolName())); 78284677Sdim const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx); 79284677Sdim MCOp = MCOperand::createExpr(Expr); 80284677Sdim break; 81284677Sdim } 82284677Sdim } 83284677Sdim OutMI.addOperand(MCOp); 84284677Sdim } 85284677Sdim} 86284677Sdim 87284677Sdimvoid AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) { 88284677Sdim const AMDGPUSubtarget &STI = MF->getSubtarget<AMDGPUSubtarget>(); 89284677Sdim AMDGPUMCInstLower MCInstLowering(OutContext, STI); 90284677Sdim 91284677Sdim#ifdef _DEBUG 92284677Sdim StringRef Err; 93284677Sdim if (!STI.getInstrInfo()->verifyInstruction(MI, Err)) { 94284677Sdim errs() << "Warning: Illegal instruction detected: " << Err << "\n"; 95284677Sdim MI->dump(); 96284677Sdim } 97284677Sdim#endif 98284677Sdim if (MI->isBundle()) { 99284677Sdim const MachineBasicBlock *MBB = MI->getParent(); 100296417Sdim MachineBasicBlock::const_instr_iterator I = ++MI->getIterator(); 101296417Sdim while (I != MBB->instr_end() && I->isInsideBundle()) { 102296417Sdim EmitInstruction(&*I); 103284677Sdim ++I; 104284677Sdim } 105284677Sdim } else { 106284677Sdim MCInst TmpInst; 107284677Sdim MCInstLowering.lower(MI, TmpInst); 108284677Sdim EmitToStreamer(*OutStreamer, TmpInst); 109284677Sdim 110284677Sdim if (STI.dumpCode()) { 111284677Sdim // Disassemble instruction/operands to text. 112284677Sdim DisasmLines.resize(DisasmLines.size() + 1); 113284677Sdim std::string &DisasmLine = DisasmLines.back(); 114284677Sdim raw_string_ostream DisasmStream(DisasmLine); 115284677Sdim 116284677Sdim AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), 117284677Sdim *MF->getSubtarget().getInstrInfo(), 118284677Sdim *MF->getSubtarget().getRegisterInfo()); 119284677Sdim InstPrinter.printInst(&TmpInst, DisasmStream, StringRef(), 120284677Sdim MF->getSubtarget()); 121284677Sdim 122284677Sdim // Disassemble instruction/operands to hex representation. 123284677Sdim SmallVector<MCFixup, 4> Fixups; 124284677Sdim SmallVector<char, 16> CodeBytes; 125284677Sdim raw_svector_ostream CodeStream(CodeBytes); 126284677Sdim 127284677Sdim auto &ObjStreamer = static_cast<MCObjectStreamer&>(*OutStreamer); 128284677Sdim MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter(); 129284677Sdim InstEmitter.encodeInstruction(TmpInst, CodeStream, Fixups, 130284677Sdim MF->getSubtarget<MCSubtargetInfo>()); 131284677Sdim HexLines.resize(HexLines.size() + 1); 132284677Sdim std::string &HexLine = HexLines.back(); 133284677Sdim raw_string_ostream HexStream(HexLine); 134284677Sdim 135284677Sdim for (size_t i = 0; i < CodeBytes.size(); i += 4) { 136284677Sdim unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i]; 137284677Sdim HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord); 138284677Sdim } 139284677Sdim 140284677Sdim DisasmStream.flush(); 141284677Sdim DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size()); 142284677Sdim } 143284677Sdim } 144284677Sdim} 145