1 //===-- PIC16TargetObjectFile.cpp - PIC16 object files --------------------===//
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 #include "PIC16TargetObjectFile.h"
11 #include "PIC16ISelLowering.h"
12 #include "PIC16TargetMachine.h"
13 #include "llvm/DerivedTypes.h"
14 #include "llvm/Module.h"
15 #include "llvm/MC/MCSection.h"
18 void PIC16TargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &tm){
19 TargetLoweringObjectFile::Initialize(Ctx, tm);
22 BSSSection_ = getOrCreateSection("udata.# UDATA", false,
23 SectionKind::get(SectionKind::BSS));
24 ReadOnlySection = getOrCreateSection("romdata.# ROMDATA", false,
25 SectionKind::get(SectionKind::ReadOnly));
26 DataSection = getOrCreateSection("idata.# IDATA", false,
27 SectionKind::get(SectionKind::DataRel));
29 // Need because otherwise a .text symbol is emitted by DwarfWriter
30 // in BeginModule, and gpasm cribbs for that .text symbol.
31 TextSection = getOrCreateSection("", true,
32 SectionKind::get(SectionKind::Text));
34 ROSections.push_back(new PIC16Section(ReadOnlySection));
36 // FIXME: I don't know what the classification of these sections really is.
37 ExternalVarDecls = new PIC16Section(getOrCreateSection("ExternalVarDecls",
39 SectionKind::get(SectionKind::Metadata)));
40 ExternalVarDefs = new PIC16Section(getOrCreateSection("ExternalVarDefs",
42 SectionKind::get(SectionKind::Metadata)));
47 PIC16TargetObjectFile::getBSSSectionForGlobal(const GlobalVariable *GV) const {
48 assert(GV->hasInitializer() && "This global doesn't need space");
49 Constant *C = GV->getInitializer();
50 assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
52 // Find how much space this global needs.
53 const TargetData *TD = TM->getTargetData();
54 const Type *Ty = C->getType();
55 unsigned ValSize = TD->getTypeAllocSize(Ty);
57 // Go through all BSS Sections and assign this variable
58 // to the first available section having enough space.
59 PIC16Section *FoundBSS = NULL;
60 for (unsigned i = 0; i < BSSSections.size(); i++) {
61 if (DataBankSize - BSSSections[i]->Size >= ValSize) {
62 FoundBSS = BSSSections[i];
67 // No BSS section spacious enough was found. Crate a new one.
69 std::string name = PAN::getUdataSectionName(BSSSections.size());
70 const MCSection *NewSection = getOrCreateSection(name.c_str(), false,
72 SectionKind::get(SectionKind::Metadata));
74 FoundBSS = new PIC16Section(NewSection);
76 // Add this newly created BSS section to the list of BSSSections.
77 BSSSections.push_back(FoundBSS);
80 // Insert the GV into this BSS.
81 FoundBSS->Items.push_back(GV);
82 FoundBSS->Size += ValSize;
87 PIC16TargetObjectFile::getIDATASectionForGlobal(const GlobalVariable *GV) const{
88 assert(GV->hasInitializer() && "This global doesn't need space");
89 Constant *C = GV->getInitializer();
90 assert(!C->isNullValue() && "initialized globals has zero initializer");
91 assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
92 "can split initialized RAM data only");
94 // Find how much space this global needs.
95 const TargetData *TD = TM->getTargetData();
96 const Type *Ty = C->getType();
97 unsigned ValSize = TD->getTypeAllocSize(Ty);
99 // Go through all IDATA Sections and assign this variable
100 // to the first available section having enough space.
101 PIC16Section *FoundIDATA = NULL;
102 for (unsigned i = 0; i < IDATASections.size(); i++) {
103 if (DataBankSize - IDATASections[i]->Size >= ValSize) {
104 FoundIDATA = IDATASections[i];
109 // No IDATA section spacious enough was found. Crate a new one.
111 std::string name = PAN::getIdataSectionName(IDATASections.size());
112 const MCSection *NewSection = getOrCreateSection(name.c_str(), false,
114 SectionKind::get(SectionKind::Metadata));
116 FoundIDATA = new PIC16Section(NewSection);
118 // Add this newly created IDATA section to the list of IDATASections.
119 IDATASections.push_back(FoundIDATA);
122 // Insert the GV into this IDATA.
123 FoundIDATA->Items.push_back(GV);
124 FoundIDATA->Size += ValSize;
125 return FoundIDATA->S_;
128 // Get the section for an automatic variable of a function.
129 // For PIC16 they are globals only with mangled names.
131 PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable *GV) const {
133 const std::string name = PAN::getSectionNameForSym(GV->getName());
135 // Go through all Auto Sections and assign this variable
136 // to the appropriate section.
137 PIC16Section *FoundAutoSec = NULL;
138 for (unsigned i = 0; i < AutosSections.size(); i++) {
139 if (AutosSections[i]->S_->getName() == name) {
140 FoundAutoSec = AutosSections[i];
145 // No Auto section was found. Crate a new one.
147 const MCSection *NewSection = getOrCreateSection(name.c_str(),
150 SectionKind::get(SectionKind::Metadata));
152 FoundAutoSec = new PIC16Section(NewSection);
154 // Add this newly created autos section to the list of AutosSections.
155 AutosSections.push_back(FoundAutoSec);
158 // Insert the auto into this section.
159 FoundAutoSec->Items.push_back(GV);
161 return FoundAutoSec->S_;
165 // Override default implementation to put the true globals into
166 // multiple data sections if required.
168 PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1,
171 const TargetMachine &TM) const {
172 // We select the section based on the initializer here, so it really
173 // has to be a GlobalVariable.
174 const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
176 return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Info, Mang,TM);
178 // Record External Var Decls.
179 if (GV->isDeclaration()) {
180 ExternalVarDecls->Items.push_back(GV);
181 return ExternalVarDecls->S_;
184 assert(GV->hasInitializer() && "A def without initializer?");
186 // First, if this is an automatic variable for a function, get the section
187 // name for it and return.
188 std::string name = GV->getName();
189 if (PAN::isLocalName(name))
190 return getSectionForAuto(GV);
192 // Record Exteranl Var Defs.
193 if (GV->hasExternalLinkage() || GV->hasCommonLinkage())
194 ExternalVarDefs->Items.push_back(GV);
196 // See if this is an uninitialized global.
197 const Constant *C = GV->getInitializer();
198 if (C->isNullValue())
199 return getBSSSectionForGlobal(GV);
201 // If this is initialized data in RAM. Put it in the correct IDATA section.
202 if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
203 return getIDATASectionForGlobal(GV);
205 // This is initialized data in rom, put it in the readonly section.
206 if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
207 return getROSectionForGlobal(GV);
209 // Else let the default implementation take care of it.
210 return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Info, Mang,TM);
213 PIC16TargetObjectFile::~PIC16TargetObjectFile() {
214 for (unsigned i = 0; i < BSSSections.size(); i++)
215 delete BSSSections[i];
216 for (unsigned i = 0; i < IDATASections.size(); i++)
217 delete IDATASections[i];
218 for (unsigned i = 0; i < AutosSections.size(); i++)
219 delete AutosSections[i];
220 for (unsigned i = 0; i < ROSections.size(); i++)
221 delete ROSections[i];
222 delete ExternalVarDecls;
223 delete ExternalVarDefs;
227 /// getSpecialCasedSectionGlobals - Allow the target to completely override
228 /// section assignment of a global.
230 PIC16TargetObjectFile::getSpecialCasedSectionGlobals(const GlobalValue *GV,
232 SectionInfo Info) const {
233 // If GV has a sectin name or section address create that section now.
234 if (GV->hasSection()) {
235 if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
236 std::string SectName = GVar->getSection();
237 // If address for a variable is specified, get the address and create
239 std::string AddrStr = "Address=";
240 if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
241 std::string SectAddr = SectName.substr(AddrStr.length());
242 return CreateSectionForGlobal(GVar, Mang, SectAddr);
245 // Create the section specified with section attribute.
246 return CreateSectionForGlobal(GVar, Mang);
253 // Create a new section for global variable. If Addr is given then create
254 // section at that address else create by name.
256 PIC16TargetObjectFile::CreateSectionForGlobal(const GlobalVariable *GV,
258 const std::string &Addr) const {
259 // See if this is an uninitialized global.
260 const Constant *C = GV->getInitializer();
261 if (C->isNullValue())
262 return CreateBSSSectionForGlobal(GV, Addr);
264 // If this is initialized data in RAM. Put it in the correct IDATA section.
265 if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
266 return CreateIDATASectionForGlobal(GV, Addr);
268 // This is initialized data in rom, put it in the readonly section.
269 if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
270 return CreateROSectionForGlobal(GV, Addr);
272 // Else let the default implementation take care of it.
273 return TargetLoweringObjectFile::SectionForGlobal(GV, Mang, *TM);
276 // Create uninitialized section for a variable.
278 PIC16TargetObjectFile::CreateBSSSectionForGlobal(const GlobalVariable *GV,
279 std::string Addr) const {
280 assert(GV->hasInitializer() && "This global doesn't need space");
281 assert(GV->getInitializer()->isNullValue() &&
282 "Unitialized global has non-zero initializer");
284 // If address is given then create a section at that address else create a
285 // section by section name specified in GV.
286 PIC16Section *FoundBSS = NULL;
288 Name = GV->getSection() + " UDATA";
289 for (unsigned i = 0; i < BSSSections.size(); i++) {
290 if (BSSSections[i]->S_->getName() == Name) {
291 FoundBSS = BSSSections[i];
296 std::string Prefix = GV->getNameStr() + "." + Addr + ".";
297 Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
300 PIC16Section *NewBSS = FoundBSS;
301 if (NewBSS == NULL) {
302 const MCSection *NewSection = getOrCreateSection(Name.c_str(), false,
303 SectionKind::get(SectionKind::BSS));
304 NewBSS = new PIC16Section(NewSection);
305 BSSSections.push_back(NewBSS);
308 // Insert the GV into this BSS.
309 NewBSS->Items.push_back(GV);
311 // We do not want to put any GV without explicit section into this section
312 // so set its size to DatabankSize.
313 NewBSS->Size = DataBankSize;
317 // Get rom section for a variable. Currently there can be only one rom section
318 // unless a variable explicitly requests a section.
320 PIC16TargetObjectFile::getROSectionForGlobal(const GlobalVariable *GV) const {
321 ROSections[0]->Items.push_back(GV);
322 return ROSections[0]->S_;
325 // Create initialized data section for a variable.
327 PIC16TargetObjectFile::CreateIDATASectionForGlobal(const GlobalVariable *GV,
328 std::string Addr) const {
329 assert(GV->hasInitializer() && "This global doesn't need space");
330 assert(!GV->getInitializer()->isNullValue() &&
331 "initialized global has zero initializer");
332 assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
333 "can be used for initialized RAM data only");
336 // If address is given then create a section at that address else create a
337 // section by section name specified in GV.
338 PIC16Section *FoundIDATASec = NULL;
340 Name = GV->getSection() + " IDATA";
341 for (unsigned i = 0; i < IDATASections.size(); i++) {
342 if (IDATASections[i]->S_->getName() == Name) {
343 FoundIDATASec = IDATASections[i];
348 std::string Prefix = GV->getNameStr() + "." + Addr + ".";
349 Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
352 PIC16Section *NewIDATASec = FoundIDATASec;
353 if (NewIDATASec == NULL) {
354 const MCSection *NewSection = getOrCreateSection(Name.c_str(), false,
356 SectionKind::get(SectionKind::Metadata));
357 NewIDATASec = new PIC16Section(NewSection);
358 IDATASections.push_back(NewIDATASec);
360 // Insert the GV into this IDATA Section.
361 NewIDATASec->Items.push_back(GV);
362 // We do not want to put any GV without explicit section into this section
363 // so set its size to DatabankSize.
364 NewIDATASec->Size = DataBankSize;
365 return NewIDATASec->S_;
368 // Create a section in rom for a variable.
370 PIC16TargetObjectFile::CreateROSectionForGlobal(const GlobalVariable *GV,
371 std::string Addr) const {
372 assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
373 "can be used for ROM data only");
376 // If address is given then create a section at that address else create a
377 // section by section name specified in GV.
378 PIC16Section *FoundROSec = NULL;
380 Name = GV->getSection() + " ROMDATA";
381 for (unsigned i = 1; i < ROSections.size(); i++) {
382 if (ROSections[i]->S_->getName() == Name) {
383 FoundROSec = ROSections[i];
388 std::string Prefix = GV->getNameStr() + "." + Addr + ".";
389 Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
392 PIC16Section *NewRomSec = FoundROSec;
393 if (NewRomSec == NULL) {
394 const MCSection *NewSection = getOrCreateSection(Name.c_str(), false,
395 SectionKind::get(SectionKind::ReadOnly));
396 NewRomSec = new PIC16Section(NewSection);
397 ROSections.push_back(NewRomSec);
400 // Insert the GV into this ROM Section.
401 NewRomSec->Items.push_back(GV);
402 return NewRomSec->S_;