08b45ea86f934f047811c6cab32a4f55baa413a5
[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/MC/MCStreamer.h"
29 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/MC/MCSymbol.h"
31 #include "llvm/Target/TargetLoweringObjectFile.h"
32 #include "llvm/Target/TargetInstrInfo.h"
33 #include "llvm/Target/TargetOptions.h"
34 #include "llvm/Target/TargetRegisterInfo.h"
35 #include "llvm/Target/TargetRegistry.h"
36 #include "llvm/ADT/Statistic.h"
37 #include "llvm/ADT/StringExtras.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Debug.h"
40 #include "llvm/Support/ErrorHandling.h"
41 #include "llvm/Support/FormattedStream.h"
42 #include "llvm/Support/MathExtras.h"
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 SPUAsmPrinter : public AsmPrinter {
51   public:
52     explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
53                            const MCAsmInfo *T, bool V) :
54       AsmPrinter(O, TM, T, 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.
66     void printInstruction(const MachineInstr *MI);
67     static const char *getRegisterName(unsigned RegNo);
68
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 << getRegisterName(RegNo);
80     }
81
82     void printOperand(const MachineInstr *MI, unsigned OpNo) {
83       const MachineOperand &MO = MI->getOperand(OpNo);
84       if (MO.isReg()) {
85         O << getRegisterName(MO.getReg());
86       } else if (MO.isImm()) {
87         O << MO.getImm();
88       } else {
89         printOp(MO);
90       }
91     }
92
93     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
94                          unsigned AsmVariant, const char *ExtraCode);
95     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
96                                unsigned AsmVariant, const char *ExtraCode);
97
98
99     void
100     printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
101     {
102       int value = MI->getOperand(OpNo).getImm();
103       value = (value << (32 - 7)) >> (32 - 7);
104
105       assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
106              && "Invalid s7 argument");
107       O << value;
108     }
109
110     void
111     printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
112     {
113       unsigned int value = MI->getOperand(OpNo).getImm();
114       assert(value < (1 << 8) && "Invalid u7 argument");
115       O << value;
116     }
117
118     void
119     printShufAddr(const MachineInstr *MI, unsigned OpNo)
120     {
121       char value = MI->getOperand(OpNo).getImm();
122       O << (int) value;
123       O << "(";
124       printOperand(MI, OpNo+1);
125       O << ")";
126     }
127
128     void
129     printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
130     {
131       O << (short) MI->getOperand(OpNo).getImm();
132     }
133
134     void
135     printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
136     {
137       O << (unsigned short)MI->getOperand(OpNo).getImm();
138     }
139
140     void
141     printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
142     {
143       O << (unsigned)MI->getOperand(OpNo).getImm();
144     }
145
146     void
147     printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
148       // When used as the base register, r0 reads constant zero rather than
149       // the value contained in the register.  For this reason, the darwin
150       // assembler requires that we print r0 as 0 (no r) when used as the base.
151       const MachineOperand &MO = MI->getOperand(OpNo);
152       O << getRegisterName(MO.getReg()) << ", ";
153       printOperand(MI, OpNo+1);
154     }
155
156     void
157     printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
158     {
159       unsigned int value = MI->getOperand(OpNo).getImm();
160       assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
161       O << value;
162     }
163
164     void
165     printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
166     {
167       short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
168                              >> 16);
169       assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
170              && "Invalid s10 argument");
171       O << value;
172     }
173
174     void
175     printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
176     {
177       short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
178                              >> 16);
179       assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
180       O << value;
181     }
182
183     void
184     printDFormAddr(const MachineInstr *MI, unsigned OpNo)
185     {
186       assert(MI->getOperand(OpNo).isImm() &&
187              "printDFormAddr first operand is not immediate");
188       int64_t value = int64_t(MI->getOperand(OpNo).getImm());
189       int16_t value16 = int16_t(value);
190       assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
191              && "Invalid dform s10 offset argument");
192       O << (value16 & ~0xf) << "(";
193       printOperand(MI, OpNo+1);
194       O << ")";
195     }
196
197     void
198     printAddr256K(const MachineInstr *MI, unsigned OpNo)
199     {
200       /* Note: operand 1 is an offset or symbol name. */
201       if (MI->getOperand(OpNo).isImm()) {
202         printS16ImmOperand(MI, OpNo);
203       } else {
204         printOp(MI->getOperand(OpNo));
205         if (MI->getOperand(OpNo+1).isImm()) {
206           int displ = int(MI->getOperand(OpNo+1).getImm());
207           if (displ > 0)
208             O << "+" << displ;
209           else if (displ < 0)
210             O << displ;
211         }
212       }
213     }
214
215     void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
216       printOp(MI->getOperand(OpNo));
217     }
218
219     void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
220       // Used to generate a ".-<target>", but it turns out that the assembler
221       // really wants the target.
222       //
223       // N.B.: This operand is used for call targets. Branch hints are another
224       // animal entirely.
225       printOp(MI->getOperand(OpNo));
226     }
227
228     void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
229       // HBR operands are generated in front of branches, hence, the
230       // program counter plus the target.
231       O << ".+";
232       printOp(MI->getOperand(OpNo));
233     }
234
235     void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
236       if (MI->getOperand(OpNo).isImm()) {
237         printS16ImmOperand(MI, OpNo);
238       } else {
239         printOp(MI->getOperand(OpNo));
240         O << "@h";
241       }
242     }
243
244     void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
245       if (MI->getOperand(OpNo).isImm()) {
246         printS16ImmOperand(MI, OpNo);
247       } else {
248         printOp(MI->getOperand(OpNo));
249         O << "@l";
250       }
251     }
252
253     /// Print local store address
254     void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
255       printOp(MI->getOperand(OpNo));
256     }
257
258     void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
259       if (MI->getOperand(OpNo).isImm()) {
260         int value = (int) MI->getOperand(OpNo).getImm();
261         assert((value >= 0 && value < 16)
262                && "Invalid negated immediate rotate 7-bit argument");
263         O << -value;
264       } else {
265         llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
266       }
267     }
268
269     void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
270       if (MI->getOperand(OpNo).isImm()) {
271         int value = (int) MI->getOperand(OpNo).getImm();
272         assert((value >= 0 && value <= 32)
273                && "Invalid negated immediate rotate 7-bit argument");
274         O << -value;
275       } else {
276         llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
277       }
278     }
279
280     virtual bool runOnMachineFunction(MachineFunction &F) = 0;
281   };
282
283   /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
284   class LinuxAsmPrinter : public SPUAsmPrinter {
285   public:
286     explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
287                              const MCAsmInfo *T, bool V)
288       : SPUAsmPrinter(O, TM, T, V) {}
289
290     virtual const char *getPassName() const {
291       return "STI CBEA SPU Assembly Printer";
292     }
293
294     bool runOnMachineFunction(MachineFunction &F);
295
296     void getAnalysisUsage(AnalysisUsage &AU) const {
297       AU.setPreservesAll();
298       AU.addRequired<MachineModuleInfo>();
299       AU.addRequired<DwarfWriter>();
300       SPUAsmPrinter::getAnalysisUsage(AU);
301     }
302   };
303 } // end of anonymous namespace
304
305 // Include the auto-generated portion of the assembly writer
306 #include "SPUGenAsmWriter.inc"
307
308 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
309   switch (MO.getType()) {
310   case MachineOperand::MO_Immediate:
311     llvm_report_error("printOp() does not handle immediate values");
312     return;
313
314   case MachineOperand::MO_MachineBasicBlock:
315     O << *GetMBBSymbol(MO.getMBB()->getNumber());
316     return;
317   case MachineOperand::MO_JumpTableIndex:
318     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
319       << '_' << MO.getIndex();
320     return;
321   case MachineOperand::MO_ConstantPoolIndex:
322     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
323       << '_' << MO.getIndex();
324     return;
325   case MachineOperand::MO_ExternalSymbol:
326     // Computing the address of an external symbol, not calling it.
327     if (TM.getRelocationModel() != Reloc::Static) {
328       O << "L" << MAI->getGlobalPrefix() << MO.getSymbolName()
329         << "$non_lazy_ptr";
330       return;
331     }
332     O << *GetExternalSymbolSymbol(MO.getSymbolName());
333     return;
334   case MachineOperand::MO_GlobalAddress:
335     // External or weakly linked global variables need non-lazily-resolved
336     // stubs
337     if (TM.getRelocationModel() != Reloc::Static) {
338       GlobalValue *GV = MO.getGlobal();
339       if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
340             GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
341         O << *GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
342         return;
343       }
344     }
345     O << *GetGlobalValueSymbol(MO.getGlobal());
346     return;
347   default:
348     O << "<unknown operand type: " << MO.getType() << ">";
349     return;
350   }
351 }
352
353 /// PrintAsmOperand - Print out an operand for an inline asm expression.
354 ///
355 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
356                                     unsigned AsmVariant,
357                                     const char *ExtraCode) {
358   // Does this asm operand have a single letter operand modifier?
359   if (ExtraCode && ExtraCode[0]) {
360     if (ExtraCode[1] != 0) return true; // Unknown modifier.
361
362     switch (ExtraCode[0]) {
363     default: return true;  // Unknown modifier.
364     case 'L': // Write second word of DImode reference.
365       // Verify that this operand has two consecutive registers.
366       if (!MI->getOperand(OpNo).isReg() ||
367           OpNo+1 == MI->getNumOperands() ||
368           !MI->getOperand(OpNo+1).isReg())
369         return true;
370       ++OpNo;   // Return the high-part.
371       break;
372     }
373   }
374
375   printOperand(MI, OpNo);
376   return false;
377 }
378
379 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
380                                           unsigned OpNo,
381                                           unsigned AsmVariant,
382                                           const char *ExtraCode) {
383   if (ExtraCode && ExtraCode[0])
384     return true; // Unknown modifier.
385   printMemRegReg(MI, OpNo);
386   return false;
387 }
388
389 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax
390 /// to the current output stream.
391 ///
392 void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
393   ++EmittedInsts;
394   processDebugLoc(MI, true);
395   printInstruction(MI);
396   if (VerboseAsm)
397     EmitComments(*MI);
398   processDebugLoc(MI, false);
399   O << '\n';
400 }
401
402 /// runOnMachineFunction - This uses the printMachineInstruction()
403 /// method to print assembly for each instruction.
404 ///
405 bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
406   SetupMachineFunction(MF);
407   O << "\n\n";
408
409   // Print out constants referenced by the function
410   EmitConstantPool(MF.getConstantPool());
411
412   // Print out labels for the function.
413   const Function *F = MF.getFunction();
414
415   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
416   EmitAlignment(MF.getAlignment(), F);
417
418   switch (F->getLinkage()) {
419   default: llvm_unreachable("Unknown linkage type!");
420   case Function::PrivateLinkage:
421   case Function::LinkerPrivateLinkage:
422   case Function::InternalLinkage:  // Symbols default to internal.
423     break;
424   case Function::ExternalLinkage:
425     O << "\t.global\t" << *CurrentFnSym << "\n" << "\t.type\t";
426     O << *CurrentFnSym << ", @function\n";
427     break;
428   case Function::WeakAnyLinkage:
429   case Function::WeakODRLinkage:
430   case Function::LinkOnceAnyLinkage:
431   case Function::LinkOnceODRLinkage:
432     O << "\t.global\t" << *CurrentFnSym << "\n";
433     O << "\t.weak_definition\t" << *CurrentFnSym << "\n";
434     break;
435   }
436   
437   O << *CurrentFnSym << ":\n";
438
439   // Emit pre-function debug information.
440   DW->BeginFunction(&MF);
441
442   // Print out code for the function.
443   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
444        I != E; ++I) {
445     // Print a label for the basic block.
446     if (I != MF.begin()) {
447       EmitBasicBlockStart(I);
448     }
449     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
450          II != E; ++II) {
451       // Print the assembly for the instruction.
452       printMachineInstruction(II);
453     }
454   }
455
456   O << "\t.size\t" << *CurrentFnSym << ",.-" << *CurrentFnSym << "\n";
457
458   // Print out jump tables referenced by the function.
459   EmitJumpTableInfo(MF);
460
461   // Emit post-function debug information.
462   DW->EndFunction(&MF);
463
464   // We didn't modify anything.
465   return false;
466 }
467
468 // Force static initialization.
469 extern "C" void LLVMInitializeCellSPUAsmPrinter() { 
470   RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);
471 }