https://github.com/fzakaria updated 
https://github.com/llvm/llvm-project/pull/174508

>From 31795f8c7bb235ed2aebc625d97ca55ec108454a Mon Sep 17 00:00:00 2001
From: Farid Zakaria <[email protected]>
Date: Thu, 8 Jan 2026 11:01:29 -0800
Subject: [PATCH 1/3] [lld] Support large encoding for FDE

---
 llvm/include/llvm/MC/MCTargetOptions.h             |  4 ++++
 llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h |  2 ++
 llvm/lib/MC/MCObjectFileInfo.cpp                   | 13 +++++++++----
 llvm/lib/MC/MCTargetOptions.cpp                    |  6 ++----
 llvm/lib/MC/MCTargetOptionsCommandFlags.cpp        |  9 +++++++++
 5 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/MC/MCTargetOptions.h 
b/llvm/include/llvm/MC/MCTargetOptions.h
index 235d58d585b40..da62be369a43c 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -108,6 +108,10 @@ class MCTargetOptions {
   // Whether or not to use full register names on PowerPC.
   bool PPCUseFullRegisterNames : 1;
 
+  // Use 8-byte pointer size for ELF FDE CFI encoding, regardless of code 
model.
+  // Useful when text sections may exceed 2GB even with medium code model
+  bool LargeFDEEncoding : 1;
+
   LLVM_ABI MCTargetOptions();
 
   /// getABIName - If this returns a non-empty string this represents the
diff --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h 
b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
index 168131b43cca8..beba9f835afeb 100644
--- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
+++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
@@ -63,6 +63,8 @@ LLVM_ABI bool getX86RelaxRelocations();
 
 LLVM_ABI bool getX86Sse2Avx();
 
+LLVM_ABI bool getLargeFDEEncoding();
+
 LLVM_ABI StringRef getABIName();
 
 LLVM_ABI StringRef getAsSecureLogFile();
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 5afe00eee2242..9667d17e63939 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -24,6 +24,7 @@
 #include "llvm/MC/MCSectionSPIRV.h"
 #include "llvm/MC/MCSectionWasm.h"
 #include "llvm/MC/MCSectionXCOFF.h"
+#include "llvm/MC/MCTargetOptions.h"
 #include "llvm/TargetParser/Triple.h"
 
 using namespace llvm;
@@ -332,7 +333,6 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const 
Triple &T) {
 
   TLSExtraDataSection = TLSTLVSection;
 }
-
 void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
   switch (T.getArch()) {
   case Triple::mips:
@@ -354,10 +354,15 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const 
Triple &T, bool Large) {
   case Triple::ppc64le:
   case Triple::aarch64:
   case Triple::aarch64_be:
-  case Triple::x86_64:
-    FDECFIEncoding = dwarf::DW_EH_PE_pcrel |
-                     (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
+  case Triple::x86_64: {
+    // Check if the user requested large FDE encoding via MCTargetOptions
+    const MCTargetOptions *TO = Ctx->getTargetOptions();
+    bool Use8ByteFDE = Large || (TO && TO->LargeFDEEncoding);
+    FDECFIEncoding =
+        dwarf::DW_EH_PE_pcrel |
+        (Use8ByteFDE ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
     break;
+  }
   case Triple::bpfel:
   case Triple::bpfeb:
     FDECFIEncoding = dwarf::DW_EH_PE_sdata8;
diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp
index be6d19d111620..ff3ce40a555ee 100644
--- a/llvm/lib/MC/MCTargetOptions.cpp
+++ b/llvm/lib/MC/MCTargetOptions.cpp
@@ -20,11 +20,9 @@ MCTargetOptions::MCTargetOptions()
       EmitDwarfUnwind(EmitDwarfUnwindType::Default),
       MCUseDwarfDirectory(DefaultDwarfDirectory),
       EmitCompactUnwindNonCanonical(false), EmitSFrameUnwind(false),
-      PPCUseFullRegisterNames(false) {}
+      PPCUseFullRegisterNames(false), LargeFDEEncoding(false) {}
 
-StringRef MCTargetOptions::getABIName() const {
-  return ABIName;
-}
+StringRef MCTargetOptions::getABIName() const { return ABIName; }
 
 StringRef MCTargetOptions::getAssemblyLanguage() const {
   return AssemblyLanguage;
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp 
b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 22494fa11eb2a..8ad5ac02cdaa6 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -59,6 +59,7 @@ MCOPT(bool, Crel)
 MCOPT(bool, ImplicitMapSyms)
 MCOPT(bool, X86RelaxRelocations)
 MCOPT(bool, X86Sse2Avx)
+MCOPT(bool, LargeFDEEncoding)
 MCSTROPT(ABIName)
 MCSTROPT(AsSecureLogFile)
 
@@ -168,6 +169,13 @@ 
llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
                               "instructions with VEX prefix"));
   MCBINDOPT(X86Sse2Avx);
 
+  static cl::opt<bool> LargeFDEEncoding(
+      "large-fde-encoding",
+      cl::desc("Use 8-byte pointer size for ELF FDE CFI encoding, useful "
+               "when text sections may exceed 2GB even with medium code"),
+      cl::init(false));
+  MCBINDOPT(LargeFDEEncoding);
+
   static cl::opt<std::string> ABIName(
       "target-abi",
       cl::desc("The name of the ABI to be targeted from the backend."),
@@ -199,6 +207,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
   Options.ImplicitMapSyms = getImplicitMapSyms();
   Options.X86RelaxRelocations = getX86RelaxRelocations();
   Options.X86Sse2Avx = getX86Sse2Avx();
+  Options.LargeFDEEncoding = getLargeFDEEncoding();
   Options.EmitDwarfUnwind = getEmitDwarfUnwind();
   Options.EmitCompactUnwindNonCanonical = getEmitCompactUnwindNonCanonical();
   Options.EmitSFrameUnwind = getEmitSFrameUnwind();

>From 40a70b62aa63c5d791fe360a642737c8a787999d Mon Sep 17 00:00:00 2001
From: Farid Zakaria <[email protected]>
Date: Thu, 8 Jan 2026 11:01:29 -0800
Subject: [PATCH 2/3] Expose large encoding option to clang

---
 clang/include/clang/Basic/CodeGenOptions.def | 3 +++
 clang/include/clang/Options/Options.td       | 5 +++++
 clang/lib/CodeGen/BackendUtil.cpp            | 1 +
 clang/lib/Driver/ToolChains/Clang.cpp        | 3 +++
 4 files changed, 12 insertions(+)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index a6b1acdcf5ea9..d9a4ac4acb7a4 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -120,6 +120,9 @@ CODEGENOPT(StackSizeSection  , 1, 0, Benign) ///< Set when 
-fstack-size-section
 ///< Set when -femit-compact-unwind-non-canonical is enabled.
 CODEGENOPT(EmitCompactUnwindNonCanonical, 1, 0, Benign)
 
+///< Set when -flarge-fde-encoding is enabled.
+CODEGENOPT(LargeFDEEncoding, 1, 0, Benign)
+
 ///< Set when -fxray-always-emit-customevents is enabled.
 CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0, Benign)
 
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index f336542992993..4d5eaf5f71111 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4791,6 +4791,11 @@ defm emit_compact_unwind_non_canonical : 
BoolFOption<"emit-compact-unwind-non-ca
   PosFlag<SetTrue, [], [ClangOption, CC1Option, CC1AsOption],
           "Try emitting Compact-Unwind for non-canonical entries. Maybe 
overridden by other constraints">,
   NegFlag<SetFalse>>;
+defm large_fde_encoding : BoolFOption<"large-fde-encoding",
+  CodeGenOpts<"LargeFDEEncoding">, DefaultFalse,
+  PosFlag<SetTrue, [], [ClangOption, CC1Option, CC1AsOption],
+          "Use 8-byte pointers for ELF FDE CFI encoding. Useful when text 
sections may exceed 2GB">,
+  NegFlag<SetFalse>>;
 def g_Flag : Flag<["-"], "g">, Group<g_Group>,
     Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
     HelpText<"Generate source-level debug information">;
diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 26794a9cbc11d..c11abd850e2a3 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -488,6 +488,7 @@ static bool initTargetOptions(const CompilerInstance &CI,
   Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind();
   Options.MCOptions.EmitCompactUnwindNonCanonical =
       CodeGenOpts.EmitCompactUnwindNonCanonical;
+  Options.MCOptions.LargeFDEEncoding = CodeGenOpts.LargeFDEEncoding;
   Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;
   Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;
   Options.MCOptions.MCUseDwarfDirectory =
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index a0c98bcea85e6..b3c0856f693aa 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5640,6 +5640,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
                    options::OPT_fno_merge_all_constants, false))
     CmdArgs.push_back("-fmerge-all-constants");
 
+  Args.addOptInFlag(CmdArgs, options::OPT_flarge_fde_encoding,
+                    options::OPT_fno_large_fde_encoding);
+
   Args.addOptOutFlag(CmdArgs, options::OPT_fdelete_null_pointer_checks,
                      options::OPT_fno_delete_null_pointer_checks);
 

>From d73ceb0c71635db641c12a2e63c39cd5d931876c Mon Sep 17 00:00:00 2001
From: Farid Zakaria <[email protected]>
Date: Thu, 8 Jan 2026 11:01:29 -0800
Subject: [PATCH 3/3] Create test for large encoding of FDE

---
 clang/test/Driver/flarge-fde-encoding.c    | 10 +++++
 lld/test/ELF/eh-frame-large-fde-encoding.s | 45 ++++++++++++++++++++++
 2 files changed, 55 insertions(+)
 create mode 100644 clang/test/Driver/flarge-fde-encoding.c
 create mode 100644 lld/test/ELF/eh-frame-large-fde-encoding.s

diff --git a/clang/test/Driver/flarge-fde-encoding.c 
b/clang/test/Driver/flarge-fde-encoding.c
new file mode 100644
index 0000000000000..48742b8dce4ba
--- /dev/null
+++ b/clang/test/Driver/flarge-fde-encoding.c
@@ -0,0 +1,10 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang -### -c --target=x86_64-linux-gnu -flarge-fde-encoding %s 2>&1 
| FileCheck %s --check-prefix=POS
+// RUN: %clang -### -c --target=x86_64-linux-gnu -fno-large-fde-encoding %s 
2>&1 | FileCheck %s --check-prefix=NEG
+// RUN: %clang -### -c --target=x86_64-linux-gnu %s 2>&1 | FileCheck %s 
--check-prefix=DEFAULT
+
+// POS: "-flarge-fde-encoding"
+// NEG-NOT: "-flarge-fde-encoding"
+// DEFAULT-NOT: "-flarge-fde-encoding"
+
+int dummy;
diff --git a/lld/test/ELF/eh-frame-large-fde-encoding.s 
b/lld/test/ELF/eh-frame-large-fde-encoding.s
new file mode 100644
index 0000000000000..e374de8444e67
--- /dev/null
+++ b/lld/test/ELF/eh-frame-large-fde-encoding.s
@@ -0,0 +1,45 @@
+# REQUIRES: x86
+
+## Test that demonstrates FDE encoding overflow when .eh_frame is placed
+## far from .text, and the fix using 8-byte (sdata8) FDE encoding.
+##
+## With the default 4-byte FDE encoding (sdata4), a PC-relative offset
+## to .text can overflow if .eh_frame is placed more than 2GB away.
+## Using -large-fde-encoding (or mcmodel=large) switches to 8-byte
+## FDE encoding which can address the full 64-bit address space.
+
+# RUN: rm -rf %t && split-file %s %t
+
+## Test 1: With default sdata4 encoding, placing .eh_frame far from .text
+## causes an overflow error.
+# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu 
--large-fde-encoding=false \
+# RUN:   %t/test.s -o %t/test-small.o
+# RUN: not ld.lld %t/test-small.o -T %t/far.lds -o /dev/null 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=OVERFLOW
+
+## Test 2: With sdata8 encoding via -large-fde-encoding, no overflow.
+# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -large-fde-encoding \
+# RUN:   %t/test.s -o %t/test-large.o
+# RUN: ld.lld %t/test-large.o -T %t/far.lds -o %t/out
+
+# OVERFLOW: ld.lld: error: <internal>:(.eh_frame+0x{{[0-9a-fA-F]+}}): 
relocation R_X86_64_PC32 out of range
+
+#--- test.s
+.text
+.globl _start
+.type _start, @function
+_start:
+  .cfi_startproc
+  ret
+  .cfi_endproc
+
+#--- far.lds
+SECTIONS {
+  ## Place .text at a low address
+  . = 0x1000;
+  .text : { *(.text) }
+
+  ## Place .eh_frame more than 2GB away to trigger overflow with sdata4
+  . = 0x100001000;
+  .eh_frame : { *(.eh_frame) }
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to