mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-08 23:55:03 +00:00
it is highly specific to the object file that will be generated in the end, this introduces a new TargetLoweringObjectFile interface that is implemented for each of ELF/MachO/COFF/Alpha/PIC16 and XCore. Though still is still a brutal and ugly refactoring, this is a major step towards goodness. This patch also: 1. fixes a bunch of dangling pointer problems in the PIC16 backend. 2. disables the TargetLowering copy ctor which PIC16 was accidentally using. 3. gets us closer to xcore having its own crazy target section flags and pic16 not having to shadow sections with its own objects. 4. fixes wierdness where ELF targets would set CStringSection but not CStringSection_. Factor the code better. 5. fixes some bugs in string lowering on ELF targets. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77294 91177308-0d34-0410-b5e6-96231b3b80d8
402 lines
15 KiB
C++
402 lines
15 KiB
C++
//===-- PIC16TargetObjectFile.cpp - PIC16 object files --------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "PIC16TargetObjectFile.h"
|
|
#include "PIC16ISelLowering.h"
|
|
#include "PIC16TargetMachine.h"
|
|
#include "llvm/DerivedTypes.h"
|
|
#include "llvm/Module.h"
|
|
using namespace llvm;
|
|
|
|
|
|
PIC16TargetObjectFile::PIC16TargetObjectFile(const PIC16TargetMachine &tm)
|
|
: TM (tm) {
|
|
BSSSection_ = getOrCreateSection("udata.# UDATA", false, SectionKind::BSS);
|
|
ReadOnlySection = getOrCreateSection("romdata.# ROMDATA", false,
|
|
SectionKind::ReadOnly);
|
|
DataSection = getOrCreateSection("idata.# IDATA", false,SectionKind::DataRel);
|
|
|
|
// Need because otherwise a .text symbol is emitted by DwarfWriter
|
|
// in BeginModule, and gpasm cribbs for that .text symbol.
|
|
TextSection = getOrCreateSection("", true, SectionKind::Text);
|
|
|
|
|
|
PIC16Section *ROSection = new PIC16Section(ReadOnlySection);
|
|
ROSections.push_back(ROSection);
|
|
|
|
// FIXME: I don't know what the classification of these sections really is.
|
|
ExternalVarDecls = new PIC16Section(getOrCreateSection("ExternalVarDecls",
|
|
false,
|
|
SectionKind::Metadata));
|
|
ExternalVarDefs = new PIC16Section(getOrCreateSection("ExternalVarDefs",
|
|
false,
|
|
SectionKind::Metadata));
|
|
}
|
|
|
|
|
|
const Section *
|
|
PIC16TargetObjectFile::getBSSSectionForGlobal(const GlobalVariable *GV) const {
|
|
assert(GV->hasInitializer() && "This global doesn't need space");
|
|
Constant *C = GV->getInitializer();
|
|
assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
|
|
|
|
// Find how much space this global needs.
|
|
const TargetData *TD = TM.getTargetData();
|
|
const Type *Ty = C->getType();
|
|
unsigned ValSize = TD->getTypeAllocSize(Ty);
|
|
|
|
// Go through all BSS Sections and assign this variable
|
|
// to the first available section having enough space.
|
|
PIC16Section *FoundBSS = NULL;
|
|
for (unsigned i = 0; i < BSSSections.size(); i++) {
|
|
if (DataBankSize - BSSSections[i]->Size >= ValSize) {
|
|
FoundBSS = BSSSections[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// No BSS section spacious enough was found. Crate a new one.
|
|
if (!FoundBSS) {
|
|
std::string name = PAN::getUdataSectionName(BSSSections.size());
|
|
const Section *NewSection = getOrCreateSection(name.c_str(), false,
|
|
// FIXME.
|
|
SectionKind::Metadata);
|
|
|
|
FoundBSS = new PIC16Section(NewSection);
|
|
|
|
// Add this newly created BSS section to the list of BSSSections.
|
|
BSSSections.push_back(FoundBSS);
|
|
}
|
|
|
|
// Insert the GV into this BSS.
|
|
FoundBSS->Items.push_back(GV);
|
|
FoundBSS->Size += ValSize;
|
|
return FoundBSS->S_;
|
|
}
|
|
|
|
const Section *
|
|
PIC16TargetObjectFile::getIDATASectionForGlobal(const GlobalVariable *GV) const{
|
|
assert(GV->hasInitializer() && "This global doesn't need space");
|
|
Constant *C = GV->getInitializer();
|
|
assert(!C->isNullValue() && "initialized globals has zero initializer");
|
|
assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
|
|
"can split initialized RAM data only");
|
|
|
|
// Find how much space this global needs.
|
|
const TargetData *TD = TM.getTargetData();
|
|
const Type *Ty = C->getType();
|
|
unsigned ValSize = TD->getTypeAllocSize(Ty);
|
|
|
|
// Go through all IDATA Sections and assign this variable
|
|
// to the first available section having enough space.
|
|
PIC16Section *FoundIDATA = NULL;
|
|
for (unsigned i = 0; i < IDATASections.size(); i++) {
|
|
if (DataBankSize - IDATASections[i]->Size >= ValSize) {
|
|
FoundIDATA = IDATASections[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// No IDATA section spacious enough was found. Crate a new one.
|
|
if (!FoundIDATA) {
|
|
std::string name = PAN::getIdataSectionName(IDATASections.size());
|
|
const Section *NewSection = getOrCreateSection(name.c_str(),
|
|
false,
|
|
// FIXME.
|
|
SectionKind::Metadata);
|
|
|
|
FoundIDATA = new PIC16Section(NewSection);
|
|
|
|
// Add this newly created IDATA section to the list of IDATASections.
|
|
IDATASections.push_back(FoundIDATA);
|
|
}
|
|
|
|
// Insert the GV into this IDATA.
|
|
FoundIDATA->Items.push_back(GV);
|
|
FoundIDATA->Size += ValSize;
|
|
return FoundIDATA->S_;
|
|
}
|
|
|
|
// Get the section for an automatic variable of a function.
|
|
// For PIC16 they are globals only with mangled names.
|
|
const Section *
|
|
PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable *GV) const {
|
|
|
|
const std::string name = PAN::getSectionNameForSym(GV->getName());
|
|
|
|
// Go through all Auto Sections and assign this variable
|
|
// to the appropriate section.
|
|
PIC16Section *FoundAutoSec = NULL;
|
|
for (unsigned i = 0; i < AutosSections.size(); i++) {
|
|
if (AutosSections[i]->S_->getName() == name) {
|
|
FoundAutoSec = AutosSections[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// No Auto section was found. Crate a new one.
|
|
if (!FoundAutoSec) {
|
|
const Section *NewSection = getOrCreateSection(name.c_str(),
|
|
// FIXME.
|
|
false,
|
|
SectionKind::Metadata);
|
|
|
|
FoundAutoSec = new PIC16Section(NewSection);
|
|
|
|
// Add this newly created autos section to the list of AutosSections.
|
|
AutosSections.push_back(FoundAutoSec);
|
|
}
|
|
|
|
// Insert the auto into this section.
|
|
FoundAutoSec->Items.push_back(GV);
|
|
|
|
return FoundAutoSec->S_;
|
|
}
|
|
|
|
|
|
// Override default implementation to put the true globals into
|
|
// multiple data sections if required.
|
|
const Section*
|
|
PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1,
|
|
SectionKind Kind,
|
|
const TargetMachine &TM) const {
|
|
// We select the section based on the initializer here, so it really
|
|
// has to be a GlobalVariable.
|
|
const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
|
|
if (!GV)
|
|
return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Kind, TM);
|
|
|
|
// Record External Var Decls.
|
|
if (GV->isDeclaration()) {
|
|
ExternalVarDecls->Items.push_back(GV);
|
|
return ExternalVarDecls->S_;
|
|
}
|
|
|
|
assert(GV->hasInitializer() && "A def without initializer?");
|
|
|
|
// First, if this is an automatic variable for a function, get the section
|
|
// name for it and return.
|
|
std::string name = GV->getName();
|
|
if (PAN::isLocalName(name))
|
|
return getSectionForAuto(GV);
|
|
|
|
// Record Exteranl Var Defs.
|
|
if (GV->hasExternalLinkage() || GV->hasCommonLinkage())
|
|
ExternalVarDefs->Items.push_back(GV);
|
|
|
|
// See if this is an uninitialized global.
|
|
const Constant *C = GV->getInitializer();
|
|
if (C->isNullValue())
|
|
return getBSSSectionForGlobal(GV);
|
|
|
|
// If this is initialized data in RAM. Put it in the correct IDATA section.
|
|
if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
|
|
return getIDATASectionForGlobal(GV);
|
|
|
|
// This is initialized data in rom, put it in the readonly section.
|
|
if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
|
|
return getROSectionForGlobal(GV);
|
|
|
|
// Else let the default implementation take care of it.
|
|
return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, TM);
|
|
}
|
|
|
|
PIC16TargetObjectFile::~PIC16TargetObjectFile() {
|
|
for (unsigned i = 0; i < BSSSections.size(); i++)
|
|
delete BSSSections[i];
|
|
for (unsigned i = 0; i < IDATASections.size(); i++)
|
|
delete IDATASections[i];
|
|
for (unsigned i = 0; i < AutosSections.size(); i++)
|
|
delete AutosSections[i];
|
|
for (unsigned i = 0; i < ROSections.size(); i++)
|
|
delete ROSections[i];
|
|
delete ExternalVarDecls;
|
|
delete ExternalVarDefs;
|
|
}
|
|
|
|
|
|
/// getSpecialCasedSectionGlobals - Allow the target to completely override
|
|
/// section assignment of a global.
|
|
const Section *
|
|
PIC16TargetObjectFile::getSpecialCasedSectionGlobals(const GlobalValue *GV,
|
|
SectionKind Kind) const {
|
|
// If GV has a sectin name or section address create that section now.
|
|
if (GV->hasSection()) {
|
|
if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
|
|
std::string SectName = GVar->getSection();
|
|
// If address for a variable is specified, get the address and create
|
|
// section.
|
|
std::string AddrStr = "Address=";
|
|
if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
|
|
std::string SectAddr = SectName.substr(AddrStr.length());
|
|
return CreateSectionForGlobal(GVar, SectAddr);
|
|
}
|
|
|
|
// Create the section specified with section attribute.
|
|
return CreateSectionForGlobal(GVar);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Create a new section for global variable. If Addr is given then create
|
|
// section at that address else create by name.
|
|
const Section *
|
|
PIC16TargetObjectFile::CreateSectionForGlobal(const GlobalVariable *GV,
|
|
const std::string &Addr) const {
|
|
// See if this is an uninitialized global.
|
|
const Constant *C = GV->getInitializer();
|
|
if (C->isNullValue())
|
|
return CreateBSSSectionForGlobal(GV, Addr);
|
|
|
|
// If this is initialized data in RAM. Put it in the correct IDATA section.
|
|
if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
|
|
return CreateIDATASectionForGlobal(GV, Addr);
|
|
|
|
// This is initialized data in rom, put it in the readonly section.
|
|
if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
|
|
return CreateROSectionForGlobal(GV, Addr);
|
|
|
|
// Else let the default implementation take care of it.
|
|
return TargetLoweringObjectFile::SectionForGlobal(GV, TM);
|
|
}
|
|
|
|
// Create uninitialized section for a variable.
|
|
const Section *
|
|
PIC16TargetObjectFile::CreateBSSSectionForGlobal(const GlobalVariable *GV,
|
|
std::string Addr) const {
|
|
assert(GV->hasInitializer() && "This global doesn't need space");
|
|
assert(GV->getInitializer()->isNullValue() &&
|
|
"Unitialized global has non-zero initializer");
|
|
std::string Name;
|
|
// If address is given then create a section at that address else create a
|
|
// section by section name specified in GV.
|
|
PIC16Section *FoundBSS = NULL;
|
|
if (Addr.empty()) {
|
|
Name = GV->getSection() + " UDATA";
|
|
for (unsigned i = 0; i < BSSSections.size(); i++) {
|
|
if (BSSSections[i]->S_->getName() == Name) {
|
|
FoundBSS = BSSSections[i];
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
|
|
Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr;
|
|
}
|
|
|
|
PIC16Section *NewBSS = FoundBSS;
|
|
if (NewBSS == NULL) {
|
|
const Section *NewSection = getOrCreateSection(Name.c_str(),
|
|
false, SectionKind::BSS);
|
|
NewBSS = new PIC16Section(NewSection);
|
|
BSSSections.push_back(NewBSS);
|
|
}
|
|
|
|
// Insert the GV into this BSS.
|
|
NewBSS->Items.push_back(GV);
|
|
|
|
// We do not want to put any GV without explicit section into this section
|
|
// so set its size to DatabankSize.
|
|
NewBSS->Size = DataBankSize;
|
|
return NewBSS->S_;
|
|
}
|
|
|
|
// Get rom section for a variable. Currently there can be only one rom section
|
|
// unless a variable explicitly requests a section.
|
|
const Section *
|
|
PIC16TargetObjectFile::getROSectionForGlobal(const GlobalVariable *GV) const {
|
|
ROSections[0]->Items.push_back(GV);
|
|
return ROSections[0]->S_;
|
|
}
|
|
|
|
// Create initialized data section for a variable.
|
|
const Section *
|
|
PIC16TargetObjectFile::CreateIDATASectionForGlobal(const GlobalVariable *GV,
|
|
std::string Addr) const {
|
|
assert(GV->hasInitializer() && "This global doesn't need space");
|
|
assert(!GV->getInitializer()->isNullValue() &&
|
|
"initialized global has zero initializer");
|
|
assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
|
|
"can be used for initialized RAM data only");
|
|
|
|
std::string Name;
|
|
// If address is given then create a section at that address else create a
|
|
// section by section name specified in GV.
|
|
PIC16Section *FoundIDATASec = NULL;
|
|
if (Addr.empty()) {
|
|
Name = GV->getSection() + " IDATA";
|
|
for (unsigned i = 0; i < IDATASections.size(); i++) {
|
|
if (IDATASections[i]->S_->getName() == Name) {
|
|
FoundIDATASec = IDATASections[i];
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
|
|
Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr;
|
|
}
|
|
|
|
PIC16Section *NewIDATASec = FoundIDATASec;
|
|
if (NewIDATASec == NULL) {
|
|
const Section *NewSection = getOrCreateSection(Name.c_str(),
|
|
false,
|
|
// FIXME:
|
|
SectionKind::Metadata);
|
|
NewIDATASec = new PIC16Section(NewSection);
|
|
IDATASections.push_back(NewIDATASec);
|
|
}
|
|
// Insert the GV into this IDATA Section.
|
|
NewIDATASec->Items.push_back(GV);
|
|
// We do not want to put any GV without explicit section into this section
|
|
// so set its size to DatabankSize.
|
|
NewIDATASec->Size = DataBankSize;
|
|
return NewIDATASec->S_;
|
|
}
|
|
|
|
// Create a section in rom for a variable.
|
|
const Section *
|
|
PIC16TargetObjectFile::CreateROSectionForGlobal(const GlobalVariable *GV,
|
|
std::string Addr) const {
|
|
assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE &&
|
|
"can be used for ROM data only");
|
|
|
|
std::string Name;
|
|
// If address is given then create a section at that address else create a
|
|
// section by section name specified in GV.
|
|
PIC16Section *FoundROSec = NULL;
|
|
if (Addr.empty()) {
|
|
Name = GV->getSection() + " ROMDATA";
|
|
for (unsigned i = 1; i < ROSections.size(); i++) {
|
|
if (ROSections[i]->S_->getName() == Name) {
|
|
FoundROSec = ROSections[i];
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
|
|
Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr;
|
|
}
|
|
|
|
PIC16Section *NewRomSec = FoundROSec;
|
|
if (NewRomSec == NULL) {
|
|
const Section *NewSection = getOrCreateSection(Name.c_str(),
|
|
false,
|
|
SectionKind::ReadOnly);
|
|
NewRomSec = new PIC16Section(NewSection);
|
|
ROSections.push_back(NewRomSec);
|
|
}
|
|
|
|
// Insert the GV into this ROM Section.
|
|
NewRomSec->Items.push_back(GV);
|
|
return NewRomSec->S_;
|
|
}
|
|
|