Rename getABITypeSize to getTypePaddedSize, as
[oota-llvm.git] / lib / Target / PIC16 / PIC16AsmPrinter.cpp
index 5102e7a241f039da1298b8269812dd72df562a74..d468efd7b34cc73f7a4f5f6c3842397a7f563519 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#define DEBUG_TYPE "asm-printer"
-#include "PIC16.h"
-#include "PIC16TargetMachine.h"
-#include "PIC16ConstantPoolValue.h"
-#include "PIC16InstrInfo.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
+#include "PIC16AsmPrinter.h"
+#include "PIC16TargetAsmInfo.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/Function.h"
 #include "llvm/Module.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
-#include <cctype>
+#include "llvm/DerivedTypes.h"
 
 using namespace llvm;
 
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
-namespace {
-  struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
-    PIC16AsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
-      : AsmPrinter(O, TM, T) {
-    }
-
-
-    /// We name each basic block in a Function with a unique number, so
-    /// that we can consistently refer to them later. This is cleared
-    /// at the beginning of each call to runOnMachineFunction().
-    ///
-    typedef std::map<const Value *, unsigned> ValueMapTy;
-    ValueMapTy NumberForBB;
-
-    /// Keeps the set of GlobalValues that require non-lazy-pointers for
-    /// indirect access.
-    std::set<std::string> GVNonLazyPtrs;
-
-    /// Keeps the set of external function GlobalAddresses that the asm
-    /// printer should generate stubs for.
-    std::set<std::string> FnStubs;
-
-    /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
-    bool InCPMode;
-    
-    virtual const char *getPassName() const {
-      return "PIC16 Assembly Printer";
-    }
-
-    void printOperand(const MachineInstr *MI, int opNum,
-                      const char *Modifier = 0);
-
-    void printSOImmOperand(const MachineInstr *MI, int opNum);
-
-    void printAddrModeOperand(const MachineInstr *MI, int OpNo);
-
-    void printRegisterList(const MachineInstr *MI, int opNum);
-    void printCPInstOperand(const MachineInstr *MI, int opNum,
-                            const char *Modifier);
-
-
-    bool printInstruction(const MachineInstr *MI);  // autogenerated.
-    void emitFunctionStart(MachineFunction &F);
-    bool runOnMachineFunction(MachineFunction &F);
-    bool doInitialization(Module &M);
-    bool doFinalization(Module &M);
-
-    virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
-    
-    void getAnalysisUsage(AnalysisUsage &AU) const;
-
-    public:
-    void SwitchToTextSection(const char *NewSection, 
-                             const GlobalValue *GV = NULL);    
-    void SwitchToDataSection(const char *NewSection, 
-                             const GlobalValue *GV = NULL);
-    void SwitchToDataOvrSection(const char *NewSection, 
-                                const GlobalValue *GV = NULL);
-  };
-} // end of anonymous namespace
-
 #include "PIC16GenAsmWriter.inc"
 
-/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
-/// assembly code for a MachineFunction to the given output stream,
-/// using the given target machine description.  This should work
-/// regardless of whether the function is in SSA form.
-///
-FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
-                                               PIC16TargetMachine &tm) {
-  return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
-}
-
-void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const 
-{
-  // FIXME: Currently unimplemented.
-}
-
-
-void PIC16AsmPrinter ::
-EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) 
-{
-  printDataDirective(MCPV->getType());
-
-  PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV;
-  GlobalValue *GV = ACPV->getGV();
-  std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
-  if (!GV)
-    Name += ACPV->getSymbol();
-  if (ACPV->isNonLazyPointer()) {
-    GVNonLazyPtrs.insert(Name);
-    O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
-  } else if (ACPV->isStub()) {
-    FnStubs.insert(Name);
-    O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
-  } else {
-    O << Name;
-  }
-
-  if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
-
-  if (ACPV->getPCAdjustment() != 0) {
-    O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
-      << utostr(ACPV->getLabelId())
-      << "+" << (unsigned)ACPV->getPCAdjustment();
-
-    if (ACPV->mustAddCurrentAddress())
-      O << "-.";
-
-    O << ")";
-  }
-  O << "\n";
-
-  // If the constant pool value is a extern weak symbol, remember to emit
-  // the weak reference.
-  if (GV && GV->hasExternalWeakLinkage())
-    ExtWeakSymbols.insert(GV);
-}
-
-/// emitFunctionStart - Emit the directives used by ASM on the start of 
-/// functions.
-void PIC16AsmPrinter::emitFunctionStart(MachineFunction &MF)
-{
-  // Print out the label for the function.
-  const Function *F = MF.getFunction();
-  MachineFrameInfo *FrameInfo = MF.getFrameInfo();
-  if (FrameInfo->hasStackObjects()) {           
-    int indexBegin = FrameInfo->getObjectIndexBegin();
-    int indexEnd = FrameInfo->getObjectIndexEnd();
-    while (indexBegin < indexEnd) {
-      if (indexBegin == 0)                     
-        SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(),
-                                F);
-                 
-        O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES" 
-          << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ;
-        indexBegin++;
+bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
+  std::string NewBankselLabel;
+  unsigned Operands = MI->getNumOperands();
+  if (Operands > 1) {
+    // Global address or external symbol should be second operand from last
+    // if we want to print banksel for it.
+    const MachineOperand &Op = MI->getOperand(Operands-2);
+    unsigned OpType = Op.getType();
+    if (OpType == MachineOperand::MO_GlobalAddress ||
+        OpType == MachineOperand::MO_ExternalSymbol) { 
+      if (OpType == MachineOperand::MO_GlobalAddress ) 
+        NewBankselLabel =  Mang->getValueName(Op.getGlobal());
+      else 
+        NewBankselLabel =  Op.getSymbolName();
+
+      // 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(Operands-1);
+      if (((int)BS.getImm() == 1) &&
+          (strcmp (CurrentBankselLabelInBasicBlock.c_str(),
+                   NewBankselLabel.c_str()))) {
+        CurrentBankselLabelInBasicBlock = NewBankselLabel;
+        O << "\tbanksel ";
+        printOperand(MI, Operands-2);
+        O << "\n";
+      }
     }
   }
-  SwitchToTextSection(CurrentFnName.c_str(), F);  
-  O << "_" << CurrentFnName << ":" ; 
-  O << "\n";
+  printInstruction(MI);
+  return true;
 }
 
-
 /// runOnMachineFunction - This uses the printInstruction()
 /// method to print assembly for each instruction.
 ///
-bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) 
-{
+bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+  // This calls the base class function required to be called at beginning
+  // of runOnMachineFunction.
   SetupMachineFunction(MF);
-  O << "\n";
 
-  // What's my mangled name?
-  CurrentFnName = Mang->getValueName(MF.getFunction());
+  // Get the mangled name.
+  const Function *F = MF.getFunction();
+  CurrentFnName = Mang->getValueName(F);
 
-  // Emit the function start directives
-  emitFunctionStart(MF);
+  // Emit the function variables.
+  emitFunctionData(MF);
+  std::string codeSection;
+  codeSection = "code." + CurrentFnName + ".#";
+  O <<  "\n";
+  SwitchToTextSection (codeSection.c_str(),F);
 
   // Print out code for the function.
   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
@@ -209,319 +85,354 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF)
       printBasicBlockLabel(I, true);
       O << '\n';
     }
+    else
+      O << CurrentFnName << ":\n";
+    CurrentBankselLabelInBasicBlock = "";
     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
          II != E; ++II) {
       // Print the assembly for the instruction.
-      O << '\t';
-      printInstruction(II);
-      ++EmittedInsts;
+        printMachineInstruction(II);
     }
   }
+  return false;  // we didn't modify anything.
+}
 
-  // We didn't modify anything.
-  return false;
+/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
+/// assembly code for a MachineFunction to the given output stream,
+/// using the given target machine description.  This should work
+/// regardless of whether the function is in SSA form.
+///
+FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
+                                               PIC16TargetMachine &tm) {
+  return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
 }
 
-void PIC16AsmPrinter::
-printOperand(const MachineInstr *MI, int opNum, const char *Modifier) 
-{
+void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
   const MachineOperand &MO = MI->getOperand(opNum);
-  const TargetRegisterInfo  &RI = *TM.getRegisterInfo();
 
   switch (MO.getType()) {
     case MachineOperand::MO_Register:
       if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
-        O << RI.get(MO.getReg()).Name;
+        O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
       else
         assert(0 && "not implemented");
-      break;
+        return;
 
-    case MachineOperand::MO_Immediate: 
-      if (!Modifier || strcmp(Modifier, "no_hash") != 0)
-        O << "#";
+    case MachineOperand::MO_Immediate:
       O << (int)MO.getImm();
-      break;
-
-    case MachineOperand::MO_MachineBasicBlock:
-      printBasicBlockLabel(MO.getMBB());
       return;
 
-    case MachineOperand::MO_GlobalAddress: 
-      O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
+    case MachineOperand::MO_GlobalAddress:
+      O << Mang->getValueName(MO.getGlobal());
       break;
 
-    case MachineOperand::MO_ExternalSymbol: 
+    case MachineOperand::MO_ExternalSymbol:
       O << MO.getSymbolName();
       break;
 
-    case MachineOperand::MO_ConstantPoolIndex:
-      O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
-        << '_' << MO.getIndex();
-      break;
-
-    case MachineOperand::MO_FrameIndex:
-      O << "_" << CurrentFnName 
-        << '+' << MO.getIndex();
-      break;
-
-    case MachineOperand::MO_JumpTableIndex:
-      O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
-        << '_' << MO.getIndex();
-      break;
-
     default:
-      O << "<unknown operand type>"; abort (); 
-      break;
-  } // end switch.
+      assert(0 && " Operand type not supported.");
+  }
 }
 
-static void 
-printSOImm(raw_ostream &O, int64_t V, const TargetAsmInfo *TAI) 
-{
-  assert(V < (1 << 12) && "Not a valid so_imm value!");
-  
-  O << (unsigned) V;
+bool PIC16AsmPrinter::doInitialization (Module &M) {
+  bool Result = AsmPrinter::doInitialization(M);
+  // FIXME:: This is temporary solution to generate the include file.
+  // The processor should be passed to llc as in input and the header file
+  // should be generated accordingly.
+  O << "\t#include P16F1937.INC\n";
+  EmitExternsAndGlobals (M);
+  EmitInitData (M);
+  EmitUnInitData(M);
+  EmitRomData(M);
+  return Result;
 }
 
-/// printSOImmOperand - SOImm is 4-bit rotated amount in bits 8-11 with 8-bit
-/// immediate in bits 0-7.
-void PIC16AsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) 
-{
-  const MachineOperand &MO = MI->getOperand(OpNum);
-  assert(MO.isImmediate() && "Not a valid so_imm value!");
-  printSOImm(O, MO.getImm(), TAI);
+void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
+ // Emit declarations for external functions.
+  O << "section.0" <<"\n";
+  for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
+    std::string Name = Mang->getValueName(I);
+    if (Name.compare("abort") == 0)
+      continue;
+    if (I->isDeclaration()) {
+      O << "\textern " <<Name << "\n";
+      O << "\textern " << Name << ".retval\n";
+      O << "\textern " << Name << ".args\n";
+    }
+    else if (I->hasExternalLinkage()) {
+      O << "\tglobal " << Name << "\n";
+      O << "\tglobal " << Name << ".retval\n";
+      O << "\tglobal " << Name << ".args\n";
+    }
+  }
+  // Emit declarations for external globals.
+  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
+       I != E; I++) {
+    std::string Name = Mang->getValueName(I);
+    if (I->isDeclaration())
+      O << "\textern "<< Name << "\n";
+    else if (I->getLinkage() == GlobalValue::CommonLinkage)
+      O << "\tglobal "<< Name << "\n";
+  }
 }
+void PIC16AsmPrinter::EmitInitData (Module &M) {
+  std::string iDataSection = "idata.#";
+  SwitchToDataSection(iDataSection.c_str());
+  for (Module::const_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();
 
-void PIC16AsmPrinter::printAddrModeOperand(const MachineInstr *MI, int Op) 
-{
-  const MachineOperand &MO1 = MI->getOperand(Op);
-  const MachineOperand &MO2 = MI->getOperand(Op+1);
+    if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
+    
+      if (EmitSpecialLLVMGlobal(I)) 
+        continue;
 
-  if (MO2.isFrameIndex ()) {
-    printOperand(MI, Op+1);
-    return;
-  }
+      // 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;
 
-  if (!MO1.isRegister()) {   
-    // FIXME: This is for CP entries, but isn't right.
-    printOperand(MI, Op);
-    return;
+      O << name;
+      EmitGlobalConstant(C);
+    }
   }
+}
 
-  // If this is Stack Slot
-  if (MO1.isRegister()) {  
-    if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) {
-      O << CurrentFnName <<"_"<< MO2.getImm();
-      return;
+void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) {
+  if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
+    unsigned BitWidth = CI->getBitWidth();
+    int Val = CI->getZExtValue();
+    if (BitWidth == 8) {
+      // Expecting db directive here. In case of romdata we need to pad the
+      // word with zeros.
+      if (IsRomData)
+        O << 0 <<", ";
+      O << Val; 
+    }
+    else if (BitWidth == 16) {
+      unsigned Element1, Element2;
+      Element1 = 0x00ff & Val;
+      Element2 = 0x00ff & (Val >> 8);
+      if (IsRomData)
+        O << 0 <<", "<<Element1 <<", "<< 0 <<", "<< Element2;
+      else
+        O << Element1 <<", "<< Element2;  
+    }
+    else if (BitWidth == 32) {
+      unsigned Element1, Element2, Element3, Element4;
+      Element1 = 0x00ff & Val;
+      Element2 = 0x00ff & (Val >> 8);
+      Element3 = 0x00ff & (Val >> 16);
+      Element4 = 0x00ff & (Val >> 24);
+      if (IsRomData)
+        O << 0 <<", "<< Element1 <<", "<< 0 <<", "<< Element2 <<", "<< 0 
+          <<", "<< Element3 <<", "<< 0 <<", "<< Element4;
+      else 
+        O << Element1 <<", "<< Element2 <<", "<< Element3 <<", "<< Element4;    
     }
-    O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
-    O << "+";
-    O << MO2.getImm();
-    O << "]";
     return;
   }
-
-  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
-  O << "]";
+  AsmPrinter::EmitConstantValueOnly(CV);
 }
 
-
-void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) 
+void PIC16AsmPrinter::EmitRomData (Module &M)
 {
-  O << "{";
-  for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
-    printOperand(MI, i);
-    if (i != e-1) O << ", ";
-  }
-  O << "}";
-}
+  std::string romDataSection = "romdata.#";
+  SwitchToRomDataSection(romDataSection.c_str());
+  IsRomData = true;
+  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
+       I != E; ++I) {
+    if (!I->hasInitializer())   // External global require no code.
+      continue;
 
-void PIC16AsmPrinter::
-printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier) 
-{
-  assert(Modifier && "This operand only works with a modifier!");
-
-  // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
-  // data itself.
-  if (!strcmp(Modifier, "label")) {
-    unsigned ID = MI->getOperand(OpNo).getImm();
-    O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
-      << '_' << ID << ":\n";
-  } else {
-    assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
-    unsigned CPI = MI->getOperand(OpNo).getIndex();
-
-    const MachineConstantPoolEntry &MCPE =  // Chasing pointers is fun?
-      MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
-    
-    if (MCPE.isMachineConstantPoolEntry())
-      EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
-    else {
-      EmitGlobalConstant(MCPE.Val.ConstVal);
-      // remember to emit the weak reference
-      if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
-        if (GV->hasExternalWeakLinkage())
-          ExtWeakSymbols.insert(GV);
+    Constant *C = I->getInitializer();
+    const PointerType *PtrTy = I->getType();
+    int AddrSpace = PtrTy->getAddressSpace();
+    if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_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 (name.find(".") != std::string::npos)
+        continue;
+
+      O << name;
+      EmitGlobalConstant(C);
+      O << "\n";
     }
   }
+  IsRomData = false;
 }
 
 
-bool PIC16AsmPrinter::doInitialization(Module &M) 
-{
-  bool Result = AsmPrinter::doInitialization(M);
-  return Result;
-}
-
-bool PIC16AsmPrinter::doFinalization(Module &M) 
+void PIC16AsmPrinter::EmitUnInitData (Module &M)
 {
+  std::string uDataSection = "udata.#";
+  SwitchToUDataSection(uDataSection.c_str());
   const TargetData *TD = TM.getTargetData();
 
   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
        I != E; ++I) {
-    if (!I->hasInitializer())   // External global require no code
+    if (!I->hasInitializer())   // External global require no code.
       continue;
 
-    if (EmitSpecialLLVMGlobal(I)) {
-      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;
+
+      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);
+  return Result;
+}
 
-    std::string name = Mang->getValueName(I);
+void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
+  const Function *F = MF.getFunction();
+  std::string FuncName = Mang->getValueName(F);
+  const Module *M = F->getParent();
+  const TargetData *TD = TM.getTargetData();
+
+  // Emit the data section name.
+  O << "\n"; 
+  std::string fDataSection = "fdata." + CurrentFnName + ".#";
+  SwitchToUDataSection(fDataSection.c_str(), F);
+  
+  //Emit function return value.
+  O << CurrentFnName << ".retval:\n";
+  const Type *RetType = F->getReturnType();
+  if (RetType->getTypeID() != Type::VoidTyID) {
+    unsigned RetSize = TD->getTypePaddedSize(RetType);
+    if (RetSize > 0)
+      O << CurrentFnName << ".retval" << " RES " << RetSize;
+   }
+  // Emit function arguments.
+  O << CurrentFnName << ".args:\n";
+  for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
+       AI != AE; ++AI) {
+    std::string ArgName = Mang->getValueName(AI);
+    const Type *ArgTy = AI->getType();
+    unsigned ArgSize = TD->getTypePaddedSize(ArgTy);
+    O << CurrentFnName << ".args." << ArgName << " RES " << ArgSize; 
+  }
+  // Emit the function variables. 
+   
+  // In PIC16 all the function arguments and local variables are global.
+  // Therefore to get the variable belonging to this function entire
+  // global list will be traversed and variables belonging to this function
+  // will be emitted in the current data section.
+  for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
+       I != E; ++I) {
+    std::string VarName = Mang->getValueName(I);
+    
+    // The variables of a function are of form FuncName.* . If this variable
+    // does not belong to this function then continue. 
+    if (!(VarName.find(FuncName + ".") == 0 ? true : false))
+      continue;
+   
     Constant *C = I->getInitializer();
     const Type *Ty = C->getType();
-    unsigned Size = TD->getABITypeSize(Ty);
-    unsigned Align = TD->getPreferredAlignmentLog(I);
+    unsigned Size = TD->getTypePaddedSize(Ty);
+    // Emit memory reserve directive.
+    O << VarName << "  RES  " << Size << "\n";
+  }
+  emitFunctionTempData(MF);
+}
 
-    const char *VisibilityDirective = NULL;
-    if (I->hasHiddenVisibility())
-      VisibilityDirective = TAI->getHiddenDirective();
-    else if (I->hasProtectedVisibility())
-      VisibilityDirective = TAI->getProtectedDirective();
+void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
+  // Emit temporary variables.
+  MachineFrameInfo *FrameInfo = MF.getFrameInfo();
+  if (FrameInfo->hasStackObjects()) {
+    int indexBegin = FrameInfo->getObjectIndexBegin();
+    int indexEnd = FrameInfo->getObjectIndexEnd();
 
-    if (VisibilityDirective)
-      O << VisibilityDirective << name << "\n";
+    if (indexBegin < indexEnd)
+      O << CurrentFnName << ".tmp RES"<< " " 
+        <<indexEnd - indexBegin <<"\n";
+    /*
+    while (indexBegin < indexEnd) {
+        O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " " 
+          << 1 << "\n" ;
+        indexBegin++;
+    }
+    */
+  }
+}
 
-    if (C->isNullValue()) {
-      if (I->hasExternalLinkage()) {
-        if (const char *Directive = TAI->getZeroFillDirective()) {
-          O << "\t.globl\t" << name << "\n";
-          O << Directive << "__DATA__, __common, " << name << ", "
-            << Size << ", " << Align << "\n";
-          continue;
-        }
-      }
+/// The function is same as AsmPrinter::SwitchtoDataSection except the call
+/// to getUDataSectionStartSuffix.
+void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection,
+                                           const GlobalValue *GV) {
+  std::string NS;
+  if (GV && GV->hasSection())
+    NS = TAI->getSwitchToSectionDirective() + GV->getSection();
+  else
+    NS = NewSection;
 
-      if (!I->hasSection() &&
-          (I->hasInternalLinkage() || I->hasWeakLinkage() ||
-           I->hasLinkOnceLinkage() || I->hasCommonLinkage())) {
-        if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
-        SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
-        if (TAI->getLCOMMDirective() != NULL) {
-          if (I->hasInternalLinkage()) {
-            O << TAI->getLCOMMDirective() << name << "," << Size;
-          } else
-            O << TAI->getCOMMDirective()  << name << "," << Size;
-        } else {
-          if (I->hasInternalLinkage())
-            O << "\t.local\t" << name << "\n";
-
-          O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " " 
-            << Size;
-          O << "\n\t\tGLOBAL" <<" "<< name;
-          if (TAI->getCOMMDirectiveTakesAlignment())
-            O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
-        }
-        continue;
-      }
-    }
+  // If we're already in this section, we're done.
+  if (CurrentSection == NS) return;
 
-    switch (I->getLinkage()) {
-    case GlobalValue::AppendingLinkage:
-      // FIXME: appending linkage variables should go into a section of
-      // their name or something.  For now, just emit them as external.
-      // FALL THROUGH
+  // Close the current section, if applicable.
+  if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
+    O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
 
-    case GlobalValue::ExternalLinkage:
-      O << "\t.globl " << name << "\n";
-      // FALL THROUGH
+  CurrentSection = NS;
 
-    case GlobalValue::InternalLinkage: 
-      break;
+  if (!CurrentSection.empty()){}
+    O << CurrentSection << (static_cast<const PIC16TargetAsmInfo *>(TAI))->
+                            getUDataSectionStartSuffix() << '\n';
 
-    default:
-      assert(0 && "Unknown linkage type!");
-      break;
-    } // end switch.
+  IsInTextSection = false;
+}
 
-    EmitAlignment(Align, I);
-    O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
-      << "\n";
+/// The function is same as AsmPrinter::SwitchtoDataSection except the call
+/// to getRomDataSectionStartSuffix.
+void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection,
+                                             const GlobalValue *GV) {
+  std::string NS;
+  if (GV && GV->hasSection())
+    NS = TAI->getSwitchToSectionDirective() + GV->getSection();
+  else
+    NS = NewSection;
 
-    // If the initializer is a extern weak symbol, remember to emit the weak
-    // reference!
-    if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
-      if (GV->hasExternalWeakLinkage())
-        ExtWeakSymbols.insert(GV);
+  // If we're already in this section, we're done.
+  if (CurrentSection == NS) return;
 
-    EmitGlobalConstant(C);
-    O << '\n';
-  } // end for.
+  // Close the current section, if applicable.
+  if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
+    O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
 
-  O << "\n "<< "END";
-  return AsmPrinter::doFinalization(M);
-}
+  CurrentSection = NS;
 
-void PIC16AsmPrinter::
-SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
-{
-  O << "\n";
-  if (NewSection && *NewSection) {
-    std::string codeSection = "code_";
-    codeSection += NewSection;
-    codeSection += " ";
-    codeSection += "CODE";
-    AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV);
-  } 
-  else 
-    AsmPrinter::SwitchToTextSection(NewSection, GV);
-}
+  if (!CurrentSection.empty()) {}
+    O << CurrentSection << (static_cast< const PIC16TargetAsmInfo *>(TAI))->
+                            getRomDataSectionStartSuffix() << '\n';
 
-void PIC16AsmPrinter::
-SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
-{
-  // Need to append index for page.
-  O << "\n";
-  if (NewSection && *NewSection) {
-    std::string dataSection = "udata_";
-    dataSection += NewSection;
-    if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
-      dataSection = dataSection.substr(0, dataSection.length() - 2);
-    }
-    dataSection += " ";
-    dataSection += "UDATA";
-    AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
-  } 
-  else
-    AsmPrinter::SwitchToDataSection(NewSection, GV);
+  IsInTextSection = false;
 }
 
-void PIC16AsmPrinter::
-SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
-{
-  O << "\n";
-  if (NewSection && *NewSection) {
-    std::string dataSection = "frame_";
-    dataSection += NewSection;
-    if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
-      dataSection = dataSection.substr(0, dataSection.length() - 2);
-    }          
-    dataSection += "_";
-    dataSection += CurrentFnName;
-    dataSection += " ";
-    dataSection += "UDATA_OVR";
-    AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
-  } 
-  else
-    AsmPrinter::SwitchToDataSection(NewSection, GV);
-}