pass the mangler down into the various SectionForGlobal methods.
[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/Metadata.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/TargetLoweringObjectFile.h"
38 #include "llvm/Target/TargetInstrInfo.h"
39 #include "llvm/Target/TargetOptions.h"
40 #include "llvm/Target/TargetRegisterInfo.h"
41 #include "llvm/Target/TargetRegistry.h"
42 #include "llvm/ADT/Statistic.h"
43 #include "llvm/ADT/StringExtras.h"
44 #include <set>
45 using namespace llvm;
46
47 namespace {
48   STATISTIC(EmittedInsts, "Number of machine instrs printed");
49
50   const std::string bss_section(".bss");
51
52   class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
53     std::set<std::string> FnStubs, GVStubs;
54   public:
55     explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
56                            const TargetAsmInfo *T, bool V) :
57       AsmPrinter(O, TM, T, V) {}
58
59     virtual const char *getPassName() const {
60       return "STI CBEA SPU Assembly Printer";
61     }
62
63     SPUTargetMachine &getTM() {
64       return static_cast<SPUTargetMachine&>(TM);
65     }
66
67     /// printInstruction - This method is automatically generated by tablegen
68     /// from the instruction set description.  This method returns true if the
69     /// machine instruction was sufficiently described to print it, otherwise it
70     /// returns false.
71     bool printInstruction(const MachineInstr *MI);
72
73     void printMachineInstruction(const MachineInstr *MI);
74     void printOp(const MachineOperand &MO);
75
76     /// printRegister - Print register according to target requirements.
77     ///
78     void printRegister(const MachineOperand &MO, bool R0AsZero) {
79       unsigned RegNo = MO.getReg();
80       assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
81              "Not physreg??");
82       O << TM.getRegisterInfo()->get(RegNo).AsmName;
83     }
84
85     void printOperand(const MachineInstr *MI, unsigned OpNo) {
86       const MachineOperand &MO = MI->getOperand(OpNo);
87       if (MO.isReg()) {
88         assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
89         O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
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 << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
157       O << ", ";
158       printOperand(MI, OpNo+1);
159     }
160
161     void
162     printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
163     {
164       unsigned int value = MI->getOperand(OpNo).getImm();
165       assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
166       O << value;
167     }
168
169     void
170     printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
171     {
172       short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
173                              >> 16);
174       assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
175              && "Invalid s10 argument");
176       O << value;
177     }
178
179     void
180     printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
181     {
182       short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
183                              >> 16);
184       assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
185       O << value;
186     }
187
188     void
189     printDFormAddr(const MachineInstr *MI, unsigned OpNo)
190     {
191       assert(MI->getOperand(OpNo).isImm() &&
192              "printDFormAddr first operand is not immediate");
193       int64_t value = int64_t(MI->getOperand(OpNo).getImm());
194       int16_t value16 = int16_t(value);
195       assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
196              && "Invalid dform s10 offset argument");
197       O << (value16 & ~0xf) << "(";
198       printOperand(MI, OpNo+1);
199       O << ")";
200     }
201
202     void
203     printAddr256K(const MachineInstr *MI, unsigned OpNo)
204     {
205       /* Note: operand 1 is an offset or symbol name. */
206       if (MI->getOperand(OpNo).isImm()) {
207         printS16ImmOperand(MI, OpNo);
208       } else {
209         printOp(MI->getOperand(OpNo));
210         if (MI->getOperand(OpNo+1).isImm()) {
211           int displ = int(MI->getOperand(OpNo+1).getImm());
212           if (displ > 0)
213             O << "+" << displ;
214           else if (displ < 0)
215             O << displ;
216         }
217       }
218     }
219
220     void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
221       printOp(MI->getOperand(OpNo));
222     }
223
224     void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
225       // Used to generate a ".-<target>", but it turns out that the assembler
226       // really wants the target.
227       //
228       // N.B.: This operand is used for call targets. Branch hints are another
229       // animal entirely.
230       printOp(MI->getOperand(OpNo));
231     }
232
233     void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
234       // HBR operands are generated in front of branches, hence, the
235       // program counter plus the target.
236       O << ".+";
237       printOp(MI->getOperand(OpNo));
238     }
239
240     void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
241       if (MI->getOperand(OpNo).isImm()) {
242         printS16ImmOperand(MI, OpNo);
243       } else {
244         printOp(MI->getOperand(OpNo));
245         O << "@h";
246       }
247     }
248
249     void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
250       if (MI->getOperand(OpNo).isImm()) {
251         printS16ImmOperand(MI, OpNo);
252       } else {
253         printOp(MI->getOperand(OpNo));
254         O << "@l";
255       }
256     }
257
258     /// Print local store address
259     void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
260       printOp(MI->getOperand(OpNo));
261     }
262
263     void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
264       if (MI->getOperand(OpNo).isImm()) {
265         int value = (int) MI->getOperand(OpNo).getImm();
266         assert((value >= 0 && value < 16)
267                && "Invalid negated immediate rotate 7-bit argument");
268         O << -value;
269       } else {
270         llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
271       }
272     }
273
274     void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
275       if (MI->getOperand(OpNo).isImm()) {
276         int value = (int) MI->getOperand(OpNo).getImm();
277         assert((value >= 0 && value <= 32)
278                && "Invalid negated immediate rotate 7-bit argument");
279         O << -value;
280       } else {
281         llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
282       }
283     }
284
285     virtual bool runOnMachineFunction(MachineFunction &F) = 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(formatted_raw_ostream &O, TargetMachine &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
303     void getAnalysisUsage(AnalysisUsage &AU) const {
304       AU.setPreservesAll();
305       AU.addRequired<MachineModuleInfo>();
306       AU.addRequired<DwarfWriter>();
307       SPUAsmPrinter::getAnalysisUsage(AU);
308     }
309
310     //! Emit a global variable according to its section and type
311     void PrintGlobalVariable(const GlobalVariable* GVar);
312   };
313 } // end of anonymous namespace
314
315 // Include the auto-generated portion of the assembly writer
316 #include "SPUGenAsmWriter.inc"
317
318 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
319   switch (MO.getType()) {
320   case MachineOperand::MO_Immediate:
321     llvm_report_error("printOp() does not handle immediate values");
322     return;
323
324   case MachineOperand::MO_MachineBasicBlock:
325     printBasicBlockLabel(MO.getMBB());
326     return;
327   case MachineOperand::MO_JumpTableIndex:
328     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
329       << '_' << MO.getIndex();
330     return;
331   case MachineOperand::MO_ConstantPoolIndex:
332     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
333       << '_' << MO.getIndex();
334     return;
335   case MachineOperand::MO_ExternalSymbol:
336     // Computing the address of an external symbol, not calling it.
337     if (TM.getRelocationModel() != Reloc::Static) {
338       std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
339       GVStubs.insert(Name);
340       O << "L" << Name << "$non_lazy_ptr";
341       return;
342     }
343     O << TAI->getGlobalPrefix() << MO.getSymbolName();
344     return;
345   case MachineOperand::MO_GlobalAddress: {
346     // Computing the address of a global symbol, not calling it.
347     GlobalValue *GV = MO.getGlobal();
348     std::string Name = Mang->getMangledName(GV);
349
350     // External or weakly linked global variables need non-lazily-resolved
351     // stubs
352     if (TM.getRelocationModel() != Reloc::Static) {
353       if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
354             GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
355         GVStubs.insert(Name);
356         O << "L" << Name << "$non_lazy_ptr";
357         return;
358       }
359     }
360     O << Name;
361     return;
362   }
363
364   default:
365     O << "<unknown operand type: " << MO.getType() << ">";
366     return;
367   }
368 }
369
370 /// PrintAsmOperand - Print out an operand for an inline asm expression.
371 ///
372 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
373                                     unsigned AsmVariant,
374                                     const char *ExtraCode) {
375   // Does this asm operand have a single letter operand modifier?
376   if (ExtraCode && ExtraCode[0]) {
377     if (ExtraCode[1] != 0) return true; // Unknown modifier.
378
379     switch (ExtraCode[0]) {
380     default: return true;  // Unknown modifier.
381     case 'L': // Write second word of DImode reference.
382       // Verify that this operand has two consecutive registers.
383       if (!MI->getOperand(OpNo).isReg() ||
384           OpNo+1 == MI->getNumOperands() ||
385           !MI->getOperand(OpNo+1).isReg())
386         return true;
387       ++OpNo;   // Return the high-part.
388       break;
389     }
390   }
391
392   printOperand(MI, OpNo);
393   return false;
394 }
395
396 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
397                                           unsigned OpNo,
398                                           unsigned AsmVariant,
399                                           const char *ExtraCode) {
400   if (ExtraCode && ExtraCode[0])
401     return true; // Unknown modifier.
402   printMemRegReg(MI, OpNo);
403   return false;
404 }
405
406 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
407 /// to the current output stream.
408 ///
409 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
410   ++EmittedInsts;
411   printInstruction(MI);
412 }
413
414 /// runOnMachineFunction - This uses the printMachineInstruction()
415 /// method to print assembly for each instruction.
416 ///
417 bool
418 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
419 {
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   SwitchToSection(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       printBasicBlockLabel(I, true, true);
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 bool LinuxAsmPrinter::doInitialization(Module &M) {
486   bool Result = AsmPrinter::doInitialization(M);
487   DW = getAnalysisIfAvailable<DwarfWriter>();
488   SwitchToTextSection("\t.text");
489   return Result;
490 }
491
492 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
493 /// Don't print things like \\n or \\0.
494 static void PrintUnmangledNameSafely(const Value *V, 
495                                      formatted_raw_ostream &OS) {
496   for (StringRef::iterator it = V->getName().begin(), 
497          ie = V->getName().end(); it != ie; ++it)
498     if (isprint(*it))
499       OS << *it;
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::PrintGlobalVariable(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(getObjFileLowering().SectionForGlobal(GVar, Mang, TM));
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::LinkerPrivateLinkage:
574    case GlobalValue::InternalLinkage:
575     break;
576    default:
577     llvm_report_error("Unknown linkage type!");
578   }
579
580   EmitAlignment(Align, GVar);
581   O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
582   PrintUnmangledNameSafely(GVar, O);
583   O << "'\n";
584
585   EmitGlobalConstant(C);
586   O << '\n';
587 }
588
589 // Force static initialization.
590 extern "C" void LLVMInitializeCellSPUAsmPrinter() { 
591   RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);
592 }