tentzen updated this revision to Diff 265442.
tentzen added a comment.

fixed formats


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D80344

Files:
  clang/include/clang/AST/Stmt.h
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGCleanup.cpp
  clang/lib/CodeGen/CGDecl.cpp
  clang/lib/CodeGen/CGException.cpp
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Sema/JumpDiagnostics.cpp
  clang/test/CodeGen/windows-seh-EHa-CppCatchDotDotDot.cpp
  clang/test/CodeGen/windows-seh-EHa-CppDtors01.cpp
  clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
  llvm/include/llvm/CodeGen/SelectionDAGISel.h
  llvm/include/llvm/CodeGen/WinEHFuncInfo.h
  llvm/include/llvm/IR/BasicBlock.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Analysis/EHPersonalities.cpp
  llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
  llvm/lib/CodeGen/AsmPrinter/WinException.cpp
  llvm/lib/CodeGen/BranchFolding.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
  llvm/lib/CodeGen/WinEHPrepare.cpp
  llvm/lib/IR/BasicBlock.cpp
  llvm/lib/IR/Verifier.cpp
  llvm/test/CodeGen/X86/windows-seh-EHa-CppCatchDotDotDot.ll
  llvm/test/CodeGen/X86/windows-seh-EHa-CppDtors01.ll
  llvm/test/CodeGen/X86/windows-seh-EHa-TryInFinally.ll

Index: llvm/test/CodeGen/X86/windows-seh-EHa-TryInFinally.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/windows-seh-EHa-TryInFinally.ll
@@ -0,0 +1,226 @@
+; RUN: llc -verify-machineinstrs < %s | FileCheck %s
+
+; CHECK-LABEL: "?fin$0@0@main@@"
+; CHECK:      .seh_handlerdata
+; CHECK:      .set ".L?fin$0@0@main@@$parent_frame_offset", 48
+; CHECK-NEXT:        .long   (.Llsda_end1-.Llsda_begin1)/16 
+; CHECK-NEXT: .Llsda_begin1:
+; CHECK-NEXT:        .long   .Ltmp
+; CHECK-NEXT:        .long   .Ltmp
+; CHECK-NEXT:        .long   "?dtor$
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT: .Llsda_end1:
+
+; ModuleID = 'windows-seh-EHa-TryInFinally.cpp'
+source_filename = "windows-seh-EHa-TryInFinally.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-msvc"
+
+$"??_C@_0CI@MDFPIOJJ@?5?9?9?9?5Test?5_Try?5in?5_finally?5?9?9?9?5i@" = comdat any
+
+$"??_C@_0BN@HHKJHLBE@?5?5In?5Inner?5_finally?5i?5?$DN?5?$CFd?5?6?$AA@" = comdat any
+
+$"??_C@_0BN@HAIIIOKI@?5?5In?5outer?5_finally?5i?5?$DN?5?$CFd?5?6?$AA@" = comdat any
+
+$"??_C@_0BJ@OJMMAGCD@?5?5In?5outer?5_try?5i?5?$DN?5?$CFd?5?6?$AA@" = comdat any
+
+$"??_C@_0CG@ENDJHCGA@?5?9?9?9?5In?5outer?5except?5handler?5i?5?$DN@" = comdat any
+
+@"??_C@_0CI@MDFPIOJJ@?5?9?9?9?5Test?5_Try?5in?5_finally?5?9?9?9?5i@" = linkonce_odr dso_local unnamed_addr constant [40 x i8] c" --- Test _Try in _finally --- i = %d \0A\00", comdat, align 1
+@"??_C@_0BN@HHKJHLBE@?5?5In?5Inner?5_finally?5i?5?$DN?5?$CFd?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [29 x i8] c"  In Inner _finally i = %d \0A\00", comdat, align 1
+@"??_C@_0BN@HAIIIOKI@?5?5In?5outer?5_finally?5i?5?$DN?5?$CFd?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [29 x i8] c"  In outer _finally i = %d \0A\00", comdat, align 1
+@"??_C@_0BJ@OJMMAGCD@?5?5In?5outer?5_try?5i?5?$DN?5?$CFd?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [25 x i8] c"  In outer _try i = %d \0A\00", comdat, align 1
+@"??_C@_0CG@ENDJHCGA@?5?9?9?9?5In?5outer?5except?5handler?5i?5?$DN@" = linkonce_odr dso_local unnamed_addr constant [38 x i8] c" --- In outer except handler i = %d \0A\00", comdat, align 1
+
+; Function Attrs: noinline norecurse optnone
+define dso_local i32 @main() #0 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
+entry:
+  %retval = alloca i32, align 4
+  %i = alloca i32, align 4
+  %__exception_code = alloca i32, align 4
+  call void (...) @llvm.localescape(i32* %i)
+  store i32 0, i32* %retval, align 4
+  store i32 0, i32* %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = load i32, i32* %i, align 4
+  %cmp = icmp slt i32 %0, 3
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %1 = load i32, i32* %i, align 4
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([40 x i8], [40 x i8]* @"??_C@_0CI@MDFPIOJJ@?5?9?9?9?5Test?5_Try?5in?5_finally?5?9?9?9?5i@", i64 0, i64 0), i32 %1)
+  invoke void @llvm.seh.try.begin()
+          to label %invoke.cont unwind label %catch.dispatch
+
+invoke.cont:                                      ; preds = %for.body
+  invoke void @llvm.seh.try.begin()
+          to label %invoke.cont1 unwind label %ehcleanup
+
+invoke.cont1:                                     ; preds = %invoke.cont
+  %2 = load volatile i32, i32* %i, align 4
+  invoke void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @"??_C@_0BJ@OJMMAGCD@?5?5In?5outer?5_try?5i?5?$DN?5?$CFd?5?6?$AA@", i64 0, i64 0), i32 %2) #6
+          to label %invoke.cont2 unwind label %ehcleanup
+
+invoke.cont2:                                     ; preds = %invoke.cont1
+  %3 = load volatile i32, i32* %i, align 4
+  %cmp3 = icmp eq i32 %3, 0
+  br i1 %cmp3, label %if.then, label %if.end
+
+if.then:                                          ; preds = %invoke.cont2
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %invoke.cont2
+  invoke void @llvm.seh.try.end()
+          to label %invoke.cont4 unwind label %ehcleanup
+
+invoke.cont4:                                     ; preds = %if.end
+  %4 = call i8* @llvm.localaddress()
+  invoke void @"?fin$0@0@main@@"(i8 0, i8* %4) #6
+          to label %invoke.cont5 unwind label %catch.dispatch
+
+invoke.cont5:                                     ; preds = %invoke.cont4
+  invoke void @llvm.seh.try.end()
+          to label %invoke.cont7 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %invoke.cont5, %invoke.cont6, %ehcleanup, %invoke.cont4, %for.body
+  %5 = catchswitch within none [label %__except] unwind to caller
+
+__except:                                         ; preds = %catch.dispatch
+  %6 = catchpad within %5 [i8* null]
+  catchret from %6 to label %__except8
+
+__except8:                                        ; preds = %__except
+  %7 = call i32 @llvm.eh.exceptioncode(token %6)
+  store i32 %7, i32* %__exception_code, align 4
+  %8 = load i32, i32* %i, align 4
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([38 x i8], [38 x i8]* @"??_C@_0CG@ENDJHCGA@?5?9?9?9?5In?5outer?5except?5handler?5i?5?$DN@", i64 0, i64 0), i32 %8)
+  br label %__try.cont
+
+__try.cont:                                       ; preds = %__except8, %invoke.cont7
+  br label %for.inc
+
+for.inc:                                          ; preds = %__try.cont
+  %9 = load i32, i32* %i, align 4
+  %inc = add nsw i32 %9, 1
+  store i32 %inc, i32* %i, align 4
+  br label %for.cond
+
+invoke.cont7:                                     ; preds = %invoke.cont5
+  br label %__try.cont
+
+ehcleanup:                                        ; preds = %if.end, %invoke.cont1, %invoke.cont
+  %10 = cleanuppad within none []
+  %11 = call i8* @llvm.localaddress()
+  invoke void @"?fin$0@0@main@@"(i8 1, i8* %11) #6 [ "funclet"(token %10) ]
+          to label %invoke.cont6 unwind label %catch.dispatch
+
+invoke.cont6:                                     ; preds = %ehcleanup
+  cleanupret from %10 unwind label %catch.dispatch
+
+for.end:                                          ; preds = %for.cond
+  ret i32 0
+}
+
+declare dso_local void @"?printf@@YAXZZ"(...) #1
+
+; Function Attrs: nounwind willreturn
+declare dso_local void @llvm.seh.try.begin() #2
+
+declare dso_local i32 @__C_specific_handler(...)
+
+; Function Attrs: noinline
+define internal void @"?fin$0@0@main@@"(i8 %abnormal_termination, i8* %frame_pointer) #3 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
+entry:
+  %frame_pointer.addr = alloca i8*, align 8
+  %abnormal_termination.addr = alloca i8, align 1
+  %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %frame_pointer, i32 0)
+  %i = bitcast i8* %0 to i32*
+  store i8* %frame_pointer, i8** %frame_pointer.addr, align 8
+  store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1
+  invoke void @llvm.seh.try.begin()
+          to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  %1 = load volatile i32, i32* %i, align 4
+  invoke void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @"??_C@_0BN@HAIIIOKI@?5?5In?5outer?5_finally?5i?5?$DN?5?$CFd?5?6?$AA@", i64 0, i64 0), i32 %1) #6
+          to label %invoke.cont1 unwind label %ehcleanup
+
+invoke.cont1:                                     ; preds = %invoke.cont
+  %2 = load volatile i32, i32* %i, align 4
+  %cmp = icmp eq i32 %2, 1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %invoke.cont1
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %invoke.cont1
+  invoke void @llvm.seh.try.end()
+          to label %invoke.cont2 unwind label %ehcleanup
+
+invoke.cont2:                                     ; preds = %if.end
+  call void @"?fin$1@0@main@@"(i8 0, i8* %frame_pointer)
+  ret void
+
+ehcleanup:                                        ; preds = %if.end, %invoke.cont, %entry
+  %3 = cleanuppad within none []
+  call void @"?fin$1@0@main@@"(i8 1, i8* %frame_pointer) [ "funclet"(token %3) ]
+  cleanupret from %3 unwind to caller
+}
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.localrecover(i8*, i8*, i32 immarg) #4
+
+; Function Attrs: noinline
+define internal void @"?fin$1@0@main@@"(i8 %abnormal_termination, i8* %frame_pointer) #3 {
+entry:
+  %frame_pointer.addr = alloca i8*, align 8
+  %abnormal_termination.addr = alloca i8, align 1
+  %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %frame_pointer, i32 0)
+  %i = bitcast i8* %0 to i32*
+  store i8* %frame_pointer, i8** %frame_pointer.addr, align 8
+  store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1
+  %1 = load i32, i32* %i, align 4
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @"??_C@_0BN@HHKJHLBE@?5?5In?5Inner?5_finally?5i?5?$DN?5?$CFd?5?6?$AA@", i64 0, i64 0), i32 %1)
+  %2 = load i32, i32* %i, align 4
+  %cmp = icmp eq i32 %2, 2
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  ret void
+}
+
+; Function Attrs: nounwind willreturn
+declare dso_local void @llvm.seh.try.end() #2
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.localaddress() #4
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.eh.exceptioncode(token) #4
+
+; Function Attrs: nounwind
+declare void @llvm.localescape(...) #5
+
+attributes #0 = { noinline norecurse optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind willreturn }
+attributes #3 = { noinline "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind readnone }
+attributes #5 = { nounwind }
+attributes #6 = { noinline }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 2}
+!1 = !{i32 2, !"eh-asynch", i32 1}
+!2 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project 7ee479a760e0a4402b4eb7fb6168768a44f66945)"}
+
Index: llvm/test/CodeGen/X86/windows-seh-EHa-CppDtors01.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/windows-seh-EHa-CppDtors01.ll
@@ -0,0 +1,258 @@
+; RUN: llc -verify-machineinstrs < %s | FileCheck %s
+
+; CHECK-LABEL: "$cppxdata$?crash@@YAXH@Z":
+; CHECK:	.long	("$stateUnwindMap$?crash@@YAXH@Z")
+; CHECK:	.long	("$ip2state$?crash@@YAXH@Z")
+
+; CHECK-LABEL: "$stateUnwindMap$?crash@@YAXH@Z":
+; CHECK:	.long	-1 
+; CHECK:	.long	"?dtor$
+; CHECK:	.long	0 
+; CHECK:	.long	"?dtor$
+; CHECK:	.long	1
+; CHECK:	.long	"?dtor$
+
+; CHECK-LABEL: "$ip2state$?crash@@YAXH@Z":
+; CHECK-NEXT:	.long	.Lfunc_begin0@IMGREL
+; CHECK-NEXT:	.long	-1                  
+; CHECK-NEXT:	.long	.Ltmp     
+; CHECK-NEXT:	.long	0                   
+; CHECK-NEXT:	.long	.Ltmp     
+; CHECK-NEXT:	.long	1                   
+; CHECK-NEXT:	.long	.Ltmp
+; CHECK-NEXT:	.long	2                   
+; CHECK-NEXT:	.long	.Ltmp
+; CHECK-NEXT:	.long	1                   
+; CHECK-NEXT:	.long	.Ltmp
+; CHECK-NEXT:	.long	0                   
+; CHECK-NEXT:	.long	.Ltmp
+; CHECK-NEXT:	.long	-1                  
+
+; ModuleID = 'windows-seh-EHa-CppDtors01.cpp'
+source_filename = "windows-seh-EHa-CppDtors01.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-msvc"
+
+%struct.A = type { i8 }
+%struct.B = type { i8 }
+%struct.C = type { i8 }
+
+$"??_C@_0CM@KAOHJHDK@?5Test?5CPP?5unwind?3?5in?5catch?5handl@" = comdat any
+
+$"??_C@_0N@FCCEEGKL@?5in?5C?5dtor?5?6?$AA@" = comdat any
+
+$"??_C@_0N@EFFPFCOI@?5in?5B?5dtor?5?6?$AA@" = comdat any
+
+$"??_C@_0N@HMNCGOCN@?5in?5A?5dtor?5?6?$AA@" = comdat any
+
+@"?g@@3HA" = dso_local global i32 0, align 4
+@"??_C@_0CM@KAOHJHDK@?5Test?5CPP?5unwind?3?5in?5catch?5handl@" = linkonce_odr dso_local unnamed_addr constant [44 x i8] c" Test CPP unwind: in catch handler i = %d \0A\00", comdat, align 1
+@"??_C@_0N@FCCEEGKL@?5in?5C?5dtor?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [13 x i8] c" in C dtor \0A\00", comdat, align 1
+@"??_C@_0N@EFFPFCOI@?5in?5B?5dtor?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [13 x i8] c" in B dtor \0A\00", comdat, align 1
+@"??_C@_0N@HMNCGOCN@?5in?5A?5dtor?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [13 x i8] c" in A dtor \0A\00", comdat, align 1
+
+; Function Attrs: noinline optnone
+define dso_local void @"?crash@@YAXH@Z"(i32 %i) #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %i.addr = alloca i32, align 4
+  %ObjA = alloca %struct.A, align 1
+  %ObjB = alloca %struct.B, align 1
+  %ObjC = alloca %struct.C, align 1
+  store i32 %i, i32* %i.addr, align 4
+  invoke void @llvm.eha.scope.begin()
+          to label %invoke.cont unwind label %ehcleanup13
+
+invoke.cont:                                      ; preds = %entry
+  %0 = load i32, i32* %i.addr, align 4
+  %cmp = icmp eq i32 %0, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %invoke.cont
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %invoke.cont
+  invoke void @llvm.eha.scope.begin()
+          to label %invoke.cont1 unwind label %ehcleanup11
+
+invoke.cont1:                                     ; preds = %if.end
+  %1 = load i32, i32* %i.addr, align 4
+  %cmp2 = icmp eq i32 %1, 1
+  br i1 %cmp2, label %if.then3, label %if.end4
+
+if.then3:                                         ; preds = %invoke.cont1
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  br label %if.end4
+
+if.end4:                                          ; preds = %if.then3, %invoke.cont1
+  invoke void @llvm.eha.scope.begin()
+          to label %invoke.cont5 unwind label %ehcleanup
+
+invoke.cont5:                                     ; preds = %if.end4
+  %2 = load i32, i32* %i.addr, align 4
+  %cmp6 = icmp eq i32 %2, 2
+  br i1 %cmp6, label %if.then7, label %if.end8
+
+if.then7:                                         ; preds = %invoke.cont5
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  br label %if.end8
+
+if.end8:                                          ; preds = %if.then7, %invoke.cont5
+  invoke void @llvm.eha.scope.end()
+          to label %invoke.cont9 unwind label %ehcleanup
+
+invoke.cont9:                                     ; preds = %if.end8
+  call void @"??1C@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.C* %ObjC) #6
+  invoke void @llvm.eha.scope.end()
+          to label %invoke.cont10 unwind label %ehcleanup11
+
+invoke.cont10:                                    ; preds = %invoke.cont9
+  call void @"??1B@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.B* %ObjB) #6
+  invoke void @llvm.eha.scope.end()
+          to label %invoke.cont12 unwind label %ehcleanup13
+
+invoke.cont12:                                    ; preds = %invoke.cont10
+  call void @"??1A@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.A* %ObjA) #6
+  ret void
+
+ehcleanup:                                        ; preds = %if.end8, %if.end4
+  %3 = cleanuppad within none []
+  call void @"??1C@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.C* %ObjC) #6 [ "funclet"(token %3) ]
+  cleanupret from %3 unwind label %ehcleanup11
+
+ehcleanup11:                                      ; preds = %invoke.cont9, %ehcleanup, %if.end
+  %4 = cleanuppad within none []
+  call void @"??1B@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.B* %ObjB) #6 [ "funclet"(token %4) ]
+  cleanupret from %4 unwind label %ehcleanup13
+
+ehcleanup13:                                      ; preds = %invoke.cont10, %ehcleanup11, %entry
+  %5 = cleanuppad within none []
+  call void @"??1A@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.A* %ObjA) #6 [ "funclet"(token %5) ]
+  cleanupret from %5 unwind to caller
+}
+
+; Function Attrs: nounwind readnone
+declare dso_local void @llvm.eha.scope.begin() #1
+
+declare dso_local i32 @__CxxFrameHandler3(...)
+
+; Function Attrs: nounwind readnone
+declare dso_local void @llvm.eha.scope.end() #1
+
+; Function Attrs: noinline nounwind optnone
+define internal void @"??1C@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.C* %this) unnamed_addr #2 align 2 {
+entry:
+  %this.addr = alloca %struct.C*, align 8
+  store %struct.C* %this, %struct.C** %this.addr, align 8
+  %this1 = load %struct.C*, %struct.C** %this.addr, align 8
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @"??_C@_0N@FCCEEGKL@?5in?5C?5dtor?5?6?$AA@", i64 0, i64 0))
+  ret void
+}
+
+; Function Attrs: noinline nounwind optnone
+define internal void @"??1B@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.B* %this) unnamed_addr #2 align 2 {
+entry:
+  %this.addr = alloca %struct.B*, align 8
+  store %struct.B* %this, %struct.B** %this.addr, align 8
+  %this1 = load %struct.B*, %struct.B** %this.addr, align 8
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @"??_C@_0N@EFFPFCOI@?5in?5B?5dtor?5?6?$AA@", i64 0, i64 0))
+  ret void
+}
+
+; Function Attrs: noinline nounwind optnone
+define internal void @"??1A@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.A* %this) unnamed_addr #2 align 2 {
+entry:
+  %this.addr = alloca %struct.A*, align 8
+  store %struct.A* %this, %struct.A** %this.addr, align 8
+  %this1 = load %struct.A*, %struct.A** %this.addr, align 8
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @"??_C@_0N@HMNCGOCN@?5in?5A?5dtor?5?6?$AA@", i64 0, i64 0))
+  ret void
+}
+
+; Function Attrs: noinline norecurse optnone
+define dso_local i32 @main() #3 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
+entry:
+  %retval = alloca i32, align 4
+  %i = alloca i32, align 4
+  %__exception_code = alloca i32, align 4
+  store i32 0, i32* %retval, align 4
+  store i32 0, i32* %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = load i32, i32* %i, align 4
+  %cmp = icmp slt i32 %0, 3
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  invoke void @llvm.seh.try.begin()
+          to label %invoke.cont unwind label %catch.dispatch
+
+invoke.cont:                                      ; preds = %for.body
+  %1 = load volatile i32, i32* %i, align 4
+  invoke void @"?crash@@YAXH@Z"(i32 %1) #7
+          to label %invoke.cont1 unwind label %catch.dispatch
+
+invoke.cont1:                                     ; preds = %invoke.cont
+  invoke void @llvm.seh.try.end()
+          to label %invoke.cont2 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %invoke.cont1, %invoke.cont, %for.body
+  %2 = catchswitch within none [label %__except] unwind to caller
+
+__except:                                         ; preds = %catch.dispatch
+  %3 = catchpad within %2 [i8* null]
+  catchret from %3 to label %__except3
+
+__except3:                                        ; preds = %__except
+  %4 = call i32 @llvm.eh.exceptioncode(token %3)
+  store i32 %4, i32* %__exception_code, align 4
+  %5 = load i32, i32* %i, align 4
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([44 x i8], [44 x i8]* @"??_C@_0CM@KAOHJHDK@?5Test?5CPP?5unwind?3?5in?5catch?5handl@", i64 0, i64 0), i32 %5)
+  br label %__try.cont
+
+__try.cont:                                       ; preds = %__except3, %invoke.cont2
+  br label %for.inc
+
+for.inc:                                          ; preds = %__try.cont
+  %6 = load i32, i32* %i, align 4
+  %inc = add nsw i32 %6, 1
+  store i32 %inc, i32* %i, align 4
+  br label %for.cond
+
+invoke.cont2:                                     ; preds = %invoke.cont1
+  br label %__try.cont
+
+for.end:                                          ; preds = %for.cond
+  ret i32 0
+}
+
+; Function Attrs: nounwind willreturn
+declare dso_local void @llvm.seh.try.begin() #4
+
+declare dso_local i32 @__C_specific_handler(...)
+
+; Function Attrs: nounwind willreturn
+declare dso_local void @llvm.seh.try.end() #4
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.eh.exceptioncode(token) #1
+
+declare dso_local void @"?printf@@YAXZZ"(...) #5
+
+attributes #0 = { noinline optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { noinline norecurse optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind willreturn }
+attributes #5 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #6 = { nounwind }
+attributes #7 = { noinline }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 2}
+!1 = !{i32 2, !"eh-asynch", i32 1}
+!2 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project 7ee479a760e0a4402b4eb7fb6168768a44f66945)"}
+
Index: llvm/test/CodeGen/X86/windows-seh-EHa-CppCatchDotDotDot.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/windows-seh-EHa-CppCatchDotDotDot.ll
@@ -0,0 +1,291 @@
+; RUN: llc -verify-machineinstrs < %s | FileCheck %s
+
+; CHECK-LABEL: "$cppxdata$?crash@@YAXH@Z":
+; CHECK:	.long	("$stateUnwindMap$?crash@@YAXH@Z")
+; CHECK:        .long   ("$tryMap$?crash@@YAXH@Z")@IMGREL # TryBlockMap
+; CHECK-NEXT:   .long   6                       # IPMapEntries
+; CHECK-NEXT:	.long	("$ip2state$?crash@@YAXH@Z")
+
+; CHECK-LABEL: "$stateUnwindMap$?crash@@YAXH@Z":
+; CHECK-NEXT:        .long   -1                
+; CHECK-NEXT:        .long   0                 
+; CHECK-NEXT:        .long   0                 
+; CHECK-NEXT:        .long   "?dtor$
+; CHECK-NEXT:        .long   -1                
+; CHECK-NEXT:        .long   0                 
+
+; CHECK-LABEL: "$tryMap$?crash@@YAXH@Z":
+; CHECK-NEXT:        .long   0             
+; CHECK-NEXT:        .long   1             
+; CHECK-NEXT:        .long   2             
+; CHECK-NEXT:        .long   1             
+; CHECK-NEXT:        .long   ("$handlerMap$
+
+; CHECK:       "$handlerMap$0$?crash@@YAXH@Z"
+; CHECK-NEXT:        .long   0             
+; CHECK-NEXT:        .long   0             
+; CHECK-NEXT:        .long   0             
+; CHECK-NEXT:        .long   "?catch$ 
+
+; CHECK-LABEL: "$ip2state$?crash@@YAXH@Z":
+; CHECK-NEXT:	.long	.Lfunc_begin0@IMGREL
+; CHECK-NEXT:	.long	-1                  
+; CHECK-NEXT:	.long	.Ltmp     
+; CHECK-NEXT:	.long	0                   
+; CHECK-NEXT:	.long	.Ltmp     
+; CHECK-NEXT:	.long	1                   
+; CHECK-NEXT:	.long	.Ltmp
+; CHECK-NEXT:	.long	0                  
+; CHECK-NEXT:	.long	.Ltmp
+; CHECK-NEXT:	.long	-1                                  
+; CHECK-NEXT:	.long	"?catch$
+; CHECK-NEXT:	.long	2                  
+
+; ModuleID = 'windows-seh-EHa-CppCatchDotDotDot.cpp'
+source_filename = "windows-seh-EHa-CppCatchDotDotDot.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-msvc"
+
+%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
+%eh.CatchableType = type { i32, i32, i32, i32, i32, i32, i32 }
+%eh.CatchableTypeArray.1 = type { i32, [1 x i32] }
+%eh.ThrowInfo = type { i32, i32, i32, i32 }
+%struct.A = type { i8 }
+
+$"??_C@_0BJ@EIKFKKLB@?5in?5catch?$CI?4?4?4?$CJ?5funclet?5?6?$AA@" = comdat any
+
+$"??_R0H@8" = comdat any
+
+$"_CT??_R0H@84" = comdat any
+
+$_CTA1H = comdat any
+
+$_TI1H = comdat any
+
+$"??_C@_0CN@MKCAOFNA@?5Test?5CPP?5unwind?3?5in?5except?5hand@" = comdat any
+
+$"??_C@_0N@LJHFFAKD@?5in?5A?5ctor?5?6?$AA@" = comdat any
+
+$"??_C@_0N@HMNCGOCN@?5in?5A?5dtor?5?6?$AA@" = comdat any
+
+@"?pt1@@3PEAHEA" = dso_local global i32* null, align 8
+@"?pt2@@3PEAHEA" = dso_local global i32* null, align 8
+@"?pt3@@3PEAHEA" = dso_local global i32* null, align 8
+@"?g@@3HA" = dso_local global i32 0, align 4
+@"??_C@_0BJ@EIKFKKLB@?5in?5catch?$CI?4?4?4?$CJ?5funclet?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [25 x i8] c" in catch(...) funclet \0A\00", comdat, align 1
+@"??_7type_info@@6B@" = external constant i8*
+@"??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
+@__ImageBase = external dso_local constant i8
+@"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"??_R0H@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 4, i32 0 }, section ".xdata", comdat
+@_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableType* @"_CT??_R0H@84" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32)] }, section ".xdata", comdat
+@_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1* @_CTA1H to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section ".xdata", comdat
+@"??_C@_0CN@MKCAOFNA@?5Test?5CPP?5unwind?3?5in?5except?5hand@" = linkonce_odr dso_local unnamed_addr constant [45 x i8] c" Test CPP unwind: in except handler i = %d \0A\00", comdat, align 1
+@"??_C@_0N@LJHFFAKD@?5in?5A?5ctor?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [13 x i8] c" in A ctor \0A\00", comdat, align 1
+@"??_C@_0N@HMNCGOCN@?5in?5A?5dtor?5?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [13 x i8] c" in A dtor \0A\00", comdat, align 1
+
+; Function Attrs: noinline nounwind optnone
+define dso_local void @"?foo@@YAXXZ"() #0 {
+entry:
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  ret void
+}
+
+; Function Attrs: noinline optnone
+define dso_local void @"?crash@@YAXH@Z"(i32 %i) #1 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %i.addr = alloca i32, align 4
+  %ObjA = alloca %struct.A, align 1
+  %tmp = alloca i32, align 4
+  store i32 %i, i32* %i.addr, align 4
+  %0 = load i32, i32* %i.addr, align 4
+  store i32 %0, i32* @"?g@@3HA", align 4
+  invoke void @llvm.seh.try.begin()
+          to label %invoke.cont unwind label %catch.dispatch
+
+invoke.cont:                                      ; preds = %entry
+  %call = invoke %struct.A* @"??0A@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.A* %ObjA)
+          to label %invoke.cont1 unwind label %catch.dispatch
+
+invoke.cont1:                                     ; preds = %invoke.cont
+  invoke void @llvm.eha.scope.begin()
+          to label %invoke.cont2 unwind label %ehcleanup
+
+invoke.cont2:                                     ; preds = %invoke.cont1
+  %1 = load i32, i32* %i.addr, align 4
+  %cmp = icmp eq i32 %1, 1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %invoke.cont2
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %invoke.cont2
+  invoke void @llvm.eha.scope.end()
+          to label %invoke.cont3 unwind label %ehcleanup
+
+invoke.cont3:                                     ; preds = %if.end
+  call void @"??1A@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.A* %ObjA) #6
+  br label %try.cont
+
+ehcleanup:                                        ; preds = %if.end, %invoke.cont1
+  %2 = cleanuppad within none []
+  call void @"??1A@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.A* %ObjA) #6 [ "funclet"(token %2) ]
+  cleanupret from %2 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %ehcleanup, %invoke.cont, %entry
+  %3 = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %4 = catchpad within %3 [i8* null, i32 0, i8* null]
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @"??_C@_0BJ@EIKFKKLB@?5in?5catch?$CI?4?4?4?$CJ?5funclet?5?6?$AA@", i64 0, i64 0)) [ "funclet"(token %4) ]
+  %5 = load i32, i32* %i.addr, align 4
+  %cmp4 = icmp eq i32 %5, 1
+  br i1 %cmp4, label %if.then5, label %if.end6
+
+if.then5:                                         ; preds = %catch
+  %6 = load i32, i32* %i.addr, align 4
+  store i32 %6, i32* %tmp, align 4
+  %7 = bitcast i32* %tmp to i8*
+  call void @_CxxThrowException(i8* %7, %eh.ThrowInfo* @_TI1H) #7 [ "funclet"(token %4) ]
+  unreachable
+
+if.end6:                                          ; preds = %catch
+  catchret from %4 to label %catchret.dest
+
+catchret.dest:                                    ; preds = %if.end6
+  br label %try.cont
+
+try.cont:                                         ; preds = %catchret.dest, %invoke.cont3
+  ret void
+}
+
+; Function Attrs: nounwind willreturn
+declare dso_local void @llvm.seh.try.begin() #2
+
+declare dso_local i32 @__CxxFrameHandler3(...)
+
+; Function Attrs: noinline optnone
+define internal %struct.A* @"??0A@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.A* returned %this) unnamed_addr #1 align 2 {
+entry:
+  %retval = alloca %struct.A*, align 8
+  %this.addr = alloca %struct.A*, align 8
+  store %struct.A* %this, %struct.A** %this.addr, align 8
+  %this1 = load %struct.A*, %struct.A** %this.addr, align 8
+  store %struct.A* %this1, %struct.A** %retval, align 8
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @"??_C@_0N@LJHFFAKD@?5in?5A?5ctor?5?6?$AA@", i64 0, i64 0))
+  %0 = load i32, i32* @"?g@@3HA", align 4
+  %cmp = icmp eq i32 %0, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  store volatile i32 0, i32* inttoptr (i64 17 to i32*), align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %1 = load %struct.A*, %struct.A** %retval, align 8
+  ret %struct.A* %1
+}
+
+; Function Attrs: nounwind readnone
+declare dso_local void @llvm.eha.scope.begin() #3
+
+; Function Attrs: nounwind readnone
+declare dso_local void @llvm.eha.scope.end() #3
+
+; Function Attrs: noinline nounwind optnone
+define internal void @"??1A@?1??crash@@YAXH@Z@QEAA@XZ"(%struct.A* %this) unnamed_addr #0 align 2 {
+entry:
+  %this.addr = alloca %struct.A*, align 8
+  store %struct.A* %this, %struct.A** %this.addr, align 8
+  %this1 = load %struct.A*, %struct.A** %this.addr, align 8
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @"??_C@_0N@HMNCGOCN@?5in?5A?5dtor?5?6?$AA@", i64 0, i64 0))
+  ret void
+}
+
+declare dso_local void @"?printf@@YAXZZ"(...) #4
+
+declare dso_local void @_CxxThrowException(i8*, %eh.ThrowInfo*)
+
+; Function Attrs: noinline norecurse optnone
+define dso_local i32 @main() #5 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
+entry:
+  %retval = alloca i32, align 4
+  %i = alloca i32, align 4
+  %__exception_code = alloca i32, align 4
+  store i32 0, i32* %retval, align 4
+  store i32 0, i32* %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = load i32, i32* %i, align 4
+  %cmp = icmp slt i32 %0, 2
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  invoke void @llvm.seh.try.begin()
+          to label %invoke.cont unwind label %catch.dispatch
+
+invoke.cont:                                      ; preds = %for.body
+  %1 = load volatile i32, i32* %i, align 4
+  invoke void @"?crash@@YAXH@Z"(i32 %1) #8
+          to label %invoke.cont1 unwind label %catch.dispatch
+
+invoke.cont1:                                     ; preds = %invoke.cont
+  invoke void @llvm.seh.try.end()
+          to label %invoke.cont2 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %invoke.cont1, %invoke.cont, %for.body
+  %2 = catchswitch within none [label %__except] unwind to caller
+
+__except:                                         ; preds = %catch.dispatch
+  %3 = catchpad within %2 [i8* null]
+  catchret from %3 to label %__except3
+
+__except3:                                        ; preds = %__except
+  %4 = call i32 @llvm.eh.exceptioncode(token %3)
+  store i32 %4, i32* %__exception_code, align 4
+  %5 = load i32, i32* %i, align 4
+  call void (...) @"?printf@@YAXZZ"(i8* getelementptr inbounds ([45 x i8], [45 x i8]* @"??_C@_0CN@MKCAOFNA@?5Test?5CPP?5unwind?3?5in?5except?5hand@", i64 0, i64 0), i32 %5)
+  br label %__try.cont
+
+__try.cont:                                       ; preds = %__except3, %invoke.cont2
+  br label %for.inc
+
+for.inc:                                          ; preds = %__try.cont
+  %6 = load i32, i32* %i, align 4
+  %inc = add nsw i32 %6, 1
+  store i32 %inc, i32* %i, align 4
+  br label %for.cond
+
+invoke.cont2:                                     ; preds = %invoke.cont1
+  br label %__try.cont
+
+for.end:                                          ; preds = %for.cond
+  ret i32 0
+}
+
+declare dso_local i32 @__C_specific_handler(...)
+
+; Function Attrs: nounwind willreturn
+declare dso_local void @llvm.seh.try.end() #2
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.eh.exceptioncode(token) #3
+
+attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { noinline optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind willreturn }
+attributes #3 = { nounwind readnone }
+attributes #4 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #5 = { noinline norecurse optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #6 = { nounwind }
+attributes #7 = { noreturn }
+attributes #8 = { noinline }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 2}
+!1 = !{i32 2, !"eh-asynch", i32 1}
+!2 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project 7ee479a760e0a4402b4eb7fb6168768a44f66945)"}
+
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -4223,6 +4223,10 @@
       Assert(
           !F->isIntrinsic() || isa<CallInst>(I) ||
               F->getIntrinsicID() == Intrinsic::donothing ||
+              F->getIntrinsicID() == Intrinsic::seh_try_begin ||
+              F->getIntrinsicID() == Intrinsic::seh_try_end ||
+              F->getIntrinsicID() == Intrinsic::eha_scope_begin ||
+              F->getIntrinsicID() == Intrinsic::eha_scope_end ||
               F->getIntrinsicID() == Intrinsic::coro_resume ||
               F->getIntrinsicID() == Intrinsic::coro_destroy ||
               F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||
Index: llvm/lib/IR/BasicBlock.cpp
===================================================================
--- llvm/lib/IR/BasicBlock.cpp
+++ llvm/lib/IR/BasicBlock.cpp
@@ -211,6 +211,15 @@
   return BB->getTerminatingDeoptimizeCall();
 }
 
+const Instruction *BasicBlock::getFirstFaultyInst() const {
+  if (InstList.empty())
+    return nullptr;
+  for (const Instruction &I : *this)
+    if (isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I))
+      return &I;
+  return nullptr;
+}
+
 const Instruction* BasicBlock::getFirstNonPHI() const {
   for (const Instruction &I : *this)
     if (!isa<PHINode>(I))
Index: llvm/lib/CodeGen/WinEHPrepare.cpp
===================================================================
--- llvm/lib/CodeGen/WinEHPrepare.cpp
+++ llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -215,6 +215,94 @@
   }
 }
 
+// See comments below for calculateSEHStateForBlocks().
+// State - incoming State of normal paths
+void llvm::calculateCXXStateForBlocks(const BasicBlock *BB, int State,
+                                      WinEHFuncInfo &EHInfo) {
+  if (EHInfo.BlockToStateMap.count(BB) && EHInfo.BlockToStateMap[BB] <= State)
+    return; // skip already visited or EHPad
+
+  const llvm::Instruction *I = BB->getFirstNonPHI();
+  const llvm::Instruction *TI = BB->getTerminator();
+  if (I->isEHPad())
+    State = EHInfo.EHPadStateMap[I];
+  EHInfo.BlockToStateMap[BB] = State; // Record state, also flag visiting
+
+  if ((isa<CleanupReturnInst>(TI) || isa<CatchReturnInst>(TI)) && State > 0) {
+    // Retrive the new State
+    State = EHInfo.CxxUnwindMap[State].ToState; // Retrive next State
+  } else if (isa<InvokeInst>(TI)) {
+    auto *Call = dyn_cast<CallBase>(TI);
+    const Function *Fn = Call->getCalledFunction();
+    if (Fn && Fn->isIntrinsic() &&
+        (Fn->getIntrinsicID() == Intrinsic::eha_scope_begin ||
+         Fn->getIntrinsicID() == Intrinsic::seh_try_begin))
+      // Retrive the new State from eha_scope_begin
+      State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)];
+    else if (Fn && Fn->isIntrinsic() &&
+             (Fn->getIntrinsicID() == Intrinsic::eha_scope_end ||
+              Fn->getIntrinsicID() == Intrinsic::seh_try_end))
+      // end of current state, retrive new state from UnwindMap
+      State = EHInfo.CxxUnwindMap[State].ToState;
+  }
+  // Continue traveling successors recursively
+  for (auto *SuccBB : successors(BB)) {
+    calculateCXXStateForBlocks(SuccBB, State, EHInfo);
+  }
+}
+
+// The central theory of this routine is based on the following:
+//   A _try scope is always a SEME (Single Entry Multiple Exits) region
+//     as jumping into a _try is not allowed
+//   The single entry must start with a seh_try_begin() invoke with a
+//     correct State number that is the initial state of the SEME.
+//   Through control-flow, state number is propagated into all blocks.
+//   Side exits marked by seh_try_end() will unwind to parent state via
+//     existing SEHUnwindMap[].
+//   Side exits can ONLY jump into parent scopes (lower state number).
+//   Thus, when a block succeeds various states from its predecessors,
+//     the lowest State triumphs others.
+//   If some exits flow to unreachable, propagation on those paths terminate,
+//     not affecting remaining blocks.
+void llvm::calculateSEHStateForBlocks(const BasicBlock *BB, int State,
+                                      WinEHFuncInfo &EHInfo) {
+  if (EHInfo.BlockToStateMap.count(BB) && EHInfo.BlockToStateMap[BB] <= State)
+    return; // skip already visited by lower State
+
+  const llvm::Instruction *I = BB->getFirstNonPHI();
+  const llvm::Instruction *TI = BB->getTerminator();
+  if (I->isEHPad())
+    State = EHInfo.EHPadStateMap[I];
+  EHInfo.BlockToStateMap[BB] = State; // Record state
+
+  if (isa<CatchPadInst>(I) && isa<CatchReturnInst>(TI)) {
+    const Constant *FilterOrNull = cast<Constant>(
+        cast<CatchPadInst>(I)->getArgOperand(0)->stripPointerCasts());
+    const Function *Filter = dyn_cast<Function>(FilterOrNull);
+    if (!Filter || !Filter->getName().startswith("__IsLocalUnwind"))
+      State = EHInfo.SEHUnwindMap[State].ToState; // Retrive next State
+  } else if ((isa<CleanupReturnInst>(TI) || isa<CatchReturnInst>(TI)) &&
+             State > 0) {
+    // Retrive the new State.
+    State = EHInfo.SEHUnwindMap[State].ToState; // Retrive next State
+  } else if (isa<InvokeInst>(TI)) {
+    auto *Call = dyn_cast<CallBase>(TI);
+    const Function *Fn = Call->getCalledFunction();
+    if (Fn && Fn->isIntrinsic() &&
+        Fn->getIntrinsicID() == Intrinsic::seh_try_begin)
+      // Retrive the new State from seh_try_begin
+      State = EHInfo.InvokeStateMap[cast<InvokeInst>(TI)];
+    else if (Fn && Fn->isIntrinsic() &&
+             Fn->getIntrinsicID() == Intrinsic::seh_try_end)
+      // end of current state, retrive new state from UnwindMap
+      State = EHInfo.SEHUnwindMap[State].ToState;
+  }
+  // Continue traveling successors recursively
+  for (auto *SuccBB : successors(BB)) {
+    calculateSEHStateForBlocks(SuccBB, State, EHInfo);
+  }
+}
+
 // Given BB which ends in an unwind edge, return the EHPad that this BB belongs
 // to. If the unwind edge came from an invoke, return null.
 static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB,
@@ -275,6 +363,7 @@
 
     for (const auto *CatchPad : Handlers) {
       FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow;
+      FuncInfo.EHPadStateMap[CatchPad] = CatchLow;
       for (const User *U : CatchPad->users()) {
         const auto *UserI = cast<Instruction>(U);
         if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) {
@@ -383,6 +472,7 @@
 
     // Everything in the __try block uses TryState as its parent state.
     FuncInfo.EHPadStateMap[CatchSwitch] = TryState;
+    FuncInfo.EHPadStateMap[CatchPad] = TryState;
     LLVM_DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
                       << CatchPadBB->getName() << '\n');
     for (const BasicBlock *PredBlock : predecessors(BB))
@@ -463,6 +553,12 @@
   }
 
   calculateStateNumbersForInvokes(Fn, FuncInfo);
+
+  bool IsEHa = Fn->getParent()->getModuleFlag("eh-asynch");
+  if (IsEHa) {
+    const BasicBlock *EntryBB = &(Fn->getEntryBlock());
+    calculateSEHStateForBlocks(EntryBB, -1, FuncInfo);
+  }
 }
 
 void llvm::calculateWinCXXEHStateNumbers(const Function *Fn,
@@ -481,6 +577,12 @@
   }
 
   calculateStateNumbersForInvokes(Fn, FuncInfo);
+
+  bool IsEHa = Fn->getParent()->getModuleFlag("eh-asynch");
+  if (IsEHa) {
+    const BasicBlock *EntryBB = &(Fn->getEntryBlock());
+    calculateCXXStateForBlocks(EntryBB, -1, FuncInfo);
+  }
 }
 
 static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState,
@@ -1267,4 +1369,8 @@
   LabelToStateMap[InvokeBegin] = std::make_pair(InvokeStateMap[II], InvokeEnd);
 }
 
+void WinEHFuncInfo::addIPToStateRange(int State, MCSymbol *InvokeBegin,
+                                      MCSymbol *InvokeEnd) {
+  LabelToStateMap[InvokeBegin] = std::make_pair(State, InvokeEnd);
+}
 WinEHFuncInfo::WinEHFuncInfo() {}
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -58,6 +58,7 @@
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/CodeGen/WinEHFuncInfo.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
@@ -1295,6 +1296,40 @@
   return true;
 }
 
+// Mark and Report IPToState for each Block under IsEHa
+void SelectionDAGISel::reportIPToStateForBlocks(MachineFunction *MF) {
+  MachineModuleInfo &MMI = MF->getMMI();
+  llvm::WinEHFuncInfo *EHInfo = MF->getWinEHFuncInfo();
+  if (!EHInfo)
+    return;
+  for (auto MBBI = MF->begin(); MBBI != MF->end(); ++MBBI) {
+    MachineBasicBlock *MBB = &*MBBI;
+    const BasicBlock *BB = MBB->getBasicBlock();
+    int State = EHInfo->BlockToStateMap[BB];
+    if (BB->getFirstFaultyInst()) {
+      // Report IP range only for blocks with Faulty inst
+      MCSymbol *BeginLabel = MMI.getContext().createTempSymbol();
+      MCSymbol *EndLabel = MMI.getContext().createTempSymbol();
+      EHInfo->addIPToStateRange(State, BeginLabel, EndLabel);
+
+      // Insert EH Labels
+      auto MBBb = MBB->getFirstNonPHI();
+      BuildMI(*MBB, MBBb, SDB->getCurDebugLoc(),
+              TII->get(TargetOpcode::EH_LABEL))
+          .addSym(BeginLabel);
+      auto MBBe = MBB->instr_end();
+      MachineInstr *MIb = &*(--MBBe);
+      // insert before (possible multiple) terminators
+      while (MIb->isTerminator())
+        MIb = &*(--MBBe);
+      ++MBBe;
+      BuildMI(*MBB, MBBe, SDB->getCurDebugLoc(),
+              TII->get(TargetOpcode::EH_LABEL))
+          .addSym(EndLabel);
+    }
+  }
+}
+
 /// isFoldedOrDeadInstruction - Return true if the specified instruction is
 /// side-effect free and is either dead or folded into a generated instruction.
 /// Return false if it needs to be emitted.
@@ -1624,6 +1659,10 @@
     ElidedArgCopyInstrs.clear();
   }
 
+  // IsEHa: Report Block State under -EHa
+  if (Fn.getParent()->getModuleFlag("eh-asynch"))
+    reportIPToStateForBlocks(MF);
+
   SP.copyToMachineFrameInfo(MF->getFrameInfo());
 
   SwiftError->propagateVRegs();
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2771,6 +2771,7 @@
   // catchswitch for successors.
   MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
   const BasicBlock *EHPadBB = I.getSuccessor(1);
+  MachineBasicBlock *CleanupMBB = FuncInfo.MBBMap[EHPadBB];
 
   // Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't
   // have to do anything here to lower funclet bundles.
@@ -2789,6 +2790,12 @@
       llvm_unreachable("Cannot invoke this intrinsic");
     case Intrinsic::donothing:
       // Ignore invokes to @llvm.donothing: jump directly to the next BB.
+    case Intrinsic::seh_try_begin:
+    case Intrinsic::eha_scope_begin:
+    case Intrinsic::seh_try_end:
+    case Intrinsic::eha_scope_end:
+      if (CleanupMBB) // a CleanupPad, referenced by EH table
+        CleanupMBB->setHasAddressTaken(); // so dtor-funclet not removed by opts
       break;
     case Intrinsic::experimental_patchpoint_void:
     case Intrinsic::experimental_patchpoint_i64:
@@ -6583,6 +6590,10 @@
       lowerCallToExternalSymbol(I, FunctionName);
     return;
   case Intrinsic::donothing:
+  case Intrinsic::seh_try_begin:
+  case Intrinsic::eha_scope_begin:
+  case Intrinsic::seh_try_end:
+  case Intrinsic::eha_scope_end:
     // ignore
     return;
   case Intrinsic::experimental_stackmap:
Index: llvm/lib/CodeGen/BranchFolding.cpp
===================================================================
--- llvm/lib/CodeGen/BranchFolding.cpp
+++ llvm/lib/CodeGen/BranchFolding.cpp
@@ -1206,7 +1206,7 @@
     MadeChange |= OptimizeBlock(MBB);
 
     // If it is dead, remove it.
-    if (MBB->pred_empty()) {
+    if (MBB->pred_empty() && !MBB->hasAddressTaken()) {
       RemoveDeadBlock(MBB);
       MadeChange = true;
       ++NumDeadBlocks;
Index: llvm/lib/CodeGen/AsmPrinter/WinException.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -746,7 +746,11 @@
   OS.emitInt32(0);
 
   AddComment("EHFlags");
-  OS.emitInt32(1);
+  if (MMI->getModule()->getModuleFlag("eh-asynch")) {
+    OS.emitInt32(0); // -EHa
+  } else {
+    OS.emitInt32(1);
+  }
 
   // UnwindMapEntry {
   //   int32_t ToState;
Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1104,7 +1104,7 @@
   // Print out code for the function.
   bool HasAnyRealCode = false;
   int NumInstsInFunction = 0;
-
+  bool IsEHa = MMI->getModule()->getModuleFlag("eh-asynch");
   for (auto &MBB : *MF) {
     // Print a label for the basic block.
     emitBasicBlockStart(MBB);
@@ -1140,10 +1140,24 @@
         emitFrameAlloc(MI);
         break;
       case TargetOpcode::ANNOTATION_LABEL:
-      case TargetOpcode::EH_LABEL:
       case TargetOpcode::GC_LABEL:
         OutStreamer->emitLabel(MI.getOperand(0).getMCSymbol());
         break;
+      case TargetOpcode::EH_LABEL:
+        OutStreamer->emitLabel(MI.getOperand(0).getMCSymbol());
+        // For IsEHa, insert a Nop if followed by a trap inst
+        //   Or the exception won't be caught.
+        //   (see MCConstantExpr::create(1,..) in WinException.cpp)
+        //  Ignore SDiv/UDiv bcause a DIV with Const-0 divisor
+        //    must have being turned into an UndefValue.
+        //  Div with variable opnds must be led by at least a Load
+        {
+          auto MI2 = std::next(MI.getIterator());
+          if (IsEHa && MI2 != MBB.end() &&
+              (MI2->mayLoadOrStore() || MI2->mayRaiseFPException()))
+            emitNops(1);
+        }
+        break;
       case TargetOpcode::INLINEASM:
       case TargetOpcode::INLINEASM_BR:
         emitInlineAsm(&MI);
Index: llvm/lib/Analysis/EHPersonalities.cpp
===================================================================
--- llvm/lib/Analysis/EHPersonalities.cpp
+++ llvm/lib/Analysis/EHPersonalities.cpp
@@ -12,6 +12,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
@@ -71,7 +72,11 @@
   // We can't simplify any invokes to nounwind functions if the personality
   // function wants to catch asynch exceptions.  The nounwind attribute only
   // implies that the function does not throw synchronous exceptions.
-  return !isAsynchronousEHPersonality(Personality);
+
+  // Cannot simplify CXX Personality under EHa
+  const llvm::Module *M = (const llvm::Module *)F->getParent();
+  bool EHa = M->getModuleFlag("eh-asynch");
+  return !isAsynchronousEHPersonality(Personality) && !EHa;
 }
 
 DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {
Index: llvm/include/llvm/IR/Intrinsics.td
===================================================================
--- llvm/include/llvm/IR/Intrinsics.td
+++ llvm/include/llvm/IR/Intrinsics.td
@@ -456,6 +456,16 @@
                                  [llvm_ptr_ty, llvm_ptr_ty],
                                  [IntrNoMem]>;
 
+// To mark the beginning/end of a try-scope for Windows SEH -EHa
+//  calls/invokes to these intrinsics are placed to model control flows
+//    caused by HW exceptions under option -EHa.
+//  calls/invokes to these intrinsics will be discarded during a codegen pass
+//   after EH tables are generated
+def int_seh_try_begin : Intrinsic<[], [], [IntrReadMem, IntrWriteMem, IntrWillReturn]>;
+def int_seh_try_end : Intrinsic<[], [], [IntrReadMem, IntrWriteMem, IntrWillReturn]>;
+def int_eha_scope_begin : Intrinsic<[], [], [IntrNoMem]>;
+def int_eha_scope_end : Intrinsic<[], [], [IntrNoMem]>;
+
 // Note: we treat stacksave/stackrestore as writemem because we don't otherwise
 // model their dependencies on allocas.
 def int_stacksave     : Intrinsic<[llvm_ptr_ty]>,
Index: llvm/include/llvm/IR/BasicBlock.h
===================================================================
--- llvm/include/llvm/IR/BasicBlock.h
+++ llvm/include/llvm/IR/BasicBlock.h
@@ -189,6 +189,13 @@
                                           ->getFirstInsertionPt().getNonConst();
   }
 
+  /// Returns the first potential -EHa faulty instruction
+  const Instruction *getFirstFaultyInst() const;
+  Instruction *getFirstFaultyInst() {
+    return const_cast<Instruction *>(
+        static_cast<const BasicBlock *>(this)->getFirstFaultyInst());
+  }
+
   /// Return a const iterator range over the instructions in the block, skipping
   /// any debug instructions.
   iterator_range<filter_iterator<BasicBlock::const_iterator,
Index: llvm/include/llvm/CodeGen/WinEHFuncInfo.h
===================================================================
--- llvm/include/llvm/CodeGen/WinEHFuncInfo.h
+++ llvm/include/llvm/CodeGen/WinEHFuncInfo.h
@@ -92,6 +92,7 @@
   DenseMap<const FuncletPadInst *, int> FuncletBaseStateMap;
   DenseMap<const InvokeInst *, int> InvokeStateMap;
   DenseMap<MCSymbol *, std::pair<int, MCSymbol *>> LabelToStateMap;
+  DenseMap<const BasicBlock *, int> BlockToStateMap; // for IsEHa
   SmallVector<CxxUnwindMapEntry, 4> CxxUnwindMap;
   SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap;
   SmallVector<SEHUnwindMapEntry, 4> SEHUnwindMap;
@@ -104,6 +105,8 @@
   void addIPToStateRange(const InvokeInst *II, MCSymbol *InvokeBegin,
                          MCSymbol *InvokeEnd);
 
+  void addIPToStateRange(int State, MCSymbol *InvokeBegin, MCSymbol *InvokeEnd);
+
   int EHRegNodeFrameIndex = std::numeric_limits<int>::max();
   int EHRegNodeEndOffset = std::numeric_limits<int>::max();
   int EHGuardFrameIndex = std::numeric_limits<int>::max();
@@ -122,6 +125,11 @@
                               WinEHFuncInfo &FuncInfo);
 
 void calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo);
+// For IsEHa
+void calculateCXXStateForBlocks(const BasicBlock *BB, int State,
+                                WinEHFuncInfo &FuncInfo);
+void calculateSEHStateForBlocks(const BasicBlock *BB, int State,
+                                WinEHFuncInfo &FuncInfo);
 
 } // end namespace llvm
 
Index: llvm/include/llvm/CodeGen/SelectionDAGISel.h
===================================================================
--- llvm/include/llvm/CodeGen/SelectionDAGISel.h
+++ llvm/include/llvm/CodeGen/SelectionDAGISel.h
@@ -330,6 +330,9 @@
   /// instruction selected, false if no code should be emitted for it.
   bool PrepareEHLandingPad();
 
+  // Mark and Report IPToState for each Block under IsEHa
+  void reportIPToStateForBlocks(MachineFunction *Fn);
+
   /// Perform instruction selection on all basic blocks in the function.
   void SelectAllBasicBlocks(const Function &Fn);
 
Index: clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple x86_64-windows -feh-asynch -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: %[[src:[0-9-]+]] = load volatile i32, i32* %i
+// CHECK-NEXT: i32 %[[src]]
+// CHECK: invoke void @llvm.seh.try.end()
+// CHECK: invoke void @llvm.seh.try.end()
+
+// CHECK: define internal void @"?fin$0@0@main@@"(i8 %abnormal_termination
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: invoke void @llvm.seh.try.end()
+
+// *****************************************************************************
+// Abstract:     Test __Try in __finally under SEH -EHa option
+void printf(...);
+int main() {
+  for (int i = 0; i < 3; i++) {
+    printf(" --- Test _Try in _finally --- i = %d \n", i);
+    __try {
+      __try {
+        printf("  In outer _try i = %d \n", i);
+        if (i == 0)
+          *(volatile int*)0x11 = 0;
+      }
+      __finally {
+        __try {
+          printf("  In outer _finally i = %d \n", i);
+          if (i == 1)
+            *(volatile int*)0x11 = 0;
+        }
+        __finally {
+          printf("  In Inner _finally i = %d \n", i);
+          if (i == 2)
+            *(volatile int*)0x11 = 0;
+        }
+      }
+    }
+    __except(1) {
+        printf(" --- In outer except handler i = %d \n", i);
+    }
+  }
+  return 0;
+}
+
Index: clang/test/CodeGen/windows-seh-EHa-CppDtors01.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/windows-seh-EHa-CppDtors01.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple x86_64-windows -feh-asynch -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: invoke void @llvm.eha.scope.begin()
+// CHECK: invoke void @llvm.eha.scope.begin()
+// CHECK: invoke void @llvm.eha.scope.begin()
+// CHECK: invoke void @llvm.eha.scope.end()
+// CHECK: invoke void @llvm.eha.scope.end()
+// CHECK: invoke void @llvm.eha.scope.end()
+
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: %[[src:[0-9-]+]] = load volatile i32, i32* %i
+// CHECK-NEXT: invoke void @"?crash@@YAXH@Z"(i32 %[[src]])
+// CHECK: invoke void @llvm.seh.try.end()
+
+// ****************************************************************************
+// Abstract:     Test CPP unwind Dtoring under SEH -EHa option
+
+void printf(...);
+
+void crash(int i) {
+  struct A {
+    ~A() {
+      printf(" in A dtor \n");
+    }
+  } ObjA;
+  if (i == 0)
+    *(volatile int*)0x11 = 0;
+
+  struct B {
+    ~B() {
+      printf(" in B dtor \n");
+    }
+  } ObjB;
+  if (i == 1)
+    *(volatile int*)0x11 = 0;
+
+  struct C {
+    ~C() {
+      printf(" in C dtor \n");
+    }
+  } ObjC;
+  if (i == 2)
+    *(volatile int*)0x11 = 0;
+
+}
+
+#define TRY __try
+#define CATCH_ALL __except (1)
+
+int g;
+int main() {
+  for (int i = 0; i < 3; i++) {
+    TRY {
+      crash(i);
+    }
+    CATCH_ALL{
+        printf(" Test CPP unwind: in catch handler i = %d \n", i);
+    }
+  }
+  return 0;
+}
+
Index: clang/test/CodeGen/windows-seh-EHa-CppCatchDotDotDot.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/windows-seh-EHa-CppCatchDotDotDot.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -triple x86_64-windows -feh-asynch -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: define dso_local void @"?crash@@YAXH@Z
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: invoke void @llvm.eha.scope.begin()
+// CHECK: invoke void @llvm.eha.scope.end()
+
+// CHECK: %[[dst:[0-9-]+]] = catchswitch within none [label %catch] unwind to caller
+// CHECK: %[[dst1:[0-9-]+]] = catchpad within %[[dst]] [i8* null, i32 0, i8* null]
+// CHECK: "funclet"(token %[[dst1]])
+
+// CHECK: invoke void @llvm.seh.try.begin()
+// CHECK: %[[src:[0-9-]+]] = load volatile i32, i32* %i
+// CHECK-NEXT: invoke void @"?crash@@YAXH@Z"(i32 %[[src]])
+// CHECK: invoke void @llvm.seh.try.end()
+
+// *****************************************************************************
+// Abstract:     Test CPP catch(...) under SEH -EHa option
+
+void printf(...);
+
+void foo() {
+  *(volatile int*)0x11 = 0;
+}
+int *pt1, *pt2, *pt3;
+int g;
+void crash(int i) {
+  g = i;
+  try 
+  {
+    struct A {
+      A() {
+        printf(" in A ctor \n");
+        if (g == 0)
+          *(volatile int*)0x11 = 0;
+      }
+      ~A() {
+        printf(" in A dtor \n");
+      }
+    } ObjA;
+    if (i == 1)
+      *(volatile int*)0x11 = 0;
+  }
+  catch (...) 
+  {
+    printf(" in catch(...) funclet \n");
+    if (i == 1)
+      throw(i);
+  }
+}
+
+int main() {
+  for (int i = 0; i < 2; i++) {
+    __try {
+      crash(i);
+    }
+    __except(1) {
+        printf(" Test CPP unwind: in except handler i = %d \n", i);
+    }
+  }
+  return 0;
+}
+
Index: clang/lib/Sema/JumpDiagnostics.cpp
===================================================================
--- clang/lib/Sema/JumpDiagnostics.cpp
+++ clang/lib/Sema/JumpDiagnostics.cpp
@@ -930,6 +930,9 @@
   if (!ToScopesWarning.empty()) {
     S.Diag(DiagLoc, JumpDiagWarning);
     NoteJumpIntoScopes(ToScopesWarning);
+    assert(isa<LabelStmt>(To));
+    LabelStmt *Label = cast<LabelStmt>(To);
+    Label->setSideEntry();
   }
 
   // Handle errors.
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -2783,6 +2783,7 @@
   Opts.IgnoreExceptions = Args.hasArg(OPT_fignore_exceptions);
   Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions);
   Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions);
+  Opts.EHAsynch = Args.hasArg(OPT_feh_asynch);
 
   // -ffixed-point
   Opts.FixedPoint =
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -426,6 +426,7 @@
     Args.ClaimAllArgs(options::OPT_fobjc_exceptions);
     Args.ClaimAllArgs(options::OPT_fno_objc_exceptions);
     Args.ClaimAllArgs(options::OPT_fcxx_exceptions);
+    Args.ClaimAllArgs(options::OPT_feh_asynch);
     Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions);
     return;
   }
@@ -434,6 +435,13 @@
   bool EH = Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
                          false);
 
+  bool EHa =
+      Args.hasFlag(options::OPT_feh_asynch, options::OPT_fno_eh_asynch, false);
+  if (EHa) {
+    CmdArgs.push_back("-feh-asynch");
+    EH = true;
+  }
+
   // Obj-C exceptions are enabled by default, regardless of -fexceptions. This
   // is not necessarily sensible, but follows GCC.
   if (types::isObjC(InputType) &&
@@ -6572,7 +6580,10 @@
     if (types::isCXX(InputType))
       CmdArgs.push_back("-fcxx-exceptions");
     CmdArgs.push_back("-fexceptions");
+    if (EH.Asynch)
+      CmdArgs.push_back("-feh-asynch");
   }
+
   if (types::isCXX(InputType) && EH.Synch && EH.NoUnwindC)
     CmdArgs.push_back("-fexternc-nounwind");
 
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -597,6 +597,10 @@
                                   llvm::DenormalMode::IEEE);
   }
 
+  if (LangOpts.EHAsynch) {
+    getModule().addModuleFlag(llvm::Module::Warning, "eh-asynch", 1);
+  }
+
   // Emit OpenCL specific module metadata: OpenCL/SPIR version.
   if (LangOpts.OpenCL) {
     EmitOpenCLMetadata();
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2687,6 +2687,11 @@
   void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
                         Address Ptr);
 
+  void EmitSehCppScopeBegin();
+  void EmitSehCppScopeEnd();
+  void EmitSehTryScopeBegin();
+  void EmitSehTryScopeEnd();
+
   llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr);
   void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
 
@@ -3037,6 +3042,8 @@
   void EmitSEHLeaveStmt(const SEHLeaveStmt &S);
   void EnterSEHTryStmt(const SEHTryStmt &S);
   void ExitSEHTryStmt(const SEHTryStmt &S);
+  void VolatilizeTryBlocks(llvm::BasicBlock *BB,
+                           llvm::SmallPtrSet<llvm::BasicBlock *, 10> &V);
 
   void pushSEHCleanup(CleanupKind kind,
                       llvm::Function *FinallyFunc);
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -604,6 +604,11 @@
 
 void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
   EmitLabel(S.getDecl());
+
+  // IsEHa - emit eha.scope.begin if it's a side entry of a scope
+  if (getLangOpts().EHAsynch && S.IsSideEntry())
+    EmitSehCppScopeBegin();
+
   EmitStmt(S.getSubStmt());
 }
 
Index: clang/lib/CodeGen/CGException.cpp
===================================================================
--- clang/lib/CodeGen/CGException.cpp
+++ clang/lib/CodeGen/CGException.cpp
@@ -38,6 +38,18 @@
   return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
 }
 
+static llvm::FunctionCallee getSehTryBeginFn(CodeGenModule &CGM) {
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+  return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin");
+}
+
+static llvm::FunctionCallee getSehTryEndFn(CodeGenModule &CGM) {
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+  return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
+}
+
 static llvm::FunctionCallee getUnexpectedFn(CodeGenModule &CGM) {
   // void __cxa_call_unexpected(void *thrown_exception);
 
@@ -450,7 +462,7 @@
   if (!FD) {
     // Check if CapturedDecl is nothrow and create terminate scope for it.
     if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) {
-      if (CD->isNothrow())
+      if (CD->isNothrow() && !getLangOpts().EHAsynch /* !IsEHa */)
         EHStack.pushTerminate();
     }
     return;
@@ -462,7 +474,8 @@
   ExceptionSpecificationType EST = Proto->getExceptionSpecType();
   if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) {
     // noexcept functions are simple terminate scopes.
-    EHStack.pushTerminate();
+    if (!getLangOpts().EHAsynch) // -EHa: HW exception still can occur
+      EHStack.pushTerminate();
   } else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
     // TODO: Revisit exception specifications for the MS ABI.  There is a way to
     // encode these in an object file but MSVC doesn't do anything with it.
@@ -527,7 +540,7 @@
   if (!FD) {
     // Check if CapturedDecl is nothrow and pop terminate scope for it.
     if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) {
-      if (CD->isNothrow())
+      if (CD->isNothrow() && !EHStack.empty())
         EHStack.popTerminate();
     }
     return;
@@ -537,7 +550,8 @@
     return;
 
   ExceptionSpecificationType EST = Proto->getExceptionSpecType();
-  if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) {
+  if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot &&
+      !EHStack.empty() /* possible empty when -EHa */) {
     EHStack.popTerminate();
   } else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
     // TODO: Revisit exception specifications for the MS ABI.  There is a way to
@@ -584,7 +598,16 @@
       CatchScope->setHandler(I, TypeInfo, Handler);
     } else {
       // No exception decl indicates '...', a catch-all.
-      CatchScope->setHandler(I, CGM.getCXXABI().getCatchAllTypeInfo(), Handler);
+      CatchTypeInfo TypeInfo = CGM.getCXXABI().getCatchAllTypeInfo();
+
+      //  For IsEHa catch(...) must handle HW exception
+      //  Adjective = HT_IsStdDotDot (0x40), only catch C++ exceptions
+      //  Also mark scope with SehTryBegin
+      if (getLangOpts().EHAsynch) {
+        TypeInfo.Flags = 0;
+        EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM));
+      }
+      CatchScope->setHandler(I, TypeInfo, Handler);
     }
   }
 }
@@ -706,7 +729,7 @@
   // If exceptions are disabled/ignored and SEH is not in use, then there is no
   // invoke destination. SEH "works" even if exceptions are off. In practice,
   // this means that C++ destructors and other EH cleanups don't run, which is
-  // consistent with MSVC's behavior.
+  // consistent with MSVC's behavior, except in the presence of -EHa
   const LangOptions &LO = CGM.getLangOpts();
   if (!LO.Exceptions || LO.IgnoreExceptions) {
     if (!LO.Borland && !LO.MicrosoftExt)
@@ -1602,7 +1625,23 @@
     JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
 
     SEHTryEpilogueStack.push_back(&TryExit);
+
+    llvm::BasicBlock *TryBB = nullptr;
+    // IsEHa: emit an invoke to _seh_try_begin() runtime for -EHa
+    if (getLangOpts().EHAsynch) {
+      EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM));
+      if (SEHTryEpilogueStack.size() == 1) // outermost only
+        TryBB = Builder.GetInsertBlock();
+    }
+
     EmitStmt(S.getTryBlock());
+
+    // Volatilize all blocks in Try, till current insert point
+    if (TryBB) {
+      llvm::SmallPtrSet<llvm::BasicBlock *, 10> Visited;
+      VolatilizeTryBlocks(TryBB, Visited);
+    }
+
     SEHTryEpilogueStack.pop_back();
 
     if (!TryExit.getBlock()->use_empty())
@@ -1613,6 +1652,38 @@
   ExitSEHTryStmt(S);
 }
 
+//  Recursively walk through blocks in a _try
+//      and make all memory instructions volatile
+void CodeGenFunction::VolatilizeTryBlocks(
+    llvm::BasicBlock *BB, llvm::SmallPtrSet<llvm::BasicBlock *, 10> &V) {
+  if (BB == SEHTryEpilogueStack.back()->getBlock() /* end of Try */ ||
+      !V.insert(BB).second /* already visited */ ||
+      !BB->getParent() /* not emitted */ || BB->empty())
+    return;
+
+  if (!BB->isEHPad()) {
+    for (llvm::BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE;
+         ++J) {
+      if (isa<llvm::LoadInst>(J)) {
+        auto LI = cast<llvm::LoadInst>(J);
+        LI->setVolatile(true);
+      } else if (isa<llvm::StoreInst>(J)) {
+        auto SI = cast<llvm::StoreInst>(J);
+        SI->setVolatile(true);
+      } else if (isa<llvm::MemIntrinsic>(J)) {
+        auto *MCI = cast<llvm::MemIntrinsic>(J);
+        MCI->setVolatile(llvm::ConstantInt::get(Builder.getInt1Ty(), 1));
+      }
+    } // end of for
+  }
+  const llvm::Instruction *TI = BB->getTerminator();
+  if (TI) {
+    unsigned N = TI->getNumSuccessors();
+    for (unsigned I = 0; I < N; I++)
+      VolatilizeTryBlocks(TI->getSuccessor(I), V);
+  }
+}
+
 namespace {
 struct PerformSEHFinally final : EHScopeStack::Cleanup {
   llvm::Function *OutlinedFinally;
@@ -2050,6 +2121,12 @@
     return;
   }
 
+  // IsEHa: emit an invoke _seh_try_end() to mark end of FT flow
+  if (getLangOpts().EHAsynch && Builder.GetInsertBlock()) {
+    llvm::FunctionCallee SehTryEnd = getSehTryEndFn(CGM);
+    EmitRuntimeCallOrInvoke(SehTryEnd);
+  }
+
   // Otherwise, we must have an __except block.
   const SEHExceptStmt *Except = S.getExceptHandler();
   assert(Except && "__try must have __finally xor __except");
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -1997,9 +1997,16 @@
   const VarDecl &D = *emission.Variable;
 
   // Check the type for a cleanup.
-  if (QualType::DestructionKind dtorKind = D.needsDestruction(getContext()))
+  if (QualType::DestructionKind dtorKind = D.needsDestruction(getContext())) {
     emitAutoVarTypeCleanup(emission, dtorKind);
 
+    // <tentzen>: Under -EHa, Invoke llvm.eha.scope.begin() right after
+    //      Ctor is emitted and EHStack.pushCleanup
+    bool IsEHa = getLangOpts().EHAsynch;
+    if (IsEHa && dtorKind == QualType::DK_cxx_destructor)
+      EmitSehCppScopeBegin();
+  }
+
   // In GC mode, honor objc_precise_lifetime.
   if (getLangOpts().getGC() != LangOptions::NonGC &&
       D.hasAttr<ObjCPreciseLifetimeAttr>()) {
Index: clang/lib/CodeGen/CGCleanup.cpp
===================================================================
--- clang/lib/CodeGen/CGCleanup.cpp
+++ clang/lib/CodeGen/CGCleanup.cpp
@@ -638,6 +638,12 @@
   delete entry;
 }
 
+static llvm::FunctionCallee getSehTryEndFn(CodeGenModule &CGM) {
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+  return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
+}
+
 /// Pops a cleanup block.  If the block includes a normal cleanup, the
 /// current insertion point is threaded through the cleanup, as are
 /// any branch fixups on the cleanup.
@@ -765,10 +771,22 @@
     destroyOptimisticNormalEntry(*this, Scope);
     EHStack.popCleanup();
   } else {
+    // Under -EHa, invoke eha_scope_end() to mark scope end before dtor
+    bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker();
+    const EHPersonality &Personality = EHPersonality::get(*this);
+
     // If we have a fallthrough and no other need for the cleanup,
     // emit it directly.
-    if (HasFallthrough && !HasPrebranchedFallthrough &&
-        !HasFixups && !HasExistingBranches) {
+    if (HasFallthrough && !HasPrebranchedFallthrough && !HasFixups &&
+        !HasExistingBranches) {
+
+      // mark EHa scope end for fall-through flow
+      if (IsEHa && getInvokeDest())
+        if (Personality.isMSVCXXPersonality()) {
+          EmitSehCppScopeEnd();
+        } else {
+          EmitSehTryScopeEnd();
+        }
 
       destroyOptimisticNormalEntry(*this, Scope);
       EHStack.popCleanup();
@@ -803,6 +821,14 @@
       // should already be branched to it.
       EmitBlock(NormalEntry);
 
+      // intercept normal cleanup to mark EHa scope end
+      if (IsEHa)
+        if (Personality.isMSVCXXPersonality()) {
+          EmitSehCppScopeEnd();
+        } else {
+          EmitSehTryScopeEnd();
+        }
+
       // III.  Figure out where we're going and build the cleanup
       // epilogue.
 
@@ -1278,3 +1304,61 @@
   pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject,
               /*useEHCleanup*/ true);
 }
+
+// Need to set "funclet" in OperandBundle properly for noThrow
+//       intrinsic (see CGCall.cpp)
+static void EmitSehEHaScope(CodeGenFunction &CGF,
+                            llvm::FunctionCallee &SehCppScope) {
+  llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
+  llvm::BasicBlock *BB = CGF.Builder.GetInsertBlock();
+  assert(BB && InvokeDest);
+  llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
+  SmallVector<llvm::OperandBundleDef, 1> BundleList =
+      CGF.getBundlesForFunclet(SehCppScope.getCallee());
+  if (CGF.CurrentFuncletPad)
+    BundleList.emplace_back("funclet", CGF.CurrentFuncletPad);
+  CGF.Builder.CreateInvoke(SehCppScope, Cont, InvokeDest, None, BundleList);
+  CGF.EmitBlock(Cont);
+}
+
+// Invoke a llvm.eha.scope.begin at the beginning of a CPP scope for -EHa
+void CodeGenFunction::EmitSehCppScopeBegin() {
+  assert(getLangOpts().EHAsynch);
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+  llvm::FunctionCallee SehCppScope =
+      CGM.CreateRuntimeFunction(FTy, "llvm.eha.scope.begin");
+  EmitSehEHaScope(*this, SehCppScope);
+}
+
+// Invoke a llvm.eha.scope.end at the end of a CPP scope for -EHa
+//   llvm.eha.scope.end is emitted before popCleanup, so it's "invoked"
+void CodeGenFunction::EmitSehCppScopeEnd() {
+  assert(getLangOpts().EHAsynch);
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+  llvm::FunctionCallee SehCppScope =
+      CGM.CreateRuntimeFunction(FTy, "llvm.eha.scope.end");
+  EmitSehEHaScope(*this, SehCppScope);
+}
+
+// Invoke a llvm.eha.scope.begin at the beginning of a CPP scope for -EHa
+void CodeGenFunction::EmitSehTryScopeBegin() {
+  assert(getLangOpts().EHAsynch);
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+  llvm::FunctionCallee SehCppScope =
+      CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin");
+  EmitSehEHaScope(*this, SehCppScope);
+}
+
+// Invoke a llvm.eha.scope.end at the end of a CPP scope for -EHa
+//   llvm.eha.scope.end is emitted before popCleanup, so it's "invoked"
+void CodeGenFunction::EmitSehTryScopeEnd() {
+  assert(getLangOpts().EHAsynch);
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+  llvm::FunctionCallee SehCppScope =
+      CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
+  EmitSehEHaScope(*this, SehCppScope);
+}
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -883,6 +883,8 @@
 def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
 def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group<f_Group>,
   HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>;
+def feh_asynch: Flag<["-"], "feh-asynch">, Group<f_Group>,
+  HelpText<"Enable EH Asynchronous exceptions">, Flags<[CC1Option]>;
 def fcxx_modules : Flag <["-"], "fcxx-modules">, Group<f_Group>,
   Flags<[DriverOption]>;
 def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group<f_Group>;
@@ -1526,6 +1528,7 @@
   Flags<[CC1Option]>,
   HelpText<"Disable creation of CodeFoundation-type constant strings">;
 def fno_cxx_exceptions: Flag<["-"], "fno-cxx-exceptions">, Group<f_Group>;
+def fno_eh_asynch: Flag<["-"], "fno-eh-asynch">, Group<f_Group>;
 def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group<f_Group>,
   Flags<[DriverOption]>;
 def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group<f_Group>,
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -128,6 +128,7 @@
 LANGOPT(Exceptions        , 1, 0, "exception handling")
 LANGOPT(ObjCExceptions    , 1, 0, "Objective-C exceptions")
 LANGOPT(CXXExceptions     , 1, 0, "C++ exceptions")
+LANGOPT(EHAsynch          , 1, 0, "C/C++ EH Asynch exceptions")
 LANGOPT(DWARFExceptions   , 1, 0, "dwarf exception handling")
 LANGOPT(SjLjExceptions    , 1, 0, "setjmp-longjump exception handling")
 LANGOPT(SEHExceptions     , 1, 0, "SEH .xdata exception handling")
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ clang/include/clang/AST/Stmt.h
@@ -1743,6 +1743,7 @@
 class LabelStmt : public ValueStmt {
   LabelDecl *TheDecl;
   Stmt *SubStmt;
+  bool SideEntry = false;
 
 public:
   /// Build a label statement.
@@ -1778,6 +1779,9 @@
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == LabelStmtClass;
   }
+
+  bool IsSideEntry() const { return SideEntry; }
+  void setSideEntry() { SideEntry = true; }
 };
 
 /// Represents an attribute applied to a statement.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to