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