62193234d1b878e38ec1a2f236df57eb921294df
[oota-llvm.git] / lib / Target / Sparc / AsmPrinter / SparcAsmPrinter.cpp
1 //===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
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 GAS-format SPARC assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "asm-printer"
16 #include "Sparc.h"
17 #include "SparcInstrInfo.h"
18 #include "SparcTargetMachine.h"
19 #include "llvm/Constants.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/Module.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/DwarfWriter.h"
24 #include "llvm/CodeGen/MachineFunctionPass.h"
25 #include "llvm/CodeGen/MachineConstantPool.h"
26 #include "llvm/CodeGen/MachineInstr.h"
27 #include "llvm/MC/MCAsmInfo.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCSymbol.h"
30 #include "llvm/Target/TargetLoweringObjectFile.h"
31 #include "llvm/Target/TargetRegistry.h"
32 #include "llvm/ADT/Statistic.h"
33 #include "llvm/ADT/StringExtras.h"
34 #include "llvm/Support/CommandLine.h"
35 #include "llvm/Support/ErrorHandling.h"
36 #include "llvm/Support/FormattedStream.h"
37 #include "llvm/Support/Mangler.h"
38 #include "llvm/Support/MathExtras.h"
39 #include <cctype>
40 #include <cstring>
41 #include <map>
42 using namespace llvm;
43
44 STATISTIC(EmittedInsts, "Number of machine instrs printed");
45
46 namespace {
47   class VISIBILITY_HIDDEN SparcAsmPrinter : public AsmPrinter {
48     /// We name each basic block in a Function with a unique number, so
49     /// that we can consistently refer to them later. This is cleared
50     /// at the beginning of each call to runOnMachineFunction().
51     ///
52     typedef std::map<const Value *, unsigned> ValueMapTy;
53     ValueMapTy NumberForBB;
54     unsigned BBNumber;
55   public:
56     explicit SparcAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
57                              const MCAsmInfo *T, bool V)
58       : AsmPrinter(O, TM, T, V), BBNumber(0) {}
59
60     virtual const char *getPassName() const {
61       return "Sparc Assembly Printer";
62     }
63
64     void PrintGlobalVariable(const GlobalVariable *GVar);
65     void printOperand(const MachineInstr *MI, int opNum);
66     void printMemOperand(const MachineInstr *MI, int opNum,
67                          const char *Modifier = 0);
68     void printCCOperand(const MachineInstr *MI, int opNum);
69
70     void printInstruction(const MachineInstr *MI);  // autogenerated.
71     static const char *getRegisterName(unsigned RegNo);
72
73     bool runOnMachineFunction(MachineFunction &F);
74     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
75                        unsigned AsmVariant, const char *ExtraCode);
76     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
77                              unsigned AsmVariant, const char *ExtraCode);
78   };
79 } // end of anonymous namespace
80
81 #include "SparcGenAsmWriter.inc"
82
83
84 /// runOnMachineFunction - This uses the printInstruction()
85 /// method to print assembly for each instruction.
86 ///
87 bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
88   this->MF = &MF;
89
90   SetupMachineFunction(MF);
91
92   // Print out constants referenced by the function
93   EmitConstantPool(MF.getConstantPool());
94
95   // BBNumber is used here so that a given Printer will never give two
96   // BBs the same name. (If you have a better way, please let me know!)
97
98   O << "\n\n";
99
100   // Print out the label for the function.
101   const Function *F = MF.getFunction();
102   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
103   EmitAlignment(MF.getAlignment(), F);
104   O << "\t.globl\t" << CurrentFnName << '\n';
105
106   printVisibility(CurrentFnName, F->getVisibility());
107
108   O << "\t.type\t" << CurrentFnName << ", #function\n";
109   O << CurrentFnName << ":\n";
110   // Emit pre-function debug information.
111   DW->BeginFunction(&MF);
112
113   // Number each basic block so that we can consistently refer to them
114   // in PC-relative references.
115   // FIXME: Why not use the MBB numbers?
116   NumberForBB.clear();
117   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
118        I != E; ++I) {
119     NumberForBB[I->getBasicBlock()] = BBNumber++;
120   }
121
122   // Print out code for the function.
123   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
124        I != E; ++I) {
125     // Print a label for the basic block.
126     if (I != MF.begin()) {
127       EmitBasicBlockStart(I);
128       O << '\n';
129     }
130     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
131          II != E; ++II) {
132       // Print the assembly for the instruction.
133       processDebugLoc(II->getDebugLoc());
134       printInstruction(II);
135       
136       if (VerboseAsm && !II->getDebugLoc().isUnknown())
137         EmitComments(*II);
138       O << '\n';
139       
140       ++EmittedInsts;
141     }
142   }
143
144   // Emit post-function debug information.
145   DW->EndFunction(&MF);
146
147   // We didn't modify anything.
148   return false;
149 }
150
151 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
152   const MachineOperand &MO = MI->getOperand (opNum);
153   const TargetRegisterInfo &RI = *TM.getRegisterInfo();
154   bool CloseParen = false;
155   if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) {
156     O << "%hi(";
157     CloseParen = true;
158   } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) &&
159              !MO.isReg() && !MO.isImm()) {
160     O << "%lo(";
161     CloseParen = true;
162   }
163   switch (MO.getType()) {
164   case MachineOperand::MO_Register:
165     if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
166       O << "%" << LowercaseString (RI.get(MO.getReg()).AsmName);
167     else
168       O << "%reg" << MO.getReg();
169     break;
170
171   case MachineOperand::MO_Immediate:
172     O << (int)MO.getImm();
173     break;
174   case MachineOperand::MO_MachineBasicBlock:
175     GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
176     return;
177   case MachineOperand::MO_GlobalAddress:
178     O << Mang->getMangledName(MO.getGlobal());
179     break;
180   case MachineOperand::MO_ExternalSymbol:
181     O << MO.getSymbolName();
182     break;
183   case MachineOperand::MO_ConstantPoolIndex:
184     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
185       << MO.getIndex();
186     break;
187   default:
188     llvm_unreachable("<unknown operand type>");
189   }
190   if (CloseParen) O << ")";
191 }
192
193 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
194                                       const char *Modifier) {
195   printOperand(MI, opNum);
196
197   // If this is an ADD operand, emit it like normal operands.
198   if (Modifier && !strcmp(Modifier, "arith")) {
199     O << ", ";
200     printOperand(MI, opNum+1);
201     return;
202   }
203
204   if (MI->getOperand(opNum+1).isReg() &&
205       MI->getOperand(opNum+1).getReg() == SP::G0)
206     return;   // don't print "+%g0"
207   if (MI->getOperand(opNum+1).isImm() &&
208       MI->getOperand(opNum+1).getImm() == 0)
209     return;   // don't print "+0"
210
211   O << "+";
212   if (MI->getOperand(opNum+1).isGlobal() ||
213       MI->getOperand(opNum+1).isCPI()) {
214     O << "%lo(";
215     printOperand(MI, opNum+1);
216     O << ")";
217   } else {
218     printOperand(MI, opNum+1);
219   }
220 }
221
222 void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
223   int CC = (int)MI->getOperand(opNum).getImm();
224   O << SPARCCondCodeToString((SPCC::CondCodes)CC);
225 }
226
227 void SparcAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
228   const TargetData *TD = TM.getTargetData();
229
230   if (!GVar->hasInitializer())
231     return;  // External global require no code
232
233   // Check to see if this is a special global used by LLVM, if so, emit it.
234   if (EmitSpecialLLVMGlobal(GVar))
235     return;
236
237   O << "\n\n";
238   std::string name = Mang->getMangledName(GVar);
239   Constant *C = GVar->getInitializer();
240   unsigned Size = TD->getTypeAllocSize(C->getType());
241   unsigned Align = TD->getPreferredAlignment(GVar);
242
243   printVisibility(name, GVar->getVisibility());
244
245   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
246                                                                   TM));
247
248   if (C->isNullValue() && !GVar->hasSection()) {
249     if (!GVar->isThreadLocal() &&
250         (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
251       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
252
253       if (GVar->hasLocalLinkage())
254         O << "\t.local " << name << '\n';
255
256       O << MAI->getCOMMDirective() << name << ',' << Size;
257       if (MAI->getCOMMDirectiveTakesAlignment())
258         O << ',' << (1 << Align);
259
260       O << '\n';
261       return;
262     }
263   }
264
265   switch (GVar->getLinkage()) {
266    case GlobalValue::CommonLinkage:
267    case GlobalValue::LinkOnceAnyLinkage:
268    case GlobalValue::LinkOnceODRLinkage:
269    case GlobalValue::WeakAnyLinkage: // FIXME: Verify correct for weak.
270    case GlobalValue::WeakODRLinkage: // FIXME: Verify correct for weak.
271     // Nonnull linkonce -> weak
272     O << "\t.weak " << name << '\n';
273     break;
274    case GlobalValue::AppendingLinkage:
275     // FIXME: appending linkage variables should go into a section of
276     // their name or something.  For now, just emit them as external.
277    case GlobalValue::ExternalLinkage:
278     // If external or appending, declare as a global symbol
279     O << MAI->getGlobalDirective() << name << '\n';
280     // FALL THROUGH
281    case GlobalValue::PrivateLinkage:
282    case GlobalValue::LinkerPrivateLinkage:
283    case GlobalValue::InternalLinkage:
284     break;
285    case GlobalValue::GhostLinkage:
286     llvm_unreachable("Should not have any unmaterialized functions!");
287    case GlobalValue::DLLImportLinkage:
288     llvm_unreachable("DLLImport linkage is not supported by this target!");
289    case GlobalValue::DLLExportLinkage:
290     llvm_unreachable("DLLExport linkage is not supported by this target!");
291    default:
292     llvm_unreachable("Unknown linkage type!");
293   }
294
295   EmitAlignment(Align, GVar);
296
297   if (MAI->hasDotTypeDotSizeDirective()) {
298     O << "\t.type " << name << ",#object\n";
299     O << "\t.size " << name << ',' << Size << '\n';
300   }
301
302   O << name << ":\n";
303   EmitGlobalConstant(C);
304 }
305
306 /// PrintAsmOperand - Print out an operand for an inline asm expression.
307 ///
308 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
309                                       unsigned AsmVariant,
310                                       const char *ExtraCode) {
311   if (ExtraCode && ExtraCode[0]) {
312     if (ExtraCode[1] != 0) return true; // Unknown modifier.
313
314     switch (ExtraCode[0]) {
315     default: return true;  // Unknown modifier.
316     case 'r':
317      break;
318     }
319   }
320
321   printOperand(MI, OpNo);
322
323   return false;
324 }
325
326 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
327                                             unsigned OpNo,
328                                             unsigned AsmVariant,
329                                             const char *ExtraCode) {
330   if (ExtraCode && ExtraCode[0])
331     return true;  // Unknown modifier
332
333   O << '[';
334   printMemOperand(MI, OpNo);
335   O << ']';
336
337   return false;
338 }
339
340 // Force static initialization.
341 extern "C" void LLVMInitializeSparcAsmPrinter() { 
342   RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
343 }