Iterate over globals once and sectionize them into appropriate sections.
[oota-llvm.git] / lib / Target / PIC16 / PIC16AsmPrinter.cpp
1 //===-- PIC16AsmPrinter.cpp - PIC16 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 PIC16 assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "PIC16AsmPrinter.h"
16 #include "PIC16TargetAsmInfo.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Function.h"
19 #include "llvm/Module.h"
20 #include "llvm/CodeGen/DwarfWriter.h"
21 #include "llvm/CodeGen/MachineFrameInfo.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include "llvm/Support/Mangler.h"
24 #include "llvm/CodeGen/DwarfWriter.h"
25 #include "llvm/CodeGen/MachineModuleInfo.h"
26
27 using namespace llvm;
28
29 #include "PIC16GenAsmWriter.inc"
30
31 bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
32   printInstruction(MI);
33   return true;
34 }
35
36 /// runOnMachineFunction - This uses the printInstruction()
37 /// method to print assembly for each instruction.
38 ///
39 bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
40   this->MF = &MF;
41
42   // This calls the base class function required to be called at beginning
43   // of runOnMachineFunction.
44   SetupMachineFunction(MF);
45
46   // Get the mangled name.
47   const Function *F = MF.getFunction();
48   CurrentFnName = Mang->getValueName(F);
49
50   // Emit the function variables.
51   emitFunctionData(MF);
52   const char *codeSection = PAN::getCodeSectionName(CurrentFnName).c_str();
53  
54   const Section *fCodeSection = TAI->getNamedSection(codeSection,
55                                                      SectionFlags::Code);
56   O <<  "\n";
57   // Start the Code Section.
58   SwitchToSection (fCodeSection);
59
60   // Emit the frame address of the function at the beginning of code.
61   O << "\tretlw  low(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
62   O << "\tretlw  high(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
63
64   // Emit function start label.
65   O << CurrentFnName << ":\n";
66
67   // Print out code for the function.
68   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
69        I != E; ++I) {
70     // Print a label for the basic block.
71     if (I != MF.begin()) {
72       printBasicBlockLabel(I, true);
73       O << '\n';
74     }
75     
76     // For emitting line directives, we need to keep track of the current
77     // source line. When it changes then only emit the line directive.
78     unsigned CurLine = 0;
79     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
80          II != E; ++II) {
81       // Emit the line directive if source line changed.
82       const DebugLoc DL = II->getDebugLoc();
83       if (!DL.isUnknown()) {
84         unsigned line = MF.getDebugLocTuple(DL).Line;
85         if (line != CurLine) {
86           O << "\t.line " << line << "\n";
87           CurLine = line;
88         }
89       }
90         
91       // Print the assembly for the instruction.
92       printMachineInstruction(II);
93     }
94   }
95   return false;  // we didn't modify anything.
96 }
97
98 /// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
99 /// assembly code for a MachineFunction to the given output stream,
100 /// using the given target machine description.  This should work
101 /// regardless of whether the function is in SSA form.
102 ///
103 FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
104                                                PIC16TargetMachine &tm,
105                                                CodeGenOpt::Level OptLevel,
106                                                bool verbose) {
107   return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
108 }
109
110
111 // printOperand - print operand of insn.
112 void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
113   const MachineOperand &MO = MI->getOperand(opNum);
114
115   switch (MO.getType()) {
116     case MachineOperand::MO_Register:
117       if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
118         O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
119       else
120         assert(0 && "not implemented");
121         return;
122
123     case MachineOperand::MO_Immediate:
124       O << (int)MO.getImm();
125       return;
126
127     case MachineOperand::MO_GlobalAddress: {
128       O << Mang->getValueName(MO.getGlobal());
129       break;
130     }
131     case MachineOperand::MO_ExternalSymbol: {
132        const char *Sname = MO.getSymbolName();
133
134       // If its a libcall name, record it to decls section.
135       if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) {
136         Decls.push_back(Sname);
137       }
138
139       O  << Sname;
140       break;
141     }
142     case MachineOperand::MO_MachineBasicBlock:
143       printBasicBlockLabel(MO.getMBB());
144       return;
145
146     default:
147       assert(0 && " Operand type not supported.");
148   }
149 }
150
151 void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
152   int CC = (int)MI->getOperand(opNum).getImm();
153   O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
154 }
155
156 void PIC16AsmPrinter::printDecls(void) {
157   // If no libcalls used, return.
158   if (Decls.empty()) return;
159
160   O << TAI->getCommentString() << "External decls for libcalls - BEGIN." <<"\n";
161   // Remove duplicate entries.
162   Decls.sort();
163   Decls.unique();
164   for (std::list<const char*>::const_iterator I = Decls.begin(); 
165        I != Decls.end(); I++) {
166     O << TAI->getExternDirective() << *I << "\n";
167     O << TAI->getExternDirective() << PAN::getArgsLabel(*I) << "\n";
168     O << TAI->getExternDirective() << PAN::getRetvalLabel(*I) << "\n";
169   }
170   O << TAI->getCommentString() << "External decls for libcalls - END." <<"\n";
171 }
172
173 bool PIC16AsmPrinter::doInitialization (Module &M) {
174   bool Result = AsmPrinter::doInitialization(M);
175   // FIXME:: This is temporary solution to generate the include file.
176   // The processor should be passed to llc as in input and the header file
177   // should be generated accordingly.
178   O << "\t#include P16F1937.INC\n";
179   MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
180   assert(MMI);
181   DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
182   assert(DW && "Dwarf Writer is not available");
183   DW->BeginModule(&M, MMI, O, this, TAI);
184
185   // Set the section names for all globals.
186   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
187        I != E; ++I) {
188     I->setSection(TAI->SectionForGlobal(I)->getName());
189   }
190
191   EmitExternsAndGlobals (M);
192   EmitIData(M);
193   EmitUData(M);
194   EmitAutos(M);
195   EmitRomData(M);
196   return Result;
197 }
198
199 void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
200  // Emit declarations for external functions.
201   O << TAI->getCommentString() << "External defs and decls - BEGIN." <<"\n";
202   for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
203     std::string Name = Mang->getValueName(I);
204     if (Name.compare("@abort") == 0)
205       continue;
206     
207     // If it is llvm intrinsic call then don't emit
208     if (Name.find("llvm.") != std::string::npos)
209       continue;
210
211     if (! (I->isDeclaration() || I->hasExternalLinkage()))
212       continue;
213
214     const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
215                                                  TAI->getGlobalDirective();
216       
217     O << directive << Name << "\n";
218     O << directive << PAN::getRetvalLabel(Name) << "\n";
219     O << directive << PAN::getArgsLabel(Name) << "\n";
220   }
221
222   // Emit header file to include declaration of library functions
223   // FIXME: find out libcall names.
224   // O << "\t#include C16IntrinsicCalls.INC\n";
225
226   // Emit declarations for external variable declarations and definitions.
227   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
228        I != E; I++) {
229     // Any variables reaching here with ".auto." in its name is a local scope
230     // variable and should not be printed in global data section.
231     std::string Name = Mang->getValueName(I);
232     if (PAN::isLocalName(Name))
233       continue;
234
235     if (!(I->isDeclaration() || I->hasExternalLinkage() || 
236           I->hasCommonLinkage()))
237       continue;
238
239     const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
240                                                  TAI->getGlobalDirective();
241     O << directive << Name << "\n";
242   }
243   O << TAI->getCommentString() << "External defs and decls - END." <<"\n";
244 }
245
246 void PIC16AsmPrinter::EmitRomData (Module &M)
247 {
248   const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
249
250   std::vector<const GlobalVariable*> Items = PTAI->ROSection->Items;
251   if (! Items.size()) return;
252
253   // Print ROData ection.
254   O << "\n";
255   SwitchToSection(PTAI->ROSection->S_);
256   for (unsigned j = 0; j < Items.size(); j++) {
257     O << Mang->getValueName(Items[j]);
258     Constant *C = Items[j]->getInitializer();
259     int AddrSpace = Items[j]->getType()->getAddressSpace();
260     EmitGlobalConstant(C, AddrSpace);
261   }
262 }
263
264 bool PIC16AsmPrinter::doFinalization(Module &M) {
265   printDecls();
266   O << "\t" << "END\n";
267   bool Result = AsmPrinter::doFinalization(M);
268   return Result;
269 }
270
271 void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
272   const Function *F = MF.getFunction();
273   std::string FuncName = Mang->getValueName(F);
274   const TargetData *TD = TM.getTargetData();
275   // Emit the data section name.
276   O << "\n"; 
277   const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str();
278
279   const Section *fPDataSection = TAI->getNamedSection(SectionName,
280                                                       SectionFlags::Writeable);
281   SwitchToSection(fPDataSection);
282   
283   // Emit function frame label
284   O << PAN::getFrameLabel(CurrentFnName) << ":\n";
285
286   const Type *RetType = F->getReturnType();
287   unsigned RetSize = 0; 
288   if (RetType->getTypeID() != Type::VoidTyID) 
289     RetSize = TD->getTypeAllocSize(RetType);
290   
291   //Emit function return value space
292   // FIXME: Do not emit RetvalLable when retsize is zero. To do this
293   // we will need to avoid printing a global directive for Retval label
294   // in emitExternandGloblas.
295   if(RetSize > 0)
296      O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n";
297   else
298      O << PAN::getRetvalLabel(CurrentFnName) << ": \n";
299    
300   // Emit variable to hold the space for function arguments 
301   unsigned ArgSize = 0;
302   for (Function::const_arg_iterator argi = F->arg_begin(),
303            arge = F->arg_end(); argi != arge ; ++argi) {
304     const Type *Ty = argi->getType();
305     ArgSize += TD->getTypeAllocSize(Ty);
306    }
307
308   O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n";
309
310   // Emit temporary space
311   int TempSize = PTLI->GetTmpSize();
312   if (TempSize > 0 )
313     O << PAN::getTempdataLabel(CurrentFnName) << " RES  " << TempSize <<"\n";
314 }
315
316 void PIC16AsmPrinter::EmitIData (Module &M) {
317   const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
318
319   // Print all IDATA sections.
320   std::vector <PIC16Section *>IDATASections = PTAI->IDATASections;
321   for (unsigned i = 0; i < IDATASections.size(); i++) {
322     O << "\n";
323     SwitchToSection(IDATASections[i]->S_);
324     std::vector<const GlobalVariable*> Items = IDATASections[i]->Items;
325     for (unsigned j = 0; j < Items.size(); j++) {
326       std::string Name = Mang->getValueName(Items[j]);
327       Constant *C = Items[j]->getInitializer();
328       int AddrSpace = Items[j]->getType()->getAddressSpace();
329       O << Name;
330       EmitGlobalConstant(C, AddrSpace);
331     }
332   }
333 }
334
335 void PIC16AsmPrinter::EmitUData (Module &M) {
336   const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
337   const TargetData *TD = TM.getTargetData();
338
339   // Print all BSS sections.
340   std::vector <PIC16Section *>BSSSections = PTAI->BSSSections;
341   for (unsigned i = 0; i < BSSSections.size(); i++) {
342     O << "\n";
343     SwitchToSection(BSSSections[i]->S_);
344     std::vector<const GlobalVariable*> Items = BSSSections[i]->Items;
345     for (unsigned j = 0; j < Items.size(); j++) {
346       std::string Name = Mang->getValueName(Items[j]);
347       Constant *C = Items[j]->getInitializer();
348       const Type *Ty = C->getType();
349       unsigned Size = TD->getTypeAllocSize(Ty);
350
351       O << Name << " " <<"RES"<< " " << Size ;
352       O << "\n";
353     }
354   }
355 }
356
357 void PIC16AsmPrinter::EmitAutos (Module &M)
358 {
359   // Section names for all globals are already set.
360
361   const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
362   const TargetData *TD = TM.getTargetData();
363
364   // Now print all Autos sections.
365   std::vector <PIC16Section *>AutosSections = PTAI->AutosSections;
366   for (unsigned i = 0; i < AutosSections.size(); i++) {
367     O << "\n";
368     SwitchToSection(AutosSections[i]->S_);
369     std::vector<const GlobalVariable*> Items = AutosSections[i]->Items;
370     for (unsigned j = 0; j < Items.size(); j++) {
371       std::string VarName = Mang->getValueName(Items[j]);
372       Constant *C = Items[j]->getInitializer();
373       const Type *Ty = C->getType();
374       unsigned Size = TD->getTypeAllocSize(Ty);
375       // Emit memory reserve directive.
376       O << VarName << "  RES  " << Size << "\n";
377     }
378   }
379 }