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