15cacd146aab13eb3133c2f7163193f3e92d22ba
[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   class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
49     std::set<std::string> FnStubs, GVStubs;
50   public:
51     explicit SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
52                            const TargetAsmInfo *T, CodeGenOpt::Level OL,
53                            bool V) :
54       AsmPrinter(O, TM, T, OL, V) {}
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     printShufAddr(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     printDFormAddr(const MachineInstr *MI, unsigned OpNo)
187     {
188       assert(MI->getOperand(OpNo).isImm() &&
189              "printDFormAddr first operand is not immediate");
190       int64_t value = int64_t(MI->getOperand(OpNo).getImm());
191       int16_t value16 = int16_t(value);
192       assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
193              && "Invalid dform s10 offset argument");
194       O << (value16 & ~0xf) << "(";
195       printOperand(MI, OpNo+1);
196       O << ")";
197     }
198
199     void
200     printAddr256K(const MachineInstr *MI, unsigned OpNo)
201     {
202       /* Note: operand 1 is an offset or symbol name. */
203       if (MI->getOperand(OpNo).isImm()) {
204         printS16ImmOperand(MI, OpNo);
205       } else {
206         printOp(MI->getOperand(OpNo));
207         if (MI->getOperand(OpNo+1).isImm()) {
208           int displ = int(MI->getOperand(OpNo+1).getImm());
209           if (displ > 0)
210             O << "+" << displ;
211           else if (displ < 0)
212             O << displ;
213         }
214       }
215     }
216
217     void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
218       printOp(MI->getOperand(OpNo));
219     }
220
221     void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
222       // Used to generate a ".-<target>", but it turns out that the assembler
223       // really wants the target.
224       //
225       // N.B.: This operand is used for call targets. Branch hints are another
226       // animal entirely.
227       printOp(MI->getOperand(OpNo));
228     }
229
230     void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
231       // HBR operands are generated in front of branches, hence, the
232       // program counter plus the target.
233       O << ".+";
234       printOp(MI->getOperand(OpNo));
235     }
236
237     void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
238       if (MI->getOperand(OpNo).isImm()) {
239         printS16ImmOperand(MI, OpNo);
240       } else {
241         printOp(MI->getOperand(OpNo));
242         O << "@h";
243       }
244     }
245
246     void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
247       if (MI->getOperand(OpNo).isImm()) {
248         printS16ImmOperand(MI, OpNo);
249       } else {
250         printOp(MI->getOperand(OpNo));
251         O << "@l";
252       }
253     }
254
255     /// Print local store address
256     void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
257       printOp(MI->getOperand(OpNo));
258     }
259
260     void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
261       if (MI->getOperand(OpNo).isImm()) {
262         int value = (int) MI->getOperand(OpNo).getImm();
263         assert((value >= 0 && value < 16)
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     void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
272       if (MI->getOperand(OpNo).isImm()) {
273         int value = (int) MI->getOperand(OpNo).getImm();
274         assert((value >= 0 && value <= 32)
275                && "Invalid negated immediate rotate 7-bit argument");
276         O << -value;
277       } else {
278         assert(0 &&"Invalid/non-immediate rotate amount in printRotateNeg7Imm");
279       }
280     }
281
282     virtual bool runOnMachineFunction(MachineFunction &F) = 0;
283     //! Assembly printer cleanup after function has been emitted
284     virtual bool doFinalization(Module &M) = 0;
285   };
286
287   /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
288   class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
289     DwarfWriter *DW;
290     MachineModuleInfo *MMI;
291   public:
292     explicit LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
293                              const TargetAsmInfo *T, CodeGenOpt::Level F,
294                              bool V)
295       : SPUAsmPrinter(O, TM, T, F, V), DW(0), MMI(0) {}
296
297     virtual const char *getPassName() const {
298       return "STI CBEA SPU Assembly Printer";
299     }
300
301     bool runOnMachineFunction(MachineFunction &F);
302     bool doInitialization(Module &M);
303     //! Dump globals, perform cleanup after function emission
304     bool doFinalization(Module &M);
305
306     void getAnalysisUsage(AnalysisUsage &AU) const {
307       AU.setPreservesAll();
308       AU.addRequired<MachineModuleInfo>();
309       AU.addRequired<DwarfWriter>();
310       SPUAsmPrinter::getAnalysisUsage(AU);
311     }
312
313     //! Emit a global variable according to its section and type
314     void printModuleLevelGV(const GlobalVariable* GVar);
315   };
316 } // end of anonymous namespace
317
318 // Include the auto-generated portion of the assembly writer
319 #include "SPUGenAsmWriter.inc"
320
321 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
322   switch (MO.getType()) {
323   case MachineOperand::MO_Immediate:
324     cerr << "printOp() does not handle immediate values\n";
325     abort();
326     return;
327
328   case MachineOperand::MO_MachineBasicBlock:
329     printBasicBlockLabel(MO.getMBB());
330     return;
331   case MachineOperand::MO_JumpTableIndex:
332     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
333       << '_' << MO.getIndex();
334     return;
335   case MachineOperand::MO_ConstantPoolIndex:
336     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
337       << '_' << MO.getIndex();
338     return;
339   case MachineOperand::MO_ExternalSymbol:
340     // Computing the address of an external symbol, not calling it.
341     if (TM.getRelocationModel() != Reloc::Static) {
342       std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
343       GVStubs.insert(Name);
344       O << "L" << Name << "$non_lazy_ptr";
345       return;
346     }
347     O << TAI->getGlobalPrefix() << MO.getSymbolName();
348     return;
349   case MachineOperand::MO_GlobalAddress: {
350     // Computing the address of a global symbol, not calling it.
351     GlobalValue *GV = MO.getGlobal();
352     std::string Name = Mang->getValueName(GV);
353
354     // External or weakly linked global variables need non-lazily-resolved
355     // stubs
356     if (TM.getRelocationModel() != Reloc::Static) {
357       if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
358             GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
359         GVStubs.insert(Name);
360         O << "L" << Name << "$non_lazy_ptr";
361         return;
362       }
363     }
364     O << Name;
365
366     if (GV->hasExternalWeakLinkage())
367       ExtWeakSymbols.insert(GV);
368     return;
369   }
370
371   default:
372     O << "<unknown operand type: " << MO.getType() << ">";
373     return;
374   }
375 }
376
377 /// PrintAsmOperand - Print out an operand for an inline asm expression.
378 ///
379 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
380                                     unsigned AsmVariant,
381                                     const char *ExtraCode) {
382   // Does this asm operand have a single letter operand modifier?
383   if (ExtraCode && ExtraCode[0]) {
384     if (ExtraCode[1] != 0) return true; // Unknown modifier.
385
386     switch (ExtraCode[0]) {
387     default: return true;  // Unknown modifier.
388     case 'L': // Write second word of DImode reference.
389       // Verify that this operand has two consecutive registers.
390       if (!MI->getOperand(OpNo).isReg() ||
391           OpNo+1 == MI->getNumOperands() ||
392           !MI->getOperand(OpNo+1).isReg())
393         return true;
394       ++OpNo;   // Return the high-part.
395       break;
396     }
397   }
398
399   printOperand(MI, OpNo);
400   return false;
401 }
402
403 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
404                                           unsigned OpNo,
405                                           unsigned AsmVariant,
406                                           const char *ExtraCode) {
407   if (ExtraCode && ExtraCode[0])
408     return true; // Unknown modifier.
409   printMemRegReg(MI, OpNo);
410   return false;
411 }
412
413 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
414 /// to the current output stream.
415 ///
416 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
417   ++EmittedInsts;
418   printInstruction(MI);
419 }
420
421 /// runOnMachineFunction - This uses the printMachineInstruction()
422 /// method to print assembly for each instruction.
423 ///
424 bool
425 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
426 {
427   this->MF = &MF;
428
429   SetupMachineFunction(MF);
430   O << "\n\n";
431
432   // Print out constants referenced by the function
433   EmitConstantPool(MF.getConstantPool());
434
435   // Print out labels for the function.
436   const Function *F = MF.getFunction();
437
438   SwitchToSection(TAI->SectionForGlobal(F));
439   EmitAlignment(3, F);
440
441   switch (F->getLinkage()) {
442   default: assert(0 && "Unknown linkage type!");
443   case Function::PrivateLinkage:
444   case Function::InternalLinkage:  // Symbols default to internal.
445     break;
446   case Function::ExternalLinkage:
447     O << "\t.global\t" << CurrentFnName << "\n"
448       << "\t.type\t" << CurrentFnName << ", @function\n";
449     break;
450   case Function::WeakAnyLinkage:
451   case Function::WeakODRLinkage:
452   case Function::LinkOnceAnyLinkage:
453   case Function::LinkOnceODRLinkage:
454     O << "\t.global\t" << CurrentFnName << "\n";
455     O << "\t.weak_definition\t" << CurrentFnName << "\n";
456     break;
457   }
458   O << CurrentFnName << ":\n";
459
460   // Emit pre-function debug information.
461   DW->BeginFunction(&MF);
462
463   // Print out code for the function.
464   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
465        I != E; ++I) {
466     // Print a label for the basic block.
467     if (I != MF.begin()) {
468       printBasicBlockLabel(I, true, true);
469       O << '\n';
470     }
471     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
472          II != E; ++II) {
473       // Print the assembly for the instruction.
474       printMachineInstruction(II);
475     }
476   }
477
478   O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
479
480   // Print out jump tables referenced by the function.
481   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
482
483   // Emit post-function debug information.
484   DW->EndFunction(&MF);
485
486   // We didn't modify anything.
487   return false;
488 }
489
490
491 bool LinuxAsmPrinter::doInitialization(Module &M) {
492   bool Result = AsmPrinter::doInitialization(M);
493   SwitchToTextSection("\t.text");
494   // Emit initial debug information.
495   DW = getAnalysisIfAvailable<DwarfWriter>();
496   assert(DW && "Dwarf Writer is not available");
497   MMI = getAnalysisIfAvailable<MachineModuleInfo>();
498   DW->BeginModule(&M, MMI, O, this, TAI);
499   return Result;
500 }
501
502 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
503 /// Don't print things like \\n or \\0.
504 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
505   for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
506        Name != E; ++Name)
507     if (isprint(*Name))
508       OS << *Name;
509 }
510
511 /*!
512   Emit a global variable according to its section, alignment, etc.
513
514   \note This code was shamelessly copied from the PowerPC's assembly printer,
515   which sort of screams for some kind of refactorization of common code.
516  */
517 void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
518   const TargetData *TD = TM.getTargetData();
519
520   if (!GVar->hasInitializer())
521     return;
522
523   // Check to see if this is a special global used by LLVM, if so, emit it.
524   if (EmitSpecialLLVMGlobal(GVar))
525     return;
526
527   std::string name = Mang->getValueName(GVar);
528
529   printVisibility(name, GVar->getVisibility());
530
531   Constant *C = GVar->getInitializer();
532   const Type *Type = C->getType();
533   unsigned Size = TD->getTypePaddedSize(Type);
534   unsigned Align = TD->getPreferredAlignmentLog(GVar);
535
536   SwitchToSection(TAI->SectionForGlobal(GVar));
537
538   if (C->isNullValue() && /* FIXME: Verify correct */
539       !GVar->hasSection() &&
540       (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
541        GVar->isWeakForLinker())) {
542       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
543
544       if (GVar->hasExternalLinkage()) {
545         O << "\t.global " << name << '\n';
546         O << "\t.type " << name << ", @object\n";
547         O << name << ":\n";
548         O << "\t.zero " << Size << '\n';
549       } else if (GVar->hasLocalLinkage()) {
550         O << TAI->getLCOMMDirective() << name << ',' << Size;
551       } else {
552         O << ".comm " << name << ',' << Size;
553       }
554       O << "\t\t" << TAI->getCommentString() << " '";
555       PrintUnmangledNameSafely(GVar, O);
556       O << "'\n";
557       return;
558   }
559
560   switch (GVar->getLinkage()) {
561     // Should never be seen for the CellSPU platform...
562    case GlobalValue::LinkOnceAnyLinkage:
563    case GlobalValue::LinkOnceODRLinkage:
564    case GlobalValue::WeakAnyLinkage:
565    case GlobalValue::WeakODRLinkage:
566    case GlobalValue::CommonLinkage:
567     O << "\t.global " << name << '\n'
568       << "\t.type " << name << ", @object\n"
569       << "\t.weak " << name << '\n';
570     break;
571    case GlobalValue::AppendingLinkage:
572     // FIXME: appending linkage variables should go into a section of
573     // their name or something.  For now, just emit them as external.
574    case GlobalValue::ExternalLinkage:
575     // If external or appending, declare as a global symbol
576     O << "\t.global " << name << '\n'
577       << "\t.type " << name << ", @object\n";
578     // FALL THROUGH
579    case GlobalValue::PrivateLinkage:
580    case GlobalValue::InternalLinkage:
581     break;
582    default:
583     cerr << "Unknown linkage type!";
584     abort();
585   }
586
587   EmitAlignment(Align, GVar);
588   O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
589   PrintUnmangledNameSafely(GVar, O);
590   O << "'\n";
591
592   // If the initializer is a extern weak symbol, remember to emit the weak
593   // reference!
594   if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
595     if (GV->hasExternalWeakLinkage())
596       ExtWeakSymbols.insert(GV);
597
598   EmitGlobalConstant(C);
599   O << '\n';
600 }
601
602 bool LinuxAsmPrinter::doFinalization(Module &M) {
603   // Print out module-level global variables here.
604   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
605        I != E; ++I)
606     printModuleLevelGV(I);
607
608   // Emit initial debug information.
609   DW->EndModule();
610
611   return AsmPrinter::doFinalization(M);
612 }
613
614 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
615 /// assembly code for a MachineFunction to the given output stream, in a format
616 /// that the Linux SPU assembler can deal with.
617 ///
618 FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
619                                             SPUTargetMachine &tm,
620                                             CodeGenOpt::Level OptLevel,
621                                             bool verbose) {
622   return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
623 }