mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-23 16:19:52 +00:00
Add support for having multiple sections with the same name and comdat.
Using this in combination with -ffunction-sections allows LLVM to output a .o file with mulitple sections named .text. This saves space by avoiding long unique names of the form .text.<C++ mangled name>. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228980 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -207,6 +207,10 @@ FunctionSections("function-sections",
|
|||||||
cl::desc("Emit functions into separate sections"),
|
cl::desc("Emit functions into separate sections"),
|
||||||
cl::init(false));
|
cl::init(false));
|
||||||
|
|
||||||
|
cl::opt<bool> UniqueSectionNames("unique-section-names",
|
||||||
|
cl::desc("Give unique names to every section"),
|
||||||
|
cl::init(true));
|
||||||
|
|
||||||
cl::opt<llvm::JumpTable::JumpTableType>
|
cl::opt<llvm::JumpTable::JumpTableType>
|
||||||
JTableType("jump-table-type",
|
JTableType("jump-table-type",
|
||||||
cl::desc("Choose the type of Jump-Instruction Table for jumptable."),
|
cl::desc("Choose the type of Jump-Instruction Table for jumptable."),
|
||||||
@@ -284,6 +288,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
|
|||||||
Options.UseInitArray = !UseCtors;
|
Options.UseInitArray = !UseCtors;
|
||||||
Options.DataSections = DataSections;
|
Options.DataSections = DataSections;
|
||||||
Options.FunctionSections = FunctionSections;
|
Options.FunctionSections = FunctionSections;
|
||||||
|
Options.UniqueSectionNames = UniqueSectionNames;
|
||||||
|
|
||||||
Options.MCOptions = InitMCTargetOptionsFromFlags();
|
Options.MCOptions = InitMCTargetOptionsFromFlags();
|
||||||
Options.JTType = JTableType;
|
Options.JTType = JTableType;
|
||||||
|
|||||||
@@ -277,6 +277,10 @@ namespace llvm {
|
|||||||
unsigned Flags, unsigned EntrySize,
|
unsigned Flags, unsigned EntrySize,
|
||||||
StringRef Group);
|
StringRef Group);
|
||||||
|
|
||||||
|
const MCSectionELF *getELFSection(StringRef Section, unsigned Type,
|
||||||
|
unsigned Flags, unsigned EntrySize,
|
||||||
|
StringRef Group, bool Unique);
|
||||||
|
|
||||||
void renameELFSection(const MCSectionELF *Section, StringRef Name);
|
void renameELFSection(const MCSectionELF *Section, StringRef Name);
|
||||||
|
|
||||||
const MCSectionELF *CreateELFGroupSection();
|
const MCSectionELF *CreateELFGroupSection();
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ class MCSectionELF : public MCSection {
|
|||||||
/// below.
|
/// below.
|
||||||
unsigned Flags;
|
unsigned Flags;
|
||||||
|
|
||||||
|
bool Unique;
|
||||||
|
|
||||||
/// EntrySize - The size of each entry in this section. This size only
|
/// EntrySize - The size of each entry in this section. This size only
|
||||||
/// makes sense for sections that contain fixed-sized entries. If a
|
/// makes sense for sections that contain fixed-sized entries. If a
|
||||||
/// section does not contain fixed-sized entries 'EntrySize' will be 0.
|
/// section does not contain fixed-sized entries 'EntrySize' will be 0.
|
||||||
@@ -48,10 +50,10 @@ class MCSectionELF : public MCSection {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MCContext;
|
friend class MCContext;
|
||||||
MCSectionELF(StringRef Section, unsigned type, unsigned flags,
|
MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K,
|
||||||
SectionKind K, unsigned entrySize, const MCSymbol *group)
|
unsigned entrySize, const MCSymbol *group, bool Unique)
|
||||||
: MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags),
|
: MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags),
|
||||||
EntrySize(entrySize), Group(group) {}
|
Unique(Unique), EntrySize(entrySize), Group(group) {}
|
||||||
~MCSectionELF();
|
~MCSectionELF();
|
||||||
|
|
||||||
void setSectionName(StringRef Name) { SectionName = Name; }
|
void setSectionName(StringRef Name) { SectionName = Name; }
|
||||||
|
|||||||
@@ -171,6 +171,8 @@ public:
|
|||||||
return Options.MCOptions.AsmVerbose;
|
return Options.MCOptions.AsmVerbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getUniqueSectionNames() const { return Options.UniqueSectionNames; }
|
||||||
|
|
||||||
/// Return true if data objects should be emitted into their own section,
|
/// Return true if data objects should be emitted into their own section,
|
||||||
/// corresponds to -fdata-sections.
|
/// corresponds to -fdata-sections.
|
||||||
bool getDataSections() const {
|
bool getDataSections() const {
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ namespace llvm {
|
|||||||
EnableFastISel(false), PositionIndependentExecutable(false),
|
EnableFastISel(false), PositionIndependentExecutable(false),
|
||||||
UseInitArray(false), DisableIntegratedAS(false),
|
UseInitArray(false), DisableIntegratedAS(false),
|
||||||
CompressDebugSections(false), FunctionSections(false),
|
CompressDebugSections(false), FunctionSections(false),
|
||||||
DataSections(false), TrapUnreachable(false), TrapFuncName(),
|
DataSections(false), UniqueSectionNames(true), TrapUnreachable(false),
|
||||||
FloatABIType(FloatABI::Default),
|
TrapFuncName(), FloatABIType(FloatABI::Default),
|
||||||
AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
|
AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
|
||||||
FCFI(false), ThreadModel(ThreadModel::POSIX),
|
FCFI(false), ThreadModel(ThreadModel::POSIX),
|
||||||
CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}
|
CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}
|
||||||
@@ -198,6 +198,8 @@ namespace llvm {
|
|||||||
/// Emit data into separate sections.
|
/// Emit data into separate sections.
|
||||||
unsigned DataSections : 1;
|
unsigned DataSections : 1;
|
||||||
|
|
||||||
|
unsigned UniqueSectionNames : 1;
|
||||||
|
|
||||||
/// Emit target-specific trap instruction for 'unreachable' IR instructions.
|
/// Emit target-specific trap instruction for 'unreachable' IR instructions.
|
||||||
unsigned TrapUnreachable : 1;
|
unsigned TrapUnreachable : 1;
|
||||||
|
|
||||||
|
|||||||
@@ -228,25 +228,25 @@ const MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
|
|||||||
/// DataSections.
|
/// DataSections.
|
||||||
static StringRef getSectionPrefixForGlobal(SectionKind Kind) {
|
static StringRef getSectionPrefixForGlobal(SectionKind Kind) {
|
||||||
if (Kind.isText())
|
if (Kind.isText())
|
||||||
return ".text.";
|
return ".text";
|
||||||
if (Kind.isReadOnly())
|
if (Kind.isReadOnly())
|
||||||
return ".rodata.";
|
return ".rodata";
|
||||||
if (Kind.isBSS())
|
if (Kind.isBSS())
|
||||||
return ".bss.";
|
return ".bss";
|
||||||
if (Kind.isThreadData())
|
if (Kind.isThreadData())
|
||||||
return ".tdata.";
|
return ".tdata";
|
||||||
if (Kind.isThreadBSS())
|
if (Kind.isThreadBSS())
|
||||||
return ".tbss.";
|
return ".tbss";
|
||||||
if (Kind.isDataNoRel())
|
if (Kind.isDataNoRel())
|
||||||
return ".data.";
|
return ".data";
|
||||||
if (Kind.isDataRelLocal())
|
if (Kind.isDataRelLocal())
|
||||||
return ".data.rel.local.";
|
return ".data.rel.local";
|
||||||
if (Kind.isDataRel())
|
if (Kind.isDataRel())
|
||||||
return ".data.rel.";
|
return ".data.rel";
|
||||||
if (Kind.isReadOnlyWithRelLocal())
|
if (Kind.isReadOnlyWithRelLocal())
|
||||||
return ".data.rel.ro.local.";
|
return ".data.rel.ro.local";
|
||||||
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
|
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
|
||||||
return ".data.rel.ro.";
|
return ".data.rel.ro";
|
||||||
}
|
}
|
||||||
|
|
||||||
const MCSection *TargetLoweringObjectFileELF::
|
const MCSection *TargetLoweringObjectFileELF::
|
||||||
@@ -268,16 +268,19 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
|||||||
StringRef Prefix = getSectionPrefixForGlobal(Kind);
|
StringRef Prefix = getSectionPrefixForGlobal(Kind);
|
||||||
|
|
||||||
SmallString<128> Name(Prefix);
|
SmallString<128> Name(Prefix);
|
||||||
|
bool UniqueSectionNames = TM.getUniqueSectionNames();
|
||||||
|
if (UniqueSectionNames) {
|
||||||
|
Name.push_back('.');
|
||||||
TM.getNameWithPrefix(Name, GV, Mang, true);
|
TM.getNameWithPrefix(Name, GV, Mang, true);
|
||||||
|
}
|
||||||
StringRef Group = "";
|
StringRef Group = "";
|
||||||
if (const Comdat *C = getELFComdat(GV)) {
|
if (const Comdat *C = getELFComdat(GV)) {
|
||||||
Flags |= ELF::SHF_GROUP;
|
Flags |= ELF::SHF_GROUP;
|
||||||
Group = C->getName();
|
Group = C->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
return getContext().getELFSection(
|
return getContext().getELFSection(Name, getELFSectionType(Name, Kind),
|
||||||
Name.str(), getELFSectionType(Name.str(), Kind), Flags, 0, Group);
|
Flags, 0, Group, !UniqueSectionNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Kind.isText()) return TextSection;
|
if (Kind.isText()) return TextSection;
|
||||||
|
|||||||
@@ -1151,7 +1151,7 @@ ELFObjectWriter::createRelocationSection(MCAssembler &Asm,
|
|||||||
|
|
||||||
const MCSectionELF *RelaSection = Ctx.getELFSection(
|
const MCSectionELF *RelaSection = Ctx.getELFSection(
|
||||||
RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
|
RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
|
||||||
Flags, EntrySize, Group);
|
Flags, EntrySize, Group, true);
|
||||||
return &Asm.getOrCreateSectionData(*RelaSection);
|
return &Asm.getOrCreateSectionData(*RelaSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,12 +272,13 @@ void MCContext::renameELFSection(const MCSectionELF *Section, StringRef Name) {
|
|||||||
|
|
||||||
const MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type,
|
const MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type,
|
||||||
unsigned Flags, unsigned EntrySize,
|
unsigned Flags, unsigned EntrySize,
|
||||||
StringRef Group) {
|
StringRef Group, bool Unique) {
|
||||||
// Do the lookup, if we have a hit, return it.
|
// Do the lookup, if we have a hit, return it.
|
||||||
auto IterBool = ELFUniquingMap.insert(
|
auto IterBool = ELFUniquingMap.insert(
|
||||||
std::make_pair(SectionGroupPair(Section, Group), nullptr));
|
std::make_pair(SectionGroupPair(Section, Group), nullptr));
|
||||||
auto &Entry = *IterBool.first;
|
auto &Entry = *IterBool.first;
|
||||||
if (!IterBool.second) return Entry.second;
|
if (!IterBool.second && !Unique)
|
||||||
|
return Entry.second;
|
||||||
|
|
||||||
MCSymbol *GroupSym = nullptr;
|
MCSymbol *GroupSym = nullptr;
|
||||||
if (!Group.empty())
|
if (!Group.empty())
|
||||||
@@ -292,15 +293,22 @@ const MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type,
|
|||||||
Kind = SectionKind::getReadOnly();
|
Kind = SectionKind::getReadOnly();
|
||||||
|
|
||||||
MCSectionELF *Result = new (*this)
|
MCSectionELF *Result = new (*this)
|
||||||
MCSectionELF(CachedName, Type, Flags, Kind, EntrySize, GroupSym);
|
MCSectionELF(CachedName, Type, Flags, Kind, EntrySize, GroupSym, Unique);
|
||||||
|
if (!Unique)
|
||||||
Entry.second = Result;
|
Entry.second = Result;
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type,
|
||||||
|
unsigned Flags, unsigned EntrySize,
|
||||||
|
StringRef Group) {
|
||||||
|
return getELFSection(Section, Type, Flags, EntrySize, Group, false);
|
||||||
|
}
|
||||||
|
|
||||||
const MCSectionELF *MCContext::CreateELFGroupSection() {
|
const MCSectionELF *MCContext::CreateELFGroupSection() {
|
||||||
MCSectionELF *Result =
|
MCSectionELF *Result =
|
||||||
new (*this) MCSectionELF(".group", ELF::SHT_GROUP, 0,
|
new (*this) MCSectionELF(".group", ELF::SHT_GROUP, 0,
|
||||||
SectionKind::getReadOnly(), 4, nullptr);
|
SectionKind::getReadOnly(), 4, nullptr, false);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -378,6 +378,8 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
|
|||||||
unsigned Flags = 0;
|
unsigned Flags = 0;
|
||||||
const MCExpr *Subsection = nullptr;
|
const MCExpr *Subsection = nullptr;
|
||||||
bool UseLastGroup = false;
|
bool UseLastGroup = false;
|
||||||
|
StringRef UniqueStr;
|
||||||
|
bool Unique = false;
|
||||||
|
|
||||||
// Set the defaults first.
|
// Set the defaults first.
|
||||||
if (SectionName == ".fini" || SectionName == ".init" ||
|
if (SectionName == ".fini" || SectionName == ".init" ||
|
||||||
@@ -462,6 +464,14 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
|
|||||||
return TokError("Linkage must be 'comdat'");
|
return TokError("Linkage must be 'comdat'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (getLexer().is(AsmToken::Comma)) {
|
||||||
|
Lex();
|
||||||
|
if (getParser().parseIdentifier(UniqueStr))
|
||||||
|
return TokError("expected identifier in directive");
|
||||||
|
if (UniqueStr != "unique")
|
||||||
|
return TokError("expected 'unique'");
|
||||||
|
Unique = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,8 +519,8 @@ EndStmt:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MCSection *ELFSection =
|
const MCSection *ELFSection = getContext().getELFSection(
|
||||||
getContext().getELFSection(SectionName, Type, Flags, Size, GroupName);
|
SectionName, Type, Flags, Size, GroupName, Unique);
|
||||||
getStreamer().SwitchSection(ELFSection, Subsection);
|
getStreamer().SwitchSection(ELFSection, Subsection);
|
||||||
|
|
||||||
if (getContext().getGenDwarfForAssembly()) {
|
if (getContext().getGenDwarfForAssembly()) {
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ MCSectionELF::~MCSectionELF() {} // anchor.
|
|||||||
bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
|
bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
|
||||||
const MCAsmInfo &MAI) const {
|
const MCAsmInfo &MAI) const {
|
||||||
|
|
||||||
|
if (Unique)
|
||||||
|
return false;
|
||||||
|
|
||||||
// FIXME: Does .section .bss/.data/.text work everywhere??
|
// FIXME: Does .section .bss/.data/.text work everywhere??
|
||||||
if (Name == ".text" || Name == ".data" ||
|
if (Name == ".text" || Name == ".data" ||
|
||||||
(Name == ".bss" && !MAI.usesELFSectionDirectiveForBSS()))
|
(Name == ".bss" && !MAI.usesELFSectionDirectiveForBSS()))
|
||||||
@@ -144,6 +147,10 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
|
|||||||
printName(OS, Group->getName());
|
printName(OS, Group->getName());
|
||||||
OS << ",comdat";
|
OS << ",comdat";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Unique)
|
||||||
|
OS << ",unique";
|
||||||
|
|
||||||
OS << '\n';
|
OS << '\n';
|
||||||
|
|
||||||
if (Subsection)
|
if (Subsection)
|
||||||
|
|||||||
15
test/CodeGen/X86/non-unique-sections.ll
Normal file
15
test/CodeGen/X86/non-unique-sections.ll
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
; RUN: llc < %s -mtriple=x86_64-pc-linux -function-sections -unique-section-names=false | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK: .section .text,"ax",@progbits,unique
|
||||||
|
; CHECK-NOT: section
|
||||||
|
; CHECK: f:
|
||||||
|
define void @f() {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: .section .text,"ax",@progbits,unique
|
||||||
|
; CHECK-NOT: section
|
||||||
|
; CHECK: g:
|
||||||
|
define void @g() {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
39
test/MC/ELF/section-unique.s
Normal file
39
test/MC/ELF/section-unique.s
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// RUN: llvm-mc -triple x86_64-pc-linux-gnu %s -o - | FileCheck %s
|
||||||
|
// RUN: llvm-mc -triple x86_64-pc-linux-gnu %s -filetype=obj -o - | llvm-readobj -t | FileCheck %s --check-prefix=OBJ
|
||||||
|
|
||||||
|
.section .text,"ax",@progbits,unique
|
||||||
|
.globl f
|
||||||
|
f:
|
||||||
|
nop
|
||||||
|
|
||||||
|
.section .text,"ax",@progbits,unique
|
||||||
|
.globl g
|
||||||
|
g:
|
||||||
|
nop
|
||||||
|
|
||||||
|
// test that f and g are in different sections.
|
||||||
|
|
||||||
|
// CHECK: .section .text,"ax",@progbits,unique
|
||||||
|
// CHECK: f:
|
||||||
|
|
||||||
|
// CHECK: .section .text,"ax",@progbits,unique
|
||||||
|
// CHECK: g:
|
||||||
|
|
||||||
|
// OBJ: Symbol {
|
||||||
|
// OBJ: Name: f
|
||||||
|
// OBJ: Value: 0x0
|
||||||
|
// OBJ: Size: 0
|
||||||
|
// OBJ: Binding: Global
|
||||||
|
// OBJ: Type: None
|
||||||
|
// OBJ: Other: 0
|
||||||
|
// OBJ: Section: .text (0x4)
|
||||||
|
// OBJ: }
|
||||||
|
// OBJ: Symbol {
|
||||||
|
// OBJ: Name: g
|
||||||
|
// OBJ: Value: 0x0
|
||||||
|
// OBJ: Size: 0
|
||||||
|
// OBJ: Binding: Global
|
||||||
|
// OBJ: Type: None
|
||||||
|
// OBJ: Other: 0
|
||||||
|
// OBJ: Section: .text (0x5)
|
||||||
|
// OBJ: }
|
||||||
Reference in New Issue
Block a user