[llvm] [llvm/mc] Add support for sdata8 for FDE CIE (PR #174508)

Farid Zakaria via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 11 12:19:55 PST 2026


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

>From d35f555d2b3c84000e4e1e1c79fd39870f68ce66 Mon Sep 17 00:00:00 2001
From: Farid Zakaria <fmzakari at fb.com>
Date: Sun, 11 Jan 2026 12:18:37 -0800
Subject: [PATCH] [lld] Support large encoding for FDE

---
 llvm/include/llvm/MC/MCTargetOptions.h        |  4 +++
 .../llvm/MC/MCTargetOptionsCommandFlags.h     |  2 ++
 llvm/lib/MC/MCObjectFileInfo.cpp              | 13 +++++---
 llvm/lib/MC/MCTargetOptions.cpp               |  6 ++--
 llvm/lib/MC/MCTargetOptionsCommandFlags.cpp   |  9 ++++++
 .../test/MC/ELF/eh-frame-large-fde-encoding.s | 32 +++++++++++++++++++
 6 files changed, 58 insertions(+), 8 deletions(-)
 create mode 100644 llvm/test/MC/ELF/eh-frame-large-fde-encoding.s

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();
diff --git a/llvm/test/MC/ELF/eh-frame-large-fde-encoding.s b/llvm/test/MC/ELF/eh-frame-large-fde-encoding.s
new file mode 100644
index 0000000000000..ec9f46f596e18
--- /dev/null
+++ b/llvm/test/MC/ELF/eh-frame-large-fde-encoding.s
@@ -0,0 +1,32 @@
+// Test that --large-fde-encoding uses 8-byte pointers in FDE CIE encoding
+// for x86_64 ELF targets.
+
+// Default encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata4 = 0x1B
+// RUN: llvm-mc -filetype=obj %s -o %t.o -triple x86_64-unknown-linux-gnu
+// RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefix=SDATA4 %s
+
+// With --large-fde-encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata8 = 0x1C
+// RUN: llvm-mc -filetype=obj %s -o %t.o -triple x86_64-unknown-linux-gnu --large-fde-encoding
+// RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefix=SDATA8 %s
+
+// Also test with --large-code-model which should also use sdata8
+// RUN: llvm-mc -filetype=obj %s -o %t.o -triple x86_64-unknown-linux-gnu --large-code-model
+// RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefix=SDATA8 %s
+
+func:
+	.cfi_startproc
+	.cfi_endproc
+
+// SDATA4:      {{[0-9a-f]+}} {{[0-9a-f]+}} 00000000 CIE
+// SDATA4-NEXT:   Format:                DWARF32
+// SDATA4-NEXT:   Version:               1
+// SDATA4-NEXT:   Augmentation:          "zR"
+// SDATA4:        Augmentation data:     1B
+//                                       ^^ fde pointer encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata4
+
+// SDATA8:      {{[0-9a-f]+}} {{[0-9a-f]+}} 00000000 CIE
+// SDATA8-NEXT:   Format:                DWARF32
+// SDATA8-NEXT:   Version:               1
+// SDATA8-NEXT:   Augmentation:          "zR"
+// SDATA8:        Augmentation data:     1C
+//                                       ^^ fde pointer encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata8



More information about the llvm-commits mailing list