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