| Tom Stellard | c501501 | 2018-05-24 20:02:01 +0000 | [diff] [blame] | 1 | //===-- R600AsmPrinter.cpp - R600 Assebly printer  ------------------------===// | 
|  | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 | 
| Tom Stellard | c501501 | 2018-05-24 20:02:01 +0000 | [diff] [blame] | 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) { | 
| Tom Stellard | c5a154d | 2018-06-28 23:47:12 +0000 | [diff] [blame] | 53 | if (MI.getOpcode() == R600::KILLGT) | 
| Tom Stellard | c501501 | 2018-05-24 20:02:01 +0000 | [diff] [blame] | 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; | 
| Tom Stellard | 5bfbae5 | 2018-07-11 20:59:01 +0000 | [diff] [blame] | 71 | if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) { | 
| Tom Stellard | c501501 | 2018-05-24 20:02:01 +0000 | [diff] [blame] | 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->EmitIntValue(RsrcReg, 4); | 
|  | 92 | OutStreamer->EmitIntValue(S_NUM_GPRS(MaxGPR + 1) | | 
|  | 93 | S_STACK_SIZE(MFI->CFStackSize), 4); | 
|  | 94 | OutStreamer->EmitIntValue(R_02880C_DB_SHADER_CONTROL, 4); | 
|  | 95 | OutStreamer->EmitIntValue(S_02880C_KILL_ENABLE(killPixel), 4); | 
|  | 96 |  | 
|  | 97 | if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) { | 
|  | 98 | OutStreamer->EmitIntValue(R_0288E8_SQ_LDS_ALLOC, 4); | 
|  | 99 | OutStreamer->EmitIntValue(alignTo(MFI->getLDSSize(), 4) >> 2, 4); | 
|  | 100 | } | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | bool R600AsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 
|  | 104 |  | 
| Jan Vesely | f5016b7 | 2018-05-31 04:08:08 +0000 | [diff] [blame] | 105 |  | 
|  | 106 | // Functions needs to be cacheline (256B) aligned. | 
| Guillaume Chatelet | 18f805a | 2019-09-27 12:54:21 +0000 | [diff] [blame] | 107 | MF.ensureAlignment(Align(256)); | 
| Jan Vesely | f5016b7 | 2018-05-31 04:08:08 +0000 | [diff] [blame] | 108 |  | 
| Tom Stellard | c501501 | 2018-05-24 20:02:01 +0000 | [diff] [blame] | 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 |  |