https://github.com/Sterling-Augustine updated https://github.com/llvm/llvm-project/pull/165806
>From 546da436c6ea1c1b7d01c975da6fb248fbce24d0 Mon Sep 17 00:00:00 2001 From: Sterling Augustine <[email protected]> Date: Thu, 30 Oct 2025 15:50:20 -0700 Subject: [PATCH 1/2] This plumbs the option --gsframe through the various levels needed to support it in the assembler. This is the final step in assembler-level sframe support for x86. With it in place, clang produces sframe-sections that successfully link with gnu-ld. LLD support is pending some discussion. --- clang/include/clang/Basic/CodeGenOptions.def | 2 ++ clang/include/clang/Driver/Options.td | 5 +++++ clang/lib/CodeGen/BackendUtil.cpp | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 18 ++++++++++++++++++ clang/test/Driver/sframe.c | 15 +++++++++++++++ clang/test/Misc/cc1as-sframe.s | 8 ++++++++ clang/tools/driver/cc1as_main.cpp | 6 ++++++ 7 files changed, 55 insertions(+) create mode 100644 clang/test/Driver/sframe.c create mode 100644 clang/test/Misc/cc1as-sframe.s diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 90e1f8d1eb5e9..99199c3a6c34c 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -120,6 +120,8 @@ CODEGENOPT(StackSizeSection , 1, 0, Benign) ///< Set when -fstack-size-section ///< Set when -femit-compact-unwind-non-canonical is enabled. CODEGENOPT(EmitCompactUnwindNonCanonical, 1, 0, Benign) +CODEGENOPT(EmitSFrameUnwind, 1, 0, Benign) ///< Set when -sframe is enabled. + ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0, Benign) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index cb5cb888c6da7..a7274fbdeabf1 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -7729,6 +7729,11 @@ def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">, def crel : Flag<["--"], "crel">, HelpText<"Enable CREL relocation format (ELF only)">, MarshallingInfoFlag<CodeGenOpts<"Crel">>; +// The leading 'g' is misleading. This is an unwind tables option, not +// a debug option. But uses this name for gnu compatibility. +def gsframe : Flag<["--"], "gsframe">, + HelpText<"Generate .sframe unwind sections (ELF only)">, + MarshallingInfoFlag<CodeGenOpts<"EmitSFrameUnwind">>; def mmapsyms_implicit : Flag<["-"], "mmapsyms=implicit">, HelpText<"Allow mapping symbol at section beginning to be implicit, " "lowering number of mapping symbols at the expense of some " diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 3c313149ca1fc..1f7a96af015b6 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -500,6 +500,7 @@ static bool initTargetOptions(const CompilerInstance &CI, Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind(); Options.MCOptions.EmitCompactUnwindNonCanonical = CodeGenOpts.EmitCompactUnwindNonCanonical; + Options.MCOptions.EmitSFrameUnwind = CodeGenOpts.EmitSFrameUnwind; 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 4e8f63ea49480..f40e68b5755ae 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2626,6 +2626,14 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, llvm::codegenoptions::DebugInfoConstructor, DwarfVersion, llvm::DebuggerKind::Default); } + } else if (Value == "--gsframe") { + if (Triple.isOSBinFormatELF() && Triple.isX86()) { + CmdArgs.push_back("--gsframe"); + } else { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Value << D.getTargetTriple(); + break; + } } else if (Value.starts_with("-mcpu") || Value.starts_with("-mfpu") || Value.starts_with("-mhwdiv") || Value.starts_with("-march")) { // Do nothing, we'll validate it later. @@ -5929,6 +5937,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else if (UnwindTables) CmdArgs.push_back("-funwind-tables=1"); + // Sframe unwind tables are independent of the other types, and only defined + // for these two targets. + if (Arg *A = Args.getLastArg(options::OPT_gsframe)) { + if ((Triple.isAArch64() || Triple.isX86()) && Triple.isOSBinFormatELF()) + CmdArgs.push_back("--gsframe"); + else + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getOption().getName() << TripleStr; + } + // Prepare `-aux-target-cpu` and `-aux-target-feature` unless // `--gpu-use-aux-triple-only` is specified. if (!Args.getLastArg(options::OPT_gpu_use_aux_triple_only) && diff --git a/clang/test/Driver/sframe.c b/clang/test/Driver/sframe.c new file mode 100644 index 0000000000000..6c0969e9042a8 --- /dev/null +++ b/clang/test/Driver/sframe.c @@ -0,0 +1,15 @@ +// RUN: %clang -### -c --target=x86_64 -Wa,--gsframe %s -Werror 2>&1 | FileCheck %s +// CHECK: "-cc1" {{.*}}"--gsframe" + +// RUN: %clang -### -c --target=x86_64 %s 2>&1 | FileCheck %s --check-prefix=NO +// NO: "-cc1" + +// RUN: %clang -### -c --target=x86_64 -Werror -Wa,--gsframe -x assembler %s -Werror 2>&1 | FileCheck %s --check-prefix=ASM +// ASM: "-cc1as" {{.*}}"--gsframe" + +// RUN: not %clang -### -c --target=mips64 -Wa,--gsframe %s 2>&1 | FileCheck %s --check-prefix=NOTARGETC +// NOTARGETC: error: unsupported option '--gsframe' for target '{{.*}}' + +// RUN: not %clang -### -c --target=mips64 -Wa,--gsframe -x assembler %s 2>&1 | FileCheck %s --check-prefix=NOTARGETASM +// NOTARGETASM: error: unsupported option '--gsframe' for target '{{.*}}' + diff --git a/clang/test/Misc/cc1as-sframe.s b/clang/test/Misc/cc1as-sframe.s new file mode 100644 index 0000000000000..9d16f0ada32ad --- /dev/null +++ b/clang/test/Misc/cc1as-sframe.s @@ -0,0 +1,8 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -cc1as -triple x86_64 %s -filetype obj --gsframe -o %t.o +// RUN: llvm-readelf -S %t.o | FileCheck %s + +// CHECK: .sframe +.cfi_startproc + call foo +.cfi_endproc diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 50da2f8449a22..3187a5b5c571b 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -163,6 +163,10 @@ struct AssemblerInvocation { LLVM_PREFERRED_TYPE(bool) unsigned EmitCompactUnwindNonCanonical : 1; + // Whether to emit sframe unwind sections. + LLVM_PREFERRED_TYPE(bool) + unsigned EmitSFrameUnwind : 1; + LLVM_PREFERRED_TYPE(bool) unsigned Crel : 1; LLVM_PREFERRED_TYPE(bool) @@ -388,6 +392,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, Opts.EmitCompactUnwindNonCanonical = Args.hasArg(OPT_femit_compact_unwind_non_canonical); + Opts.EmitSFrameUnwind = Args.hasArg(OPT_gsframe); Opts.Crel = Args.hasArg(OPT_crel); Opts.ImplicitMapsyms = Args.hasArg(OPT_mmapsyms_implicit); Opts.X86RelaxRelocations = !Args.hasArg(OPT_mrelax_relocations_no); @@ -450,6 +455,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, MCOptions.MCRelaxAll = Opts.RelaxAll; MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind; MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical; + MCOptions.EmitSFrameUnwind = Opts.EmitSFrameUnwind; MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels; MCOptions.Crel = Opts.Crel; MCOptions.ImplicitMapSyms = Opts.ImplicitMapsyms; >From c2b7871a70c74611e1c7966e94552d37b55c0af7 Mon Sep 17 00:00:00 2001 From: Sterling Augustine <[email protected]> Date: Mon, 3 Nov 2025 09:44:55 -0800 Subject: [PATCH 2/2] Tighten test cases; fix comment and aarch64 clause. --- clang/lib/Driver/ToolChains/Clang.cpp | 6 +++--- clang/test/Driver/sframe.c | 10 ++++++---- clang/test/Misc/cc1as-sframe.s | 3 +-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f40e68b5755ae..9c7f1fc8bd2c3 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5937,10 +5937,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else if (UnwindTables) CmdArgs.push_back("-funwind-tables=1"); - // Sframe unwind tables are independent of the other types, and only defined - // for these two targets. + // Sframe unwind tables are independent of the other types. Although also + // defined for aarch64, only x86_64 support is implemented at the moment. if (Arg *A = Args.getLastArg(options::OPT_gsframe)) { - if ((Triple.isAArch64() || Triple.isX86()) && Triple.isOSBinFormatELF()) + if (Triple.isOSBinFormatELF() && Triple.isX86()) CmdArgs.push_back("--gsframe"); else D.Diag(diag::err_drv_unsupported_opt_for_target) diff --git a/clang/test/Driver/sframe.c b/clang/test/Driver/sframe.c index 6c0969e9042a8..88fa6ebc6aacb 100644 --- a/clang/test/Driver/sframe.c +++ b/clang/test/Driver/sframe.c @@ -1,11 +1,13 @@ // RUN: %clang -### -c --target=x86_64 -Wa,--gsframe %s -Werror 2>&1 | FileCheck %s -// CHECK: "-cc1" {{.*}}"--gsframe" +// CHECK: "-cc1" +// CHECK-SAME: "--gsframe" -// RUN: %clang -### -c --target=x86_64 %s 2>&1 | FileCheck %s --check-prefix=NO -// NO: "-cc1" +// RUN: %clang -### -c --target=x86_64 %s 2>&1 | FileCheck %s --check-prefix=NO-GSFRAME +// NO-GSFRAME-NOT: "--gsframe" // RUN: %clang -### -c --target=x86_64 -Werror -Wa,--gsframe -x assembler %s -Werror 2>&1 | FileCheck %s --check-prefix=ASM -// ASM: "-cc1as" {{.*}}"--gsframe" +// ASM: "-cc1as" +// ASM-SAME: "--gsframe" // RUN: not %clang -### -c --target=mips64 -Wa,--gsframe %s 2>&1 | FileCheck %s --check-prefix=NOTARGETC // NOTARGETC: error: unsupported option '--gsframe' for target '{{.*}}' diff --git a/clang/test/Misc/cc1as-sframe.s b/clang/test/Misc/cc1as-sframe.s index 9d16f0ada32ad..23f3d7b40f171 100644 --- a/clang/test/Misc/cc1as-sframe.s +++ b/clang/test/Misc/cc1as-sframe.s @@ -1,6 +1,5 @@ // REQUIRES: x86-registered-target -// RUN: %clang -cc1as -triple x86_64 %s -filetype obj --gsframe -o %t.o -// RUN: llvm-readelf -S %t.o | FileCheck %s +// RUN: %clang -cc1as -triple x86_64 %s -filetype obj --gsframe | llvm-readelf -S - | FileCheck %s // CHECK: .sframe .cfi_startproc _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
