Switch Alpha to new section handling stuff
[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 #define DEBUG_TYPE "asm-printer"
16 #include "PIC16.h"
17 #include "PIC16TargetMachine.h"
18 #include "PIC16ConstantPoolValue.h"
19 #include "PIC16InstrInfo.h"
20 #include "llvm/Constants.h"
21 #include "llvm/DerivedTypes.h"
22 #include "llvm/Module.h"
23 #include "llvm/ADT/Statistic.h"
24 #include "llvm/ADT/StringExtras.h"
25 #include "llvm/CodeGen/AsmPrinter.h"
26 #include "llvm/CodeGen/MachineFunctionPass.h"
27 #include "llvm/CodeGen/MachineConstantPool.h"
28 #include "llvm/CodeGen/MachineFrameInfo.h"
29 #include "llvm/CodeGen/MachineInstr.h"
30 #include "llvm/Support/CommandLine.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/Mangler.h"
33 #include "llvm/Support/MathExtras.h"
34 #include "llvm/Target/TargetAsmInfo.h"
35 #include "llvm/Target/TargetData.h"
36 #include "llvm/Target/TargetMachine.h"
37 #include "llvm/Target/TargetOptions.h"
38 #include <cctype>
39
40 using namespace llvm;
41
42 STATISTIC(EmittedInsts, "Number of machine instrs printed");
43
44 namespace {
45   struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
46     PIC16AsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
47       : AsmPrinter(O, TM, T) {
48     }
49
50
51     /// We name each basic block in a Function with a unique number, so
52     /// that we can consistently refer to them later. This is cleared
53     /// at the beginning of each call to runOnMachineFunction().
54     ///
55     typedef std::map<const Value *, unsigned> ValueMapTy;
56     ValueMapTy NumberForBB;
57
58     /// Keeps the set of GlobalValues that require non-lazy-pointers for
59     /// indirect access.
60     std::set<std::string> GVNonLazyPtrs;
61
62     /// Keeps the set of external function GlobalAddresses that the asm
63     /// printer should generate stubs for.
64     std::set<std::string> FnStubs;
65
66     /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
67     bool InCPMode;
68     
69     virtual const char *getPassName() const {
70       return "PIC16 Assembly Printer";
71     }
72
73     void printOperand(const MachineInstr *MI, int opNum,
74                       const char *Modifier = 0);
75
76     void printSOImmOperand(const MachineInstr *MI, int opNum);
77
78     void printAddrModeOperand(const MachineInstr *MI, int OpNo);
79
80     void printRegisterList(const MachineInstr *MI, int opNum);
81     void printCPInstOperand(const MachineInstr *MI, int opNum,
82                             const char *Modifier);
83
84
85     bool printInstruction(const MachineInstr *MI);  // autogenerated.
86     void emitFunctionStart(MachineFunction &F);
87     bool runOnMachineFunction(MachineFunction &F);
88     bool doInitialization(Module &M);
89     bool doFinalization(Module &M);
90
91     virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
92     
93     void getAnalysisUsage(AnalysisUsage &AU) const;
94
95     public:
96     void SwitchToTextSection(const char *NewSection, 
97                              const GlobalValue *GV = NULL);    
98     void SwitchToDataSection(const char *NewSection, 
99                              const GlobalValue *GV = NULL);
100     void SwitchToDataOvrSection(const char *NewSection, 
101                                 const GlobalValue *GV = NULL);
102   };
103 } // end of anonymous namespace
104
105 #include "PIC16GenAsmWriter.inc"
106
107 /// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
108 /// assembly code for a MachineFunction to the given output stream,
109 /// using the given target machine description.  This should work
110 /// regardless of whether the function is in SSA form.
111 ///
112 FunctionPass *llvm::createPIC16CodePrinterPass(std::ostream &o,
113                                                PIC16TargetMachine &tm) {
114   return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
115 }
116
117 void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const 
118 {
119   // FIXME: Currently unimplemented.
120 }
121
122
123 void PIC16AsmPrinter ::
124 EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) 
125 {
126   printDataDirective(MCPV->getType());
127
128   PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV;
129   GlobalValue *GV = ACPV->getGV();
130   std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
131   if (!GV)
132     Name += ACPV->getSymbol();
133   if (ACPV->isNonLazyPointer()) {
134     GVNonLazyPtrs.insert(Name);
135     O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
136   } else if (ACPV->isStub()) {
137     FnStubs.insert(Name);
138     O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
139   } else {
140     O << Name;
141   }
142
143   if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
144
145   if (ACPV->getPCAdjustment() != 0) {
146     O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
147       << utostr(ACPV->getLabelId())
148       << "+" << (unsigned)ACPV->getPCAdjustment();
149
150     if (ACPV->mustAddCurrentAddress())
151       O << "-.";
152
153     O << ")";
154   }
155   O << "\n";
156
157   // If the constant pool value is a extern weak symbol, remember to emit
158   // the weak reference.
159   if (GV && GV->hasExternalWeakLinkage())
160     ExtWeakSymbols.insert(GV);
161 }
162
163 /// emitFunctionStart - Emit the directives used by ASM on the start of 
164 /// functions.
165 void PIC16AsmPrinter::emitFunctionStart(MachineFunction &MF)
166 {
167   // Print out the label for the function.
168   const Function *F = MF.getFunction();
169   MachineFrameInfo *FrameInfo = MF.getFrameInfo();
170   if (FrameInfo->hasStackObjects()) {           
171     int indexBegin = FrameInfo->getObjectIndexBegin();
172     int indexEnd = FrameInfo->getObjectIndexEnd();
173     while (indexBegin < indexEnd) {
174       if (indexBegin == 0)                     
175         SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(),
176                                 F);
177                  
178         O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES" 
179           << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ;
180         indexBegin++;
181     }
182   }
183   SwitchToTextSection(CurrentFnName.c_str(), F);  
184   O << "_" << CurrentFnName << ":" ; 
185   O << "\n";
186 }
187
188
189 /// runOnMachineFunction - This uses the printInstruction()
190 /// method to print assembly for each instruction.
191 ///
192 bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) 
193 {
194   SetupMachineFunction(MF);
195   O << "\n";
196
197   // What's my mangled name?
198   CurrentFnName = Mang->getValueName(MF.getFunction());
199
200   // Emit the function start directives
201   emitFunctionStart(MF);
202
203   // Print out code for the function.
204   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
205        I != E; ++I) {
206     // Print a label for the basic block.
207     if (I != MF.begin()) {
208       printBasicBlockLabel(I, true);
209       O << '\n';
210     }
211     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
212          II != E; ++II) {
213       // Print the assembly for the instruction.
214       O << '\t';
215       printInstruction(II);
216       ++EmittedInsts;
217     }
218   }
219
220   // We didn't modify anything.
221   return false;
222 }
223
224 void PIC16AsmPrinter::
225 printOperand(const MachineInstr *MI, int opNum, const char *Modifier) 
226 {
227   const MachineOperand &MO = MI->getOperand(opNum);
228   const TargetRegisterInfo  &RI = *TM.getRegisterInfo();
229
230   switch (MO.getType()) {
231     case MachineOperand::MO_Register:
232       if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
233         O << RI.get(MO.getReg()).Name;
234       else
235         assert(0 && "not implemented");
236       break;
237
238     case MachineOperand::MO_Immediate: 
239       if (!Modifier || strcmp(Modifier, "no_hash") != 0)
240         O << "#";
241       O << (int)MO.getImm();
242       break;
243
244     case MachineOperand::MO_MachineBasicBlock:
245       printBasicBlockLabel(MO.getMBB());
246       return;
247
248     case MachineOperand::MO_GlobalAddress: 
249       O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
250       break;
251
252     case MachineOperand::MO_ExternalSymbol: 
253       O << MO.getSymbolName();
254       break;
255
256     case MachineOperand::MO_ConstantPoolIndex:
257       O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
258         << '_' << MO.getIndex();
259       break;
260
261     case MachineOperand::MO_FrameIndex:
262       O << "_" << CurrentFnName 
263         << '+' << MO.getIndex();
264       break;
265
266     case MachineOperand::MO_JumpTableIndex:
267       O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
268         << '_' << MO.getIndex();
269       break;
270
271     default:
272       O << "<unknown operand type>"; abort (); 
273       break;
274   } // end switch.
275 }
276
277 static void 
278 printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) 
279 {
280   assert(V < (1 << 12) && "Not a valid so_imm value!");
281   
282   O << (unsigned) V;
283 }
284
285 /// printSOImmOperand - SOImm is 4-bit rotated amount in bits 8-11 with 8-bit
286 /// immediate in bits 0-7.
287 void PIC16AsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) 
288 {
289   const MachineOperand &MO = MI->getOperand(OpNum);
290   assert(MO.isImmediate() && "Not a valid so_imm value!");
291   printSOImm(O, MO.getImm(), TAI);
292 }
293
294
295 void PIC16AsmPrinter::printAddrModeOperand(const MachineInstr *MI, int Op) 
296 {
297   const MachineOperand &MO1 = MI->getOperand(Op);
298   const MachineOperand &MO2 = MI->getOperand(Op+1);
299
300   if (MO2.isFrameIndex ()) {
301     printOperand(MI, Op+1);
302     return;
303   }
304
305   if (!MO1.isRegister()) {   
306     // FIXME: This is for CP entries, but isn't right.
307     printOperand(MI, Op);
308     return;
309   }
310
311   // If this is Stack Slot
312   if (MO1.isRegister()) {  
313     if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) {
314       O << CurrentFnName <<"_"<< MO2.getImm();
315       return;
316     }
317     O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
318     O << "+";
319     O << MO2.getImm();
320     O << "]";
321     return;
322   }
323
324   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
325   O << "]";
326 }
327
328
329 void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) 
330 {
331   O << "{";
332   for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
333     printOperand(MI, i);
334     if (i != e-1) O << ", ";
335   }
336   O << "}";
337 }
338
339 void PIC16AsmPrinter::
340 printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier) 
341 {
342   assert(Modifier && "This operand only works with a modifier!");
343
344   // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
345   // data itself.
346   if (!strcmp(Modifier, "label")) {
347     unsigned ID = MI->getOperand(OpNo).getImm();
348     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
349       << '_' << ID << ":\n";
350   } else {
351     assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
352     unsigned CPI = MI->getOperand(OpNo).getIndex();
353
354     const MachineConstantPoolEntry &MCPE =  // Chasing pointers is fun?
355       MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
356     
357     if (MCPE.isMachineConstantPoolEntry())
358       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
359     else {
360       EmitGlobalConstant(MCPE.Val.ConstVal);
361       // remember to emit the weak reference
362       if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
363         if (GV->hasExternalWeakLinkage())
364           ExtWeakSymbols.insert(GV);
365     }
366   }
367 }
368
369
370 bool PIC16AsmPrinter::doInitialization(Module &M) 
371 {
372   bool Result = AsmPrinter::doInitialization(M);
373   return Result;
374 }
375
376 bool PIC16AsmPrinter::doFinalization(Module &M) 
377 {
378   const TargetData *TD = TM.getTargetData();
379
380   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
381        I != E; ++I) {
382     if (!I->hasInitializer())   // External global require no code
383       continue;
384
385     if (EmitSpecialLLVMGlobal(I)) {
386       continue;
387     }
388
389     std::string name = Mang->getValueName(I);
390     Constant *C = I->getInitializer();
391     const Type *Ty = C->getType();
392     unsigned Size = TD->getABITypeSize(Ty);
393     unsigned Align = TD->getPreferredAlignmentLog(I);
394
395     const char *VisibilityDirective = NULL;
396     if (I->hasHiddenVisibility())
397       VisibilityDirective = TAI->getHiddenDirective();
398     else if (I->hasProtectedVisibility())
399       VisibilityDirective = TAI->getProtectedDirective();
400
401     if (VisibilityDirective)
402       O << VisibilityDirective << name << "\n";
403
404     if (C->isNullValue()) {
405       if (I->hasExternalLinkage()) {
406         if (const char *Directive = TAI->getZeroFillDirective()) {
407           O << "\t.globl\t" << name << "\n";
408           O << Directive << "__DATA__, __common, " << name << ", "
409             << Size << ", " << Align << "\n";
410           continue;
411         }
412       }
413
414       if (!I->hasSection() &&
415           (I->hasInternalLinkage() || I->hasWeakLinkage() ||
416            I->hasLinkOnceLinkage() || I->hasCommonLinkage())) {
417         if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
418         if (!NoZerosInBSS && TAI->getBSSSection())
419           SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
420         else
421           SwitchToDataSection(TAI->getDataSection(), I);
422         if (TAI->getLCOMMDirective() != NULL) {
423           if (I->hasInternalLinkage()) {
424             O << TAI->getLCOMMDirective() << name << "," << Size;
425           } else
426             O << TAI->getCOMMDirective()  << name << "," << Size;
427         } else {
428           if (I->hasInternalLinkage())
429             O << "\t.local\t" << name << "\n";
430
431           O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " " 
432             << Size;
433           O << "\n\t\tGLOBAL" <<" "<< name;
434           if (TAI->getCOMMDirectiveTakesAlignment())
435             O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
436         }
437         continue;
438       }
439     }
440
441     switch (I->getLinkage()) {
442     case GlobalValue::AppendingLinkage:
443       // FIXME: appending linkage variables should go into a section of
444       // their name or something.  For now, just emit them as external.
445       // FALL THROUGH
446
447     case GlobalValue::ExternalLinkage:
448       O << "\t.globl " << name << "\n";
449       // FALL THROUGH
450
451     case GlobalValue::InternalLinkage: 
452       if (I->isConstant()) {
453         const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
454         if (TAI->getCStringSection() && CVA && CVA->isCString()) {
455           SwitchToDataSection(TAI->getCStringSection(), I);
456           break;
457         }
458       }
459       break;
460
461     default:
462       assert(0 && "Unknown linkage type!");
463       break;
464     } // end switch.
465
466     EmitAlignment(Align, I);
467     O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
468       << "\n";
469
470     // If the initializer is a extern weak symbol, remember to emit the weak
471     // reference!
472     if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
473       if (GV->hasExternalWeakLinkage())
474         ExtWeakSymbols.insert(GV);
475
476     EmitGlobalConstant(C);
477     O << '\n';
478   } // end for.
479
480   O << "\n "<< "END";
481   return AsmPrinter::doFinalization(M);
482 }
483
484 void PIC16AsmPrinter::
485 SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
486 {
487   O << "\n";
488   if (NewSection && *NewSection) {
489     std::string codeSection = "code_";
490     codeSection += NewSection;
491     codeSection += " ";
492     codeSection += "CODE";
493     AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV);
494   } 
495   else 
496     AsmPrinter::SwitchToTextSection(NewSection, GV);
497 }
498
499 void PIC16AsmPrinter::
500 SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
501 {
502   // Need to append index for page.
503   O << "\n";
504   if (NewSection && *NewSection) {
505     std::string dataSection = "udata_";
506     dataSection += NewSection;
507     if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
508       dataSection = dataSection.substr(0, dataSection.length() - 2);
509     }
510     dataSection += " ";
511     dataSection += "UDATA";
512     AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
513   } 
514   else
515     AsmPrinter::SwitchToDataSection(NewSection, GV);
516 }
517
518 void PIC16AsmPrinter::
519 SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
520 {
521   O << "\n";
522   if (NewSection && *NewSection) {
523     std::string dataSection = "frame_";
524     dataSection += NewSection;
525     if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
526       dataSection = dataSection.substr(0, dataSection.length() - 2);
527     }          
528     dataSection += "_";
529     dataSection += CurrentFnName;
530     dataSection += " ";
531     dataSection += "UDATA_OVR";
532     AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
533   } 
534   else
535     AsmPrinter::SwitchToDataSection(NewSection, GV);
536 }