diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -235,6 +235,8 @@ /// Set the code model. void setCodeModel(CodeModel::Model CM) { CMModel = CM; } + bool isLargeData() const; + bool isPositionIndependent() const; bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const; diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -614,21 +614,21 @@ /// Return the section prefix name used by options FunctionsSections and /// DataSections. -static StringRef getSectionPrefixForGlobal(SectionKind Kind) { +static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) { if (Kind.isText()) return ".text"; if (Kind.isReadOnly()) - return ".rodata"; + return IsLarge ? ".lrodata" : ".rodata"; if (Kind.isBSS()) - return ".bss"; + return IsLarge ? ".lbss" : ".bss"; if (Kind.isThreadData()) return ".tdata"; if (Kind.isThreadBSS()) return ".tbss"; if (Kind.isData()) - return ".data"; + return IsLarge ? ".ldata" : ".data"; if (Kind.isReadOnlyWithRel()) - return ".data.rel.ro"; + return IsLarge ? ".ldata.rel.ro" : ".data.rel.ro"; llvm_unreachable("Unknown section kind"); } @@ -650,7 +650,10 @@ Name = ".rodata.cst"; Name += utostr(EntrySize); } else { - Name = getSectionPrefixForGlobal(Kind); + bool IsLarge = false; + if (isa(GO)) + IsLarge = TM.isLargeData(); + Name = getSectionPrefixForGlobal(Kind, IsLarge); } bool HasPrefix = false; @@ -852,6 +855,12 @@ Group = C->getName(); IsComdat = C->getSelectionKind() == Comdat::Any; } + if (isa(GO)) { + if (TM.isLargeData()) { + assert(TM.getTargetTriple().getArch() == Triple::x86_64); + Flags |= ELF::SHF_X86_64_LARGE; + } + } // Get the section entry size based on the kind. unsigned EntrySize = getEntrySizeForKind(Kind); @@ -2165,7 +2174,7 @@ } bool UniqueSectionNames = TM.getUniqueSectionNames(); - SmallString<128> Name = getSectionPrefixForGlobal(Kind); + SmallString<128> Name = getSectionPrefixForGlobal(Kind, /*IsLarge=*/false); if (const auto *F = dyn_cast(GO)) { const auto &OptionalPrefix = F->getSectionPrefix(); diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -21,6 +21,7 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetLoweringObjectFile.h" using namespace llvm; @@ -38,6 +39,16 @@ TargetMachine::~TargetMachine() = default; +bool TargetMachine::isLargeData() const { + if (getTargetTriple().getArch() != Triple::x86_64) + return false; + // Large data under the large code model still needs to be thought about, so + // restrict this to medium. + if (getCodeModel() != CodeModel::Medium) + return false; + return true; +} + bool TargetMachine::isPositionIndependent() const { return getRelocationModel() == Reloc::PIC_; } diff --git a/llvm/test/CodeGen/X86/code-model-elf-sections.ll b/llvm/test/CodeGen/X86/code-model-elf-sections.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/code-model-elf-sections.ll @@ -0,0 +1,81 @@ +; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=small -o %t +; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=SMALL +; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -o %t +; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=LARGE +; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -o %t +; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=SMALL + +; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=small -data-sections -o %t +; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=SMALL +; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -data-sections -o %t +; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=LARGE +; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -data-sections -o %t +; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=SMALL + +; LARGE: Name: .ldata +; LARGE-NEXT: Type: SHT_PROGBITS +; LARGE-NEXT: Flags [ +; LARGE-NEXT: SHF_ALLOC +; LARGE-NEXT: SHF_WRITE +; LARGE-NEXT: SHF_X86_64_LARGE +; LARGE-NEXT: ] + +; LARGE: Name: .lbss +; LARGE-NEXT: Type: SHT_NOBITS +; LARGE-NEXT: Flags [ +; LARGE-NEXT: SHF_ALLOC +; LARGE-NEXT: SHF_WRITE +; LARGE-NEXT: SHF_X86_64_LARGE +; LARGE-NEXT: ] + +; LARGE: Name: .lrodata +; LARGE-NEXT: Type: SHT_PROGBITS +; LARGE-NEXT: Flags [ +; LARGE-NEXT: SHF_ALLOC +; LARGE-NEXT: SHF_X86_64_LARGE +; LARGE-NEXT: ] + +; LARGE: Name: .ldata.rel.ro +; LARGE-NEXT: Type: SHT_PROGBITS +; LARGE-NEXT: Flags [ +; LARGE-NEXT: SHF_ALLOC +; LARGE-NEXT: SHF_WRITE +; LARGE-NEXT: SHF_X86_64_LARGE +; LARGE-NEXT: ] + +; SMALL: Name: .data +; SMALL-NEXT: Type: SHT_PROGBITS +; SMALL-NEXT: Flags [ +; SMALL-NEXT: SHF_ALLOC +; SMALL-NEXT: SHF_WRITE +; SMALL-NEXT: ] + +; SMALL: Name: .bss +; SMALL-NEXT: Type: SHT_NOBITS +; SMALL-NEXT: Flags [ +; SMALL-NEXT: SHF_ALLOC +; SMALL-NEXT: SHF_WRITE +; SMALL-NEXT: ] + +; SMALL: Name: .rodata +; SMALL-NEXT: Type: SHT_PROGBITS +; SMALL-NEXT: Flags [ +; SMALL-NEXT: SHF_ALLOC +; SMALL-NEXT: ] + +; SMALL: Name: .data.rel.ro +; SMALL-NEXT: Type: SHT_PROGBITS +; SMALL-NEXT: Flags [ +; SMALL-NEXT: SHF_ALLOC +; SMALL-NEXT: SHF_WRITE +; SMALL-NEXT: ] + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64--linux" + +@data = internal global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], align 16 +@bss = internal global [10 x i32] zeroinitializer, align 16 +@rodata = internal constant [10 x i32] zeroinitializer, align 16 +@relro = internal constant ptr @func, align 16 + +declare void @func()