Avoid compiler warnings when assertions are turned off.
[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   Data64bitsDirective = NULL;
34   RomData8bitsDirective = " dw ";
35   RomData16bitsDirective = " rom_di ";
36   RomData32bitsDirective = " rom_dl ";
37   ZeroDirective = NULL;
38   AsciiDirective = " dt ";
39   AscizDirective = NULL;
40   BSSSection_  = getNamedSection("udata.# UDATA",
41                               SectionFlags::Writeable | SectionFlags::BSS);
42   ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None);
43   DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable);
44   SwitchToSectionDirective = "";
45   // Need because otherwise a .text symbol is emitted by DwarfWriter
46   // in BeginModule, and gpasm cribbs for that .text symbol.
47   TextSection = getUnnamedSection("", SectionFlags::Code);
48   PIC16Section *ROSection = new PIC16Section(getReadOnlySection());
49   ROSections.push_back(ROSection);
50   ExternalVarDecls = new PIC16Section(getNamedSection("ExternalVarDecls"));
51   ExternalVarDefs = new PIC16Section(getNamedSection("ExternalVarDefs"));
52   // Set it to false because we weed to generate c file name and not bc file
53   // name.
54   HasSingleParameterDotFile = false;
55 }
56
57 const char *PIC16TargetAsmInfo::getRomDirective(unsigned size) const
58 {
59   if (size == 8)
60     return RomData8bitsDirective;
61   else if (size == 16)
62     return RomData16bitsDirective;
63   else if (size == 32)
64     return RomData32bitsDirective;
65   else
66     return NULL;
67 }
68
69
70 const char *PIC16TargetAsmInfo::getASDirective(unsigned size, 
71                                                unsigned AS) const {
72   if (AS == PIC16ISD::ROM_SPACE)
73     return getRomDirective(size);
74   else
75     return NULL;
76 }
77
78 const Section *
79 PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
80   assert (GV->hasInitializer() && "This global doesn't need space");
81   Constant *C = GV->getInitializer();
82   assert (C->isNullValue() && "Unitialized globals has non-zero initializer");
83
84   // Find how much space this global needs.
85   const TargetData *TD = TM.getTargetData();
86   const Type *Ty = C->getType(); 
87   unsigned ValSize = TD->getTypeAllocSize(Ty);
88  
89   // Go through all BSS Sections and assign this variable
90   // to the first available section having enough space.
91   PIC16Section *FoundBSS = NULL;
92   for (unsigned i = 0; i < BSSSections.size(); i++) {
93     if (DataBankSize - BSSSections[i]->Size >= ValSize) {
94       FoundBSS = BSSSections[i];
95       break;
96     }
97   }
98
99   // No BSS section spacious enough was found. Crate a new one.
100   if (! FoundBSS) {
101     std::string name = PAN::getUdataSectionName(BSSSections.size());
102     const Section *NewSection = getNamedSection (name.c_str());
103
104     FoundBSS = new PIC16Section(NewSection);
105
106     // Add this newly created BSS section to the list of BSSSections.
107     BSSSections.push_back(FoundBSS);
108   }
109   
110   // Insert the GV into this BSS.
111   FoundBSS->Items.push_back(GV);
112   FoundBSS->Size += ValSize;
113
114   // We can't do this here because GV is const .
115   // const std::string SName = FoundBSS->S_->getName();
116   // GV->setSection(SName);
117
118   return FoundBSS->S_;
119
120
121 const Section *
122 PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
123   assert (GV->hasInitializer() && "This global doesn't need space");
124   Constant *C = GV->getInitializer();
125   assert (!C->isNullValue() && "initialized globals has zero initializer");
126   assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
127           "can split initialized RAM data only");
128
129   // Find how much space this global needs.
130   const TargetData *TD = TM.getTargetData();
131   const Type *Ty = C->getType(); 
132   unsigned ValSize = TD->getTypeAllocSize(Ty);
133  
134   // Go through all IDATA Sections and assign this variable
135   // to the first available section having enough space.
136   PIC16Section *FoundIDATA = NULL;
137   for (unsigned i = 0; i < IDATASections.size(); i++) {
138     if ( DataBankSize - IDATASections[i]->Size >= ValSize) {
139       FoundIDATA = IDATASections[i]; 
140       break;
141     }
142   }
143
144   // No IDATA section spacious enough was found. Crate a new one.
145   if (! FoundIDATA) {
146     std::string name = PAN::getIdataSectionName(IDATASections.size());
147     const Section *NewSection = getNamedSection (name.c_str());
148
149     FoundIDATA = new PIC16Section(NewSection);
150
151     // Add this newly created IDATA section to the list of IDATASections.
152     IDATASections.push_back(FoundIDATA);
153   }
154   
155   // Insert the GV into this IDATA.
156   FoundIDATA->Items.push_back(GV);
157   FoundIDATA->Size += ValSize;
158
159   // We can't do this here because GV is const .
160   // GV->setSection(FoundIDATA->S->getName());
161
162   return FoundIDATA->S_;
163
164
165 // Get the section for an automatic variable of a function.
166 // For PIC16 they are globals only with mangled names.
167 const Section *
168 PIC16TargetAsmInfo::getSectionForAuto(const GlobalVariable *GV) const {
169
170   const std::string name = PAN::getSectionNameForSym(GV->getName());
171
172   // Go through all Auto Sections and assign this variable
173   // to the appropriate section.
174   PIC16Section *FoundAutoSec = NULL;
175   for (unsigned i = 0; i < AutosSections.size(); i++) {
176     if ( AutosSections[i]->S_->getName() == name) {
177       FoundAutoSec = AutosSections[i];
178       break;
179     }
180   }
181
182   // No Auto section was found. Crate a new one.
183   if (! FoundAutoSec) {
184     const Section *NewSection = getNamedSection (name.c_str());
185
186     FoundAutoSec = new PIC16Section(NewSection);
187
188     // Add this newly created autos section to the list of AutosSections.
189     AutosSections.push_back(FoundAutoSec);
190   }
191
192   // Insert the auto into this section.
193   FoundAutoSec->Items.push_back(GV);
194
195   return FoundAutoSec->S_;
196 }
197
198
199 // Override default implementation to put the true globals into
200 // multiple data sections if required.
201 const Section*
202 PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1) const {
203   // We select the section based on the initializer here, so it really
204   // has to be a GlobalVariable.
205   const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1); 
206
207   if (!GV)
208     return TargetAsmInfo::SelectSectionForGlobal(GV1);
209
210   // Record Exteranl Var Decls.
211   if (GV->isDeclaration()) {
212     ExternalVarDecls->Items.push_back(GV);
213     return ExternalVarDecls->S_;
214   }
215     
216   assert (GV->hasInitializer() && "A def without initializer?");
217
218   // First, if this is an automatic variable for a function, get the section
219   // name for it and return.
220   const std::string name = GV->getName();
221   if (PAN::isLocalName(name)) {
222     return getSectionForAuto(GV);
223   }
224
225   // Record Exteranl Var Defs.
226   if (GV->hasExternalLinkage() || GV->hasCommonLinkage()) {
227     ExternalVarDefs->Items.push_back(GV);
228   }
229
230   // See if this is an uninitialized global.
231   const Constant *C = GV->getInitializer();
232   if (C->isNullValue()) 
233     return getBSSSectionForGlobal(GV); 
234
235   // If this is initialized data in RAM. Put it in the correct IDATA section.
236   if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) 
237     return getIDATASectionForGlobal(GV);
238
239   // This is initialized data in rom, put it in the readonly section.
240   if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
241     return getROSectionForGlobal(GV);
242
243   // Else let the default implementation take care of it.
244   return TargetAsmInfo::SelectSectionForGlobal(GV);
245 }
246
247 PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {
248   
249   for (unsigned i = 0; i < BSSSections.size(); i++) {
250       delete BSSSections[i]; 
251   }
252
253   for (unsigned i = 0; i < IDATASections.size(); i++) {
254       delete IDATASections[i]; 
255   }
256
257   for (unsigned i = 0; i < AutosSections.size(); i++) {
258       delete AutosSections[i]; 
259   }
260
261   for (unsigned i = 0; i < ROSections.size(); i++) {
262       delete ROSections[i];
263   }
264
265   delete ExternalVarDecls;
266   delete ExternalVarDefs;
267 }
268
269 // Override the default implementation. Create PIC16sections for variables 
270 // which have a section name or address.
271 const Section* 
272 PIC16TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
273   const Section* S;
274   // If GV has a sectin name or section address create that section now.
275   if (GV->hasSection()) {
276     std::string SectName = GV->getSection();
277     // If address for a variable is specified, get the address and create
278     // section.
279     std::string AddrStr = "Address=";
280     if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
281       std::string SectAddr = SectName.substr(AddrStr.length());
282       S = CreateSectionForGlobal(GV, SectAddr);
283     }
284     else {
285       S = CreateSectionForGlobal(GV);
286     } 
287   } else {
288     // Use section depending on the 'type' of variable
289     S = SelectSectionForGlobal(GV);
290   }
291   return S;
292 }
293
294 // Create a new section for global variable. If Addr is given then create
295 // section at that address else create by name.
296 const Section *
297 PIC16TargetAsmInfo::CreateSectionForGlobal(const GlobalValue *GV1,
298                                            std::string Addr) const {
299   const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
300
301   if (!GV)
302     return TargetAsmInfo::SectionForGlobal(GV1);
303
304   // See if this is an uninitialized global.
305   const Constant *C = GV->getInitializer();
306   if (C->isNullValue())
307     return CreateBSSSectionForGlobal(GV, Addr);
308
309   // If this is initialized data in RAM. Put it in the correct IDATA section.
310   if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
311     return CreateIDATASectionForGlobal(GV, Addr);
312
313   // This is initialized data in rom, put it in the readonly section.
314   if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
315     return CreateROSectionForGlobal(GV, Addr);
316
317   // Else let the default implementation take care of it.
318   return TargetAsmInfo::SectionForGlobal(GV);
319 }
320
321 // Create uninitialized section for a variable.
322 const Section *
323 PIC16TargetAsmInfo::CreateBSSSectionForGlobal(const GlobalVariable *GV,
324                                               std::string Addr) const {
325   assert (GV->hasInitializer() && "This global doesn't need space");
326   assert (GV->getInitializer()->isNullValue() &&
327           "Unitialized global has non-zero initializer");
328   std::string Name;
329   // If address is given then create a section at that address else create a
330   // section by section name specified in GV.
331   PIC16Section *FoundBSS = NULL;
332   if (Addr.empty()) { 
333     Name = GV->getSection() + " UDATA";
334     for (unsigned i = 0; i < BSSSections.size(); i++) {
335       if (BSSSections[i]->S_->getName() == Name) {
336         FoundBSS = BSSSections[i];
337         break;
338       }
339     }
340   }
341   else {
342     std::string Prefix = GV->getName() + "." + Addr + ".";
343     Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
344   }
345   
346   PIC16Section *NewBSS = FoundBSS;
347   if (NewBSS == NULL) {
348     const Section *NewSection = getNamedSection (Name.c_str());
349     NewBSS = new PIC16Section(NewSection);
350     BSSSections.push_back(NewBSS);
351   }
352
353   // Insert the GV into this BSS.
354   NewBSS->Items.push_back(GV);
355
356   // We do not want to put any  GV without explicit section into this section
357   // so set its size to DatabankSize.
358   NewBSS->Size = DataBankSize;
359   return NewBSS->S_;
360 }
361
362 // Get rom section for a variable. Currently there can be only one rom section
363 // unless a variable explicitly requests a section.
364 const Section *
365 PIC16TargetAsmInfo::getROSectionForGlobal(const GlobalVariable *GV) const {
366   ROSections[0]->Items.push_back(GV);
367   return ROSections[0]->S_;
368 }
369
370 // Create initialized data section for a variable.
371 const Section *
372 PIC16TargetAsmInfo::CreateIDATASectionForGlobal(const GlobalVariable *GV,
373                                                 std::string Addr) const {
374   assert (GV->hasInitializer() && "This global doesn't need space");
375   assert (!GV->getInitializer()->isNullValue() &&
376           "initialized global has zero initializer");
377   assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
378           "can be used for initialized RAM data only");
379
380   std::string Name;
381   // If address is given then create a section at that address else create a
382   // section by section name specified in GV.
383   PIC16Section *FoundIDATASec = NULL;
384   if (Addr.empty()) {
385     Name = GV->getSection() + " IDATA";
386     for (unsigned i = 0; i < IDATASections.size(); i++) {
387       if (IDATASections[i]->S_->getName() == Name) {
388         FoundIDATASec = IDATASections[i];
389         break;
390       }
391     }
392   }
393   else {
394     std::string Prefix = GV->getName() + "." + Addr + ".";
395     Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
396   }
397
398   PIC16Section *NewIDATASec = FoundIDATASec;
399   if (NewIDATASec == NULL) {
400     const Section *NewSection = getNamedSection (Name.c_str());
401     NewIDATASec = new PIC16Section(NewSection);
402     IDATASections.push_back(NewIDATASec);
403   }
404   // Insert the GV into this IDATA Section.
405   NewIDATASec->Items.push_back(GV);
406   // We do not want to put any  GV without explicit section into this section 
407   // so set its size to DatabankSize.
408   NewIDATASec->Size = DataBankSize;
409   return NewIDATASec->S_;
410 }
411
412 // Create a section in rom for a variable.
413 const Section *
414 PIC16TargetAsmInfo::CreateROSectionForGlobal(const GlobalVariable *GV,
415                                              std::string Addr) const {
416   assert (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
417           "can be used for ROM data only");
418
419   std::string Name;
420   // If address is given then create a section at that address else create a
421   // section by section name specified in GV.
422   PIC16Section *FoundROSec = NULL;
423   if (Addr.empty()) {
424     Name = GV->getSection() + " ROMDATA";
425     for (unsigned i = 1; i < ROSections.size(); i++) {
426       if (ROSections[i]->S_->getName() == Name) {
427         FoundROSec = ROSections[i];
428         break;
429       }
430     }
431   }
432   else {
433     std::string Prefix = GV->getName() + "." + Addr + ".";
434     Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
435   }
436
437   PIC16Section *NewRomSec = FoundROSec;
438   if (NewRomSec == NULL) {
439     const Section *NewSection = getNamedSection (Name.c_str());
440     NewRomSec = new PIC16Section(NewSection);
441     ROSections.push_back(NewRomSec);
442   }
443
444   // Insert the GV into this ROM Section.
445   NewRomSec->Items.push_back(GV);
446   return NewRomSec->S_;
447 }
448