diff options
Diffstat (limited to 'contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp b/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp new file mode 100644 index 0000000..ff0f971 --- /dev/null +++ b/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp @@ -0,0 +1,384 @@ +//===-- 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 "PIC16TargetMachine.h" +#include "PIC16Section.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + + +PIC16TargetObjectFile::PIC16TargetObjectFile() { +} + +PIC16TargetObjectFile::~PIC16TargetObjectFile() { +} + +/// Find a pic16 section. Return null if not found. Do not create one. +PIC16Section *PIC16TargetObjectFile:: +findPIC16Section(const std::string &Name) const { + /// Return if we have an already existing one. + PIC16Section *Entry = SectionsByName[Name]; + if (Entry) + return Entry; + + return NULL; +} + + +/// Find a pic16 section. If not found, create one. +PIC16Section *PIC16TargetObjectFile:: +getPIC16Section(const std::string &Name, PIC16SectionType Ty, + const std::string &Address, int Color) const { + + /// Return if we have an already existing one. + PIC16Section *&Entry = SectionsByName[Name]; + if (Entry) + return Entry; + + + Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext()); + return Entry; +} + +/// Find a standard pic16 data section. If not found, create one and keep +/// track of it by adding it to appropriate std section list. +PIC16Section *PIC16TargetObjectFile:: +getPIC16DataSection(const std::string &Name, PIC16SectionType Ty, + const std::string &Address, int Color) const { + + /// Return if we have an already existing one. + PIC16Section *&Entry = SectionsByName[Name]; + if (Entry) + return Entry; + + + /// Else create a new one and add it to appropriate section list. + Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext()); + + switch (Ty) { + default: llvm_unreachable ("unknow standard section type."); + case UDATA: UDATASections_.push_back(Entry); break; + case IDATA: IDATASections_.push_back(Entry); break; + case ROMDATA: ROMDATASection_ = Entry; break; + case UDATA_SHR: SHAREDUDATASection_ = Entry; break; + } + + return Entry; +} + + +/// Find a standard pic16 autos section. If not found, create one and keep +/// track of it by adding it to appropriate std section list. +PIC16Section *PIC16TargetObjectFile:: +getPIC16AutoSection(const std::string &Name, PIC16SectionType Ty, + const std::string &Address, int Color) const { + + /// Return if we have an already existing one. + PIC16Section *&Entry = SectionsByName[Name]; + if (Entry) + return Entry; + + + /// Else create a new one and add it to appropriate section list. + Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext()); + + assert (Ty == UDATA_OVR && "incorrect section type for autos"); + AUTOSections_.push_back(Entry); + + return Entry; +} + +/// Find a pic16 user section. If not found, create one and keep +/// track of it by adding it to appropriate std section list. +PIC16Section *PIC16TargetObjectFile:: +getPIC16UserSection(const std::string &Name, PIC16SectionType Ty, + const std::string &Address, int Color) const { + + /// Return if we have an already existing one. + PIC16Section *&Entry = SectionsByName[Name]; + if (Entry) + return Entry; + + + /// Else create a new one and add it to appropriate section list. + Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext()); + + USERSections_.push_back(Entry); + + return Entry; +} + +/// Do some standard initialization. +void PIC16TargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &tm){ + TargetLoweringObjectFile::Initialize(Ctx, tm); + TM = &tm; + + ROMDATASection_ = NULL; + SHAREDUDATASection_ = NULL; +} + +/// allocateUDATA - Allocate a un-initialized global to an existing or new UDATA +/// section and return that section. +const MCSection * +PIC16TargetObjectFile::allocateUDATA(const GlobalVariable *GV) const { + assert(GV->hasInitializer() && "This global doesn't need space"); + const 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 UDATA Sections and assign this variable + // to the first available section having enough space. + PIC16Section *Found = NULL; + for (unsigned i = 0; i < UDATASections_.size(); i++) { + if (DataBankSize - UDATASections_[i]->getSize() >= ValSize) { + Found = UDATASections_[i]; + break; + } + } + + // No UDATA section spacious enough was found. Crate a new one. + if (!Found) { + std::string name = PAN::getUdataSectionName(UDATASections_.size()); + Found = getPIC16DataSection(name.c_str(), UDATA); + } + + // Insert the GV into this UDATA section. + Found->Items.push_back(GV); + Found->setSize(Found->getSize() + ValSize); + return Found; +} + +/// allocateIDATA - allocate an initialized global into an existing +/// or new section and return that section. +const MCSection * +PIC16TargetObjectFile::allocateIDATA(const GlobalVariable *GV) const{ + assert(GV->hasInitializer() && "This global doesn't need space"); + const Constant *C = GV->getInitializer(); + assert(!C->isNullValue() && "initialized globals has zero initializer"); + assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE && + "can allocate 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 *Found = NULL; + for (unsigned i = 0; i < IDATASections_.size(); i++) { + if (DataBankSize - IDATASections_[i]->getSize() >= ValSize) { + Found = IDATASections_[i]; + break; + } + } + + // No IDATA section spacious enough was found. Crate a new one. + if (!Found) { + std::string name = PAN::getIdataSectionName(IDATASections_.size()); + Found = getPIC16DataSection(name.c_str(), IDATA); + } + + // Insert the GV into this IDATA. + Found->Items.push_back(GV); + Found->setSize(Found->getSize() + ValSize); + return Found; +} + +// Allocate a program memory variable into ROMDATA section. +const MCSection * +PIC16TargetObjectFile::allocateROMDATA(const GlobalVariable *GV) const { + + std::string name = PAN::getRomdataSectionName(); + PIC16Section *S = getPIC16DataSection(name.c_str(), ROMDATA); + + S->Items.push_back(GV); + return S; +} + +// Get the section for an automatic variable of a function. +// For PIC16 they are globals only with mangled names. +const MCSection * +PIC16TargetObjectFile::allocateAUTO(const GlobalVariable *GV) const { + + const std::string name = PAN::getSectionNameForSym(GV->getName()); + PIC16Section *S = getPIC16AutoSection(name.c_str()); + + S->Items.push_back(GV); + return S; +} + + +// Override default implementation to put the true globals into +// multiple data sections if required. +const MCSection * +PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1, + SectionKind Kind, + Mangler *Mang, + 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, Mang,TM); + + 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 allocateAUTO(GV); + + // See if this is an uninitialized global. + const Constant *C = GV->getInitializer(); + if (C->isNullValue()) + return allocateUDATA(GV); + + // If this is initialized data in RAM. Put it in the correct IDATA section. + if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) + return allocateIDATA(GV); + + // This is initialized data in rom, put it in the readonly section. + if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) + return allocateROMDATA(GV); + + // Else let the default implementation take care of it. + return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, Mang,TM); +} + + + + +/// getExplicitSectionGlobal - Allow the target to completely override +/// section assignment of a global. +const MCSection *PIC16TargetObjectFile:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + assert(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. + // FIXME: move this attribute checking in PAN. + std::string AddrStr = "Address="; + if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) { + std::string SectAddr = SectName.substr(AddrStr.length()); + if (SectAddr.compare("NEAR") == 0) + return allocateSHARED(GVar, Mang); + else + return allocateAtGivenAddress(GVar, SectAddr); + } + + // Create the section specified with section attribute. + return allocateInGivenSection(GVar); + } + + return getPIC16DataSection(GV->getSection().c_str(), UDATA); +} + +const MCSection * +PIC16TargetObjectFile::allocateSHARED(const GlobalVariable *GV, + Mangler *Mang) const { + // Make sure that this is an uninitialized global. + assert(GV->hasInitializer() && "This global doesn't need space"); + if (!GV->getInitializer()->isNullValue()) { + // FIXME: Generate a warning in this case that near qualifier will be + // ignored. + return SelectSectionForGlobal(GV, SectionKind::getDataRel(), Mang, *TM); + } + std::string Name = PAN::getSharedUDataSectionName(); + + PIC16Section *SharedUDataSect = getPIC16DataSection(Name.c_str(), UDATA_SHR); + // Insert the GV into shared section. + SharedUDataSect->Items.push_back(GV); + return SharedUDataSect; +} + + +// Interface used by AsmPrinter to get a code section for a function. +const PIC16Section * +PIC16TargetObjectFile::SectionForCode(const std::string &FnName, + bool isISR) const { + const std::string &sec_name = PAN::getCodeSectionName(FnName); + // If it is ISR, its code section starts at a specific address. + if (isISR) + return getPIC16Section(sec_name, CODE, PAN::getISRAddr()); + return getPIC16Section(sec_name, CODE); +} + +// Interface used by AsmPrinter to get a frame section for a function. +const PIC16Section * +PIC16TargetObjectFile::SectionForFrame(const std::string &FnName) const { + const std::string &sec_name = PAN::getFrameSectionName(FnName); + return getPIC16Section(sec_name, UDATA_OVR); +} + +// Allocate a global var in existing or new section of given name. +const MCSection * +PIC16TargetObjectFile::allocateInGivenSection(const GlobalVariable *GV) const { + // Determine the type of section that we need to create. + PIC16SectionType SecTy; + + // See if this is an uninitialized global. + const Constant *C = GV->getInitializer(); + if (C->isNullValue()) + SecTy = UDATA; + // If this is initialized data in RAM. Put it in the correct IDATA section. + else if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) + SecTy = IDATA; + // This is initialized data in rom, put it in the readonly section. + else if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) + SecTy = ROMDATA; + else + llvm_unreachable ("Could not determine section type for global"); + + PIC16Section *S = getPIC16UserSection(GV->getSection().c_str(), SecTy); + S->Items.push_back(GV); + return S; +} + +// Allocate a global var in a new absolute sections at given address. +const MCSection * +PIC16TargetObjectFile::allocateAtGivenAddress(const GlobalVariable *GV, + const std::string &Addr) const { + // Determine the type of section that we need to create. + PIC16SectionType SecTy; + + // See if this is an uninitialized global. + const Constant *C = GV->getInitializer(); + if (C->isNullValue()) + SecTy = UDATA; + // If this is initialized data in RAM. Put it in the correct IDATA section. + else if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) + SecTy = IDATA; + // This is initialized data in rom, put it in the readonly section. + else if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) + SecTy = ROMDATA; + else + llvm_unreachable ("Could not determine section type for global"); + + std::string Prefix = GV->getNameStr() + "." + Addr + "."; + std::string SName = PAN::getUserSectionName(Prefix); + PIC16Section *S = getPIC16UserSection(SName.c_str(), SecTy, Addr.c_str()); + S->Items.push_back(GV); + return S; +} + + |