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