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