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