Index: llvm/trunk/include/llvm/IR/GlobalObject.h =================================================================== --- llvm/trunk/include/llvm/IR/GlobalObject.h +++ llvm/trunk/include/llvm/IR/GlobalObject.h @@ -37,11 +37,11 @@ setGlobalValueSubClassData(0); } - std::string Section; // Section to emit this into, empty means default Comdat *ObjComdat; enum { LastAlignmentBit = 4, HasMetadataHashEntryBit, + HasSectionHashEntryBit, GlobalObjectBits, }; @@ -66,8 +66,26 @@ unsigned getGlobalObjectSubClassData() const; void setGlobalObjectSubClassData(unsigned Val); - bool hasSection() const { return !getSection().empty(); } - StringRef getSection() const { return Section; } + /// Check if this global has a custom object file section. + /// + /// This is more efficient than calling getSection() and checking for an empty + /// string. + bool hasSection() const { + return getGlobalValueSubClassData() & (1 << HasSectionHashEntryBit); + } + + /// Get the custom section of this global if it has one. + /// + /// If this global does not have a custom section, this will be empty and the + /// default object file section (.text, .data, etc) will be used. + StringRef getSection() const { + return hasSection() ? getSectionImpl() : StringRef(); + } + + /// Change the section for this global. + /// + /// Setting the section to the empty string tells LLVM to choose an + /// appropriate default object file section. void setSection(StringRef S); bool hasComdat() const { return getComdat() != nullptr; } @@ -134,14 +152,20 @@ void clearMetadata(); private: + void setGlobalObjectFlag(unsigned Bit, bool Val) { + unsigned Mask = 1 << Bit; + setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) | + (Val ? Mask : 0u)); + } + bool hasMetadataHashEntry() const { return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit); } void setHasMetadataHashEntry(bool HasEntry) { - unsigned Mask = 1 << HasMetadataHashEntryBit; - setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) | - (HasEntry ? Mask : 0u)); + setGlobalObjectFlag(HasMetadataHashEntryBit, HasEntry); } + + StringRef getSectionImpl() const; }; } // end namespace llvm Index: llvm/trunk/lib/IR/Globals.cpp =================================================================== --- llvm/trunk/lib/IR/Globals.cpp +++ llvm/trunk/lib/IR/Globals.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Operator.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "LLVMContextImpl.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -37,6 +38,10 @@ sizeof(Constant) + 2 * sizeof(void *) + 2 * sizeof(unsigned), "unexpected GlobalValue size growth"); +// GlobalObject adds a comdat. +static_assert(sizeof(GlobalObject) == sizeof(GlobalValue) + sizeof(void *), + "unexpected GlobalObject size growth"); + bool GlobalValue::isMaterializable() const { if (const Function *F = dyn_cast(this)) return F->isMaterializable(); @@ -160,11 +165,24 @@ return cast(this)->getComdat(); } -void GlobalObject::setSection(StringRef S) { - Section = S; +StringRef GlobalObject::getSectionImpl() const { + assert(hasSection()); + return getContext().pImpl->GlobalObjectSections[this]; +} - // The C api requires this to be null terminated. - Section.c_str(); +void GlobalObject::setSection(StringRef S) { + // Do nothing if we're clearing the section and it is already empty. + if (!hasSection() && S.empty()) + return; + + // Get or create a stable section name string and put it in the table in the + // context. + S = getContext().pImpl->SectionStrings.insert(S).first->first(); + getContext().pImpl->GlobalObjectSections[this] = S; + + // Update the HasSectionHashEntryBit. Setting the section to the empty string + // means this global no longer has a section. + setGlobalObjectFlag(HasSectionHashEntryBit, !S.empty()); } bool GlobalValue::isDeclaration() const { Index: llvm/trunk/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/trunk/lib/IR/LLVMContextImpl.h +++ llvm/trunk/lib/IR/LLVMContextImpl.h @@ -26,6 +26,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" @@ -1194,6 +1195,12 @@ /// Collection of per-GlobalObject metadata used in this context. DenseMap GlobalObjectMetadata; + /// Collection of per-GlobalObject sections used in this context. + DenseMap GlobalObjectSections; + + /// Stable collection of section strings. + StringSet<> SectionStrings; + /// DiscriminatorTable - This table maps file:line locations to an /// integer representing the next DWARF path discriminator to assign to /// instructions in different blocks at the same location.