blob: ed1caf225e2f3bcc3e2c9aad61bfae0fd07cd2f0 [file] [log] [blame]
Chris Lattnerf0144122009-07-28 03:13:23 +00001//===-- 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"
Chris Lattnerf7427e52009-08-08 21:37:01 +000011#include "PIC16Section.h"
Chris Lattnerf0144122009-07-28 03:13:23 +000012#include "PIC16ISelLowering.h"
13#include "PIC16TargetMachine.h"
14#include "llvm/DerivedTypes.h"
15#include "llvm/Module.h"
Chris Lattnera87dea42009-07-31 18:48:30 +000016#include "llvm/MC/MCSection.h"
Chris Lattnerfbf1d272009-08-08 20:14:13 +000017#include "llvm/MC/MCContext.h"
Chris Lattner93b6db32009-08-08 23:39:42 +000018#include "llvm/Support/raw_ostream.h"
Chris Lattnerf0144122009-07-28 03:13:23 +000019using namespace llvm;
20
Chris Lattner93b6db32009-08-08 23:39:42 +000021MCSectionPIC16::MCSectionPIC16(const StringRef &name, SectionKind K,
22 MCContext &Ctx) : MCSection(K), Name(name) {
23 Ctx.SetSection(Name, this);
24}
25
26MCSectionPIC16 *MCSectionPIC16::Create(const StringRef &Name,
27 SectionKind K, MCContext &Ctx) {
28 return new (Ctx) MCSectionPIC16(Name, K, Ctx);
29}
30
31
32void MCSectionPIC16::PrintSwitchToSection(const TargetAsmInfo &TAI,
33 raw_ostream &OS) const {
34 OS << getName() << '\n';
35}
36
37
38
39
Daniel Dunbar967ce7f2009-08-02 01:25:15 +000040PIC16TargetObjectFile::PIC16TargetObjectFile()
Chris Lattner759b8882009-08-06 16:27:28 +000041 : ExternalVarDecls(0), ExternalVarDefs(0) {
Daniel Dunbar967ce7f2009-08-02 01:25:15 +000042}
43
Chris Lattner93b6db32009-08-08 23:39:42 +000044const MCSectionPIC16 *PIC16TargetObjectFile::
45getPIC16Section(const char *Name, SectionKind Kind) const {
Chris Lattnerfbf1d272009-08-08 20:14:13 +000046 if (MCSection *S = getContext().GetSection(Name))
Chris Lattner93b6db32009-08-08 23:39:42 +000047 return (MCSectionPIC16*)S;
48 return MCSectionPIC16::Create(Name, Kind, getContext());
Chris Lattnerfbf1d272009-08-08 20:14:13 +000049}
50
51
Chris Lattnera87dea42009-07-31 18:48:30 +000052void PIC16TargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &tm){
53 TargetLoweringObjectFile::Initialize(Ctx, tm);
54 TM = &tm;
55
Chris Lattner93b6db32009-08-08 23:39:42 +000056 BSSSection = getPIC16Section("udata.# UDATA", SectionKind::getBSS());
57 ReadOnlySection = getPIC16Section("romdata.# ROMDATA",
Chris Lattner9aee1812009-08-08 20:23:47 +000058 SectionKind::getReadOnly());
Chris Lattner93b6db32009-08-08 23:39:42 +000059 DataSection = getPIC16Section("idata.# IDATA", SectionKind::getDataRel());
Chris Lattnerf0144122009-07-28 03:13:23 +000060
61 // Need because otherwise a .text symbol is emitted by DwarfWriter
62 // in BeginModule, and gpasm cribbs for that .text symbol.
Chris Lattner93b6db32009-08-08 23:39:42 +000063 TextSection = getPIC16Section("", SectionKind::getText());
Chris Lattnerf0144122009-07-28 03:13:23 +000064
Chris Lattner93b6db32009-08-08 23:39:42 +000065 ROSections.push_back(new PIC16Section((MCSectionPIC16*)ReadOnlySection));
Chris Lattnerf0144122009-07-28 03:13:23 +000066
67 // FIXME: I don't know what the classification of these sections really is.
Chris Lattner9aee1812009-08-08 20:23:47 +000068 ExternalVarDecls = new PIC16Section(getPIC16Section("ExternalVarDecls",
Chris Lattner1ef9be22009-08-02 00:02:44 +000069 SectionKind::getMetadata()));
Chris Lattner9aee1812009-08-08 20:23:47 +000070 ExternalVarDefs = new PIC16Section(getPIC16Section("ExternalVarDefs",
Chris Lattner1ef9be22009-08-02 00:02:44 +000071 SectionKind::getMetadata()));
Chris Lattnerf0144122009-07-28 03:13:23 +000072}
73
Chris Lattner759b8882009-08-06 16:27:28 +000074const MCSection *PIC16TargetObjectFile::
75getSectionForFunction(const std::string &FnName) const {
76 std::string T = PAN::getCodeSectionName(FnName);
Chris Lattner93b6db32009-08-08 23:39:42 +000077 return getPIC16Section(T.c_str(), SectionKind::getText());
Chris Lattner759b8882009-08-06 16:27:28 +000078}
79
80
81const MCSection *PIC16TargetObjectFile::
82getSectionForFunctionFrame(const std::string &FnName) const {
83 std::string T = PAN::getFrameSectionName(FnName);
Chris Lattner93b6db32009-08-08 23:39:42 +000084 return getPIC16Section(T.c_str(), SectionKind::getDataRel());
Chris Lattner759b8882009-08-06 16:27:28 +000085}
Chris Lattnerf0144122009-07-28 03:13:23 +000086
Chris Lattnera87dea42009-07-31 18:48:30 +000087const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +000088PIC16TargetObjectFile::getBSSSectionForGlobal(const GlobalVariable *GV) const {
89 assert(GV->hasInitializer() && "This global doesn't need space");
90 Constant *C = GV->getInitializer();
91 assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
92
93 // Find how much space this global needs.
Chris Lattnera87dea42009-07-31 18:48:30 +000094 const TargetData *TD = TM->getTargetData();
Chris Lattnerf0144122009-07-28 03:13:23 +000095 const Type *Ty = C->getType();
96 unsigned ValSize = TD->getTypeAllocSize(Ty);
97
98 // Go through all BSS Sections and assign this variable
99 // to the first available section having enough space.
100 PIC16Section *FoundBSS = NULL;
101 for (unsigned i = 0; i < BSSSections.size(); i++) {
102 if (DataBankSize - BSSSections[i]->Size >= ValSize) {
103 FoundBSS = BSSSections[i];
104 break;
105 }
106 }
107
108 // No BSS section spacious enough was found. Crate a new one.
109 if (!FoundBSS) {
110 std::string name = PAN::getUdataSectionName(BSSSections.size());
Chris Lattner93b6db32009-08-08 23:39:42 +0000111 const MCSectionPIC16 *NewSection
112 = getPIC16Section(name.c_str(), /*FIXME*/ SectionKind::getMetadata());
Chris Lattnerf0144122009-07-28 03:13:23 +0000113
114 FoundBSS = new PIC16Section(NewSection);
115
116 // Add this newly created BSS section to the list of BSSSections.
117 BSSSections.push_back(FoundBSS);
118 }
119
120 // Insert the GV into this BSS.
121 FoundBSS->Items.push_back(GV);
122 FoundBSS->Size += ValSize;
123 return FoundBSS->S_;
124}
125
Chris Lattnera87dea42009-07-31 18:48:30 +0000126const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +0000127PIC16TargetObjectFile::getIDATASectionForGlobal(const GlobalVariable *GV) const{
128 assert(GV->hasInitializer() && "This global doesn't need space");
129 Constant *C = GV->getInitializer();
130 assert(!C->isNullValue() && "initialized globals has zero initializer");
131 assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
132 "can split initialized RAM data only");
133
134 // Find how much space this global needs.
Chris Lattnera87dea42009-07-31 18:48:30 +0000135 const TargetData *TD = TM->getTargetData();
Chris Lattnerf0144122009-07-28 03:13:23 +0000136 const Type *Ty = C->getType();
137 unsigned ValSize = TD->getTypeAllocSize(Ty);
138
139 // Go through all IDATA Sections and assign this variable
140 // to the first available section having enough space.
141 PIC16Section *FoundIDATA = NULL;
142 for (unsigned i = 0; i < IDATASections.size(); i++) {
143 if (DataBankSize - IDATASections[i]->Size >= ValSize) {
144 FoundIDATA = IDATASections[i];
145 break;
146 }
147 }
148
149 // No IDATA section spacious enough was found. Crate a new one.
150 if (!FoundIDATA) {
151 std::string name = PAN::getIdataSectionName(IDATASections.size());
Chris Lattner93b6db32009-08-08 23:39:42 +0000152 const MCSectionPIC16 *NewSection =
153 getPIC16Section(name.c_str(), /*FIXME*/ SectionKind::getMetadata());
Chris Lattnerf0144122009-07-28 03:13:23 +0000154
155 FoundIDATA = new PIC16Section(NewSection);
156
157 // Add this newly created IDATA section to the list of IDATASections.
158 IDATASections.push_back(FoundIDATA);
159 }
160
161 // Insert the GV into this IDATA.
162 FoundIDATA->Items.push_back(GV);
163 FoundIDATA->Size += ValSize;
164 return FoundIDATA->S_;
165}
166
167// Get the section for an automatic variable of a function.
168// For PIC16 they are globals only with mangled names.
Chris Lattnera87dea42009-07-31 18:48:30 +0000169const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +0000170PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable *GV) const {
171
172 const std::string name = PAN::getSectionNameForSym(GV->getName());
173
174 // Go through all Auto Sections and assign this variable
175 // to the appropriate section.
176 PIC16Section *FoundAutoSec = NULL;
177 for (unsigned i = 0; i < AutosSections.size(); i++) {
178 if (AutosSections[i]->S_->getName() == name) {
179 FoundAutoSec = AutosSections[i];
180 break;
181 }
182 }
183
184 // No Auto section was found. Crate a new one.
185 if (!FoundAutoSec) {
Chris Lattner93b6db32009-08-08 23:39:42 +0000186 const MCSectionPIC16 *NewSection =
187 getPIC16Section(name.c_str(), /*FIXME*/ SectionKind::getMetadata());
Chris Lattnerf0144122009-07-28 03:13:23 +0000188
189 FoundAutoSec = new PIC16Section(NewSection);
190
191 // Add this newly created autos section to the list of AutosSections.
192 AutosSections.push_back(FoundAutoSec);
193 }
194
195 // Insert the auto into this section.
196 FoundAutoSec->Items.push_back(GV);
197
198 return FoundAutoSec->S_;
199}
200
201
202// Override default implementation to put the true globals into
203// multiple data sections if required.
Chris Lattnera87dea42009-07-31 18:48:30 +0000204const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +0000205PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1,
Chris Lattnerf9650c02009-08-01 21:46:23 +0000206 SectionKind Kind,
Chris Lattnere53a6002009-07-29 05:09:30 +0000207 Mangler *Mang,
Chris Lattnerf0144122009-07-28 03:13:23 +0000208 const TargetMachine &TM) const {
209 // We select the section based on the initializer here, so it really
210 // has to be a GlobalVariable.
211 const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
212 if (!GV)
Chris Lattnerf9650c02009-08-01 21:46:23 +0000213 return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Kind, Mang,TM);
Chris Lattnerf0144122009-07-28 03:13:23 +0000214
215 // Record External Var Decls.
216 if (GV->isDeclaration()) {
217 ExternalVarDecls->Items.push_back(GV);
218 return ExternalVarDecls->S_;
219 }
220
221 assert(GV->hasInitializer() && "A def without initializer?");
222
223 // First, if this is an automatic variable for a function, get the section
224 // name for it and return.
225 std::string name = GV->getName();
226 if (PAN::isLocalName(name))
227 return getSectionForAuto(GV);
228
229 // Record Exteranl Var Defs.
230 if (GV->hasExternalLinkage() || GV->hasCommonLinkage())
231 ExternalVarDefs->Items.push_back(GV);
232
233 // See if this is an uninitialized global.
234 const Constant *C = GV->getInitializer();
235 if (C->isNullValue())
236 return getBSSSectionForGlobal(GV);
237
238 // If this is initialized data in RAM. Put it in the correct IDATA section.
239 if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
240 return getIDATASectionForGlobal(GV);
241
242 // This is initialized data in rom, put it in the readonly section.
243 if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
244 return getROSectionForGlobal(GV);
245
246 // Else let the default implementation take care of it.
Chris Lattnerf9650c02009-08-01 21:46:23 +0000247 return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, Mang,TM);
Chris Lattnerf0144122009-07-28 03:13:23 +0000248}
249
250PIC16TargetObjectFile::~PIC16TargetObjectFile() {
251 for (unsigned i = 0; i < BSSSections.size(); i++)
252 delete BSSSections[i];
253 for (unsigned i = 0; i < IDATASections.size(); i++)
254 delete IDATASections[i];
255 for (unsigned i = 0; i < AutosSections.size(); i++)
256 delete AutosSections[i];
257 for (unsigned i = 0; i < ROSections.size(); i++)
258 delete ROSections[i];
259 delete ExternalVarDecls;
260 delete ExternalVarDefs;
261}
262
263
264/// getSpecialCasedSectionGlobals - Allow the target to completely override
265/// section assignment of a global.
Chris Lattner24f654c2009-08-06 16:39:58 +0000266const MCSection *PIC16TargetObjectFile::
267getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
268 Mangler *Mang, const TargetMachine &TM) const {
269 assert(GV->hasSection());
270
271 if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
272 std::string SectName = GVar->getSection();
273 // If address for a variable is specified, get the address and create
274 // section.
275 std::string AddrStr = "Address=";
276 if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
277 std::string SectAddr = SectName.substr(AddrStr.length());
278 return CreateSectionForGlobal(GVar, Mang, SectAddr);
Chris Lattnerf0144122009-07-28 03:13:23 +0000279 }
Chris Lattner24f654c2009-08-06 16:39:58 +0000280
281 // Create the section specified with section attribute.
282 return CreateSectionForGlobal(GVar, Mang);
Chris Lattnerf0144122009-07-28 03:13:23 +0000283 }
284
Chris Lattner93b6db32009-08-08 23:39:42 +0000285 return getPIC16Section(GV->getSection().c_str(), Kind);
Chris Lattnerf0144122009-07-28 03:13:23 +0000286}
287
288// Create a new section for global variable. If Addr is given then create
289// section at that address else create by name.
Chris Lattnera87dea42009-07-31 18:48:30 +0000290const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +0000291PIC16TargetObjectFile::CreateSectionForGlobal(const GlobalVariable *GV,
Chris Lattnere53a6002009-07-29 05:09:30 +0000292 Mangler *Mang,
Chris Lattnerf0144122009-07-28 03:13:23 +0000293 const std::string &Addr) const {
294 // See if this is an uninitialized global.
295 const Constant *C = GV->getInitializer();
296 if (C->isNullValue())
297 return CreateBSSSectionForGlobal(GV, Addr);
298
299 // If this is initialized data in RAM. Put it in the correct IDATA section.
300 if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
301 return CreateIDATASectionForGlobal(GV, Addr);
302
303 // This is initialized data in rom, put it in the readonly section.
304 if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
305 return CreateROSectionForGlobal(GV, Addr);
306
307 // Else let the default implementation take care of it.
Chris Lattnera87dea42009-07-31 18:48:30 +0000308 return TargetLoweringObjectFile::SectionForGlobal(GV, Mang, *TM);
Chris Lattnerf0144122009-07-28 03:13:23 +0000309}
310
311// Create uninitialized section for a variable.
Chris Lattnera87dea42009-07-31 18:48:30 +0000312const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +0000313PIC16TargetObjectFile::CreateBSSSectionForGlobal(const GlobalVariable *GV,
314 std::string Addr) const {
315 assert(GV->hasInitializer() && "This global doesn't need space");
316 assert(GV->getInitializer()->isNullValue() &&
317 "Unitialized global has non-zero initializer");
318 std::string Name;
319 // If address is given then create a section at that address else create a
320 // section by section name specified in GV.
321 PIC16Section *FoundBSS = NULL;
322 if (Addr.empty()) {
323 Name = GV->getSection() + " UDATA";
324 for (unsigned i = 0; i < BSSSections.size(); i++) {
325 if (BSSSections[i]->S_->getName() == Name) {
326 FoundBSS = BSSSections[i];
327 break;
328 }
329 }
330 } else {
331 std::string Prefix = GV->getNameStr() + "." + Addr + ".";
332 Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
333 }
334
335 PIC16Section *NewBSS = FoundBSS;
336 if (NewBSS == NULL) {
Chris Lattner93b6db32009-08-08 23:39:42 +0000337 const MCSectionPIC16 *NewSection =
338 getPIC16Section(Name.c_str(), SectionKind::getBSS());
Chris Lattnerf0144122009-07-28 03:13:23 +0000339 NewBSS = new PIC16Section(NewSection);
340 BSSSections.push_back(NewBSS);
341 }
342
343 // Insert the GV into this BSS.
344 NewBSS->Items.push_back(GV);
345
346 // We do not want to put any GV without explicit section into this section
347 // so set its size to DatabankSize.
348 NewBSS->Size = DataBankSize;
349 return NewBSS->S_;
350}
351
352// Get rom section for a variable. Currently there can be only one rom section
353// unless a variable explicitly requests a section.
Chris Lattnera87dea42009-07-31 18:48:30 +0000354const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +0000355PIC16TargetObjectFile::getROSectionForGlobal(const GlobalVariable *GV) const {
356 ROSections[0]->Items.push_back(GV);
357 return ROSections[0]->S_;
358}
359
360// Create initialized data section for a variable.
Chris Lattnera87dea42009-07-31 18:48:30 +0000361const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +0000362PIC16TargetObjectFile::CreateIDATASectionForGlobal(const GlobalVariable *GV,
363 std::string Addr) const {
364 assert(GV->hasInitializer() && "This global doesn't need space");
365 assert(!GV->getInitializer()->isNullValue() &&
366 "initialized global has zero initializer");
367 assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
368 "can be used for initialized RAM data only");
369
370 std::string Name;
371 // If address is given then create a section at that address else create a
372 // section by section name specified in GV.
373 PIC16Section *FoundIDATASec = NULL;
374 if (Addr.empty()) {
375 Name = GV->getSection() + " IDATA";
376 for (unsigned i = 0; i < IDATASections.size(); i++) {
377 if (IDATASections[i]->S_->getName() == Name) {
378 FoundIDATASec = IDATASections[i];
379 break;
380 }
381 }
382 } else {
383 std::string Prefix = GV->getNameStr() + "." + Addr + ".";
384 Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
385 }
386
387 PIC16Section *NewIDATASec = FoundIDATASec;
388 if (NewIDATASec == NULL) {
Chris Lattner93b6db32009-08-08 23:39:42 +0000389 const MCSectionPIC16 *NewSection =
390 getPIC16Section(Name.c_str(), /* FIXME */SectionKind::getMetadata());
Chris Lattnerf0144122009-07-28 03:13:23 +0000391 NewIDATASec = new PIC16Section(NewSection);
392 IDATASections.push_back(NewIDATASec);
393 }
394 // Insert the GV into this IDATA Section.
395 NewIDATASec->Items.push_back(GV);
396 // We do not want to put any GV without explicit section into this section
397 // so set its size to DatabankSize.
398 NewIDATASec->Size = DataBankSize;
399 return NewIDATASec->S_;
400}
401
402// Create a section in rom for a variable.
Chris Lattnera87dea42009-07-31 18:48:30 +0000403const MCSection *
Chris Lattnerf0144122009-07-28 03:13:23 +0000404PIC16TargetObjectFile::CreateROSectionForGlobal(const GlobalVariable *GV,
405 std::string Addr) const {
406 assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
407 "can be used for ROM data only");
408
409 std::string Name;
410 // If address is given then create a section at that address else create a
411 // section by section name specified in GV.
412 PIC16Section *FoundROSec = NULL;
413 if (Addr.empty()) {
414 Name = GV->getSection() + " ROMDATA";
415 for (unsigned i = 1; i < ROSections.size(); i++) {
416 if (ROSections[i]->S_->getName() == Name) {
417 FoundROSec = ROSections[i];
418 break;
419 }
420 }
421 } else {
422 std::string Prefix = GV->getNameStr() + "." + Addr + ".";
423 Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
424 }
425
426 PIC16Section *NewRomSec = FoundROSec;
427 if (NewRomSec == NULL) {
Chris Lattner93b6db32009-08-08 23:39:42 +0000428 const MCSectionPIC16 *NewSection =
429 getPIC16Section(Name.c_str(), SectionKind::getReadOnly());
Chris Lattnerf0144122009-07-28 03:13:23 +0000430 NewRomSec = new PIC16Section(NewSection);
431 ROSections.push_back(NewRomSec);
432 }
433
434 // Insert the GV into this ROM Section.
435 NewRomSec->Items.push_back(GV);
436 return NewRomSec->S_;
437}
438