hoist the call to processDebugLoc out of the generated
[oota-llvm.git] / lib / Target / CellSPU / AsmPrinter / SPUAsmPrinter.cpp
1 //===-- SPUAsmPrinter.cpp - Print machine instrs to Cell SPU assembly -------=//
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 Cell SPU assembly language. This printer
12 // is the output mechanism used by `llc'.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #define DEBUG_TYPE "asmprinter"
17 #include "SPU.h"
18 #include "SPUTargetMachine.h"
19 #include "llvm/Constants.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/Module.h"
22 #include "llvm/Assembly/Writer.h"
23 #include "llvm/CodeGen/AsmPrinter.h"
24 #include "llvm/CodeGen/DwarfWriter.h"
25 #include "llvm/CodeGen/MachineModuleInfo.h"
26 #include "llvm/CodeGen/MachineFunctionPass.h"
27 #include "llvm/CodeGen/MachineInstr.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/Target/TargetLoweringObjectFile.h"
31 #include "llvm/Target/TargetInstrInfo.h"
32 #include "llvm/Target/TargetOptions.h"
33 #include "llvm/Target/TargetRegisterInfo.h"
34 #include "llvm/Target/TargetRegistry.h"
35 #include "llvm/ADT/Statistic.h"
36 #include "llvm/ADT/StringExtras.h"
37 #include "llvm/Support/CommandLine.h"
38 #include "llvm/Support/Compiler.h"
39 #include "llvm/Support/Debug.h"
40 #include "llvm/Support/ErrorHandling.h"
41 #include "llvm/Support/FormattedStream.h"
42 #include "llvm/Support/Mangler.h"
43 #include "llvm/Support/MathExtras.h"
44 #include <set>
45 using namespace llvm;
46
47 namespace {
48   STATISTIC(EmittedInsts, "Number of machine instrs printed");
49
50   const std::string bss_section(".bss");
51
52   class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
53     std::set<std::string> FnStubs, GVStubs;
54   public:
55     explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
56                            const MCAsmInfo *T, bool V) :
57       AsmPrinter(O, TM, T, V) {}
58
59     virtual const char *getPassName() const {
60       return "STI CBEA SPU Assembly Printer";
61     }
62
63     SPUTargetMachine &getTM() {
64       return static_cast<SPUTargetMachine&>(TM);
65     }
66
67     /// printInstruction - This method is automatically generated by tablegen
68     /// from the instruction set description.  This method returns true if the
69     /// machine instruction was sufficiently described to print it, otherwise it
70     /// returns false.
71     void printInstruction(const MachineInstr *MI);
72
73     void printMachineInstruction(const MachineInstr *MI);
74     void printOp(const MachineOperand &MO);
75
76     /// printRegister - Print register according to target requirements.
77     ///
78     void printRegister(const MachineOperand &MO, bool R0AsZero) {
79       unsigned RegNo = MO.getReg();
80       assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
81              "Not physreg??");
82       O << TM.getRegisterInfo()->get(RegNo).AsmName;
83     }
84
85     void printOperand(const MachineInstr *MI, unsigned OpNo) {
86       const MachineOperand &MO = MI->getOperand(OpNo);
87       if (MO.isReg()) {
88         assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
89         O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
90       } else if (MO.isImm()) {
91         O << MO.getImm();
92       } else {
93         printOp(MO);
94       }
95     }
96
97     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
98                          unsigned AsmVariant, const char *ExtraCode);
99     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
100                                unsigned AsmVariant, const char *ExtraCode);
101
102
103     void
104     printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
105     {
106       int value = MI->getOperand(OpNo).getImm();
107       value = (value << (32 - 7)) >> (32 - 7);
108
109       assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
110              && "Invalid s7 argument");
111       O << value;
112     }
113
114     void
115     printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
116     {
117       unsigned int value = MI->getOperand(OpNo).getImm();
118       assert(value < (1 << 8) && "Invalid u7 argument");
119       O << value;
120     }
121
122     void
123     printShufAddr(const MachineInstr *MI, unsigned OpNo)
124     {
125       char value = MI->getOperand(OpNo).getImm();
126       O << (int) value;
127       O << "(";
128       printOperand(MI, OpNo+1);
129       O << ")";
130     }
131
132     void
133     printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
134     {
135       O << (short) MI->getOperand(OpNo).getImm();
136     }
137
138     void
139     printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
140     {
141       O << (unsigned short)MI->getOperand(OpNo).getImm();
142     }
143
144     void
145     printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
146     {
147       O << (unsigned)MI->getOperand(OpNo).getImm();
148     }
149
150     void
151     printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
152       // When used as the base register, r0 reads constant zero rather than
153       // the value contained in the register.  For this reason, the darwin
154       // assembler requires that we print r0 as 0 (no r) when used as the base.
155       const MachineOperand &MO = MI->getOperand(OpNo);
156       O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
157       O << ", ";
158       printOperand(MI, OpNo+1);
159     }
160
161     void
162     printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
163     {
164       unsigned int value = MI->getOperand(OpNo).getImm();
165       assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
166       O << value;
167     }
168
169     void
170     printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
171     {
172       short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
173                              >> 16);
174       assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
175              && "Invalid s10 argument");
176       O << value;
177     }
178
179     void
180     printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
181     {
182       short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
183                              >> 16);
184       assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
185       O << value;
186     }
187
188     void
189     printDFormAddr(const MachineInstr *MI, unsigned OpNo)
190     {
191       assert(MI->getOperand(OpNo).isImm() &&
192              "printDFormAddr first operand is not immediate");
193       int64_t value = int64_t(MI->getOperand(OpNo).getImm());
194       int16_t value16 = int16_t(value);
195       assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
196              && "Invalid dform s10 offset argument");
197       O << (value16 & ~0xf) << "(";
198       printOperand(MI, OpNo+1);
199       O << ")";
200     }
201
202     void
203     printAddr256K(const MachineInstr *MI, unsigned OpNo)
204     {
205       /* Note: operand 1 is an offset or symbol name. */
206       if (MI->getOperand(OpNo).isImm()) {
207         printS16ImmOperand(MI, OpNo);
208       } else {
209         printOp(MI->getOperand(OpNo));
210         if (MI->getOperand(OpNo+1).isImm()) {
211           int displ = int(MI->getOperand(OpNo+1).getImm());
212           if (displ > 0)
213             O << "+" << displ;
214           else if (displ < 0)
215             O << displ;
216         }
217       }
218     }
219
220     void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
221       printOp(MI->getOperand(OpNo));
222     }
223
224     void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
225       // Used to generate a ".-<target>", but it turns out that the assembler
226       // really wants the target.
227       //
228       // N.B.: This operand is used for call targets. Branch hints are another
229       // animal entirely.
230       printOp(MI->getOperand(OpNo));
231     }
232
233     void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
234       // HBR operands are generated in front of branches, hence, the
235       // program counter plus the target.
236       O << ".+";
237       printOp(MI->getOperand(OpNo));
238     }
239
240     void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
241       if (MI->getOperand(OpNo).isImm()) {
242         printS16ImmOperand(MI, OpNo);
243       } else {
244         printOp(MI->getOperand(OpNo));
245         O << "@h";
246       }
247     }
248
249     void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
250       if (MI->getOperand(OpNo).isImm()) {
251         printS16ImmOperand(MI, OpNo);
252       } else {
253         printOp(MI->getOperand(OpNo));
254         O << "@l";
255       }
256     }
257
258     /// Print local store address
259     void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
260       printOp(MI->getOperand(OpNo));
261     }
262
263     void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
264       if (MI->getOperand(OpNo).isImm()) {
265         int value = (int) MI->getOperand(OpNo).getImm();
266         assert((value >= 0 && value < 16)
267                && "Invalid negated immediate rotate 7-bit argument");
268         O << -value;
269       } else {
270         llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
271       }
272     }
273
274     void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
275       if (MI->getOperand(OpNo).isImm()) {
276         int value = (int) MI->getOperand(OpNo).getImm();
277         assert((value >= 0 && value <= 32)
278                && "Invalid negated immediate rotate 7-bit argument");
279         O << -value;
280       } else {
281         llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
282       }
283     }
284
285     virtual bool runOnMachineFunction(MachineFunction &F) = 0;
286   };
287
288   /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
289   class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
290     DwarfWriter *DW;
291   public:
292     explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
293                              const MCAsmInfo *T, bool V)
294       : SPUAsmPrinter(O, TM, T, V), DW(0) {}
295
296     virtual const char *getPassName() const {
297       return "STI CBEA SPU Assembly Printer";
298     }
299
300     bool runOnMachineFunction(MachineFunction &F);
301     bool doInitialization(Module &M);
302
303     void getAnalysisUsage(AnalysisUsage &AU) const {
304       AU.setPreservesAll();
305       AU.addRequired<MachineModuleInfo>();
306       AU.addRequired<DwarfWriter>();
307       SPUAsmPrinter::getAnalysisUsage(AU);
308     }
309
310     //! Emit a global variable according to its section and type
311     void PrintGlobalVariable(const GlobalVariable* GVar);
312   };
313 } // end of anonymous namespace
314
315 // Include the auto-generated portion of the assembly writer
316 #include "SPUGenAsmWriter.inc"
317
318 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
319   switch (MO.getType()) {
320   case MachineOperand::MO_Immediate:
321     llvm_report_error("printOp() does not handle immediate values");
322     return;
323
324   case MachineOperand::MO_MachineBasicBlock:
325     printBasicBlockLabel(MO.getMBB());
326     return;
327   case MachineOperand::MO_JumpTableIndex:
328     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
329       << '_' << MO.getIndex();
330     return;
331   case MachineOperand::MO_ConstantPoolIndex:
332     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
333       << '_' << MO.getIndex();
334     return;
335   case MachineOperand::MO_ExternalSymbol:
336     // Computing the address of an external symbol, not calling it.
337     if (TM.getRelocationModel() != Reloc::Static) {
338       std::string Name(MAI->getGlobalPrefix()); Name += MO.getSymbolName();
339       GVStubs.insert(Name);
340       O << "L" << Name << "$non_lazy_ptr";
341       return;
342     }
343     O << MAI->getGlobalPrefix() << MO.getSymbolName();
344     return;
345   case MachineOperand::MO_GlobalAddress: {
346     // Computing the address of a global symbol, not calling it.
347     GlobalValue *GV = MO.getGlobal();
348     std::string Name = Mang->getMangledName(GV);
349
350     // External or weakly linked global variables need non-lazily-resolved
351     // stubs
352     if (TM.getRelocationModel() != Reloc::Static) {
353       if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
354             GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
355         GVStubs.insert(Name);
356         O << "L" << Name << "$non_lazy_ptr";
357         return;
358       }
359     }
360     O << Name;
361     return;
362   }
363
364   default:
365     O << "<unknown operand type: " << MO.getType() << ">";
366     return;
367   }
368 }
369
370 /// PrintAsmOperand - Print out an operand for an inline asm expression.
371 ///
372 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
373                                     unsigned AsmVariant,
374                                     const char *ExtraCode) {
375   // Does this asm operand have a single letter operand modifier?
376   if (ExtraCode && ExtraCode[0]) {
377     if (ExtraCode[1] != 0) return true; // Unknown modifier.
378
379     switch (ExtraCode[0]) {
380     default: return true;  // Unknown modifier.
381     case 'L': // Write second word of DImode reference.
382       // Verify that this operand has two consecutive registers.
383       if (!MI->getOperand(OpNo).isReg() ||
384           OpNo+1 == MI->getNumOperands() ||
385           !MI->getOperand(OpNo+1).isReg())
386         return true;
387       ++OpNo;   // Return the high-part.
388       break;
389     }
390   }
391
392   printOperand(MI, OpNo);
393   return false;
394 }
395
396 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
397                                           unsigned OpNo,
398                                           unsigned AsmVariant,
399                                           const char *ExtraCode) {
400   if (ExtraCode && ExtraCode[0])
401     return true; // Unknown modifier.
402   printMemRegReg(MI, OpNo);
403   return false;
404 }
405
406 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
407 /// to the current output stream.
408 ///
409 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
410   ++EmittedInsts;
411   processDebugLoc(MI->getDebugLoc());
412   printInstruction(MI);
413 }
414
415 /// runOnMachineFunction - This uses the printMachineInstruction()
416 /// method to print assembly for each instruction.
417 ///
418 bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
419   this->MF = &MF;
420
421   SetupMachineFunction(MF);
422   O << "\n\n";
423
424   // Print out constants referenced by the function
425   EmitConstantPool(MF.getConstantPool());
426
427   // Print out labels for the function.
428   const Function *F = MF.getFunction();
429
430   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
431   EmitAlignment(MF.getAlignment(), F);
432
433   switch (F->getLinkage()) {
434   default: llvm_unreachable("Unknown linkage type!");
435   case Function::PrivateLinkage:
436   case Function::LinkerPrivateLinkage:
437   case Function::InternalLinkage:  // Symbols default to internal.
438     break;
439   case Function::ExternalLinkage:
440     O << "\t.global\t" << CurrentFnName << "\n"
441       << "\t.type\t" << CurrentFnName << ", @function\n";
442     break;
443   case Function::WeakAnyLinkage:
444   case Function::WeakODRLinkage:
445   case Function::LinkOnceAnyLinkage:
446   case Function::LinkOnceODRLinkage:
447     O << "\t.global\t" << CurrentFnName << "\n";
448     O << "\t.weak_definition\t" << CurrentFnName << "\n";
449     break;
450   }
451   O << CurrentFnName << ":\n";
452
453   // Emit pre-function debug information.
454   DW->BeginFunction(&MF);
455
456   // Print out code for the function.
457   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
458        I != E; ++I) {
459     // Print a label for the basic block.
460     if (I != MF.begin()) {
461       printBasicBlockLabel(I, true, true);
462       O << '\n';
463     }
464     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
465          II != E; ++II) {
466       // Print the assembly for the instruction.
467       printMachineInstruction(II);
468     }
469   }
470
471   O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
472
473   // Print out jump tables referenced by the function.
474   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
475
476   // Emit post-function debug information.
477   DW->EndFunction(&MF);
478
479   // We didn't modify anything.
480   return false;
481 }
482
483
484 bool LinuxAsmPrinter::doInitialization(Module &M) {
485   bool Result = AsmPrinter::doInitialization(M);
486   DW = getAnalysisIfAvailable<DwarfWriter>();
487   return Result;
488 }
489
490 /*!
491   Emit a global variable according to its section, alignment, etc.
492
493   \note This code was shamelessly copied from the PowerPC's assembly printer,
494   which sort of screams for some kind of refactorization of common code.
495  */
496 void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
497   const TargetData *TD = TM.getTargetData();
498
499   if (!GVar->hasInitializer())
500     return;
501
502   // Check to see if this is a special global used by LLVM, if so, emit it.
503   if (EmitSpecialLLVMGlobal(GVar))
504     return;
505
506   std::string name = Mang->getMangledName(GVar);
507
508   printVisibility(name, GVar->getVisibility());
509
510   Constant *C = GVar->getInitializer();
511   const Type *Type = C->getType();
512   unsigned Size = TD->getTypeAllocSize(Type);
513   unsigned Align = TD->getPreferredAlignmentLog(GVar);
514
515   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
516                                                                   TM));
517
518   if (C->isNullValue() && /* FIXME: Verify correct */
519       !GVar->hasSection() &&
520       (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
521        GVar->isWeakForLinker())) {
522       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
523
524       if (GVar->hasExternalLinkage()) {
525         O << "\t.global " << name << '\n';
526         O << "\t.type " << name << ", @object\n";
527         O << name << ":\n";
528         O << "\t.zero " << Size << '\n';
529       } else if (GVar->hasLocalLinkage()) {
530         O << MAI->getLCOMMDirective() << name << ',' << Size;
531       } else {
532         O << ".comm " << name << ',' << Size;
533       }
534       O << "\t\t" << MAI->getCommentString() << " '";
535       WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
536       O << "'\n";
537       return;
538   }
539
540   switch (GVar->getLinkage()) {
541     // Should never be seen for the CellSPU platform...
542    case GlobalValue::LinkOnceAnyLinkage:
543    case GlobalValue::LinkOnceODRLinkage:
544    case GlobalValue::WeakAnyLinkage:
545    case GlobalValue::WeakODRLinkage:
546    case GlobalValue::CommonLinkage:
547     O << "\t.global " << name << '\n'
548       << "\t.type " << name << ", @object\n"
549       << "\t.weak " << name << '\n';
550     break;
551    case GlobalValue::AppendingLinkage:
552     // FIXME: appending linkage variables should go into a section of
553     // their name or something.  For now, just emit them as external.
554    case GlobalValue::ExternalLinkage:
555     // If external or appending, declare as a global symbol
556     O << "\t.global " << name << '\n'
557       << "\t.type " << name << ", @object\n";
558     // FALL THROUGH
559    case GlobalValue::PrivateLinkage:
560    case GlobalValue::LinkerPrivateLinkage:
561    case GlobalValue::InternalLinkage:
562     break;
563    default:
564     llvm_report_error("Unknown linkage type!");
565   }
566
567   EmitAlignment(Align, GVar);
568   O << name << ":\t\t\t\t" << MAI->getCommentString() << " '";
569   WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
570   O << "'\n";
571
572   EmitGlobalConstant(C);
573   O << '\n';
574 }
575
576 // Force static initialization.
577 extern "C" void LLVMInitializeCellSPUAsmPrinter() { 
578   RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);
579 }