tentzen updated this revision to Diff 256836.
tentzen marked an inline comment as done.
tentzen added a comment.

Per Eli's feedbacks:
(1) a test case (windows-seh-abnormal-exit.c) is added under clang\test\CodeGen 
directory.  
(2) an assert is added to catch the extremely rare case that the number of 
JumpDests in a function is greater than 255.  The max. number of JumpDests is 1 
(return) + 2*M + N, where M is the number of for/while-loops and N is the 
number of Goto targets.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77936/new/

https://reviews.llvm.org/D77936

Files:
  clang/lib/CodeGen/CGCleanup.cpp
  clang/lib/CodeGen/CGException.cpp
  clang/lib/CodeGen/EHScopeStack.h
  clang/test/CodeGen/windows-seh-abnormal-exits.c

Index: clang/test/CodeGen/windows-seh-abnormal-exits.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/windows-seh-abnormal-exits.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple x86_64-windows -Wno-implicit-function-declaraton -S -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: %[[src:[0-9-]+]] = call i8* @llvm.localaddress()
+// CHECK-NEXT: %cleanup.dest = load i32, i32* %cleanup.dest.slot, align 4
+// CHECK-NEXT: %[[src2:[0-9-]+]] = trunc i32 %cleanup.dest to i8
+// CHECK-NEXT: call void @"?fin$0@0@seh_abnormal_exits@@"(i8 %[[src2]], i8* %[[src]])
+
+void seh_abnormal_exits(int *Counter) {
+  for (int i = 0; i < 5; i++) {
+    __try {
+      if (i == 0)
+        continue;   // abnormal termination
+      else if (i == 1)
+        goto t10;   // abnormal termination
+      else if (i == 2)
+        __leave;  // normal execution
+      else if (i == 4)
+        return;  // abnormal termination
+    }
+    __finally {
+      if (AbnormalTermination()) {
+        *Counter += 1;
+      }
+    }
+  t10:;
+  }
+  return; // *Counter == 3
+}
+
Index: clang/lib/CodeGen/EHScopeStack.h
===================================================================
--- clang/lib/CodeGen/EHScopeStack.h
+++ clang/lib/CodeGen/EHScopeStack.h
@@ -158,9 +158,10 @@
     /// Generation flags.
     class Flags {
       enum {
-        F_IsForEH             = 0x1,
+        F_IsForEH = 0x1,
         F_IsNormalCleanupKind = 0x2,
-        F_IsEHCleanupKind     = 0x4
+        F_IsEHCleanupKind = 0x4,
+        F_HasSehAbnormalExits = 0x8,
       };
       unsigned flags;
 
@@ -179,8 +180,10 @@
       /// 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; }
+    };
 
     /// Emit the cleanup.  For normal cleanups, this is run in the
     /// same EH context as when the cleanup was pushed, i.e. the
Index: clang/lib/CodeGen/CGException.cpp
===================================================================
--- clang/lib/CodeGen/CGException.cpp
+++ clang/lib/CodeGen/CGException.cpp
@@ -1639,6 +1639,19 @@
 
     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()) {
+      assert(CGF.NextCleanupDestIndex < 256 && " JumpDest Index exceeds 255");
+      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);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to