forked from OSchip/llvm-project
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:
parent
9d81cc668a
commit
1d68bd7f97
|
@ -32,66 +32,131 @@ namespace llvm {
|
|||
}
|
||||
|
||||
/// 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 {
|
||||
enum Kind {
|
||||
Text, ///< Text section.
|
||||
BSS, ///< BSS section.
|
||||
/// Text - Text section, used for functions and other executable code.
|
||||
Text,
|
||||
|
||||
Data, ///< Data section.
|
||||
DataRel, ///< Data that has relocations.
|
||||
DataRelLocal, ///< Data that only has local relocations.
|
||||
/// ReadOnly - Data that is never written to at program runtime by the
|
||||
/// program or the dynamic linker. Things in the top-level readonly
|
||||
/// SectionKind are not mergable.
|
||||
ReadOnly,
|
||||
|
||||
// Readonly data.
|
||||
ROData, ///< Readonly data section.
|
||||
DataRelRO, ///< Readonly data with non-local relocations.
|
||||
DataRelROLocal, ///< Readonly data with local relocations only.
|
||||
/// 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,
|
||||
|
||||
/// Mergable sections.
|
||||
RODataMergeStr, ///< Readonly data section: nul-terminated strings.
|
||||
RODataMergeConst, ///< Readonly data section: fixed-length constants.
|
||||
/// 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.
|
||||
|
||||
// FIXME: Eliminate.
|
||||
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 {
|
||||
bool isText() const {
|
||||
return K == Text;
|
||||
}
|
||||
|
||||
bool isWritable() const {
|
||||
return isTLS() ||
|
||||
K == Data ||
|
||||
K == DataRel || K == DataRelLocal ||
|
||||
K == DataRelRO || K == DataRelROLocal ||
|
||||
K == BSS;
|
||||
bool isReadOnly() const {
|
||||
return K == ReadOnly || K == MergableCString || K == MergableConst;
|
||||
}
|
||||
|
||||
bool isMergableString() const { return K == RODataMergeStr; }
|
||||
bool isMergableConstant() const {
|
||||
return K == RODataMergeStr || K == RODataMergeConst;
|
||||
bool isMergableCString() const { return K == MergableCString; }
|
||||
bool isMergableConst() const { return K == MergableConst; }
|
||||
|
||||
bool isWritable() const {
|
||||
return isThreadLocal() || isGlobalWritableData();
|
||||
}
|
||||
|
||||
bool isThreadLocal() const {
|
||||
return K == ThreadData || K == ThreadBSS;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -99,17 +164,19 @@ namespace llvm {
|
|||
return Res;
|
||||
}
|
||||
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 getData() { return get(Data); }
|
||||
static SectionKind getDataRel() { return get(DataRel); }
|
||||
static SectionKind getDataRelLocal() { return get(DataRelLocal); }
|
||||
static SectionKind getROData() { return get(ROData); }
|
||||
static SectionKind getDataRelRO() { return get(DataRelRO); }
|
||||
static SectionKind getDataRelROLocal() { return get(DataRelROLocal); }
|
||||
static SectionKind getRODataMergeStr() { return get(RODataMergeStr); }
|
||||
static SectionKind getRODataMergeConst() { return get(RODataMergeConst); }
|
||||
static SectionKind getThreadData() { return get(ThreadData); }
|
||||
static SectionKind getThreadBSS() { return get(ThreadBSS); }
|
||||
static SectionKind getDataNoRel() { return get(DataNoRel); }
|
||||
static SectionKind getReadOnlyWithRel() { return get(ReadOnlyWithRel); }
|
||||
static SectionKind getReadOnlyWithRelLocal() {
|
||||
return get(ReadOnlyWithRelLocal);
|
||||
}
|
||||
};
|
||||
|
||||
namespace SectionFlags {
|
||||
|
|
|
@ -127,12 +127,12 @@ bool DarwinTargetAsmInfo::emitUsedDirectiveFor(const GlobalValue* GV,
|
|||
const Section*
|
||||
DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
|
||||
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.
|
||||
bool isWeak = GV->isWeakForLinker();
|
||||
|
||||
if (Kind.isCode())
|
||||
if (Kind.isText())
|
||||
return isWeak ? TextCoalSection : TextSection;
|
||||
|
||||
// If this is weak/linkonce, put this in a coalescable section, either in text
|
||||
|
@ -144,25 +144,25 @@ DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
|
|||
}
|
||||
|
||||
// FIXME: Alignment check should be handled by section classifier.
|
||||
if (Kind.isMergableString())
|
||||
if (Kind.isMergableCString())
|
||||
return MergeableStringSection(cast<GlobalVariable>(GV));
|
||||
|
||||
if (Kind.isMergableConstant()) {
|
||||
if (Kind.isMergableConst()) {
|
||||
const Type *Ty = cast<GlobalVariable>(GV)->getInitializer()->getType();
|
||||
const TargetData *TD = TM.getTargetData();
|
||||
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
|
||||
// by the static linker. Why not mergable?
|
||||
if (Kind.isReadOnly())
|
||||
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.
|
||||
return DataSection;
|
||||
}
|
||||
|
|
|
@ -49,28 +49,30 @@ ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
|
|||
const Section*
|
||||
ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
|
||||
SectionKind Kind) const {
|
||||
switch (Kind.getKind()) {
|
||||
default: llvm_unreachable("Unknown section kind");
|
||||
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:
|
||||
if (Kind.isText()) return TextSection;
|
||||
if (Kind.isMergableCString())
|
||||
return MergeableStringSection(cast<GlobalVariable>(GV));
|
||||
case SectionKind::RODataMergeConst: {
|
||||
if (Kind.isMergableConst()) {
|
||||
const Type *Ty = cast<GlobalVariable>(GV)->getInitializer()->getType();
|
||||
const TargetData *TD = TM.getTargetData();
|
||||
return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0);
|
||||
}
|
||||
case SectionKind::ThreadData:
|
||||
return TLSDataSection;
|
||||
case SectionKind::ThreadBSS:
|
||||
return TLSBSSSection;
|
||||
}
|
||||
if (Kind.isReadOnly()) return getReadOnlySection();
|
||||
|
||||
|
||||
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
|
||||
|
@ -129,21 +131,20 @@ unsigned ELFTargetAsmInfo::getFlagsForNamedSection(const char *Name) const {
|
|||
|
||||
const char *
|
||||
ELFTargetAsmInfo::getSectionPrefixForUniqueGlobal(SectionKind Kind) const{
|
||||
switch (Kind.getKind()) {
|
||||
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.";
|
||||
}
|
||||
if (Kind.isText()) return ".gnu.linkonce.t.";
|
||||
if (Kind.isReadOnly()) return ".gnu.linkonce.r.";
|
||||
|
||||
if (Kind.isThreadData()) return ".gnu.linkonce.td.";
|
||||
if (Kind.isThreadBSS()) return ".gnu.linkonce.tb.";
|
||||
|
||||
if (Kind.isBSS()) return ".gnu.linkonce.b.";
|
||||
if (Kind.isDataNoRel()) return ".gnu.linkonce.d.";
|
||||
if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local.";
|
||||
if (Kind.isDataRel()) return ".gnu.linkonce.d.rel.";
|
||||
if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local.";
|
||||
|
||||
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
|
||||
return ".gnu.linkonce.d.rel.ro.";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -204,11 +204,11 @@ static unsigned SectionFlagsForGlobal(const GlobalValue *GV,
|
|||
unsigned Flags = SectionFlags::None;
|
||||
if (GV->isWeakForLinker())
|
||||
Flags |= SectionFlags::Linkonce;
|
||||
if (Kind.isBSS())
|
||||
if (Kind.isBSS() || Kind.isThreadBSS())
|
||||
Flags |= SectionFlags::BSS;
|
||||
if (Kind.isTLS())
|
||||
if (Kind.isThreadLocal())
|
||||
Flags |= SectionFlags::TLS;
|
||||
if (Kind.isCode())
|
||||
if (Kind.isText())
|
||||
Flags |= SectionFlags::Code;
|
||||
if (Kind.isWritable())
|
||||
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"
|
||||
// section if the target has it.
|
||||
if (isConstantString(C))
|
||||
return SectionKind::getRODataMergeStr();
|
||||
return SectionKind::getMergableCString();
|
||||
|
||||
// Otherwise, just drop it into a mergable constant section.
|
||||
return SectionKind::getRODataMergeConst();
|
||||
return SectionKind::getMergableConst();
|
||||
|
||||
case Constant::LocalRelocation:
|
||||
// In static relocation model, the linker will resolve all addresses, so
|
||||
// the relocation entries will actually be constants by the time the app
|
||||
// starts up.
|
||||
if (ReloModel == Reloc::Static)
|
||||
return SectionKind::getROData();
|
||||
return SectionKind::getReadOnly();
|
||||
|
||||
// Otherwise, the dynamic linker needs to fix it up, put it in the
|
||||
// writable data.rel.local section.
|
||||
return SectionKind::getDataRelROLocal();
|
||||
return SectionKind::getReadOnlyWithRelLocal();
|
||||
|
||||
case Constant::GlobalRelocations:
|
||||
// In static relocation model, the linker will resolve all addresses, so
|
||||
// the relocation entries will actually be constants by the time the app
|
||||
// starts up.
|
||||
if (ReloModel == Reloc::Static)
|
||||
return SectionKind::getROData();
|
||||
return SectionKind::getReadOnly();
|
||||
|
||||
// Otherwise, the dynamic linker needs to fix it up, put it in the
|
||||
// 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
|
||||
// linker.
|
||||
if (ReloModel == Reloc::Static)
|
||||
return SectionKind::getData();
|
||||
return SectionKind::getDataNoRel();
|
||||
|
||||
switch (C->getRelocationInfo()) {
|
||||
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::GlobalRelocations: return SectionKind::getDataRel();
|
||||
}
|
||||
|
@ -342,7 +342,9 @@ const Section *TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
|
|||
const Section*
|
||||
TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV,
|
||||
SectionKind Kind) const {
|
||||
if (Kind.isCode())
|
||||
assert(!Kind.isThreadLocal() && "Doesn't support TLS");
|
||||
|
||||
if (Kind.isText())
|
||||
return getTextSection();
|
||||
|
||||
if (Kind.isBSS())
|
||||
|
|
|
@ -267,7 +267,7 @@ X86COFFTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
|
|||
|
||||
const char *X86COFFTargetAsmInfo::
|
||||
getSectionPrefixForUniqueGlobal(SectionKind Kind) const {
|
||||
if (Kind.isCode())
|
||||
if (Kind.isText())
|
||||
return ".text$linkonce";
|
||||
if (Kind.isWritable())
|
||||
return ".data$linkonce";
|
||||
|
|
Loading…
Reference in New Issue