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