//===-- PIC16TargetAsmInfo.cpp - PIC16 asm properties ---------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains the declarations of the PIC16TargetAsmInfo properties. // //===----------------------------------------------------------------------===// #include "PIC16TargetAsmInfo.h" #include "PIC16TargetMachine.h" #include "llvm/GlobalValue.h" #include "llvm/GlobalVariable.h" #include "llvm/DerivedTypes.h" using namespace llvm; PIC16TargetAsmInfo:: PIC16TargetAsmInfo(const PIC16TargetMachine &TM) : TargetAsmInfo(TM) { CommentString = ";"; Data8bitsDirective = " db "; Data16bitsDirective = " dw "; Data32bitsDirective = " dl "; RomData8bitsDirective = " dw "; RomData16bitsDirective = " rom_di "; RomData32bitsDirective = " rom_dl "; ZeroDirective = NULL; AsciiDirective = " dt "; AscizDirective = NULL; BSSSection_ = getNamedSection("udata.# UDATA", SectionFlags::Writeable | SectionFlags::BSS); ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None); DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable); SwitchToSectionDirective = ""; // Need because otherwise a .text symbol is emitted by DwarfWriter // in BeginModule, and gpasm cribbs for that .text symbol. TextSection = getUnnamedSection("", SectionFlags::Code); } const char *PIC16TargetAsmInfo::getRomDirective(unsigned size) const { if (size == 8) return RomData8bitsDirective; else if (size == 16) return RomData16bitsDirective; else if (size == 32) return RomData32bitsDirective; else return NULL; } const char *PIC16TargetAsmInfo::getASDirective(unsigned size, unsigned AS) const { if (AS == PIC16ISD::ROM_SPACE) return getRomDirective(size); else 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) { char *name = new char[32]; sprintf (name, "udata.%d.# UDATA", (int)BSSSections.size()); const Section *NewSection = getNamedSection (name); 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; // We can't do this here because GV is const . // const std::string SName = FoundBSS->S_->getName(); // GV->setSection(SName); 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) { char *name = new char[32]; sprintf (name, "idata.%d.# IDATA", (int)IDATASections.size()); const Section *NewSection = getNamedSection (name); 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; // We can't do this here because GV is const . // GV->setSection(FoundIDATA->S->getName()); return FoundIDATA->S_; } // Override default implementation to put the true globals into // multiple data sections if required. const Section* PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1) const { // We select the section based on the initializer here, so it really // has to be a GlobalVariable. if (!isa(GV1)) return TargetAsmInfo::SelectSectionForGlobal(GV1); const GlobalVariable *GV = dyn_cast(GV1); // We are only dealing with true globals here. So names with a "." // are local globals. Also declarations are not entertained. std::string name = GV->getName(); if (name.find(".auto.") != std::string::npos || name.find(".arg.") != std::string::npos || !GV->hasInitializer()) return TargetAsmInfo::SelectSectionForGlobal(GV); const Constant *C = GV->getInitializer(); // See if this is an uninitialized global. if (C->isNullValue()) return getBSSSectionForGlobal(GV); // This is initialized data. We only deal with initialized data in RAM. if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) return getIDATASectionForGlobal(GV); // Else let the default implementation take care of it. return TargetAsmInfo::SelectSectionForGlobal(GV); } void PIC16TargetAsmInfo::SetSectionForGVs(Module &M) { for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { if (!I->hasInitializer()) // External global require no code. continue; // Any variables reaching here with "." in its name is a local scope // variable and should not be printed in global data section. std::string name = I->getName(); if (name.find(".auto.") != std::string::npos || name.find(".args.") != std::string::npos) continue; int AddrSpace = I->getType()->getAddressSpace(); if (AddrSpace == PIC16ISD::RAM_SPACE) I->setSection(SectionForGlobal(I)->getName()); } } PIC16TargetAsmInfo::~PIC16TargetAsmInfo() { for (unsigned i = 0; i < BSSSections.size(); i++) { delete BSSSections[i]; } for (unsigned i = 0; i < IDATASections.size(); i++) { delete IDATASections[i]; } }