Rearrange all the SectionKinds and structure them into a hierarchical

group instead of a bunch of random unrelated ideas.  Provide predicates
to categorize a SectionKind into a group, and use them instead of 
getKind() throughout the code.

This also renames a ton of SectionKinds to be more consistent and
evocative, and adds a huge number of comments on the enums so that
I will hopefully be able to remember how this stuff works long from
now.

llvm-svn: 77129
This commit is contained in:
Chris Lattner 2009-07-26 05:44:20 +00:00
parent 9d81cc668a
commit 1d68bd7f97
5 changed files with 180 additions and 110 deletions

View File

@ -32,66 +32,131 @@ namespace llvm {
} }
/// SectionKind - This is a simple POD value that classifies the properties of /// SectionKind - This is a simple POD value that classifies the properties of
/// a section. /// a section. A global variable is classified into the deepest possible
/// classification, and then the target maps them onto their sections based on
/// what capabilities they have.
///
/// The comments below describe these as if they were an inheritance hierarchy
/// in order to explain the predicates below.
struct SectionKind { struct SectionKind {
enum Kind { enum Kind {
Text, ///< Text section. /// Text - Text section, used for functions and other executable code.
BSS, ///< BSS section. Text,
Data, ///< Data section.
DataRel, ///< Data that has relocations.
DataRelLocal, ///< Data that only has local relocations.
// Readonly data.
ROData, ///< Readonly data section.
DataRelRO, ///< Readonly data with non-local relocations.
DataRelROLocal, ///< Readonly data with local relocations only.
/// Mergable sections. /// ReadOnly - Data that is never written to at program runtime by the
RODataMergeStr, ///< Readonly data section: nul-terminated strings. /// program or the dynamic linker. Things in the top-level readonly
RODataMergeConst, ///< Readonly data section: fixed-length constants. /// SectionKind are not mergable.
ReadOnly,
/// MergableCString - This is a special section for nul-terminated
/// strings. The linker can unique the C strings, knowing their
/// semantics. Because it uniques based on the nul terminators, the
/// compiler can't put strings in this section that have embeded nuls
/// in them.
MergableCString,
/// MergableConst - These are sections for merging fixed-length
/// constants together. For example, this can be used to unique
/// constant pool entries etc.
MergableConst,
/// Writable - This is the base of all segments that need to be written
/// to during program runtime.
/// ThreadLocal - This is the base of all TLS segments. All TLS
/// objects must be writable, otherwise there is no reason for them to
/// be thread local!
/// ThreadBSS - Zero-initialized TLS data objects.
ThreadBSS,
/// ThreadData - Initialized TLS data objects.
ThreadData,
/// GlobalWritableData - Writable data that is global (not thread
/// local).
/// BSS - Zero initialized writable data.
BSS,
/// DataRel - This is the most general form of data that is written
/// to by the program, it can have random relocations to arbitrary
/// globals.
DataRel,
/// DataRelLocal - This is writable data that has a non-zero
/// initializer and has relocations in it, but all of the
/// relocations are known to be within the final linked image
/// the global is linked into.
DataRelLocal,
/// DataNoRel - This is writable data that has a non-zero
/// initializer, but whose initializer is known to have no
/// relocations.
DataNoRel,
/// ReadOnlyWithRel - These are global variables that are never
/// written to by the program, but that have relocations, so they
/// must be stuck in a writable section so that the dynamic linker
/// can write to them. If it chooses to, the dynamic linker can
/// mark the pages these globals end up on as read-only after it is
/// done with its relocation phase.
ReadOnlyWithRel,
/// ReadOnlyWithRelLocal - This is data that is readonly by the
/// program, but must be writable so that the dynamic linker
/// can perform relocations in it. This is used when we know
/// that all the relocations are to globals in this final
/// linked image.
ReadOnlyWithRelLocal
/// Thread local data.
ThreadData, ///< Initialized TLS data objects
ThreadBSS ///< Uninitialized TLS data objects
} K : 8; // This is private. } K : 8; // This is private.
// FIXME: Eliminate. bool isText() const {
Kind getKind() const { return K; }
bool isReadOnly() const {
return K == ROData || K == RODataMergeConst || K == RODataMergeStr;
}
/// isReadOnlyWithDynamicInit - Return true if this data is readonly, but
/// the dynamic linker has to write to it to apply relocations.
bool isReadOnlyWithDynamicInit() const {
return K == DataRelRO || K == DataRelROLocal;
}
bool isBSS() const {
return K == BSS || K == ThreadBSS;
}
bool isTLS() const {
return K == ThreadData || K == ThreadBSS;
}
bool isCode() const {
return K == Text; return K == Text;
} }
bool isReadOnly() const {
return K == ReadOnly || K == MergableCString || K == MergableConst;
}
bool isMergableCString() const { return K == MergableCString; }
bool isMergableConst() const { return K == MergableConst; }
bool isWritable() const { bool isWritable() const {
return isTLS() || return isThreadLocal() || isGlobalWritableData();
K == Data ||
K == DataRel || K == DataRelLocal ||
K == DataRelRO || K == DataRelROLocal ||
K == BSS;
} }
bool isMergableString() const { return K == RODataMergeStr; } bool isThreadLocal() const {
bool isMergableConstant() const { return K == ThreadData || K == ThreadBSS;
return K == RODataMergeStr || K == RODataMergeConst; }
bool isThreadBSS() const { return K == ThreadBSS; }
bool isThreadData() const { return K == ThreadData; }
bool isGlobalWritableData() const {
return isBSS() || isDataRel() || isReadOnlyWithRel();
}
bool isBSS() const { return K == BSS; }
bool isDataRel() const {
return K == DataRel || K == DataRelLocal || K == DataNoRel;
}
bool isDataRelLocal() const {
return K == DataRelLocal || K == DataNoRel;
}
bool isDataNoRel() const { return K == DataNoRel; }
bool isReadOnlyWithRel() const {
return K == ReadOnlyWithRel || K == ReadOnlyWithRelLocal;
}
bool isReadOnlyWithRelLocal() const {
return K == ReadOnlyWithRelLocal;
} }
static SectionKind get(Kind K) { static SectionKind get(Kind K) {
@ -99,17 +164,19 @@ namespace llvm {
return Res; return Res;
} }
static SectionKind getText() { return get(Text); } static SectionKind getText() { return get(Text); }
static SectionKind getReadOnly() { return get(ReadOnly); }
static SectionKind getMergableCString() { return get(MergableCString); }
static SectionKind getMergableConst() { return get(MergableConst); }
static SectionKind getThreadBSS() { return get(ThreadBSS); }
static SectionKind getThreadData() { return get(ThreadData); }
static SectionKind getBSS() { return get(BSS); } static SectionKind getBSS() { return get(BSS); }
static SectionKind getData() { return get(Data); }
static SectionKind getDataRel() { return get(DataRel); } static SectionKind getDataRel() { return get(DataRel); }
static SectionKind getDataRelLocal() { return get(DataRelLocal); } static SectionKind getDataRelLocal() { return get(DataRelLocal); }
static SectionKind getROData() { return get(ROData); } static SectionKind getDataNoRel() { return get(DataNoRel); }
static SectionKind getDataRelRO() { return get(DataRelRO); } static SectionKind getReadOnlyWithRel() { return get(ReadOnlyWithRel); }
static SectionKind getDataRelROLocal() { return get(DataRelROLocal); } static SectionKind getReadOnlyWithRelLocal() {
static SectionKind getRODataMergeStr() { return get(RODataMergeStr); } return get(ReadOnlyWithRelLocal);
static SectionKind getRODataMergeConst() { return get(RODataMergeConst); } }
static SectionKind getThreadData() { return get(ThreadData); }
static SectionKind getThreadBSS() { return get(ThreadBSS); }
}; };
namespace SectionFlags { namespace SectionFlags {

View File

@ -127,12 +127,12 @@ bool DarwinTargetAsmInfo::emitUsedDirectiveFor(const GlobalValue* GV,
const Section* const Section*
DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const { SectionKind Kind) const {
assert(!Kind.isTLS() && "Darwin doesn't support TLS"); assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS");
// FIXME: Use sectionflags:linkonce instead of isWeakForLinker() here. // FIXME: Use sectionflags:linkonce instead of isWeakForLinker() here.
bool isWeak = GV->isWeakForLinker(); bool isWeak = GV->isWeakForLinker();
if (Kind.isCode()) if (Kind.isText())
return isWeak ? TextCoalSection : TextSection; return isWeak ? TextCoalSection : TextSection;
// If this is weak/linkonce, put this in a coalescable section, either in text // If this is weak/linkonce, put this in a coalescable section, either in text
@ -144,24 +144,24 @@ DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
} }
// FIXME: Alignment check should be handled by section classifier. // FIXME: Alignment check should be handled by section classifier.
if (Kind.isMergableString()) if (Kind.isMergableCString())
return MergeableStringSection(cast<GlobalVariable>(GV)); return MergeableStringSection(cast<GlobalVariable>(GV));
if (Kind.isMergableConstant()) { if (Kind.isMergableConst()) {
const Type *Ty = cast<GlobalVariable>(GV)->getInitializer()->getType(); const Type *Ty = cast<GlobalVariable>(GV)->getInitializer()->getType();
const TargetData *TD = TM.getTargetData(); const TargetData *TD = TM.getTargetData();
return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0); return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0);
} }
// If this is marked const, put it into a const section. But if the dynamic
// linker needs to write to it, put it in the data segment.
if (Kind.isReadOnlyWithDynamicInit())
return ConstDataSection;
// FIXME: ROData -> const in -static mode that is relocatable but they happen // FIXME: ROData -> const in -static mode that is relocatable but they happen
// by the static linker. Why not mergable? // by the static linker. Why not mergable?
if (Kind.isReadOnly()) if (Kind.isReadOnly())
return getReadOnlySection(); return getReadOnlySection();
// If this is marked const, put it into a const section. But if the dynamic
// linker needs to write to it, put it in the data segment.
if (Kind.isReadOnlyWithRel())
return ConstDataSection;
// Otherwise, just drop the variable in the normal data section. // Otherwise, just drop the variable in the normal data section.
return DataSection; return DataSection;

View File

@ -49,28 +49,30 @@ ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
const Section* const Section*
ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const { SectionKind Kind) const {
switch (Kind.getKind()) { if (Kind.isText()) return TextSection;
default: llvm_unreachable("Unknown section kind"); if (Kind.isMergableCString())
case SectionKind::Text: return TextSection;
case SectionKind::BSS: return getBSSSection_();
case SectionKind::Data: return DataSection;
case SectionKind::DataRel: return DataRelSection;
case SectionKind::DataRelLocal: return DataRelLocalSection;
case SectionKind::DataRelRO: return DataRelROSection;
case SectionKind::DataRelROLocal: return DataRelROLocalSection;
case SectionKind::ROData: return getReadOnlySection();
case SectionKind::RODataMergeStr:
return MergeableStringSection(cast<GlobalVariable>(GV)); return MergeableStringSection(cast<GlobalVariable>(GV));
case SectionKind::RODataMergeConst: { if (Kind.isMergableConst()) {
const Type *Ty = cast<GlobalVariable>(GV)->getInitializer()->getType(); const Type *Ty = cast<GlobalVariable>(GV)->getInitializer()->getType();
const TargetData *TD = TM.getTargetData(); const TargetData *TD = TM.getTargetData();
return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0); return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0);
} }
case SectionKind::ThreadData: if (Kind.isReadOnly()) return getReadOnlySection();
return TLSDataSection;
case SectionKind::ThreadBSS:
return TLSBSSSection; if (Kind.isThreadData()) return TLSDataSection;
} if (Kind.isThreadBSS()) return TLSBSSSection;
if (Kind.isBSS()) return getBSSSection_();
if (Kind.isDataNoRel()) return DataSection;
if (Kind.isDataRelLocal()) return DataRelLocalSection;
if (Kind.isDataRel()) return DataRelSection;
if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection;
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
return DataRelROSection;
} }
/// getSectionForMergableConstant - Given a mergable constant with the /// getSectionForMergableConstant - Given a mergable constant with the
@ -129,21 +131,20 @@ unsigned ELFTargetAsmInfo::getFlagsForNamedSection(const char *Name) const {
const char * const char *
ELFTargetAsmInfo::getSectionPrefixForUniqueGlobal(SectionKind Kind) const{ ELFTargetAsmInfo::getSectionPrefixForUniqueGlobal(SectionKind Kind) const{
switch (Kind.getKind()) { if (Kind.isText()) return ".gnu.linkonce.t.";
default: llvm_unreachable("Unknown section kind"); if (Kind.isReadOnly()) return ".gnu.linkonce.r.";
case SectionKind::Text: return ".gnu.linkonce.t.";
case SectionKind::Data: return ".gnu.linkonce.d."; if (Kind.isThreadData()) return ".gnu.linkonce.td.";
case SectionKind::DataRel: return ".gnu.linkonce.d.rel."; if (Kind.isThreadBSS()) return ".gnu.linkonce.tb.";
case SectionKind::DataRelLocal: return ".gnu.linkonce.d.rel.local.";
case SectionKind::DataRelRO: return ".gnu.linkonce.d.rel.ro."; if (Kind.isBSS()) return ".gnu.linkonce.b.";
case SectionKind::DataRelROLocal: return ".gnu.linkonce.d.rel.ro.local."; if (Kind.isDataNoRel()) return ".gnu.linkonce.d.";
case SectionKind::BSS: return ".gnu.linkonce.b."; if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local.";
case SectionKind::ROData: if (Kind.isDataRel()) return ".gnu.linkonce.d.rel.";
case SectionKind::RODataMergeConst: if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local.";
case SectionKind::RODataMergeStr: return ".gnu.linkonce.r.";
case SectionKind::ThreadData: return ".gnu.linkonce.td."; assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
case SectionKind::ThreadBSS: return ".gnu.linkonce.tb."; return ".gnu.linkonce.d.rel.ro.";
}
} }

View File

@ -204,11 +204,11 @@ static unsigned SectionFlagsForGlobal(const GlobalValue *GV,
unsigned Flags = SectionFlags::None; unsigned Flags = SectionFlags::None;
if (GV->isWeakForLinker()) if (GV->isWeakForLinker())
Flags |= SectionFlags::Linkonce; Flags |= SectionFlags::Linkonce;
if (Kind.isBSS()) if (Kind.isBSS() || Kind.isThreadBSS())
Flags |= SectionFlags::BSS; Flags |= SectionFlags::BSS;
if (Kind.isTLS()) if (Kind.isThreadLocal())
Flags |= SectionFlags::TLS; Flags |= SectionFlags::TLS;
if (Kind.isCode()) if (Kind.isText())
Flags |= SectionFlags::Code; Flags |= SectionFlags::Code;
if (Kind.isWritable()) if (Kind.isWritable())
Flags |= SectionFlags::Writable; Flags |= SectionFlags::Writable;
@ -247,32 +247,32 @@ static SectionKind SectionKindForGlobal(const GlobalValue *GV,
// If initializer is a null-terminated string, put it in a "cstring" // If initializer is a null-terminated string, put it in a "cstring"
// section if the target has it. // section if the target has it.
if (isConstantString(C)) if (isConstantString(C))
return SectionKind::getRODataMergeStr(); return SectionKind::getMergableCString();
// Otherwise, just drop it into a mergable constant section. // Otherwise, just drop it into a mergable constant section.
return SectionKind::getRODataMergeConst(); return SectionKind::getMergableConst();
case Constant::LocalRelocation: case Constant::LocalRelocation:
// In static relocation model, the linker will resolve all addresses, so // In static relocation model, the linker will resolve all addresses, so
// the relocation entries will actually be constants by the time the app // the relocation entries will actually be constants by the time the app
// starts up. // starts up.
if (ReloModel == Reloc::Static) if (ReloModel == Reloc::Static)
return SectionKind::getROData(); return SectionKind::getReadOnly();
// Otherwise, the dynamic linker needs to fix it up, put it in the // Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel.local section. // writable data.rel.local section.
return SectionKind::getDataRelROLocal(); return SectionKind::getReadOnlyWithRelLocal();
case Constant::GlobalRelocations: case Constant::GlobalRelocations:
// In static relocation model, the linker will resolve all addresses, so // In static relocation model, the linker will resolve all addresses, so
// the relocation entries will actually be constants by the time the app // the relocation entries will actually be constants by the time the app
// starts up. // starts up.
if (ReloModel == Reloc::Static) if (ReloModel == Reloc::Static)
return SectionKind::getROData(); return SectionKind::getReadOnly();
// Otherwise, the dynamic linker needs to fix it up, put it in the // Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel section. // writable data.rel section.
return SectionKind::getDataRelRO(); return SectionKind::getReadOnlyWithRel();
} }
} }
@ -282,11 +282,11 @@ static SectionKind SectionKindForGlobal(const GlobalValue *GV,
// globals together onto fewer pages, improving the locality of the dynamic // globals together onto fewer pages, improving the locality of the dynamic
// linker. // linker.
if (ReloModel == Reloc::Static) if (ReloModel == Reloc::Static)
return SectionKind::getData(); return SectionKind::getDataNoRel();
switch (C->getRelocationInfo()) { switch (C->getRelocationInfo()) {
default: llvm_unreachable("unknown relocation info kind"); default: llvm_unreachable("unknown relocation info kind");
case Constant::NoRelocation: return SectionKind::getData(); case Constant::NoRelocation: return SectionKind::getDataNoRel();
case Constant::LocalRelocation: return SectionKind::getDataRelLocal(); case Constant::LocalRelocation: return SectionKind::getDataRelLocal();
case Constant::GlobalRelocations: return SectionKind::getDataRel(); case Constant::GlobalRelocations: return SectionKind::getDataRel();
} }
@ -342,7 +342,9 @@ const Section *TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
const Section* const Section*
TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV, TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
SectionKind Kind) const { SectionKind Kind) const {
if (Kind.isCode()) assert(!Kind.isThreadLocal() && "Doesn't support TLS");
if (Kind.isText())
return getTextSection(); return getTextSection();
if (Kind.isBSS()) if (Kind.isBSS())

View File

@ -267,7 +267,7 @@ X86COFFTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
const char *X86COFFTargetAsmInfo:: const char *X86COFFTargetAsmInfo::
getSectionPrefixForUniqueGlobal(SectionKind Kind) const { getSectionPrefixForUniqueGlobal(SectionKind Kind) const {
if (Kind.isCode()) if (Kind.isText())
return ".text$linkonce"; return ".text$linkonce";
if (Kind.isWritable()) if (Kind.isWritable())
return ".data$linkonce"; return ".data$linkonce";