blob: 4553c4556cf5cebd9e0c81521e0295a0268423fb [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"
24#include "llvm/MC/MCStreamer.h"
25#include "llvm/Target/TargetLoweringObjectFile.h"
26#include "llvm/Support/TargetRegistry.h"
27
28using namespace llvm;
29
30
31static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
32 MCStreamer &Streamer) {
33 return new AMDGPUAsmPrinter(tm, Streamer);
34}
35
36extern "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.
42bool 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 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
51 if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
52 EmitProgramInfo(MF);
53 }
54 EmitFunctionBody();
55 return false;
56}
57
58void AMDGPUAsmPrinter::EmitProgramInfo(MachineFunction &MF) {
59 unsigned MaxSGPR = 0;
60 unsigned MaxVGPR = 0;
61 bool VCCUsed = false;
62 const SIRegisterInfo * RI =
63 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
64
65 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
66 BB != BB_E; ++BB) {
67 MachineBasicBlock &MBB = *BB;
68 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
69 I != E; ++I) {
70 MachineInstr &MI = *I;
71
72 unsigned numOperands = MI.getNumOperands();
73 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
74 MachineOperand & MO = MI.getOperand(op_idx);
75 unsigned maxUsed;
76 unsigned width = 0;
77 bool isSGPR = false;
78 unsigned reg;
79 unsigned hwReg;
80 if (!MO.isReg()) {
81 continue;
82 }
83 reg = MO.getReg();
84 if (reg == AMDGPU::VCC) {
85 VCCUsed = true;
86 continue;
87 }
88 switch (reg) {
89 default: break;
90 case AMDGPU::EXEC:
91 case AMDGPU::SI_LITERAL_CONSTANT:
92 case AMDGPU::SREG_LIT_0:
93 case AMDGPU::M0:
94 continue;
95 }
96
97 if (AMDGPU::SReg_32RegClass.contains(reg)) {
98 isSGPR = true;
99 width = 1;
100 } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
101 isSGPR = false;
102 width = 1;
103 } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
104 isSGPR = true;
105 width = 2;
106 } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
107 isSGPR = false;
108 width = 2;
109 } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
110 isSGPR = true;
111 width = 4;
112 } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
113 isSGPR = false;
114 width = 4;
115 } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
116 isSGPR = true;
117 width = 8;
118 } else {
119 assert(!"Unknown register class");
120 }
121 hwReg = RI->getEncodingValue(reg);
122 maxUsed = hwReg + width - 1;
123 if (isSGPR) {
124 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
125 } else {
126 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
127 }
128 }
129 }
130 }
131 if (VCCUsed) {
132 MaxSGPR += 2;
133 }
134 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
135 OutStreamer.EmitIntValue(MaxSGPR + 1, 4);
136 OutStreamer.EmitIntValue(MaxVGPR + 1, 4);
137 OutStreamer.EmitIntValue(MFI->SPIPSInputAddr, 4);
138}