blob: 4d6bc5c95be4b13c29b50b2f0ff980c228d4eba2 [file] [log] [blame]
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +00001//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly writer ---------------===//
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// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to the SystemZ assembly language.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "asm-printer"
16#include "SystemZ.h"
17#include "SystemZInstrInfo.h"
18#include "SystemZTargetMachine.h"
19#include "llvm/Constants.h"
20#include "llvm/DerivedTypes.h"
21#include "llvm/Module.h"
22#include "llvm/CodeGen/AsmPrinter.h"
23#include "llvm/CodeGen/DwarfWriter.h"
24#include "llvm/CodeGen/MachineModuleInfo.h"
25#include "llvm/CodeGen/MachineFunctionPass.h"
26#include "llvm/CodeGen/MachineConstantPool.h"
27#include "llvm/CodeGen/MachineInstr.h"
28#include "llvm/Target/TargetAsmInfo.h"
29#include "llvm/Target/TargetData.h"
30#include "llvm/ADT/Statistic.h"
31#include "llvm/Support/Compiler.h"
32#include "llvm/Support/Mangler.h"
33#include "llvm/Support/raw_ostream.h"
34
35using namespace llvm;
36
37STATISTIC(EmittedInsts, "Number of machine instrs printed");
38
39namespace {
40 class VISIBILITY_HIDDEN SystemZAsmPrinter : public AsmPrinter {
41 public:
42 SystemZAsmPrinter(raw_ostream &O, SystemZTargetMachine &TM,
43 const TargetAsmInfo *TAI,
44 CodeGenOpt::Level OL, bool V)
45 : AsmPrinter(O, TM, TAI, OL, V) {}
46
47 virtual const char *getPassName() const {
48 return "SystemZ Assembly Printer";
49 }
50
51 void printOperand(const MachineInstr *MI, int OpNum,
52 const char* Modifier = 0);
Anton Korobeynikova58fac92009-07-16 13:43:18 +000053 void printRIAddrOperand(const MachineInstr *MI, int OpNum,
54 const char* Modifier = 0);
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +000055 void printRRIAddrOperand(const MachineInstr *MI, int OpNum,
56 const char* Modifier = 0);
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000057 bool printInstruction(const MachineInstr *MI); // autogenerated.
58 void printMachineInstruction(const MachineInstr * MI);
59
60 void emitFunctionHeader(const MachineFunction &MF);
61 bool runOnMachineFunction(MachineFunction &F);
62 bool doInitialization(Module &M);
63 bool doFinalization(Module &M);
64
65 void getAnalysisUsage(AnalysisUsage &AU) const {
66 AsmPrinter::getAnalysisUsage(AU);
67 AU.setPreservesAll();
68 }
69 };
70} // end of anonymous namespace
71
72#include "SystemZGenAsmWriter.inc"
73
74/// createSystemZCodePrinterPass - Returns a pass that prints the SystemZ
75/// assembly code for a MachineFunction to the given output stream,
76/// using the given target machine description. This should work
77/// regardless of whether the function is in SSA form.
78///
79FunctionPass *llvm::createSystemZCodePrinterPass(raw_ostream &o,
80 SystemZTargetMachine &tm,
81 CodeGenOpt::Level OptLevel,
82 bool verbose) {
83 return new SystemZAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
84}
85
86bool SystemZAsmPrinter::doInitialization(Module &M) {
87 Mang = new Mangler(M, "", TAI->getPrivateGlobalPrefix());
88 return false; // success
89}
90
91
92bool SystemZAsmPrinter::doFinalization(Module &M) {
93 return AsmPrinter::doFinalization(M);
94}
95
96void SystemZAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
97 const Function *F = MF.getFunction();
98
99 SwitchToSection(TAI->SectionForGlobal(F));
100
101 unsigned FnAlign = 4;
102 if (F->hasFnAttr(Attribute::OptimizeForSize))
103 FnAlign = 1;
104
105 EmitAlignment(FnAlign, F);
106
107 switch (F->getLinkage()) {
108 default: assert(0 && "Unknown linkage type!");
109 case Function::InternalLinkage: // Symbols default to internal.
110 case Function::PrivateLinkage:
111 break;
112 case Function::ExternalLinkage:
113 O << "\t.globl\t" << CurrentFnName << '\n';
114 break;
115 case Function::LinkOnceAnyLinkage:
116 case Function::LinkOnceODRLinkage:
117 case Function::WeakAnyLinkage:
118 case Function::WeakODRLinkage:
119 O << "\t.weak\t" << CurrentFnName << '\n';
120 break;
121 }
122
123 printVisibility(CurrentFnName, F->getVisibility());
124
125 O << "\t.type\t" << CurrentFnName << ",@function\n"
126 << CurrentFnName << ":\n";
127}
128
129bool SystemZAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
130 SetupMachineFunction(MF);
131 O << "\n\n";
132
133 // Print the 'header' of function
134 emitFunctionHeader(MF);
135
136 // Print out code for the function.
137 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
138 I != E; ++I) {
139 // Print a label for the basic block.
140 if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) {
141 // This is an entry block or a block that's only reachable via a
142 // fallthrough edge. In non-VerboseAsm mode, don't print the label.
143 } else {
144 printBasicBlockLabel(I, true, true, VerboseAsm);
145 O << '\n';
146 }
147
148 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
149 II != E; ++II)
150 // Print the assembly for the instruction.
151 printMachineInstruction(II);
152 }
153
154 if (TAI->hasDotTypeDotSizeDirective())
155 O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
156
157 O.flush();
158
159 // We didn't modify anything
160 return false;
161}
162
163void SystemZAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
164 ++EmittedInsts;
165
166 // Call the autogenerated instruction printer routines.
167 if (printInstruction(MI))
168 return;
169
170 assert(0 && "Should not happen");
171}
172
173void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
Anton Korobeynikova58fac92009-07-16 13:43:18 +0000174 const char* Modifier) {
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000175 const MachineOperand &MO = MI->getOperand(OpNum);
176 switch (MO.getType()) {
177 case MachineOperand::MO_Register:
178 assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
179 "Virtual registers should be already mapped!");
180 O << '%' << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
181 return;
182 case MachineOperand::MO_Immediate:
183 O << MO.getImm();
184 return;
185 case MachineOperand::MO_MachineBasicBlock:
186 printBasicBlockLabel(MO.getMBB());
187 return;
Anton Korobeynikov961cd4a2009-07-16 13:50:21 +0000188 case MachineOperand::MO_GlobalAddress: {
189 std::string Name = Mang->getValueName(MO.getGlobal());
190 assert(MO.getOffset() == 0 && "No offsets allowed!");
191
192 O << Name;
193
194 return;
195 }
196 case MachineOperand::MO_ExternalSymbol: {
197 std::string Name(TAI->getGlobalPrefix());
198 Name += MO.getSymbolName();
199 O << Name;
200 return;
201 }
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000202 default:
203 assert(0 && "Not implemented yet!");
204 }
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000205}
Anton Korobeynikova58fac92009-07-16 13:43:18 +0000206
207void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
208 const char* Modifier) {
209 const MachineOperand &Base = MI->getOperand(OpNum);
210
211 // Print displacement operand.
212 printOperand(MI, OpNum+1);
213
214 // Print base operand (if any)
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000215 if (Base.getReg()) {
Anton Korobeynikova58fac92009-07-16 13:43:18 +0000216 O << '(';
217 printOperand(MI, OpNum);
218 O << ')';
219 }
220}
221
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000222void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
223 const char* Modifier) {
224 const MachineOperand &Base = MI->getOperand(OpNum);
Anton Korobeynikovf7cefd92009-07-16 13:48:42 +0000225 const MachineOperand &Index = MI->getOperand(OpNum+2);
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000226
227 // Print displacement operand.
Anton Korobeynikovf7cefd92009-07-16 13:48:42 +0000228 printOperand(MI, OpNum+1);
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000229
230 // Print base operand (if any)
231 if (Base.getReg()) {
232 O << '(';
233 printOperand(MI, OpNum);
234 if (Index.getReg()) {
235 O << ',';
Anton Korobeynikovf7cefd92009-07-16 13:48:42 +0000236 printOperand(MI, OpNum+2);
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000237 }
238 O << ')';
239 } else
240 assert(!Index.getReg() && "Should allocate base register first!");
241}
242