a81c95f1594b480c5c2fc33f251ca082782bb4f3
[oota-llvm.git] / lib / Target / PIC16 / PIC16TargetAsmInfo.cpp
1 //===-- PIC16TargetAsmInfo.cpp - PIC16 asm properties ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source 
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the declarations of the PIC16TargetAsmInfo properties.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "PIC16TargetAsmInfo.h"
15 #include "PIC16TargetMachine.h"
16 #include "llvm/GlobalValue.h"
17 #include "llvm/GlobalVariable.h"
18 #include "llvm/DerivedTypes.h"
19
20 using namespace llvm;
21
22 PIC16TargetAsmInfo::
23 PIC16TargetAsmInfo(const PIC16TargetMachine &TM) 
24   : TargetAsmInfo(TM) {
25   CommentString = ";";
26   GlobalPrefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
27   GlobalDirective = "\tglobal\t";
28   ExternDirective = "\textern\t";
29
30   Data8bitsDirective = " db ";
31   Data16bitsDirective = " dw ";
32   Data32bitsDirective = " dl ";
33   RomData8bitsDirective = " dw ";
34   RomData16bitsDirective = " rom_di ";
35   RomData32bitsDirective = " rom_dl ";
36   ZeroDirective = NULL;
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
52   // name.
53   HasSingleParameterDotFile = false;
54 }
55
56 const char *PIC16TargetAsmInfo::getRomDirective(unsigned size) const
57 {
58   if (size == 8)
59     return RomData8bitsDirective;
60   else if (size == 16)
61     return RomData16bitsDirective;
62   else if (size == 32)
63     return RomData32bitsDirective;
64   else
65     return NULL;
66 }
67
68
69 const char *PIC16TargetAsmInfo::getASDirective(unsigned size, 
70                                                unsigned AS) const {
71   if (AS == PIC16ISD::ROM_SPACE)
72     return getRomDirective(size);
73   else
74     return NULL;
75 }
76
77 const Section *
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");
82
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);
87  
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];
94       break;
95     }
96   }
97
98   // No BSS section spacious enough was found. Crate a new one.
99   if (! FoundBSS) {
100     std::string name = PAN::getUdataSectionName(BSSSections.size());
101     const Section *NewSection = getNamedSection (name.c_str());
102
103     FoundBSS = new PIC16Section(NewSection);
104
105     // Add this newly created BSS section to the list of BSSSections.
106     BSSSections.push_back(FoundBSS);
107   }
108   
109   // Insert the GV into this BSS.
110   FoundBSS->Items.push_back(GV);
111   FoundBSS->Size += ValSize;
112
113   // We can't do this here because GV is const .
114   // const std::string SName = FoundBSS->S_->getName();
115   // GV->setSection(SName);
116
117   return FoundBSS->S_;
118
119
120 const Section *
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");
127
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);
132  
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]; 
139       break;
140     }
141   }
142
143   // No IDATA section spacious enough was found. Crate a new one.
144   if (! FoundIDATA) {
145     std::string name = PAN::getIdataSectionName(IDATASections.size());
146     const Section *NewSection = getNamedSection (name.c_str());
147
148     FoundIDATA = new PIC16Section(NewSection);
149
150     // Add this newly created IDATA section to the list of IDATASections.
151     IDATASections.push_back(FoundIDATA);
152   }
153   
154   // Insert the GV into this IDATA.
155   FoundIDATA->Items.push_back(GV);
156   FoundIDATA->Size += ValSize;
157
158   // We can't do this here because GV is const .
159   // GV->setSection(FoundIDATA->S->getName());
160
161   return FoundIDATA->S_;
162
163
164 // Get the section for an automatic variable of a function.
165 // For PIC16 they are globals only with mangled names.
166 const Section *
167 PIC16TargetAsmInfo::getSectionForAuto(const GlobalVariable *GV) const {
168
169   const std::string name = PAN::getSectionNameForSym(GV->getName());
170
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];
177       break;
178     }
179   }
180
181   // No Auto section was found. Crate a new one.
182   if (! FoundAutoSec) {
183     const Section *NewSection = getNamedSection (name.c_str());
184
185     FoundAutoSec = new PIC16Section(NewSection);
186
187     // Add this newly created autos section to the list of AutosSections.
188     AutosSections.push_back(FoundAutoSec);
189   }
190
191   // Insert the auto into this section.
192   FoundAutoSec->Items.push_back(GV);
193
194   return FoundAutoSec->S_;
195 }
196
197
198 // Override default implementation to put the true globals into
199 // multiple data sections if required.
200 const Section*
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); 
205
206   if (!GV)
207     return TargetAsmInfo::SelectSectionForGlobal(GV1);
208
209   // Record Exteranl Var Decls.
210   if (GV->isDeclaration()) {
211     ExternalVarDecls->Items.push_back(GV);
212     return ExternalVarDecls->S_;
213   }
214     
215   assert (GV->hasInitializer() && "A def without initializer?");
216
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);
222   }
223
224   // Record Exteranl Var Defs.
225   if (GV->hasExternalLinkage() || GV->hasCommonLinkage()) {
226     ExternalVarDefs->Items.push_back(GV);
227   }
228
229   // See if this is an uninitialized global.
230   const Constant *C = GV->getInitializer();
231   if (C->isNullValue()) 
232     return getBSSSectionForGlobal(GV); 
233
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);
237
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);
241
242   // Else let the default implementation take care of it.
243   return TargetAsmInfo::SelectSectionForGlobal(GV);
244 }
245
246 PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {
247   
248   for (unsigned i = 0; i < BSSSections.size(); i++) {
249       delete BSSSections[i]; 
250   }
251
252   for (unsigned i = 0; i < IDATASections.size(); i++) {
253       delete IDATASections[i]; 
254   }
255
256   for (unsigned i = 0; i < AutosSections.size(); i++) {
257       delete AutosSections[i]; 
258   }
259
260   for (unsigned i = 0; i < ROSections.size(); i++) {
261       delete ROSections[i];
262   }
263
264   delete ExternalVarDecls;
265   delete ExternalVarDefs;
266 }
267
268 // Override the default implementation. Create PIC16sections for variables 
269 // which have a section name or address.
270 const Section* 
271 PIC16TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
272   const Section* S;
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
277     // section.
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);
282     }
283     else {
284       S = CreateSectionForGlobal(GV);
285     } 
286   } else {
287     // Use section depending on the 'type' of variable
288     S = SelectSectionForGlobal(GV);
289   }
290   return S;
291 }
292
293 // Create a new section for global variable. If Addr is given then create
294 // section at that address else create by name.
295 const Section *
296 PIC16TargetAsmInfo::CreateSectionForGlobal(const GlobalValue *GV1,
297                                            std::string Addr) const {
298   const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
299
300   if (!GV)
301     return TargetAsmInfo::SectionForGlobal(GV1);
302
303   // See if this is an uninitialized global.
304   const Constant *C = GV->getInitializer();
305   if (C->isNullValue())
306     return CreateBSSSectionForGlobal(GV, Addr);
307
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);
311
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);
315
316   // Else let the default implementation take care of it.
317   return TargetAsmInfo::SectionForGlobal(GV);
318 }
319
320 // Create uninitialized section for a variable.
321 const Section *
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");
327   std::string Name;
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;
331   if (Addr.empty()) { 
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];
336         break;
337       }
338     }
339   }
340   else {
341     std::string Prefix = GV->getName() + "." + Addr + ".";
342     Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
343   }
344   
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);
350   }
351
352   // Insert the GV into this BSS.
353   NewBSS->Items.push_back(GV);
354
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;
358   return NewBSS->S_;
359 }
360
361 // Get rom section for a variable. Currently there can be only one rom section
362 // unless a variable explicitly requests a section.
363 const Section *
364 PIC16TargetAsmInfo::getROSectionForGlobal(const GlobalVariable *GV) const {
365   ROSections[0]->Items.push_back(GV);
366   return ROSections[0]->S_;
367 }
368
369 // Create initialized data section for a variable.
370 const Section *
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");
378
379   std::string Name;
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;
383   if (Addr.empty()) {
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];
388         break;
389       }
390     }
391   }
392   else {
393     std::string Prefix = GV->getName() + "." + Addr + ".";
394     Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
395   }
396
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);
402   }
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_;
409 }
410
411 // Create a section in rom for a variable.
412 const Section *
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");
417
418   std::string Name;
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;
422   if (Addr.empty()) {
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];
427         break;
428       }
429     }
430   }
431   else {
432     std::string Prefix = GV->getName() + "." + Addr + ".";
433     Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
434   }
435
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);
441   }
442
443   // Insert the GV into this ROM Section.
444   NewRomSec->Items.push_back(GV);
445   return NewRomSec->S_;
446 }
447