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 "MCSectionPIC16.h"
12 #include "PIC16ISelLowering.h"
13 #include "PIC16TargetMachine.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"
22 MCSectionPIC16
*MCSectionPIC16::Create(const StringRef
&Name
, SectionKind K
,
23 int Address
, int Color
, MCContext
&Ctx
) {
24 return new (Ctx
) MCSectionPIC16(Name
, K
, Address
, Color
);
28 void MCSectionPIC16::PrintSwitchToSection(const MCAsmInfo
&MAI
,
29 raw_ostream
&OS
) const {
30 OS
<< getName() << '\n';
36 PIC16TargetObjectFile::PIC16TargetObjectFile()
37 : ExternalVarDecls(0), ExternalVarDefs(0) {
40 const MCSectionPIC16
*PIC16TargetObjectFile::
41 getPIC16Section(const char *Name
, SectionKind Kind
,
42 int Address
, int Color
) const {
43 MCSectionPIC16
*&Entry
= SectionsByName
[Name
];
47 return Entry
= MCSectionPIC16::Create(Name
, Kind
, Address
, Color
,
52 void PIC16TargetObjectFile::Initialize(MCContext
&Ctx
, const TargetMachine
&tm
){
53 TargetLoweringObjectFile::Initialize(Ctx
, tm
);
56 BSSSection
= getPIC16Section("udata.# UDATA", MCSectionPIC16::UDATA_Kind());
57 ReadOnlySection
= getPIC16Section("romdata.# ROMDATA",
58 MCSectionPIC16::ROMDATA_Kind());
59 DataSection
= getPIC16Section("idata.# IDATA", MCSectionPIC16::IDATA_Kind());
61 // Need because otherwise a .text symbol is emitted by DwarfWriter
62 // in BeginModule, and gpasm cribbs for that .text symbol.
63 TextSection
= getPIC16Section("", SectionKind::getText());
65 ROSections
.push_back(new PIC16Section((MCSectionPIC16
*)ReadOnlySection
));
67 // FIXME: I don't know what the classification of these sections really is.
68 // These aren't really objects belonging to any section. Just emit them
69 // in AsmPrinter and remove this code from here.
70 ExternalVarDecls
= new PIC16Section(getPIC16Section("ExternalVarDecls",
71 SectionKind::getMetadata()));
72 ExternalVarDefs
= new PIC16Section(getPIC16Section("ExternalVarDefs",
73 SectionKind::getMetadata()));
76 const MCSection
*PIC16TargetObjectFile::
77 getSectionForFunction(const std::string
&FnName
) const {
78 std::string T
= PAN::getCodeSectionName(FnName
);
79 return getPIC16Section(T
.c_str(), SectionKind::getText());
83 const MCSection
*PIC16TargetObjectFile::
84 getSectionForFunctionFrame(const std::string
&FnName
) const {
85 std::string T
= PAN::getFrameSectionName(FnName
);
86 return getPIC16Section(T
.c_str(), SectionKind::getDataRel());
90 PIC16TargetObjectFile::getBSSSectionForGlobal(const GlobalVariable
*GV
) const {
91 assert(GV
->hasInitializer() && "This global doesn't need space");
92 Constant
*C
= GV
->getInitializer();
93 assert(C
->isNullValue() && "Unitialized globals has non-zero initializer");
95 // Find how much space this global needs.
96 const TargetData
*TD
= TM
->getTargetData();
97 const Type
*Ty
= C
->getType();
98 unsigned ValSize
= TD
->getTypeAllocSize(Ty
);
100 // Go through all BSS Sections and assign this variable
101 // to the first available section having enough space.
102 PIC16Section
*FoundBSS
= NULL
;
103 for (unsigned i
= 0; i
< BSSSections
.size(); i
++) {
104 if (DataBankSize
- BSSSections
[i
]->Size
>= ValSize
) {
105 FoundBSS
= BSSSections
[i
];
110 // No BSS section spacious enough was found. Crate a new one.
112 std::string name
= PAN::getUdataSectionName(BSSSections
.size());
113 const MCSectionPIC16
*NewSection
114 = getPIC16Section(name
.c_str(), MCSectionPIC16::UDATA_Kind());
116 FoundBSS
= new PIC16Section(NewSection
);
118 // Add this newly created BSS section to the list of BSSSections.
119 BSSSections
.push_back(FoundBSS
);
122 // Insert the GV into this BSS.
123 FoundBSS
->Items
.push_back(GV
);
124 FoundBSS
->Size
+= ValSize
;
129 PIC16TargetObjectFile::getIDATASectionForGlobal(const GlobalVariable
*GV
) const{
130 assert(GV
->hasInitializer() && "This global doesn't need space");
131 Constant
*C
= GV
->getInitializer();
132 assert(!C
->isNullValue() && "initialized globals has zero initializer");
133 assert(GV
->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE
&&
134 "can split initialized RAM data only");
136 // Find how much space this global needs.
137 const TargetData
*TD
= TM
->getTargetData();
138 const Type
*Ty
= C
->getType();
139 unsigned ValSize
= TD
->getTypeAllocSize(Ty
);
141 // Go through all IDATA Sections and assign this variable
142 // to the first available section having enough space.
143 PIC16Section
*FoundIDATA
= NULL
;
144 for (unsigned i
= 0; i
< IDATASections
.size(); i
++) {
145 if (DataBankSize
- IDATASections
[i
]->Size
>= ValSize
) {
146 FoundIDATA
= IDATASections
[i
];
151 // No IDATA section spacious enough was found. Crate a new one.
153 std::string name
= PAN::getIdataSectionName(IDATASections
.size());
154 const MCSectionPIC16
*NewSection
=
155 getPIC16Section(name
.c_str(), MCSectionPIC16::IDATA_Kind());
157 FoundIDATA
= new PIC16Section(NewSection
);
159 // Add this newly created IDATA section to the list of IDATASections.
160 IDATASections
.push_back(FoundIDATA
);
163 // Insert the GV into this IDATA.
164 FoundIDATA
->Items
.push_back(GV
);
165 FoundIDATA
->Size
+= ValSize
;
166 return FoundIDATA
->S_
;
169 // Get the section for an automatic variable of a function.
170 // For PIC16 they are globals only with mangled names.
172 PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable
*GV
) const {
174 const std::string name
= PAN::getSectionNameForSym(GV
->getName());
176 // Go through all Auto Sections and assign this variable
177 // to the appropriate section.
178 PIC16Section
*FoundAutoSec
= NULL
;
179 for (unsigned i
= 0; i
< AutosSections
.size(); i
++) {
180 if (AutosSections
[i
]->S_
->getName() == name
) {
181 FoundAutoSec
= AutosSections
[i
];
186 // No Auto section was found. Crate a new one.
188 const MCSectionPIC16
*NewSection
=
189 getPIC16Section(name
.c_str(), MCSectionPIC16::UDATA_OVR_Kind());
191 FoundAutoSec
= new PIC16Section(NewSection
);
193 // Add this newly created autos section to the list of AutosSections.
194 AutosSections
.push_back(FoundAutoSec
);
197 // Insert the auto into this section.
198 FoundAutoSec
->Items
.push_back(GV
);
200 return FoundAutoSec
->S_
;
204 // Override default implementation to put the true globals into
205 // multiple data sections if required.
207 PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue
*GV1
,
210 const TargetMachine
&TM
) const {
211 // We select the section based on the initializer here, so it really
212 // has to be a GlobalVariable.
213 const GlobalVariable
*GV
= dyn_cast
<GlobalVariable
>(GV1
);
215 return TargetLoweringObjectFile::SelectSectionForGlobal(GV1
, Kind
, Mang
,TM
);
217 // Record External Var Decls.
218 if (GV
->isDeclaration()) {
219 ExternalVarDecls
->Items
.push_back(GV
);
220 return ExternalVarDecls
->S_
;
223 assert(GV
->hasInitializer() && "A def without initializer?");
225 // First, if this is an automatic variable for a function, get the section
226 // name for it and return.
227 std::string name
= GV
->getName();
228 if (PAN::isLocalName(name
))
229 return getSectionForAuto(GV
);
231 // Record Exteranl Var Defs.
232 if (GV
->hasExternalLinkage() || GV
->hasCommonLinkage())
233 ExternalVarDefs
->Items
.push_back(GV
);
235 // See if this is an uninitialized global.
236 const Constant
*C
= GV
->getInitializer();
237 if (C
->isNullValue())
238 return getBSSSectionForGlobal(GV
);
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 getIDATASectionForGlobal(GV
);
244 // This is initialized data in rom, put it in the readonly section.
245 if (GV
->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE
)
246 return getROSectionForGlobal(GV
);
248 // Else let the default implementation take care of it.
249 return TargetLoweringObjectFile::SelectSectionForGlobal(GV
, Kind
, Mang
,TM
);
252 PIC16TargetObjectFile::~PIC16TargetObjectFile() {
253 for (unsigned i
= 0; i
< BSSSections
.size(); i
++)
254 delete BSSSections
[i
];
255 for (unsigned i
= 0; i
< IDATASections
.size(); i
++)
256 delete IDATASections
[i
];
257 for (unsigned i
= 0; i
< AutosSections
.size(); i
++)
258 delete AutosSections
[i
];
259 for (unsigned i
= 0; i
< ROSections
.size(); i
++)
260 delete ROSections
[i
];
261 delete ExternalVarDecls
;
262 delete ExternalVarDefs
;
266 /// getSpecialCasedSectionGlobals - Allow the target to completely override
267 /// section assignment of a global.
268 const MCSection
*PIC16TargetObjectFile::
269 getExplicitSectionGlobal(const GlobalValue
*GV
, SectionKind Kind
,
270 Mangler
*Mang
, const TargetMachine
&TM
) const {
271 assert(GV
->hasSection());
273 if (const GlobalVariable
*GVar
= cast
<GlobalVariable
>(GV
)) {
274 std::string SectName
= GVar
->getSection();
275 // If address for a variable is specified, get the address and create
277 std::string AddrStr
= "Address=";
278 if (SectName
.compare(0, AddrStr
.length(), AddrStr
) == 0) {
279 std::string SectAddr
= SectName
.substr(AddrStr
.length());
280 return CreateSectionForGlobal(GVar
, Mang
, SectAddr
);
283 // Create the section specified with section attribute.
284 return CreateSectionForGlobal(GVar
, Mang
);
287 return getPIC16Section(GV
->getSection().c_str(), Kind
);
290 // Create a new section for global variable. If Addr is given then create
291 // section at that address else create by name.
293 PIC16TargetObjectFile::CreateSectionForGlobal(const GlobalVariable
*GV
,
295 const std::string
&Addr
) const {
296 // See if this is an uninitialized global.
297 const Constant
*C
= GV
->getInitializer();
298 if (C
->isNullValue())
299 return CreateBSSSectionForGlobal(GV
, Addr
);
301 // If this is initialized data in RAM. Put it in the correct IDATA section.
302 if (GV
->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE
)
303 return CreateIDATASectionForGlobal(GV
, Addr
);
305 // This is initialized data in rom, put it in the readonly section.
306 if (GV
->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE
)
307 return CreateROSectionForGlobal(GV
, Addr
);
309 // Else let the default implementation take care of it.
310 return TargetLoweringObjectFile::SectionForGlobal(GV
, Mang
, *TM
);
313 // Create uninitialized section for a variable.
315 PIC16TargetObjectFile::CreateBSSSectionForGlobal(const GlobalVariable
*GV
,
316 std::string Addr
) const {
317 assert(GV
->hasInitializer() && "This global doesn't need space");
318 assert(GV
->getInitializer()->isNullValue() &&
319 "Unitialized global has non-zero initializer");
321 // If address is given then create a section at that address else create a
322 // section by section name specified in GV.
323 PIC16Section
*FoundBSS
= NULL
;
325 Name
= GV
->getSection() + " UDATA";
326 for (unsigned i
= 0; i
< BSSSections
.size(); i
++) {
327 if (BSSSections
[i
]->S_
->getName() == Name
) {
328 FoundBSS
= BSSSections
[i
];
333 std::string Prefix
= GV
->getNameStr() + "." + Addr
+ ".";
334 Name
= PAN::getUdataSectionName(BSSSections
.size(), Prefix
) + " " + Addr
;
337 PIC16Section
*NewBSS
= FoundBSS
;
338 if (NewBSS
== NULL
) {
339 const MCSectionPIC16
*NewSection
=
340 getPIC16Section(Name
.c_str(), MCSectionPIC16::UDATA_Kind());
341 NewBSS
= new PIC16Section(NewSection
);
342 BSSSections
.push_back(NewBSS
);
345 // Insert the GV into this BSS.
346 NewBSS
->Items
.push_back(GV
);
348 // We do not want to put any GV without explicit section into this section
349 // so set its size to DatabankSize.
350 NewBSS
->Size
= DataBankSize
;
354 // Get rom section for a variable. Currently there can be only one rom section
355 // unless a variable explicitly requests a section.
357 PIC16TargetObjectFile::getROSectionForGlobal(const GlobalVariable
*GV
) const {
358 ROSections
[0]->Items
.push_back(GV
);
359 return ROSections
[0]->S_
;
362 // Create initialized data section for a variable.
364 PIC16TargetObjectFile::CreateIDATASectionForGlobal(const GlobalVariable
*GV
,
365 std::string Addr
) const {
366 assert(GV
->hasInitializer() && "This global doesn't need space");
367 assert(!GV
->getInitializer()->isNullValue() &&
368 "initialized global has zero initializer");
369 assert(GV
->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE
&&
370 "can be used for initialized RAM data only");
373 // If address is given then create a section at that address else create a
374 // section by section name specified in GV.
375 PIC16Section
*FoundIDATASec
= NULL
;
377 Name
= GV
->getSection() + " IDATA";
378 for (unsigned i
= 0; i
< IDATASections
.size(); i
++) {
379 if (IDATASections
[i
]->S_
->getName() == Name
) {
380 FoundIDATASec
= IDATASections
[i
];
385 std::string Prefix
= GV
->getNameStr() + "." + Addr
+ ".";
386 Name
= PAN::getIdataSectionName(IDATASections
.size(), Prefix
) + " " + Addr
;
389 PIC16Section
*NewIDATASec
= FoundIDATASec
;
390 if (NewIDATASec
== NULL
) {
391 const MCSectionPIC16
*NewSection
=
392 getPIC16Section(Name
.c_str(), MCSectionPIC16::IDATA_Kind());
393 NewIDATASec
= new PIC16Section(NewSection
);
394 IDATASections
.push_back(NewIDATASec
);
396 // Insert the GV into this IDATA Section.
397 NewIDATASec
->Items
.push_back(GV
);
398 // We do not want to put any GV without explicit section into this section
399 // so set its size to DatabankSize.
400 NewIDATASec
->Size
= DataBankSize
;
401 return NewIDATASec
->S_
;
404 // Create a section in rom for a variable.
406 PIC16TargetObjectFile::CreateROSectionForGlobal(const GlobalVariable
*GV
,
407 std::string Addr
) const {
408 assert(GV
->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE
&&
409 "can be used for ROM data only");
412 // If address is given then create a section at that address else create a
413 // section by section name specified in GV.
414 PIC16Section
*FoundROSec
= NULL
;
416 Name
= GV
->getSection() + " ROMDATA";
417 for (unsigned i
= 1; i
< ROSections
.size(); i
++) {
418 if (ROSections
[i
]->S_
->getName() == Name
) {
419 FoundROSec
= ROSections
[i
];
424 std::string Prefix
= GV
->getNameStr() + "." + Addr
+ ".";
425 Name
= PAN::getRomdataSectionName(ROSections
.size(), Prefix
) + " " + Addr
;
428 PIC16Section
*NewRomSec
= FoundROSec
;
429 if (NewRomSec
== NULL
) {
430 const MCSectionPIC16
*NewSection
=
431 getPIC16Section(Name
.c_str(), MCSectionPIC16::ROMDATA_Kind());
432 NewRomSec
= new PIC16Section(NewSection
);
433 ROSections
.push_back(NewRomSec
);
436 // Insert the GV into this ROM Section.
437 NewRomSec
->Items
.push_back(GV
);
438 return NewRomSec
->S_
;