Remove trailing whitespace
[oota-llvm.git] / lib / Target / Alpha / AlphaAsmPrinter.cpp
1 //===-- AlphaAsmPrinter.cpp - Alpha 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 Alpha assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "Alpha.h"
16 #include "AlphaInstrInfo.h"
17 #include "llvm/Module.h"
18 #include "llvm/Type.h"
19 #include "llvm/Assembly/Writer.h"
20 #include "llvm/CodeGen/MachineConstantPool.h"
21 #include "llvm/CodeGen/ValueTypes.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23
24 #include "llvm/Target/TargetMachine.h"
25
26 #include "llvm/Support/Mangler.h"
27 #include "llvm/ADT/Statistic.h"
28 #include "llvm/Support/CommandLine.h"
29
30 using namespace llvm;
31
32 namespace llvm {
33   extern cl::opt<bool> EnableAlphaFTOI;
34 }
35
36 namespace {
37   Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
38
39   struct AlphaAsmPrinter : public AsmPrinter {
40
41     /// Unique incrementer for label values for referencing Global values.
42     ///
43     unsigned LabelNumber;
44
45      AlphaAsmPrinter(std::ostream &o, TargetMachine &tm)
46        : AsmPrinter(o, tm), LabelNumber(0)
47     {
48       AlignmentIsInBytes = false;
49     }
50
51     /// We name each basic block in a Function with a unique number, so
52     /// that we can consistently refer to them later. This is cleared
53     /// at the beginning of each call to runOnMachineFunction().
54     ///
55     typedef std::map<const Value *, unsigned> ValueMapTy;
56     ValueMapTy NumberForBB;
57     std::string CurSection;
58
59     virtual const char *getPassName() const {
60       return "Alpha Assembly Printer";
61     }
62     bool printInstruction(const MachineInstr *MI);
63     void printOp(const MachineOperand &MO, bool IsCallOp = false);
64     void printConstantPool(MachineConstantPool *MCP);
65     void printOperand(const MachineInstr *MI, int opNum, MVT::ValueType VT);
66     void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true);
67     void printMachineInstruction(const MachineInstr *MI);
68     bool runOnMachineFunction(MachineFunction &F);
69     bool doInitialization(Module &M);
70     bool doFinalization(Module &M);
71     void SwitchSection(std::ostream &OS, const char *NewSection);
72   };
73 } // end of anonymous namespace
74
75 /// createAlphaCodePrinterPass - Returns a pass that prints the Alpha
76 /// assembly code for a MachineFunction to the given output stream,
77 /// using the given target machine description.  This should work
78 /// regardless of whether the function is in SSA form.
79 ///
80 FunctionPass *llvm::createAlphaCodePrinterPass (std::ostream &o,
81                                                   TargetMachine &tm) {
82   return new AlphaAsmPrinter(o, tm);
83 }
84
85 #include "AlphaGenAsmWriter.inc"
86
87 void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum, MVT::ValueType VT)
88 {
89   const MachineOperand &MO = MI->getOperand(opNum);
90   if (MO.getType() == MachineOperand::MO_MachineRegister) {
91     assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
92     O << TM.getRegisterInfo()->get(MO.getReg()).Name;
93   } else if (MO.isImmediate()) {
94     O << MO.getImmedValue();
95   } else {
96     printOp(MO);
97   }
98 }
99
100
101 void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
102   const MRegisterInfo &RI = *TM.getRegisterInfo();
103   int new_symbol;
104
105   switch (MO.getType()) {
106   case MachineOperand::MO_VirtualRegister:
107     if (Value *V = MO.getVRegValueOrNull()) {
108       O << "<" << V->getName() << ">";
109       return;
110     }
111     // FALLTHROUGH
112   case MachineOperand::MO_MachineRegister:
113   case MachineOperand::MO_CCRegister:
114     O << RI.get(MO.getReg()).Name;
115     return;
116
117   case MachineOperand::MO_SignExtendedImmed:
118   case MachineOperand::MO_UnextendedImmed:
119     std::cerr << "printOp() does not handle immediate values\n";
120     abort();
121     return;
122
123   case MachineOperand::MO_PCRelativeDisp:
124     std::cerr << "Shouldn't use addPCDisp() when building Alpha MachineInstrs";
125     abort();
126     return;
127
128   case MachineOperand::MO_MachineBasicBlock: {
129     MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
130     O << "LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
131       << "_" << MBBOp->getNumber() << "\t" << CommentString << " "
132       << MBBOp->getBasicBlock()->getName();
133     return;
134   }
135
136   case MachineOperand::MO_ConstantPoolIndex:
137     O << "CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
138     return;
139
140   case MachineOperand::MO_ExternalSymbol:
141     O << MO.getSymbolName();
142     return;
143
144   case MachineOperand::MO_GlobalAddress:
145     //Abuse PCrel to specify pcrel calls
146     //calls are the only thing that use this flag
147     if (MO.isPCRelative())
148       O << "$" << Mang->getValueName(MO.getGlobal()) << "..ng";
149     else
150       O << Mang->getValueName(MO.getGlobal());
151     return;
152
153   default:
154     O << "<unknown operand type: " << MO.getType() << ">";
155     return;
156   }
157 }
158
159 /// printMachineInstruction -- Print out a single Alpha MI to
160 /// the current output stream.
161 ///
162 void AlphaAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
163   ++EmittedInsts;
164   if (printInstruction(MI))
165     return; // Printer was automatically generated
166
167   assert(0 && "Unhandled instruction in asm writer!");
168   abort();
169   return;
170 }
171
172
173 /// runOnMachineFunction - This uses the printMachineInstruction()
174 /// method to print assembly for each instruction.
175 ///
176 bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
177   setupMachineFunction(MF);
178   O << "\n\n";
179
180   // Print out constants referenced by the function
181   printConstantPool(MF.getConstantPool());
182
183   // Print out labels for the function.
184   SwitchSection(O, "text");
185   emitAlignment(4);
186   O << "\t.globl\t" << CurrentFnName << "\n";
187   O << "\t.ent\t" << CurrentFnName << "\n";
188
189   O << CurrentFnName << ":\n";
190
191   // Print out code for the function.
192   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
193        I != E; ++I) {
194     // Print a label for the basic block.
195     O << "LBB" << CurrentFnName << "_" << I->getNumber() << ":\t"
196       << CommentString << " " << I->getBasicBlock()->getName() << "\n";
197     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
198          II != E; ++II) {
199       // Print the assembly for the instruction.
200       O << "\t";
201       printMachineInstruction(II);
202     }
203   }
204   ++LabelNumber;
205
206   O << "\t.end " << CurrentFnName << "\n";
207
208   // We didn't modify anything.
209   return false;
210 }
211
212
213 /// printConstantPool - Print to the current output stream assembly
214 /// representations of the constants in the constant pool MCP. This is
215 /// used to print out constants which have been "spilled to memory" by
216 /// the code generator.
217 ///
218 void AlphaAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
219   const std::vector<Constant*> &CP = MCP->getConstants();
220   const TargetData &TD = TM.getTargetData();
221
222   if (CP.empty()) return;
223
224   SwitchSection(O, "section .rodata");
225   for (unsigned i = 0, e = CP.size(); i != e; ++i) {
226     //    SwitchSection(O, "section .rodata, \"dr\"");
227     emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType()));
228     O << "CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString
229       << *CP[i] << "\n";
230     emitGlobalConstant(CP[i]);
231   }
232 }
233
234 bool AlphaAsmPrinter::doInitialization(Module &M)
235 {
236   AsmPrinter::doInitialization(M);
237   if(EnableAlphaFTOI)
238     O << "\t.arch ev6\n";
239   else
240     O << "\t.arch ev56\n";
241   return false;
242 }
243
244
245 // SwitchSection - Switch to the specified section of the executable if we are
246 // not already in it!
247 //
248 void AlphaAsmPrinter::SwitchSection(std::ostream &OS, const char *NewSection)
249 {
250   if (CurSection != NewSection) {
251     CurSection = NewSection;
252     if (!CurSection.empty())
253       OS << "\t." << NewSection << "\n";
254   }
255 }
256
257 bool AlphaAsmPrinter::doFinalization(Module &M) {
258   const TargetData &TD = TM.getTargetData();
259
260   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
261     if (I->hasInitializer()) {   // External global require no code
262       O << "\n\n";
263       std::string name = Mang->getValueName(I);
264       Constant *C = I->getInitializer();
265       unsigned Size = TD.getTypeSize(C->getType());
266       unsigned Align = TD.getTypeAlignmentShift(C->getType());
267
268       if (C->isNullValue() &&
269           (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
270            I->hasWeakLinkage() /* FIXME: Verify correct */)) {
271         SwitchSection(O, "data");
272         if (I->hasInternalLinkage())
273           O << "\t.local " << name << "\n";
274
275         O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
276           << "," << (1 << Align);
277         O << "\t\t# ";
278         WriteAsOperand(O, I, true, true, &M);
279         O << "\n";
280       } else {
281         switch (I->getLinkage()) {
282         case GlobalValue::LinkOnceLinkage:
283         case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
284           // Nonnull linkonce -> weak
285           O << "\t.weak " << name << "\n";
286           SwitchSection(O, "");
287           O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
288           break;
289         case GlobalValue::AppendingLinkage:
290           // FIXME: appending linkage variables should go into a section of
291           // their name or something.  For now, just emit them as external.
292         case GlobalValue::ExternalLinkage:
293           // If external or appending, declare as a global symbol
294           O << "\t.globl " << name << "\n";
295           // FALL THROUGH
296         case GlobalValue::InternalLinkage:
297           if (C->isNullValue())
298             SwitchSection(O, "bss"); //was .bss
299           else
300             SwitchSection(O, "data");
301           break;
302         case GlobalValue::GhostLinkage:
303           std::cerr << "GhostLinkage cannot appear in AlphaAsmPrinter!\n";
304           abort();
305         }
306
307         emitAlignment(Align);
308         O << "\t.type " << name << ",@object\n";
309         O << "\t.size " << name << "," << Size << "\n";
310         O << name << ":\t\t\t\t# ";
311         WriteAsOperand(O, I, true, true, &M);
312         O << " = ";
313         WriteAsOperand(O, C, false, false, &M);
314         O << "\n";
315         emitGlobalConstant(C);
316       }
317     }
318
319   AsmPrinter::doFinalization(M);
320   return false;
321 }