Emit banksel and movlp instructions.
Split large global data (both initialized and un-initialized) into multiple sections of <= 80 bytes.
Provide routines to manage PIC16 ABI naming conventions.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71073 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp
index 510e105..87ecb20 100644
--- a/lib/Target/PIC16/PIC16AsmPrinter.cpp
+++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp
@@ -45,51 +45,6 @@
 }
 
 bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
-  std::string NewBank = "";
-  unsigned Operands = MI->getNumOperands();
-  if (Operands > 1) {
-    // If we have a Global address or external symbol then we need to print 
-    // banksel for it. 
-    unsigned BankSelVar = 0;
-    MachineOperand Op = MI->getOperand(BankSelVar);
-    while (BankSelVar < Operands-1) {
-      Op = MI->getOperand(BankSelVar);
-      if ((Op.getType() ==  MachineOperand::MO_GlobalAddress) ||
-          (Op.getType() ==  MachineOperand::MO_ExternalSymbol))
-        break;
-      BankSelVar++;
-    }
-    if (BankSelVar < Operands-1) {
-      unsigned OpType = Op.getType();
-      if (OpType == MachineOperand::MO_GlobalAddress ) 
-        NewBank = Op.getGlobal()->getSection(); 
-      else {
-        // External Symbol is generated for temp data and arguments. They are 
-        // in fpdata.<functionname>.# section.
-        std::string ESName = Op.getSymbolName();
-        int index = ESName.find_first_of(".");
-        std::string FnName = ESName.substr(0,index);
-        NewBank = "fpdata." + FnName +".#";
-      }
-      // Operand after global address or external symbol should be  banksel.
-      // Value 1 for this operand means we need to generate banksel else do not
-      // generate banksel.
-      const MachineOperand &BS = MI->getOperand(BankSelVar+1);
-      // If Section names are same then the variables are in same section.
-      // This is not true for external variables as section names for global
-      // variables in all files are same at this time. For eg. initialized 
-      // data in put in idata.# section in all files. 
-      if ((BS.getType() == MachineOperand::MO_Immediate 
-          && (int)BS.getImm() == 1) 
-          && ((Op.isGlobal() && Op.getGlobal()->hasExternalLinkage()) ||
-           (NewBank.compare(CurBank) != 0))) { 
-        O << "\tbanksel ";
-        printOperand(MI, BankSelVar);
-        O << "\n";
-        CurBank = NewBank;
-      }
-    }
-  }
   printInstruction(MI);
   return true;
 }
@@ -118,8 +73,8 @@
   SwitchToSection (fCodeSection);
 
   // Emit the frame address of the function at the beginning of code.
-  O << "    retlw  low(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n";
-  O << "    retlw  high(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n"; 
+  O << "    retlw  low(" << FunctionLabelBegin<< CurrentFnName << ".frame.)\n";
+  O << "    retlw  high(" << FunctionLabelBegin<< CurrentFnName << ".frame.)\n"; 
   O << CurrentFnName << ":\n";
 
 
@@ -131,7 +86,6 @@
       printBasicBlockLabel(I, true);
       O << '\n';
     }
-    CurBank = "";
     
     // For emitting line directives, we need to keep track of the current
     // source line. When it changes then only emit the line directive.
@@ -225,8 +179,7 @@
   DW->BeginModule(&M, MMI, O, this, TAI);
 
   EmitExternsAndGlobals (M);
-  EmitInitData (M);
-  EmitUnInitData(M);
+  EmitGlobalData(M);
   EmitRomData(M);
   return Result;
 }
@@ -245,13 +198,13 @@
 
     if (I->isDeclaration()) {
       O << "\textern " <<Name << "\n";
-      O << "\textern "  << FunctionLabelBegin << Name << ".retval\n";
-      O << "\textern " << FunctionLabelBegin << Name << ".args\n";
+      O << "\textern "  << FunctionLabelBegin << Name << ".ret.\n";
+      O << "\textern " << FunctionLabelBegin << Name << ".args.\n";
     }
     else if (I->hasExternalLinkage()) {
       O << "\tglobal " << Name << "\n";
-      O << "\tglobal " << FunctionLabelBegin << Name << ".retval\n";
-      O << "\tglobal " << FunctionLabelBegin<< Name << ".args\n";
+      O << "\tglobal " << FunctionLabelBegin << Name << ".ret.\n";
+      O << "\tglobal " << FunctionLabelBegin<< Name << ".args.\n";
     }
   }
 
@@ -274,35 +227,6 @@
   }
 }
 
-void PIC16AsmPrinter::EmitInitData (Module &M) {
-  SwitchToSection(TAI->getDataSection());
-  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
-       I != E; ++I) {
-    if (!I->hasInitializer())   // External global require no code.
-      continue;
-
-    Constant *C = I->getInitializer();
-    const PointerType *PtrTy = I->getType();
-    int AddrSpace = PtrTy->getAddressSpace();
-
-    if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
-    
-      if (EmitSpecialLLVMGlobal(I)) 
-        continue;
-
-      // Any variables reaching here with "." in its name is a local scope
-      // variable and should not be printed in global data section.
-      std::string Name = Mang->getValueName(I);
-      if (isLocalName(Name))
-        continue;
-
-      I->setSection(TAI->getDataSection()->getName());
-      O << Name;
-      EmitGlobalConstant(C, AddrSpace);
-    }
-  }
-}
-
 void PIC16AsmPrinter::EmitRomData (Module &M)
 {
   SwitchToSection(TAI->getReadOnlySection());
@@ -335,39 +259,6 @@
   IsRomData = false;
 }
 
-void PIC16AsmPrinter::EmitUnInitData (Module &M)
-{
-  SwitchToSection(TAI->getBSSSection_());
-  const TargetData *TD = TM.getTargetData();
-
-  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
-       I != E; ++I) {
-    if (!I->hasInitializer())   // External global require no code.
-      continue;
-
-    Constant *C = I->getInitializer();
-    if (C->isNullValue()) {
-
-      if (EmitSpecialLLVMGlobal(I))
-        continue;
-
-      // Any variables reaching here with "." in its name is a local scope
-      // variable and should not be printed in global data section.
-      std::string name = Mang->getValueName(I);
-      if (name.find(".") != std::string::npos)
-        continue;
-
-      I->setSection(TAI->getBSSSection_()->getName());
-
-      const Type *Ty = C->getType();
-      unsigned Size = TD->getTypePaddedSize(Ty);
-
-      O << name << " " <<"RES"<< " " << Size ;
-      O << "\n";
-    }
-  }
-}
-
 bool PIC16AsmPrinter::doFinalization(Module &M) {
   O << "\t" << "END\n";
   bool Result = AsmPrinter::doFinalization(M);
@@ -390,7 +281,7 @@
   
 
   // Emit function frame label
-  O << FunctionLabelBegin << CurrentFnName << ".frame:\n";
+  O << FunctionLabelBegin << CurrentFnName << ".frame.:\n";
 
   const Type *RetType = F->getReturnType();
   unsigned RetSize = 0; 
@@ -399,10 +290,10 @@
   
   //Emit function return value space
   if(RetSize > 0)
-     O << FunctionLabelBegin << CurrentFnName << ".retval    RES  " << RetSize 
+     O << FunctionLabelBegin << CurrentFnName << ".ret.    RES  " << RetSize 
        << "\n";
   else
-     O << FunctionLabelBegin << CurrentFnName << ".retval:\n";
+     O << FunctionLabelBegin << CurrentFnName << ".ret.:\n";
    
   // Emit variable to hold the space for function arguments 
   unsigned ArgSize = 0;
@@ -411,13 +302,13 @@
     const Type *Ty = argi->getType();
     ArgSize += TD->getTypePaddedSize(Ty);
    }
-  O << FunctionLabelBegin << CurrentFnName << ".args      RES  " << ArgSize 
+  O << FunctionLabelBegin << CurrentFnName << ".args.      RES  " << ArgSize 
     << "\n";
 
   // Emit temporary space
   int TempSize = PTLI->GetTmpSize();
   if (TempSize > 0 )
-    O << FunctionLabelBegin << CurrentFnName << ".tmp       RES  " << TempSize 
+    O << FunctionLabelBegin << CurrentFnName << ".temp.       RES  " << TempSize 
       <<"\n";
 
   // Emit the section name for local variables.
@@ -454,5 +345,40 @@
     // Emit memory reserve directive.
     O << FunctionLabelBegin << VarName << "  RES  " << Size << "\n";
   }
-
 }
+
+void PIC16AsmPrinter::EmitGlobalData (Module &M)
+{
+  const PIC16TargetAsmInfo *PTAI = static_cast<const PIC16TargetAsmInfo *>(TAI);
+  const_cast<PIC16TargetAsmInfo *>(PTAI)->SetSectionForGVs(M);
+  const TargetData *TD = TM.getTargetData();
+
+  std::vector <PIC16Section *>IDATASections = PTAI->getIDATASections();
+  for (unsigned i = 0; i < IDATASections.size(); i++) {
+    SwitchToSection(IDATASections[i]->S_);
+    std::vector<const GlobalVariable*> Items = IDATASections[i]->Items;
+    for (unsigned j = 0; j < Items.size(); j++) {
+      std::string Name = Mang->getValueName(Items[j]);
+      Constant *C = Items[j]->getInitializer();
+      int AddrSpace = Items[j]->getType()->getAddressSpace();
+      O << Name;
+      EmitGlobalConstant(C, AddrSpace);
+    }
+  }
+
+  std::vector <PIC16Section *>BSSSections = PTAI->getBSSSections();
+  for (unsigned i = 0; i < BSSSections.size(); i++) {
+    SwitchToSection(BSSSections[i]->S_);
+    std::vector<const GlobalVariable*> Items = BSSSections[i]->Items;
+    for (unsigned j = 0; j < Items.size(); j++) {
+      std::string Name = Mang->getValueName(Items[j]);
+      Constant *C = Items[j]->getInitializer();
+      const Type *Ty = C->getType();
+      unsigned Size = TD->getTypePaddedSize(Ty);
+
+      O << Name << " " <<"RES"<< " " << Size ;
+      O << "\n";
+    }
+  }
+}
+