convert some uses of printBasicBlockLabel to use GetMBBSymbol
[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     DwarfWriter *DW;
57     const XCoreSubtarget &Subtarget;
58   public:
59     explicit XCoreAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
60                              const MCAsmInfo *T, bool V)
61       : AsmPrinter(O, TM, T, V), DW(0),
62       Subtarget(TM.getSubtarget<XCoreSubtarget>()) {}
63
64     virtual const char *getPassName() const {
65       return "XCore Assembly Printer";
66     }
67
68     void printMemOperand(const MachineInstr *MI, int opNum);
69     void printOperand(const MachineInstr *MI, int opNum);
70     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
71                         unsigned AsmVariant, const char *ExtraCode);
72
73     void emitGlobalDirective(const std::string &name);
74     void emitExternDirective(const std::string &name);
75     
76     void emitArrayBound(const std::string &name, const GlobalVariable *GV);
77     virtual void PrintGlobalVariable(const GlobalVariable *GV);
78
79     void emitFunctionStart(MachineFunction &MF);
80     void emitFunctionEnd(MachineFunction &MF);
81
82     void printInstruction(const MachineInstr *MI);  // autogenerated.
83     void printMachineInstruction(const MachineInstr *MI);
84     bool runOnMachineFunction(MachineFunction &F);
85     bool doInitialization(Module &M);
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       printBasicBlockLabel(I, true , true);
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 << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
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 ";
361     O << TM.getRegisterInfo()->get(dst).AsmName;
362     O << ", ";
363     O << TM.getRegisterInfo()->get(src).AsmName;
364     O << "\n";
365     return;
366   }
367   printInstruction(MI);
368   if (VerboseAsm && !MI->getDebugLoc().isUnknown())
369     EmitComments(*MI);
370   O << '\n';
371 }
372
373 bool XCoreAsmPrinter::doInitialization(Module &M) {
374   bool Result = AsmPrinter::doInitialization(M);
375   DW = getAnalysisIfAvailable<DwarfWriter>();
376   
377   return Result;
378 }
379
380 // Force static initialization.
381 extern "C" void LLVMInitializeXCoreAsmPrinter() { 
382   RegisterAsmPrinter<XCoreAsmPrinter> X(TheXCoreTarget);
383 }