1 //===-- R600AsmPrinter.cpp - R600 Assembly printer ------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file 10 /// 11 /// The R600AsmPrinter is used to print both assembly string and also binary 12 /// code. When passed an MCAsmStreamer it prints assembly and when passed 13 /// an MCObjectStreamer it outputs binary code. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "R600AsmPrinter.h" 18 #include "AMDGPUSubtarget.h" 19 #include "R600Defines.h" 20 #include "R600MachineFunctionInfo.h" 21 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 22 #include "llvm/BinaryFormat/ELF.h" 23 #include "llvm/MC/MCContext.h" 24 #include "llvm/MC/MCSectionELF.h" 25 #include "llvm/MC/MCStreamer.h" 26 #include "llvm/Target/TargetLoweringObjectFile.h" 27 28 using namespace llvm; 29 30 AsmPrinter * 31 llvm::createR600AsmPrinterPass(TargetMachine &TM, 32 std::unique_ptr<MCStreamer> &&Streamer) { 33 return new R600AsmPrinter(TM, std::move(Streamer)); 34 } 35 36 R600AsmPrinter::R600AsmPrinter(TargetMachine &TM, 37 std::unique_ptr<MCStreamer> Streamer) 38 : AsmPrinter(TM, std::move(Streamer)) { } 39 40 StringRef R600AsmPrinter::getPassName() const { 41 return "R600 Assembly Printer"; 42 } 43 44 void R600AsmPrinter::EmitProgramInfoR600(const MachineFunction &MF) { 45 unsigned MaxGPR = 0; 46 bool killPixel = false; 47 const R600Subtarget &STM = MF.getSubtarget<R600Subtarget>(); 48 const R600RegisterInfo *RI = STM.getRegisterInfo(); 49 const R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>(); 50 51 for (const MachineBasicBlock &MBB : MF) { 52 for (const MachineInstr &MI : MBB) { 53 if (MI.getOpcode() == R600::KILLGT) 54 killPixel = true; 55 unsigned numOperands = MI.getNumOperands(); 56 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) { 57 const MachineOperand &MO = MI.getOperand(op_idx); 58 if (!MO.isReg()) 59 continue; 60 unsigned HWReg = RI->getHWRegIndex(MO.getReg()); 61 62 // Register with value > 127 aren't GPR 63 if (HWReg > 127) 64 continue; 65 MaxGPR = std::max(MaxGPR, HWReg); 66 } 67 } 68 } 69 70 unsigned RsrcReg; 71 if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) { 72 // Evergreen / Northern Islands 73 switch (MF.getFunction().getCallingConv()) { 74 default: LLVM_FALLTHROUGH; 75 case CallingConv::AMDGPU_CS: RsrcReg = R_0288D4_SQ_PGM_RESOURCES_LS; break; 76 case CallingConv::AMDGPU_GS: RsrcReg = R_028878_SQ_PGM_RESOURCES_GS; break; 77 case CallingConv::AMDGPU_PS: RsrcReg = R_028844_SQ_PGM_RESOURCES_PS; break; 78 case CallingConv::AMDGPU_VS: RsrcReg = R_028860_SQ_PGM_RESOURCES_VS; break; 79 } 80 } else { 81 // R600 / R700 82 switch (MF.getFunction().getCallingConv()) { 83 default: LLVM_FALLTHROUGH; 84 case CallingConv::AMDGPU_GS: LLVM_FALLTHROUGH; 85 case CallingConv::AMDGPU_CS: LLVM_FALLTHROUGH; 86 case CallingConv::AMDGPU_VS: RsrcReg = R_028868_SQ_PGM_RESOURCES_VS; break; 87 case CallingConv::AMDGPU_PS: RsrcReg = R_028850_SQ_PGM_RESOURCES_PS; break; 88 } 89 } 90 91 OutStreamer->emitInt32(RsrcReg); 92 OutStreamer->emitIntValue(S_NUM_GPRS(MaxGPR + 1) | 93 S_STACK_SIZE(MFI->CFStackSize), 4); 94 OutStreamer->emitInt32(R_02880C_DB_SHADER_CONTROL); 95 OutStreamer->emitInt32(S_02880C_KILL_ENABLE(killPixel)); 96 97 if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) { 98 OutStreamer->emitInt32(R_0288E8_SQ_LDS_ALLOC); 99 OutStreamer->emitIntValue(alignTo(MFI->getLDSSize(), 4) >> 2, 4); 100 } 101 } 102 103 bool R600AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 104 105 106 // Functions needs to be cacheline (256B) aligned. 107 MF.ensureAlignment(Align(256)); 108 109 SetupMachineFunction(MF); 110 111 MCContext &Context = getObjFileLowering().getContext(); 112 MCSectionELF *ConfigSection = 113 Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0); 114 OutStreamer->SwitchSection(ConfigSection); 115 116 EmitProgramInfoR600(MF); 117 118 emitFunctionBody(); 119 120 if (isVerbose()) { 121 MCSectionELF *CommentSection = 122 Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0); 123 OutStreamer->SwitchSection(CommentSection); 124 125 R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>(); 126 OutStreamer->emitRawComment( 127 Twine("SQ_PGM_RESOURCES:STACK_SIZE = " + Twine(MFI->CFStackSize))); 128 } 129 130 return false; 131 } 132 133