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