The AsmPrinter base class contains a DwarfWriter member, so there's no need
[oota-llvm.git] / lib / Target / XCore / AsmPrinter / XCoreAsmPrinter.cpp
1 //===-- XCoreAsmPrinter.cpp - XCore 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 the XAS-format XCore assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "asm-printer"
16 #include "XCore.h"
17 #include "XCoreInstrInfo.h"
18 #include "XCoreSubtarget.h"
19 #include "XCoreMCAsmInfo.h"
20 #include "XCoreTargetMachine.h"
21 #include "llvm/Constants.h"
22 #include "llvm/DerivedTypes.h"
23 #include "llvm/Module.h"
24 #include "llvm/CodeGen/AsmPrinter.h"
25 #include "llvm/CodeGen/DwarfWriter.h"
26 #include "llvm/CodeGen/MachineModuleInfo.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineConstantPool.h"
29 #include "llvm/CodeGen/MachineInstr.h"
30 #include "llvm/MC/MCStreamer.h"
31 #include "llvm/MC/MCSymbol.h"
32 #include "llvm/Target/TargetData.h"
33 #include "llvm/Target/TargetLoweringObjectFile.h"
34 #include "llvm/Target/TargetRegistry.h"
35 #include "llvm/ADT/Statistic.h"
36 #include "llvm/ADT/StringExtras.h"
37 #include "llvm/Support/CommandLine.h"
38 #include "llvm/Support/ErrorHandling.h"
39 #include "llvm/Support/FormattedStream.h"
40 #include "llvm/Support/Mangler.h"
41 #include "llvm/Support/MathExtras.h"
42 #include <algorithm>
43 #include <cctype>
44 using namespace llvm;
45
46 STATISTIC(EmittedInsts, "Number of machine instrs printed");
47
48 static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional,
49   cl::desc("Maximum number of threads (for emulation thread-local storage)"),
50   cl::Hidden,
51   cl::value_desc("number"),
52   cl::init(8));
53
54 namespace {
55   class VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter {
56     const XCoreSubtarget &Subtarget;
57   public:
58     explicit XCoreAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
59                              const MCAsmInfo *T, bool V)
60       : AsmPrinter(O, TM, T, V),
61       Subtarget(TM.getSubtarget<XCoreSubtarget>()) {}
62
63     virtual const char *getPassName() const {
64       return "XCore Assembly Printer";
65     }
66
67     void printMemOperand(const MachineInstr *MI, int opNum);
68     void printOperand(const MachineInstr *MI, int opNum);
69     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
70                         unsigned AsmVariant, const char *ExtraCode);
71
72     void emitGlobalDirective(const std::string &name);
73     void emitExternDirective(const std::string &name);
74     
75     void emitArrayBound(const std::string &name, const GlobalVariable *GV);
76     virtual void PrintGlobalVariable(const GlobalVariable *GV);
77
78     void emitFunctionStart(MachineFunction &MF);
79     void emitFunctionEnd(MachineFunction &MF);
80
81     void printInstruction(const MachineInstr *MI);  // autogenerated.
82     static const char *getRegisterName(unsigned RegNo);
83
84     void printMachineInstruction(const MachineInstr *MI);
85     bool runOnMachineFunction(MachineFunction &F);
86     
87     void getAnalysisUsage(AnalysisUsage &AU) const {
88       AsmPrinter::getAnalysisUsage(AU);
89       AU.setPreservesAll();
90       AU.addRequired<MachineModuleInfo>();
91       AU.addRequired<DwarfWriter>();
92     }
93   };
94 } // end of anonymous namespace
95
96 #include "XCoreGenAsmWriter.inc"
97
98 void XCoreAsmPrinter::
99 emitGlobalDirective(const std::string &name)
100 {
101   O << MAI->getGlobalDirective() << name;
102   O << "\n";
103 }
104
105 void XCoreAsmPrinter::
106 emitExternDirective(const std::string &name)
107 {
108   O << "\t.extern\t" << name;
109   O << '\n';
110 }
111
112 void XCoreAsmPrinter::
113 emitArrayBound(const std::string &name, const GlobalVariable *GV)
114 {
115   assert(((GV->hasExternalLinkage() ||
116     GV->hasWeakLinkage()) ||
117     GV->hasLinkOnceLinkage()) && "Unexpected linkage");
118   if (const ArrayType *ATy = dyn_cast<ArrayType>(
119     cast<PointerType>(GV->getType())->getElementType()))
120   {
121     O << MAI->getGlobalDirective() << name << ".globound" << "\n";
122     O << MAI->getSetDirective() << name << ".globound" << ","
123       << ATy->getNumElements() << "\n";
124     if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
125       // TODO Use COMDAT groups for LinkOnceLinkage
126       O << MAI->getWeakDefDirective() << name << ".globound" << "\n";
127     }
128   }
129 }
130
131 void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) {
132   // Check to see if this is a special global used by LLVM, if so, emit it.
133   if (!GV->hasInitializer() ||
134       EmitSpecialLLVMGlobal(GV))
135     return;
136
137   const TargetData *TD = TM.getTargetData();
138   
139   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));
140   
141   std::string name = Mang->getMangledName(GV);
142   Constant *C = GV->getInitializer();
143   unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
144   
145   // Mark the start of the global
146   O << "\t.cc_top " << name << ".data," << name << "\n";
147
148   switch (GV->getLinkage()) {
149   case GlobalValue::AppendingLinkage:
150     llvm_report_error("AppendingLinkage is not supported by this target!");
151   case GlobalValue::LinkOnceAnyLinkage:
152   case GlobalValue::LinkOnceODRLinkage:
153   case GlobalValue::WeakAnyLinkage:
154   case GlobalValue::WeakODRLinkage:
155   case GlobalValue::ExternalLinkage:
156     emitArrayBound(name, GV);
157     emitGlobalDirective(name);
158     // TODO Use COMDAT groups for LinkOnceLinkage
159     if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
160       O << MAI->getWeakDefDirective() << name << "\n";
161     }
162     // FALL THROUGH
163   case GlobalValue::InternalLinkage:
164   case GlobalValue::PrivateLinkage:
165   case GlobalValue::LinkerPrivateLinkage:
166     break;
167   case GlobalValue::GhostLinkage:
168     llvm_unreachable("Should not have any unmaterialized functions!");
169   case GlobalValue::DLLImportLinkage:
170     llvm_unreachable("DLLImport linkage is not supported by this target!");
171   case GlobalValue::DLLExportLinkage:
172     llvm_unreachable("DLLExport linkage is not supported by this target!");
173   default:
174     llvm_unreachable("Unknown linkage type!");
175   }
176
177   EmitAlignment(Align, GV, 2);
178   
179   unsigned Size = TD->getTypeAllocSize(C->getType());
180   if (GV->isThreadLocal()) {
181     Size *= MaxThreads;
182   }
183   if (MAI->hasDotTypeDotSizeDirective()) {
184     O << "\t.type " << name << ",@object\n";
185     O << "\t.size " << name << "," << Size << "\n";
186   }
187   O << name << ":\n";
188   
189   EmitGlobalConstant(C);
190   if (GV->isThreadLocal()) {
191     for (unsigned i = 1; i < MaxThreads; ++i) {
192       EmitGlobalConstant(C);
193     }
194   }
195   if (Size < 4) {
196     // The ABI requires that unsigned scalar types smaller than 32 bits
197     // are are padded to 32 bits.
198     EmitZeros(4 - Size);
199   }
200   
201   // Mark the end of the global
202   O << "\t.cc_bottom " << name << ".data\n";
203 }
204
205 /// Emit the directives on the start of functions
206 void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) {
207   // Print out the label for the function.
208   const Function *F = MF.getFunction();
209
210   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
211   
212   // Mark the start of the function
213   O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n";
214
215   switch (F->getLinkage()) {
216   default: llvm_unreachable("Unknown linkage type!");
217   case Function::InternalLinkage:  // Symbols default to internal.
218   case Function::PrivateLinkage:
219   case Function::LinkerPrivateLinkage:
220     break;
221   case Function::ExternalLinkage:
222     emitGlobalDirective(CurrentFnName);
223     break;
224   case Function::LinkOnceAnyLinkage:
225   case Function::LinkOnceODRLinkage:
226   case Function::WeakAnyLinkage:
227   case Function::WeakODRLinkage:
228     // TODO Use COMDAT groups for LinkOnceLinkage
229     O << MAI->getGlobalDirective() << CurrentFnName << "\n";
230     O << MAI->getWeakDefDirective() << CurrentFnName << "\n";
231     break;
232   }
233   // (1 << 1) byte aligned
234   EmitAlignment(MF.getAlignment(), F, 1);
235   if (MAI->hasDotTypeDotSizeDirective()) {
236     O << "\t.type " << CurrentFnName << ",@function\n";
237   }
238   O << CurrentFnName << ":\n";
239 }
240
241 /// Emit the directives on the end of functions
242 void XCoreAsmPrinter::
243 emitFunctionEnd(MachineFunction &MF) 
244 {
245   // Mark the end of the function
246   O << "\t.cc_bottom " << CurrentFnName << ".function\n";
247 }
248
249 /// runOnMachineFunction - This uses the printMachineInstruction()
250 /// method to print assembly for each instruction.
251 ///
252 bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF)
253 {
254   this->MF = &MF;
255
256   SetupMachineFunction(MF);
257
258   // Print out constants referenced by the function
259   EmitConstantPool(MF.getConstantPool());
260
261   // Print out jump tables referenced by the function
262   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
263
264   // Emit the function start directives
265   emitFunctionStart(MF);
266   
267   // Emit pre-function debug information.
268   DW->BeginFunction(&MF);
269
270   // Print out code for the function.
271   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
272        I != E; ++I) {
273
274     // Print a label for the basic block.
275     if (I != MF.begin()) {
276       EmitBasicBlockStart(I);
277       O << '\n';
278     }
279
280     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
281          II != E; ++II) {
282       // Print the assembly for the instruction.
283       printMachineInstruction(II);
284     }
285
286     // Each Basic Block is separated by a newline
287     O << '\n';
288   }
289
290   // Emit function end directives
291   emitFunctionEnd(MF);
292   
293   // Emit post-function debug information.
294   DW->EndFunction(&MF);
295
296   // We didn't modify anything.
297   return false;
298 }
299
300 void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum)
301 {
302   printOperand(MI, opNum);
303   
304   if (MI->getOperand(opNum+1).isImm()
305     && MI->getOperand(opNum+1).getImm() == 0)
306     return;
307   
308   O << "+";
309   printOperand(MI, opNum+1);
310 }
311
312 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
313   const MachineOperand &MO = MI->getOperand(opNum);
314   switch (MO.getType()) {
315   case MachineOperand::MO_Register:
316     O << getRegisterName(MO.getReg());
317     break;
318   case MachineOperand::MO_Immediate:
319     O << MO.getImm();
320     break;
321   case MachineOperand::MO_MachineBasicBlock:
322     GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
323     break;
324   case MachineOperand::MO_GlobalAddress:
325     O << Mang->getMangledName(MO.getGlobal());
326     break;
327   case MachineOperand::MO_ExternalSymbol:
328     O << MO.getSymbolName();
329     break;
330   case MachineOperand::MO_ConstantPoolIndex:
331     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
332       << '_' << MO.getIndex();
333     break;
334   case MachineOperand::MO_JumpTableIndex:
335     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
336       << '_' << MO.getIndex();
337     break;
338   default:
339     llvm_unreachable("not implemented");
340   }
341 }
342
343 /// PrintAsmOperand - Print out an operand for an inline asm expression.
344 ///
345 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
346                                       unsigned AsmVariant, 
347                                       const char *ExtraCode) {
348   printOperand(MI, OpNo);
349   return false;
350 }
351
352 void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
353   ++EmittedInsts;
354
355   processDebugLoc(MI->getDebugLoc());
356
357   // Check for mov mnemonic
358   unsigned src, dst, srcSR, dstSR;
359   if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) {
360     O << "\tmov " << getRegisterName(dst) << ", ";
361     O << getRegisterName(src) << '\n';
362     return;
363   }
364   printInstruction(MI);
365   if (VerboseAsm && !MI->getDebugLoc().isUnknown())
366     EmitComments(*MI);
367   O << '\n';
368 }
369
370 // Force static initialization.
371 extern "C" void LLVMInitializeXCoreAsmPrinter() { 
372   RegisterAsmPrinter<XCoreAsmPrinter> X(TheXCoreTarget);
373 }