[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
panagiotidisc wrote: >Future work: attempting to chain unwind info across multiple tables if there >are too many unwind codes due to epilogs and adding a heuristic to detect if >an epilog will be too far from the end of the function. The epilog offset is from the end of the RuntimeFunction, not the end of the whole procedure (which is ill-defined especially in the case of discontiguous functions) > I'm a little concerned about the wording of the errors here. The "too many > epilogues" and "too many opcodes" errors should say that it's not yet > implemented, or something, so it's clear it's a limitation of the compiler. > Maybe try to suggest a workaround of some sort... maybe mention tail-calls > since that's the most likely culprit. There are limitations by the format. An individual UnwindInfo may have up to 0xFF UnwindCode words, and there is a 0xFF size restriction on prologues, and 0xFFF offset limitation from end of RuntimeFunction on epilogues. In such (unlikely) cases, the procedure must be split into multiple RuntimeFunction/UnwindInfo. > The other conditions shouldn't occur at all: there's no reason to generate an > epilogue that doesn't match the prologue, as far as I know. With chained UnwindInfo, it is possible to save additional non-vol registers multiple times in the body of the function (multiple shrink-wrapping). Instructions restoring these registers may then be immediately be followed by an epilogue, so it may catch an erroneous placement of SEH_BeginEpilogue. Another issue that arises is correctly recording in which chained UnwindInfo of the procedure which additional saves must be assumed, either by A) chaining with the UnwindInfo that did the save, or by B) having these unwind codes with offset 00 (eg. `00: SAVE_NONVOL, register=rdi offset=0x90`), and chaining with another UnwindInfo. Msvc seems to do chaining and shrink-wrapping based on the control flow graph, and some rules that I unfortunately haven't quite figured out. Additional note: RuntimeFunctions don't have to be one-to-one with UnwindInfo. msvc shares UnwindInfo between RuntimeFunctions, as long as they don't have PUSH_MACHFRAME, or Unwind flags: CHAININFO https://github.com/llvm/llvm-project/pull/143577 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
https://github.com/dpaoliello updated https://github.com/llvm/llvm-project/pull/143577 >From 082514ffe8cd9086d82cbe0a114dfc736b0518dc Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 6 Jun 2025 16:39:07 -0700 Subject: [PATCH 1/2] Add support for requiring Win x64 Unwind V2 --- clang/include/clang/Basic/CodeGenOptions.def | 6 +- clang/include/clang/Driver/Options.td | 17 +- clang/lib/CodeGen/CodeGenModule.cpp | 6 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 +- clang/test/CodeGen/epilog-unwind.c| 10 +- clang/test/Driver/cl-options.c| 6 +- llvm/include/llvm/IR/Module.h | 4 + llvm/include/llvm/Support/CodeGen.h | 9 + llvm/lib/IR/Module.cpp| 7 + llvm/lib/Target/X86/X86WinEHUnwindV2.cpp | 152 +++-- .../CodeGen/X86/win64-eh-unwindv2-errors.mir | 318 ++ .../win64-eh-unwindv2-too-many-epilogs.mir| 94 ++ 12 files changed, 595 insertions(+), 43 deletions(-) create mode 100644 llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir create mode 100644 llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index fa9474d63ae42..32a2ee0e23200 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -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" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 152df89118a6a..0a1e1e0a25f40 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2167,11 +2167,14 @@ defm assume_nothrow_exception_dtor: BoolFOption<"assume-nothrow-exception-dtor", LangOpts<"AssumeNothrowExceptionDtor">, DefaultFalse, PosFlag, NegFlag>; -defm winx64_eh_unwindv2 : BoolFOption<"winx64-eh-unwindv2", - CodeGenOpts<"WinX64EHUnwindV2">, DefaultFalse, - PosFlag, - NegFlag, - BothFlags<[], [ClangOption], " unwind v2 (epilog) information for x64 Windows">>; +def winx64_eh_unwindv2 +: Joined<["-"], "fwinx64-eh-unwindv2=">, 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, "Disabled">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group, Visibility<[ClangOption, CLOption]>, HelpText<"Allows control over excess precision on targets where native " @@ -8971,7 +8974,9 @@ def _SLASH_volatile_Group : OptionGroup<"">, 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">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 16e49aab4fe61..148c31912acbd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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(CodeGenOpts.getWinX64EHUnwindV2())); // Indicate whether this Module was compiled with -fopenmp if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1d11be1d82be8..dc910ae125f06 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7352,8 +7352,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Unwind v2 (epilog) information for x64 Windows. - Args.
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
https://github.com/dpaoliello updated https://github.com/llvm/llvm-project/pull/143577 >From 082514ffe8cd9086d82cbe0a114dfc736b0518dc Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 6 Jun 2025 16:39:07 -0700 Subject: [PATCH] Add support for requiring Win x64 Unwind V2 --- clang/include/clang/Basic/CodeGenOptions.def | 6 +- clang/include/clang/Driver/Options.td | 17 +- clang/lib/CodeGen/CodeGenModule.cpp | 6 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 +- clang/test/CodeGen/epilog-unwind.c| 10 +- clang/test/Driver/cl-options.c| 6 +- llvm/include/llvm/IR/Module.h | 4 + llvm/include/llvm/Support/CodeGen.h | 9 + llvm/lib/IR/Module.cpp| 7 + llvm/lib/Target/X86/X86WinEHUnwindV2.cpp | 152 +++-- .../CodeGen/X86/win64-eh-unwindv2-errors.mir | 318 ++ .../win64-eh-unwindv2-too-many-epilogs.mir| 94 ++ 12 files changed, 595 insertions(+), 43 deletions(-) create mode 100644 llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir create mode 100644 llvm/test/CodeGen/X86/win64-eh-unwindv2-too-many-epilogs.mir diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index fa9474d63ae42..32a2ee0e23200 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -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" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 152df89118a6a..0a1e1e0a25f40 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2167,11 +2167,14 @@ defm assume_nothrow_exception_dtor: BoolFOption<"assume-nothrow-exception-dtor", LangOpts<"AssumeNothrowExceptionDtor">, DefaultFalse, PosFlag, NegFlag>; -defm winx64_eh_unwindv2 : BoolFOption<"winx64-eh-unwindv2", - CodeGenOpts<"WinX64EHUnwindV2">, DefaultFalse, - PosFlag, - NegFlag, - BothFlags<[], [ClangOption], " unwind v2 (epilog) information for x64 Windows">>; +def winx64_eh_unwindv2 +: Joined<["-"], "fwinx64-eh-unwindv2=">, 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, "Disabled">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group, Visibility<[ClangOption, CLOption]>, HelpText<"Allows control over excess precision on targets where native " @@ -8971,7 +8974,9 @@ def _SLASH_volatile_Group : OptionGroup<"">, 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">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 16e49aab4fe61..148c31912acbd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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(CodeGenOpts.getWinX64EHUnwindV2())); // Indicate whether this Module was compiled with -fopenmp if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1d11be1d82be8..dc910ae125f06 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7352,8 +7352,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Unwind v2 (epilog) information for x64 Windows. - Args.addO
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
https://github.com/dpaoliello updated https://github.com/llvm/llvm-project/pull/143577 >From 07390317820324535fc75f7bd9dd53c2e65bda41 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 6 Jun 2025 16:39:07 -0700 Subject: [PATCH] Add support for requiring Win x64 Unwind V2 --- clang/include/clang/Basic/CodeGenOptions.def | 6 +- clang/include/clang/Driver/Options.td | 17 +- clang/lib/CodeGen/CodeGenModule.cpp | 6 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 +- clang/test/CodeGen/epilog-unwind.c| 10 +- clang/test/Driver/cl-options.c| 6 +- llvm/include/llvm/IR/Module.h | 4 + llvm/include/llvm/Support/CodeGen.h | 9 + llvm/lib/IR/Module.cpp| 7 + llvm/lib/Target/X86/X86WinEHUnwindV2.cpp | 152 +++-- .../CodeGen/X86/win64-eh-unwindv2-errors.mir | 318 ++ 11 files changed, 501 insertions(+), 43 deletions(-) create mode 100644 llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index fa9474d63ae42..32a2ee0e23200 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -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" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 89c63fb3397d3..d13ce5ce16467 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2167,11 +2167,14 @@ defm assume_nothrow_exception_dtor: BoolFOption<"assume-nothrow-exception-dtor", LangOpts<"AssumeNothrowExceptionDtor">, DefaultFalse, PosFlag, NegFlag>; -defm winx64_eh_unwindv2 : BoolFOption<"winx64-eh-unwindv2", - CodeGenOpts<"WinX64EHUnwindV2">, DefaultFalse, - PosFlag, - NegFlag, - BothFlags<[], [ClangOption], " unwind v2 (epilog) information for x64 Windows">>; +def winx64_eh_unwindv2 +: Joined<["-"], "fwinx64-eh-unwindv2=">, 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, "Disabled">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group, Visibility<[ClangOption, CLOption]>, HelpText<"Allows control over excess precision on targets where native " @@ -8968,7 +8971,9 @@ def _SLASH_volatile_Group : OptionGroup<"">, 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">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 16e49aab4fe61..148c31912acbd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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(CodeGenOpts.getWinX64EHUnwindV2())); // Indicate whether this Module was compiled with -fopenmp if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 65f101ddf1d0a..dce5d132b10a7 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7471,8 +7471,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, op
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
efriedma-quic wrote: The only code that generates prologues and epilogues is PrologEpilogInserter. There isn't any way to skip the normal codegen codepath. (You can write a naked function, but then you'd be responsible for writing your own unwind directives.) reportFatalInternalError seems fine. https://github.com/llvm/llvm-project/pull/143577 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
dpaoliello wrote: I'm happy to change these back to `llvm_unreachable` or `reportFatalInternalError`. Is it possible for something other than LLVM to emit the prolog and epilog, like hand-written assembly or a frontend (e.g., for a custom calling convention). I'll change the too many epilog error to add some guidance (only reasonable thing to do is to manually split the function). https://github.com/llvm/llvm-project/pull/143577 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
https://github.com/efriedma-quic commented: I'm a little concerned about the wording of the errors here. The "too many epilogues" and "too many opcodes" errors should say that it's not yet implemented, or something, so it's clear it's a limitation of the compiler. Maybe try to suggest a workaround of some sort... maybe mention tail-calls since that's the most likely culprit. The other conditions shouldn't occur at all: there's no reason to generate an epilogue that doesn't match the prologue, as far as I know. https://github.com/llvm/llvm-project/pull/143577 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
https://github.com/dpaoliello updated https://github.com/llvm/llvm-project/pull/143577 >From 9a8ab617682ac3bdb13818b6625fe4bd00aacd20 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 6 Jun 2025 16:39:07 -0700 Subject: [PATCH] Add support for requiring Win x64 Unwind V2 --- clang/include/clang/Basic/CodeGenOptions.def | 6 +- clang/include/clang/Driver/Options.td | 17 +- clang/lib/CodeGen/CodeGenModule.cpp | 6 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 +- clang/test/CodeGen/epilog-unwind.c| 10 +- clang/test/Driver/cl-options.c| 6 +- llvm/include/llvm/IR/Module.h | 4 + llvm/include/llvm/Support/CodeGen.h | 9 + llvm/lib/IR/Module.cpp| 7 + llvm/lib/Target/X86/X86WinEHUnwindV2.cpp | 148 ++-- .../CodeGen/X86/win64-eh-unwindv2-errors.mir | 327 ++ 11 files changed, 507 insertions(+), 42 deletions(-) create mode 100644 llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index fa9474d63ae42..32a2ee0e23200 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -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" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 89c63fb3397d3..d13ce5ce16467 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2167,11 +2167,14 @@ defm assume_nothrow_exception_dtor: BoolFOption<"assume-nothrow-exception-dtor", LangOpts<"AssumeNothrowExceptionDtor">, DefaultFalse, PosFlag, NegFlag>; -defm winx64_eh_unwindv2 : BoolFOption<"winx64-eh-unwindv2", - CodeGenOpts<"WinX64EHUnwindV2">, DefaultFalse, - PosFlag, - NegFlag, - BothFlags<[], [ClangOption], " unwind v2 (epilog) information for x64 Windows">>; +def winx64_eh_unwindv2 +: Joined<["-"], "fwinx64-eh-unwindv2=">, 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, "Disabled">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group, Visibility<[ClangOption, CLOption]>, HelpText<"Allows control over excess precision on targets where native " @@ -8968,7 +8971,9 @@ def _SLASH_volatile_Group : OptionGroup<"">, 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">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 16e49aab4fe61..148c31912acbd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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(CodeGenOpts.getWinX64EHUnwindV2())); // Indicate whether this Module was compiled with -fopenmp if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 65f101ddf1d0a..dce5d132b10a7 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7471,8 +7471,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, opt
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff HEAD~1 HEAD --extensions c,cpp,h -- clang/lib/CodeGen/CodeGenModule.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/test/CodeGen/epilog-unwind.c clang/test/Driver/cl-options.c llvm/include/llvm/IR/Module.h llvm/include/llvm/Support/CodeGen.h llvm/lib/IR/Module.cpp llvm/lib/Target/X86/X86WinEHUnwindV2.cpp `` View the diff from clang-format here. ``diff diff --git a/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp b/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp index 01256ec89..ae53a5060 100644 --- a/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp +++ b/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp @@ -37,9 +37,9 @@ static cl::opt MaximumUnwindCodes( cl::desc("Maximum number of unwind codes permitted in each unwind info."), cl::init(UINT8_MAX)); -static cl::opt ForceMode( -"x86-wineh-unwindv2-force-mode", cl::Hidden, -cl::desc("Overwrites the Unwind v2 mode for testing purposes.")); +static cl::opt +ForceMode("x86-wineh-unwindv2-force-mode", cl::Hidden, + cl::desc("Overwrites the Unwind v2 mode for testing purposes.")); namespace { @@ -57,8 +57,7 @@ public: private: bool rejectCurrentFunction(const MachineFunction &MF, const DebugLoc &Loc, - WinX64EHUnwindV2Mode Mode, - StringRef Reason) const; + WinX64EHUnwindV2Mode Mode, StringRef Reason) const; bool rejectCurrentFunction(const MachineFunction &MF, const MachineBasicBlock &EpilogBlock, @@ -67,8 +66,7 @@ private: // If we're in the Epilog, then the generated instructions might not have a // location, so use the terminator's location. return rejectCurrentFunction( -MF, EpilogBlock.getFirstTerminator()->getDebugLoc(), Mode, -Reason); +MF, EpilogBlock.getFirstTerminator()->getDebugLoc(), Mode, Reason); } }; @@ -204,14 +202,14 @@ bool X86WinEHUnwindV2::runOnMachineFunction(MachineFunction &MF) { // If the prolog contains a stack allocation, then the first // instruction in the epilog must be to adjust the stack pointer. if (!HasStackAlloc) -return rejectCurrentFunction( -MF, MBB, Mode, -"The epilog is deallocating a stack allocation, but the prolog did " -"not allocate one"); +return rejectCurrentFunction(MF, MBB, Mode, + "The epilog is deallocating a stack " + "allocation, but the prolog did " + "not allocate one"); if (HasStackDealloc) -return rejectCurrentFunction( -MF, MBB, Mode, -"The epilog is deallocating the stack allocation more than once"); +return rejectCurrentFunction(MF, MBB, Mode, + "The epilog is deallocating the stack " + "allocation more than once"); if (PoppedRegCount > 0) llvm_unreachable( "Should have raised an error: either popping before " @@ -230,19 +228,20 @@ bool X86WinEHUnwindV2::runOnMachineFunction(MachineFunction &MF) { // POP each register in reverse order of the PUSHes in the prolog. PoppedRegCount++; if (HasStackAlloc != HasStackDealloc) -return rejectCurrentFunction(MF, MBB, Mode, - "Cannot pop registers before the stack " - "allocation has been deallocated"); +return rejectCurrentFunction( +MF, MBB, Mode, +"Cannot pop registers before the stack " +"allocation has been deallocated"); if (PoppedRegCount > PushedRegs.size()) return rejectCurrentFunction( MF, MBB, Mode, "The epilog is popping more registers than the prolog pushed"); if (PushedRegs[PushedRegs.size() - PoppedRegCount] != MI.getOperand(0).getReg()) -return rejectCurrentFunction( -MF, MBB, Mode, -"The epilog is popping a registers in a different order than the " -"prolog pushed them"); +return rejectCurrentFunction(MF, MBB, Mode, + "The epilog is popping a registers in " + "a different order than the " + "prolog pushed them"); // Unwind v2 records the size of the epilog not from where we place // SEH_BeginEpilogue (as that contains the instruction to adjust th
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
https://github.com/dpaoliello created https://github.com/llvm/llvm-project/pull/143577 #129142 added support for emitting Windows x64 unwind v2 information, but it was "best effort". If any function didn't follow the requirements for v2 it was silently downgraded to v1. There are some parts of Windows (specifically kernel-mode code running on Xbox) that require v2, hence we need the ability to fail the compilation if v2 can't be used. This change also adds a heuristic to check if there might be too many unwind codes, it's currently conservative (i.e., assumes that certain prolog instructions will use the maximum number of unwind codes). Future work: attempting to chain unwind info across multiple tables if there are too many unwind codes due to epilogs and adding a heuristic to detect if an epilog will be too far from the end of the function. >From 8244cf55c8e432f637863ddf9acbac56792750d5 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 6 Jun 2025 16:39:07 -0700 Subject: [PATCH] Add support for requiring Win x64 Unwind V2 --- clang/include/clang/Basic/CodeGenOptions.def | 6 +- clang/include/clang/Driver/Options.td | 17 +- clang/lib/CodeGen/CodeGenModule.cpp | 6 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 +- clang/test/CodeGen/epilog-unwind.c| 10 +- clang/test/Driver/cl-options.c| 6 +- llvm/include/llvm/IR/Module.h | 4 + llvm/include/llvm/Support/CodeGen.h | 9 + llvm/lib/IR/Module.cpp| 7 + llvm/lib/Target/X86/X86WinEHUnwindV2.cpp | 151 ++-- .../CodeGen/X86/win64-eh-unwindv2-errors.mir | 327 ++ 11 files changed, 510 insertions(+), 42 deletions(-) create mode 100644 llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index fa9474d63ae42..32a2ee0e23200 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -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" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 89c63fb3397d3..d13ce5ce16467 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2167,11 +2167,14 @@ defm assume_nothrow_exception_dtor: BoolFOption<"assume-nothrow-exception-dtor", LangOpts<"AssumeNothrowExceptionDtor">, DefaultFalse, PosFlag, NegFlag>; -defm winx64_eh_unwindv2 : BoolFOption<"winx64-eh-unwindv2", - CodeGenOpts<"WinX64EHUnwindV2">, DefaultFalse, - PosFlag, - NegFlag, - BothFlags<[], [ClangOption], " unwind v2 (epilog) information for x64 Windows">>; +def winx64_eh_unwindv2 +: Joined<["-"], "fwinx64-eh-unwindv2=">, 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, "Disabled">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group, Visibility<[ClangOption, CLOption]>, HelpText<"Allows control over excess precision on targets where native " @@ -8968,7 +8971,9 @@ def _SLASH_volatile_Group : OptionGroup<"">, 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">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 16e49aab4fe61..148c31912acbd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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) +get
[clang] [llvm] [win][x64] Unwind v2 3/n: Add support for requiring unwind v2 to be used (equivalent to MSVC's /d2epilogunwindrequirev2) (PR #143577)
llvmbot wrote: @llvm/pr-subscribers-llvm-support @llvm/pr-subscribers-clang-codegen Author: Daniel Paoliello (dpaoliello) Changes #129142 added support for emitting Windows x64 unwind v2 information, but it was "best effort". If any function didn't follow the requirements for v2 it was silently downgraded to v1. There are some parts of Windows (specifically kernel-mode code running on Xbox) that require v2, hence we need the ability to fail the compilation if v2 can't be used. This change also adds a heuristic to check if there might be too many unwind codes, it's currently conservative (i.e., assumes that certain prolog instructions will use the maximum number of unwind codes). Future work: attempting to chain unwind info across multiple tables if there are too many unwind codes due to epilogs and adding a heuristic to detect if an epilog will be too far from the end of the function. --- Patch is 32.26 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143577.diff 11 Files Affected: - (modified) clang/include/clang/Basic/CodeGenOptions.def (+4-2) - (modified) clang/include/clang/Driver/Options.td (+11-6) - (modified) clang/lib/CodeGen/CodeGenModule.cpp (+4-2) - (modified) clang/lib/Driver/ToolChains/Clang.cpp (+5-4) - (modified) clang/test/CodeGen/epilog-unwind.c (+6-4) - (modified) clang/test/Driver/cl-options.c (+5-1) - (modified) llvm/include/llvm/IR/Module.h (+4) - (modified) llvm/include/llvm/Support/CodeGen.h (+9) - (modified) llvm/lib/IR/Module.cpp (+7) - (modified) llvm/lib/Target/X86/X86WinEHUnwindV2.cpp (+128-23) - (added) llvm/test/CodeGen/X86/win64-eh-unwindv2-errors.mir (+327) ``diff diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index fa9474d63ae42..32a2ee0e23200 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -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" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 89c63fb3397d3..d13ce5ce16467 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2167,11 +2167,14 @@ defm assume_nothrow_exception_dtor: BoolFOption<"assume-nothrow-exception-dtor", LangOpts<"AssumeNothrowExceptionDtor">, DefaultFalse, PosFlag, NegFlag>; -defm winx64_eh_unwindv2 : BoolFOption<"winx64-eh-unwindv2", - CodeGenOpts<"WinX64EHUnwindV2">, DefaultFalse, - PosFlag, - NegFlag, - BothFlags<[], [ClangOption], " unwind v2 (epilog) information for x64 Windows">>; +def winx64_eh_unwindv2 +: Joined<["-"], "fwinx64-eh-unwindv2=">, 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, "Disabled">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group, Visibility<[ClangOption, CLOption]>, HelpText<"Allows control over excess precision on targets where native " @@ -8968,7 +8971,9 @@ def _SLASH_volatile_Group : OptionGroup<"">, 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">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 16e49aab4fe61..148c31912acbd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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(CodeGenOpts.getWinX