Rename MDNode.h header. It defines MDnode and other metadata classes.
[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/Metadata.h"
21 #include "llvm/Type.h"
22 #include "llvm/Assembly/Writer.h"
23 #include "llvm/CodeGen/AsmPrinter.h"
24 #include "llvm/CodeGen/DwarfWriter.h"
25 #include "llvm/Target/TargetAsmInfo.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 TargetAsmInfo *T, bool V)
45       : AsmPrinter(o, tm, T, V) {}
46
47     virtual const char *getPassName() const {
48       return "Alpha Assembly Printer";
49     }
50     bool 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   SwitchToSection(getObjFileLowering().SectionForGlobal(F, 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       if (!printInstruction(II)) {
180         llvm_unreachable("Unhandled instruction in asm writer!");
181       }
182     }
183   }
184
185   O << "\t.end " << CurrentFnName << "\n";
186
187   // We didn't modify anything.
188   return false;
189 }
190
191 bool AlphaAsmPrinter::doInitialization(Module &M)
192 {
193   if(TM.getSubtarget<AlphaSubtarget>().hasCT())
194     O << "\t.arch ev6\n"; //This might need to be ev67, so leave this test here
195   else
196     O << "\t.arch ev6\n";
197   O << "\t.set noat\n";
198   return AsmPrinter::doInitialization(M);
199 }
200
201 void AlphaAsmPrinter::PrintGlobalVariable(const GlobalVariable *GVar) {
202   const TargetData *TD = TM.getTargetData();
203
204   if (!GVar->hasInitializer()) return;  // External global require no code
205
206   // Check to see if this is a special global used by LLVM, if so, emit it.
207   if (EmitSpecialLLVMGlobal(GVar))
208     return;
209
210   std::string name = Mang->getMangledName(GVar);
211   Constant *C = GVar->getInitializer();
212   if (isa<MDNode>(C) || isa<MDString>(C))
213     return;
214   unsigned Size = TD->getTypeAllocSize(C->getType());
215   unsigned Align = TD->getPreferredAlignmentLog(GVar);
216
217   // 0: Switch to section
218   SwitchToSection(getObjFileLowering().SectionForGlobal(GVar, 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 << TAI->getWeakRefDirective() << name << '\n';
231     break;
232    case GlobalValue::AppendingLinkage:
233    case GlobalValue::ExternalLinkage:
234       O << TAI->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 (TAI->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 }