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