10b57cec5SDimitry Andric //===- AMDGPUMCInstLower.cpp - Lower AMDGPU MachineInstr to an MCInst -----===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// Code to lower AMDGPU MachineInstrs to their corresponding MCInst. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric 15349cc55cSDimitry Andric #include "AMDGPUMCInstLower.h" 16*06c3fb27SDimitry Andric #include "AMDGPU.h" 170b57cec5SDimitry Andric #include "AMDGPUAsmPrinter.h" 18bdd1243dSDimitry Andric #include "AMDGPUMachineFunction.h" 190b57cec5SDimitry Andric #include "AMDGPUTargetMachine.h" 200b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUInstPrinter.h" 210b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 240b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 250b57cec5SDimitry Andric #include "llvm/IR/Function.h" 260b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 300b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 310b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h" 320b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 340b57cec5SDimitry Andric #include "llvm/Support/Format.h" 350b57cec5SDimitry Andric #include <algorithm> 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace llvm; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric #include "AMDGPUGenMCPseudoLowering.inc" 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric AMDGPUMCInstLower::AMDGPUMCInstLower(MCContext &ctx, 420b57cec5SDimitry Andric const TargetSubtargetInfo &st, 430b57cec5SDimitry Andric const AsmPrinter &ap): 440b57cec5SDimitry Andric Ctx(ctx), ST(st), AP(ap) { } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind getVariantKind(unsigned MOFlags) { 470b57cec5SDimitry Andric switch (MOFlags) { 480b57cec5SDimitry Andric default: 490b57cec5SDimitry Andric return MCSymbolRefExpr::VK_None; 500b57cec5SDimitry Andric case SIInstrInfo::MO_GOTPCREL: 510b57cec5SDimitry Andric return MCSymbolRefExpr::VK_GOTPCREL; 520b57cec5SDimitry Andric case SIInstrInfo::MO_GOTPCREL32_LO: 530b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_LO; 540b57cec5SDimitry Andric case SIInstrInfo::MO_GOTPCREL32_HI: 550b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_HI; 560b57cec5SDimitry Andric case SIInstrInfo::MO_REL32_LO: 570b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_REL32_LO; 580b57cec5SDimitry Andric case SIInstrInfo::MO_REL32_HI: 590b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_REL32_HI; 600b57cec5SDimitry Andric case SIInstrInfo::MO_ABS32_LO: 610b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_ABS32_LO; 620b57cec5SDimitry Andric case SIInstrInfo::MO_ABS32_HI: 630b57cec5SDimitry Andric return MCSymbolRefExpr::VK_AMDGPU_ABS32_HI; 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric bool AMDGPUMCInstLower::lowerOperand(const MachineOperand &MO, 680b57cec5SDimitry Andric MCOperand &MCOp) const { 690b57cec5SDimitry Andric switch (MO.getType()) { 700b57cec5SDimitry Andric default: 71fe6060f1SDimitry Andric break; 720b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 730b57cec5SDimitry Andric MCOp = MCOperand::createImm(MO.getImm()); 740b57cec5SDimitry Andric return true; 750b57cec5SDimitry Andric case MachineOperand::MO_Register: 760b57cec5SDimitry Andric MCOp = MCOperand::createReg(AMDGPU::getMCReg(MO.getReg(), ST)); 770b57cec5SDimitry Andric return true; 78fe6060f1SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 790b57cec5SDimitry Andric MCOp = MCOperand::createExpr( 800b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); 810b57cec5SDimitry Andric return true; 820b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: { 830b57cec5SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 840b57cec5SDimitry Andric SmallString<128> SymbolName; 850b57cec5SDimitry Andric AP.getNameWithPrefix(SymbolName, GV); 860b57cec5SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(SymbolName); 870b57cec5SDimitry Andric const MCExpr *Expr = 880b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, getVariantKind(MO.getTargetFlags()),Ctx); 890b57cec5SDimitry Andric int64_t Offset = MO.getOffset(); 900b57cec5SDimitry Andric if (Offset != 0) { 910b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, 920b57cec5SDimitry Andric MCConstantExpr::create(Offset, Ctx), Ctx); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric MCOp = MCOperand::createExpr(Expr); 950b57cec5SDimitry Andric return true; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: { 980b57cec5SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(StringRef(MO.getSymbolName())); 990b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx); 1000b57cec5SDimitry Andric MCOp = MCOperand::createExpr(Expr); 1010b57cec5SDimitry Andric return true; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 1040b57cec5SDimitry Andric // Regmasks are like implicit defs. 1050b57cec5SDimitry Andric return false; 106fe6060f1SDimitry Andric case MachineOperand::MO_MCSymbol: 107fe6060f1SDimitry Andric if (MO.getTargetFlags() == SIInstrInfo::MO_FAR_BRANCH_OFFSET) { 108fe6060f1SDimitry Andric MCSymbol *Sym = MO.getMCSymbol(); 109fe6060f1SDimitry Andric MCOp = MCOperand::createExpr(Sym->getVariableValue()); 110fe6060f1SDimitry Andric return true; 1110b57cec5SDimitry Andric } 112fe6060f1SDimitry Andric break; 113fe6060f1SDimitry Andric } 114fe6060f1SDimitry Andric llvm_unreachable("unknown operand type"); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric void AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { 1180b57cec5SDimitry Andric unsigned Opcode = MI->getOpcode(); 1190b57cec5SDimitry Andric const auto *TII = static_cast<const SIInstrInfo*>(ST.getInstrInfo()); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // FIXME: Should be able to handle this with emitPseudoExpansionLowering. We 1220b57cec5SDimitry Andric // need to select it to the subtarget specific version, and there's no way to 1230b57cec5SDimitry Andric // do that with a single pseudo source operation. 12481ad6265SDimitry Andric if (Opcode == AMDGPU::S_SETPC_B64_return) 1250b57cec5SDimitry Andric Opcode = AMDGPU::S_SETPC_B64; 1260b57cec5SDimitry Andric else if (Opcode == AMDGPU::SI_CALL) { 1270b57cec5SDimitry Andric // SI_CALL is just S_SWAPPC_B64 with an additional operand to track the 1280b57cec5SDimitry Andric // called function (which we need to remove here). 1290b57cec5SDimitry Andric OutMI.setOpcode(TII->pseudoToMCOpcode(AMDGPU::S_SWAPPC_B64)); 1300b57cec5SDimitry Andric MCOperand Dest, Src; 1310b57cec5SDimitry Andric lowerOperand(MI->getOperand(0), Dest); 1320b57cec5SDimitry Andric lowerOperand(MI->getOperand(1), Src); 1330b57cec5SDimitry Andric OutMI.addOperand(Dest); 1340b57cec5SDimitry Andric OutMI.addOperand(Src); 1350b57cec5SDimitry Andric return; 136*06c3fb27SDimitry Andric } else if (Opcode == AMDGPU::SI_TCRETURN || 137*06c3fb27SDimitry Andric Opcode == AMDGPU::SI_TCRETURN_GFX) { 1380b57cec5SDimitry Andric // TODO: How to use branch immediate and avoid register+add? 1390b57cec5SDimitry Andric Opcode = AMDGPU::S_SETPC_B64; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric int MCOpcode = TII->pseudoToMCOpcode(Opcode); 1430b57cec5SDimitry Andric if (MCOpcode == -1) { 1440b57cec5SDimitry Andric LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext(); 1450b57cec5SDimitry Andric C.emitError("AMDGPUMCInstLower::lower - Pseudo instruction doesn't have " 1460b57cec5SDimitry Andric "a target-specific version: " + Twine(MI->getOpcode())); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric OutMI.setOpcode(MCOpcode); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric for (const MachineOperand &MO : MI->explicit_operands()) { 1520b57cec5SDimitry Andric MCOperand MCOp; 1530b57cec5SDimitry Andric lowerOperand(MO, MCOp); 1540b57cec5SDimitry Andric OutMI.addOperand(MCOp); 1550b57cec5SDimitry Andric } 1568bcb0991SDimitry Andric 1578bcb0991SDimitry Andric int FIIdx = AMDGPU::getNamedOperandIdx(MCOpcode, AMDGPU::OpName::fi); 1588bcb0991SDimitry Andric if (FIIdx >= (int)OutMI.getNumOperands()) 1598bcb0991SDimitry Andric OutMI.addOperand(MCOperand::createImm(0)); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric bool AMDGPUAsmPrinter::lowerOperand(const MachineOperand &MO, 1630b57cec5SDimitry Andric MCOperand &MCOp) const { 1640b57cec5SDimitry Andric const GCNSubtarget &STI = MF->getSubtarget<GCNSubtarget>(); 1650b57cec5SDimitry Andric AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this); 1660b57cec5SDimitry Andric return MCInstLowering.lowerOperand(MO, MCOp); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric const MCExpr *AMDGPUAsmPrinter::lowerConstant(const Constant *CV) { 170bdd1243dSDimitry Andric 171bdd1243dSDimitry Andric // Intercept LDS variables with known addresses 172*06c3fb27SDimitry Andric if (const GlobalVariable *GV = dyn_cast<const GlobalVariable>(CV)) { 173*06c3fb27SDimitry Andric if (std::optional<uint32_t> Address = 174*06c3fb27SDimitry Andric AMDGPUMachineFunction::getLDSAbsoluteAddress(*GV)) { 175*06c3fb27SDimitry Andric auto *IntTy = Type::getInt32Ty(CV->getContext()); 176*06c3fb27SDimitry Andric return AsmPrinter::lowerConstant(ConstantInt::get(IntTy, *Address)); 177bdd1243dSDimitry Andric } 178bdd1243dSDimitry Andric } 179bdd1243dSDimitry Andric 1800b57cec5SDimitry Andric if (const MCExpr *E = lowerAddrSpaceCast(TM, CV, OutContext)) 1810b57cec5SDimitry Andric return E; 1820b57cec5SDimitry Andric return AsmPrinter::lowerConstant(CV); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1855ffd83dbSDimitry Andric void AMDGPUAsmPrinter::emitInstruction(const MachineInstr *MI) { 186753f127fSDimitry Andric // FIXME: Enable feature predicate checks once all the test pass. 187753f127fSDimitry Andric // AMDGPU_MC::verifyInstructionPredicates(MI->getOpcode(), 188753f127fSDimitry Andric // getSubtargetInfo().getFeatureBits()); 189753f127fSDimitry Andric 1900b57cec5SDimitry Andric if (emitPseudoExpansionLowering(*OutStreamer, MI)) 1910b57cec5SDimitry Andric return; 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric const GCNSubtarget &STI = MF->getSubtarget<GCNSubtarget>(); 1940b57cec5SDimitry Andric AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric StringRef Err; 1970b57cec5SDimitry Andric if (!STI.getInstrInfo()->verifyInstruction(*MI, Err)) { 1980b57cec5SDimitry Andric LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext(); 1990b57cec5SDimitry Andric C.emitError("Illegal instruction detected: " + Err); 2000b57cec5SDimitry Andric MI->print(errs()); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric if (MI->isBundle()) { 2040b57cec5SDimitry Andric const MachineBasicBlock *MBB = MI->getParent(); 2050b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator I = ++MI->getIterator(); 2060b57cec5SDimitry Andric while (I != MBB->instr_end() && I->isInsideBundle()) { 2075ffd83dbSDimitry Andric emitInstruction(&*I); 2080b57cec5SDimitry Andric ++I; 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric } else { 211fe6060f1SDimitry Andric // We don't want these pseudo instructions encoded. They are 2120b57cec5SDimitry Andric // placeholder terminator instructions and should only be printed as 2130b57cec5SDimitry Andric // comments. 2140b57cec5SDimitry Andric if (MI->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG) { 2150b57cec5SDimitry Andric if (isVerbose()) 2160b57cec5SDimitry Andric OutStreamer->emitRawComment(" return to shader part epilog"); 2170b57cec5SDimitry Andric return; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric if (MI->getOpcode() == AMDGPU::WAVE_BARRIER) { 2210b57cec5SDimitry Andric if (isVerbose()) 2220b57cec5SDimitry Andric OutStreamer->emitRawComment(" wave barrier"); 2230b57cec5SDimitry Andric return; 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 22681ad6265SDimitry Andric if (MI->getOpcode() == AMDGPU::SCHED_BARRIER) { 22781ad6265SDimitry Andric if (isVerbose()) { 22881ad6265SDimitry Andric std::string HexString; 22981ad6265SDimitry Andric raw_string_ostream HexStream(HexString); 23081ad6265SDimitry Andric HexStream << format_hex(MI->getOperand(0).getImm(), 10, true); 23181ad6265SDimitry Andric OutStreamer->emitRawComment(" sched_barrier mask(" + HexString + ")"); 23281ad6265SDimitry Andric } 23381ad6265SDimitry Andric return; 23481ad6265SDimitry Andric } 23581ad6265SDimitry Andric 236bdd1243dSDimitry Andric if (MI->getOpcode() == AMDGPU::SCHED_GROUP_BARRIER) { 237bdd1243dSDimitry Andric if (isVerbose()) { 238bdd1243dSDimitry Andric std::string HexString; 239bdd1243dSDimitry Andric raw_string_ostream HexStream(HexString); 240bdd1243dSDimitry Andric HexStream << format_hex(MI->getOperand(0).getImm(), 10, true); 241bdd1243dSDimitry Andric OutStreamer->emitRawComment( 242bdd1243dSDimitry Andric " sched_group_barrier mask(" + HexString + ") size(" + 243bdd1243dSDimitry Andric Twine(MI->getOperand(1).getImm()) + ") SyncID(" + 244bdd1243dSDimitry Andric Twine(MI->getOperand(2).getImm()) + ")"); 245bdd1243dSDimitry Andric } 246bdd1243dSDimitry Andric return; 247bdd1243dSDimitry Andric } 248bdd1243dSDimitry Andric 249bdd1243dSDimitry Andric if (MI->getOpcode() == AMDGPU::IGLP_OPT) { 250bdd1243dSDimitry Andric if (isVerbose()) { 251bdd1243dSDimitry Andric std::string HexString; 252bdd1243dSDimitry Andric raw_string_ostream HexStream(HexString); 253bdd1243dSDimitry Andric HexStream << format_hex(MI->getOperand(0).getImm(), 10, true); 254bdd1243dSDimitry Andric OutStreamer->emitRawComment(" iglp_opt mask(" + HexString + ")"); 255bdd1243dSDimitry Andric } 256bdd1243dSDimitry Andric return; 257bdd1243dSDimitry Andric } 258bdd1243dSDimitry Andric 2590b57cec5SDimitry Andric if (MI->getOpcode() == AMDGPU::SI_MASKED_UNREACHABLE) { 2600b57cec5SDimitry Andric if (isVerbose()) 2610b57cec5SDimitry Andric OutStreamer->emitRawComment(" divergent unreachable"); 2620b57cec5SDimitry Andric return; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 265349cc55cSDimitry Andric if (MI->isMetaInstruction()) { 266349cc55cSDimitry Andric if (isVerbose()) 267349cc55cSDimitry Andric OutStreamer->emitRawComment(" meta instruction"); 268349cc55cSDimitry Andric return; 269349cc55cSDimitry Andric } 270349cc55cSDimitry Andric 2710b57cec5SDimitry Andric MCInst TmpInst; 2720b57cec5SDimitry Andric MCInstLowering.lower(MI, TmpInst); 2730b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 276349cc55cSDimitry Andric // Check getInstSizeInBytes on explicitly specified CPUs (it cannot 2770b57cec5SDimitry Andric // work correctly for the generic CPU). 2780b57cec5SDimitry Andric // 2790b57cec5SDimitry Andric // The isPseudo check really shouldn't be here, but unfortunately there are 2800b57cec5SDimitry Andric // some negative lit tests that depend on being able to continue through 2810b57cec5SDimitry Andric // here even when pseudo instructions haven't been lowered. 282e8d8bef9SDimitry Andric // 283e8d8bef9SDimitry Andric // We also overestimate branch sizes with the offset bug. 284e8d8bef9SDimitry Andric if (!MI->isPseudo() && STI.isCPUStringValid(STI.getCPU()) && 285e8d8bef9SDimitry Andric (!STI.hasOffset3fBug() || !MI->isBranch())) { 2860b57cec5SDimitry Andric SmallVector<MCFixup, 4> Fixups; 2870b57cec5SDimitry Andric SmallVector<char, 16> CodeBytes; 2880b57cec5SDimitry Andric 289*06c3fb27SDimitry Andric std::unique_ptr<MCCodeEmitter> InstEmitter(createAMDGPUMCCodeEmitter( 29081ad6265SDimitry Andric *STI.getInstrInfo(), OutContext)); 291*06c3fb27SDimitry Andric InstEmitter->encodeInstruction(TmpInst, CodeBytes, Fixups, STI); 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric assert(CodeBytes.size() == STI.getInstrInfo()->getInstSizeInBytes(*MI)); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric #endif 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric if (DumpCodeInstEmitter) { 2980b57cec5SDimitry Andric // Disassemble instruction/operands to text 2990b57cec5SDimitry Andric DisasmLines.resize(DisasmLines.size() + 1); 3000b57cec5SDimitry Andric std::string &DisasmLine = DisasmLines.back(); 3010b57cec5SDimitry Andric raw_string_ostream DisasmStream(DisasmLine); 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *STI.getInstrInfo(), 3040b57cec5SDimitry Andric *STI.getRegisterInfo()); 305480093f4SDimitry Andric InstPrinter.printInst(&TmpInst, 0, StringRef(), STI, DisasmStream); 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric // Disassemble instruction/operands to hex representation. 3080b57cec5SDimitry Andric SmallVector<MCFixup, 4> Fixups; 3090b57cec5SDimitry Andric SmallVector<char, 16> CodeBytes; 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric DumpCodeInstEmitter->encodeInstruction( 312*06c3fb27SDimitry Andric TmpInst, CodeBytes, Fixups, MF->getSubtarget<MCSubtargetInfo>()); 3130b57cec5SDimitry Andric HexLines.resize(HexLines.size() + 1); 3140b57cec5SDimitry Andric std::string &HexLine = HexLines.back(); 3150b57cec5SDimitry Andric raw_string_ostream HexStream(HexLine); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric for (size_t i = 0; i < CodeBytes.size(); i += 4) { 3180b57cec5SDimitry Andric unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i]; 3190b57cec5SDimitry Andric HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord); 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric DisasmStream.flush(); 3230b57cec5SDimitry Andric DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size()); 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric } 327