| ; RUN: llc < %s -mtriple=i686-pc-windows-msvc | FileCheck %s -check-prefix=X32 |
| ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s -check-prefixes=X64 |
| ; Control Flow Guard is currently only available on Windows |
| |
| ; funclets only supported in MSVC env. |
| |
| ; Test that Control Flow Guard Checks are added well for targets in try-catch. |
| |
| |
| declare i32 @target_func() |
| |
| |
| %eh.ThrowInfo = type { i32, ptr, ptr, ptr } |
| |
| declare i32 @__CxxFrameHandler3(...) |
| declare void @_CxxThrowException(ptr, ptr) |
| |
| define i32 @func_cf_exception() personality ptr @__CxxFrameHandler3 { |
| entry: |
| %func_ptr = alloca ptr, align 8 |
| store ptr @target_func, ptr %func_ptr, align 8 |
| invoke void @_CxxThrowException(ptr null, ptr null) #11 |
| to label %unreachable unwind label %ehcleanup |
| |
| ehcleanup: |
| %0 = cleanuppad within none [] |
| %isnull = icmp eq ptr %func_ptr, null |
| br i1 %isnull, label %exit, label %callfn |
| |
| callfn: |
| %1 = load ptr, ptr %func_ptr, align 8 |
| %2 = call i32 %1() #9 [ "funclet"(token %0) ] |
| br label %exit |
| |
| exit: |
| cleanupret from %0 unwind label %catch.dispatch |
| |
| unreachable: |
| unreachable |
| |
| catch.dispatch: |
| %3 = catchswitch within none [label %catch] unwind to caller |
| |
| catch: |
| %4 = catchpad within %3 [ptr null, i32 64, ptr null] |
| catchret from %4 to label %try.cont |
| |
| try.cont: |
| ret i32 0 |
| |
| ; X32-LABEL: func_cf_exception |
| ; X32: calll *___guard_check_icall_fptr |
| ; X32-NEXT: calll *%ecx |
| |
| ; X64-LABEL: func_cf_exception |
| ; X64: callq *__guard_dispatch_icall_fptr(%rip) |
| ; X64-NOT: callq |
| } |
| |
| |
| !llvm.module.flags = !{!0} |
| !0 = !{i32 2, !"cfguard", i32 2} |