Rename TargetAsmInfo (and its subclasses) to MCAsmInfo.
[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/Target/TargetLoweringObjectFile.h"
27 #include "llvm/Target/TargetMachine.h"
28 #include "llvm/Target/TargetRegistry.h"
29 #include "llvm/Support/Compiler.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 VISIBILITY_HIDDEN 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     void printOp(const MachineOperand &MO, bool IsCallOp = false);
52     void printOperand(const MachineInstr *MI, int opNum);
53     void printBaseOffsetPair(const MachineInstr *MI, int i, bool brackets=true);
54     void PrintGlobalVariable(const GlobalVariable *GVar);
55     bool runOnMachineFunction(MachineFunction &F);
56     bool doInitialization(Module &M);
57
58     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
59                          unsigned AsmVariant, const char *ExtraCode);
60     bool PrintAsmMemoryOperand(const MachineInstr *MI,
61                                unsigned OpNo,
62                                unsigned AsmVariant,
63                                const char *ExtraCode);
64   };
65 } // end of anonymous namespace
66
67 #include "AlphaGenAsmWriter.inc"
68
69 void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum)
70 {
71   const MachineOperand &MO = MI->getOperand(opNum);
72   if (MO.getType() == MachineOperand::MO_Register) {
73     assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
74            "Not physreg??");
75     O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
76   } else if (MO.isImm()) {
77     O << MO.getImm();
78     assert(MO.getImm() < (1 << 30));
79   } else {
80     printOp(MO);
81   }
82 }
83
84
85 void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
86   const TargetRegisterInfo &RI = *TM.getRegisterInfo();
87
88   switch (MO.getType()) {
89   case MachineOperand::MO_Register:
90     O << RI.get(MO.getReg()).AsmName;
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     printBasicBlockLabel(MO.getMBB());
99     return;
100
101   case MachineOperand::MO_ConstantPoolIndex:
102     O << TAI->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 << TAI->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 << TAI->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       printBasicBlockLabel(I, true, true);
173       O << '\n';
174     }
175     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
176          II != E; ++II) {
177       // Print the assembly for the instruction.
178       ++EmittedInsts;
179       printInstruction(II);
180     }
181   }
182
183   O << "\t.end " << CurrentFnName << "\n";
184
185   // We didn't modify anything.
186   return false;
187 }
188
189 bool AlphaAsmPrinter::doInitialization(Module &M)
190 {
191   if(TM.getSubtarget<AlphaSubtarget>().hasCT())
192     O << "\t.arch ev6\n"; //This might need to be ev67, so leave this test here
193   else
194     O << "\t.arch ev6\n";
195   O << "\t.set noat\n";
196   return AsmPrinter::doInitialization(M);
197 }
198
199 void AlphaAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
200   const TargetData *TD = TM.getTargetData();
201
202   if (!GVar->hasInitializer()) return;  // External global require no code
203
204   // Check to see if this is a special global used by LLVM, if so, emit it.
205   if (EmitSpecialLLVMGlobal(GVar))
206     return;
207
208   std::string name = Mang->getMangledName(GVar);
209   Constant *C = GVar->getInitializer();
210   unsigned Size = TD->getTypeAllocSize(C->getType());
211   unsigned Align = TD->getPreferredAlignmentLog(GVar);
212
213   // 0: Switch to section
214   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
215                                                                   TM));
216
217   // 1: Check visibility
218   printVisibility(name, GVar->getVisibility());
219
220   // 2: Kind
221   switch (GVar->getLinkage()) {
222    case GlobalValue::LinkOnceAnyLinkage:
223    case GlobalValue::LinkOnceODRLinkage:
224    case GlobalValue::WeakAnyLinkage:
225    case GlobalValue::WeakODRLinkage:
226    case GlobalValue::CommonLinkage:
227     O << TAI->getWeakRefDirective() << name << '\n';
228     break;
229    case GlobalValue::AppendingLinkage:
230    case GlobalValue::ExternalLinkage:
231       O << TAI->getGlobalDirective() << name << "\n";
232       break;
233     case GlobalValue::InternalLinkage:
234     case GlobalValue::PrivateLinkage:
235     case GlobalValue::LinkerPrivateLinkage:
236       break;
237     default:
238       llvm_unreachable("Unknown linkage type!");
239     }
240
241   // 3: Type, Size, Align
242   if (TAI->hasDotTypeDotSizeDirective()) {
243     O << "\t.type\t" << name << ", @object\n";
244     O << "\t.size\t" << name << ", " << Size << "\n";
245   }
246
247   EmitAlignment(Align, GVar);
248
249   O << name << ":\n";
250
251   EmitGlobalConstant(C);
252   O << '\n';
253 }
254
255 /// PrintAsmOperand - Print out an operand for an inline asm expression.
256 ///
257 bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
258                                       unsigned AsmVariant,
259                                       const char *ExtraCode) {
260   printOperand(MI, OpNo);
261   return false;
262 }
263
264 bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
265                                             unsigned OpNo,
266                                             unsigned AsmVariant,
267                                             const char *ExtraCode) {
268   if (ExtraCode && ExtraCode[0])
269     return true; // Unknown modifier.
270   O << "0(";
271   printOperand(MI, OpNo);
272   O << ")";
273   return false;
274 }
275
276 // Force static initialization.
277 extern "C" void LLVMInitializeAlphaAsmPrinter() { 
278   RegisterAsmPrinter<AlphaAsmPrinter> X(TheAlphaTarget);
279 }