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
26using namespace llvm;
27
28
29static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
30                                              MCStreamer &Streamer) {
31  return new AMDGPUAsmPrinter(tm, Streamer);
32}
33
34extern "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.
40bool 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
54void 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