[PATCH] D77936: [Windows SEH] Fix abnormal-exits in _try

Ten Tzen via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sat Apr 11 01:34:28 PDT 2020


tentzen created this revision.
tentzen added reviewers: rnk, eli.friedman, JosephTremoulet, asmith.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77936

Files:
  clang/lib/CodeGen/CGCleanup.cpp
  clang/lib/CodeGen/CGException.cpp
  clang/lib/CodeGen/EHScopeStack.h


Index: clang/lib/CodeGen/EHScopeStack.h
===================================================================
--- clang/lib/CodeGen/EHScopeStack.h
+++ clang/lib/CodeGen/EHScopeStack.h
@@ -160,7 +160,8 @@
       enum {
         F_IsForEH             = 0x1,
         F_IsNormalCleanupKind = 0x2,
-        F_IsEHCleanupKind     = 0x4
+        F_IsEHCleanupKind     = 0x4,
+        F_HasSehAbnormalExits = 0x8
       };
       unsigned flags;
 
@@ -179,6 +180,9 @@
       /// cleanup.
       bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; }
       void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
+
+      bool hasSehAbnormalExits() const { return flags & F_HasSehAbnormalExits; }
+      void setHasSehAbnormalExits() { flags |= F_HasSehAbnormalExits; }
     };
 
 
Index: clang/lib/CodeGen/CGException.cpp
===================================================================
--- clang/lib/CodeGen/CGException.cpp
+++ clang/lib/CodeGen/CGException.cpp
@@ -1639,6 +1639,18 @@
 
     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.hasSehAbnormalExits()) {
+      Address Addr = CGF.getNormalCleanupDestSlot();
+      llvm::Value* Load = CGF.Builder.CreateLoad(Addr, "cleanup.dest");
+      IsForEH = CGF.Builder.CreateTrunc(Load, CGM.Int8Ty);
+    }
+
     Args.add(RValue::get(IsForEH), ArgTys[0]);
     Args.add(RValue::get(FP), ArgTys[1]);
 
Index: clang/lib/CodeGen/CGCleanup.cpp
===================================================================
--- clang/lib/CodeGen/CGCleanup.cpp
+++ clang/lib/CodeGen/CGCleanup.cpp
@@ -860,6 +860,9 @@
         // TODO: base this on the number of branch-afters and fixups
         const unsigned SwitchCapacity = 10;
 
+        // pass the abnormal exit flag to Fn (SEH cleanup)
+        cleanupFlags.setHasSehAbnormalExits();
+
         llvm::LoadInst *Load =
           createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest",
                                nullptr);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D77936.256754.patch
Type: text/x-patch
Size: 2367 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200411/ce8552e0/attachment-0001.bin>


More information about the cfe-commits mailing list