jyu2 created this revision.
jyu2 added reviewers: asmith, tentzen, rnk, efriedma, pengfei.
jyu2 added a project: clang.
Herald added a project: All.
jyu2 requested review of this revision.

When return out of __try block.  In this test case, currently "false" is
passed to the OutlinedFinally call,  "true" should be passed to indicate 
abnormal
terminations.

The rule: Except _leave and fall-through at the end, all other exits
in a _try (return/goto/continue/break) are considered as abnormal
terminations, NormalCleanupDestSlot is used to indicate abnormal
terminations.

The problem is, during the processing abnormal termination,
the ExitSwitch is used.  However, in this case, Existswitch is route out.

One way to fix is to skip route it without a switch. So proper
abnormal termination's code could be generated.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158233

Files:
  clang/lib/CodeGen/CGCleanup.cpp
  clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp


Index: clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
===================================================================
--- clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
+++ clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions 
-fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S 
-emit-llvm %s -o - | FileCheck %s
 
+// CHECK-LABEL: @main()
 // CHECK: invoke void @llvm.seh.try.begin()
 // CHECK: invoke void @llvm.seh.try.begin()
 // CHECK: %[[src:[0-9-]+]] = load volatile i32, ptr %i
@@ -40,3 +41,29 @@
   }
   return 0;
 }
+
+// CHECK-LABEL:@"?foo@@YAXXZ"()
+// CHECK: invoke.cont:
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: store volatile i32 1, ptr %cleanup.dest.slot
+// CHECK: invoke void @llvm.seh.try.end()
+// CHECK: invoke.cont2:
+// CHECK: %cleanup.dest = load i32, ptr %cleanup.dest.slot
+// CHECK: %1 = icmp ne i32 %cleanup.dest, 0
+// CHECK: %2 = zext i1 %1 to i8
+// CHECK: call void @"?fin$0@0@foo@@"(i8 noundef %2, ptr noundef %0)
+// CHECK: ehcleanup:
+// CHECK: call void @"?fin$0@0@foo@@"(i8 noundef 1, ptr noundef %4)
+void foo()
+{
+  __try {
+    return;
+  }
+  __finally {
+    if (_abnormal_termination()) {
+      printf("Passed\n");
+    } else {
+      printf("Failed\n");
+    }
+  }
+}
Index: clang/lib/CodeGen/CGCleanup.cpp
===================================================================
--- clang/lib/CodeGen/CGCleanup.cpp
+++ clang/lib/CodeGen/CGCleanup.cpp
@@ -873,8 +873,13 @@
 
       // If there's exactly one branch-after and no other threads,
       // we can route it without a switch.
+      // Skip for SEH, since ExitSwitch is used to generate code to indicate
+      // abnormal termination. (SEH: Except _leave and fall-through at
+      // the end, all other exits in a _try (return/goto/continue/break)
+      // are considered as abnormal terminations, using NormalCleanupDestSlot
+      // to indicate abnormal termination)
       if (!Scope.hasBranchThroughs() && !HasFixups && !HasFallthrough &&
-          Scope.getNumBranchAfters() == 1) {
+          !getLangOpts().EHAsynch && Scope.getNumBranchAfters() == 1) {
         assert(!BranchThroughDest || !IsActive);
 
         // Clean up the possibly dead store to the cleanup dest slot.


Index: clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
===================================================================
--- clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
+++ clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s
 
+// CHECK-LABEL: @main()
 // CHECK: invoke void @llvm.seh.try.begin()
 // CHECK: invoke void @llvm.seh.try.begin()
 // CHECK: %[[src:[0-9-]+]] = load volatile i32, ptr %i
@@ -40,3 +41,29 @@
   }
   return 0;
 }
+
+// CHECK-LABEL:@"?foo@@YAXXZ"()
+// CHECK: invoke.cont:
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: store volatile i32 1, ptr %cleanup.dest.slot
+// CHECK: invoke void @llvm.seh.try.end()
+// CHECK: invoke.cont2:
+// CHECK: %cleanup.dest = load i32, ptr %cleanup.dest.slot
+// CHECK: %1 = icmp ne i32 %cleanup.dest, 0
+// CHECK: %2 = zext i1 %1 to i8
+// CHECK: call void @"?fin$0@0@foo@@"(i8 noundef %2, ptr noundef %0)
+// CHECK: ehcleanup:
+// CHECK: call void @"?fin$0@0@foo@@"(i8 noundef 1, ptr noundef %4)
+void foo()
+{
+  __try {
+    return;
+  }
+  __finally {
+    if (_abnormal_termination()) {
+      printf("Passed\n");
+    } else {
+      printf("Failed\n");
+    }
+  }
+}
Index: clang/lib/CodeGen/CGCleanup.cpp
===================================================================
--- clang/lib/CodeGen/CGCleanup.cpp
+++ clang/lib/CodeGen/CGCleanup.cpp
@@ -873,8 +873,13 @@
 
       // If there's exactly one branch-after and no other threads,
       // we can route it without a switch.
+      // Skip for SEH, since ExitSwitch is used to generate code to indicate
+      // abnormal termination. (SEH: Except _leave and fall-through at
+      // the end, all other exits in a _try (return/goto/continue/break)
+      // are considered as abnormal terminations, using NormalCleanupDestSlot
+      // to indicate abnormal termination)
       if (!Scope.hasBranchThroughs() && !HasFixups && !HasFallthrough &&
-          Scope.getNumBranchAfters() == 1) {
+          !getLangOpts().EHAsynch && Scope.getNumBranchAfters() == 1) {
         assert(!BranchThroughDest || !IsActive);
 
         // Clean up the possibly dead store to the cleanup dest slot.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to