2c73517db9bf45e44fcf689b5a82e732cdbb3997
[oota-llvm.git] / lib / Target / SystemZ / AsmPrinter / SystemZAsmPrinter.cpp
1 //===-- 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/Target/TargetLoweringObjectFile.h"
31 #include "llvm/Target/TargetRegistry.h"
32 #include "llvm/ADT/Statistic.h"
33 #include "llvm/Support/Compiler.h"
34 #include "llvm/Support/FormattedStream.h"
35 #include "llvm/Support/Mangler.h"
36
37 using namespace llvm;
38
39 STATISTIC(EmittedInsts, "Number of machine instrs printed");
40
41 namespace {
42   class VISIBILITY_HIDDEN SystemZAsmPrinter : public AsmPrinter {
43   public:
44     SystemZAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
45                       const TargetAsmInfo *TAI, bool V)
46       : AsmPrinter(O, TM, TAI, V) {}
47
48     virtual const char *getPassName() const {
49       return "SystemZ Assembly Printer";
50     }
51
52     void printOperand(const MachineInstr *MI, int OpNum,
53                       const char* Modifier = 0);
54     void printPCRelImmOperand(const MachineInstr *MI, int OpNum);
55     void printRIAddrOperand(const MachineInstr *MI, int OpNum,
56                             const char* Modifier = 0);
57     void printRRIAddrOperand(const MachineInstr *MI, int OpNum,
58                              const char* Modifier = 0);
59     void printS16ImmOperand(const MachineInstr *MI, int OpNum) {
60       O << (int16_t)MI->getOperand(OpNum).getImm();
61     }
62     void printS32ImmOperand(const MachineInstr *MI, int OpNum) {
63       O << (int32_t)MI->getOperand(OpNum).getImm();
64     }
65
66     bool printInstruction(const MachineInstr *MI);  // autogenerated.
67     void printMachineInstruction(const MachineInstr * MI);
68
69     void emitFunctionHeader(const MachineFunction &MF);
70     bool runOnMachineFunction(MachineFunction &F);
71     void PrintGlobalVariable(const GlobalVariable* GVar);
72
73     void getAnalysisUsage(AnalysisUsage &AU) const {
74       AsmPrinter::getAnalysisUsage(AU);
75       AU.setPreservesAll();
76     }
77   };
78 } // end of anonymous namespace
79
80 #include "SystemZGenAsmWriter.inc"
81
82 void SystemZAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
83   unsigned FnAlign = MF.getAlignment();
84   const Function *F = MF.getFunction();
85
86   SwitchToSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
87
88   EmitAlignment(FnAlign, F);
89
90   switch (F->getLinkage()) {
91   default: assert(0 && "Unknown linkage type!");
92   case Function::InternalLinkage:  // Symbols default to internal.
93   case Function::PrivateLinkage:
94   case Function::LinkerPrivateLinkage:
95     break;
96   case Function::ExternalLinkage:
97     O << "\t.globl\t" << CurrentFnName << '\n';
98     break;
99   case Function::LinkOnceAnyLinkage:
100   case Function::LinkOnceODRLinkage:
101   case Function::WeakAnyLinkage:
102   case Function::WeakODRLinkage:
103     O << "\t.weak\t" << CurrentFnName << '\n';
104     break;
105   }
106
107   printVisibility(CurrentFnName, F->getVisibility());
108
109   O << "\t.type\t" << CurrentFnName << ",@function\n"
110     << CurrentFnName << ":\n";
111 }
112
113 bool SystemZAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
114   SetupMachineFunction(MF);
115   O << "\n\n";
116
117   // Print out constants referenced by the function
118   EmitConstantPool(MF.getConstantPool());
119
120   // Print the 'header' of function
121   emitFunctionHeader(MF);
122
123   // Print out code for the function.
124   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
125        I != E; ++I) {
126     // Print a label for the basic block.
127     if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) {
128       // This is an entry block or a block that's only reachable via a
129       // fallthrough edge. In non-VerboseAsm mode, don't print the label.
130     } else {
131       printBasicBlockLabel(I, true, true, VerboseAsm);
132       O << '\n';
133     }
134
135     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
136          II != E; ++II)
137       // Print the assembly for the instruction.
138       printMachineInstruction(II);
139   }
140
141   if (TAI->hasDotTypeDotSizeDirective())
142     O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
143
144   // Print out jump tables referenced by the function.
145   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
146
147   // We didn't modify anything
148   return false;
149 }
150
151 void SystemZAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
152   ++EmittedInsts;
153
154   // Call the autogenerated instruction printer routines.
155   printInstruction(MI);
156 }
157
158 void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum) {
159   const MachineOperand &MO = MI->getOperand(OpNum);
160   switch (MO.getType()) {
161   case MachineOperand::MO_Immediate:
162     O << MO.getImm();
163     return;
164   case MachineOperand::MO_MachineBasicBlock:
165     printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
166     return;
167   case MachineOperand::MO_GlobalAddress: {
168     const GlobalValue *GV = MO.getGlobal();
169     std::string Name = Mang->getMangledName(GV);
170
171     O << Name;
172
173     // Assemble calls via PLT for externally visible symbols if PIC.
174     if (TM.getRelocationModel() == Reloc::PIC_ &&
175         !GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
176         !GV->hasLocalLinkage())
177       O << "@PLT";
178
179     printOffset(MO.getOffset());
180     return;
181   }
182   case MachineOperand::MO_ExternalSymbol: {
183     std::string Name(TAI->getGlobalPrefix());
184     Name += MO.getSymbolName();
185     O << Name;
186
187     if (TM.getRelocationModel() == Reloc::PIC_)
188       O << "@PLT";
189
190     return;
191   }
192   default:
193     assert(0 && "Not implemented yet!");
194   }
195 }
196
197
198 void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
199                                      const char* Modifier) {
200   const MachineOperand &MO = MI->getOperand(OpNum);
201   switch (MO.getType()) {
202   case MachineOperand::MO_Register: {
203     assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
204             "Virtual registers should be already mapped!");
205     unsigned Reg = MO.getReg();
206     if (Modifier && strncmp(Modifier, "subreg", 6) == 0) {
207       if (strncmp(Modifier + 7, "even", 4) == 0)
208         Reg = TRI->getSubReg(Reg, SystemZ::SUBREG_EVEN);
209       else if (strncmp(Modifier + 7, "odd", 3) == 0)
210         Reg = TRI->getSubReg(Reg, SystemZ::SUBREG_ODD);
211       else
212         assert(0 && "Invalid subreg modifier");
213     }
214
215     O << '%' << TRI->getAsmName(Reg);
216     return;
217   }
218   case MachineOperand::MO_Immediate:
219     O << MO.getImm();
220     return;
221   case MachineOperand::MO_MachineBasicBlock:
222     printBasicBlockLabel(MO.getMBB());
223     return;
224   case MachineOperand::MO_JumpTableIndex:
225     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
226       << MO.getIndex();
227
228     return;
229   case MachineOperand::MO_ConstantPoolIndex:
230     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
231       << MO.getIndex();
232
233     printOffset(MO.getOffset());
234     break;
235   case MachineOperand::MO_GlobalAddress: {
236     const GlobalValue *GV = MO.getGlobal();
237     std::string Name = Mang->getMangledName(GV);
238
239     O << Name;
240     break;
241   }
242   case MachineOperand::MO_ExternalSymbol: {
243     std::string Name(TAI->getGlobalPrefix());
244     Name += MO.getSymbolName();
245     O << Name;
246     break;
247   }
248   default:
249     assert(0 && "Not implemented yet!");
250   }
251
252   switch (MO.getTargetFlags()) {
253   default:
254     llvm_unreachable("Unknown target flag on GV operand");
255   case SystemZII::MO_NO_FLAG:
256     break;
257   case SystemZII::MO_GOTENT:    O << "@GOTENT";    break;
258   case SystemZII::MO_PLT:       O << "@PLT";       break;
259   }
260
261   printOffset(MO.getOffset());
262 }
263
264 void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
265                                            const char* Modifier) {
266   const MachineOperand &Base = MI->getOperand(OpNum);
267
268   // Print displacement operand.
269   printOperand(MI, OpNum+1);
270
271   // Print base operand (if any)
272   if (Base.getReg()) {
273     O << '(';
274     printOperand(MI, OpNum);
275     O << ')';
276   }
277 }
278
279 void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
280                                             const char* Modifier) {
281   const MachineOperand &Base = MI->getOperand(OpNum);
282   const MachineOperand &Index = MI->getOperand(OpNum+2);
283
284   // Print displacement operand.
285   printOperand(MI, OpNum+1);
286
287   // Print base operand (if any)
288   if (Base.getReg()) {
289     O << '(';
290     printOperand(MI, OpNum);
291     if (Index.getReg()) {
292       O << ',';
293       printOperand(MI, OpNum+2);
294     }
295     O << ')';
296   } else
297     assert(!Index.getReg() && "Should allocate base register first!");
298 }
299
300 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
301 /// Don't print things like \\n or \\0.
302 static void PrintUnmangledNameSafely(const Value *V, 
303                                      formatted_raw_ostream &OS) {
304   for (StringRef::iterator it = V->getName().begin(), 
305          ie = V->getName().end(); it != ie; ++it)
306     if (isprint(*it))
307       OS << *it;
308 }
309
310 void SystemZAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
311   const TargetData *TD = TM.getTargetData();
312
313   if (!GVar->hasInitializer())
314     return;   // External global require no code
315
316   // Check to see if this is a special global used by LLVM, if so, emit it.
317   if (EmitSpecialLLVMGlobal(GVar))
318     return;
319
320   std::string name = Mang->getMangledName(GVar);
321   Constant *C = GVar->getInitializer();
322   unsigned Size = TD->getTypeAllocSize(C->getType());
323   unsigned Align = std::max(1U, TD->getPreferredAlignmentLog(GVar));
324
325   printVisibility(name, GVar->getVisibility());
326
327   O << "\t.type\t" << name << ",@object\n";
328
329   SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, Mang, TM));
330
331   if (C->isNullValue() && !GVar->hasSection() &&
332       !GVar->isThreadLocal() &&
333       (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
334
335     if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
336
337     if (GVar->hasLocalLinkage())
338       O << "\t.local\t" << name << '\n';
339
340     O << TAI->getCOMMDirective()  << name << ',' << Size;
341     if (TAI->getCOMMDirectiveTakesAlignment())
342       O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
343
344     if (VerboseAsm) {
345       O << "\t\t" << TAI->getCommentString() << ' ';
346       PrintUnmangledNameSafely(GVar, O);
347     }
348     O << '\n';
349     return;
350   }
351
352   switch (GVar->getLinkage()) {
353   case GlobalValue::CommonLinkage:
354   case GlobalValue::LinkOnceAnyLinkage:
355   case GlobalValue::LinkOnceODRLinkage:
356   case GlobalValue::WeakAnyLinkage:
357   case GlobalValue::WeakODRLinkage:
358     O << "\t.weak\t" << name << '\n';
359     break;
360   case GlobalValue::DLLExportLinkage:
361   case GlobalValue::AppendingLinkage:
362     // FIXME: appending linkage variables should go into a section of
363     // their name or something.  For now, just emit them as external.
364   case GlobalValue::ExternalLinkage:
365     // If external or appending, declare as a global symbol
366     O << "\t.globl " << name << '\n';
367     // FALL THROUGH
368   case GlobalValue::PrivateLinkage:
369   case GlobalValue::LinkerPrivateLinkage:
370   case GlobalValue::InternalLinkage:
371      break;
372   default:
373     assert(0 && "Unknown linkage type!");
374   }
375
376   // Use 16-bit alignment by default to simplify bunch of stuff
377   EmitAlignment(Align, GVar, 1);
378   O << name << ":";
379   if (VerboseAsm) {
380     O << "\t\t\t\t" << TAI->getCommentString() << ' ';
381     PrintUnmangledNameSafely(GVar, O);
382   }
383   O << '\n';
384   if (TAI->hasDotTypeDotSizeDirective())
385     O << "\t.size\t" << name << ", " << Size << '\n';
386
387   EmitGlobalConstant(C);
388 }
389
390 // Force static initialization.
391 extern "C" void LLVMInitializeSystemZAsmPrinter() {
392   RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
393 }