Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -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)">,
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is only on AArch64 and X86, it may be good to mention that here. This has been done for some other options too, such as print-supported-extensions. Since AArch64 has not been supported yet, it should probably just be X86.

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 "
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The comment on line 5970 says that unwind tables are only defined for x86 and aarch64, but this seems to only add --gsframe for x86. Is this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Aarch64 is incomplete in the backend, but on its way.

Cleaned up the comment and removed that clause on 5970.

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.
Expand Down Expand Up @@ -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. Although also
// defined for aarch64, only x86_64 support is implemented at the moment.
if (Arg *A = Args.getLastArg(options::OPT_gsframe)) {
if (Triple.isOSBinFormatELF() && Triple.isX86())
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) &&
Expand Down
17 changes: 17 additions & 0 deletions clang/test/Driver/sframe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang -### -c --target=x86_64 -Wa,--gsframe %s -Werror 2>&1 | FileCheck %s
// CHECK: "-cc1"
// CHECK-SAME: "--gsframe"

// 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"
// 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 '{{.*}}'

// 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 '{{.*}}'
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this option is only available on x86_64 and aarch64, it would be good to add some tests for the latter as well.

Copy link
Contributor Author

@Sterling-Augustine Sterling-Augustine Nov 3, 2025

Choose a reason for hiding this comment

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

aarch64 support in the backend is incomplete. So probably better to leave testing out until the backend is ready. I will add it here when it is more mature.


7 changes: 7 additions & 0 deletions clang/test/Misc/cc1as-sframe.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// REQUIRES: x86-registered-target
// RUN: %clang -cc1as -triple x86_64 %s -filetype obj --gsframe | llvm-readelf -S - | FileCheck %s

// CHECK: .sframe
.cfi_startproc
call foo
.cfi_endproc
6 changes: 6 additions & 0 deletions clang/tools/driver/cc1as_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down