tentzen updated this revision to Diff 257849.
tentzen added a comment.
Replace F_HasSehAbnormalExits with F_HasExitSwitch
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,30 @@
+// RUN: %clang_cc1 -triple x86_64-windows -fms-extensions -Wno-implicit-function-declaration -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-]+]] = icmp ne i32 %cleanup.dest, 0
+// CHECK-NEXT: %[[src3:[0-9-]+]] = zext i1 %[[src2]] to i8
+// CHECK-NEXT: call void @"?fin$0@0@seh_abnormal_exits@@"(i8 %[[src3]], 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_HasExitSwitch = 0x8,
};
unsigned flags;
@@ -179,8 +180,10 @@
/// cleanup.
bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; }
void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
- };
+ bool hasExitSwitch() const { return flags & F_HasExitSwitch; }
+ void setHasExitSwitch() { flags |= F_HasExitSwitch; }
+ };
/// 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.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]);
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.setHasExitSwitch();
+
llvm::LoadInst *Load =
createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest",
nullptr);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits