Fix may-be-used-uninitialized warning.
[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/Compiler.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include "llvm/Target/TargetAsmInfo.h"
36 #include "llvm/Target/TargetRegisterInfo.h"
37 #include "llvm/Target/TargetInstrInfo.h"
38 #include "llvm/Target/TargetOptions.h"
39 #include "llvm/ADT/Statistic.h"
40 #include "llvm/ADT/StringExtras.h"
41 #include <set>
42 using namespace llvm;
43
44 namespace {
45   STATISTIC(EmittedInsts, "Number of machine instrs printed");
46
47   const std::string bss_section(".bss");
48
49   class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
50     std::set<std::string> FnStubs, GVStubs;
51   public:
52     explicit SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
53                            const TargetAsmInfo *T, CodeGenOpt::Level OL,
54                            bool V) :
55       AsmPrinter(O, TM, T, OL, 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         assert(0 &&"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         assert(0 &&"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, CodeGenOpt::Level F,
294                              bool V)
295       : SPUAsmPrinter(O, TM, T, F, V), DW(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     return;
366   }
367
368   default:
369     O << "<unknown operand type: " << MO.getType() << ">";
370     return;
371   }
372 }
373
374 /// PrintAsmOperand - Print out an operand for an inline asm expression.
375 ///
376 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
377                                     unsigned AsmVariant,
378                                     const char *ExtraCode) {
379   // Does this asm operand have a single letter operand modifier?
380   if (ExtraCode && ExtraCode[0]) {
381     if (ExtraCode[1] != 0) return true; // Unknown modifier.
382
383     switch (ExtraCode[0]) {
384     default: return true;  // Unknown modifier.
385     case 'L': // Write second word of DImode reference.
386       // Verify that this operand has two consecutive registers.
387       if (!MI->getOperand(OpNo).isReg() ||
388           OpNo+1 == MI->getNumOperands() ||
389           !MI->getOperand(OpNo+1).isReg())
390         return true;
391       ++OpNo;   // Return the high-part.
392       break;
393     }
394   }
395
396   printOperand(MI, OpNo);
397   return false;
398 }
399
400 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
401                                           unsigned OpNo,
402                                           unsigned AsmVariant,
403                                           const char *ExtraCode) {
404   if (ExtraCode && ExtraCode[0])
405     return true; // Unknown modifier.
406   printMemRegReg(MI, OpNo);
407   return false;
408 }
409
410 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
411 /// to the current output stream.
412 ///
413 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
414   ++EmittedInsts;
415   printInstruction(MI);
416 }
417
418 /// runOnMachineFunction - This uses the printMachineInstruction()
419 /// method to print assembly for each instruction.
420 ///
421 bool
422 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
423 {
424   this->MF = &MF;
425
426   SetupMachineFunction(MF);
427   O << "\n\n";
428
429   // Print out constants referenced by the function
430   EmitConstantPool(MF.getConstantPool());
431
432   // Print out labels for the function.
433   const Function *F = MF.getFunction();
434
435   SwitchToSection(TAI->SectionForGlobal(F));
436   EmitAlignment(3, F);
437
438   switch (F->getLinkage()) {
439   default: assert(0 && "Unknown linkage type!");
440   case Function::PrivateLinkage:
441   case Function::InternalLinkage:  // Symbols default to internal.
442     break;
443   case Function::ExternalLinkage:
444     O << "\t.global\t" << CurrentFnName << "\n"
445       << "\t.type\t" << CurrentFnName << ", @function\n";
446     break;
447   case Function::WeakAnyLinkage:
448   case Function::WeakODRLinkage:
449   case Function::LinkOnceAnyLinkage:
450   case Function::LinkOnceODRLinkage:
451     O << "\t.global\t" << CurrentFnName << "\n";
452     O << "\t.weak_definition\t" << CurrentFnName << "\n";
453     break;
454   }
455   O << CurrentFnName << ":\n";
456
457   // Emit pre-function debug information.
458   DW->BeginFunction(&MF);
459
460   // Print out code for the function.
461   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
462        I != E; ++I) {
463     // Print a label for the basic block.
464     if (I != MF.begin()) {
465       printBasicBlockLabel(I, true, true);
466       O << '\n';
467     }
468     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
469          II != E; ++II) {
470       // Print the assembly for the instruction.
471       printMachineInstruction(II);
472     }
473   }
474
475   O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
476
477   // Print out jump tables referenced by the function.
478   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
479
480   // Emit post-function debug information.
481   DW->EndFunction(&MF);
482
483   // We didn't modify anything.
484   return false;
485 }
486
487
488 bool LinuxAsmPrinter::doInitialization(Module &M) {
489   bool Result = AsmPrinter::doInitialization(M);
490   DW = getAnalysisIfAvailable<DwarfWriter>();
491   SwitchToTextSection("\t.text");
492   return Result;
493 }
494
495 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
496 /// Don't print things like \\n or \\0.
497 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
498   for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
499        Name != E; ++Name)
500     if (isprint(*Name))
501       OS << *Name;
502 }
503
504 /*!
505   Emit a global variable according to its section, alignment, etc.
506
507   \note This code was shamelessly copied from the PowerPC's assembly printer,
508   which sort of screams for some kind of refactorization of common code.
509  */
510 void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
511   const TargetData *TD = TM.getTargetData();
512
513   if (!GVar->hasInitializer())
514     return;
515
516   // Check to see if this is a special global used by LLVM, if so, emit it.
517   if (EmitSpecialLLVMGlobal(GVar))
518     return;
519
520   std::string name = Mang->getValueName(GVar);
521
522   printVisibility(name, GVar->getVisibility());
523
524   Constant *C = GVar->getInitializer();
525   if (isa<MDNode>(C))
526     return;
527   const Type *Type = C->getType();
528   unsigned Size = TD->getTypeAllocSize(Type);
529   unsigned Align = TD->getPreferredAlignmentLog(GVar);
530
531   SwitchToSection(TAI->SectionForGlobal(GVar));
532
533   if (C->isNullValue() && /* FIXME: Verify correct */
534       !GVar->hasSection() &&
535       (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
536        GVar->isWeakForLinker())) {
537       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
538
539       if (GVar->hasExternalLinkage()) {
540         O << "\t.global " << name << '\n';
541         O << "\t.type " << name << ", @object\n";
542         O << name << ":\n";
543         O << "\t.zero " << Size << '\n';
544       } else if (GVar->hasLocalLinkage()) {
545         O << TAI->getLCOMMDirective() << name << ',' << Size;
546       } else {
547         O << ".comm " << name << ',' << Size;
548       }
549       O << "\t\t" << TAI->getCommentString() << " '";
550       PrintUnmangledNameSafely(GVar, O);
551       O << "'\n";
552       return;
553   }
554
555   switch (GVar->getLinkage()) {
556     // Should never be seen for the CellSPU platform...
557    case GlobalValue::LinkOnceAnyLinkage:
558    case GlobalValue::LinkOnceODRLinkage:
559    case GlobalValue::WeakAnyLinkage:
560    case GlobalValue::WeakODRLinkage:
561    case GlobalValue::CommonLinkage:
562     O << "\t.global " << name << '\n'
563       << "\t.type " << name << ", @object\n"
564       << "\t.weak " << name << '\n';
565     break;
566    case GlobalValue::AppendingLinkage:
567     // FIXME: appending linkage variables should go into a section of
568     // their name or something.  For now, just emit them as external.
569    case GlobalValue::ExternalLinkage:
570     // If external or appending, declare as a global symbol
571     O << "\t.global " << name << '\n'
572       << "\t.type " << name << ", @object\n";
573     // FALL THROUGH
574    case GlobalValue::PrivateLinkage:
575    case GlobalValue::InternalLinkage:
576     break;
577    default:
578     cerr << "Unknown linkage type!";
579     abort();
580   }
581
582   EmitAlignment(Align, GVar);
583   O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
584   PrintUnmangledNameSafely(GVar, O);
585   O << "'\n";
586
587   EmitGlobalConstant(C);
588   O << '\n';
589 }
590
591 bool LinuxAsmPrinter::doFinalization(Module &M) {
592   // Print out module-level global variables here.
593   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
594        I != E; ++I)
595     printModuleLevelGV(I);
596
597   return AsmPrinter::doFinalization(M);
598 }
599
600 /// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
601 /// assembly code for a MachineFunction to the given output stream, in a format
602 /// that the Linux SPU assembler can deal with.
603 ///
604 FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
605                                             SPUTargetMachine &tm,
606                                             CodeGenOpt::Level OptLevel,
607                                             bool verbose) {
608   return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
609 }
610
611 // Force static initialization.
612 extern "C" void LLVMInitializeCellSPUAsmPrinter() { }
613
614 namespace {
615   static struct Register {
616     Register() {
617       SPUTargetMachine::registerAsmPrinter(createSPUAsmPrinterPass);
618     }
619   } Registrator;
620 }