aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGException.cpp
diff options
context:
space:
mode:
authorAaron Smith <aaron.smith@microsoft.com>2020-04-30 09:38:19 -0700
committerAaron Smith <aaron.smith@microsoft.com>2020-04-30 09:38:19 -0700
commit4eabd006125424f879a7129eca824998192d89a9 (patch)
tree934e82b10b9cc7aef02fd8d51c9a1c67f3b2f8cc /clang/lib/CodeGen/CGException.cpp
parentb257d3c8a897b9999b9bdb660fc8eaad772a0085 (diff)
downloadllvm-4eabd006125424f879a7129eca824998192d89a9.zip
llvm-4eabd006125424f879a7129eca824998192d89a9.tar.gz
llvm-4eabd006125424f879a7129eca824998192d89a9.tar.bz2
[Windows SEH] Fix abnormal-exits in _try
Summary: Per Windows SEH Spec, except _leave, all other early exits of a _try (goto/return/continue/break) are considered abnormal exits. In those cases, the first parameter passes to its _finally funclet should be TRUE to indicate an abnormal-termination. One way to implement abnormal exits in _try is to invoke Windows runtime _local_unwind() (MSVC approach) that will invoke _dtor funclet where abnormal-termination flag is always TRUE when calling _finally. Obviously this approach is less optimal and is complicated to implement in Clang. Clang today has a NormalCleanupDestSlot mechanism to dispatch multiple exits at the end of _try. Since _leave (or try-end fall-through) is always Indexed with 0 in that NormalCleanupDestSlot, this fix takes the advantage of that mechanism and just passes NormalCleanupDest ID as 1st Arg to _finally. Reviewers: rnk, eli.friedman, JosephTremoulet, asmith, efriedma Reviewed By: efriedma Subscribers: efriedma, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D77936
Diffstat (limited to 'clang/lib/CodeGen/CGException.cpp')
-rw-r--r--clang/lib/CodeGen/CGException.cpp13
1 files changed, 13 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index a542c3d..a5dae1b 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1639,6 +1639,19 @@ struct PerformSEHFinally final : EHScopeStack::Cleanup {
llvm::Value *IsForEH =
llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
+
+ // Except _leave and fall-through at the end, all other exits in a _try
+ // (return/goto/continue/break) are considered as abnormal terminations
+ // since _leave/fall-through is always Indexed 0,
+ // just use NormalCleanupDestSlot (>= 1 for goto/return/..),
+ // as 1st Arg to indicate abnormal termination
+ if (!F.isForEHCleanup() && F.hasExitSwitch()) {
+ Address Addr = CGF.getNormalCleanupDestSlot();
+ llvm::Value *Load = CGF.Builder.CreateLoad(Addr, "cleanup.dest");
+ llvm::Value *Zero = llvm::Constant::getNullValue(CGM.Int32Ty);
+ IsForEH = CGF.Builder.CreateICmpNE(Load, Zero);
+ }
+
Args.add(RValue::get(IsForEH), ArgTys[0]);
Args.add(RValue::get(FP), ArgTys[1]);