Cleaned up some code. No functionality change.
[oota-llvm.git] / lib / Target / PIC16 / PIC16TargetObjectFile.cpp
1 //===-- PIC16TargetObjectFile.cpp - PIC16 object files --------------------===//
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 #include "PIC16TargetObjectFile.h"
11 #include "PIC16ISelLowering.h"
12 #include "PIC16TargetMachine.h"
13 #include "PIC16Section.h"
14 #include "llvm/DerivedTypes.h"
15 #include "llvm/Module.h"
16 #include "llvm/MC/MCSection.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/Support/raw_ostream.h"
19 using namespace llvm;
20
21
22 PIC16TargetObjectFile::PIC16TargetObjectFile() {
23 }
24
25 PIC16TargetObjectFile::~PIC16TargetObjectFile() {
26 }
27
28 /// Find a pic16 section. If not found, create one.
29 PIC16Section *PIC16TargetObjectFile::
30 getPIC16Section(const std::string &Name, PIC16SectionType Ty, 
31                 const std::string &Address, int Color) const {
32
33   /// Return if we have an already existing one.
34   PIC16Section *&Entry = SectionsByName[Name];
35   if (Entry)
36     return Entry;
37
38
39   Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
40   return Entry;
41 }
42
43 /// Find a standard pic16 data section. If not found, create one and keep
44 /// track of it by adding it to appropriate std section list.
45 PIC16Section *PIC16TargetObjectFile::
46 getPIC16DataSection(const std::string &Name, PIC16SectionType Ty, 
47                     const std::string &Address, int Color) const {
48
49   /// Return if we have an already existing one.
50   PIC16Section *&Entry = SectionsByName[Name];
51   if (Entry)
52     return Entry;
53
54
55   /// Else create a new one and add it to appropriate section list.
56   Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
57
58   switch (Ty) {
59   default: llvm_unreachable ("unknow standard section type.");
60   case UDATA: UDATASections_.push_back(Entry); break;
61   case IDATA: IDATASections_.push_back(Entry); break;
62   case ROMDATA: ROMDATASection_ = Entry; break;
63   }
64
65   return Entry;
66 }
67     
68
69 /// Find a standard pic16 autos section. If not found, create one and keep
70 /// track of it by adding it to appropriate std section list.
71 PIC16Section *PIC16TargetObjectFile::
72 getPIC16AutoSection(const std::string &Name, PIC16SectionType Ty, 
73                     const std::string &Address, int Color) const {
74
75   /// Return if we have an already existing one.
76   PIC16Section *&Entry = SectionsByName[Name];
77   if (Entry)
78     return Entry;
79
80
81   /// Else create a new one and add it to appropriate section list.
82   Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
83
84   assert (Ty == UDATA_OVR && "incorrect section type for autos");
85   AUTOSections_.push_back(Entry);
86
87   return Entry;
88 }
89     
90 /// Find a pic16 user section. If not found, create one and keep
91 /// track of it by adding it to appropriate std section list.
92 PIC16Section *PIC16TargetObjectFile::
93 getPIC16UserSection(const std::string &Name, PIC16SectionType Ty, 
94                     const std::string &Address, int Color) const {
95
96   /// Return if we have an already existing one.
97   PIC16Section *&Entry = SectionsByName[Name];
98   if (Entry)
99     return Entry;
100
101
102   /// Else create a new one and add it to appropriate section list.
103   Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
104
105   USERSections_.push_back(Entry);
106
107   return Entry;
108 }
109
110 /// Do some standard initialization.
111 void PIC16TargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &tm){
112   TargetLoweringObjectFile::Initialize(Ctx, tm);
113   TM = &tm;
114   
115   ROMDATASection_ = NULL;
116 }
117
118 /// allocateUDATA - Allocate a un-initialized global to an existing or new UDATA
119 /// section and return that section.
120 const MCSection *
121 PIC16TargetObjectFile::allocateUDATA(const GlobalVariable *GV) const {
122   assert(GV->hasInitializer() && "This global doesn't need space");
123   Constant *C = GV->getInitializer();
124   assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
125
126   // Find how much space this global needs.
127   const TargetData *TD = TM->getTargetData();
128   const Type *Ty = C->getType(); 
129   unsigned ValSize = TD->getTypeAllocSize(Ty);
130  
131   // Go through all UDATA Sections and assign this variable
132   // to the first available section having enough space.
133   PIC16Section *Found = NULL;
134   for (unsigned i = 0; i < UDATASections_.size(); i++) {
135     if (DataBankSize - UDATASections_[i]->getSize() >= ValSize) {
136       Found = UDATASections_[i];
137       break;
138     }
139   }
140
141   // No UDATA section spacious enough was found. Crate a new one.
142   if (!Found) {
143     std::string name = PAN::getUdataSectionName(UDATASections_.size());
144     Found = getPIC16DataSection(name.c_str(), UDATA);
145   }
146   
147   // Insert the GV into this UDATA section.
148   Found->Items.push_back(GV);
149   Found->setSize(Found->getSize() + ValSize);
150   return Found;
151
152
153 /// allocateIDATA - allocate an initialized global into an existing
154 /// or new section and return that section.
155 const MCSection *
156 PIC16TargetObjectFile::allocateIDATA(const GlobalVariable *GV) const{
157   assert(GV->hasInitializer() && "This global doesn't need space");
158   Constant *C = GV->getInitializer();
159   assert(!C->isNullValue() && "initialized globals has zero initializer");
160   assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
161          "can allocate initialized RAM data only");
162
163   // Find how much space this global needs.
164   const TargetData *TD = TM->getTargetData();
165   const Type *Ty = C->getType(); 
166   unsigned ValSize = TD->getTypeAllocSize(Ty);
167  
168   // Go through all IDATA Sections and assign this variable
169   // to the first available section having enough space.
170   PIC16Section *Found = NULL;
171   for (unsigned i = 0; i < IDATASections_.size(); i++) {
172     if (DataBankSize - IDATASections_[i]->getSize() >= ValSize) {
173       Found = IDATASections_[i]; 
174       break;
175     }
176   }
177
178   // No IDATA section spacious enough was found. Crate a new one.
179   if (!Found) {
180     std::string name = PAN::getIdataSectionName(IDATASections_.size());
181     Found = getPIC16DataSection(name.c_str(), IDATA);
182   }
183   
184   // Insert the GV into this IDATA.
185   Found->Items.push_back(GV);
186   Found->setSize(Found->getSize() + ValSize);
187   return Found;
188
189
190 // Allocate a program memory variable into ROMDATA section.
191 const MCSection *
192 PIC16TargetObjectFile::allocateROMDATA(const GlobalVariable *GV) const {
193
194   std::string name = PAN::getRomdataSectionName();
195   PIC16Section *S = getPIC16DataSection(name.c_str(), ROMDATA);
196
197   S->Items.push_back(GV);
198   return S;
199 }
200
201 // Get the section for an automatic variable of a function.
202 // For PIC16 they are globals only with mangled names.
203 const MCSection *
204 PIC16TargetObjectFile::allocateAUTO(const GlobalVariable *GV) const {
205
206   const std::string name = PAN::getSectionNameForSym(GV->getName());
207   PIC16Section *S = getPIC16AutoSection(name.c_str());
208
209   S->Items.push_back(GV);
210   return S;
211 }
212
213
214 // Override default implementation to put the true globals into
215 // multiple data sections if required.
216 const MCSection *
217 PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1,
218                                               SectionKind Kind,
219                                               Mangler *Mang,
220                                               const TargetMachine &TM) const {
221   // We select the section based on the initializer here, so it really
222   // has to be a GlobalVariable.
223   const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1); 
224   if (!GV)
225     return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Kind, Mang,TM);
226
227   assert(GV->hasInitializer() && "A def without initializer?");
228
229   // First, if this is an automatic variable for a function, get the section
230   // name for it and return.
231   std::string name = GV->getName();
232   if (PAN::isLocalName(name))
233     return allocateAUTO(GV);
234
235   // See if this is an uninitialized global.
236   const Constant *C = GV->getInitializer();
237   if (C->isNullValue()) 
238     return allocateUDATA(GV);
239
240   // If this is initialized data in RAM. Put it in the correct IDATA section.
241   if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) 
242     return allocateIDATA(GV);
243
244   // This is initialized data in rom, put it in the readonly section.
245   if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
246     return allocateROMDATA(GV);
247
248   // Else let the default implementation take care of it.
249   return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, Mang,TM);
250 }
251
252
253
254
255 /// getExplicitSectionGlobal - Allow the target to completely override
256 /// section assignment of a global.
257 const MCSection *PIC16TargetObjectFile::
258 getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, 
259                          Mangler *Mang, const TargetMachine &TM) const {
260   assert(GV->hasSection());
261   
262   if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
263     std::string SectName = GVar->getSection();
264     // If address for a variable is specified, get the address and create
265     // section.
266     // FIXME: move this attribute checking in PAN.
267     std::string AddrStr = "Address=";
268     if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
269       std::string SectAddr = SectName.substr(AddrStr.length());
270       return allocateAtGivenAddress(GVar, SectAddr);
271     }
272      
273     // Create the section specified with section attribute. 
274     return allocateInGivenSection(GVar);
275   }
276
277   return getPIC16DataSection(GV->getSection().c_str(), UDATA);
278 }
279
280 // Interface used by AsmPrinter to get a code section for a function.
281 const PIC16Section *
282 PIC16TargetObjectFile::SectionForCode(const std::string &FnName) const {
283   const std::string &sec_name = PAN::getCodeSectionName(FnName);
284   return getPIC16Section(sec_name, CODE);
285 }
286
287 // Interface used by AsmPrinter to get a frame section for a function.
288 const PIC16Section *
289 PIC16TargetObjectFile::SectionForFrame(const std::string &FnName) const {
290   const std::string &sec_name = PAN::getFrameSectionName(FnName);
291   return getPIC16Section(sec_name, UDATA_OVR);
292 }
293
294 // Allocate a global var in existing or new section of given name.
295 const MCSection *
296 PIC16TargetObjectFile::allocateInGivenSection(const GlobalVariable *GV) const {
297   // Determine the type of section that we need to create.
298   PIC16SectionType SecTy;
299
300   // See if this is an uninitialized global.
301   const Constant *C = GV->getInitializer();
302   if (C->isNullValue())
303     SecTy = UDATA;
304   // If this is initialized data in RAM. Put it in the correct IDATA section.
305   else if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
306     SecTy = IDATA;
307   // This is initialized data in rom, put it in the readonly section.
308   else if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
309     SecTy = ROMDATA;
310   else
311     llvm_unreachable ("Could not determine section type for global");
312
313   PIC16Section *S = getPIC16UserSection(GV->getSection().c_str(), SecTy);
314   S->Items.push_back(GV);
315   return S;
316 }
317
318 // Allocate a global var in a new absolute sections at given address.
319 const MCSection *
320 PIC16TargetObjectFile::allocateAtGivenAddress(const GlobalVariable *GV,
321                                                const std::string &Addr) const {
322   // Determine the type of section that we need to create.
323   PIC16SectionType SecTy;
324
325   // See if this is an uninitialized global.
326   const Constant *C = GV->getInitializer();
327   if (C->isNullValue())
328     SecTy = UDATA;
329   // If this is initialized data in RAM. Put it in the correct IDATA section.
330   else if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
331     SecTy = IDATA;
332   // This is initialized data in rom, put it in the readonly section.
333   else if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) 
334     SecTy = ROMDATA;
335   else
336     llvm_unreachable ("Could not determine section type for global");
337
338   std::string Prefix = GV->getNameStr() + "." + Addr + ".";
339   std::string SName = PAN::getUserSectionName(Prefix);
340   PIC16Section *S = getPIC16UserSection(SName.c_str(), SecTy, Addr.c_str());
341   S->Items.push_back(GV);
342   return S;
343 }
344
345