Index: llvm/lib/Target/TargetLoweringObjectFile.cpp =================================================================== --- llvm/lib/Target/TargetLoweringObjectFile.cpp +++ llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -135,6 +135,26 @@ const MCSymbol *Sym) const { } +static bool inExplicitSection(const GlobalObject *GO, SectionKind Kind) { + if (GO->hasSection()) + return true; + + if (auto *GVar = dyn_cast(GO)) { + auto Attrs = GVar->getAttributes(); + if ((Attrs.hasAttribute("bss-section") && Kind.isBSS()) || + (Attrs.hasAttribute("data-section") && Kind.isData()) || + (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly())) { + return true; + } + } + + if (auto *F = dyn_cast(GO)) { + if (F->hasFnAttribute("implicit-section-name")) + return true; + } + + return false; +} /// getKindForGlobal - This is a top-level target-independent classifier for /// a global object. Given a global variable and information from the TM, this @@ -187,6 +207,15 @@ if (!GVar->hasGlobalUnnamedAddr()) return SectionKind::getReadOnly(); + // If two globals with differing sizes end up in the same mergeable section that + // section can be assigned an incorrect entry size. To avoid this we do not put + // globals into a mergeable section if they have been explicitly assigned to a section. + // TODO: This is a pessimistic solution as we lose the benifits of mergeable sections. A + // better solution might be to bin globals of the same size into difference mergeable + // sections with the same name. + if (inExplicitSection(GO, SectionKind::getReadOnly())) + return SectionKind::getReadOnly(); + // If initializer is a null-terminated string, put it in a "cstring" // section of the right width. if (ArrayType *ATy = dyn_cast(C->getType())) { @@ -245,24 +274,8 @@ /// available externally) globals. MCSection *TargetLoweringObjectFile::SectionForGlobal( const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { - // Select section name. - if (GO->hasSection()) + if (inExplicitSection(GO, Kind)) return getExplicitSectionGlobal(GO, Kind, TM); - - if (auto *GVar = dyn_cast(GO)) { - auto Attrs = GVar->getAttributes(); - if ((Attrs.hasAttribute("bss-section") && Kind.isBSS()) || - (Attrs.hasAttribute("data-section") && Kind.isData()) || - (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly())) { - return getExplicitSectionGlobal(GO, Kind, TM); - } - } - - if (auto *F = dyn_cast(GO)) { - if (F->hasFnAttribute("implicit-section-name")) - return getExplicitSectionGlobal(GO, Kind, TM); - } - // Use default section depending on the 'type' of global return SelectSectionForGlobal(GO, Kind, TM); } Index: llvm/test/CodeGen/X86/explict-section-mergeable.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/explict-section-mergeable.ll @@ -0,0 +1,22 @@ +; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck %s + +;; show that the implicitly generated sections are as expected +@implicit1 = unnamed_addr constant [2 x i16] [i16 1, i16 1] +; CHECK: .section .rodata.cst4,"aM",@progbits,4 +@implicit2 = unnamed_addr constant [2 x i32] [i32 1, i32 1] +; CHECK: .section .rodata.cst8,"aM",@progbits,8 +@implicit3 = unnamed_addr constant [2 x i16] [i16 1, i16 0] +; CHECK: .section .rodata.str2.2,"aMS",@progbits,2 + +;; Check that an explicitly created section is not SHF_MERGE and that +;; it contains all three symbols. +@explicit1 = unnamed_addr constant [2 x i16] [i16 1, i16 1] "rodata-section"=".explicit" +@explicit2 = unnamed_addr constant [2 x i32] [i32 1, i32 1] "rodata-section"=".explicit" +@explicit3 = unnamed_addr constant [2 x i16] [i16 1, i16 0] "rodata-section"=".explicit" +; CHECK: .section .explicit,"a",@progbits +; CHECK-NOT: .section +; CHECK: explicit1: +; CHECK-NOT: .section +; CHECK: explicit2: +; CHECK-NOT: .section +; CHECK: explicit3: Index: llvm/test/CodeGen/X86/section_mergeable_size.ll =================================================================== --- llvm/test/CodeGen/X86/section_mergeable_size.ll +++ /dev/null @@ -1,3 +0,0 @@ -; RUN: llc -mtriple x86_64-linux-gnu < %s | FileCheck %s -@a = internal unnamed_addr constant [1 x [1 x i32]] zeroinitializer, section ".init.rodata", align 4 -; CHECK: .init.rodata,"aM",{{[@%]}}progbits,4