209a5bf416673cf19e13a62585c5dd6ecd8dd5f1
[oota-llvm.git] / lib / Target / Alpha / AsmPrinter / AlphaAsmPrinter.cpp
1 //===-- AlphaAsmPrinter.cpp - Alpha 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 Alpha assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "asm-printer"
16 #include "Alpha.h"
17 #include "AlphaInstrInfo.h"
18 #include "AlphaTargetMachine.h"
19 #include "llvm/Module.h"
20 #include "llvm/Type.h"
21 #include "llvm/Assembly/Writer.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/DwarfWriter.h"
24 #include "llvm/MC/MCStreamer.h"
25 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/Target/TargetLoweringObjectFile.h"
28 #include "llvm/Target/TargetMachine.h"
29 #include "llvm/Target/TargetRegistry.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/Mangler.h"
32 #include "llvm/Support/FormattedStream.h"
33 #include "llvm/ADT/Statistic.h"
34 using namespace llvm;
35
36 STATISTIC(EmittedInsts, "Number of machine instrs printed");
37
38 namespace {
39   struct AlphaAsmPrinter : public AsmPrinter {
40     /// Unique incrementer for label values for referencing Global values.
41     ///
42
43     explicit AlphaAsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
44                              const MCAsmInfo *T, bool V)
45       : AsmPrinter(o, tm, T, V) {}
46
47     virtual const char *getPassName() const {
48       return "Alpha Assembly Printer";
49     }
50     void printInstruction(const MachineInstr *MI);
51     static const char *getRegisterName(unsigned RegNo);
52
53     void printOp(const MachineOperand &MO, bool IsCallOp = false);
54     void printOperand(const MachineInstr *MI, int opNum);
55     void printBaseOffsetPair(const MachineInstr *MI, int i, bool brackets=true);
56     void PrintGlobalVariable(const GlobalVariable *GVar);
57     bool runOnMachineFunction(MachineFunction &F);
58     void EmitStartOfAsmFile(Module &M);
59
60     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
61                          unsigned AsmVariant, const char *ExtraCode);
62     bool PrintAsmMemoryOperand(const MachineInstr *MI,
63                                unsigned OpNo,
64                                unsigned AsmVariant,
65                                const char *ExtraCode);
66   };
67 } // end of anonymous namespace
68
69 #include "AlphaGenAsmWriter.inc"
70
71 void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum)
72 {
73   const MachineOperand &MO = MI->getOperand(opNum);
74   if (MO.getType() == MachineOperand::MO_Register) {
75     assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
76            "Not physreg??");
77     O << getRegisterName(MO.getReg());
78   } else if (MO.isImm()) {
79     O << MO.getImm();
80     assert(MO.getImm() < (1 << 30));
81   } else {
82     printOp(MO);
83   }
84 }
85
86
87 void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
88   switch (MO.getType()) {
89   case MachineOperand::MO_Register:
90     O << getRegisterName(MO.getReg());
91     return;
92
93   case MachineOperand::MO_Immediate:
94     llvm_unreachable("printOp() does not handle immediate values");
95     return;
96
97   case MachineOperand::MO_MachineBasicBlock:
98     GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
99     return;
100
101   case MachineOperand::MO_ConstantPoolIndex:
102     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
103       << MO.getIndex();
104     return;
105
106   case MachineOperand::MO_ExternalSymbol:
107     O << MO.getSymbolName();
108     return;
109
110   case MachineOperand::MO_GlobalAddress:
111     O << Mang->getMangledName(MO.getGlobal());
112     return;
113
114   case MachineOperand::MO_JumpTableIndex:
115     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
116       << '_' << MO.getIndex();
117     return;
118
119   default:
120     O << "<unknown operand type: " << MO.getType() << ">";
121     return;
122   }
123 }
124
125 /// runOnMachineFunction - This uses the printMachineInstruction()
126 /// method to print assembly for each instruction.
127 ///
128 bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
129   this->MF = &MF;
130
131   SetupMachineFunction(MF);
132   O << "\n\n";
133
134   // Print out constants referenced by the function
135   EmitConstantPool(MF.getConstantPool());
136
137   // Print out jump tables referenced by the function
138   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
139
140   // Print out labels for the function.
141   const Function *F = MF.getFunction();
142   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
143
144   EmitAlignment(MF.getAlignment(), F);
145   switch (F->getLinkage()) {
146   default: llvm_unreachable("Unknown linkage type!");
147   case Function::InternalLinkage:  // Symbols default to internal.
148   case Function::PrivateLinkage:
149   case Function::LinkerPrivateLinkage:
150     break;
151    case Function::ExternalLinkage:
152      O << "\t.globl " << CurrentFnName << "\n";
153      break;
154   case Function::WeakAnyLinkage:
155   case Function::WeakODRLinkage:
156   case Function::LinkOnceAnyLinkage:
157   case Function::LinkOnceODRLinkage:
158     O << MAI->getWeakRefDirective() << CurrentFnName << "\n";
159     break;
160   }
161
162   printVisibility(CurrentFnName, F->getVisibility());
163
164   O << "\t.ent " << CurrentFnName << "\n";
165
166   O << CurrentFnName << ":\n";
167
168   // Print out code for the function.
169   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
170        I != E; ++I) {
171     if (I != MF.begin()) {
172       EmitBasicBlockStart(I);
173     }
174     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
175          II != E; ++II) {
176       // Print the assembly for the instruction.
177       ++EmittedInsts;
178       processDebugLoc(II, true);
179       printInstruction(II);
180       
181       if (VerboseAsm && !II->getDebugLoc().isUnknown())
182         EmitComments(*II);
183       O << '\n';
184       processDebugLoc(II, false);
185     }
186   }
187
188   O << "\t.end " << CurrentFnName << "\n";
189
190   // We didn't modify anything.
191   return false;
192 }
193
194 void AlphaAsmPrinter::EmitStartOfAsmFile(Module &M) {
195   if (TM.getSubtarget<AlphaSubtarget>().hasCT())
196     O << "\t.arch ev6\n"; //This might need to be ev67, so leave this test here
197   else
198     O << "\t.arch ev6\n";
199   O << "\t.set noat\n";
200 }
201
202 void AlphaAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
203   const TargetData *TD = TM.getTargetData();
204
205   if (!GVar->hasInitializer()) return;  // External global require no code
206
207   // Check to see if this is a special global used by LLVM, if so, emit it.
208   if (EmitSpecialLLVMGlobal(GVar))
209     return;
210
211   std::string name = Mang->getMangledName(GVar);
212   Constant *C = GVar->getInitializer();
213   unsigned Size = TD->getTypeAllocSize(C->getType());
214   unsigned Align = TD->getPreferredAlignmentLog(GVar);
215
216   // 0: Switch to section
217   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
218                                                                   TM));
219
220   // 1: Check visibility
221   printVisibility(name, GVar->getVisibility());
222
223   // 2: Kind
224   switch (GVar->getLinkage()) {
225    case GlobalValue::LinkOnceAnyLinkage:
226    case GlobalValue::LinkOnceODRLinkage:
227    case GlobalValue::WeakAnyLinkage:
228    case GlobalValue::WeakODRLinkage:
229    case GlobalValue::CommonLinkage:
230     O << MAI->getWeakRefDirective() << name << '\n';
231     break;
232    case GlobalValue::AppendingLinkage:
233    case GlobalValue::ExternalLinkage:
234       O << MAI->getGlobalDirective() << name << "\n";
235       break;
236     case GlobalValue::InternalLinkage:
237     case GlobalValue::PrivateLinkage:
238     case GlobalValue::LinkerPrivateLinkage:
239       break;
240     default:
241       llvm_unreachable("Unknown linkage type!");
242     }
243
244   // 3: Type, Size, Align
245   if (MAI->hasDotTypeDotSizeDirective()) {
246     O << "\t.type\t" << name << ", @object\n";
247     O << "\t.size\t" << name << ", " << Size << "\n";
248   }
249
250   EmitAlignment(Align, GVar);
251
252   O << name << ":\n";
253
254   EmitGlobalConstant(C);
255   O << '\n';
256 }
257
258 /// PrintAsmOperand - Print out an operand for an inline asm expression.
259 ///
260 bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
261                                       unsigned AsmVariant,
262                                       const char *ExtraCode) {
263   printOperand(MI, OpNo);
264   return false;
265 }
266
267 bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
268                                             unsigned OpNo,
269                                             unsigned AsmVariant,
270                                             const char *ExtraCode) {
271   if (ExtraCode && ExtraCode[0])
272     return true; // Unknown modifier.
273   O << "0(";
274   printOperand(MI, OpNo);
275   O << ")";
276   return false;
277 }
278
279 // Force static initialization.
280 extern "C" void LLVMInitializeAlphaAsmPrinter() { 
281   RegisterAsmPrinter<AlphaAsmPrinter> X(TheAlphaTarget);
282 }