diff options
Diffstat (limited to 'lib/Target/PIC16')
-rw-r--r-- | lib/Target/PIC16/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16AsmPrinter.cpp | 42 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16AsmPrinter.h | 11 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16ISelLowering.cpp | 4 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16TargetAsmInfo.cpp | 396 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16TargetAsmInfo.h | 79 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16TargetObjectFile.cpp | 401 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16TargetObjectFile.h | 100 |
8 files changed, 551 insertions, 483 deletions
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 @@ add_llvm_target(PIC16 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 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 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 @@ bool PIC16AsmPrinter::doInitialization(Module &M) { // 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 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) { // 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 @@ void PIC16AsmPrinter::EmitUndefinedVars(Module &M) { // 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 @@ void PIC16AsmPrinter::EmitDefinedVars(Module &M) { // 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 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { 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::EmitFunctionFrame(MachineFunction &MF) { 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 @@ void PIC16AsmPrinter::EmitUData(Module &M) { 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 @@ void PIC16AsmPrinter::EmitAutos(std::string FunctName) { // 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 @@ void PIC16AsmPrinter::EmitRemainingAutos() { 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 @@ namespace llvm { } 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 @@ static const char *getIntrinsicName(unsigned opcode) { // 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 @@ PIC16TargetAsmInfo(const PIC16TargetMachine &TM) 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::getRomDirective(unsigned Size) const { } } - -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; - 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; + public: + PIC16TargetAsmInfo(const PIC16TargetMachine &TM); + + virtual const char *getDataASDirective(unsigned size, unsigned AS) 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 |