a4475036966b42404ef6294aa5597f532a8b4cb7
[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/MDNode.h"
23 #include "llvm/Assembly/Writer.h"
24 #include "llvm/CodeGen/AsmPrinter.h"
25 #include "llvm/CodeGen/DwarfWriter.h"
26 #include "llvm/CodeGen/MachineModuleInfo.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineInstr.h"
29 #include "llvm/Support/Mangler.h"
30 #include "llvm/Support/MathExtras.h"
31 #include "llvm/Support/CommandLine.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/Compiler.h"
35 #include "llvm/Support/FormattedStream.h"
36 #include "llvm/Target/TargetAsmInfo.h"
37 #include "llvm/Target/TargetRegisterInfo.h"
38 #include "llvm/Target/TargetInstrInfo.h"
39 #include "llvm/Target/TargetOptions.h"
40 #include "llvm/Target/TargetRegistry.h"
41 #include "llvm/ADT/Statistic.h"
42 #include "llvm/ADT/StringExtras.h"
43 #include <set>
44 using namespace llvm;
45
46 namespace {
47   STATISTIC(EmittedInsts, "Number of machine instrs printed");
48
49   const std::string bss_section(".bss");
50
51   class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
52     std::set<std::string> FnStubs, GVStubs;
53   public:
54     explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
55                            const TargetAsmInfo *T, bool V) :
56       AsmPrinter(O, TM, T, V) {}
57
58     virtual const char *getPassName() const {
59       return "STI CBEA SPU Assembly Printer";
60     }
61
62     SPUTargetMachine &getTM() {
63       return static_cast<SPUTargetMachine&>(TM);
64     }
65
66     /// printInstruction - This method is automatically generated by tablegen
67     /// from the instruction set description.  This method returns true if the
68     /// machine instruction was sufficiently described to print it, otherwise it
69     /// returns false.
70     bool printInstruction(const MachineInstr *MI);
71
72     void printMachineInstruction(const MachineInstr *MI);
73     void printOp(const MachineOperand &MO);
74
75     /// printRegister - Print register according to target requirements.
76     ///
77     void printRegister(const MachineOperand &MO, bool R0AsZero) {
78       unsigned RegNo = MO.getReg();
79       assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
80              "Not physreg??");
81       O << TM.getRegisterInfo()->get(RegNo).AsmName;
82     }
83
84     void printOperand(const MachineInstr *MI, unsigned OpNo) {
85       const MachineOperand &MO = MI->getOperand(OpNo);
86       if (MO.isReg()) {
87         assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
88         O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
89       } else if (MO.isImm()) {
90         O << MO.getImm();
91       } else {
92         printOp(MO);
93       }
94     }
95
96     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
97                          unsigned AsmVariant, const char *ExtraCode);
98     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
99                                unsigned AsmVariant, const char *ExtraCode);
100
101
102     void
103     printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
104     {
105       int value = MI->getOperand(OpNo).getImm();
106       value = (value << (32 - 7)) >> (32 - 7);
107
108       assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
109              && "Invalid s7 argument");
110       O << value;
111     }
112
113     void
114     printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
115     {
116       unsigned int value = MI->getOperand(OpNo).getImm();
117       assert(value < (1 << 8) && "Invalid u7 argument");
118       O << value;
119     }
120
121     void
122     printShufAddr(const MachineInstr *MI, unsigned OpNo)
123     {
124       char value = MI->getOperand(OpNo).getImm();
125       O << (int) value;
126       O << "(";
127       printOperand(MI, OpNo+1);
128       O << ")";
129     }
130
131     void
132     printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
133     {
134       O << (short) MI->getOperand(OpNo).getImm();
135     }
136
137     void
138     printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
139     {
140       O << (unsigned short)MI->getOperand(OpNo).getImm();
141     }
142
143     void
144     printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
145     {
146       O << (unsigned)MI->getOperand(OpNo).getImm();
147     }
148
149     void
150     printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
151       // When used as the base register, r0 reads constant zero rather than
152       // the value contained in the register.  For this reason, the darwin
153       // assembler requires that we print r0 as 0 (no r) when used as the base.
154       const MachineOperand &MO = MI->getOperand(OpNo);
155       O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
156       O << ", ";
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     DwarfWriter *DW;
290   public:
291     explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
292                              const TargetAsmInfo *T, bool V)
293       : SPUAsmPrinter(O, TM, T, V), DW(0) {}
294
295     virtual const char *getPassName() const {
296       return "STI CBEA SPU Assembly Printer";
297     }
298
299     bool runOnMachineFunction(MachineFunction &F);
300     bool doInitialization(Module &M);
301
302     void getAnalysisUsage(AnalysisUsage &AU) const {
303       AU.setPreservesAll();
304       AU.addRequired<MachineModuleInfo>();
305       AU.addRequired<DwarfWriter>();
306       SPUAsmPrinter::getAnalysisUsage(AU);
307     }
308
309     //! Emit a global variable according to its section and type
310     void PrintGlobalVariable(const GlobalVariable* GVar);
311   };
312 } // end of anonymous namespace
313
314 // Include the auto-generated portion of the assembly writer
315 #include "SPUGenAsmWriter.inc"
316
317 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
318   switch (MO.getType()) {
319   case MachineOperand::MO_Immediate:
320     llvm_report_error("printOp() does not handle immediate values");
321     return;
322
323   case MachineOperand::MO_MachineBasicBlock:
324     printBasicBlockLabel(MO.getMBB());
325     return;
326   case MachineOperand::MO_JumpTableIndex:
327     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
328       << '_' << MO.getIndex();
329     return;
330   case MachineOperand::MO_ConstantPoolIndex:
331     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
332       << '_' << MO.getIndex();
333     return;
334   case MachineOperand::MO_ExternalSymbol:
335     // Computing the address of an external symbol, not calling it.
336     if (TM.getRelocationModel() != Reloc::Static) {
337       std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
338       GVStubs.insert(Name);
339       O << "L" << Name << "$non_lazy_ptr";
340       return;
341     }
342     O << TAI->getGlobalPrefix() << MO.getSymbolName();
343     return;
344   case MachineOperand::MO_GlobalAddress: {
345     // Computing the address of a global symbol, not calling it.
346     GlobalValue *GV = MO.getGlobal();
347     std::string Name = Mang->getMangledName(GV);
348
349     // External or weakly linked global variables need non-lazily-resolved
350     // stubs
351     if (TM.getRelocationModel() != Reloc::Static) {
352       if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
353             GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
354         GVStubs.insert(Name);
355         O << "L" << Name << "$non_lazy_ptr";
356         return;
357       }
358     }
359     O << Name;
360     return;
361   }
362
363   default:
364     O << "<unknown operand type: " << MO.getType() << ">";
365     return;
366   }
367 }
368
369 /// PrintAsmOperand - Print out an operand for an inline asm expression.
370 ///
371 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
372                                     unsigned AsmVariant,
373                                     const char *ExtraCode) {
374   // Does this asm operand have a single letter operand modifier?
375   if (ExtraCode && ExtraCode[0]) {
376     if (ExtraCode[1] != 0) return true; // Unknown modifier.
377
378     switch (ExtraCode[0]) {
379     default: return true;  // Unknown modifier.
380     case 'L': // Write second word of DImode reference.
381       // Verify that this operand has two consecutive registers.
382       if (!MI->getOperand(OpNo).isReg() ||
383           OpNo+1 == MI->getNumOperands() ||
384           !MI->getOperand(OpNo+1).isReg())
385         return true;
386       ++OpNo;   // Return the high-part.
387       break;
388     }
389   }
390
391   printOperand(MI, OpNo);
392   return false;
393 }
394
395 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
396                                           unsigned OpNo,
397                                           unsigned AsmVariant,
398                                           const char *ExtraCode) {
399   if (ExtraCode && ExtraCode[0])
400     return true; // Unknown modifier.
401   printMemRegReg(MI, OpNo);
402   return false;
403 }
404
405 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
406 /// to the current output stream.
407 ///
408 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
409   ++EmittedInsts;
410   printInstruction(MI);
411 }
412
413 /// runOnMachineFunction - This uses the printMachineInstruction()
414 /// method to print assembly for each instruction.
415 ///
416 bool
417 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
418 {
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   SwitchToSection(TAI->SectionForGlobal(F));
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   SwitchToTextSection("\t.text");
488   return Result;
489 }
490
491 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
492 /// Don't print things like \\n or \\0.
493 static void PrintUnmangledNameSafely(const Value *V, formatted_raw_ostream &OS) {
494   for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
495        Name != E; ++Name)
496     if (isprint(*Name))
497       OS << *Name;
498 }
499
500 /*!
501   Emit a global variable according to its section, alignment, etc.
502
503   \note This code was shamelessly copied from the PowerPC's assembly printer,
504   which sort of screams for some kind of refactorization of common code.
505  */
506 void LinuxAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
507   const TargetData *TD = TM.getTargetData();
508
509   if (!GVar->hasInitializer())
510     return;
511
512   // Check to see if this is a special global used by LLVM, if so, emit it.
513   if (EmitSpecialLLVMGlobal(GVar))
514     return;
515
516   std::string name = Mang->getMangledName(GVar);
517
518   printVisibility(name, GVar->getVisibility());
519
520   Constant *C = GVar->getInitializer();
521   if (isa<MDNode>(C) || isa<MDString>(C))
522     return;
523   const Type *Type = C->getType();
524   unsigned Size = TD->getTypeAllocSize(Type);
525   unsigned Align = TD->getPreferredAlignmentLog(GVar);
526
527   SwitchToSection(TAI->SectionForGlobal(GVar));
528
529   if (C->isNullValue() && /* FIXME: Verify correct */
530       !GVar->hasSection() &&
531       (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
532        GVar->isWeakForLinker())) {
533       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
534
535       if (GVar->hasExternalLinkage()) {
536         O << "\t.global " << name << '\n';
537         O << "\t.type " << name << ", @object\n";
538         O << name << ":\n";
539         O << "\t.zero " << Size << '\n';
540       } else if (GVar->hasLocalLinkage()) {
541         O << TAI->getLCOMMDirective() << name << ',' << Size;
542       } else {
543         O << ".comm " << name << ',' << Size;
544       }
545       O << "\t\t" << TAI->getCommentString() << " '";
546       PrintUnmangledNameSafely(GVar, O);
547       O << "'\n";
548       return;
549   }
550
551   switch (GVar->getLinkage()) {
552     // Should never be seen for the CellSPU platform...
553    case GlobalValue::LinkOnceAnyLinkage:
554    case GlobalValue::LinkOnceODRLinkage:
555    case GlobalValue::WeakAnyLinkage:
556    case GlobalValue::WeakODRLinkage:
557    case GlobalValue::CommonLinkage:
558     O << "\t.global " << name << '\n'
559       << "\t.type " << name << ", @object\n"
560       << "\t.weak " << name << '\n';
561     break;
562    case GlobalValue::AppendingLinkage:
563     // FIXME: appending linkage variables should go into a section of
564     // their name or something.  For now, just emit them as external.
565    case GlobalValue::ExternalLinkage:
566     // If external or appending, declare as a global symbol
567     O << "\t.global " << name << '\n'
568       << "\t.type " << name << ", @object\n";
569     // FALL THROUGH
570    case GlobalValue::PrivateLinkage:
571    case GlobalValue::LinkerPrivateLinkage:
572    case GlobalValue::InternalLinkage:
573     break;
574    default:
575     llvm_report_error("Unknown linkage type!");
576   }
577
578   EmitAlignment(Align, GVar);
579   O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
580   PrintUnmangledNameSafely(GVar, O);
581   O << "'\n";
582
583   EmitGlobalConstant(C);
584   O << '\n';
585 }
586
587 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
588 /// assembly code for a MachineFunction to the given output stream, in a format
589 /// that the Linux SPU assembler can deal with.
590 ///
591 FunctionPass *llvm::createSPUAsmPrinterPass(formatted_raw_ostream &o,
592                                             TargetMachine &tm,
593                                             bool verbose) {
594   return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
595 }
596
597 // Force static initialization.
598 extern "C" void LLVMInitializeCellSPUAsmPrinter() { 
599   TargetRegistry::RegisterAsmPrinter(TheCellSPUTarget, createSPUAsmPrinterPass);
600 }