xref: /src/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
14a16efa3SDimitry Andric //===- AMDGPUMCInstLower.cpp - Lower AMDGPU MachineInstr to an MCInst -----===//
24a16efa3SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64a16efa3SDimitry Andric //
74a16efa3SDimitry Andric //===----------------------------------------------------------------------===//
84a16efa3SDimitry Andric //
94a16efa3SDimitry Andric /// \file
10eb11fae6SDimitry Andric /// Code to lower AMDGPU MachineInstrs to their corresponding MCInst.
114a16efa3SDimitry Andric //
124a16efa3SDimitry Andric //===----------------------------------------------------------------------===//
134a16efa3SDimitry Andric //
144a16efa3SDimitry Andric 
15c0981da4SDimitry Andric #include "AMDGPUMCInstLower.h"
167fa27ce4SDimitry Andric #include "AMDGPU.h"
174a16efa3SDimitry Andric #include "AMDGPUAsmPrinter.h"
18e3b55780SDimitry Andric #include "AMDGPUMachineFunction.h"
195ca98fd9SDimitry Andric #include "AMDGPUTargetMachine.h"
20e6d15924SDimitry Andric #include "MCTargetDesc/AMDGPUInstPrinter.h"
21eb11fae6SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
224a16efa3SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
234a16efa3SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
244a16efa3SDimitry Andric #include "llvm/IR/Constants.h"
25ec304151SDimitry Andric #include "llvm/IR/Function.h"
265ca98fd9SDimitry Andric #include "llvm/IR/GlobalVariable.h"
27f8af5cf6SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
285ca98fd9SDimitry Andric #include "llvm/MC/MCContext.h"
294a16efa3SDimitry Andric #include "llvm/MC/MCExpr.h"
304a16efa3SDimitry Andric #include "llvm/MC/MCInst.h"
31f8af5cf6SDimitry Andric #include "llvm/MC/MCObjectStreamer.h"
324a16efa3SDimitry Andric #include "llvm/MC/MCStreamer.h"
334a16efa3SDimitry Andric #include "llvm/Support/ErrorHandling.h"
34f8af5cf6SDimitry Andric #include "llvm/Support/Format.h"
35f8af5cf6SDimitry Andric #include <algorithm>
364a16efa3SDimitry Andric 
374a16efa3SDimitry Andric using namespace llvm;
384a16efa3SDimitry Andric 
39b915e9e0SDimitry Andric #include "AMDGPUGenMCPseudoLowering.inc"
40b915e9e0SDimitry Andric 
AMDGPUMCInstLower(MCContext & ctx,const TargetSubtargetInfo & st,const AsmPrinter & ap)41eb11fae6SDimitry Andric AMDGPUMCInstLower::AMDGPUMCInstLower(MCContext &ctx,
42eb11fae6SDimitry Andric                                      const TargetSubtargetInfo &st,
43b915e9e0SDimitry Andric                                      const AsmPrinter &ap):
44b915e9e0SDimitry Andric   Ctx(ctx), ST(st), AP(ap) { }
4501095a5dSDimitry Andric 
getVariantKind(unsigned MOFlags)4601095a5dSDimitry Andric static MCSymbolRefExpr::VariantKind getVariantKind(unsigned MOFlags) {
4701095a5dSDimitry Andric   switch (MOFlags) {
48b915e9e0SDimitry Andric   default:
49b915e9e0SDimitry Andric     return MCSymbolRefExpr::VK_None;
50b915e9e0SDimitry Andric   case SIInstrInfo::MO_GOTPCREL:
51b915e9e0SDimitry Andric     return MCSymbolRefExpr::VK_GOTPCREL;
52b915e9e0SDimitry Andric   case SIInstrInfo::MO_GOTPCREL32_LO:
53b915e9e0SDimitry Andric     return MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_LO;
54b915e9e0SDimitry Andric   case SIInstrInfo::MO_GOTPCREL32_HI:
55b915e9e0SDimitry Andric     return MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_HI;
56b915e9e0SDimitry Andric   case SIInstrInfo::MO_REL32_LO:
57b915e9e0SDimitry Andric     return MCSymbolRefExpr::VK_AMDGPU_REL32_LO;
58b915e9e0SDimitry Andric   case SIInstrInfo::MO_REL32_HI:
59b915e9e0SDimitry Andric     return MCSymbolRefExpr::VK_AMDGPU_REL32_HI;
60e6d15924SDimitry Andric   case SIInstrInfo::MO_ABS32_LO:
61e6d15924SDimitry Andric     return MCSymbolRefExpr::VK_AMDGPU_ABS32_LO;
62e6d15924SDimitry Andric   case SIInstrInfo::MO_ABS32_HI:
63e6d15924SDimitry Andric     return MCSymbolRefExpr::VK_AMDGPU_ABS32_HI;
64b915e9e0SDimitry Andric   }
65b915e9e0SDimitry Andric }
66b915e9e0SDimitry Andric 
lowerOperand(const MachineOperand & MO,MCOperand & MCOp) const67b915e9e0SDimitry Andric bool AMDGPUMCInstLower::lowerOperand(const MachineOperand &MO,
68b915e9e0SDimitry Andric                                      MCOperand &MCOp) const {
69b915e9e0SDimitry Andric   switch (MO.getType()) {
70b915e9e0SDimitry Andric   default:
71344a3780SDimitry Andric     break;
72b915e9e0SDimitry Andric   case MachineOperand::MO_Immediate:
73b915e9e0SDimitry Andric     MCOp = MCOperand::createImm(MO.getImm());
74b915e9e0SDimitry Andric     return true;
75b915e9e0SDimitry Andric   case MachineOperand::MO_Register:
76b915e9e0SDimitry Andric     MCOp = MCOperand::createReg(AMDGPU::getMCReg(MO.getReg(), ST));
77b915e9e0SDimitry Andric     return true;
78344a3780SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
79b915e9e0SDimitry Andric     MCOp = MCOperand::createExpr(
80b915e9e0SDimitry Andric         MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
81b915e9e0SDimitry Andric     return true;
82b915e9e0SDimitry Andric   case MachineOperand::MO_GlobalAddress: {
83b915e9e0SDimitry Andric     const GlobalValue *GV = MO.getGlobal();
84b915e9e0SDimitry Andric     SmallString<128> SymbolName;
85b915e9e0SDimitry Andric     AP.getNameWithPrefix(SymbolName, GV);
86b915e9e0SDimitry Andric     MCSymbol *Sym = Ctx.getOrCreateSymbol(SymbolName);
87e6d15924SDimitry Andric     const MCExpr *Expr =
88b915e9e0SDimitry Andric       MCSymbolRefExpr::create(Sym, getVariantKind(MO.getTargetFlags()),Ctx);
89e6d15924SDimitry Andric     int64_t Offset = MO.getOffset();
90e6d15924SDimitry Andric     if (Offset != 0) {
91e6d15924SDimitry Andric       Expr = MCBinaryExpr::createAdd(Expr,
92e6d15924SDimitry Andric                                      MCConstantExpr::create(Offset, Ctx), Ctx);
93e6d15924SDimitry Andric     }
94b915e9e0SDimitry Andric     MCOp = MCOperand::createExpr(Expr);
95b915e9e0SDimitry Andric     return true;
96b915e9e0SDimitry Andric   }
97b915e9e0SDimitry Andric   case MachineOperand::MO_ExternalSymbol: {
98b915e9e0SDimitry Andric     MCSymbol *Sym = Ctx.getOrCreateSymbol(StringRef(MO.getSymbolName()));
99b915e9e0SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
100b915e9e0SDimitry Andric     MCOp = MCOperand::createExpr(Expr);
101b915e9e0SDimitry Andric     return true;
102b915e9e0SDimitry Andric   }
103044eb2f6SDimitry Andric   case MachineOperand::MO_RegisterMask:
104044eb2f6SDimitry Andric     // Regmasks are like implicit defs.
105044eb2f6SDimitry Andric     return false;
106344a3780SDimitry Andric   case MachineOperand::MO_MCSymbol:
107344a3780SDimitry Andric     if (MO.getTargetFlags() == SIInstrInfo::MO_FAR_BRANCH_OFFSET) {
108344a3780SDimitry Andric       MCSymbol *Sym = MO.getMCSymbol();
109344a3780SDimitry Andric       MCOp = MCOperand::createExpr(Sym->getVariableValue());
110344a3780SDimitry Andric       return true;
11101095a5dSDimitry Andric     }
112344a3780SDimitry Andric     break;
113344a3780SDimitry Andric   }
114344a3780SDimitry Andric   llvm_unreachable("unknown operand type");
11501095a5dSDimitry Andric }
1164a16efa3SDimitry Andric 
lower(const MachineInstr * MI,MCInst & OutMI) const1174a16efa3SDimitry Andric void AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
118b5630dbaSDimitry Andric   unsigned Opcode = MI->getOpcode();
119eb11fae6SDimitry Andric   const auto *TII = static_cast<const SIInstrInfo*>(ST.getInstrInfo());
1204a16efa3SDimitry Andric 
121b5630dbaSDimitry Andric   // FIXME: Should be able to handle this with emitPseudoExpansionLowering. We
122b5630dbaSDimitry Andric   // need to select it to the subtarget specific version, and there's no way to
123b5630dbaSDimitry Andric   // do that with a single pseudo source operation.
124145449b1SDimitry Andric   if (Opcode == AMDGPU::S_SETPC_B64_return)
125b5630dbaSDimitry Andric     Opcode = AMDGPU::S_SETPC_B64;
126044eb2f6SDimitry Andric   else if (Opcode == AMDGPU::SI_CALL) {
127044eb2f6SDimitry Andric     // SI_CALL is just S_SWAPPC_B64 with an additional operand to track the
128044eb2f6SDimitry Andric     // called function (which we need to remove here).
129044eb2f6SDimitry Andric     OutMI.setOpcode(TII->pseudoToMCOpcode(AMDGPU::S_SWAPPC_B64));
130044eb2f6SDimitry Andric     MCOperand Dest, Src;
131044eb2f6SDimitry Andric     lowerOperand(MI->getOperand(0), Dest);
132044eb2f6SDimitry Andric     lowerOperand(MI->getOperand(1), Src);
133044eb2f6SDimitry Andric     OutMI.addOperand(Dest);
134044eb2f6SDimitry Andric     OutMI.addOperand(Src);
135044eb2f6SDimitry Andric     return;
1367fa27ce4SDimitry Andric   } else if (Opcode == AMDGPU::SI_TCRETURN ||
1377fa27ce4SDimitry Andric              Opcode == AMDGPU::SI_TCRETURN_GFX) {
138044eb2f6SDimitry Andric     // TODO: How to use branch immediate and avoid register+add?
139044eb2f6SDimitry Andric     Opcode = AMDGPU::S_SETPC_B64;
140044eb2f6SDimitry Andric   }
141ec304151SDimitry Andric 
142044eb2f6SDimitry Andric   int MCOpcode = TII->pseudoToMCOpcode(Opcode);
143ec304151SDimitry Andric   if (MCOpcode == -1) {
144044eb2f6SDimitry Andric     LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext();
145ec304151SDimitry Andric     C.emitError("AMDGPUMCInstLower::lower - Pseudo instruction doesn't have "
146ec304151SDimitry Andric                 "a target-specific version: " + Twine(MI->getOpcode()));
147ec304151SDimitry Andric   }
148ec304151SDimitry Andric 
149ec304151SDimitry Andric   OutMI.setOpcode(MCOpcode);
1504a16efa3SDimitry Andric 
1515ca98fd9SDimitry Andric   for (const MachineOperand &MO : MI->explicit_operands()) {
1524a16efa3SDimitry Andric     MCOperand MCOp;
153b915e9e0SDimitry Andric     lowerOperand(MO, MCOp);
1544a16efa3SDimitry Andric     OutMI.addOperand(MCOp);
1554a16efa3SDimitry Andric   }
1561d5ae102SDimitry Andric 
1571d5ae102SDimitry Andric   int FIIdx = AMDGPU::getNamedOperandIdx(MCOpcode, AMDGPU::OpName::fi);
1581d5ae102SDimitry Andric   if (FIIdx >= (int)OutMI.getNumOperands())
1591d5ae102SDimitry Andric     OutMI.addOperand(MCOperand::createImm(0));
1604a16efa3SDimitry Andric }
1614a16efa3SDimitry Andric 
lowerOperand(const MachineOperand & MO,MCOperand & MCOp) const162b915e9e0SDimitry Andric bool AMDGPUAsmPrinter::lowerOperand(const MachineOperand &MO,
163b915e9e0SDimitry Andric                                     MCOperand &MCOp) const {
164eb11fae6SDimitry Andric   const GCNSubtarget &STI = MF->getSubtarget<GCNSubtarget>();
165b915e9e0SDimitry Andric   AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this);
166b915e9e0SDimitry Andric   return MCInstLowering.lowerOperand(MO, MCOp);
167b915e9e0SDimitry Andric }
168b915e9e0SDimitry Andric 
lowerConstant(const Constant * CV)169eb11fae6SDimitry Andric const MCExpr *AMDGPUAsmPrinter::lowerConstant(const Constant *CV) {
170e3b55780SDimitry Andric 
171e3b55780SDimitry Andric   // Intercept LDS variables with known addresses
1727fa27ce4SDimitry Andric   if (const GlobalVariable *GV = dyn_cast<const GlobalVariable>(CV)) {
1737fa27ce4SDimitry Andric     if (std::optional<uint32_t> Address =
1747fa27ce4SDimitry Andric             AMDGPUMachineFunction::getLDSAbsoluteAddress(*GV)) {
1757fa27ce4SDimitry Andric       auto *IntTy = Type::getInt32Ty(CV->getContext());
1767fa27ce4SDimitry Andric       return AsmPrinter::lowerConstant(ConstantInt::get(IntTy, *Address));
177e3b55780SDimitry Andric     }
178e3b55780SDimitry Andric   }
179e3b55780SDimitry Andric 
180eb11fae6SDimitry Andric   if (const MCExpr *E = lowerAddrSpaceCast(TM, CV, OutContext))
181eb11fae6SDimitry Andric     return E;
18271d5a254SDimitry Andric   return AsmPrinter::lowerConstant(CV);
18371d5a254SDimitry Andric }
18471d5a254SDimitry Andric 
emitInstruction(const MachineInstr * MI)185cfca06d7SDimitry Andric void AMDGPUAsmPrinter::emitInstruction(const MachineInstr *MI) {
1861f917f69SDimitry Andric   // FIXME: Enable feature predicate checks once all the test pass.
1871f917f69SDimitry Andric   // AMDGPU_MC::verifyInstructionPredicates(MI->getOpcode(),
1881f917f69SDimitry Andric   //                                        getSubtargetInfo().getFeatureBits());
1891f917f69SDimitry Andric 
190b915e9e0SDimitry Andric   if (emitPseudoExpansionLowering(*OutStreamer, MI))
191b915e9e0SDimitry Andric     return;
192b915e9e0SDimitry Andric 
193eb11fae6SDimitry Andric   const GCNSubtarget &STI = MF->getSubtarget<GCNSubtarget>();
194b915e9e0SDimitry Andric   AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this);
1954a16efa3SDimitry Andric 
1965ca98fd9SDimitry Andric   StringRef Err;
19701095a5dSDimitry Andric   if (!STI.getInstrInfo()->verifyInstruction(*MI, Err)) {
198044eb2f6SDimitry Andric     LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext();
19901095a5dSDimitry Andric     C.emitError("Illegal instruction detected: " + Err);
20071d5a254SDimitry Andric     MI->print(errs());
2015ca98fd9SDimitry Andric   }
20201095a5dSDimitry Andric 
2034a16efa3SDimitry Andric   if (MI->isBundle()) {
2044a16efa3SDimitry Andric     const MachineBasicBlock *MBB = MI->getParent();
205dd58ef01SDimitry Andric     MachineBasicBlock::const_instr_iterator I = ++MI->getIterator();
206dd58ef01SDimitry Andric     while (I != MBB->instr_end() && I->isInsideBundle()) {
207cfca06d7SDimitry Andric       emitInstruction(&*I);
2084a16efa3SDimitry Andric       ++I;
2094a16efa3SDimitry Andric     }
2104a16efa3SDimitry Andric   } else {
211344a3780SDimitry Andric     // We don't want these pseudo instructions encoded. They are
21271d5a254SDimitry Andric     // placeholder terminator instructions and should only be printed as
21371d5a254SDimitry Andric     // comments.
21471d5a254SDimitry Andric     if (MI->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG) {
21501095a5dSDimitry Andric       if (isVerbose())
21671d5a254SDimitry Andric         OutStreamer->emitRawComment(" return to shader part epilog");
21701095a5dSDimitry Andric       return;
21801095a5dSDimitry Andric     }
21901095a5dSDimitry Andric 
220b915e9e0SDimitry Andric     if (MI->getOpcode() == AMDGPU::WAVE_BARRIER) {
221b915e9e0SDimitry Andric       if (isVerbose())
222b915e9e0SDimitry Andric         OutStreamer->emitRawComment(" wave barrier");
223b915e9e0SDimitry Andric       return;
224b915e9e0SDimitry Andric     }
225b915e9e0SDimitry Andric 
226145449b1SDimitry Andric     if (MI->getOpcode() == AMDGPU::SCHED_BARRIER) {
227145449b1SDimitry Andric       if (isVerbose()) {
228145449b1SDimitry Andric         std::string HexString;
229145449b1SDimitry Andric         raw_string_ostream HexStream(HexString);
230145449b1SDimitry Andric         HexStream << format_hex(MI->getOperand(0).getImm(), 10, true);
231145449b1SDimitry Andric         OutStreamer->emitRawComment(" sched_barrier mask(" + HexString + ")");
232145449b1SDimitry Andric       }
233145449b1SDimitry Andric       return;
234145449b1SDimitry Andric     }
235145449b1SDimitry Andric 
236e3b55780SDimitry Andric     if (MI->getOpcode() == AMDGPU::SCHED_GROUP_BARRIER) {
237e3b55780SDimitry Andric       if (isVerbose()) {
238e3b55780SDimitry Andric         std::string HexString;
239e3b55780SDimitry Andric         raw_string_ostream HexStream(HexString);
240e3b55780SDimitry Andric         HexStream << format_hex(MI->getOperand(0).getImm(), 10, true);
241e3b55780SDimitry Andric         OutStreamer->emitRawComment(
242e3b55780SDimitry Andric             " sched_group_barrier mask(" + HexString + ") size(" +
243e3b55780SDimitry Andric             Twine(MI->getOperand(1).getImm()) + ") SyncID(" +
244e3b55780SDimitry Andric             Twine(MI->getOperand(2).getImm()) + ")");
245e3b55780SDimitry Andric       }
246e3b55780SDimitry Andric       return;
247e3b55780SDimitry Andric     }
248e3b55780SDimitry Andric 
249e3b55780SDimitry Andric     if (MI->getOpcode() == AMDGPU::IGLP_OPT) {
250e3b55780SDimitry Andric       if (isVerbose()) {
251e3b55780SDimitry Andric         std::string HexString;
252e3b55780SDimitry Andric         raw_string_ostream HexStream(HexString);
253e3b55780SDimitry Andric         HexStream << format_hex(MI->getOperand(0).getImm(), 10, true);
254e3b55780SDimitry Andric         OutStreamer->emitRawComment(" iglp_opt mask(" + HexString + ")");
255e3b55780SDimitry Andric       }
256e3b55780SDimitry Andric       return;
257e3b55780SDimitry Andric     }
258e3b55780SDimitry Andric 
25912f3ca4cSDimitry Andric     if (MI->getOpcode() == AMDGPU::SI_MASKED_UNREACHABLE) {
26012f3ca4cSDimitry Andric       if (isVerbose())
26112f3ca4cSDimitry Andric         OutStreamer->emitRawComment(" divergent unreachable");
26212f3ca4cSDimitry Andric       return;
26312f3ca4cSDimitry Andric     }
26412f3ca4cSDimitry Andric 
265c0981da4SDimitry Andric     if (MI->isMetaInstruction()) {
266c0981da4SDimitry Andric       if (isVerbose())
267c0981da4SDimitry Andric         OutStreamer->emitRawComment(" meta instruction");
268c0981da4SDimitry Andric       return;
269c0981da4SDimitry Andric     }
270c0981da4SDimitry Andric 
2714a16efa3SDimitry Andric     MCInst TmpInst;
2724a16efa3SDimitry Andric     MCInstLowering.lower(MI, TmpInst);
2735a5ac124SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
274f8af5cf6SDimitry Andric 
275d8e91e46SDimitry Andric #ifdef EXPENSIVE_CHECKS
276c0981da4SDimitry Andric     // Check getInstSizeInBytes on explicitly specified CPUs (it cannot
277d8e91e46SDimitry Andric     // work correctly for the generic CPU).
278d8e91e46SDimitry Andric     //
279d8e91e46SDimitry Andric     // The isPseudo check really shouldn't be here, but unfortunately there are
280d8e91e46SDimitry Andric     // some negative lit tests that depend on being able to continue through
281d8e91e46SDimitry Andric     // here even when pseudo instructions haven't been lowered.
282b60736ecSDimitry Andric     //
283b60736ecSDimitry Andric     // We also overestimate branch sizes with the offset bug.
284b60736ecSDimitry Andric     if (!MI->isPseudo() && STI.isCPUStringValid(STI.getCPU()) &&
285b60736ecSDimitry Andric         (!STI.hasOffset3fBug() || !MI->isBranch())) {
286d8e91e46SDimitry Andric       SmallVector<MCFixup, 4> Fixups;
287d8e91e46SDimitry Andric       SmallVector<char, 16> CodeBytes;
288d8e91e46SDimitry Andric 
2897fa27ce4SDimitry Andric       std::unique_ptr<MCCodeEmitter> InstEmitter(createAMDGPUMCCodeEmitter(
290145449b1SDimitry Andric           *STI.getInstrInfo(), OutContext));
2917fa27ce4SDimitry Andric       InstEmitter->encodeInstruction(TmpInst, CodeBytes, Fixups, STI);
292d8e91e46SDimitry Andric 
293d8e91e46SDimitry Andric       assert(CodeBytes.size() == STI.getInstrInfo()->getInstSizeInBytes(*MI));
294d8e91e46SDimitry Andric     }
295d8e91e46SDimitry Andric #endif
296d8e91e46SDimitry Andric 
297e6d15924SDimitry Andric     if (DumpCodeInstEmitter) {
298e6d15924SDimitry Andric       // Disassemble instruction/operands to text
299f8af5cf6SDimitry Andric       DisasmLines.resize(DisasmLines.size() + 1);
300f8af5cf6SDimitry Andric       std::string &DisasmLine = DisasmLines.back();
301f8af5cf6SDimitry Andric       raw_string_ostream DisasmStream(DisasmLine);
302f8af5cf6SDimitry Andric 
303e6d15924SDimitry Andric       AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *STI.getInstrInfo(),
30401095a5dSDimitry Andric                                     *STI.getRegisterInfo());
305706b4fc4SDimitry Andric       InstPrinter.printInst(&TmpInst, 0, StringRef(), STI, DisasmStream);
306f8af5cf6SDimitry Andric 
307f8af5cf6SDimitry Andric       // Disassemble instruction/operands to hex representation.
308f8af5cf6SDimitry Andric       SmallVector<MCFixup, 4> Fixups;
309f8af5cf6SDimitry Andric       SmallVector<char, 16> CodeBytes;
310f8af5cf6SDimitry Andric 
311e6d15924SDimitry Andric       DumpCodeInstEmitter->encodeInstruction(
3127fa27ce4SDimitry Andric           TmpInst, CodeBytes, Fixups, MF->getSubtarget<MCSubtargetInfo>());
313f8af5cf6SDimitry Andric       HexLines.resize(HexLines.size() + 1);
314f8af5cf6SDimitry Andric       std::string &HexLine = HexLines.back();
315f8af5cf6SDimitry Andric       raw_string_ostream HexStream(HexLine);
316f8af5cf6SDimitry Andric 
317f8af5cf6SDimitry Andric       for (size_t i = 0; i < CodeBytes.size(); i += 4) {
318f8af5cf6SDimitry Andric         unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i];
319f8af5cf6SDimitry Andric         HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord);
320f8af5cf6SDimitry Andric       }
321f8af5cf6SDimitry Andric 
322f8af5cf6SDimitry Andric       DisasmStream.flush();
323f8af5cf6SDimitry Andric       DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size());
324f8af5cf6SDimitry Andric     }
3254a16efa3SDimitry Andric   }
3264a16efa3SDimitry Andric }
327