Rip all of the global variable lowering logic out of TargetAsmInfo.  Since
it is highly specific to the object file that will be generated in the end,
this introduces a new TargetLoweringObjectFile interface that is implemented
for each of ELF/MachO/COFF/Alpha/PIC16 and XCore.

Though still is still a brutal and ugly refactoring, this is a major step
towards goodness.

This patch also:
1. fixes a bunch of dangling pointer problems in the PIC16 backend.
2. disables the TargetLowering copy ctor which PIC16 was accidentally using.
3. gets us closer to xcore having its own crazy target section flags and
   pic16 not having to shadow sections with its own objects.
4. fixes wierdness where ELF targets would set CStringSection but not
   CStringSection_.  Factor the code better.
5. fixes some bugs in string lowering on ELF targets.




git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77294 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/PIC16/CMakeLists.txt b/lib/Target/PIC16/CMakeLists.txt
index 00d737a..ba1dfb4 100644
--- a/lib/Target/PIC16/CMakeLists.txt
+++ b/lib/Target/PIC16/CMakeLists.txt
@@ -21,4 +21,5 @@
   PIC16Subtarget.cpp
   PIC16TargetAsmInfo.cpp
   PIC16TargetMachine.cpp
+  PIC16TargetObjectFile.cpp
   )
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp
index ec86585..7fad6f3 100644
--- a/lib/Target/PIC16/PIC16AsmPrinter.cpp
+++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp
@@ -25,11 +25,20 @@
 #include "llvm/CodeGen/DwarfWriter.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
 
 using namespace llvm;
 
 #include "PIC16GenAsmWriter.inc"
 
+PIC16AsmPrinter::PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
+                                 const TargetAsmInfo *T, bool V)
+: AsmPrinter(O, TM, T, V), DbgInfo(O, T) {
+  PTLI = static_cast<const PIC16TargetLowering*>(TM.getTargetLowering());
+  PTAI = static_cast<const PIC16TargetAsmInfo*>(T);
+  PTOF = static_cast<const PIC16TargetObjectFile*>(&PTLI->getObjFileLowering());
+}
+
 bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
   printInstruction(MI);
   return true;
@@ -59,10 +68,12 @@
   EmitAutos(CurrentFnName);
 
   // Now emit the instructions of function in its code section.
-  const char *codeSection = PAN::getCodeSectionName(CurrentFnName).c_str();
+  std::string T = PAN::getCodeSectionName(CurrentFnName);
+  const char *codeSection = T.c_str();
  
   const Section *fCodeSection = 
-    TAI->getOrCreateSection(codeSection, false, SectionKind::Text);
+    getObjFileLowering().getOrCreateSection(codeSection, false, 
+                                            SectionKind::Text);
   // Start the Code Section.
   O <<  "\n";
   SwitchToSection(fCodeSection);
@@ -211,9 +222,8 @@
 
   // Set the section names for all globals.
   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
-       I != E; ++I) {
-    I->setSection(TAI->SectionForGlobal(I)->getName());
-  }
+       I != E; ++I)
+    I->setSection(getObjFileLowering().SectionForGlobal(I, TM)->getName());
 
   DbgInfo.BeginModule(M);
   EmitFunctionDecls(M);
@@ -256,7 +266,7 @@
 
 // Emit variables imported from other Modules.
 void PIC16AsmPrinter::EmitUndefinedVars(Module &M) {
-  std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDecls->Items;
+  std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDecls->Items;
   if (!Items.size()) return;
 
   O << "\n" << TAI->getCommentString() << "Imported Variables - BEGIN" << "\n";
@@ -268,7 +278,7 @@
 
 // Emit variables defined in this module and are available to other modules.
 void PIC16AsmPrinter::EmitDefinedVars(Module &M) {
-  std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDefs->Items;
+  std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDefs->Items;
   if (!Items.size()) return;
 
   O << "\n" << TAI->getCommentString() << "Exported Variables - BEGIN" << "\n";
@@ -281,12 +291,12 @@
 // Emit initialized data placed in ROM.
 void PIC16AsmPrinter::EmitRomData(Module &M) {
   // Print ROM Data section.
-  const std::vector<PIC16Section*> &ROSections = PTAI->ROSections;
+  const std::vector<PIC16Section*> &ROSections = PTOF->ROSections;
   for (unsigned i = 0; i < ROSections.size(); i++) {
     const std::vector<const GlobalVariable*> &Items = ROSections[i]->Items;
     if (!Items.size()) continue;
     O << "\n";
-    SwitchToSection(PTAI->ROSections[i]->S_);
+    SwitchToSection(PTOF->ROSections[i]->S_);
     for (unsigned j = 0; j < Items.size(); j++) {
       O << Mang->getMangledName(Items[j]);
       Constant *C = Items[j]->getInitializer();
@@ -310,10 +320,12 @@
   const TargetData *TD = TM.getTargetData();
   // Emit the data section name.
   O << "\n"; 
-  const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str();
+  std::string T = PAN::getFrameSectionName(CurrentFnName);
+  const char *SectionName = T.c_str();
 
   const Section *fPDataSection =
-    TAI->getOrCreateSection(SectionName, false, SectionKind::DataRel);
+    getObjFileLowering().getOrCreateSection(SectionName, false,
+                                            SectionKind::DataRel);
   SwitchToSection(fPDataSection);
   
   // Emit function frame label
@@ -352,7 +364,7 @@
 void PIC16AsmPrinter::EmitIData(Module &M) {
 
   // Print all IDATA sections.
-  const std::vector<PIC16Section*> &IDATASections = PTAI->IDATASections;
+  const std::vector<PIC16Section*> &IDATASections = PTOF->IDATASections;
   for (unsigned i = 0; i < IDATASections.size(); i++) {
     O << "\n";
     if (IDATASections[i]->S_->getName().find("llvm.") != std::string::npos)
@@ -373,7 +385,7 @@
   const TargetData *TD = TM.getTargetData();
 
   // Print all BSS sections.
-  const std::vector<PIC16Section*> &BSSSections = PTAI->BSSSections;
+  const std::vector<PIC16Section*> &BSSSections = PTOF->BSSSections;
   for (unsigned i = 0; i < BSSSections.size(); i++) {
     O << "\n";
     SwitchToSection(BSSSections[i]->S_);
@@ -395,7 +407,7 @@
 
   // Now print Autos section for this function.
   std::string SectionName = PAN::getAutosSectionName(FunctName);
-  const std::vector<PIC16Section*> &AutosSections = PTAI->AutosSections;
+  const std::vector<PIC16Section*> &AutosSections = PTOF->AutosSections;
   for (unsigned i = 0; i < AutosSections.size(); i++) {
     O << "\n";
     if (AutosSections[i]->S_->getName() == SectionName) { 
@@ -422,7 +434,7 @@
   const TargetData *TD = TM.getTargetData();
 
   // Now print Autos section for this function.
-  std::vector <PIC16Section *>AutosSections = PTAI->AutosSections;
+  std::vector <PIC16Section *>AutosSections = PTOF->AutosSections;
   for (unsigned i = 0; i < AutosSections.size(); i++) {
     
     // if the section is already printed then don't print again
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.h b/lib/Target/PIC16/PIC16AsmPrinter.h
index 0e05940..c365b5a 100644
--- a/lib/Target/PIC16/PIC16AsmPrinter.h
+++ b/lib/Target/PIC16/PIC16AsmPrinter.h
@@ -18,6 +18,7 @@
 #include "PIC16.h"
 #include "PIC16TargetMachine.h"
 #include "PIC16DebugInfo.h"
+#include "PIC16TargetObjectFile.h"
 #include "llvm/Analysis/DebugInfo.h"
 #include "PIC16TargetAsmInfo.h"
 #include "llvm/CodeGen/AsmPrinter.h"
@@ -28,13 +29,10 @@
 #include <string>
 
 namespace llvm {
-  struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
+  class VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
+  public:
     explicit PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
-                             const TargetAsmInfo *T, bool V)
-      : AsmPrinter(O, TM, T, V), DbgInfo(O, T) {
-      PTLI = static_cast<const PIC16TargetLowering *> (TM.getTargetLowering());
-      PTAI = static_cast<const PIC16TargetAsmInfo *> (T);
-    }
+                             const TargetAsmInfo *T, bool V);
   private:
     virtual const char *getPassName() const {
       return "PIC16 Assembly Printer";
@@ -66,6 +64,7 @@
     }
     
   private:
+    PIC16TargetObjectFile *PTOF;
     PIC16TargetLowering *PTLI;
     PIC16DbgInfo DbgInfo;
     const PIC16TargetAsmInfo *PTAI;
diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp
index 13d9654..f194dc8 100644
--- a/lib/Target/PIC16/PIC16ISelLowering.cpp
+++ b/lib/Target/PIC16/PIC16ISelLowering.cpp
@@ -12,8 +12,8 @@
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "pic16-lower"
-
 #include "PIC16ISelLowering.h"
+#include "PIC16TargetObjectFile.h"
 #include "PIC16TargetMachine.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/GlobalValue.h"
@@ -123,7 +123,7 @@
 
 // PIC16TargetLowering Constructor.
 PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
-  : TargetLowering(TM), TmpSize(0) {
+  : TargetLowering(TM, new PIC16TargetObjectFile(TM)), TmpSize(0) {
  
   Subtarget = &TM.getSubtarget<PIC16Subtarget>();
 
diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
index 5a4387a..9912543 100644
--- a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
+++ b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
@@ -31,36 +31,26 @@
   Data16bitsDirective = " dw ";
   Data32bitsDirective = " dl ";
   Data64bitsDirective = NULL;
-  RomData8bitsDirective = " dw ";
-  RomData16bitsDirective = " rom_di ";
-  RomData32bitsDirective = " rom_dl ";
   ZeroDirective = NULL;
   AsciiDirective = " dt ";
   AscizDirective = NULL;
-  BSSSection_  = getOrCreateSection("udata.# UDATA", false, SectionKind::BSS);
-  ReadOnlySection = getOrCreateSection("romdata.# ROMDATA", false,
-                                       SectionKind::ReadOnly);
-  DataSection = getOrCreateSection("idata.# IDATA", false,SectionKind::DataRel);
   SwitchToSectionDirective = "";
-  // Need because otherwise a .text symbol is emitted by DwarfWriter
-  // in BeginModule, and gpasm cribbs for that .text symbol.
-  TextSection = getOrCreateSection("", true, SectionKind::Text);
-  PIC16Section *ROSection = new PIC16Section(getReadOnlySection());
-  ROSections.push_back(ROSection);
     
-  // FIXME: I don't know what the classification of these sections really is.
-  ExternalVarDecls = new PIC16Section(getOrCreateSection("ExternalVarDecls",
-                                                         false,
-                                                         SectionKind::Metadata));
-  ExternalVarDefs = new PIC16Section(getOrCreateSection("ExternalVarDefs",
-                                                        false,
-                                                        SectionKind::Metadata));
+  RomData8bitsDirective = " dw ";
+  RomData16bitsDirective = " rom_di ";
+  RomData32bitsDirective = " rom_dl ";
+    
+    
   // Set it to false because we weed to generate c file name and not bc file
   // name.
   HasSingleParameterDotFile = false;
 }
 
-const char *PIC16TargetAsmInfo::getRomDirective(unsigned Size) const {
+const char *PIC16TargetAsmInfo::
+getDataASDirective(unsigned Size, unsigned AS) const {
+  if (AS != PIC16ISD::ROM_SPACE)
+    return 0;
+  
   switch (Size) {
   case  8: return RomData8bitsDirective;
   case 16: return RomData16bitsDirective;
@@ -69,369 +59,3 @@
   }
 }
 
-
-const char *PIC16TargetAsmInfo::
-getDataASDirective(unsigned Size, unsigned AS) const {
-  if (AS == PIC16ISD::ROM_SPACE)
-    return getRomDirective(Size);
-  return NULL;
-}
-
-const Section *
-PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
-  assert(GV->hasInitializer() && "This global doesn't need space");
-  Constant *C = GV->getInitializer();
-  assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
-
-  // Find how much space this global needs.
-  const TargetData *TD = TM.getTargetData();
-  const Type *Ty = C->getType(); 
-  unsigned ValSize = TD->getTypeAllocSize(Ty);
- 
-  // Go through all BSS Sections and assign this variable
-  // to the first available section having enough space.
-  PIC16Section *FoundBSS = NULL;
-  for (unsigned i = 0; i < BSSSections.size(); i++) {
-    if (DataBankSize - BSSSections[i]->Size >= ValSize) {
-      FoundBSS = BSSSections[i];
-      break;
-    }
-  }
-
-  // No BSS section spacious enough was found. Crate a new one.
-  if (!FoundBSS) {
-    std::string name = PAN::getUdataSectionName(BSSSections.size());
-    const Section *NewSection = getOrCreateSection(name.c_str(), false,
-                                                   // FIXME.
-                                                   SectionKind::Metadata);
-
-    FoundBSS = new PIC16Section(NewSection);
-
-    // Add this newly created BSS section to the list of BSSSections.
-    BSSSections.push_back(FoundBSS);
-  }
-  
-  // Insert the GV into this BSS.
-  FoundBSS->Items.push_back(GV);
-  FoundBSS->Size += ValSize;
-  return FoundBSS->S_;
-} 
-
-const Section *
-PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
-  assert(GV->hasInitializer() && "This global doesn't need space");
-  Constant *C = GV->getInitializer();
-  assert(!C->isNullValue() && "initialized globals has zero initializer");
-  assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
-         "can split initialized RAM data only");
-
-  // Find how much space this global needs.
-  const TargetData *TD = TM.getTargetData();
-  const Type *Ty = C->getType(); 
-  unsigned ValSize = TD->getTypeAllocSize(Ty);
- 
-  // Go through all IDATA Sections and assign this variable
-  // to the first available section having enough space.
-  PIC16Section *FoundIDATA = NULL;
-  for (unsigned i = 0; i < IDATASections.size(); i++) {
-    if (DataBankSize - IDATASections[i]->Size >= ValSize) {
-      FoundIDATA = IDATASections[i]; 
-      break;
-    }
-  }
-
-  // No IDATA section spacious enough was found. Crate a new one.
-  if (!FoundIDATA) {
-    std::string name = PAN::getIdataSectionName(IDATASections.size());
-    const Section *NewSection = getOrCreateSection(name.c_str(),
-                                                   false,
-                                                   // FIXME.
-                                                   SectionKind::Metadata);
-
-    FoundIDATA = new PIC16Section(NewSection);
-
-    // Add this newly created IDATA section to the list of IDATASections.
-    IDATASections.push_back(FoundIDATA);
-  }
-  
-  // Insert the GV into this IDATA.
-  FoundIDATA->Items.push_back(GV);
-  FoundIDATA->Size += ValSize;
-  return FoundIDATA->S_;
-} 
-
-// Get the section for an automatic variable of a function.
-// For PIC16 they are globals only with mangled names.
-const Section *
-PIC16TargetAsmInfo::getSectionForAuto(const GlobalVariable *GV) const {
-
-  const std::string name = PAN::getSectionNameForSym(GV->getName());
-
-  // Go through all Auto Sections and assign this variable
-  // to the appropriate section.
-  PIC16Section *FoundAutoSec = NULL;
-  for (unsigned i = 0; i < AutosSections.size(); i++) {
-    if (AutosSections[i]->S_->getName() == name) {
-      FoundAutoSec = AutosSections[i];
-      break;
-    }
-  }
-
-  // No Auto section was found. Crate a new one.
-  if (!FoundAutoSec) {
-    const Section *NewSection = getOrCreateSection(name.c_str(),
-                                                   // FIXME.
-                                                   false,
-                                                   SectionKind::Metadata);
-
-    FoundAutoSec = new PIC16Section(NewSection);
-
-    // Add this newly created autos section to the list of AutosSections.
-    AutosSections.push_back(FoundAutoSec);
-  }
-
-  // Insert the auto into this section.
-  FoundAutoSec->Items.push_back(GV);
-
-  return FoundAutoSec->S_;
-}
-
-
-// Override default implementation to put the true globals into
-// multiple data sections if required.
-const Section*
-PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1,
-                                           SectionKind Kind) const {
-  // We select the section based on the initializer here, so it really
-  // has to be a GlobalVariable.
-  const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1); 
-  if (!GV)
-    return TargetAsmInfo::SelectSectionForGlobal(GV1, Kind);
-
-  // Record External Var Decls.
-  if (GV->isDeclaration()) {
-    ExternalVarDecls->Items.push_back(GV);
-    return ExternalVarDecls->S_;
-  }
-    
-  assert(GV->hasInitializer() && "A def without initializer?");
-
-  // First, if this is an automatic variable for a function, get the section
-  // name for it and return.
-  std::string name = GV->getName();
-  if (PAN::isLocalName(name))
-    return getSectionForAuto(GV);
-
-  // Record Exteranl Var Defs.
-  if (GV->hasExternalLinkage() || GV->hasCommonLinkage())
-    ExternalVarDefs->Items.push_back(GV);
-
-  // See if this is an uninitialized global.
-  const Constant *C = GV->getInitializer();
-  if (C->isNullValue()) 
-    return getBSSSectionForGlobal(GV); 
-
-  // If this is initialized data in RAM. Put it in the correct IDATA section.
-  if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) 
-    return getIDATASectionForGlobal(GV);
-
-  // This is initialized data in rom, put it in the readonly section.
-  if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
-    return getROSectionForGlobal(GV);
-
-  // Else let the default implementation take care of it.
-  return TargetAsmInfo::SelectSectionForGlobal(GV, Kind);
-}
-
-PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {
-  for (unsigned i = 0; i < BSSSections.size(); i++)
-    delete BSSSections[i]; 
-  for (unsigned i = 0; i < IDATASections.size(); i++)
-    delete IDATASections[i]; 
-  for (unsigned i = 0; i < AutosSections.size(); i++)
-    delete AutosSections[i]; 
-  for (unsigned i = 0; i < ROSections.size(); i++)
-    delete ROSections[i];
-  delete ExternalVarDecls;
-  delete ExternalVarDefs;
-}
-
-
-/// getSpecialCasedSectionGlobals - Allow the target to completely override
-/// section assignment of a global.
-const Section *
-PIC16TargetAsmInfo::getSpecialCasedSectionGlobals(const GlobalValue *GV,
-                                                  SectionKind Kind) const {
-  // If GV has a sectin name or section address create that section now.
-  if (GV->hasSection()) {
-    if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
-      std::string SectName = GVar->getSection();
-      // If address for a variable is specified, get the address and create
-      // section.
-      std::string AddrStr = "Address=";
-      if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
-        std::string SectAddr = SectName.substr(AddrStr.length());
-        return CreateSectionForGlobal(GVar, SectAddr);
-      }
-       
-      // Create the section specified with section attribute. 
-      return CreateSectionForGlobal(GVar);
-    }
-  }
-
-  return 0;
-}
-
-// Create a new section for global variable. If Addr is given then create
-// section at that address else create by name.
-const Section *
-PIC16TargetAsmInfo::CreateSectionForGlobal(const GlobalVariable *GV,
-                                           const std::string &Addr) const {
-  // See if this is an uninitialized global.
-  const Constant *C = GV->getInitializer();
-  if (C->isNullValue())
-    return CreateBSSSectionForGlobal(GV, Addr);
-
-  // If this is initialized data in RAM. Put it in the correct IDATA section.
-  if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
-    return CreateIDATASectionForGlobal(GV, Addr);
-
-  // This is initialized data in rom, put it in the readonly section.
-  if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
-    return CreateROSectionForGlobal(GV, Addr);
-
-  // Else let the default implementation take care of it.
-  return TargetAsmInfo::SectionForGlobal(GV);
-}
-
-// Create uninitialized section for a variable.
-const Section *
-PIC16TargetAsmInfo::CreateBSSSectionForGlobal(const GlobalVariable *GV,
-                                              std::string Addr) const {
-  assert(GV->hasInitializer() && "This global doesn't need space");
-  assert(GV->getInitializer()->isNullValue() &&
-         "Unitialized global has non-zero initializer");
-  std::string Name;
-  // If address is given then create a section at that address else create a
-  // section by section name specified in GV.
-  PIC16Section *FoundBSS = NULL;
-  if (Addr.empty()) { 
-    Name = GV->getSection() + " UDATA";
-    for (unsigned i = 0; i < BSSSections.size(); i++) {
-      if (BSSSections[i]->S_->getName() == Name) {
-        FoundBSS = BSSSections[i];
-        break;
-      }
-    }
-  } else {
-    std::string Prefix = GV->getNameStr() + "." + Addr + ".";
-    Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
-  }
-  
-  PIC16Section *NewBSS = FoundBSS;
-  if (NewBSS == NULL) {
-    const Section *NewSection = getOrCreateSection(Name.c_str(),
-                                                   false, SectionKind::BSS);
-    NewBSS = new PIC16Section(NewSection);
-    BSSSections.push_back(NewBSS);
-  }
-
-  // Insert the GV into this BSS.
-  NewBSS->Items.push_back(GV);
-
-  // We do not want to put any  GV without explicit section into this section
-  // so set its size to DatabankSize.
-  NewBSS->Size = DataBankSize;
-  return NewBSS->S_;
-}
-
-// Get rom section for a variable. Currently there can be only one rom section
-// unless a variable explicitly requests a section.
-const Section *
-PIC16TargetAsmInfo::getROSectionForGlobal(const GlobalVariable *GV) const {
-  ROSections[0]->Items.push_back(GV);
-  return ROSections[0]->S_;
-}
-
-// Create initialized data section for a variable.
-const Section *
-PIC16TargetAsmInfo::CreateIDATASectionForGlobal(const GlobalVariable *GV,
-                                                std::string Addr) const {
-  assert(GV->hasInitializer() && "This global doesn't need space");
-  assert(!GV->getInitializer()->isNullValue() &&
-         "initialized global has zero initializer");
-  assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
-         "can be used for initialized RAM data only");
-
-  std::string Name;
-  // If address is given then create a section at that address else create a
-  // section by section name specified in GV.
-  PIC16Section *FoundIDATASec = NULL;
-  if (Addr.empty()) {
-    Name = GV->getSection() + " IDATA";
-    for (unsigned i = 0; i < IDATASections.size(); i++) {
-      if (IDATASections[i]->S_->getName() == Name) {
-        FoundIDATASec = IDATASections[i];
-        break;
-      }
-    }
-  } else {
-    std::string Prefix = GV->getNameStr() + "." + Addr + ".";
-    Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
-  }
-
-  PIC16Section *NewIDATASec = FoundIDATASec;
-  if (NewIDATASec == NULL) {
-    const Section *NewSection = getOrCreateSection(Name.c_str(),
-                                                   false,
-                                                   // FIXME:
-                                                   SectionKind::Metadata);
-    NewIDATASec = new PIC16Section(NewSection);
-    IDATASections.push_back(NewIDATASec);
-  }
-  // Insert the GV into this IDATA Section.
-  NewIDATASec->Items.push_back(GV);
-  // We do not want to put any  GV without explicit section into this section 
-  // so set its size to DatabankSize.
-  NewIDATASec->Size = DataBankSize;
-  return NewIDATASec->S_;
-}
-
-// Create a section in rom for a variable.
-const Section *
-PIC16TargetAsmInfo::CreateROSectionForGlobal(const GlobalVariable *GV,
-                                             std::string Addr) const {
-  assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
-         "can be used for ROM data only");
-
-  std::string Name;
-  // If address is given then create a section at that address else create a
-  // section by section name specified in GV.
-  PIC16Section *FoundROSec = NULL;
-  if (Addr.empty()) {
-    Name = GV->getSection() + " ROMDATA";
-    for (unsigned i = 1; i < ROSections.size(); i++) {
-      if (ROSections[i]->S_->getName() == Name) {
-        FoundROSec = ROSections[i];
-        break;
-      }
-    }
-  } else {
-    std::string Prefix = GV->getNameStr() + "." + Addr + ".";
-    Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
-  }
-
-  PIC16Section *NewRomSec = FoundROSec;
-  if (NewRomSec == NULL) {
-    const Section *NewSection = getOrCreateSection(Name.c_str(),
-                                                   false,
-                                                   SectionKind::ReadOnly);
-    NewRomSec = new PIC16Section(NewSection);
-    ROSections.push_back(NewRomSec);
-  }
-
-  // Insert the GV into this ROM Section.
-  NewRomSec->Items.push_back(GV);
-  return NewRomSec->S_;
-}
-
diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.h b/lib/Target/PIC16/PIC16TargetAsmInfo.h
index 1ced3bf..8fb9e0c 100644
--- a/lib/Target/PIC16/PIC16TargetAsmInfo.h
+++ b/lib/Target/PIC16/PIC16TargetAsmInfo.h
@@ -14,91 +14,22 @@
 #ifndef PIC16TARGETASMINFO_H
 #define PIC16TARGETASMINFO_H
 
-#include "PIC16.h"
 #include "llvm/Target/TargetAsmInfo.h"
-#include <vector>
-#include "llvm/Module.h"
 
 namespace llvm {
 
-  enum { DataBankSize = 80 };
-
   // Forward declaration.
   class PIC16TargetMachine;
-  class GlobalVariable;
-
-  /// PIC16 Splits the global data into mulitple udata and idata sections.
-  /// Each udata and idata section needs to contain a list of globals that
-  /// they contain, in order to avoid scanning over all the global values 
-  /// again and printing only those that match the current section. 
-  /// Keeping values inside the sections make printing a section much easier.
-  struct PIC16Section {
-    const Section *S_; // Connection to actual Section.
-    unsigned Size;  // Total size of the objects contained.
-    bool SectionPrinted;
-    std::vector<const GlobalVariable*> Items;
-   
-    PIC16Section(const Section *s) {
-      S_ = s;
-      Size = 0;
-      SectionPrinted = false;
-    }
-    bool isPrinted() const { return SectionPrinted; }
-    void setPrintedStatus(bool status) { SectionPrinted = status; } 
-  };
       
-  struct PIC16TargetAsmInfo : public TargetAsmInfo {
-    std::string getSectionNameForSym(const std::string &Sym) const;
-    PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
-    mutable std::vector<PIC16Section *> BSSSections;
-    mutable std::vector<PIC16Section *> IDATASections;
-    mutable std::vector<PIC16Section *> AutosSections;
-    mutable std::vector<PIC16Section *> ROSections;
-    mutable PIC16Section *ExternalVarDecls;
-    mutable PIC16Section *ExternalVarDefs;
-    virtual ~PIC16TargetAsmInfo();
-
-  private:
+  class PIC16TargetAsmInfo : public TargetAsmInfo {
     const char *RomData8bitsDirective;
     const char *RomData16bitsDirective;
     const char *RomData32bitsDirective;
-    const char *getRomDirective(unsigned size) const;
+  public:    
+    PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
+
+    
     virtual const char *getDataASDirective(unsigned size, unsigned AS) const;
-    const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const;
-    const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const;
-    const Section *getSectionForAuto(const GlobalVariable *GV) const;
-    const Section *CreateBSSSectionForGlobal(const GlobalVariable *GV,
-                                             std::string Addr = "") const;
-    const Section *CreateIDATASectionForGlobal(const GlobalVariable *GV,
-                                               std::string Addr = "") const;
-    const Section *getROSectionForGlobal(const GlobalVariable *GV) const;
-    const Section *CreateROSectionForGlobal(const GlobalVariable *GV,
-                                            std::string Addr = "") const;
-    virtual const Section *SelectSectionForGlobal(const GlobalValue *GV,
-                                                  SectionKind Kind) const;
-    const Section *CreateSectionForGlobal(const GlobalVariable *GV,
-                                          const std::string &Addr = "") const;
-  public:
-    void SetSectionForGVs(Module &M);
-    const std::vector<PIC16Section*> &getBSSSections() const {
-      return BSSSections;
-    }
-    const std::vector<PIC16Section*> &getIDATASections() const {
-      return IDATASections;
-    }
-    const std::vector<PIC16Section*> &getAutosSections() const {
-      return AutosSections;
-    }
-    const std::vector<PIC16Section*> &getROSections() const {
-      return ROSections;
-    }
-    
-    /// getSpecialCasedSectionGlobals - Allow the target to completely override
-    /// section assignment of a global.
-    virtual const Section *
-    getSpecialCasedSectionGlobals(const GlobalValue *GV,
-                                  SectionKind Kind) const;
-    
   };
 
 } // namespace llvm
diff --git a/lib/Target/PIC16/PIC16TargetObjectFile.cpp b/lib/Target/PIC16/PIC16TargetObjectFile.cpp
new file mode 100644
index 0000000..efc03ac
--- /dev/null
+++ b/lib/Target/PIC16/PIC16TargetObjectFile.cpp
@@ -0,0 +1,401 @@
+//===-- PIC16TargetObjectFile.cpp - PIC16 object files --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16TargetObjectFile.h"
+#include "PIC16ISelLowering.h"
+#include "PIC16TargetMachine.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+using namespace llvm;
+
+
+PIC16TargetObjectFile::PIC16TargetObjectFile(const PIC16TargetMachine &tm) 
+: TM (tm) {
+  BSSSection_  = getOrCreateSection("udata.# UDATA", false, SectionKind::BSS);
+  ReadOnlySection = getOrCreateSection("romdata.# ROMDATA", false,
+                                       SectionKind::ReadOnly);
+  DataSection = getOrCreateSection("idata.# IDATA", false,SectionKind::DataRel);
+  
+  // Need because otherwise a .text symbol is emitted by DwarfWriter
+  // in BeginModule, and gpasm cribbs for that .text symbol.
+  TextSection = getOrCreateSection("", true, SectionKind::Text);
+
+  
+  PIC16Section *ROSection = new PIC16Section(ReadOnlySection);
+  ROSections.push_back(ROSection);
+  
+  // FIXME: I don't know what the classification of these sections really is.
+  ExternalVarDecls = new PIC16Section(getOrCreateSection("ExternalVarDecls",
+                                                         false,
+                                                        SectionKind::Metadata));
+  ExternalVarDefs = new PIC16Section(getOrCreateSection("ExternalVarDefs",
+                                                        false,
+                                                        SectionKind::Metadata));
+}
+
+
+const Section *
+PIC16TargetObjectFile::getBSSSectionForGlobal(const GlobalVariable *GV) const {
+  assert(GV->hasInitializer() && "This global doesn't need space");
+  Constant *C = GV->getInitializer();
+  assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
+
+  // Find how much space this global needs.
+  const TargetData *TD = TM.getTargetData();
+  const Type *Ty = C->getType(); 
+  unsigned ValSize = TD->getTypeAllocSize(Ty);
+ 
+  // Go through all BSS Sections and assign this variable
+  // to the first available section having enough space.
+  PIC16Section *FoundBSS = NULL;
+  for (unsigned i = 0; i < BSSSections.size(); i++) {
+    if (DataBankSize - BSSSections[i]->Size >= ValSize) {
+      FoundBSS = BSSSections[i];
+      break;
+    }
+  }
+
+  // No BSS section spacious enough was found. Crate a new one.
+  if (!FoundBSS) {
+    std::string name = PAN::getUdataSectionName(BSSSections.size());
+    const Section *NewSection = getOrCreateSection(name.c_str(), false,
+                                                   // FIXME.
+                                                   SectionKind::Metadata);
+
+    FoundBSS = new PIC16Section(NewSection);
+
+    // Add this newly created BSS section to the list of BSSSections.
+    BSSSections.push_back(FoundBSS);
+  }
+  
+  // Insert the GV into this BSS.
+  FoundBSS->Items.push_back(GV);
+  FoundBSS->Size += ValSize;
+  return FoundBSS->S_;
+} 
+
+const Section *
+PIC16TargetObjectFile::getIDATASectionForGlobal(const GlobalVariable *GV) const{
+  assert(GV->hasInitializer() && "This global doesn't need space");
+  Constant *C = GV->getInitializer();
+  assert(!C->isNullValue() && "initialized globals has zero initializer");
+  assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
+         "can split initialized RAM data only");
+
+  // Find how much space this global needs.
+  const TargetData *TD = TM.getTargetData();
+  const Type *Ty = C->getType(); 
+  unsigned ValSize = TD->getTypeAllocSize(Ty);
+ 
+  // Go through all IDATA Sections and assign this variable
+  // to the first available section having enough space.
+  PIC16Section *FoundIDATA = NULL;
+  for (unsigned i = 0; i < IDATASections.size(); i++) {
+    if (DataBankSize - IDATASections[i]->Size >= ValSize) {
+      FoundIDATA = IDATASections[i]; 
+      break;
+    }
+  }
+
+  // No IDATA section spacious enough was found. Crate a new one.
+  if (!FoundIDATA) {
+    std::string name = PAN::getIdataSectionName(IDATASections.size());
+    const Section *NewSection = getOrCreateSection(name.c_str(),
+                                                   false,
+                                                   // FIXME.
+                                                   SectionKind::Metadata);
+
+    FoundIDATA = new PIC16Section(NewSection);
+
+    // Add this newly created IDATA section to the list of IDATASections.
+    IDATASections.push_back(FoundIDATA);
+  }
+  
+  // Insert the GV into this IDATA.
+  FoundIDATA->Items.push_back(GV);
+  FoundIDATA->Size += ValSize;
+  return FoundIDATA->S_;
+} 
+
+// Get the section for an automatic variable of a function.
+// For PIC16 they are globals only with mangled names.
+const Section *
+PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable *GV) const {
+
+  const std::string name = PAN::getSectionNameForSym(GV->getName());
+
+  // Go through all Auto Sections and assign this variable
+  // to the appropriate section.
+  PIC16Section *FoundAutoSec = NULL;
+  for (unsigned i = 0; i < AutosSections.size(); i++) {
+    if (AutosSections[i]->S_->getName() == name) {
+      FoundAutoSec = AutosSections[i];
+      break;
+    }
+  }
+
+  // No Auto section was found. Crate a new one.
+  if (!FoundAutoSec) {
+    const Section *NewSection = getOrCreateSection(name.c_str(),
+                                                   // FIXME.
+                                                   false,
+                                                   SectionKind::Metadata);
+
+    FoundAutoSec = new PIC16Section(NewSection);
+
+    // Add this newly created autos section to the list of AutosSections.
+    AutosSections.push_back(FoundAutoSec);
+  }
+
+  // Insert the auto into this section.
+  FoundAutoSec->Items.push_back(GV);
+
+  return FoundAutoSec->S_;
+}
+
+
+// Override default implementation to put the true globals into
+// multiple data sections if required.
+const Section*
+PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1,
+                                              SectionKind Kind,
+                                              const TargetMachine &TM) const {
+  // We select the section based on the initializer here, so it really
+  // has to be a GlobalVariable.
+  const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1); 
+  if (!GV)
+    return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Kind, TM);
+
+  // Record External Var Decls.
+  if (GV->isDeclaration()) {
+    ExternalVarDecls->Items.push_back(GV);
+    return ExternalVarDecls->S_;
+  }
+    
+  assert(GV->hasInitializer() && "A def without initializer?");
+
+  // First, if this is an automatic variable for a function, get the section
+  // name for it and return.
+  std::string name = GV->getName();
+  if (PAN::isLocalName(name))
+    return getSectionForAuto(GV);
+
+  // Record Exteranl Var Defs.
+  if (GV->hasExternalLinkage() || GV->hasCommonLinkage())
+    ExternalVarDefs->Items.push_back(GV);
+
+  // See if this is an uninitialized global.
+  const Constant *C = GV->getInitializer();
+  if (C->isNullValue()) 
+    return getBSSSectionForGlobal(GV); 
+
+  // If this is initialized data in RAM. Put it in the correct IDATA section.
+  if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) 
+    return getIDATASectionForGlobal(GV);
+
+  // This is initialized data in rom, put it in the readonly section.
+  if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
+    return getROSectionForGlobal(GV);
+
+  // Else let the default implementation take care of it.
+  return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, TM);
+}
+
+PIC16TargetObjectFile::~PIC16TargetObjectFile() {
+  for (unsigned i = 0; i < BSSSections.size(); i++)
+    delete BSSSections[i]; 
+  for (unsigned i = 0; i < IDATASections.size(); i++)
+    delete IDATASections[i]; 
+  for (unsigned i = 0; i < AutosSections.size(); i++)
+    delete AutosSections[i]; 
+  for (unsigned i = 0; i < ROSections.size(); i++)
+    delete ROSections[i];
+  delete ExternalVarDecls;
+  delete ExternalVarDefs;
+}
+
+
+/// getSpecialCasedSectionGlobals - Allow the target to completely override
+/// section assignment of a global.
+const Section *
+PIC16TargetObjectFile::getSpecialCasedSectionGlobals(const GlobalValue *GV,
+                                                     SectionKind Kind) const {
+  // If GV has a sectin name or section address create that section now.
+  if (GV->hasSection()) {
+    if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
+      std::string SectName = GVar->getSection();
+      // If address for a variable is specified, get the address and create
+      // section.
+      std::string AddrStr = "Address=";
+      if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
+        std::string SectAddr = SectName.substr(AddrStr.length());
+        return CreateSectionForGlobal(GVar, SectAddr);
+      }
+       
+      // Create the section specified with section attribute. 
+      return CreateSectionForGlobal(GVar);
+    }
+  }
+
+  return 0;
+}
+
+// Create a new section for global variable. If Addr is given then create
+// section at that address else create by name.
+const Section *
+PIC16TargetObjectFile::CreateSectionForGlobal(const GlobalVariable *GV,
+                                              const std::string &Addr) const {
+  // See if this is an uninitialized global.
+  const Constant *C = GV->getInitializer();
+  if (C->isNullValue())
+    return CreateBSSSectionForGlobal(GV, Addr);
+
+  // If this is initialized data in RAM. Put it in the correct IDATA section.
+  if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
+    return CreateIDATASectionForGlobal(GV, Addr);
+
+  // This is initialized data in rom, put it in the readonly section.
+  if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
+    return CreateROSectionForGlobal(GV, Addr);
+
+  // Else let the default implementation take care of it.
+  return TargetLoweringObjectFile::SectionForGlobal(GV, TM);
+}
+
+// Create uninitialized section for a variable.
+const Section *
+PIC16TargetObjectFile::CreateBSSSectionForGlobal(const GlobalVariable *GV,
+                                                 std::string Addr) const {
+  assert(GV->hasInitializer() && "This global doesn't need space");
+  assert(GV->getInitializer()->isNullValue() &&
+         "Unitialized global has non-zero initializer");
+  std::string Name;
+  // If address is given then create a section at that address else create a
+  // section by section name specified in GV.
+  PIC16Section *FoundBSS = NULL;
+  if (Addr.empty()) { 
+    Name = GV->getSection() + " UDATA";
+    for (unsigned i = 0; i < BSSSections.size(); i++) {
+      if (BSSSections[i]->S_->getName() == Name) {
+        FoundBSS = BSSSections[i];
+        break;
+      }
+    }
+  } else {
+    std::string Prefix = GV->getNameStr() + "." + Addr + ".";
+    Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
+  }
+  
+  PIC16Section *NewBSS = FoundBSS;
+  if (NewBSS == NULL) {
+    const Section *NewSection = getOrCreateSection(Name.c_str(),
+                                                   false, SectionKind::BSS);
+    NewBSS = new PIC16Section(NewSection);
+    BSSSections.push_back(NewBSS);
+  }
+
+  // Insert the GV into this BSS.
+  NewBSS->Items.push_back(GV);
+
+  // We do not want to put any  GV without explicit section into this section
+  // so set its size to DatabankSize.
+  NewBSS->Size = DataBankSize;
+  return NewBSS->S_;
+}
+
+// Get rom section for a variable. Currently there can be only one rom section
+// unless a variable explicitly requests a section.
+const Section *
+PIC16TargetObjectFile::getROSectionForGlobal(const GlobalVariable *GV) const {
+  ROSections[0]->Items.push_back(GV);
+  return ROSections[0]->S_;
+}
+
+// Create initialized data section for a variable.
+const Section *
+PIC16TargetObjectFile::CreateIDATASectionForGlobal(const GlobalVariable *GV,
+                                                   std::string Addr) const {
+  assert(GV->hasInitializer() && "This global doesn't need space");
+  assert(!GV->getInitializer()->isNullValue() &&
+         "initialized global has zero initializer");
+  assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
+         "can be used for initialized RAM data only");
+
+  std::string Name;
+  // If address is given then create a section at that address else create a
+  // section by section name specified in GV.
+  PIC16Section *FoundIDATASec = NULL;
+  if (Addr.empty()) {
+    Name = GV->getSection() + " IDATA";
+    for (unsigned i = 0; i < IDATASections.size(); i++) {
+      if (IDATASections[i]->S_->getName() == Name) {
+        FoundIDATASec = IDATASections[i];
+        break;
+      }
+    }
+  } else {
+    std::string Prefix = GV->getNameStr() + "." + Addr + ".";
+    Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
+  }
+
+  PIC16Section *NewIDATASec = FoundIDATASec;
+  if (NewIDATASec == NULL) {
+    const Section *NewSection = getOrCreateSection(Name.c_str(),
+                                                   false,
+                                                   // FIXME:
+                                                   SectionKind::Metadata);
+    NewIDATASec = new PIC16Section(NewSection);
+    IDATASections.push_back(NewIDATASec);
+  }
+  // Insert the GV into this IDATA Section.
+  NewIDATASec->Items.push_back(GV);
+  // We do not want to put any  GV without explicit section into this section 
+  // so set its size to DatabankSize.
+  NewIDATASec->Size = DataBankSize;
+  return NewIDATASec->S_;
+}
+
+// Create a section in rom for a variable.
+const Section *
+PIC16TargetObjectFile::CreateROSectionForGlobal(const GlobalVariable *GV,
+                                                std::string Addr) const {
+  assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
+         "can be used for ROM data only");
+
+  std::string Name;
+  // If address is given then create a section at that address else create a
+  // section by section name specified in GV.
+  PIC16Section *FoundROSec = NULL;
+  if (Addr.empty()) {
+    Name = GV->getSection() + " ROMDATA";
+    for (unsigned i = 1; i < ROSections.size(); i++) {
+      if (ROSections[i]->S_->getName() == Name) {
+        FoundROSec = ROSections[i];
+        break;
+      }
+    }
+  } else {
+    std::string Prefix = GV->getNameStr() + "." + Addr + ".";
+    Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
+  }
+
+  PIC16Section *NewRomSec = FoundROSec;
+  if (NewRomSec == NULL) {
+    const Section *NewSection = getOrCreateSection(Name.c_str(),
+                                                   false,
+                                                   SectionKind::ReadOnly);
+    NewRomSec = new PIC16Section(NewSection);
+    ROSections.push_back(NewRomSec);
+  }
+
+  // Insert the GV into this ROM Section.
+  NewRomSec->Items.push_back(GV);
+  return NewRomSec->S_;
+}
+
diff --git a/lib/Target/PIC16/PIC16TargetObjectFile.h b/lib/Target/PIC16/PIC16TargetObjectFile.h
new file mode 100644
index 0000000..77aea78
--- /dev/null
+++ b/lib/Target/PIC16/PIC16TargetObjectFile.h
@@ -0,0 +1,100 @@
+//===-- PIC16TargetObjectFile.h - PIC16 Object Info -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_PIC16_TARGETOBJECTFILE_H
+#define LLVM_TARGET_PIC16_TARGETOBJECTFILE_H
+
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include <vector>
+
+namespace llvm {
+  class GlobalVariable;
+  class Module;
+  class PIC16TargetMachine;
+  
+  enum { DataBankSize = 80 };
+
+  /// PIC16 Splits the global data into mulitple udata and idata sections.
+  /// Each udata and idata section needs to contain a list of globals that
+  /// they contain, in order to avoid scanning over all the global values 
+  /// again and printing only those that match the current section. 
+  /// Keeping values inside the sections make printing a section much easier.
+  ///
+  /// FIXME: Reimplement by inheriting from MCSection.
+  ///
+  struct PIC16Section {
+    const Section *S_; // Connection to actual Section.
+    unsigned Size;  // Total size of the objects contained.
+    bool SectionPrinted;
+    std::vector<const GlobalVariable*> Items;
+    
+    PIC16Section(const Section *s) {
+      S_ = s;
+      Size = 0;
+      SectionPrinted = false;
+    }
+    bool isPrinted() const { return SectionPrinted; }
+    void setPrintedStatus(bool status) { SectionPrinted = status; } 
+  };
+  
+  class PIC16TargetObjectFile : public TargetLoweringObjectFile {
+    const PIC16TargetMachine &TM;
+  public:
+    mutable std::vector<PIC16Section*> BSSSections;
+    mutable std::vector<PIC16Section*> IDATASections;
+    mutable std::vector<PIC16Section*> AutosSections;
+    mutable std::vector<PIC16Section*> ROSections;
+    mutable PIC16Section *ExternalVarDecls;
+    mutable PIC16Section *ExternalVarDefs;
+    
+    PIC16TargetObjectFile(const PIC16TargetMachine &TM);
+    ~PIC16TargetObjectFile();
+    
+    /// getSpecialCasedSectionGlobals - Allow the target to completely override
+    /// section assignment of a global.
+    virtual const Section *
+    getSpecialCasedSectionGlobals(const GlobalValue *GV,
+                                  SectionKind Kind) const;
+    virtual const Section *SelectSectionForGlobal(const GlobalValue *GV,
+                                                  SectionKind Kind,
+                                                  const TargetMachine&) const;
+  private:
+    std::string getSectionNameForSym(const std::string &Sym) const;
+
+    const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const;
+    const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const;
+    const Section *getSectionForAuto(const GlobalVariable *GV) const;
+    const Section *CreateBSSSectionForGlobal(const GlobalVariable *GV,
+                                             std::string Addr = "") const;
+    const Section *CreateIDATASectionForGlobal(const GlobalVariable *GV,
+                                               std::string Addr = "") const;
+    const Section *getROSectionForGlobal(const GlobalVariable *GV) const;
+    const Section *CreateROSectionForGlobal(const GlobalVariable *GV,
+                                            std::string Addr = "") const;
+    const Section *CreateSectionForGlobal(const GlobalVariable *GV,
+                                          const std::string &Addr = "") const;
+  public:
+    void SetSectionForGVs(Module &M);
+    const std::vector<PIC16Section*> &getBSSSections() const {
+      return BSSSections;
+    }
+    const std::vector<PIC16Section*> &getIDATASections() const {
+      return IDATASections;
+    }
+    const std::vector<PIC16Section*> &getAutosSections() const {
+      return AutosSections;
+    }
+    const std::vector<PIC16Section*> &getROSections() const {
+      return ROSections;
+    }
+    
+  };
+} // end namespace llvm
+
+#endif