blob: 72f98ee0b009229ab7d3145624f6ccf3676bd8df [file] [log] [blame]
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001//===-- 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"
Tom Stellardbf1efe62013-04-15 17:51:30 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCSectionELF.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000026#include "llvm/MC/MCStreamer.h"
Tom Stellardbf1efe62013-04-15 17:51:30 +000027#include "llvm/Support/ELF.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000028#include "llvm/Support/TargetRegistry.h"
Chandler Carruth58a2cbe2013-01-02 10:22:59 +000029#include "llvm/Target/TargetLoweringObjectFile.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000030
31using namespace llvm;
32
33
34static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
35 MCStreamer &Streamer) {
36 return new AMDGPUAsmPrinter(tm, Streamer);
37}
38
39extern "C" void LLVMInitializeR600AsmPrinter() {
40 TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
41}
42
43/// We need to override this function so we can avoid
44/// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
45bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
46 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
47 if (STM.dumpCode()) {
48#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
49 MF.dump();
50#endif
51 }
52 SetupMachineFunction(MF);
Tom Stellard3ce2ec82013-02-05 17:09:11 +000053 if (OutStreamer.hasRawTextSupport()) {
54 OutStreamer.EmitRawText("@" + MF.getName() + ":");
55 }
Tom Stellardf98f2ce2012-12-11 21:25:42 +000056 if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
Tom Stellardbf1efe62013-04-15 17:51:30 +000057 const MCSectionELF *ConfigSection = getObjFileLowering().getContext()
58 .getELFSection(".AMDGPU.config",
59 ELF::SHT_NULL, 0,
60 SectionKind::getReadOnly());
61 OutStreamer.SwitchSection(ConfigSection);
Tom Stellardf98f2ce2012-12-11 21:25:42 +000062 EmitProgramInfo(MF);
63 }
Tom Stellardbf1efe62013-04-15 17:51:30 +000064 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
Tom Stellardf98f2ce2012-12-11 21:25:42 +000065 EmitFunctionBody();
66 return false;
67}
68
69void AMDGPUAsmPrinter::EmitProgramInfo(MachineFunction &MF) {
70 unsigned MaxSGPR = 0;
71 unsigned MaxVGPR = 0;
72 bool VCCUsed = false;
73 const SIRegisterInfo * RI =
74 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
75
76 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
77 BB != BB_E; ++BB) {
78 MachineBasicBlock &MBB = *BB;
79 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
80 I != E; ++I) {
81 MachineInstr &MI = *I;
82
83 unsigned numOperands = MI.getNumOperands();
84 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
85 MachineOperand & MO = MI.getOperand(op_idx);
86 unsigned maxUsed;
87 unsigned width = 0;
88 bool isSGPR = false;
89 unsigned reg;
90 unsigned hwReg;
91 if (!MO.isReg()) {
92 continue;
93 }
94 reg = MO.getReg();
95 if (reg == AMDGPU::VCC) {
96 VCCUsed = true;
97 continue;
98 }
99 switch (reg) {
100 default: break;
101 case AMDGPU::EXEC:
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000102 case AMDGPU::M0:
103 continue;
104 }
105
106 if (AMDGPU::SReg_32RegClass.contains(reg)) {
107 isSGPR = true;
108 width = 1;
109 } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
110 isSGPR = false;
111 width = 1;
112 } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
113 isSGPR = true;
114 width = 2;
115 } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
116 isSGPR = false;
117 width = 2;
Christian Konig4d0e8a82013-04-10 08:39:16 +0000118 } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
119 isSGPR = false;
120 width = 3;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000121 } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
122 isSGPR = true;
123 width = 4;
124 } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
125 isSGPR = false;
126 width = 4;
127 } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
128 isSGPR = true;
129 width = 8;
Tom Stellard36ba9092013-02-07 17:02:09 +0000130 } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
131 isSGPR = false;
132 width = 8;
133 } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
134 isSGPR = false;
135 width = 16;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000136 } else {
137 assert(!"Unknown register class");
138 }
Tom Stellard184f5c12013-02-07 19:39:45 +0000139 hwReg = RI->getEncodingValue(reg) & 0xff;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000140 maxUsed = hwReg + width - 1;
141 if (isSGPR) {
142 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
143 } else {
144 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
145 }
146 }
147 }
148 }
149 if (VCCUsed) {
150 MaxSGPR += 2;
151 }
152 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
153 OutStreamer.EmitIntValue(MaxSGPR + 1, 4);
154 OutStreamer.EmitIntValue(MaxVGPR + 1, 4);
Christian Konigcc226402013-03-07 09:04:14 +0000155 OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000156}