r70270 isn't ready yet. Back this out. Sorry for the noise.
[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 inline static bool isLocalToFunc (std::string &FuncName, std::string &VarName) {
32   if (VarName.find(FuncName + ".auto.") != std::string::npos 
33       || VarName.find(FuncName + ".arg.") != std::string::npos)
34     return true;
35
36   return false;
37 }
38
39 inline static bool isLocalName (std::string &Name) {
40   if (Name.find(".auto.") != std::string::npos 
41       || Name.find(".arg.") != std::string::npos) 
42     return true;
43
44   return false;
45 }
46
47 bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
48   std::string NewBank = "";
49   unsigned Operands = MI->getNumOperands();
50   if (Operands > 1) {
51     // If we have a Global address or external symbol then we need to print 
52     // banksel for it. 
53     unsigned BankSelVar = 0;
54     MachineOperand Op = MI->getOperand(BankSelVar);
55     while (BankSelVar < Operands-1) {
56       Op = MI->getOperand(BankSelVar);
57       if ((Op.getType() ==  MachineOperand::MO_GlobalAddress) ||
58           (Op.getType() ==  MachineOperand::MO_ExternalSymbol))
59         break;
60       BankSelVar++;
61     }
62     if (BankSelVar < Operands-1) {
63       unsigned OpType = Op.getType();
64       if (OpType == MachineOperand::MO_GlobalAddress ) 
65         NewBank = Op.getGlobal()->getSection(); 
66       else {
67         // External Symbol is generated for temp data and arguments. They are 
68         // in fpdata.<functionname>.# section.
69         std::string ESName = Op.getSymbolName();
70         int index = ESName.find_first_of(".");
71         std::string FnName = ESName.substr(0,index);
72         NewBank = "fpdata." + FnName +".#";
73       }
74       // Operand after global address or external symbol should be  banksel.
75       // Value 1 for this operand means we need to generate banksel else do not
76       // generate banksel.
77       const MachineOperand &BS = MI->getOperand(BankSelVar+1);
78       // If Section names are same then the variables are in same section.
79       // This is not true for external variables as section names for global
80       // variables in all files are same at this time. For eg. initialized 
81       // data in put in idata.# section in all files. 
82       if ((BS.getType() == MachineOperand::MO_Immediate 
83           && (int)BS.getImm() == 1) 
84           && ((Op.isGlobal() && Op.getGlobal()->hasExternalLinkage()) ||
85            (NewBank.compare(CurBank) != 0))) { 
86         O << "\tbanksel ";
87         printOperand(MI, BankSelVar);
88         O << "\n";
89         CurBank = NewBank;
90       }
91     }
92   }
93   printInstruction(MI);
94   return true;
95 }
96
97 /// runOnMachineFunction - This uses the printInstruction()
98 /// method to print assembly for each instruction.
99 ///
100 bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
101   this->MF = &MF;
102
103   // This calls the base class function required to be called at beginning
104   // of runOnMachineFunction.
105   SetupMachineFunction(MF);
106
107   // Get the mangled name.
108   const Function *F = MF.getFunction();
109   CurrentFnName = Mang->getValueName(F);
110
111   // Emit the function variables.
112   emitFunctionData(MF);
113   std::string codeSection;
114   codeSection = "code." + CurrentFnName + ".# " + "CODE";
115   const Section *fCodeSection = TAI->getNamedSection(codeSection.c_str(),
116                                                SectionFlags::Code);
117   O <<  "\n";
118   SwitchToSection (fCodeSection);
119
120   // Emit the frame address of the function at the beginning of code.
121   O << "    retlw  low(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n";
122   O << "    retlw  high(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n"; 
123   O << CurrentFnName << ":\n";
124
125
126   // Print out code for the function.
127   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
128        I != E; ++I) {
129     // Print a label for the basic block.
130     if (I != MF.begin()) {
131       printBasicBlockLabel(I, true);
132       O << '\n';
133     }
134     CurBank = "";
135     
136     // For emitting line directives, we need to keep track of the current
137     // source line. When it changes then only emit the line directive.
138     unsigned CurLine = 0;
139     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
140          II != E; ++II) {
141       // Emit the line directive if source line changed.
142       const DebugLoc DL = II->getDebugLoc();
143       if (!DL.isUnknown()) {
144         unsigned line = MF.getDebugLocTuple(DL).Line;
145         if (line != CurLine) {
146           O << "\t.line " << line << "\n";
147           CurLine = line;
148         }
149       }
150       // Print the assembly for the instruction.
151       printMachineInstruction(II);
152     }
153   }
154   return false;  // we didn't modify anything.
155 }
156
157 /// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
158 /// assembly code for a MachineFunction to the given output stream,
159 /// using the given target machine description.  This should work
160 /// regardless of whether the function is in SSA form.
161 ///
162 FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
163                                                PIC16TargetMachine &tm,
164                                                bool fast, bool verbose) {
165   return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo(), fast, verbose);
166 }
167
168 void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
169   const MachineOperand &MO = MI->getOperand(opNum);
170
171   switch (MO.getType()) {
172     case MachineOperand::MO_Register:
173       if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
174         O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
175       else
176         assert(0 && "not implemented");
177         return;
178
179     case MachineOperand::MO_Immediate:
180       O << (int)MO.getImm();
181       return;
182
183     case MachineOperand::MO_GlobalAddress: {
184       std::string Name = Mang->getValueName(MO.getGlobal());
185       if (isLocalName(Name)) 
186         O << FunctionLabelBegin << Mang->getValueName(MO.getGlobal());
187       else
188          O << Mang->getValueName(MO.getGlobal());
189       break;
190     }
191     case MachineOperand::MO_ExternalSymbol: {
192       std::string Name = MO.getSymbolName(); 
193       if (Name.find("__intrinsics.") != std::string::npos)
194         O  << MO.getSymbolName();
195       else
196         O << FunctionLabelBegin << MO.getSymbolName();
197       break;
198     }
199     case MachineOperand::MO_MachineBasicBlock:
200       printBasicBlockLabel(MO.getMBB());
201       return;
202
203     default:
204       assert(0 && " Operand type not supported.");
205   }
206 }
207
208 void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
209   int CC = (int)MI->getOperand(opNum).getImm();
210   O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
211 }
212
213
214 bool PIC16AsmPrinter::doInitialization (Module &M) {
215   bool Result = AsmPrinter::doInitialization(M);
216   // FIXME:: This is temporary solution to generate the include file.
217   // The processor should be passed to llc as in input and the header file
218   // should be generated accordingly.
219   O << "\t#include P16F1937.INC\n";
220   MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
221   assert(MMI);
222   DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
223   assert(DW && "Dwarf Writer is not available");
224   DW->BeginModule(&M, MMI, O, this, TAI);
225
226   EmitExternsAndGlobals (M);
227   EmitInitData (M);
228   EmitUnInitData(M);
229   EmitRomData(M);
230   return Result;
231 }
232
233 void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
234  // Emit declarations for external functions.
235   O << "section.0" <<"\n";
236   for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
237     std::string Name = Mang->getValueName(I);
238     if (Name.compare("abort") == 0)
239       continue;
240     
241     // If it is llvm intrinsic call then don't emit
242     if (Name.find("llvm.") != std::string::npos)
243       continue;
244
245     if (I->isDeclaration()) {
246       O << "\textern " <<Name << "\n";
247       O << "\textern "  << FunctionLabelBegin << Name << ".retval\n";
248       O << "\textern " << FunctionLabelBegin << Name << ".args\n";
249     }
250     else if (I->hasExternalLinkage()) {
251       O << "\tglobal " << Name << "\n";
252       O << "\tglobal " << FunctionLabelBegin << Name << ".retval\n";
253       O << "\tglobal " << FunctionLabelBegin<< Name << ".args\n";
254     }
255   }
256
257   // Emit header file to include declaration of library functions
258   O << "\t#include C16IntrinsicCalls.INC\n";
259
260   // Emit declarations for external globals.
261   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
262        I != E; I++) {
263     // Any variables reaching here with ".auto." in its name is a local scope
264     // variable and should not be printed in global data section.
265     std::string Name = Mang->getValueName(I);
266     if (isLocalName (Name))
267       continue;
268
269     if (I->isDeclaration())
270       O << "\textern "<< Name << "\n";
271     else if (I->hasCommonLinkage() || I->hasExternalLinkage())
272       O << "\tglobal "<< Name << "\n";
273   }
274 }
275
276 void PIC16AsmPrinter::EmitInitData (Module &M) {
277   SwitchToSection(TAI->getDataSection());
278   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
279        I != E; ++I) {
280     if (!I->hasInitializer())   // External global require no code.
281       continue;
282
283     Constant *C = I->getInitializer();
284     const PointerType *PtrTy = I->getType();
285     int AddrSpace = PtrTy->getAddressSpace();
286
287     if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
288     
289       if (EmitSpecialLLVMGlobal(I)) 
290         continue;
291
292       // Any variables reaching here with "." in its name is a local scope
293       // variable and should not be printed in global data section.
294       std::string Name = Mang->getValueName(I);
295       if (isLocalName(Name))
296         continue;
297
298       I->setSection(TAI->getDataSection()->getName());
299       O << Name;
300       EmitGlobalConstant(C, AddrSpace);
301     }
302   }
303 }
304
305 void PIC16AsmPrinter::EmitRomData (Module &M)
306 {
307   SwitchToSection(TAI->getReadOnlySection());
308   IsRomData = true;
309   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
310        I != E; ++I) {
311     if (!I->hasInitializer())   // External global require no code.
312       continue;
313
314     Constant *C = I->getInitializer();
315     const PointerType *PtrTy = I->getType();
316     int AddrSpace = PtrTy->getAddressSpace();
317     if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_SPACE)) {
318
319       if (EmitSpecialLLVMGlobal(I))
320         continue;
321
322       // Any variables reaching here with "." in its name is a local scope
323       // variable and should not be printed in global data section.
324       std::string name = Mang->getValueName(I);
325       if (name.find(".") != std::string::npos)
326         continue;
327
328       I->setSection(TAI->getReadOnlySection()->getName());
329       O << name;
330       EmitGlobalConstant(C, AddrSpace);
331       O << "\n";
332     }
333   }
334   IsRomData = false;
335 }
336
337 void PIC16AsmPrinter::EmitUnInitData (Module &M)
338 {
339   SwitchToSection(TAI->getBSSSection_());
340   const TargetData *TD = TM.getTargetData();
341
342   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
343        I != E; ++I) {
344     if (!I->hasInitializer())   // External global require no code.
345       continue;
346
347     Constant *C = I->getInitializer();
348     if (C->isNullValue()) {
349
350       if (EmitSpecialLLVMGlobal(I))
351         continue;
352
353       // Any variables reaching here with "." in its name is a local scope
354       // variable and should not be printed in global data section.
355       std::string name = Mang->getValueName(I);
356       if (name.find(".") != std::string::npos)
357         continue;
358
359       I->setSection(TAI->getBSSSection_()->getName());
360
361       const Type *Ty = C->getType();
362       unsigned Size = TD->getTypePaddedSize(Ty);
363
364       O << name << " " <<"RES"<< " " << Size ;
365       O << "\n";
366     }
367   }
368 }
369
370 bool PIC16AsmPrinter::doFinalization(Module &M) {
371   O << "\t" << "END\n";
372   bool Result = AsmPrinter::doFinalization(M);
373   return Result;
374 }
375
376 void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
377   const Function *F = MF.getFunction();
378   std::string FuncName = Mang->getValueName(F);
379   Module *M = const_cast<Module *>(F->getParent());
380   const TargetData *TD = TM.getTargetData();
381   unsigned FrameSize = 0;
382   // Emit the data section name.
383   O << "\n"; 
384   std::string SectionName = "fpdata." + CurrentFnName + ".# " + "UDATA_OVR";
385
386   const Section *fPDataSection = TAI->getNamedSection(SectionName.c_str(),
387                                                       SectionFlags::Writeable);
388   SwitchToSection(fPDataSection);
389   
390
391   // Emit function frame label
392   O << FunctionLabelBegin << CurrentFnName << ".frame:\n";
393
394   const Type *RetType = F->getReturnType();
395   unsigned RetSize = 0; 
396   if (RetType->getTypeID() != Type::VoidTyID) 
397     RetSize = TD->getTypePaddedSize(RetType);
398   
399   //Emit function return value space
400   if(RetSize > 0)
401      O << FunctionLabelBegin << CurrentFnName << ".retval    RES  " << RetSize 
402        << "\n";
403   else
404      O << FunctionLabelBegin << CurrentFnName << ".retval:\n";
405    
406   // Emit variable to hold the space for function arguments 
407   unsigned ArgSize = 0;
408   for (Function::const_arg_iterator argi = F->arg_begin(),
409            arge = F->arg_end(); argi != arge ; ++argi) {
410     const Type *Ty = argi->getType();
411     ArgSize += TD->getTypePaddedSize(Ty);
412    }
413   O << FunctionLabelBegin << CurrentFnName << ".args      RES  " << ArgSize 
414     << "\n";
415
416   // Emit temporary space
417   int TempSize = PTLI->GetTmpSize();
418   if (TempSize > 0 )
419     O << FunctionLabelBegin << CurrentFnName << ".tmp       RES  " << TempSize 
420       <<"\n";
421
422   // Emit the section name for local variables.
423   O << "\n";
424   std::string SecNameLocals = "fadata." + CurrentFnName + ".# " + "UDATA_OVR";
425
426   const Section *fADataSection = TAI->getNamedSection(SecNameLocals.c_str(),
427                                                       SectionFlags::Writeable);
428   SwitchToSection(fADataSection);
429
430   // Emit the function variables. 
431    
432   // In PIC16 all the function arguments and local variables are global.
433   // Therefore to get the variable belonging to this function entire
434   // global list will be traversed and variables belonging to this function
435   // will be emitted in the current data section.
436   for (Module::global_iterator I = M->global_begin(), E = M->global_end();
437        I != E; ++I) {
438     std::string VarName = Mang->getValueName(I);
439     
440     // The variables of a function are of form FuncName.* . If this variable
441     // does not belong to this function then continue. 
442     // Static local varilabes of a function does not have .auto. in their
443     // name. They are not printed as part of function data but module
444     // level global data.
445     if (! isLocalToFunc(FuncName, VarName))
446      continue;
447
448     I->setSection("fadata." + CurrentFnName + ".#");
449     Constant *C = I->getInitializer();
450     const Type *Ty = C->getType();
451     unsigned Size = TD->getTypePaddedSize(Ty);
452     FrameSize += Size; 
453     // Emit memory reserve directive.
454     O << FunctionLabelBegin << VarName << "  RES  " << Size << "\n";
455   }
456
457 }