18f0fd8f6SDimitry Andric //===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly printer --------------------===// 28f0fd8f6SDimitry Andric // 38f0fd8f6SDimitry Andric // The LLVM Compiler Infrastructure 48f0fd8f6SDimitry Andric // 58f0fd8f6SDimitry Andric // This file is distributed under the University of Illinois Open Source 68f0fd8f6SDimitry Andric // License. See LICENSE.TXT for details. 78f0fd8f6SDimitry Andric // 88f0fd8f6SDimitry Andric //===----------------------------------------------------------------------===// 98f0fd8f6SDimitry Andric // 108f0fd8f6SDimitry Andric /// \file 118f0fd8f6SDimitry Andric /// 128f0fd8f6SDimitry Andric /// The AMDGPUAsmPrinter is used to print both assembly string and also binary 138f0fd8f6SDimitry Andric /// code. When passed an MCAsmStreamer it prints assembly and when passed 148f0fd8f6SDimitry Andric /// an MCObjectStreamer it outputs binary code. 158f0fd8f6SDimitry Andric // 168f0fd8f6SDimitry Andric //===----------------------------------------------------------------------===// 178f0fd8f6SDimitry Andric // 188f0fd8f6SDimitry Andric 198f0fd8f6SDimitry Andric #include "AMDGPUAsmPrinter.h" 208f0fd8f6SDimitry Andric #include "InstPrinter/AMDGPUInstPrinter.h" 218f0fd8f6SDimitry Andric #include "AMDGPU.h" 228f0fd8f6SDimitry Andric #include "AMDKernelCodeT.h" 238f0fd8f6SDimitry Andric #include "AMDGPUSubtarget.h" 248f0fd8f6SDimitry Andric #include "R600Defines.h" 258f0fd8f6SDimitry Andric #include "R600MachineFunctionInfo.h" 268f0fd8f6SDimitry Andric #include "R600RegisterInfo.h" 278f0fd8f6SDimitry Andric #include "SIDefines.h" 288f0fd8f6SDimitry Andric #include "SIMachineFunctionInfo.h" 298f0fd8f6SDimitry Andric #include "SIRegisterInfo.h" 308f0fd8f6SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 318f0fd8f6SDimitry Andric #include "llvm/MC/MCContext.h" 328f0fd8f6SDimitry Andric #include "llvm/MC/MCSectionELF.h" 338f0fd8f6SDimitry Andric #include "llvm/MC/MCStreamer.h" 348f0fd8f6SDimitry Andric #include "llvm/Support/ELF.h" 358f0fd8f6SDimitry Andric #include "llvm/Support/MathExtras.h" 368f0fd8f6SDimitry Andric #include "llvm/Support/TargetRegistry.h" 378f0fd8f6SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 388f0fd8f6SDimitry Andric 398f0fd8f6SDimitry Andric using namespace llvm; 408f0fd8f6SDimitry Andric 418f0fd8f6SDimitry Andric // TODO: This should get the default rounding mode from the kernel. We just set 428f0fd8f6SDimitry Andric // the default here, but this could change if the OpenCL rounding mode pragmas 438f0fd8f6SDimitry Andric // are used. 448f0fd8f6SDimitry Andric // 458f0fd8f6SDimitry Andric // The denormal mode here should match what is reported by the OpenCL runtime 468f0fd8f6SDimitry Andric // for the CL_FP_DENORM bit from CL_DEVICE_{HALF|SINGLE|DOUBLE}_FP_CONFIG, but 478f0fd8f6SDimitry Andric // can also be override to flush with the -cl-denorms-are-zero compiler flag. 488f0fd8f6SDimitry Andric // 498f0fd8f6SDimitry Andric // AMD OpenCL only sets flush none and reports CL_FP_DENORM for double 508f0fd8f6SDimitry Andric // precision, and leaves single precision to flush all and does not report 518f0fd8f6SDimitry Andric // CL_FP_DENORM for CL_DEVICE_SINGLE_FP_CONFIG. Mesa's OpenCL currently reports 528f0fd8f6SDimitry Andric // CL_FP_DENORM for both. 538f0fd8f6SDimitry Andric // 548f0fd8f6SDimitry Andric // FIXME: It seems some instructions do not support single precision denormals 558f0fd8f6SDimitry Andric // regardless of the mode (exp_*_f32, rcp_*_f32, rsq_*_f32, rsq_*f32, sqrt_f32, 568f0fd8f6SDimitry Andric // and sin_f32, cos_f32 on most parts). 578f0fd8f6SDimitry Andric 588f0fd8f6SDimitry Andric // We want to use these instructions, and using fp32 denormals also causes 598f0fd8f6SDimitry Andric // instructions to run at the double precision rate for the device so it's 608f0fd8f6SDimitry Andric // probably best to just report no single precision denormals. 618f0fd8f6SDimitry Andric static uint32_t getFPMode(const MachineFunction &F) { 628f0fd8f6SDimitry Andric const AMDGPUSubtarget& ST = F.getSubtarget<AMDGPUSubtarget>(); 638f0fd8f6SDimitry Andric // TODO: Is there any real use for the flush in only / flush out only modes? 648f0fd8f6SDimitry Andric 658f0fd8f6SDimitry Andric uint32_t FP32Denormals = 668f0fd8f6SDimitry Andric ST.hasFP32Denormals() ? FP_DENORM_FLUSH_NONE : FP_DENORM_FLUSH_IN_FLUSH_OUT; 678f0fd8f6SDimitry Andric 688f0fd8f6SDimitry Andric uint32_t FP64Denormals = 698f0fd8f6SDimitry Andric ST.hasFP64Denormals() ? FP_DENORM_FLUSH_NONE : FP_DENORM_FLUSH_IN_FLUSH_OUT; 708f0fd8f6SDimitry Andric 718f0fd8f6SDimitry Andric return FP_ROUND_MODE_SP(FP_ROUND_ROUND_TO_NEAREST) | 728f0fd8f6SDimitry Andric FP_ROUND_MODE_DP(FP_ROUND_ROUND_TO_NEAREST) | 738f0fd8f6SDimitry Andric FP_DENORM_MODE_SP(FP32Denormals) | 748f0fd8f6SDimitry Andric FP_DENORM_MODE_DP(FP64Denormals); 758f0fd8f6SDimitry Andric } 768f0fd8f6SDimitry Andric 778f0fd8f6SDimitry Andric static AsmPrinter * 788f0fd8f6SDimitry Andric createAMDGPUAsmPrinterPass(TargetMachine &tm, 798f0fd8f6SDimitry Andric std::unique_ptr<MCStreamer> &&Streamer) { 808f0fd8f6SDimitry Andric return new AMDGPUAsmPrinter(tm, std::move(Streamer)); 818f0fd8f6SDimitry Andric } 828f0fd8f6SDimitry Andric 838f0fd8f6SDimitry Andric extern "C" void LLVMInitializeAMDGPUAsmPrinter() { 848f0fd8f6SDimitry Andric TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass); 858f0fd8f6SDimitry Andric TargetRegistry::RegisterAsmPrinter(TheGCNTarget, createAMDGPUAsmPrinterPass); 868f0fd8f6SDimitry Andric } 878f0fd8f6SDimitry Andric 888f0fd8f6SDimitry Andric AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM, 898f0fd8f6SDimitry Andric std::unique_ptr<MCStreamer> Streamer) 908f0fd8f6SDimitry Andric : AsmPrinter(TM, std::move(Streamer)) {} 918f0fd8f6SDimitry Andric 928f0fd8f6SDimitry Andric void AMDGPUAsmPrinter::EmitEndOfAsmFile(Module &M) { 938f0fd8f6SDimitry Andric 948f0fd8f6SDimitry Andric // This label is used to mark the end of the .text section. 958f0fd8f6SDimitry Andric const TargetLoweringObjectFile &TLOF = getObjFileLowering(); 968f0fd8f6SDimitry Andric OutStreamer->SwitchSection(TLOF.getTextSection()); 978f0fd8f6SDimitry Andric MCSymbol *EndOfTextLabel = 988f0fd8f6SDimitry Andric OutContext.getOrCreateSymbol(StringRef(END_OF_TEXT_LABEL_NAME)); 998f0fd8f6SDimitry Andric OutStreamer->EmitLabel(EndOfTextLabel); 1008f0fd8f6SDimitry Andric } 1018f0fd8f6SDimitry Andric 1028f0fd8f6SDimitry Andric bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 1038f0fd8f6SDimitry Andric 1048f0fd8f6SDimitry Andric // The starting address of all shader programs must be 256 bytes aligned. 1058f0fd8f6SDimitry Andric MF.setAlignment(8); 1068f0fd8f6SDimitry Andric 1078f0fd8f6SDimitry Andric SetupMachineFunction(MF); 1088f0fd8f6SDimitry Andric 1098f0fd8f6SDimitry Andric MCContext &Context = getObjFileLowering().getContext(); 1108f0fd8f6SDimitry Andric MCSectionELF *ConfigSection = 1118f0fd8f6SDimitry Andric Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0); 1128f0fd8f6SDimitry Andric OutStreamer->SwitchSection(ConfigSection); 1138f0fd8f6SDimitry Andric 1148f0fd8f6SDimitry Andric const AMDGPUSubtarget &STM = MF.getSubtarget<AMDGPUSubtarget>(); 1158f0fd8f6SDimitry Andric SIProgramInfo KernelInfo; 1168f0fd8f6SDimitry Andric if (STM.isAmdHsaOS()) { 1178f0fd8f6SDimitry Andric getSIProgramInfo(KernelInfo, MF); 1188f0fd8f6SDimitry Andric EmitAmdKernelCodeT(MF, KernelInfo); 1198f0fd8f6SDimitry Andric OutStreamer->EmitCodeAlignment(2 << (MF.getAlignment() - 1)); 1208f0fd8f6SDimitry Andric } else if (STM.getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) { 1218f0fd8f6SDimitry Andric getSIProgramInfo(KernelInfo, MF); 1228f0fd8f6SDimitry Andric EmitProgramInfoSI(MF, KernelInfo); 1238f0fd8f6SDimitry Andric } else { 1248f0fd8f6SDimitry Andric EmitProgramInfoR600(MF); 1258f0fd8f6SDimitry Andric } 1268f0fd8f6SDimitry Andric 1278f0fd8f6SDimitry Andric DisasmLines.clear(); 1288f0fd8f6SDimitry Andric HexLines.clear(); 1298f0fd8f6SDimitry Andric DisasmLineMaxLen = 0; 1308f0fd8f6SDimitry Andric 1318f0fd8f6SDimitry Andric EmitFunctionBody(); 1328f0fd8f6SDimitry Andric 1338f0fd8f6SDimitry Andric if (isVerbose()) { 1348f0fd8f6SDimitry Andric MCSectionELF *CommentSection = 1358f0fd8f6SDimitry Andric Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0); 1368f0fd8f6SDimitry Andric OutStreamer->SwitchSection(CommentSection); 1378f0fd8f6SDimitry Andric 1388f0fd8f6SDimitry Andric if (STM.getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) { 1398f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" Kernel info:", false); 1408f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" codeLenInByte = " + Twine(KernelInfo.CodeLen), 1418f0fd8f6SDimitry Andric false); 1428f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" NumSgprs: " + Twine(KernelInfo.NumSGPR), 1438f0fd8f6SDimitry Andric false); 1448f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" NumVgprs: " + Twine(KernelInfo.NumVGPR), 1458f0fd8f6SDimitry Andric false); 1468f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" FloatMode: " + Twine(KernelInfo.FloatMode), 1478f0fd8f6SDimitry Andric false); 1488f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" IeeeMode: " + Twine(KernelInfo.IEEEMode), 1498f0fd8f6SDimitry Andric false); 1508f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" ScratchSize: " + Twine(KernelInfo.ScratchSize), 1518f0fd8f6SDimitry Andric false); 1528f0fd8f6SDimitry Andric } else { 1538f0fd8f6SDimitry Andric R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>(); 1548f0fd8f6SDimitry Andric OutStreamer->emitRawComment( 1558f0fd8f6SDimitry Andric Twine("SQ_PGM_RESOURCES:STACK_SIZE = " + Twine(MFI->StackSize))); 1568f0fd8f6SDimitry Andric } 1578f0fd8f6SDimitry Andric } 1588f0fd8f6SDimitry Andric 1598f0fd8f6SDimitry Andric if (STM.dumpCode()) { 1608f0fd8f6SDimitry Andric 1618f0fd8f6SDimitry Andric OutStreamer->SwitchSection( 1628f0fd8f6SDimitry Andric Context.getELFSection(".AMDGPU.disasm", ELF::SHT_NOTE, 0)); 1638f0fd8f6SDimitry Andric 1648f0fd8f6SDimitry Andric for (size_t i = 0; i < DisasmLines.size(); ++i) { 1658f0fd8f6SDimitry Andric std::string Comment(DisasmLineMaxLen - DisasmLines[i].size(), ' '); 1668f0fd8f6SDimitry Andric Comment += " ; " + HexLines[i] + "\n"; 1678f0fd8f6SDimitry Andric 1688f0fd8f6SDimitry Andric OutStreamer->EmitBytes(StringRef(DisasmLines[i])); 1698f0fd8f6SDimitry Andric OutStreamer->EmitBytes(StringRef(Comment)); 1708f0fd8f6SDimitry Andric } 1718f0fd8f6SDimitry Andric } 1728f0fd8f6SDimitry Andric 1738f0fd8f6SDimitry Andric return false; 1748f0fd8f6SDimitry Andric } 1758f0fd8f6SDimitry Andric 1768f0fd8f6SDimitry Andric void AMDGPUAsmPrinter::EmitProgramInfoR600(const MachineFunction &MF) { 1778f0fd8f6SDimitry Andric unsigned MaxGPR = 0; 1788f0fd8f6SDimitry Andric bool killPixel = false; 1798f0fd8f6SDimitry Andric const AMDGPUSubtarget &STM = MF.getSubtarget<AMDGPUSubtarget>(); 1808f0fd8f6SDimitry Andric const R600RegisterInfo *RI = 1818f0fd8f6SDimitry Andric static_cast<const R600RegisterInfo *>(STM.getRegisterInfo()); 1828f0fd8f6SDimitry Andric const R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>(); 1838f0fd8f6SDimitry Andric 1848f0fd8f6SDimitry Andric for (const MachineBasicBlock &MBB : MF) { 1858f0fd8f6SDimitry Andric for (const MachineInstr &MI : MBB) { 1868f0fd8f6SDimitry Andric if (MI.getOpcode() == AMDGPU::KILLGT) 1878f0fd8f6SDimitry Andric killPixel = true; 1888f0fd8f6SDimitry Andric unsigned numOperands = MI.getNumOperands(); 1898f0fd8f6SDimitry Andric for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) { 1908f0fd8f6SDimitry Andric const MachineOperand &MO = MI.getOperand(op_idx); 1918f0fd8f6SDimitry Andric if (!MO.isReg()) 1928f0fd8f6SDimitry Andric continue; 1938f0fd8f6SDimitry Andric unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff; 1948f0fd8f6SDimitry Andric 1958f0fd8f6SDimitry Andric // Register with value > 127 aren't GPR 1968f0fd8f6SDimitry Andric if (HWReg > 127) 1978f0fd8f6SDimitry Andric continue; 1988f0fd8f6SDimitry Andric MaxGPR = std::max(MaxGPR, HWReg); 1998f0fd8f6SDimitry Andric } 2008f0fd8f6SDimitry Andric } 2018f0fd8f6SDimitry Andric } 2028f0fd8f6SDimitry Andric 2038f0fd8f6SDimitry Andric unsigned RsrcReg; 2048f0fd8f6SDimitry Andric if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) { 2058f0fd8f6SDimitry Andric // Evergreen / Northern Islands 2068f0fd8f6SDimitry Andric switch (MFI->getShaderType()) { 2078f0fd8f6SDimitry Andric default: // Fall through 2088f0fd8f6SDimitry Andric case ShaderType::COMPUTE: RsrcReg = R_0288D4_SQ_PGM_RESOURCES_LS; break; 2098f0fd8f6SDimitry Andric case ShaderType::GEOMETRY: RsrcReg = R_028878_SQ_PGM_RESOURCES_GS; break; 2108f0fd8f6SDimitry Andric case ShaderType::PIXEL: RsrcReg = R_028844_SQ_PGM_RESOURCES_PS; break; 2118f0fd8f6SDimitry Andric case ShaderType::VERTEX: RsrcReg = R_028860_SQ_PGM_RESOURCES_VS; break; 2128f0fd8f6SDimitry Andric } 2138f0fd8f6SDimitry Andric } else { 2148f0fd8f6SDimitry Andric // R600 / R700 2158f0fd8f6SDimitry Andric switch (MFI->getShaderType()) { 2168f0fd8f6SDimitry Andric default: // Fall through 2178f0fd8f6SDimitry Andric case ShaderType::GEOMETRY: // Fall through 2188f0fd8f6SDimitry Andric case ShaderType::COMPUTE: // Fall through 2198f0fd8f6SDimitry Andric case ShaderType::VERTEX: RsrcReg = R_028868_SQ_PGM_RESOURCES_VS; break; 2208f0fd8f6SDimitry Andric case ShaderType::PIXEL: RsrcReg = R_028850_SQ_PGM_RESOURCES_PS; break; 2218f0fd8f6SDimitry Andric } 2228f0fd8f6SDimitry Andric } 2238f0fd8f6SDimitry Andric 2248f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(RsrcReg, 4); 2258f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_NUM_GPRS(MaxGPR + 1) | 2268f0fd8f6SDimitry Andric S_STACK_SIZE(MFI->StackSize), 4); 2278f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_02880C_DB_SHADER_CONTROL, 4); 2288f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_02880C_KILL_ENABLE(killPixel), 4); 2298f0fd8f6SDimitry Andric 2308f0fd8f6SDimitry Andric if (MFI->getShaderType() == ShaderType::COMPUTE) { 2318f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_0288E8_SQ_LDS_ALLOC, 4); 2328f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(RoundUpToAlignment(MFI->LDSSize, 4) >> 2, 4); 2338f0fd8f6SDimitry Andric } 2348f0fd8f6SDimitry Andric } 2358f0fd8f6SDimitry Andric 2368f0fd8f6SDimitry Andric void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo, 2378f0fd8f6SDimitry Andric const MachineFunction &MF) const { 2388f0fd8f6SDimitry Andric const AMDGPUSubtarget &STM = MF.getSubtarget<AMDGPUSubtarget>(); 2398f0fd8f6SDimitry Andric const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 2408f0fd8f6SDimitry Andric uint64_t CodeSize = 0; 2418f0fd8f6SDimitry Andric unsigned MaxSGPR = 0; 2428f0fd8f6SDimitry Andric unsigned MaxVGPR = 0; 2438f0fd8f6SDimitry Andric bool VCCUsed = false; 2448f0fd8f6SDimitry Andric bool FlatUsed = false; 2458f0fd8f6SDimitry Andric const SIRegisterInfo *RI = 2468f0fd8f6SDimitry Andric static_cast<const SIRegisterInfo *>(STM.getRegisterInfo()); 2478f0fd8f6SDimitry Andric 2488f0fd8f6SDimitry Andric for (const MachineBasicBlock &MBB : MF) { 2498f0fd8f6SDimitry Andric for (const MachineInstr &MI : MBB) { 2508f0fd8f6SDimitry Andric // TODO: CodeSize should account for multiple functions. 2518f0fd8f6SDimitry Andric CodeSize += MI.getDesc().Size; 2528f0fd8f6SDimitry Andric 2538f0fd8f6SDimitry Andric unsigned numOperands = MI.getNumOperands(); 2548f0fd8f6SDimitry Andric for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) { 2558f0fd8f6SDimitry Andric const MachineOperand &MO = MI.getOperand(op_idx); 2568f0fd8f6SDimitry Andric unsigned width = 0; 2578f0fd8f6SDimitry Andric bool isSGPR = false; 2588f0fd8f6SDimitry Andric 2598f0fd8f6SDimitry Andric if (!MO.isReg()) { 2608f0fd8f6SDimitry Andric continue; 2618f0fd8f6SDimitry Andric } 2628f0fd8f6SDimitry Andric unsigned reg = MO.getReg(); 2638f0fd8f6SDimitry Andric if (reg == AMDGPU::VCC || reg == AMDGPU::VCC_LO || 2648f0fd8f6SDimitry Andric reg == AMDGPU::VCC_HI) { 2658f0fd8f6SDimitry Andric VCCUsed = true; 2668f0fd8f6SDimitry Andric continue; 2678f0fd8f6SDimitry Andric } else if (reg == AMDGPU::FLAT_SCR || 2688f0fd8f6SDimitry Andric reg == AMDGPU::FLAT_SCR_LO || 2698f0fd8f6SDimitry Andric reg == AMDGPU::FLAT_SCR_HI) { 2708f0fd8f6SDimitry Andric FlatUsed = true; 2718f0fd8f6SDimitry Andric continue; 2728f0fd8f6SDimitry Andric } 2738f0fd8f6SDimitry Andric 2748f0fd8f6SDimitry Andric switch (reg) { 2758f0fd8f6SDimitry Andric default: break; 2768f0fd8f6SDimitry Andric case AMDGPU::SCC: 2778f0fd8f6SDimitry Andric case AMDGPU::EXEC: 2788f0fd8f6SDimitry Andric case AMDGPU::M0: 2798f0fd8f6SDimitry Andric continue; 2808f0fd8f6SDimitry Andric } 2818f0fd8f6SDimitry Andric 2828f0fd8f6SDimitry Andric if (AMDGPU::SReg_32RegClass.contains(reg)) { 2838f0fd8f6SDimitry Andric isSGPR = true; 2848f0fd8f6SDimitry Andric width = 1; 2858f0fd8f6SDimitry Andric } else if (AMDGPU::VGPR_32RegClass.contains(reg)) { 2868f0fd8f6SDimitry Andric isSGPR = false; 2878f0fd8f6SDimitry Andric width = 1; 2888f0fd8f6SDimitry Andric } else if (AMDGPU::SReg_64RegClass.contains(reg)) { 2898f0fd8f6SDimitry Andric isSGPR = true; 2908f0fd8f6SDimitry Andric width = 2; 2918f0fd8f6SDimitry Andric } else if (AMDGPU::VReg_64RegClass.contains(reg)) { 2928f0fd8f6SDimitry Andric isSGPR = false; 2938f0fd8f6SDimitry Andric width = 2; 2948f0fd8f6SDimitry Andric } else if (AMDGPU::VReg_96RegClass.contains(reg)) { 2958f0fd8f6SDimitry Andric isSGPR = false; 2968f0fd8f6SDimitry Andric width = 3; 2978f0fd8f6SDimitry Andric } else if (AMDGPU::SReg_128RegClass.contains(reg)) { 2988f0fd8f6SDimitry Andric isSGPR = true; 2998f0fd8f6SDimitry Andric width = 4; 3008f0fd8f6SDimitry Andric } else if (AMDGPU::VReg_128RegClass.contains(reg)) { 3018f0fd8f6SDimitry Andric isSGPR = false; 3028f0fd8f6SDimitry Andric width = 4; 3038f0fd8f6SDimitry Andric } else if (AMDGPU::SReg_256RegClass.contains(reg)) { 3048f0fd8f6SDimitry Andric isSGPR = true; 3058f0fd8f6SDimitry Andric width = 8; 3068f0fd8f6SDimitry Andric } else if (AMDGPU::VReg_256RegClass.contains(reg)) { 3078f0fd8f6SDimitry Andric isSGPR = false; 3088f0fd8f6SDimitry Andric width = 8; 3098f0fd8f6SDimitry Andric } else if (AMDGPU::SReg_512RegClass.contains(reg)) { 3108f0fd8f6SDimitry Andric isSGPR = true; 3118f0fd8f6SDimitry Andric width = 16; 3128f0fd8f6SDimitry Andric } else if (AMDGPU::VReg_512RegClass.contains(reg)) { 3138f0fd8f6SDimitry Andric isSGPR = false; 3148f0fd8f6SDimitry Andric width = 16; 3158f0fd8f6SDimitry Andric } else { 3168f0fd8f6SDimitry Andric llvm_unreachable("Unknown register class"); 3178f0fd8f6SDimitry Andric } 3188f0fd8f6SDimitry Andric unsigned hwReg = RI->getEncodingValue(reg) & 0xff; 3198f0fd8f6SDimitry Andric unsigned maxUsed = hwReg + width - 1; 3208f0fd8f6SDimitry Andric if (isSGPR) { 3218f0fd8f6SDimitry Andric MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR; 3228f0fd8f6SDimitry Andric } else { 3238f0fd8f6SDimitry Andric MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR; 3248f0fd8f6SDimitry Andric } 3258f0fd8f6SDimitry Andric } 3268f0fd8f6SDimitry Andric } 3278f0fd8f6SDimitry Andric } 3288f0fd8f6SDimitry Andric 3298f0fd8f6SDimitry Andric if (VCCUsed) 3308f0fd8f6SDimitry Andric MaxSGPR += 2; 3318f0fd8f6SDimitry Andric 3328f0fd8f6SDimitry Andric if (FlatUsed) 3338f0fd8f6SDimitry Andric MaxSGPR += 2; 3348f0fd8f6SDimitry Andric 3358f0fd8f6SDimitry Andric // We found the maximum register index. They start at 0, so add one to get the 3368f0fd8f6SDimitry Andric // number of registers. 3378f0fd8f6SDimitry Andric ProgInfo.NumVGPR = MaxVGPR + 1; 3388f0fd8f6SDimitry Andric ProgInfo.NumSGPR = MaxSGPR + 1; 3398f0fd8f6SDimitry Andric 3408f0fd8f6SDimitry Andric if (STM.hasSGPRInitBug()) { 3418f0fd8f6SDimitry Andric if (ProgInfo.NumSGPR > AMDGPUSubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG) { 3428f0fd8f6SDimitry Andric LLVMContext &Ctx = MF.getFunction()->getContext(); 3438f0fd8f6SDimitry Andric Ctx.emitError("too many SGPRs used with the SGPR init bug"); 3448f0fd8f6SDimitry Andric } 3458f0fd8f6SDimitry Andric 3468f0fd8f6SDimitry Andric ProgInfo.NumSGPR = AMDGPUSubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG; 3478f0fd8f6SDimitry Andric } 3488f0fd8f6SDimitry Andric 3498f0fd8f6SDimitry Andric ProgInfo.VGPRBlocks = (ProgInfo.NumVGPR - 1) / 4; 3508f0fd8f6SDimitry Andric ProgInfo.SGPRBlocks = (ProgInfo.NumSGPR - 1) / 8; 3518f0fd8f6SDimitry Andric // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode 3528f0fd8f6SDimitry Andric // register. 3538f0fd8f6SDimitry Andric ProgInfo.FloatMode = getFPMode(MF); 3548f0fd8f6SDimitry Andric 3558f0fd8f6SDimitry Andric // XXX: Not quite sure what this does, but sc seems to unset this. 3568f0fd8f6SDimitry Andric ProgInfo.IEEEMode = 0; 3578f0fd8f6SDimitry Andric 3588f0fd8f6SDimitry Andric // Do not clamp NAN to 0. 3598f0fd8f6SDimitry Andric ProgInfo.DX10Clamp = 0; 3608f0fd8f6SDimitry Andric 3618f0fd8f6SDimitry Andric const MachineFrameInfo *FrameInfo = MF.getFrameInfo(); 3628f0fd8f6SDimitry Andric ProgInfo.ScratchSize = FrameInfo->estimateStackSize(MF); 3638f0fd8f6SDimitry Andric 3648f0fd8f6SDimitry Andric ProgInfo.FlatUsed = FlatUsed; 3658f0fd8f6SDimitry Andric ProgInfo.VCCUsed = VCCUsed; 3668f0fd8f6SDimitry Andric ProgInfo.CodeLen = CodeSize; 3678f0fd8f6SDimitry Andric 3688f0fd8f6SDimitry Andric unsigned LDSAlignShift; 3698f0fd8f6SDimitry Andric if (STM.getGeneration() < AMDGPUSubtarget::SEA_ISLANDS) { 3708f0fd8f6SDimitry Andric // LDS is allocated in 64 dword blocks. 3718f0fd8f6SDimitry Andric LDSAlignShift = 8; 3728f0fd8f6SDimitry Andric } else { 3738f0fd8f6SDimitry Andric // LDS is allocated in 128 dword blocks. 3748f0fd8f6SDimitry Andric LDSAlignShift = 9; 3758f0fd8f6SDimitry Andric } 3768f0fd8f6SDimitry Andric 3778f0fd8f6SDimitry Andric unsigned LDSSpillSize = MFI->LDSWaveSpillSize * 3788f0fd8f6SDimitry Andric MFI->getMaximumWorkGroupSize(MF); 3798f0fd8f6SDimitry Andric 3808f0fd8f6SDimitry Andric ProgInfo.LDSSize = MFI->LDSSize + LDSSpillSize; 3818f0fd8f6SDimitry Andric ProgInfo.LDSBlocks = 3828f0fd8f6SDimitry Andric RoundUpToAlignment(ProgInfo.LDSSize, 1 << LDSAlignShift) >> LDSAlignShift; 3838f0fd8f6SDimitry Andric 3848f0fd8f6SDimitry Andric // Scratch is allocated in 256 dword blocks. 3858f0fd8f6SDimitry Andric unsigned ScratchAlignShift = 10; 3868f0fd8f6SDimitry Andric // We need to program the hardware with the amount of scratch memory that 3878f0fd8f6SDimitry Andric // is used by the entire wave. ProgInfo.ScratchSize is the amount of 3888f0fd8f6SDimitry Andric // scratch memory used per thread. 3898f0fd8f6SDimitry Andric ProgInfo.ScratchBlocks = 3908f0fd8f6SDimitry Andric RoundUpToAlignment(ProgInfo.ScratchSize * STM.getWavefrontSize(), 3918f0fd8f6SDimitry Andric 1 << ScratchAlignShift) >> ScratchAlignShift; 3928f0fd8f6SDimitry Andric 3938f0fd8f6SDimitry Andric ProgInfo.ComputePGMRSrc1 = 3948f0fd8f6SDimitry Andric S_00B848_VGPRS(ProgInfo.VGPRBlocks) | 3958f0fd8f6SDimitry Andric S_00B848_SGPRS(ProgInfo.SGPRBlocks) | 3968f0fd8f6SDimitry Andric S_00B848_PRIORITY(ProgInfo.Priority) | 3978f0fd8f6SDimitry Andric S_00B848_FLOAT_MODE(ProgInfo.FloatMode) | 3988f0fd8f6SDimitry Andric S_00B848_PRIV(ProgInfo.Priv) | 3998f0fd8f6SDimitry Andric S_00B848_DX10_CLAMP(ProgInfo.DX10Clamp) | 4008f0fd8f6SDimitry Andric S_00B848_IEEE_MODE(ProgInfo.DebugMode) | 4018f0fd8f6SDimitry Andric S_00B848_IEEE_MODE(ProgInfo.IEEEMode); 4028f0fd8f6SDimitry Andric 4038f0fd8f6SDimitry Andric ProgInfo.ComputePGMRSrc2 = 4048f0fd8f6SDimitry Andric S_00B84C_SCRATCH_EN(ProgInfo.ScratchBlocks > 0) | 4058f0fd8f6SDimitry Andric S_00B84C_USER_SGPR(MFI->NumUserSGPRs) | 4068f0fd8f6SDimitry Andric S_00B84C_TGID_X_EN(1) | 4078f0fd8f6SDimitry Andric S_00B84C_TGID_Y_EN(1) | 4088f0fd8f6SDimitry Andric S_00B84C_TGID_Z_EN(1) | 4098f0fd8f6SDimitry Andric S_00B84C_TG_SIZE_EN(1) | 4108f0fd8f6SDimitry Andric S_00B84C_TIDIG_COMP_CNT(2) | 4118f0fd8f6SDimitry Andric S_00B84C_LDS_SIZE(ProgInfo.LDSBlocks); 4128f0fd8f6SDimitry Andric } 4138f0fd8f6SDimitry Andric 4148f0fd8f6SDimitry Andric static unsigned getRsrcReg(unsigned ShaderType) { 4158f0fd8f6SDimitry Andric switch (ShaderType) { 4168f0fd8f6SDimitry Andric default: // Fall through 4178f0fd8f6SDimitry Andric case ShaderType::COMPUTE: return R_00B848_COMPUTE_PGM_RSRC1; 4188f0fd8f6SDimitry Andric case ShaderType::GEOMETRY: return R_00B228_SPI_SHADER_PGM_RSRC1_GS; 4198f0fd8f6SDimitry Andric case ShaderType::PIXEL: return R_00B028_SPI_SHADER_PGM_RSRC1_PS; 4208f0fd8f6SDimitry Andric case ShaderType::VERTEX: return R_00B128_SPI_SHADER_PGM_RSRC1_VS; 4218f0fd8f6SDimitry Andric } 4228f0fd8f6SDimitry Andric } 4238f0fd8f6SDimitry Andric 4248f0fd8f6SDimitry Andric void AMDGPUAsmPrinter::EmitProgramInfoSI(const MachineFunction &MF, 4258f0fd8f6SDimitry Andric const SIProgramInfo &KernelInfo) { 4268f0fd8f6SDimitry Andric const AMDGPUSubtarget &STM = MF.getSubtarget<AMDGPUSubtarget>(); 4278f0fd8f6SDimitry Andric const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 4288f0fd8f6SDimitry Andric unsigned RsrcReg = getRsrcReg(MFI->getShaderType()); 4298f0fd8f6SDimitry Andric 4308f0fd8f6SDimitry Andric if (MFI->getShaderType() == ShaderType::COMPUTE) { 4318f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_00B848_COMPUTE_PGM_RSRC1, 4); 4328f0fd8f6SDimitry Andric 4338f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(KernelInfo.ComputePGMRSrc1, 4); 4348f0fd8f6SDimitry Andric 4358f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4); 4368f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(KernelInfo.ComputePGMRSrc2, 4); 4378f0fd8f6SDimitry Andric 4388f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_00B860_COMPUTE_TMPRING_SIZE, 4); 4398f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_00B860_WAVESIZE(KernelInfo.ScratchBlocks), 4); 4408f0fd8f6SDimitry Andric 4418f0fd8f6SDimitry Andric // TODO: Should probably note flat usage somewhere. SC emits a "FlatPtr32 = 4428f0fd8f6SDimitry Andric // 0" comment but I don't see a corresponding field in the register spec. 4438f0fd8f6SDimitry Andric } else { 4448f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(RsrcReg, 4); 4458f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_00B028_VGPRS(KernelInfo.VGPRBlocks) | 4468f0fd8f6SDimitry Andric S_00B028_SGPRS(KernelInfo.SGPRBlocks), 4); 4478f0fd8f6SDimitry Andric if (STM.isVGPRSpillingEnabled(MFI)) { 4488f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_0286E8_SPI_TMPRING_SIZE, 4); 4498f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_0286E8_WAVESIZE(KernelInfo.ScratchBlocks), 4); 4508f0fd8f6SDimitry Andric } 4518f0fd8f6SDimitry Andric } 4528f0fd8f6SDimitry Andric 4538f0fd8f6SDimitry Andric if (MFI->getShaderType() == ShaderType::PIXEL) { 4548f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4); 4558f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(KernelInfo.LDSBlocks), 4); 4568f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4); 4578f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(MFI->PSInputAddr, 4); 4588f0fd8f6SDimitry Andric } 4598f0fd8f6SDimitry Andric } 4608f0fd8f6SDimitry Andric 4618f0fd8f6SDimitry Andric void AMDGPUAsmPrinter::EmitAmdKernelCodeT(const MachineFunction &MF, 4628f0fd8f6SDimitry Andric const SIProgramInfo &KernelInfo) const { 4638f0fd8f6SDimitry Andric const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 4648f0fd8f6SDimitry Andric const AMDGPUSubtarget &STM = MF.getSubtarget<AMDGPUSubtarget>(); 4658f0fd8f6SDimitry Andric amd_kernel_code_t header; 4668f0fd8f6SDimitry Andric 4678f0fd8f6SDimitry Andric memset(&header, 0, sizeof(header)); 4688f0fd8f6SDimitry Andric 4698f0fd8f6SDimitry Andric header.amd_code_version_major = AMD_CODE_VERSION_MAJOR; 4708f0fd8f6SDimitry Andric header.amd_code_version_minor = AMD_CODE_VERSION_MINOR; 4718f0fd8f6SDimitry Andric 4728f0fd8f6SDimitry Andric header.struct_byte_size = sizeof(amd_kernel_code_t); 4738f0fd8f6SDimitry Andric 4748f0fd8f6SDimitry Andric header.target_chip = STM.getAmdKernelCodeChipID(); 4758f0fd8f6SDimitry Andric 4768f0fd8f6SDimitry Andric header.kernel_code_entry_byte_offset = (1ULL << MF.getAlignment()); 4778f0fd8f6SDimitry Andric 4788f0fd8f6SDimitry Andric header.compute_pgm_resource_registers = 4798f0fd8f6SDimitry Andric KernelInfo.ComputePGMRSrc1 | 4808f0fd8f6SDimitry Andric (KernelInfo.ComputePGMRSrc2 << 32); 4818f0fd8f6SDimitry Andric 4828f0fd8f6SDimitry Andric // Code Properties: 4838f0fd8f6SDimitry Andric header.code_properties = AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR | 4848f0fd8f6SDimitry Andric AMD_CODE_PROPERTY_IS_PTR64; 4858f0fd8f6SDimitry Andric 4868f0fd8f6SDimitry Andric if (KernelInfo.FlatUsed) 4878f0fd8f6SDimitry Andric header.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT; 4888f0fd8f6SDimitry Andric 4898f0fd8f6SDimitry Andric if (KernelInfo.ScratchBlocks) 4908f0fd8f6SDimitry Andric header.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE; 4918f0fd8f6SDimitry Andric 4928f0fd8f6SDimitry Andric header.workitem_private_segment_byte_size = KernelInfo.ScratchSize; 4938f0fd8f6SDimitry Andric header.workgroup_group_segment_byte_size = KernelInfo.LDSSize; 4948f0fd8f6SDimitry Andric 4958f0fd8f6SDimitry Andric // MFI->ABIArgOffset is the number of bytes for the kernel arguments 4968f0fd8f6SDimitry Andric // plus 36. 36 is the number of bytes reserved at the begining of the 4978f0fd8f6SDimitry Andric // input buffer to store work-group size information. 4988f0fd8f6SDimitry Andric // FIXME: We should be adding the size of the implicit arguments 4998f0fd8f6SDimitry Andric // to this value. 5008f0fd8f6SDimitry Andric header.kernarg_segment_byte_size = MFI->ABIArgOffset; 5018f0fd8f6SDimitry Andric 5028f0fd8f6SDimitry Andric header.wavefront_sgpr_count = KernelInfo.NumSGPR; 5038f0fd8f6SDimitry Andric header.workitem_vgpr_count = KernelInfo.NumVGPR; 5048f0fd8f6SDimitry Andric 5058f0fd8f6SDimitry Andric // FIXME: What values do I put for these alignments 5068f0fd8f6SDimitry Andric header.kernarg_segment_alignment = 0; 5078f0fd8f6SDimitry Andric header.group_segment_alignment = 0; 5088f0fd8f6SDimitry Andric header.private_segment_alignment = 0; 5098f0fd8f6SDimitry Andric 5108f0fd8f6SDimitry Andric header.code_type = 1; // HSA_EXT_CODE_KERNEL 5118f0fd8f6SDimitry Andric 5128f0fd8f6SDimitry Andric header.wavefront_size = STM.getWavefrontSize(); 5138f0fd8f6SDimitry Andric 5148f0fd8f6SDimitry Andric MCSectionELF *VersionSection = 5158f0fd8f6SDimitry Andric OutContext.getELFSection(".hsa.version", ELF::SHT_PROGBITS, 0); 5168f0fd8f6SDimitry Andric OutStreamer->SwitchSection(VersionSection); 5178f0fd8f6SDimitry Andric OutStreamer->EmitBytes(Twine("HSA Code Unit:" + 5188f0fd8f6SDimitry Andric Twine(header.hsail_version_major) + "." + 5198f0fd8f6SDimitry Andric Twine(header.hsail_version_minor) + ":" + 5208f0fd8f6SDimitry Andric "AMD:" + 5218f0fd8f6SDimitry Andric Twine(header.amd_code_version_major) + "." + 5228f0fd8f6SDimitry Andric Twine(header.amd_code_version_minor) + ":" + 5238f0fd8f6SDimitry Andric "GFX8.1:0").str()); 5248f0fd8f6SDimitry Andric 5258f0fd8f6SDimitry Andric OutStreamer->SwitchSection(getObjFileLowering().getTextSection()); 5268f0fd8f6SDimitry Andric 5278f0fd8f6SDimitry Andric if (isVerbose()) { 5288f0fd8f6SDimitry Andric OutStreamer->emitRawComment("amd_code_version_major = " + 5298f0fd8f6SDimitry Andric Twine(header.amd_code_version_major), false); 5308f0fd8f6SDimitry Andric OutStreamer->emitRawComment("amd_code_version_minor = " + 5318f0fd8f6SDimitry Andric Twine(header.amd_code_version_minor), false); 5328f0fd8f6SDimitry Andric OutStreamer->emitRawComment("struct_byte_size = " + 5338f0fd8f6SDimitry Andric Twine(header.struct_byte_size), false); 5348f0fd8f6SDimitry Andric OutStreamer->emitRawComment("target_chip = " + 5358f0fd8f6SDimitry Andric Twine(header.target_chip), false); 5368f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" compute_pgm_rsrc1: " + 5378f0fd8f6SDimitry Andric Twine::utohexstr(KernelInfo.ComputePGMRSrc1), 5388f0fd8f6SDimitry Andric false); 5398f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" compute_pgm_rsrc2: " + 5408f0fd8f6SDimitry Andric Twine::utohexstr(KernelInfo.ComputePGMRSrc2), 5418f0fd8f6SDimitry Andric false); 5428f0fd8f6SDimitry Andric OutStreamer->emitRawComment("enable_sgpr_private_segment_buffer = " + 5438f0fd8f6SDimitry Andric Twine((bool)(header.code_properties & 5448f0fd8f6SDimitry Andric AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE)), false); 5458f0fd8f6SDimitry Andric OutStreamer->emitRawComment("enable_sgpr_kernarg_segment_ptr = " + 5468f0fd8f6SDimitry Andric Twine((bool)(header.code_properties & 5478f0fd8f6SDimitry Andric AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR)), false); 5488f0fd8f6SDimitry Andric OutStreamer->emitRawComment("private_element_size = 2 ", false); 5498f0fd8f6SDimitry Andric OutStreamer->emitRawComment("is_ptr64 = " + 5508f0fd8f6SDimitry Andric Twine((bool)(header.code_properties & AMD_CODE_PROPERTY_IS_PTR64)), false); 5518f0fd8f6SDimitry Andric OutStreamer->emitRawComment("workitem_private_segment_byte_size = " + 5528f0fd8f6SDimitry Andric Twine(header.workitem_private_segment_byte_size), 5538f0fd8f6SDimitry Andric false); 5548f0fd8f6SDimitry Andric OutStreamer->emitRawComment("workgroup_group_segment_byte_size = " + 5558f0fd8f6SDimitry Andric Twine(header.workgroup_group_segment_byte_size), 5568f0fd8f6SDimitry Andric false); 5578f0fd8f6SDimitry Andric OutStreamer->emitRawComment("gds_segment_byte_size = " + 5588f0fd8f6SDimitry Andric Twine(header.gds_segment_byte_size), false); 5598f0fd8f6SDimitry Andric OutStreamer->emitRawComment("kernarg_segment_byte_size = " + 5608f0fd8f6SDimitry Andric Twine(header.kernarg_segment_byte_size), false); 5618f0fd8f6SDimitry Andric OutStreamer->emitRawComment("wavefront_sgpr_count = " + 5628f0fd8f6SDimitry Andric Twine(header.wavefront_sgpr_count), false); 5638f0fd8f6SDimitry Andric OutStreamer->emitRawComment("workitem_vgpr_count = " + 5648f0fd8f6SDimitry Andric Twine(header.workitem_vgpr_count), false); 5658f0fd8f6SDimitry Andric OutStreamer->emitRawComment("code_type = " + Twine(header.code_type), false); 5668f0fd8f6SDimitry Andric OutStreamer->emitRawComment("wavefront_size = " + 5678f0fd8f6SDimitry Andric Twine((int)header.wavefront_size), false); 5688f0fd8f6SDimitry Andric OutStreamer->emitRawComment("optimization_level = " + 5698f0fd8f6SDimitry Andric Twine(header.optimization_level), false); 5708f0fd8f6SDimitry Andric OutStreamer->emitRawComment("hsail_profile = " + 5718f0fd8f6SDimitry Andric Twine(header.hsail_profile), false); 5728f0fd8f6SDimitry Andric OutStreamer->emitRawComment("hsail_machine_model = " + 5738f0fd8f6SDimitry Andric Twine(header.hsail_machine_model), false); 5748f0fd8f6SDimitry Andric OutStreamer->emitRawComment("hsail_version_major = " + 5758f0fd8f6SDimitry Andric Twine(header.hsail_version_major), false); 5768f0fd8f6SDimitry Andric OutStreamer->emitRawComment("hsail_version_minor = " + 5778f0fd8f6SDimitry Andric Twine(header.hsail_version_minor), false); 5788f0fd8f6SDimitry Andric } 5798f0fd8f6SDimitry Andric 5808f0fd8f6SDimitry Andric OutStreamer->EmitBytes(StringRef((char*)&header, sizeof(header))); 5818f0fd8f6SDimitry Andric } 5828f0fd8f6SDimitry Andric 5838f0fd8f6SDimitry Andric bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 5848f0fd8f6SDimitry Andric unsigned AsmVariant, 5858f0fd8f6SDimitry Andric const char *ExtraCode, raw_ostream &O) { 5868f0fd8f6SDimitry Andric if (ExtraCode && ExtraCode[0]) { 5878f0fd8f6SDimitry Andric if (ExtraCode[1] != 0) 5888f0fd8f6SDimitry Andric return true; // Unknown modifier. 5898f0fd8f6SDimitry Andric 5908f0fd8f6SDimitry Andric switch (ExtraCode[0]) { 5918f0fd8f6SDimitry Andric default: 5928f0fd8f6SDimitry Andric // See if this is a generic print operand 5938f0fd8f6SDimitry Andric return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); 5948f0fd8f6SDimitry Andric case 'r': 5958f0fd8f6SDimitry Andric break; 5968f0fd8f6SDimitry Andric } 5978f0fd8f6SDimitry Andric } 5988f0fd8f6SDimitry Andric 5998f0fd8f6SDimitry Andric AMDGPUInstPrinter::printRegOperand(MI->getOperand(OpNo).getReg(), O, 6008f0fd8f6SDimitry Andric *TM.getSubtargetImpl(*MF->getFunction())->getRegisterInfo()); 6018f0fd8f6SDimitry Andric return false; 6028f0fd8f6SDimitry Andric } 603