Separate target specific asm properties from the asm printers.
[oota-llvm.git] / lib / Target / Sparc / SparcAsmPrinter.cpp
1 //===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source 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 #include "Sparc.h"
16 #include "SparcInstrInfo.h"
17 #include "llvm/Constants.h"
18 #include "llvm/DerivedTypes.h"
19 #include "llvm/Module.h"
20 #include "llvm/Assembly/Writer.h"
21 #include "llvm/CodeGen/AsmPrinter.h"
22 #include "llvm/CodeGen/MachineFunctionPass.h"
23 #include "llvm/CodeGen/MachineConstantPool.h"
24 #include "llvm/CodeGen/MachineInstr.h"
25 #include "llvm/Target/TargetAsmInfo.h"
26 #include "llvm/Target/TargetData.h"
27 #include "llvm/Target/TargetMachine.h"
28 #include "llvm/Support/Mangler.h"
29 #include "llvm/ADT/Statistic.h"
30 #include "llvm/ADT/StringExtras.h"
31 #include "llvm/Support/CommandLine.h"
32 #include "llvm/Support/MathExtras.h"
33 #include <cctype>
34 #include <iostream>
35 using namespace llvm;
36
37 namespace {
38   Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
39
40   struct VISIBILITY_HIDDEN SparcTargetAsmInfo : public TargetAsmInfo {
41     SparcTargetAsmInfo() {
42       Data16bitsDirective = "\t.half\t";
43       Data32bitsDirective = "\t.word\t";
44       Data64bitsDirective = 0;  // .xword is only supported by V9.
45       ZeroDirective = "\t.skip\t";
46       CommentString = "!";
47       ConstantPoolSection = "\t.section \".rodata\",#alloc\n";
48     }
49   };
50
51   struct VISIBILITY_HIDDEN SparcAsmPrinter : public AsmPrinter {
52     SparcAsmPrinter(std::ostream &O, TargetMachine &TM, TargetAsmInfo *T)
53       : AsmPrinter(O, TM, T) {
54     }
55
56     /// We name each basic block in a Function with a unique number, so
57     /// that we can consistently refer to them later. This is cleared
58     /// at the beginning of each call to runOnMachineFunction().
59     ///
60     typedef std::map<const Value *, unsigned> ValueMapTy;
61     ValueMapTy NumberForBB;
62
63     virtual const char *getPassName() const {
64       return "Sparc Assembly Printer";
65     }
66
67     void printOperand(const MachineInstr *MI, int opNum);
68     void printMemOperand(const MachineInstr *MI, int opNum,
69                          const char *Modifier = 0);
70     void printCCOperand(const MachineInstr *MI, int opNum);
71
72     bool printInstruction(const MachineInstr *MI);  // autogenerated.
73     bool runOnMachineFunction(MachineFunction &F);
74     bool doInitialization(Module &M);
75     bool doFinalization(Module &M);
76   };
77 } // end of anonymous namespace
78
79 #include "SparcGenAsmWriter.inc"
80
81 /// createSparcCodePrinterPass - Returns a pass that prints the SPARC
82 /// assembly code for a MachineFunction to the given output stream,
83 /// using the given target machine description.  This should work
84 /// regardless of whether the function is in SSA form.
85 ///
86 FunctionPass *llvm::createSparcCodePrinterPass(std::ostream &o,
87                                                TargetMachine &tm) {
88   SparcTargetAsmInfo *TAI = new SparcTargetAsmInfo();
89   return new SparcAsmPrinter(o, tm, TAI);
90 }
91
92 /// runOnMachineFunction - This uses the printMachineInstruction()
93 /// method to print assembly for each instruction.
94 ///
95 bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
96   SetupMachineFunction(MF);
97
98   // Print out constants referenced by the function
99   EmitConstantPool(MF.getConstantPool());
100
101   // BBNumber is used here so that a given Printer will never give two
102   // BBs the same name. (If you have a better way, please let me know!)
103   static unsigned BBNumber = 0;
104
105   O << "\n\n";
106   // What's my mangled name?
107   CurrentFnName = Mang->getValueName(MF.getFunction());
108
109   // Print out labels for the function.
110   SwitchToTextSection(".text", MF.getFunction());
111   EmitAlignment(4, MF.getFunction());
112   O << "\t.globl\t" << CurrentFnName << "\n";
113   O << "\t.type\t" << CurrentFnName << ", #function\n";
114   O << CurrentFnName << ":\n";
115
116   // Number each basic block so that we can consistently refer to them
117   // in PC-relative references.
118   NumberForBB.clear();
119   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
120        I != E; ++I) {
121     NumberForBB[I->getBasicBlock()] = BBNumber++;
122   }
123
124   // Print out code for the function.
125   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
126        I != E; ++I) {
127     // Print a label for the basic block.
128     if (I != MF.begin()) {
129       printBasicBlockLabel(I, true);
130       O << '\n';
131     }
132     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
133          II != E; ++II) {
134       // Print the assembly for the instruction.
135       O << "\t";
136       printInstruction(II);
137       ++EmittedInsts;
138     }
139   }
140
141   // We didn't modify anything.
142   return false;
143 }
144
145 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
146   const MachineOperand &MO = MI->getOperand (opNum);
147   const MRegisterInfo &RI = *TM.getRegisterInfo();
148   bool CloseParen = false;
149   if (MI->getOpcode() == SP::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
150     O << "%hi(";
151     CloseParen = true;
152   } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri)
153              && !MO.isRegister() && !MO.isImmediate()) {
154     O << "%lo(";
155     CloseParen = true;
156   }
157   switch (MO.getType()) {
158   case MachineOperand::MO_Register:
159     if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
160       O << "%" << LowercaseString (RI.get(MO.getReg()).Name);
161     else
162       O << "%reg" << MO.getReg();
163     break;
164
165   case MachineOperand::MO_Immediate:
166     O << (int)MO.getImmedValue();
167     break;
168   case MachineOperand::MO_MachineBasicBlock:
169     printBasicBlockLabel(MO.getMachineBasicBlock());
170     return;
171   case MachineOperand::MO_GlobalAddress:
172     O << Mang->getValueName(MO.getGlobal());
173     break;
174   case MachineOperand::MO_ExternalSymbol:
175     O << MO.getSymbolName();
176     break;
177   case MachineOperand::MO_ConstantPoolIndex:
178     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
179       << MO.getConstantPoolIndex();
180     break;
181   default:
182     O << "<unknown operand type>"; abort (); break;
183   }
184   if (CloseParen) O << ")";
185 }
186
187 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
188                                       const char *Modifier) {
189   printOperand(MI, opNum);
190   
191   // If this is an ADD operand, emit it like normal operands.
192   if (Modifier && !strcmp(Modifier, "arith")) {
193     O << ", ";
194     printOperand(MI, opNum+1);
195     return;
196   }
197   
198   MachineOperand::MachineOperandType OpTy = MI->getOperand(opNum+1).getType();
199   
200   if (MI->getOperand(opNum+1).isRegister() &&
201       MI->getOperand(opNum+1).getReg() == SP::G0)
202     return;   // don't print "+%g0"
203   if (MI->getOperand(opNum+1).isImmediate() &&
204       MI->getOperand(opNum+1).getImmedValue() == 0)
205     return;   // don't print "+0"
206   
207   O << "+";
208   if (MI->getOperand(opNum+1).isGlobalAddress() ||
209       MI->getOperand(opNum+1).isConstantPoolIndex()) {
210     O << "%lo(";
211     printOperand(MI, opNum+1);
212     O << ")";
213   } else {
214     printOperand(MI, opNum+1);
215   }
216 }
217
218 void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
219   int CC = (int)MI->getOperand(opNum).getImmedValue();
220   O << SPARCCondCodeToString((SPCC::CondCodes)CC);
221 }
222
223
224
225 bool SparcAsmPrinter::doInitialization(Module &M) {
226   Mang = new Mangler(M);
227   return false; // success
228 }
229
230 bool SparcAsmPrinter::doFinalization(Module &M) {
231   const TargetData *TD = TM.getTargetData();
232
233   // Print out module-level global variables here.
234   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
235        I != E; ++I)
236     if (I->hasInitializer()) {   // External global require no code
237       // Check to see if this is a special global used by LLVM, if so, emit it.
238       if (EmitSpecialLLVMGlobal(I))
239         continue;
240       
241       O << "\n\n";
242       std::string name = Mang->getValueName(I);
243       Constant *C = I->getInitializer();
244       unsigned Size = TD->getTypeSize(C->getType());
245       unsigned Align = TD->getTypeAlignment(C->getType());
246
247       if (C->isNullValue() &&
248           (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
249            I->hasWeakLinkage() /* FIXME: Verify correct */)) {
250         SwitchToDataSection(".data", I);
251         if (I->hasInternalLinkage())
252           O << "\t.local " << name << "\n";
253
254         O << "\t.comm " << name << "," << TD->getTypeSize(C->getType())
255           << "," << (unsigned)TD->getTypeAlignment(C->getType());
256         O << "\t\t! ";
257         WriteAsOperand(O, I, true, true, &M);
258         O << "\n";
259       } else {
260         switch (I->getLinkage()) {
261         case GlobalValue::LinkOnceLinkage:
262         case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
263           // Nonnull linkonce -> weak
264           O << "\t.weak " << name << "\n";
265           SwitchToDataSection("", I);
266           O << "\t.section\t\".llvm.linkonce.d." << name
267             << "\",\"aw\",@progbits\n";
268           break;
269
270         case GlobalValue::AppendingLinkage:
271           // FIXME: appending linkage variables should go into a section of
272           // their name or something.  For now, just emit them as external.
273         case GlobalValue::ExternalLinkage:
274           // If external or appending, declare as a global symbol
275           O << "\t.globl " << name << "\n";
276           // FALL THROUGH
277         case GlobalValue::InternalLinkage:
278           if (C->isNullValue())
279             SwitchToDataSection(".bss", I);
280           else
281             SwitchToDataSection(".data", I);
282           break;
283         case GlobalValue::GhostLinkage:
284           std::cerr << "Should not have any unmaterialized functions!\n";
285           abort();
286         }
287
288         O << "\t.align " << Align << "\n";
289         O << "\t.type " << name << ",#object\n";
290         O << "\t.size " << name << "," << Size << "\n";
291         O << name << ":\t\t\t\t! ";
292         WriteAsOperand(O, I, true, true, &M);
293         O << "\n";
294         EmitGlobalConstant(C);
295       }
296     }
297
298   AsmPrinter::doFinalization(M);
299   return false; // success
300 }