diff options
-rw-r--r-- | include/llvm/Target/TargetAsmInfo.h | 165 | ||||
-rw-r--r-- | lib/Target/DarwinTargetAsmInfo.cpp | 18 | ||||
-rw-r--r-- | lib/Target/ELFTargetAsmInfo.cpp | 65 | ||||
-rw-r--r-- | lib/Target/TargetAsmInfo.cpp | 26 | ||||
-rw-r--r-- | lib/Target/X86/X86TargetAsmInfo.cpp | 2 |
5 files changed, 173 insertions, 103 deletions
diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index 59fb8c9..f9105dd 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -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. - - 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. + /// Text - Text section, used for functions and other executable code. + Text, + + /// 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, + + /// 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, - /// Mergable sections. - RODataMergeStr, ///< Readonly data section: nul-terminated strings. - RODataMergeConst, ///< Readonly data section: fixed-length constants. + /// 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; + bool isText() const { + return K == Text; } - /// 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 isReadOnly() const { + return K == ReadOnly || K == MergableCString || K == MergableConst; } - bool isBSS() const { - return K == BSS || K == ThreadBSS; + bool isMergableCString() const { return K == MergableCString; } + bool isMergableConst() const { return K == MergableConst; } + + bool isWritable() const { + return isThreadLocal() || isGlobalWritableData(); } - bool isTLS() const { + bool isThreadLocal() const { return K == ThreadData || K == ThreadBSS; } - bool isCode() const { - return K == Text; + bool isThreadBSS() const { return K == ThreadBSS; } + bool isThreadData() const { return K == ThreadData; } + + bool isGlobalWritableData() const { + return isBSS() || isDataRel() || isReadOnlyWithRel(); } - bool isWritable() const { - return isTLS() || - K == Data || - K == DataRel || K == DataRelLocal || - K == DataRelRO || K == DataRelROLocal || - K == BSS; + bool isBSS() const { return K == BSS; } + + bool isDataRel() const { + return K == DataRel || K == DataRelLocal || K == DataNoRel; } - bool isMergableString() const { return K == RODataMergeStr; } - bool isMergableConstant() const { - return K == RODataMergeStr || K == RODataMergeConst; + 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 { diff --git a/lib/Target/DarwinTargetAsmInfo.cpp b/lib/Target/DarwinTargetAsmInfo.cpp index 1356f67..7321b18 100644 --- a/lib/Target/DarwinTargetAsmInfo.cpp +++ b/lib/Target/DarwinTargetAsmInfo.cpp @@ -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,24 +144,24 @@ 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; diff --git a/lib/Target/ELFTargetAsmInfo.cpp b/lib/Target/ELFTargetAsmInfo.cpp index 880dfbc..c401109 100644 --- a/lib/Target/ELFTargetAsmInfo.cpp +++ b/lib/Target/ELFTargetAsmInfo.cpp @@ -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."; } diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp index c3fb942..02e01be 100644 --- a/lib/Target/TargetAsmInfo.cpp +++ b/lib/Target/TargetAsmInfo.cpp @@ -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()) diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp index 39dfb00..9e7973a 100644 --- a/lib/Target/X86/X86TargetAsmInfo.cpp +++ b/lib/Target/X86/X86TargetAsmInfo.cpp @@ -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"; |