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