this is (unfortunately) several changes mixed together:

1. Spell SectionFlags::Writeable as "Writable".
2. Add predicates for deriving SectionFlags from SectionKinds.
3. Sink ELF-specific getSectionPrefixForUniqueGlobal impl into
   ELFTargetAsmInfo.
4. Fix SectionFlagsForGlobal to know that BSS/ThreadBSS has the
   BSS bit set (the real fix for PR4619).
5. Fix isSuitableForBSS to not put globals with explicit sections
   set in BSS (which was the reason #4 wasn't fixed earlier).
6. Remove my previous hack for PR4619.

llvm-svn: 77085
This commit is contained in:
Chris Lattner 2009-07-25 18:57:34 +00:00
parent 7b5e51091e
commit 60f3b73e11
14 changed files with 100 additions and 89 deletions

View File

@ -43,12 +43,6 @@ namespace llvm {
virtual const Section * virtual const Section *
getSectionForMergableConstant(uint64_t Size, unsigned ReloInfo) const; getSectionForMergableConstant(uint64_t Size, unsigned ReloInfo) const;
virtual const char *
getSectionPrefixForUniqueGlobal(SectionKind::Kind Kind) const {
// Darwin doesn't use uniqued sections for weak symbols.
return 0;
}
private: private:
const Section* MergeableStringSection(const GlobalVariable *GV) const; const Section* MergeableStringSection(const GlobalVariable *GV) const;
}; };

View File

@ -37,6 +37,8 @@ namespace llvm {
/// ".tbss" gets the TLS bit set etc. /// ".tbss" gets the TLS bit set etc.
virtual unsigned getFlagsForNamedSection(const char *Section) const; virtual unsigned getFlagsForNamedSection(const char *Section) const;
const char *getSectionPrefixForUniqueGlobal(SectionKind::Kind Kind) const;
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV, virtual const Section* SelectSectionForGlobal(const GlobalValue *GV,
SectionKind::Kind Kind) const; SectionKind::Kind Kind) const;
virtual std::string printSectionFlags(unsigned flags) const; virtual std::string printSectionFlags(unsigned flags) const;

View File

@ -62,13 +62,35 @@ namespace llvm {
K == SectionKind::RODataMergeConst || K == SectionKind::RODataMergeConst ||
K == SectionKind::RODataMergeStr); K == SectionKind::RODataMergeStr);
} }
static inline bool isBSS(Kind K) {
return K == BSS || K == ThreadBSS;
}
static inline bool isTLS(Kind K) {
return K == ThreadData || K == ThreadBSS;
}
static inline bool isCode(Kind K) {
return K == Text;
}
static inline bool isWritable(Kind K) {
return isTLS(K) ||
K == SectionKind::Data ||
K == SectionKind::DataRel ||
K == SectionKind::DataRelLocal ||
K == SectionKind::DataRelRO ||
K == SectionKind::DataRelROLocal ||
K == SectionKind::BSS;
}
} }
namespace SectionFlags { namespace SectionFlags {
const unsigned Invalid = -1U; const unsigned Invalid = -1U;
const unsigned None = 0; const unsigned None = 0;
const unsigned Code = 1 << 0; ///< Section contains code const unsigned Code = 1 << 0; ///< Section contains code
const unsigned Writeable = 1 << 1; ///< Section is writeable const unsigned Writable = 1 << 1; ///< Section is writable
const unsigned BSS = 1 << 2; ///< Section contains only zeroes const unsigned BSS = 1 << 2; ///< Section contains only zeroes
const unsigned Mergeable = 1 << 3; ///< Section contains mergeable data const unsigned Mergeable = 1 << 3; ///< Section contains mergeable data
const unsigned Strings = 1 << 4; ///< Section contains C-type strings const unsigned Strings = 1 << 4; ///< Section contains C-type strings
@ -582,7 +604,9 @@ namespace llvm {
/// global. This is important for globals that need to be merged across /// global. This is important for globals that need to be merged across
/// translation units. /// translation units.
virtual const char * virtual const char *
getSectionPrefixForUniqueGlobal(SectionKind::Kind Kind) const; getSectionPrefixForUniqueGlobal(SectionKind::Kind Kind) const {
return 0;
}
/// getFlagsForNamedSection - If this target wants to be able to infer /// getFlagsForNamedSection - If this target wants to be able to infer
/// section flags based on the name of the section specified for a global /// section flags based on the name of the section specified for a global

View File

@ -222,7 +222,7 @@ unsigned ELFWriter::getElfSectionFlags(unsigned Flags) {
if (Flags & SectionFlags::Code) if (Flags & SectionFlags::Code)
ElfSectionFlags |= ELFSection::SHF_EXECINSTR; ElfSectionFlags |= ELFSection::SHF_EXECINSTR;
if (Flags & SectionFlags::Writeable) if (Flags & SectionFlags::Writable)
ElfSectionFlags |= ELFSection::SHF_WRITE; ElfSectionFlags |= ELFSection::SHF_WRITE;
if (Flags & SectionFlags::Mergeable) if (Flags & SectionFlags::Mergeable)
ElfSectionFlags |= ELFSection::SHF_MERGE; ElfSectionFlags |= ELFSection::SHF_MERGE;

View File

@ -36,7 +36,7 @@ SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) :
// BSS section needs to be emitted as ".section" // BSS section needs to be emitted as ".section"
BSSSection = "\t.section\t.bss"; BSSSection = "\t.section\t.bss";
BSSSection_ = getUnnamedSection("\t.section\t.bss", BSSSection_ = getUnnamedSection("\t.section\t.bss",
SectionFlags::Writeable | SectionFlags::BSS, SectionFlags::Writable | SectionFlags::BSS,
true); true);
SupportsDebugInformation = true; SupportsDebugInformation = true;

View File

@ -50,7 +50,7 @@ DarwinTargetAsmInfo::DarwinTargetAsmInfo(const TargetMachine &TM)
SectionFlags::None); SectionFlags::None);
ConstDataSection = getUnnamedSection(".const_data", SectionFlags::None); ConstDataSection = getUnnamedSection(".const_data", SectionFlags::None);
DataCoalSection = getNamedSection("\t__DATA,__datacoal_nt,coalesced", DataCoalSection = getNamedSection("\t__DATA,__datacoal_nt,coalesced",
SectionFlags::Writeable); SectionFlags::Writable);
// Common settings for all Darwin targets. // Common settings for all Darwin targets.
@ -127,6 +127,7 @@ bool DarwinTargetAsmInfo::emitUsedDirectiveFor(const GlobalValue* GV,
const Section* const Section*
DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind::Kind Kind) const { SectionKind::Kind Kind) const {
// FIXME: Use sectionflags:linkonce instead of isWeakForLinker() here.
bool isWeak = GV->isWeakForLinker(); bool isWeak = GV->isWeakForLinker();
bool isNonStatic = TM.getRelocationModel() != Reloc::Static; bool isNonStatic = TM.getRelocationModel() != Reloc::Static;

View File

@ -29,20 +29,20 @@ ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
: TargetAsmInfo(TM) { : TargetAsmInfo(TM) {
BSSSection_ = getUnnamedSection("\t.bss", BSSSection_ = getUnnamedSection("\t.bss",
SectionFlags::Writeable | SectionFlags::BSS); SectionFlags::Writable | SectionFlags::BSS);
ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None); ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None);
TLSDataSection = getNamedSection("\t.tdata", TLSDataSection = getNamedSection("\t.tdata",
SectionFlags::Writeable | SectionFlags::TLS); SectionFlags::Writable | SectionFlags::TLS);
TLSBSSSection = getNamedSection("\t.tbss", TLSBSSSection = getNamedSection("\t.tbss",
SectionFlags::Writeable | SectionFlags::TLS | SectionFlags::BSS); SectionFlags::Writable | SectionFlags::TLS | SectionFlags::BSS);
DataRelSection = getNamedSection("\t.data.rel", SectionFlags::Writeable); DataRelSection = getNamedSection("\t.data.rel", SectionFlags::Writable);
DataRelLocalSection = getNamedSection("\t.data.rel.local", DataRelLocalSection = getNamedSection("\t.data.rel.local",
SectionFlags::Writeable); SectionFlags::Writable);
DataRelROSection = getNamedSection("\t.data.rel.ro", DataRelROSection = getNamedSection("\t.data.rel.ro",
SectionFlags::Writeable); SectionFlags::Writable);
DataRelROLocalSection = getNamedSection("\t.data.rel.ro.local", DataRelROLocalSection = getNamedSection("\t.data.rel.ro.local",
SectionFlags::Writeable); SectionFlags::Writable);
} }
@ -145,6 +145,28 @@ unsigned ELFTargetAsmInfo::getFlagsForNamedSection(const char *Name) const {
} }
const char *
ELFTargetAsmInfo::getSectionPrefixForUniqueGlobal(SectionKind::Kind Kind) const{
switch (Kind) {
default: llvm_unreachable("Unknown section kind");
case SectionKind::Text: return ".gnu.linkonce.t.";
case SectionKind::Data: return ".gnu.linkonce.d.";
case SectionKind::DataRel: return ".gnu.linkonce.d.rel.";
case SectionKind::DataRelLocal: return ".gnu.linkonce.d.rel.local.";
case SectionKind::DataRelRO: return ".gnu.linkonce.d.rel.ro.";
case SectionKind::DataRelROLocal: return ".gnu.linkonce.d.rel.ro.local.";
case SectionKind::BSS: return ".gnu.linkonce.b.";
case SectionKind::ROData:
case SectionKind::RODataMergeConst:
case SectionKind::RODataMergeStr: return ".gnu.linkonce.r.";
case SectionKind::ThreadData: return ".gnu.linkonce.td.";
case SectionKind::ThreadBSS: return ".gnu.linkonce.tb.";
}
}
const Section* const Section*
ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const { ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
const TargetData *TD = TM.getTargetData(); const TargetData *TD = TM.getTargetData();
@ -177,7 +199,7 @@ std::string ELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
Flags += 'a'; Flags += 'a';
if (flags & SectionFlags::Code) if (flags & SectionFlags::Code)
Flags += 'x'; Flags += 'x';
if (flags & SectionFlags::Writeable) if (flags & SectionFlags::Writable)
Flags += 'w'; Flags += 'w';
if (flags & SectionFlags::Mergeable) if (flags & SectionFlags::Mergeable)
Flags += 'M'; Flags += 'M';

View File

@ -292,7 +292,7 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str(); const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str();
const Section *fPDataSection = TAI->getNamedSection(SectionName, const Section *fPDataSection = TAI->getNamedSection(SectionName,
SectionFlags::Writeable); SectionFlags::Writable);
SwitchToSection(fPDataSection); SwitchToSection(fPDataSection);
// Emit function frame label // Emit function frame label

View File

@ -38,9 +38,9 @@ PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
AsciiDirective = " dt "; AsciiDirective = " dt ";
AscizDirective = NULL; AscizDirective = NULL;
BSSSection_ = getNamedSection("udata.# UDATA", BSSSection_ = getNamedSection("udata.# UDATA",
SectionFlags::Writeable | SectionFlags::BSS); SectionFlags::Writable | SectionFlags::BSS);
ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None); ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None);
DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable); DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writable);
SwitchToSectionDirective = ""; SwitchToSectionDirective = "";
// Need because otherwise a .text symbol is emitted by DwarfWriter // Need because otherwise a .text symbol is emitted by DwarfWriter
// in BeginModule, and gpasm cribbs for that .text symbol. // in BeginModule, and gpasm cribbs for that .text symbol.

View File

@ -75,7 +75,7 @@ PPCLinuxTargetAsmInfo::PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM) :
// PPC/Linux normally uses named section for BSS. // PPC/Linux normally uses named section for BSS.
BSSSection_ = getNamedSection("\t.bss", BSSSection_ = getNamedSection("\t.bss",
SectionFlags::Writeable | SectionFlags::BSS, SectionFlags::Writable | SectionFlags::BSS,
/* Override */ true); /* Override */ true);
// Debug Information // Debug Information

View File

@ -28,7 +28,7 @@ SparcELFTargetAsmInfo::SparcELFTargetAsmInfo(const TargetMachine &TM):
// Sparc normally uses named section for BSS. // Sparc normally uses named section for BSS.
BSSSection_ = getNamedSection("\t.bss", BSSSection_ = getNamedSection("\t.bss",
SectionFlags::Writeable | SectionFlags::BSS, SectionFlags::Writable | SectionFlags::BSS,
/* Override */ true); /* Override */ true);
} }
@ -41,7 +41,7 @@ std::string SparcELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
Flags += ",#alloc"; Flags += ",#alloc";
if (flags & SectionFlags::Code) if (flags & SectionFlags::Code)
Flags += ",#execinstr"; Flags += ",#execinstr";
if (flags & SectionFlags::Writeable) if (flags & SectionFlags::Writable)
Flags += ",#write"; Flags += ",#write";
if (flags & SectionFlags::TLS) if (flags & SectionFlags::TLS)
Flags += ",#tls"; Flags += ",#tls";

View File

@ -122,7 +122,7 @@ TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm) : TM(tm) {
DwarfExceptionSection = ".gcc_except_table"; DwarfExceptionSection = ".gcc_except_table";
AsmTransCBE = 0; AsmTransCBE = 0;
TextSection = getUnnamedSection("\t.text", SectionFlags::Code); TextSection = getUnnamedSection("\t.text", SectionFlags::Code);
DataSection = getUnnamedSection("\t.data", SectionFlags::Writeable); DataSection = getUnnamedSection("\t.data", SectionFlags::Writable);
} }
TargetAsmInfo::~TargetAsmInfo() { TargetAsmInfo::~TargetAsmInfo() {
@ -160,9 +160,22 @@ unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
} }
static bool isSuitableForBSS(const GlobalVariable *GV) { static bool isSuitableForBSS(const GlobalVariable *GV) {
// Leave constant zeros in readonly constant sections, so they can be shared
Constant *C = GV->getInitializer(); Constant *C = GV->getInitializer();
return (C->isNullValue() && !GV->isConstant() && !NoZerosInBSS);
// Must have zero initializer.
if (!C->isNullValue())
return false;
// Leave constant zeros in readonly constant sections, so they can be shared.
if (GV->isConstant())
return false;
// If the global has an explicit section specified, don't put it in BSS.
if (!GV->getSection().empty())
return false;
// Otherwise, put it in BSS unless the target really doesn't want us to.
return !NoZerosInBSS;
} }
static bool isConstantString(const Constant *C) { static bool isConstantString(const Constant *C) {
@ -183,36 +196,18 @@ static bool isConstantString(const Constant *C) {
static unsigned SectionFlagsForGlobal(const GlobalValue *GV, static unsigned SectionFlagsForGlobal(const GlobalValue *GV,
SectionKind::Kind Kind) { SectionKind::Kind Kind) {
// Decode flags from global and section kind.
unsigned Flags = SectionFlags::None; unsigned Flags = SectionFlags::None;
// Decode flags from global itself.
switch (Kind) {
case SectionKind::Text:
Flags |= SectionFlags::Code;
break;
case SectionKind::ThreadData:
case SectionKind::ThreadBSS:
Flags |= SectionFlags::TLS;
// FALLS THROUGH
case SectionKind::Data:
case SectionKind::DataRel:
case SectionKind::DataRelLocal:
case SectionKind::DataRelRO:
case SectionKind::DataRelROLocal:
case SectionKind::BSS:
Flags |= SectionFlags::Writeable;
break;
case SectionKind::ROData:
case SectionKind::RODataMergeStr:
case SectionKind::RODataMergeConst:
// No additional flags here
break;
default:
llvm_unreachable("Unexpected section kind!");
}
if (GV->isWeakForLinker()) if (GV->isWeakForLinker())
Flags |= SectionFlags::Linkonce; Flags |= SectionFlags::Linkonce;
if (SectionKind::isBSS(Kind))
Flags |= SectionFlags::BSS;
if (SectionKind::isTLS(Kind))
Flags |= SectionFlags::TLS;
if (SectionKind::isCode(Kind))
Flags |= SectionFlags::Code;
if (SectionKind::isWritable(Kind))
Flags |= SectionFlags::Writable;
return Flags; return Flags;
} }
@ -331,11 +326,6 @@ const Section *TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
// FIXME: Use mangler interface (PR4584). // FIXME: Use mangler interface (PR4584).
std::string Name = Prefix+GV->getNameStr(); std::string Name = Prefix+GV->getNameStr();
// Pick up the flags for the uniquing section.
// FIXME: HACK.
Flags |= getFlagsForNamedSection(Name.c_str());
return getNamedSection(Name.c_str(), Flags); return getNamedSection(Name.c_str(), Flags);
} }
} }
@ -348,10 +338,10 @@ const Section *TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
const Section* const Section*
TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind::Kind Kind) const { SectionKind::Kind Kind) const {
if (Kind == SectionKind::Text) if (SectionKind::isCode(Kind))
return getTextSection(); return getTextSection();
if (Kind == SectionKind::BSS) if (SectionKind::isBSS(SectionKind::BSS))
if (const Section *S = getBSSSection_()) if (const Section *S = getBSSSection_())
return S; return S;
@ -374,27 +364,6 @@ TargetAsmInfo::getSectionForMergableConstant(uint64_t Size,
} }
const char *
TargetAsmInfo::getSectionPrefixForUniqueGlobal(SectionKind::Kind Kind) const {
switch (Kind) {
default: llvm_unreachable("Unknown section kind");
case SectionKind::Text: return ".gnu.linkonce.t.";
case SectionKind::Data: return ".gnu.linkonce.d.";
case SectionKind::DataRel: return ".gnu.linkonce.d.rel.";
case SectionKind::DataRelLocal: return ".gnu.linkonce.d.rel.local.";
case SectionKind::DataRelRO: return ".gnu.linkonce.d.rel.ro.";
case SectionKind::DataRelROLocal: return ".gnu.linkonce.d.rel.ro.local.";
case SectionKind::BSS: return ".gnu.linkonce.b.";
case SectionKind::ROData:
case SectionKind::RODataMergeConst:
case SectionKind::RODataMergeStr: return ".gnu.linkonce.r.";
case SectionKind::ThreadData: return ".gnu.linkonce.td.";
case SectionKind::ThreadBSS: return ".gnu.linkonce.tb.";
}
}
const Section *TargetAsmInfo::getNamedSection(const char *Name, unsigned Flags, const Section *TargetAsmInfo::getNamedSection(const char *Name, unsigned Flags,
bool Override) const { bool Override) const {
Section &S = Sections[Name]; Section &S = Sections[Name];

View File

@ -282,7 +282,6 @@ getSectionPrefixForUniqueGlobal(SectionKind::Kind Kind) const {
case SectionKind::RODataMergeConst: case SectionKind::RODataMergeConst:
case SectionKind::RODataMergeStr: return ".rdata$linkonce"; case SectionKind::RODataMergeStr: return ".rdata$linkonce";
} }
return NULL;
} }
std::string X86COFFTargetAsmInfo::printSectionFlags(unsigned flags) const { std::string X86COFFTargetAsmInfo::printSectionFlags(unsigned flags) const {
@ -290,7 +289,7 @@ std::string X86COFFTargetAsmInfo::printSectionFlags(unsigned flags) const {
if (flags & SectionFlags::Code) if (flags & SectionFlags::Code)
Flags += 'x'; Flags += 'x';
if (flags & SectionFlags::Writeable) if (flags & SectionFlags::Writable)
Flags += 'w'; Flags += 'w';
Flags += "\""; Flags += "\"";
@ -322,7 +321,7 @@ X86WinTargetAsmInfo::X86WinTargetAsmInfo(const X86TargetMachine &TM):
AlignmentIsInBytes = true; AlignmentIsInBytes = true;
TextSection = getUnnamedSection("_text", SectionFlags::Code); TextSection = getUnnamedSection("_text", SectionFlags::Code);
DataSection = getUnnamedSection("_data", SectionFlags::Writeable); DataSection = getUnnamedSection("_data", SectionFlags::Writable);
JumpTableDataSection = NULL; JumpTableDataSection = NULL;
SwitchToSectionDirective = ""; SwitchToSectionDirective = "";

View File

@ -25,8 +25,8 @@ XCoreTargetAsmInfo::XCoreTargetAsmInfo(const XCoreTargetMachine &TM)
: ELFTargetAsmInfo(TM) { : ELFTargetAsmInfo(TM) {
SupportsDebugInformation = true; SupportsDebugInformation = true;
TextSection = getUnnamedSection("\t.text", SectionFlags::Code); TextSection = getUnnamedSection("\t.text", SectionFlags::Code);
DataSection = getNamedSection("\t.dp.data", SectionFlags::Writeable); DataSection = getNamedSection("\t.dp.data", SectionFlags::Writable);
BSSSection_ = getNamedSection("\t.dp.bss", SectionFlags::Writeable | BSSSection_ = getNamedSection("\t.dp.bss", SectionFlags::Writable |
SectionFlags::BSS); SectionFlags::BSS);
// TLS globals are lowered in the backend to arrays indexed by the current // TLS globals are lowered in the backend to arrays indexed by the current
@ -36,7 +36,7 @@ XCoreTargetAsmInfo::XCoreTargetAsmInfo(const XCoreTargetMachine &TM)
TLSBSSSection = BSSSection_; TLSBSSSection = BSSSection_;
if (TM.getSubtargetImpl()->isXS1A()) if (TM.getSubtargetImpl()->isXS1A())
ReadOnlySection = getNamedSection("\t.dp.rodata", SectionFlags::Writeable); ReadOnlySection = getNamedSection("\t.dp.rodata", SectionFlags::Writable);
else else
ReadOnlySection = getNamedSection("\t.cp.rodata", SectionFlags::None); ReadOnlySection = getNamedSection("\t.cp.rodata", SectionFlags::None);
Data16bitsDirective = "\t.short\t"; Data16bitsDirective = "\t.short\t";