Skip to content

Commit

Permalink
[X86] Change how we treat functions with explicit sections as small/l…
Browse files Browse the repository at this point in the history
…arge (#88172)

Following #78348, we should treat functions with an explicit section as
small, unless the section name is (or has the prefix) ".ltext".

Clang emits global initializers into a ".text.startup" section on Linux.
If we mix small/medium code model object files with large code model
object files, we'll end up mixing sections with and without the large
section flag.

Reland of #87838 with a check for non-ELF platforms in
TargetMachine::isLargeGlobalValue(), otherwise MCJIT on Windows tests
fail.
  • Loading branch information
aeubanks authored Apr 16, 2024
1 parent f430e37 commit 281d716
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
26 changes: 20 additions & 6 deletions llvm/lib/Target/TargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const {
if (getTargetTriple().getArch() != Triple::x86_64)
return false;

// Remaining logic below is ELF-specific. For other object file formats where
// the large code model is mostly used for JIT compilation, just look at the
// code model.
if (!getTargetTriple().isOSBinFormatELF())
return getCodeModel() == CodeModel::Large;

auto *GO = GVal->getAliaseeObject();

// Be conservative if we can't find an underlying GlobalObject.
Expand All @@ -51,9 +57,20 @@ bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const {

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

auto IsPrefix = [](StringRef Name, StringRef Prefix) {
return Name.consume_front(Prefix) && (Name.empty() || Name[0] == '.');
};

// Functions/GlobalIFuncs are only large under the large code model.
if (!GV)
if (!GV) {
// Handle explicit sections as we do for GlobalVariables with an explicit
// section, see comments below.
if (GO->hasSection()) {
StringRef Name = GO->getSection();
return IsPrefix(Name, ".ltext");
}
return getCodeModel() == CodeModel::Large;
}

if (GV->isThreadLocal())
return false;
Expand All @@ -73,11 +90,8 @@ bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const {
// data sections. The code model attribute overrides this above.
if (GV->hasSection()) {
StringRef Name = GV->getSection();
auto IsPrefix = [&](StringRef Prefix) {
StringRef S = Name;
return S.consume_front(Prefix) && (S.empty() || S[0] == '.');
};
return IsPrefix(".lbss") || IsPrefix(".ldata") || IsPrefix(".lrodata");
return IsPrefix(Name, ".lbss") || IsPrefix(Name, ".ldata") ||
IsPrefix(Name, ".lrodata");
}

// Respect large data threshold for medium and large code models.
Expand Down
23 changes: 23 additions & 0 deletions llvm/test/CodeGen/X86/code-model-elf-text-sections.ll
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,36 @@
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=LARGE-DS

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

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

define void @func() {
ret void
}

define void @ltext() section ".ltext" {
ret void
}

define void @ltext2() section ".ltext.2" {
ret void
}

define void @foo() section ".foo" {
ret void
}

0 comments on commit 281d716

Please sign in to comment.