Skip to content

[win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) #143577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 16, 2025
Merged
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
6 changes: 4 additions & 2 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,10 @@ CODEGENOPT(StaticClosure, 1, 0)
/// Assume that UAVs/SRVs may alias
CODEGENOPT(ResMayAlias, 1, 0)

/// Enables unwind v2 (epilog) information for x64 Windows.
CODEGENOPT(WinX64EHUnwindV2, 1, 0)
/// Controls how unwind v2 (epilog) information should be generated for x64
/// Windows.
ENUM_CODEGENOPT(WinX64EHUnwindV2, llvm::WinX64EHUnwindV2Mode,
2, llvm::WinX64EHUnwindV2Mode::Disabled)

/// FIXME: Make DebugOptions its own top-level .def file.
#include "DebugOptions.def"
Expand Down
17 changes: 11 additions & 6 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2167,11 +2167,14 @@ defm assume_nothrow_exception_dtor: BoolFOption<"assume-nothrow-exception-dtor",
LangOpts<"AssumeNothrowExceptionDtor">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Assume that exception objects' destructors are non-throwing">,
NegFlag<SetFalse>>;
defm winx64_eh_unwindv2 : BoolFOption<"winx64-eh-unwindv2",
CodeGenOpts<"WinX64EHUnwindV2">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
NegFlag<SetFalse, [], [ClangOption], "Disable">,
BothFlags<[], [ClangOption], " unwind v2 (epilog) information for x64 Windows">>;
def winx64_eh_unwindv2
: Joined<["-"], "fwinx64-eh-unwindv2=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Generate unwind v2 (epilog) information for x64 Windows">,
Values<"disabled,best-effort,required">,
NormalizedValues<["Disabled", "BestEffort", "Required"]>,
NormalizedValuesScope<"llvm::WinX64EHUnwindV2Mode">,
MarshallingInfoEnum<CodeGenOpts<"WinX64EHUnwindV2">, "Disabled">;
def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group<f_Group>,
Visibility<[ClangOption, CLOption]>,
HelpText<"Allows control over excess precision on targets where native "
Expand Down Expand Up @@ -8971,7 +8974,9 @@ def _SLASH_volatile_Group : OptionGroup<"</volatile group>">,
Group<cl_compile_Group>;

def _SLASH_d2epilogunwind : CLFlag<"d2epilogunwind">,
HelpText<"Enable unwind v2 (epilog) information for x64 Windows">;
HelpText<"Best effort generate unwind v2 (epilog) information for x64 Windows">;
def _SLASH_d2epilogunwindrequirev2 : CLFlag<"d2epilogunwindrequirev2">,
HelpText<"Require generation of unwind v2 (epilog) information for x64 Windows">;
def _SLASH_EH : CLJoined<"EH">, HelpText<"Set exception handling model">;
def _SLASH_EP : CLFlag<"EP">,
HelpText<"Disable linemarker output and preprocess to stdout">;
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1314,8 +1314,10 @@ void CodeGenModule::Release() {
1);

// Enable unwind v2 (epilog).
if (CodeGenOpts.WinX64EHUnwindV2)
getModule().addModuleFlag(llvm::Module::Warning, "winx64-eh-unwindv2", 1);
if (CodeGenOpts.getWinX64EHUnwindV2() != llvm::WinX64EHUnwindV2Mode::Disabled)
getModule().addModuleFlag(
llvm::Module::Warning, "winx64-eh-unwindv2",
static_cast<unsigned>(CodeGenOpts.getWinX64EHUnwindV2()));

// Indicate whether this Module was compiled with -fopenmp
if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd)
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7352,8 +7352,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}

// Unwind v2 (epilog) information for x64 Windows.
Args.addOptInFlag(CmdArgs, options::OPT_fwinx64_eh_unwindv2,
options::OPT_fno_winx64_eh_unwindv2);
Args.AddLastArg(CmdArgs, options::OPT_winx64_eh_unwindv2);

// C++ "sane" operator new.
Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
Expand Down Expand Up @@ -8410,8 +8409,10 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fms-kernel");

// Unwind v2 (epilog) information for x64 Windows.
if (Args.hasArg(options::OPT__SLASH_d2epilogunwind))
CmdArgs.push_back("-fwinx64-eh-unwindv2");
if (Args.hasArg(options::OPT__SLASH_d2epilogunwindrequirev2))
CmdArgs.push_back("-fwinx64-eh-unwindv2=required");
else if (Args.hasArg(options::OPT__SLASH_d2epilogunwind))
CmdArgs.push_back("-fwinx64-eh-unwindv2=best-effort");

for (const Arg *A : Args.filtered(options::OPT__SLASH_guard)) {
StringRef GuardArgs = A->getValue();
Expand Down
10 changes: 6 additions & 4 deletions clang/test/CodeGen/epilog-unwind.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -check-prefix=DISABLED
// RUN: %clang_cc1 -fwinx64-eh-unwindv2 -emit-llvm %s -o - | FileCheck %s -check-prefix=ENABLED
// RUN: %clang -fwinx64-eh-unwindv2 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=ENABLED
// RUN: %clang -fno-winx64-eh-unwindv2 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DISABLED
// RUN: %clang_cc1 -fwinx64-eh-unwindv2=disabled -emit-llvm %s -o - | FileCheck %s -check-prefix=DISABLED
// RUN: %clang_cc1 -fwinx64-eh-unwindv2=best-effort -emit-llvm %s -o - | FileCheck %s -check-prefix=BESTEFFORT
// RUN: %clang_cc1 -fwinx64-eh-unwindv2=required -emit-llvm %s -o - | FileCheck %s -check-prefix=REQUIRED
// RUN: %clang -fwinx64-eh-unwindv2=best-effort -S -emit-llvm %s -o - | FileCheck %s -check-prefix=BESTEFFORT

void f(void) {}

// ENABLED: !"winx64-eh-unwindv2", i32 1}
// BESTEFFORT: !"winx64-eh-unwindv2", i32 1}
// REQUIRED: !"winx64-eh-unwindv2", i32 2}
// DISABLED-NOT: "winx64-eh-unwindv2"
6 changes: 5 additions & 1 deletion clang/test/Driver/cl-options.c
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,11 @@
// ARM64EC_OVERRIDE: warning: /arm64EC has been overridden by specified target: x86_64-pc-windows-msvc; option ignored

// RUN: %clang_cl /d2epilogunwind /c -### -- %s 2>&1 | FileCheck %s --check-prefix=EPILOGUNWIND
// EPILOGUNWIND: -fwinx64-eh-unwindv2
// EPILOGUNWIND: -fwinx64-eh-unwindv2=best-effort

// RUN: %clang_cl /d2epilogunwindrequirev2 /c -### -- %s 2>&1 | FileCheck %s --check-prefix=EPILOGUNWINDREQUIREV2
// RUN: %clang_cl /d2epilogunwindrequirev2 /d2epilogunwind /c -### -- %s 2>&1 | FileCheck %s --check-prefix=EPILOGUNWINDREQUIREV2
// EPILOGUNWINDREQUIREV2: -fwinx64-eh-unwindv2=require

// RUN: %clang_cl /funcoverride:override_me1 /funcoverride:override_me2 /c -### -- %s 2>&1 | FileCheck %s --check-prefix=FUNCOVERRIDE
// FUNCOVERRIDE: -loader-replaceable-function=override_me1
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,10 @@ class LLVM_ABI Module {

/// Returns target-abi from MDString, null if target-abi is absent.
StringRef getTargetABIFromMD();

/// Get how unwind v2 (epilog) information should be generated for x64
/// Windows.
WinX64EHUnwindV2Mode getWinX64EHUnwindV2Mode() const;
};

/// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the
Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/Support/CodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ namespace llvm {
Invalid = 2, ///< Not used.
};

enum class WinX64EHUnwindV2Mode {
// Don't use unwind v2 (i.e., use v1).
Disabled = 0,
// Use unwind v2 here possible, otherwise fallback to v1.
BestEffort = 1,
// Use unwind v2 everywhere, otherwise raise an error.
Required = 2,
};

} // namespace llvm

#endif
7 changes: 7 additions & 0 deletions llvm/lib/IR/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -917,3 +917,10 @@ StringRef Module::getTargetABIFromMD() {
TargetABI = TargetABIMD->getString();
return TargetABI;
}

WinX64EHUnwindV2Mode Module::getWinX64EHUnwindV2Mode() const {
Metadata *MD = getModuleFlag("winx64-eh-unwindv2");
if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(MD))
return static_cast<WinX64EHUnwindV2Mode>(CI->getZExtValue());
return WinX64EHUnwindV2Mode::Disabled;
}
Loading