1 //===-- PIC16TargetAsmInfo.cpp - PIC16 asm properties ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains the declarations of the PIC16TargetAsmInfo properties.
12 //===----------------------------------------------------------------------===//
14 #include "PIC16TargetAsmInfo.h"
15 #include "PIC16TargetMachine.h"
16 #include "llvm/GlobalValue.h"
17 #include "llvm/GlobalVariable.h"
18 #include "llvm/DerivedTypes.h"
23 PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
26 GlobalPrefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
27 GlobalDirective = "\tglobal\t";
28 ExternDirective = "\textern\t";
30 Data8bitsDirective = " db ";
31 Data16bitsDirective = " dw ";
32 Data32bitsDirective = " dl ";
33 RomData8bitsDirective = " dw ";
34 RomData16bitsDirective = " rom_di ";
35 RomData32bitsDirective = " rom_dl ";
37 AsciiDirective = " dt ";
38 AscizDirective = NULL;
39 BSSSection_ = getNamedSection("udata.# UDATA",
40 SectionFlags::Writeable | SectionFlags::BSS);
41 ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None);
42 DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable);
43 SwitchToSectionDirective = "";
44 // Need because otherwise a .text symbol is emitted by DwarfWriter
45 // in BeginModule, and gpasm cribbs for that .text symbol.
46 TextSection = getUnnamedSection("", SectionFlags::Code);
47 PIC16Section *ROSection = new PIC16Section(getReadOnlySection());
48 ROSections.push_back(ROSection);
49 ExternalVarDecls = new PIC16Section(getNamedSection("ExternalVarDecls"));
50 ExternalVarDefs = new PIC16Section(getNamedSection("ExternalVarDefs"));
51 // Set it to false because we weed to generate c file name and not bc file
53 HasSingleParameterDotFile = false;
56 const char *PIC16TargetAsmInfo::getRomDirective(unsigned size) const
59 return RomData8bitsDirective;
61 return RomData16bitsDirective;
63 return RomData32bitsDirective;
69 const char *PIC16TargetAsmInfo::getASDirective(unsigned size,
71 if (AS == PIC16ISD::ROM_SPACE)
72 return getRomDirective(size);
78 PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
79 assert (GV->hasInitializer() && "This global doesn't need space");
80 Constant *C = GV->getInitializer();
81 assert (C->isNullValue() && "Unitialized globals has non-zero initializer");
83 // Find how much space this global needs.
84 const TargetData *TD = TM.getTargetData();
85 const Type *Ty = C->getType();
86 unsigned ValSize = TD->getTypeAllocSize(Ty);
88 // Go through all BSS Sections and assign this variable
89 // to the first available section having enough space.
90 PIC16Section *FoundBSS = NULL;
91 for (unsigned i = 0; i < BSSSections.size(); i++) {
92 if (DataBankSize - BSSSections[i]->Size >= ValSize) {
93 FoundBSS = BSSSections[i];
98 // No BSS section spacious enough was found. Crate a new one.
100 std::string name = PAN::getUdataSectionName(BSSSections.size());
101 const Section *NewSection = getNamedSection (name.c_str());
103 FoundBSS = new PIC16Section(NewSection);
105 // Add this newly created BSS section to the list of BSSSections.
106 BSSSections.push_back(FoundBSS);
109 // Insert the GV into this BSS.
110 FoundBSS->Items.push_back(GV);
111 FoundBSS->Size += ValSize;
113 // We can't do this here because GV is const .
114 // const std::string SName = FoundBSS->S_->getName();
115 // GV->setSection(SName);
121 PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
122 assert (GV->hasInitializer() && "This global doesn't need space");
123 Constant *C = GV->getInitializer();
124 assert (!C->isNullValue() && "initialized globals has zero initializer");
125 assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
126 "can split initialized RAM data only");
128 // Find how much space this global needs.
129 const TargetData *TD = TM.getTargetData();
130 const Type *Ty = C->getType();
131 unsigned ValSize = TD->getTypeAllocSize(Ty);
133 // Go through all IDATA Sections and assign this variable
134 // to the first available section having enough space.
135 PIC16Section *FoundIDATA = NULL;
136 for (unsigned i = 0; i < IDATASections.size(); i++) {
137 if ( DataBankSize - IDATASections[i]->Size >= ValSize) {
138 FoundIDATA = IDATASections[i];
143 // No IDATA section spacious enough was found. Crate a new one.
145 std::string name = PAN::getIdataSectionName(IDATASections.size());
146 const Section *NewSection = getNamedSection (name.c_str());
148 FoundIDATA = new PIC16Section(NewSection);
150 // Add this newly created IDATA section to the list of IDATASections.
151 IDATASections.push_back(FoundIDATA);
154 // Insert the GV into this IDATA.
155 FoundIDATA->Items.push_back(GV);
156 FoundIDATA->Size += ValSize;
158 // We can't do this here because GV is const .
159 // GV->setSection(FoundIDATA->S->getName());
161 return FoundIDATA->S_;
164 // Get the section for an automatic variable of a function.
165 // For PIC16 they are globals only with mangled names.
167 PIC16TargetAsmInfo::getSectionForAuto(const GlobalVariable *GV) const {
169 const std::string name = PAN::getSectionNameForSym(GV->getName());
171 // Go through all Auto Sections and assign this variable
172 // to the appropriate section.
173 PIC16Section *FoundAutoSec = NULL;
174 for (unsigned i = 0; i < AutosSections.size(); i++) {
175 if ( AutosSections[i]->S_->getName() == name) {
176 FoundAutoSec = AutosSections[i];
181 // No Auto section was found. Crate a new one.
182 if (! FoundAutoSec) {
183 const Section *NewSection = getNamedSection (name.c_str());
185 FoundAutoSec = new PIC16Section(NewSection);
187 // Add this newly created autos section to the list of AutosSections.
188 AutosSections.push_back(FoundAutoSec);
191 // Insert the auto into this section.
192 FoundAutoSec->Items.push_back(GV);
194 return FoundAutoSec->S_;
198 // Override default implementation to put the true globals into
199 // multiple data sections if required.
201 PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1) const {
202 // We select the section based on the initializer here, so it really
203 // has to be a GlobalVariable.
204 const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
207 return TargetAsmInfo::SelectSectionForGlobal(GV1);
209 // Record Exteranl Var Decls.
210 if (GV->isDeclaration()) {
211 ExternalVarDecls->Items.push_back(GV);
212 return ExternalVarDecls->S_;
215 assert (GV->hasInitializer() && "A def without initializer?");
217 // First, if this is an automatic variable for a function, get the section
218 // name for it and return.
219 const std::string name = GV->getName();
220 if (PAN::isLocalName(name)) {
221 return getSectionForAuto(GV);
224 // Record Exteranl Var Defs.
225 if (GV->hasExternalLinkage() || GV->hasCommonLinkage()) {
226 ExternalVarDefs->Items.push_back(GV);
229 // See if this is an uninitialized global.
230 const Constant *C = GV->getInitializer();
231 if (C->isNullValue())
232 return getBSSSectionForGlobal(GV);
234 // If this is initialized data in RAM. Put it in the correct IDATA section.
235 if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
236 return getIDATASectionForGlobal(GV);
238 // This is initialized data in rom, put it in the readonly section.
239 if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
240 return getROSectionForGlobal(GV);
242 // Else let the default implementation take care of it.
243 return TargetAsmInfo::SelectSectionForGlobal(GV);
246 PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {
248 for (unsigned i = 0; i < BSSSections.size(); i++) {
249 delete BSSSections[i];
252 for (unsigned i = 0; i < IDATASections.size(); i++) {
253 delete IDATASections[i];
256 for (unsigned i = 0; i < AutosSections.size(); i++) {
257 delete AutosSections[i];
260 for (unsigned i = 0; i < ROSections.size(); i++) {
261 delete ROSections[i];
264 delete ExternalVarDecls;
265 delete ExternalVarDefs;
268 // Override the default implementation. Create PIC16sections for variables
269 // which have a section name or address.
271 PIC16TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
273 // If GV has a sectin name or section address create that section now.
274 if (GV->hasSection()) {
275 std::string SectName = GV->getSection();
276 // If address for a variable is specified, get the address and create
278 std::string AddrStr = "Address=";
279 if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
280 std::string SectAddr = SectName.substr(AddrStr.length());
281 S = CreateSectionForGlobal(GV, SectAddr);
284 S = CreateSectionForGlobal(GV);
287 // Use section depending on the 'type' of variable
288 S = SelectSectionForGlobal(GV);
293 // Create a new section for global variable. If Addr is given then create
294 // section at that address else create by name.
296 PIC16TargetAsmInfo::CreateSectionForGlobal(const GlobalValue *GV1,
297 std::string Addr) const {
298 const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
301 return TargetAsmInfo::SectionForGlobal(GV1);
303 // See if this is an uninitialized global.
304 const Constant *C = GV->getInitializer();
305 if (C->isNullValue())
306 return CreateBSSSectionForGlobal(GV, Addr);
308 // If this is initialized data in RAM. Put it in the correct IDATA section.
309 if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
310 return CreateIDATASectionForGlobal(GV, Addr);
312 // This is initialized data in rom, put it in the readonly section.
313 if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
314 return CreateROSectionForGlobal(GV, Addr);
316 // Else let the default implementation take care of it.
317 return TargetAsmInfo::SectionForGlobal(GV);
320 // Create uninitialized section for a variable.
322 PIC16TargetAsmInfo::CreateBSSSectionForGlobal(const GlobalVariable *GV,
323 std::string Addr) const {
324 assert (GV->hasInitializer() && "This global doesn't need space");
325 Constant *C = GV->getInitializer();
326 assert (C->isNullValue() && "Unitialized globals has non-zero initializer");
328 // If address is given then create a section at that address else create a
329 // section by section name specified in GV.
330 PIC16Section *FoundBSS = NULL;
332 Name = GV->getSection() + " UDATA";
333 for (unsigned i = 0; i < BSSSections.size(); i++) {
334 if (BSSSections[i]->S_->getName() == Name) {
335 FoundBSS = BSSSections[i];
341 std::string Prefix = GV->getName() + "." + Addr + ".";
342 Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
345 PIC16Section *NewBSS = FoundBSS;
346 if (NewBSS == NULL) {
347 const Section *NewSection = getNamedSection (Name.c_str());
348 NewBSS = new PIC16Section(NewSection);
349 BSSSections.push_back(NewBSS);
352 // Insert the GV into this BSS.
353 NewBSS->Items.push_back(GV);
355 // We do not want to put any GV without explicit section into this section
356 // so set its size to DatabankSize.
357 NewBSS->Size = DataBankSize;
361 // Get rom section for a variable. Currently there can be only one rom section
362 // unless a variable explicitly requests a section.
364 PIC16TargetAsmInfo::getROSectionForGlobal(const GlobalVariable *GV) const {
365 ROSections[0]->Items.push_back(GV);
366 return ROSections[0]->S_;
369 // Create initialized data section for a variable.
371 PIC16TargetAsmInfo::CreateIDATASectionForGlobal(const GlobalVariable *GV,
372 std::string Addr) const {
373 assert (GV->hasInitializer() && "This global doesn't need space");
374 Constant *C = GV->getInitializer();
375 assert (!C->isNullValue() && "initialized globals has zero initializer");
376 assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
377 "can be used for initialized RAM data only");
380 // If address is given then create a section at that address else create a
381 // section by section name specified in GV.
382 PIC16Section *FoundIDATASec = NULL;
384 Name = GV->getSection() + " IDATA";
385 for (unsigned i = 0; i < IDATASections.size(); i++) {
386 if (IDATASections[i]->S_->getName() == Name) {
387 FoundIDATASec = IDATASections[i];
393 std::string Prefix = GV->getName() + "." + Addr + ".";
394 Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
397 PIC16Section *NewIDATASec = FoundIDATASec;
398 if (NewIDATASec == NULL) {
399 const Section *NewSection = getNamedSection (Name.c_str());
400 NewIDATASec = new PIC16Section(NewSection);
401 IDATASections.push_back(NewIDATASec);
403 // Insert the GV into this IDATA Section.
404 NewIDATASec->Items.push_back(GV);
405 // We do not want to put any GV without explicit section into this section
406 // so set its size to DatabankSize.
407 NewIDATASec->Size = DataBankSize;
408 return NewIDATASec->S_;
411 // Create a section in rom for a variable.
413 PIC16TargetAsmInfo::CreateROSectionForGlobal(const GlobalVariable *GV,
414 std::string Addr) const {
415 assert (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
416 "can be used for ROM data only");
419 // If address is given then create a section at that address else create a
420 // section by section name specified in GV.
421 PIC16Section *FoundROSec = NULL;
423 Name = GV->getSection() + " ROMDATA";
424 for (unsigned i = 1; i < ROSections.size(); i++) {
425 if (ROSections[i]->S_->getName() == Name) {
426 FoundROSec = ROSections[i];
432 std::string Prefix = GV->getName() + "." + Addr + ".";
433 Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
436 PIC16Section *NewRomSec = FoundROSec;
437 if (NewRomSec == NULL) {
438 const Section *NewSection = getNamedSection (Name.c_str());
439 NewRomSec = new PIC16Section(NewSection);
440 ROSections.push_back(NewRomSec);
443 // Insert the GV into this ROM Section.
444 NewRomSec->Items.push_back(GV);
445 return NewRomSec->S_;