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