1 //===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly printer --------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// 12 /// The AMDGPUAsmPrinter is used to print both assembly string and also binary 13 /// code. When passed an MCAsmStreamer it prints assembly and when passed 14 /// an MCObjectStreamer it outputs binary code. 15 // 16 //===----------------------------------------------------------------------===// 17 // 18 19 20 #include "AMDGPUAsmPrinter.h" 21 #include "AMDGPU.h" 22 #include "SIMachineFunctionInfo.h" 23 #include "SIRegisterInfo.h" 24 #include "llvm/MC/MCStreamer.h" 25 #include "llvm/Support/TargetRegistry.h" 26 #include "llvm/Target/TargetLoweringObjectFile.h" 27 28 using namespace llvm; 29 30 31 static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm, 32 MCStreamer &Streamer) { 33 return new AMDGPUAsmPrinter(tm, Streamer); 34 } 35 36 extern "C" void LLVMInitializeR600AsmPrinter() { 37 TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass); 38 } 39 40 /// We need to override this function so we can avoid 41 /// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle. 42 bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 43 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>(); 44 if (STM.dumpCode()) { 45 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 46 MF.dump(); 47 #endif 48 } 49 SetupMachineFunction(MF); 50 if (OutStreamer.hasRawTextSupport()) { 51 OutStreamer.EmitRawText("@" + MF.getName() + ":"); 52 } 53 OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); 54 if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) { 55 EmitProgramInfo(MF); 56 } 57 EmitFunctionBody(); 58 return false; 59 } 60 61 void AMDGPUAsmPrinter::EmitProgramInfo(MachineFunction &MF) { 62 unsigned MaxSGPR = 0; 63 unsigned MaxVGPR = 0; 64 bool VCCUsed = false; 65 const SIRegisterInfo * RI = 66 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo()); 67 68 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end(); 69 BB != BB_E; ++BB) { 70 MachineBasicBlock &MBB = *BB; 71 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); 72 I != E; ++I) { 73 MachineInstr &MI = *I; 74 75 unsigned numOperands = MI.getNumOperands(); 76 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) { 77 MachineOperand & MO = MI.getOperand(op_idx); 78 unsigned maxUsed; 79 unsigned width = 0; 80 bool isSGPR = false; 81 unsigned reg; 82 unsigned hwReg; 83 if (!MO.isReg()) { 84 continue; 85 } 86 reg = MO.getReg(); 87 if (reg == AMDGPU::VCC) { 88 VCCUsed = true; 89 continue; 90 } 91 switch (reg) { 92 default: break; 93 case AMDGPU::EXEC: 94 case AMDGPU::M0: 95 continue; 96 } 97 98 if (AMDGPU::SReg_32RegClass.contains(reg)) { 99 isSGPR = true; 100 width = 1; 101 } else if (AMDGPU::VReg_32RegClass.contains(reg)) { 102 isSGPR = false; 103 width = 1; 104 } else if (AMDGPU::SReg_64RegClass.contains(reg)) { 105 isSGPR = true; 106 width = 2; 107 } else if (AMDGPU::VReg_64RegClass.contains(reg)) { 108 isSGPR = false; 109 width = 2; 110 } else if (AMDGPU::SReg_128RegClass.contains(reg)) { 111 isSGPR = true; 112 width = 4; 113 } else if (AMDGPU::VReg_128RegClass.contains(reg)) { 114 isSGPR = false; 115 width = 4; 116 } else if (AMDGPU::SReg_256RegClass.contains(reg)) { 117 isSGPR = true; 118 width = 8; 119 } else if (AMDGPU::VReg_256RegClass.contains(reg)) { 120 isSGPR = false; 121 width = 8; 122 } else if (AMDGPU::VReg_512RegClass.contains(reg)) { 123 isSGPR = false; 124 width = 16; 125 } else { 126 assert(!"Unknown register class"); 127 } 128 hwReg = RI->getEncodingValue(reg) & 0xff; 129 maxUsed = hwReg + width - 1; 130 if (isSGPR) { 131 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR; 132 } else { 133 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR; 134 } 135 } 136 } 137 } 138 if (VCCUsed) { 139 MaxSGPR += 2; 140 } 141 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>(); 142 OutStreamer.EmitIntValue(MaxSGPR + 1, 4); 143 OutStreamer.EmitIntValue(MaxVGPR + 1, 4); 144 OutStreamer.EmitIntValue(MFI->PSInputAddr, 4); 145 } 146