[lld] [llvm] [LLD][ELF] Support for SHN_AMD64_LCOMMON and lbss on x86-64 (PR #161697)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 2 09:41:24 PDT 2025
https://github.com/ssijaric-nv created https://github.com/llvm/llvm-project/pull/161697
Place LARGE_COMMON (SHN_AMD64_LCOMMON) into lbss on x86-64. Needed to
support large Fortran common blocks with medium and large code models on
x86-64:
Sections:
...
25 .lbss b44834508 0000000000004060 0000000000004060 0000304c 2**3
ALLOC
...
SYMBOL TABLE:
...
0000000000004060 g O .lbss 0000000b44834508 __BLNK__
where __BLNK__ is a large common block resulting from:
program test
implicit integer (i-n)
implicit real*8 (a-h, o-z)
parameter (n1=77777, n2=77777)
common v2(n1,n2)
common /ccc/ v6
v6 = 1
v2(6777,6777) = 2
write (*,*) v6, v2(6777, 6777)
end program test
There is a sperate PR for emitting SHN_AMD64_LCOMMON.
>From 9cdc2dba013e4360288c88656f4ea4a539677362 Mon Sep 17 00:00:00 2001
From: Sanjin Sijaric <ssijaric at nvidia.com>
Date: Wed, 1 Oct 2025 15:50:07 -0700
Subject: [PATCH] [LLD][ELF] Support for SHN_AMD64_LCOMMON and lbss on x86-64
Place LARGE_COMMON (SHN_AMD64_LCOMMON) into lbss on x86-64. Needed to
support large Fortran common blocks with medium and large code models on
x86-64:
Sections:
...
25 .lbss b44834508 0000000000004060 0000000000004060 0000304c 2**3
ALLOC
...
SYMBOL TABLE:
...
0000000000004060 g O .lbss 0000000b44834508 __BLNK__
where __BLNK__ is a large common block resulting from:
program test
implicit integer (i-n)
implicit real*8 (a-h, o-z)
parameter (n1=77777, n2=77777)
common v2(n1,n2)
common /ccc/ v6
v6 = 1
v2(6777,6777) = 2
write (*,*) v6, v2(6777, 6777)
end program test
There is a sperate PR for emitting SHN_AMD64_LCOMMON.
---
lld/ELF/Driver.cpp | 5 ++++-
lld/ELF/InputFiles.cpp | 8 ++++++--
lld/ELF/InputSection.cpp | 2 +-
lld/ELF/InputSection.h | 1 +
lld/ELF/LinkerScript.cpp | 6 +++++-
lld/ELF/Symbols.h | 8 +++++---
lld/ELF/SyntheticSections.cpp | 6 ++++++
lld/ELF/SyntheticSections.h | 13 ++++++++++++-
llvm/include/llvm/BinaryFormat/ELF.h | 5 +++++
9 files changed, 45 insertions(+), 9 deletions(-)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 1beab8d33f4ba..013c8ae6f7ddd 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2530,7 +2530,10 @@ static void replaceCommonSymbols(Ctx &ctx) {
if (!s)
continue;
- auto *bss = make<BssSection>(ctx, "COMMON", s->size, s->alignment);
+ auto *bss =
+ (s->isLargeCommon)
+ ? make<LbssSection>(ctx, "LARGE_COMMON", s->size, s->alignment)
+ : make<BssSection>(ctx, "COMMON", s->size, s->alignment);
bss->file = s->file;
ctx.inputSections.push_back(bss);
Defined(ctx, s->file, StringRef(), s->binding, s->stOther, s->type,
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index a5921feb18299..413f3a600174f 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1223,13 +1223,17 @@ void ObjFile<ELFT>::initializeSymbols(const object::ELFFile<ELFT> &obj) {
Symbol *sym = symbols[i];
sym->isUsedInRegularObj = true;
- if (LLVM_UNLIKELY(eSym.st_shndx == SHN_COMMON)) {
+
+ bool isLargeCommon = LLVM_UNLIKELY(eSym.st_shndx == SHN_AMD64_LCOMMON) &&
+ ctx.arg.emachine == EM_X86_64;
+ if (LLVM_UNLIKELY(eSym.st_shndx == SHN_COMMON) || isLargeCommon) {
+
if (value == 0 || value >= UINT32_MAX)
Err(ctx) << this << ": common symbol '" << sym->getName()
<< "' has invalid alignment: " << value;
hasCommonSyms = true;
sym->resolve(ctx, CommonSymbol{ctx, this, StringRef(), binding, stOther,
- type, value, size});
+ type, value, size, isLargeCommon});
continue;
}
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index ff7ef2dce5c79..8dc4241bc6bde 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -59,7 +59,7 @@ InputSectionBase::InputSectionBase(InputFile *file, StringRef name,
Kind sectionKind)
: SectionBase(sectionKind, file, name, type, flags, link, info, addralign,
entsize),
- bss(0), decodedCrel(0), keepUnique(0), nopFiller(0),
+ bss(0), lbss(0), decodedCrel(0), keepUnique(0), nopFiller(0),
content_(data.data()), size(data.size()) {
// In order to reduce memory allocation, we assume that mergeable
// sections are smaller than 4 GiB, which is not an unreasonable
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index dc29fedbc5c53..74d6f4db5c1bc 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -168,6 +168,7 @@ class InputSectionBase : public SectionBase {
LLVM_PREFERRED_TYPE(bool)
uint8_t bss : 1;
+ uint8_t lbss : 1;
// Whether this section is SHT_CREL and has been decoded to RELA by
// relsOrRelas.
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 218c9d3a86184..0fbda4396dd88 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -70,9 +70,13 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
return s->name;
// A BssSection created for a common symbol is identified as "COMMON" in
- // linker scripts. It should go to .bss section.
+ // linker scripts. It should go to .bss section. A large bss section,
+ // LbssCommon, created for a large common symbol is identified as
+ // "LARGE_COMMON".
if (s->name == "COMMON")
return ".bss";
+ else if (s->name == "LARGE_COMMON")
+ return ".lbss";
if (hasSectionsCommand)
return s->name;
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index c117e3b716c1b..6cec6d40b6c91 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -408,21 +408,23 @@ class Defined : public Symbol {
class CommonSymbol : public Symbol {
public:
CommonSymbol(Ctx &ctx, InputFile *file, StringRef name, uint8_t binding,
- uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size)
+ uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size,
+ bool isLargeCommon = false)
: Symbol(CommonKind, file, name, binding, stOther, type),
- alignment(alignment), size(size) {
- }
+ alignment(alignment), size(size), isLargeCommon(isLargeCommon) {}
void overwrite(Symbol &sym) const {
Symbol::overwrite(sym, CommonKind);
auto &s = static_cast<CommonSymbol &>(sym);
s.alignment = alignment;
s.size = size;
+ s.isLargeCommon = isLargeCommon;
}
static bool classof(const Symbol *s) { return s->isCommon(); }
uint32_t alignment;
uint64_t size;
+ bool isLargeCommon;
};
class Undefined : public Symbol {
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index bbf4b29a9fda5..0a3394cf9880c 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -397,6 +397,12 @@ BssSection::BssSection(Ctx &ctx, StringRef name, uint64_t size,
this->size = size;
}
+LbssSection::LbssSection(Ctx &ctx, StringRef name, uint64_t size,
+ uint32_t alignment)
+ : BssSection(ctx, name, size, alignment) {
+ this->lbss = true;
+}
+
EhFrameSection::EhFrameSection(Ctx &ctx)
: SyntheticSection(ctx, ".eh_frame", SHT_PROGBITS, SHF_ALLOC, 1) {}
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index ac3ec63f0a7a5..b7d8f86be4a0a 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -172,7 +172,7 @@ class BuildIdSection : public SyntheticSection {
// We create three instances of this class for .bss, .bss.rel.ro and "COMMON",
// that are used for writable symbols, read-only symbols and common symbols,
// respectively.
-class BssSection final : public SyntheticSection {
+class BssSection : public SyntheticSection {
public:
BssSection(Ctx &, StringRef name, uint64_t size, uint32_t addralign);
void writeTo(uint8_t *) override {}
@@ -185,6 +185,17 @@ class BssSection final : public SyntheticSection {
uint64_t size;
};
+// LbssSection is used to reserve space for large common symbols on x86-64,
+// "LARGE_COMMON".
+class LbssSection final : public BssSection {
+public:
+ LbssSection(Ctx &, StringRef name, uint64_t size, uint32_t addralign);
+
+ static bool classof(const SectionBase *s) {
+ return isa<SyntheticSection>(s) && cast<SyntheticSection>(s)->lbss;
+ }
+};
+
class MipsGotSection final : public SyntheticSection {
public:
MipsGotSection(Ctx &);
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index e619b186dfe3d..ca6ec30e1f95e 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -589,6 +589,11 @@ enum {
SHN_MIPS_SUNDEFINED = 0xff04 // Undefined symbols for global data area
};
+// x86-64 speciifc section index
+enum {
+ SHN_AMD64_LCOMMON = 0xff02, // Large FORTRAN COMMON variables
+};
+
// ELF Relocation types for Mips
enum {
#include "ELFRelocs/Mips.def"
More information about the llvm-commits
mailing list