Skip to content

Conversation

@fzakaria
Copy link

@fzakaria fzakaria commented Jan 5, 2026

Motivation

This is related to #174486 and part of a larger effort to support larger binaries (>2GiB .text) while still retaining the medium code-model.

I have a separate change that leverages thunks to support large .text and I hit this overflows on the FDE. At the moment the only way around this is the large code model but I want to avoid it.

This can also still occur if a linker script places the .eh_frame far enough from the .text which is what the test leverages.

  • Add a separate toggle to enable large encoding for the FDEs
  • Add clang driver support
  • Add tests

@github-actions
Copy link

github-actions bot commented Jan 5, 2026

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added lld clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. llvm:mc Machine (object) code lld:ELF labels Jan 5, 2026
@fzakaria
Copy link
Author

fzakaria commented Jan 5, 2026

Maintainers: @rui314 @MaskRay

@llvmbot
Copy link
Member

llvmbot commented Jan 5, 2026

@llvm/pr-subscribers-lld-elf
@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-llvm-mc

Author: Farid Zakaria (fzakaria)

Changes

Motivation

This is related to #174486 and part of a larger effort to support larger binaries (>2GiB .text) while still retaining the medium code-model.

I have a separate change that leverages thunks to support large .text and I hit this overflows on the FDE. At the moment the only way around this is the large code model but I want to avoid it.

This can also still occur if a linker script places the .eh_frame far enough from the .text which is what the test leverages.

  • Add a separate toggle to enable large encoding for the FDEs
  • Add clang driver support
  • Add tests

Full diff: https://github.com/llvm/llvm-project/pull/174508.diff

10 Files Affected:

  • (modified) clang/include/clang/Basic/CodeGenOptions.def (+3)
  • (modified) clang/include/clang/Options/Options.td (+5)
  • (modified) clang/lib/CodeGen/BackendUtil.cpp (+1)
  • (added) clang/test/Driver/flarge-fde-encoding.c (+10)
  • (added) lld/test/ELF/eh-frame-large-fde-encoding.s (+45)
  • (modified) llvm/include/llvm/MC/MCTargetOptions.h (+4)
  • (modified) llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h (+2)
  • (modified) llvm/lib/MC/MCObjectFileInfo.cpp (+9-4)
  • (modified) llvm/lib/MC/MCTargetOptions.cpp (+2-4)
  • (modified) llvm/lib/MC/MCTargetOptionsCommandFlags.cpp (+9)
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index a1572578fb141..7c71220d16ed9 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 04756ce486eaf..555528088676d 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4780,6 +4780,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 e4b64a0c2ff48..20d3d26d9de3d 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -514,6 +514,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/test/Driver/flarge-fde-encoding.c b/clang/test/Driver/flarge-fde-encoding.c
new file mode 100644
index 0000000000000..e20da6651f4c8
--- /dev/null
+++ b/clang/test/Driver/flarge-fde-encoding.c
@@ -0,0 +1,10 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang -### --target=x86_64-linux-gnu -flarge-fde-encoding %s 2>&1 | FileCheck %s --check-prefix=POS
+// RUN: %clang -### --target=x86_64-linux-gnu -fno-large-fde-encoding %s 2>&1 | FileCheck %s --check-prefix=NEG
+// RUN: %clang -### --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) }
+}
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();

@llvmbot
Copy link
Member

llvmbot commented Jan 5, 2026

@llvm/pr-subscribers-clang-codegen

Author: Farid Zakaria (fzakaria)

Changes

Motivation

This is related to #174486 and part of a larger effort to support larger binaries (>2GiB .text) while still retaining the medium code-model.

I have a separate change that leverages thunks to support large .text and I hit this overflows on the FDE. At the moment the only way around this is the large code model but I want to avoid it.

This can also still occur if a linker script places the .eh_frame far enough from the .text which is what the test leverages.

  • Add a separate toggle to enable large encoding for the FDEs
  • Add clang driver support
  • Add tests

Full diff: https://github.com/llvm/llvm-project/pull/174508.diff

10 Files Affected:

  • (modified) clang/include/clang/Basic/CodeGenOptions.def (+3)
  • (modified) clang/include/clang/Options/Options.td (+5)
  • (modified) clang/lib/CodeGen/BackendUtil.cpp (+1)
  • (added) clang/test/Driver/flarge-fde-encoding.c (+10)
  • (added) lld/test/ELF/eh-frame-large-fde-encoding.s (+45)
  • (modified) llvm/include/llvm/MC/MCTargetOptions.h (+4)
  • (modified) llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h (+2)
  • (modified) llvm/lib/MC/MCObjectFileInfo.cpp (+9-4)
  • (modified) llvm/lib/MC/MCTargetOptions.cpp (+2-4)
  • (modified) llvm/lib/MC/MCTargetOptionsCommandFlags.cpp (+9)
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index a1572578fb141..7c71220d16ed9 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 04756ce486eaf..555528088676d 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4780,6 +4780,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 e4b64a0c2ff48..20d3d26d9de3d 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -514,6 +514,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/test/Driver/flarge-fde-encoding.c b/clang/test/Driver/flarge-fde-encoding.c
new file mode 100644
index 0000000000000..e20da6651f4c8
--- /dev/null
+++ b/clang/test/Driver/flarge-fde-encoding.c
@@ -0,0 +1,10 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang -### --target=x86_64-linux-gnu -flarge-fde-encoding %s 2>&1 | FileCheck %s --check-prefix=POS
+// RUN: %clang -### --target=x86_64-linux-gnu -fno-large-fde-encoding %s 2>&1 | FileCheck %s --check-prefix=NEG
+// RUN: %clang -### --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) }
+}
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();

@llvmbot
Copy link
Member

llvmbot commented Jan 5, 2026

@llvm/pr-subscribers-lld

Author: Farid Zakaria (fzakaria)

Changes

Motivation

This is related to #174486 and part of a larger effort to support larger binaries (>2GiB .text) while still retaining the medium code-model.

I have a separate change that leverages thunks to support large .text and I hit this overflows on the FDE. At the moment the only way around this is the large code model but I want to avoid it.

This can also still occur if a linker script places the .eh_frame far enough from the .text which is what the test leverages.

  • Add a separate toggle to enable large encoding for the FDEs
  • Add clang driver support
  • Add tests

Full diff: https://github.com/llvm/llvm-project/pull/174508.diff

10 Files Affected:

  • (modified) clang/include/clang/Basic/CodeGenOptions.def (+3)
  • (modified) clang/include/clang/Options/Options.td (+5)
  • (modified) clang/lib/CodeGen/BackendUtil.cpp (+1)
  • (added) clang/test/Driver/flarge-fde-encoding.c (+10)
  • (added) lld/test/ELF/eh-frame-large-fde-encoding.s (+45)
  • (modified) llvm/include/llvm/MC/MCTargetOptions.h (+4)
  • (modified) llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h (+2)
  • (modified) llvm/lib/MC/MCObjectFileInfo.cpp (+9-4)
  • (modified) llvm/lib/MC/MCTargetOptions.cpp (+2-4)
  • (modified) llvm/lib/MC/MCTargetOptionsCommandFlags.cpp (+9)
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index a1572578fb141..7c71220d16ed9 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 04756ce486eaf..555528088676d 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4780,6 +4780,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 e4b64a0c2ff48..20d3d26d9de3d 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -514,6 +514,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/test/Driver/flarge-fde-encoding.c b/clang/test/Driver/flarge-fde-encoding.c
new file mode 100644
index 0000000000000..e20da6651f4c8
--- /dev/null
+++ b/clang/test/Driver/flarge-fde-encoding.c
@@ -0,0 +1,10 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang -### --target=x86_64-linux-gnu -flarge-fde-encoding %s 2>&1 | FileCheck %s --check-prefix=POS
+// RUN: %clang -### --target=x86_64-linux-gnu -fno-large-fde-encoding %s 2>&1 | FileCheck %s --check-prefix=NEG
+// RUN: %clang -### --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) }
+}
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();

Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work with LTO?

Should we turn this on by default with medium code model?

@fzakaria
Copy link
Author

fzakaria commented Jan 6, 2026

Does this work with LTO?

Should we turn this on by default with medium code model?

@efriedma-quic I think it's simpler to just turn on for medium code model but it does come with the additional space consideration which is why I set it as a separate toggle for the initial pass.
I am open to both;

@github-actions
Copy link

github-actions bot commented Jan 6, 2026

🐧 Linux x64 Test Results

  • 194897 tests passed
  • 6376 tests skipped

✅ The build succeeded and all tests passed.

@github-actions
Copy link

github-actions bot commented Jan 6, 2026

🪟 Windows x64 Test Results

  • 130735 tests passed
  • 4163 tests skipped

✅ The build succeeded and all tests passed.

@MaskRay
Copy link
Member

MaskRay commented Jan 6, 2026

There are clang and llvm MC changes, so applying just the [lld] tag could be misleading. I would only llvm change in this patch and extract clang and lld changes to separate patches.
If you are proposing a driver option clang -flarge-fde-encoding, it's best to have coordination with GCC folks.

GCC's x86-64 port uses sdata4 with small and medium code models and sdata8 with large. While it's good for clang to keep consistency, an option to switch to sdata8 with medium code model might be useful, since large code model has the long branch penalty.

@fzakaria fzakaria changed the title [lld] Add support for sdata8 for FDE CIE [lld][llvm/mc] Add support for sdata8 for FDE CIE Jan 6, 2026
@fzakaria
Copy link
Author

fzakaria commented Jan 6, 2026

@MaskRay -- Hi Ray, thanks for taking the time to look at this patch.
I've updated the title to also reflect llvm/mc.

I am not sure what entails "coordination" with GCC folks. Sending an email to their distribution list to let them know?
The other option would be for clang to emit sdata8 for medium code irrespective of the flag.

The lld changes are only a test file but although the changes are specific to llvm-mc; I hit the relocation overflow of the FDIE during relocations at link time which is why I tagged it as such.

If I don't include the clang driver option, this can still be toggle via -Wa ?

@smeenai smeenai requested a review from MaskRay January 6, 2026 05:48
@fzakaria
Copy link
Author

fzakaria commented Jan 6, 2026

Current failure:

sccache: Starting the server...
sccache: error: Timed out waiting for server startup

@MaskRay
Copy link
Member

MaskRay commented Jan 8, 2026

I was actually quite interested in exploring this during my final months at the previous emplyer, but unfortunately, I didn't have the chance to implement it at the time. Apologies that I am writing the following in a rush.

For better coordiation we should

@fzakaria
Copy link
Author

fzakaria commented Jan 8, 2026

@MaskRay is it better to remove the clang driver for now to make progress.
Internally we can rely on -Wa to pass it in the meantime to the assembler.

What should the discussion be about in the ABI group? I can kickstart it but I am not sure the topic.
The format itself supports multiple byte-encodings so it seems like purely a lack of implementation support.
(This is not adding a new byte-encoding type)

Appreciate any guidance on how to make progress here.
I have a few more contributions in this direction (I sent you an email to maskray.me) about it 🙇

@fzakaria
Copy link
Author

fzakaria commented Jan 8, 2026

@MaskRay I removed the clang driver portion for now so it's specific to lld & MC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:codegen IR generation bugs: mangling, exceptions, etc. clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" lld:ELF lld llvm:mc Machine (object) code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants