diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 5de0bf58fe0..f97ab167118 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -189,6 +189,10 @@ public: return S->getVariant() == SV_ELF; } static bool classof(const MCSectionELF *) { return true; } + + // Return the entry size for sections with fixed-width data. + static unsigned DetermineEntrySize(SectionKind Kind); + }; } // end namespace llvm diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index e5586a0d7c3..1e65f877924 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -160,6 +160,10 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags, StringMapEntry &Entry = Map.GetOrCreateValue(Section); if (Entry.getValue()) return Entry.getValue(); + // Possibly refine the entry size first. + if (!EntrySize) { + EntrySize = MCSectionELF::DetermineEntrySize(Kind); + } MCSectionELF *Result = new (*this) MCSectionELF(Entry.getKey(), Type, Flags, Kind, IsExplicit, EntrySize); Entry.setValue(Result); diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index a7599de1b7b..ef935d0c64b 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -104,17 +104,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, else if (Type == MCSectionELF::SHT_PROGBITS) OS << "progbits"; - if (getKind().isMergeable1ByteCString()) { - OS << ",1"; - } else if (getKind().isMergeable2ByteCString()) { - OS << ",2"; - } else if (getKind().isMergeable4ByteCString() || - getKind().isMergeableConst4()) { - OS << ",4"; - } else if (getKind().isMergeableConst8()) { - OS << ",8"; - } else if (getKind().isMergeableConst16()) { - OS << ",16"; + if (EntrySize) { + OS << "," << EntrySize; } } @@ -132,4 +123,12 @@ bool MCSectionELF::HasCommonSymbols() const { return false; } - +unsigned MCSectionELF::DetermineEntrySize(SectionKind Kind) { + if (Kind.isMergeable1ByteCString()) return 1; + if (Kind.isMergeable2ByteCString()) return 2; + if (Kind.isMergeable4ByteCString()) return 4; + if (Kind.isMergeableConst4()) return 4; + if (Kind.isMergeableConst8()) return 8; + if (Kind.isMergeableConst16()) return 16; + return 0; +} diff --git a/test/MC/ELF/entsize.ll b/test/MC/ELF/entsize.ll new file mode 100644 index 00000000000..f8290d122d8 --- /dev/null +++ b/test/MC/ELF/entsize.ll @@ -0,0 +1,44 @@ +; RUN: llc -filetype=obj -mtriple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck -check-prefix=64 %s + +; Test that constant mergeable strings have sh_entsize set. + +@.str1 = private constant [6 x i8] c"tring\00" +@.str2 = private constant [7 x i8] c"String\00" +@.c8a = private constant [1 x i64] [i64 42] +@.c8b = private constant [1 x i64] [i64 42] + +define i32 @main() nounwind { + %1 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str1, i32 0, i32 0)) + %2 = call i32 @puts(i8* getelementptr inbounds ([7 x i8]* @.str2, i32 0, i32 0)) + call void @foo(i64* getelementptr inbounds ([1 x i64]* @.c8a, i32 0, i32 0)) + call void @foo(i64* getelementptr inbounds ([1 x i64]* @.c8b, i32 0, i32 0)) + ret i32 0 +} + +declare i32 @puts(i8* nocapture) nounwind +declare void @foo(i64* nocapture) nounwind + +;;;;; + +; 64: (('sh_name', 7) # '.rodata.str1.1' +; 64-NEXT: ('sh_type', 1) +; 64-NEXT: ('sh_flags', 50) +; 64-NEXT: ('sh_addr', +; 64-NEXT: ('sh_offset', +; 64-NEXT: ('sh_size', 13) +; 64-NEXT: ('sh_link', +; 64-NEXT: ('sh_info', +; 64-NEXT: ('sh_addralign', 1) +; 64-NEXT: ('sh_entsize', 1) + +; 64: (('sh_name', 22) # '.rodata.cst8' +; 64-NEXT: ('sh_type', 1) +; 64-NEXT: ('sh_flags', 18) +; 64-NEXT: ('sh_addr', +; 64-NEXT: ('sh_offset', +; 64-NEXT: ('sh_size', 16) +; 64-NEXT: ('sh_link', +; 64-NEXT: ('sh_info', +; 64-NEXT: ('sh_addralign', 8) +; 64-NEXT: ('sh_entsize', 8) +