Skip to content

Commit

Permalink
Reland [X86] With large code model, put functions into .ltext with la…
Browse files Browse the repository at this point in the history
…rge section flag (llvm#73037)

So that when mixing small and large text, large text stays out of the
way of the rest of the binary.

This is useful for mixing precompiled small code model object files and
built-from-source large code model binaries so that the the text
sections don't get merged.

The reland fixes an issue where a function in the large code model would reference small data without GOTOFF.

This was incorrectly reverted in 76f78ec.
  • Loading branch information
aeubanks committed Dec 1, 2023
1 parent 8206b75 commit d8a0439
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 51 deletions.
2 changes: 1 addition & 1 deletion llvm/include/llvm/Target/TargetMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class TargetMachine {
void setCodeModel(CodeModel::Model CM) { CMModel = CM; }

void setLargeDataThreshold(uint64_t LDT) { LargeDataThreshold = LDT; }
bool isLargeData(const GlobalVariable *GV) const;
bool isLargeGlobalObject(const GlobalObject *GO) const;

bool isPositionIndependent() const;

Expand Down
15 changes: 4 additions & 11 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ static unsigned getEntrySizeForKind(SectionKind Kind) {
/// DataSections.
static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) {
if (Kind.isText())
return ".text";
return IsLarge ? ".ltext" : ".text";
if (Kind.isReadOnly())
return IsLarge ? ".lrodata" : ".rodata";
if (Kind.isBSS())
Expand Down Expand Up @@ -650,10 +650,7 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
Name = ".rodata.cst";
Name += utostr(EntrySize);
} else {
bool IsLarge = false;
if (auto *GV = dyn_cast<GlobalVariable>(GO))
IsLarge = TM.isLargeData(GV);
Name = getSectionPrefixForGlobal(Kind, IsLarge);
Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalObject(GO));
}

bool HasPrefix = false;
Expand Down Expand Up @@ -773,12 +770,8 @@ getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) {
Group = C->getName();
IsComdat = C->getSelectionKind() == Comdat::Any;
}
if (auto *GV = dyn_cast<GlobalVariable>(GO)) {
if (TM.isLargeData(GV)) {
assert(TM.getTargetTriple().getArch() == Triple::x86_64);
Flags |= ELF::SHF_X86_64_LARGE;
}
}
if (TM.isLargeGlobalObject(GO))
Flags |= ELF::SHF_X86_64_LARGE;
return {Group, IsComdat, Flags};
}

Expand Down
12 changes: 10 additions & 2 deletions llvm/lib/Target/TargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,21 @@ TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,

TargetMachine::~TargetMachine() = default;

bool TargetMachine::isLargeData(const GlobalVariable *GV) const {
if (getTargetTriple().getArch() != Triple::x86_64 || GV->isThreadLocal())
bool TargetMachine::isLargeGlobalObject(const GlobalObject *GO) const {
if (getTargetTriple().getArch() != Triple::x86_64)
return false;

if (getCodeModel() != CodeModel::Medium && getCodeModel() != CodeModel::Large)
return false;

if (isa<Function>(GO))
return getCodeModel() == CodeModel::Large;

auto *GV = cast<GlobalVariable>(GO);

if (GV->isThreadLocal())
return false;

// Allowing large metadata sections in the presence of an explicit section is
// useful, even if GCC does not allow them. However, we should not mark
// certain well-known prefixes as large, because it would make the whole
Expand Down
38 changes: 13 additions & 25 deletions llvm/lib/Target/X86/X86Subtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,32 +83,20 @@ X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
if (is64Bit()) {
// 64-bit ELF PIC local references may use GOTOFF relocations.
if (isTargetELF()) {
switch (TM.getCodeModel()) {
// 64-bit small code model is simple: All rip-relative.
case CodeModel::Tiny:
llvm_unreachable("Tiny codesize model not supported on X86");
case CodeModel::Small:
case CodeModel::Kernel:
return X86II::MO_NO_FLAG;

// The large PIC code model uses GOTOFF.
case CodeModel::Large:
CodeModel::Model CM = TM.getCodeModel();
assert(CM != CodeModel::Tiny &&
"Tiny codesize model not supported on X86");
// In the large code model, even referencing a global under the large data
// threshold which is considered "small", we need to use GOTOFF.
if (CM == CodeModel::Large)
return X86II::MO_GOTOFF;

// Medium is a hybrid: RIP-rel for code and non-large data, GOTOFF for
// remaining DSO local data.
case CodeModel::Medium:
// Constant pool and jump table handling pass a nullptr to this
// function so we need to use isa_and_nonnull.
if (isa_and_nonnull<Function>(GV))
return X86II::MO_NO_FLAG; // All code is RIP-relative
if (auto *GVar = dyn_cast_or_null<GlobalVariable>(GV)) {
if (TM.isLargeData(GVar))
return X86II::MO_GOTOFF;
}
return X86II::MO_NO_FLAG; // Local symbols use GOTOFF.
}
llvm_unreachable("invalid code model");
// Large objects use GOTOFF, otherwise use RIP-rel access.
if (auto *GO = dyn_cast_or_null<GlobalObject>(GV))
return TM.isLargeGlobalObject(GO) ? X86II::MO_GOTOFF
: X86II::MO_NO_FLAG;
// For non-GlobalObjects, the small and medium code models treat them as
// accessible with a RIP-rel access.
return X86II::MO_NO_FLAG;
}

// Otherwise, this is either a RIP-relative reference or a 64-bit movabsq,
Expand Down
25 changes: 25 additions & 0 deletions llvm/test/CodeGen/X86/code-model-elf-text-sections.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=small -o %t
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -o %t
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -o %t
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=LARGE

; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=small -function-sections -o %t
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL-DS
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -function-sections -o %t
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL-DS
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -function-sections -o %t
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=LARGE-DS

; SMALL: .text {{.*}} AX {{.*}}
; SMALL-DS: .text.func {{.*}} AX {{.*}}
; LARGE: .ltext {{.*}} AXl {{.*}}
; LARGE-DS: .ltext.func {{.*}} AXl {{.*}}

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"

define void @func() {
ret void
}
1 change: 1 addition & 0 deletions llvm/test/CodeGen/X86/code-model-elf.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=medium -large-data-threshold=1000 | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-SMALL-DATA-PIC
; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=medium | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-PIC
; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-PIC
; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large -large-data-threshold=1000 | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-PIC

; Generated from this C source:
;
Expand Down
22 changes: 11 additions & 11 deletions llvm/test/CodeGen/X86/pcsections.ll
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ define void @empty_no_aux() !pcsections !0 {
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: retq
; CHECK-NEXT: .Lfunc_end0:
; CHECK: .section section_no_aux,"awo",@progbits,.text
; CHECK: .section section_no_aux,"awo",@progbits,.{{l?}}text
; CHECK-NEXT: .Lpcsection_base0:
; DEFCM-NEXT: .long .Lfunc_begin0-.Lpcsection_base0
; LARGE-NEXT: .quad .Lfunc_begin0-.Lpcsection_base0
; CHECK-NEXT: .long .Lfunc_end0-.Lfunc_begin0
; CHECK-NEXT: .text
; CHECK-NEXT: .{{l?}}text
entry:
ret void
}
Expand All @@ -35,15 +35,15 @@ define void @empty_aux() !pcsections !1 {
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: retq
; CHECK-NEXT: .Lfunc_end1:
; CHECK: .section section_aux,"awo",@progbits,.text
; CHECK: .section section_aux,"awo",@progbits,.{{l?}}text
; CHECK-NEXT: .Lpcsection_base1:
; DEFCM-NEXT: .long .Lfunc_begin1-.Lpcsection_base1
; LARGE-NEXT: .quad .Lfunc_begin1-.Lpcsection_base1
; CHECK-NEXT: .long .Lfunc_end1-.Lfunc_begin1
; CHECK-NEXT: .long 10
; CHECK-NEXT: .long 20
; CHECK-NEXT: .long 30
; CHECK-NEXT: .text
; CHECK-NEXT: .{{l?}}text
entry:
ret void
}
Expand All @@ -56,44 +56,44 @@ define i64 @multiple() !pcsections !0 {
; CHECK-NEXT: movq
; CHECK-NEXT: retq
; CHECK-NEXT: .Lfunc_end2:
; CHECK: .section section_no_aux,"awo",@progbits,.text
; CHECK: .section section_no_aux,"awo",@progbits,.{{l?}}text
; CHECK-NEXT: .Lpcsection_base2:
; DEFCM-NEXT: .long .Lfunc_begin2-.Lpcsection_base2
; LARGE-NEXT: .quad .Lfunc_begin2-.Lpcsection_base2
; CHECK-NEXT: .long .Lfunc_end2-.Lfunc_begin2
; CHECK-NEXT: .section section_aux_42,"awo",@progbits,.text
; CHECK-NEXT: .section section_aux_42,"awo",@progbits,.{{l?}}text
; CHECK-NEXT: .Lpcsection_base3:
; DEFCM-NEXT: .long .Lpcsection0-.Lpcsection_base3
; LARGE-NEXT: .quad .Lpcsection0-.Lpcsection_base3
; CHECK-NEXT: .long 42
; CHECK-NEXT: .section section_aux_21264,"awo",@progbits,.text
; CHECK-NEXT: .section section_aux_21264,"awo",@progbits,.{{l?}}text
; CHECK-NEXT: .Lpcsection_base4:
; DEFCM-NEXT: .long .Lpcsection0-.Lpcsection_base4
; LARGE-NEXT: .quad .Lpcsection0-.Lpcsection_base4
; CHECK-NEXT: .long 21264
; CHECK-NEXT: .text
; CHECK-NEXT: .{{l?}}text
entry:
%0 = load i64, ptr @bar, align 8, !pcsections !2
ret i64 %0
}

define void @multiple_uleb128() !pcsections !6 {
; CHECK-LABEL: multiple_uleb128:
; CHECK: .section section_aux,"awo",@progbits,.text
; CHECK: .section section_aux,"awo",@progbits,.{{l?}}text
; CHECK-NEXT: .Lpcsection_base5:
; DEFCM-NEXT: .long .Lfunc_begin3-.Lpcsection_base5
; LARGE-NEXT: .quad .Lfunc_begin3-.Lpcsection_base5
; CHECK-NEXT: .uleb128 .Lfunc_end3-.Lfunc_begin3
; CHECK-NEXT: .byte 42
; CHECK-NEXT: .ascii "\345\216&"
; CHECK-NEXT: .byte 255
; CHECK-NEXT: .section section_aux_21264,"awo",@progbits,.text
; CHECK-NEXT: .section section_aux_21264,"awo",@progbits,.{{l?}}text
; CHECK-NEXT: .Lpcsection_base6:
; DEFCM-NEXT: .long .Lfunc_begin3-.Lpcsection_base6
; LARGE-NEXT: .quad .Lfunc_begin3-.Lpcsection_base6
; CHECK-NEXT: .long .Lfunc_end3-.Lfunc_begin3
; CHECK-NEXT: .long 21264
; CHECK-NEXT: .text
; CHECK-NEXT: .{{l?}}text
entry:
ret void
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
; RUN: --generate=__dump_jit_debug_objects %s | llvm-objdump --section-headers - | \
; RUN: FileCheck --check-prefix=CHECK_LOAD_ADDR %s
;
; CHECK_LOAD_ADDR-NOT: {{[0-9]*}} .text {{.*}} 0000000000000000 TEXT
; CHECK_LOAD_ADDR-NOT: {{[0-9]*}} .ltext {{.*}} 0000000000000000 TEXT

target triple = "x86_64-unknown-unknown-elf"

Expand Down

0 comments on commit d8a0439

Please sign in to comment.