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
34using namespace llvm;
35
36AMDGPUMCInstLower::AMDGPUMCInstLower(MCContext &ctx, const AMDGPUSubtarget &st):
37  Ctx(ctx), ST(st)
38{ }
39
40enum AMDGPUMCInstLower::SISubtarget
41AMDGPUMCInstLower::AMDGPUSubtargetToSISubtarget(unsigned) const {
42  return AMDGPUMCInstLower::SI;
43}
44
45unsigned 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
55void 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
85void 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