-; RUN: llc -mtriple=x86_64-pc-windows-coreclr < %s | FileCheck %s
+; RUN: llc -mtriple=x86_64-pc-windows-coreclr -verify-machineinstrs < %s | FileCheck %s
declare void @ProcessCLRException()
declare void @f(i32)
+declare void @g(i8 addrspace(1)*)
+declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token)
; Simplified IR for pseudo-C# like the following:
; void test1() {
define void @test1() personality i8* bitcast (void ()* @ProcessCLRException to i8*) {
entry:
; CHECK: # %entry
+; CHECK: leaq [[FPOffset:[0-9]+]](%rsp), %rbp
; CHECK: .seh_endprologue
+; CHECK: movq %rsp, [[PSPSymOffset:[0-9]+]](%rsp)
; CHECK: [[L_before_f1:.+]]:
; CHECK-NEXT: movl $1, %ecx
; CHECK-NEXT: callq f
%catch1 = catchpad [i32 1]
to label %catch1.body unwind label %catch2.pad
catch1.body:
+; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
+; ^ all funclets use the same frame size
+; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
+; ^ establisher frame pointer passed in rcx
+; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
+; CHECK: leaq [[FPOffset]](%rcx), %rbp
; CHECK: .seh_endprologue
+; CHECK: movq %rdx, %rcx
+; ^ exception pointer passed in rdx
+; CHECK-NEXT: callq g
+ %exn1 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch1)
+ call void @g(i8 addrspace(1)* %exn1)
; CHECK: [[L_before_f3:.+]]:
; CHECK-NEXT: movl $3, %ecx
; CHECK-NEXT: callq f
%catch2 = catchpad [i32 2]
to label %catch2.body unwind label %catch.end
catch2.body:
+; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
+; ^ all funclets use the same frame size
+; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
+; ^ establisher frame pointer passed in rcx
+; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
+; CHECK: leaq [[FPOffset]](%rcx), %rbp
; CHECK: .seh_endprologue
+; CHECK: movq %rdx, %rcx
+; ^ exception pointer passed in rdx
+; CHECK-NEXT: callq g
+ %exn2 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch2)
+ call void @g(i8 addrspace(1)* %exn2)
; CHECK: [[L_before_f4:.+]]:
; CHECK-NEXT: movl $4, %ecx
; CHECK-NEXT: callq f
fault.pad:
; CHECK: .seh_proc [[L_fault:[^ ]+]]
%fault = cleanuppad [i32 undef]
+; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
+; ^ all funclets use the same frame size
+; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
+; ^ establisher frame pointer passed in rcx
+; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
+; CHECK: leaq [[FPOffset]](%rcx), %rbp
; CHECK: .seh_endprologue
; CHECK: [[L_before_f6:.+]]:
; CHECK-NEXT: movl $6, %ecx
finally.pad:
; CHECK: .seh_proc [[L_finally:[^ ]+]]
%finally = cleanuppad []
+; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
+; ^ all funclets use the same frame size
+; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
+; ^ establisher frame pointer passed in rcx
+; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
+; CHECK: leaq [[FPOffset]](%rcx), %rbp
; CHECK: .seh_endprologue
; CHECK: [[L_before_f7:.+]]:
; CHECK-NEXT: movl $7, %ecx