[WinEH] Find root frame correctly in CLR funclets
Summary:
The value that the CoreCLR personality passes to a funclet for the
establisher frame may be the root function's frame or may be the parent
funclet's (mostly empty) frame in the case of nested funclets. Each
funclet stores a pointer to the root frame in its own (mostly empty)
frame, as does the root function itself. All frames allocate this slot at
the same offset, measured from the post-prolog stack pointer, so that the
same sequence can accept any ancestor as an establisher frame parameter
value, and so that a single offset can be reported to the GC, which also
looks at this slot.
This change allocate the slot when processing function entry, and records
its frame index on the WinEHFuncInfo object, then inserts the code to
set/copy it during prolog emission.
Reviewers: majnemer, AndyAyers, pgavlin, rnk
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D14614
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252983 91177308-0d34-0410-b5e6-96231b3b80d8
2015-11-13 00:39:23 +00:00
|
|
|
; RUN: llc -mtriple=x86_64-pc-windows-coreclr -verify-machineinstrs < %s | FileCheck %s
|
2015-10-13 20:18:27 +00:00
|
|
|
|
|
|
|
declare void @ProcessCLRException()
|
|
|
|
declare void @f(i32)
|
2015-11-07 01:11:31 +00:00
|
|
|
declare void @g(i8 addrspace(1)*)
|
|
|
|
declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token)
|
2015-10-13 20:18:27 +00:00
|
|
|
|
|
|
|
; Simplified IR for pseudo-C# like the following:
|
|
|
|
; void test1() {
|
|
|
|
; try {
|
|
|
|
; f(1);
|
|
|
|
; try {
|
|
|
|
; f(2);
|
|
|
|
; } catch (type1) {
|
|
|
|
; f(3);
|
|
|
|
; } catch (type2) [
|
|
|
|
; f(4);
|
|
|
|
; try {
|
|
|
|
; f(5);
|
|
|
|
; } fault {
|
|
|
|
; f(6);
|
|
|
|
; }
|
|
|
|
; }
|
|
|
|
; } finally {
|
|
|
|
; f(7);
|
|
|
|
; }
|
|
|
|
; f(8);
|
|
|
|
; }
|
|
|
|
|
|
|
|
; CHECK-LABEL: test1: # @test1
|
|
|
|
; CHECK-NEXT: [[L_begin:.*func_begin.*]]:
|
|
|
|
define void @test1() personality i8* bitcast (void ()* @ProcessCLRException to i8*) {
|
|
|
|
entry:
|
|
|
|
; CHECK: # %entry
|
[WinEH] Find root frame correctly in CLR funclets
Summary:
The value that the CoreCLR personality passes to a funclet for the
establisher frame may be the root function's frame or may be the parent
funclet's (mostly empty) frame in the case of nested funclets. Each
funclet stores a pointer to the root frame in its own (mostly empty)
frame, as does the root function itself. All frames allocate this slot at
the same offset, measured from the post-prolog stack pointer, so that the
same sequence can accept any ancestor as an establisher frame parameter
value, and so that a single offset can be reported to the GC, which also
looks at this slot.
This change allocate the slot when processing function entry, and records
its frame index on the WinEHFuncInfo object, then inserts the code to
set/copy it during prolog emission.
Reviewers: majnemer, AndyAyers, pgavlin, rnk
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D14614
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252983 91177308-0d34-0410-b5e6-96231b3b80d8
2015-11-13 00:39:23 +00:00
|
|
|
; CHECK: leaq [[FPOffset:[0-9]+]](%rsp), %rbp
|
2015-10-13 20:18:27 +00:00
|
|
|
; CHECK: .seh_endprologue
|
[WinEH] Find root frame correctly in CLR funclets
Summary:
The value that the CoreCLR personality passes to a funclet for the
establisher frame may be the root function's frame or may be the parent
funclet's (mostly empty) frame in the case of nested funclets. Each
funclet stores a pointer to the root frame in its own (mostly empty)
frame, as does the root function itself. All frames allocate this slot at
the same offset, measured from the post-prolog stack pointer, so that the
same sequence can accept any ancestor as an establisher frame parameter
value, and so that a single offset can be reported to the GC, which also
looks at this slot.
This change allocate the slot when processing function entry, and records
its frame index on the WinEHFuncInfo object, then inserts the code to
set/copy it during prolog emission.
Reviewers: majnemer, AndyAyers, pgavlin, rnk
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D14614
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252983 91177308-0d34-0410-b5e6-96231b3b80d8
2015-11-13 00:39:23 +00:00
|
|
|
; CHECK: movq %rsp, [[PSPSymOffset:[0-9]+]](%rsp)
|
2015-10-13 20:18:27 +00:00
|
|
|
; CHECK: [[L_before_f1:.+]]:
|
|
|
|
; CHECK-NEXT: movl $1, %ecx
|
|
|
|
; CHECK-NEXT: callq f
|
|
|
|
; CHECK-NEXT: [[L_after_f1:.+]]:
|
|
|
|
invoke void @f(i32 1)
|
|
|
|
to label %inner_try unwind label %finally.pad
|
|
|
|
inner_try:
|
|
|
|
; CHECK: # %inner_try
|
|
|
|
; CHECK: [[L_before_f2:.+]]:
|
|
|
|
; CHECK-NEXT: movl $2, %ecx
|
|
|
|
; CHECK-NEXT: callq f
|
|
|
|
; CHECK-NEXT: [[L_after_f2:.+]]:
|
|
|
|
invoke void @f(i32 2)
|
|
|
|
to label %finally.clone unwind label %catch1.pad
|
|
|
|
catch1.pad:
|
|
|
|
; CHECK: .seh_proc [[L_catch1:[^ ]+]]
|
|
|
|
%catch1 = catchpad [i32 1]
|
|
|
|
to label %catch1.body unwind label %catch2.pad
|
|
|
|
catch1.body:
|
[WinEH] Find root frame correctly in CLR funclets
Summary:
The value that the CoreCLR personality passes to a funclet for the
establisher frame may be the root function's frame or may be the parent
funclet's (mostly empty) frame in the case of nested funclets. Each
funclet stores a pointer to the root frame in its own (mostly empty)
frame, as does the root function itself. All frames allocate this slot at
the same offset, measured from the post-prolog stack pointer, so that the
same sequence can accept any ancestor as an establisher frame parameter
value, and so that a single offset can be reported to the GC, which also
looks at this slot.
This change allocate the slot when processing function entry, and records
its frame index on the WinEHFuncInfo object, then inserts the code to
set/copy it during prolog emission.
Reviewers: majnemer, AndyAyers, pgavlin, rnk
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D14614
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252983 91177308-0d34-0410-b5e6-96231b3b80d8
2015-11-13 00:39:23 +00:00
|
|
|
; 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
|
2015-10-13 20:18:27 +00:00
|
|
|
; CHECK: .seh_endprologue
|
2015-11-07 01:11:31 +00:00
|
|
|
; 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)
|
2015-10-13 20:18:27 +00:00
|
|
|
; CHECK: [[L_before_f3:.+]]:
|
|
|
|
; CHECK-NEXT: movl $3, %ecx
|
|
|
|
; CHECK-NEXT: callq f
|
|
|
|
; CHECK-NEXT: [[L_after_f3:.+]]:
|
|
|
|
invoke void @f(i32 3)
|
|
|
|
to label %catch1.ret unwind label %catch.end
|
|
|
|
catch1.ret:
|
|
|
|
catchret %catch1 to label %finally.clone
|
|
|
|
catch2.pad:
|
|
|
|
; CHECK: .seh_proc [[L_catch2:[^ ]+]]
|
|
|
|
%catch2 = catchpad [i32 2]
|
|
|
|
to label %catch2.body unwind label %catch.end
|
|
|
|
catch2.body:
|
[WinEH] Find root frame correctly in CLR funclets
Summary:
The value that the CoreCLR personality passes to a funclet for the
establisher frame may be the root function's frame or may be the parent
funclet's (mostly empty) frame in the case of nested funclets. Each
funclet stores a pointer to the root frame in its own (mostly empty)
frame, as does the root function itself. All frames allocate this slot at
the same offset, measured from the post-prolog stack pointer, so that the
same sequence can accept any ancestor as an establisher frame parameter
value, and so that a single offset can be reported to the GC, which also
looks at this slot.
This change allocate the slot when processing function entry, and records
its frame index on the WinEHFuncInfo object, then inserts the code to
set/copy it during prolog emission.
Reviewers: majnemer, AndyAyers, pgavlin, rnk
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D14614
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252983 91177308-0d34-0410-b5e6-96231b3b80d8
2015-11-13 00:39:23 +00:00
|
|
|
; 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
|
2015-10-13 20:18:27 +00:00
|
|
|
; CHECK: .seh_endprologue
|
2015-11-07 01:11:31 +00:00
|
|
|
; 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)
|
2015-10-13 20:18:27 +00:00
|
|
|
; CHECK: [[L_before_f4:.+]]:
|
|
|
|
; CHECK-NEXT: movl $4, %ecx
|
|
|
|
; CHECK-NEXT: callq f
|
|
|
|
; CHECK-NEXT: [[L_after_f4:.+]]:
|
|
|
|
invoke void @f(i32 4)
|
|
|
|
to label %try_in_catch unwind label %catch.end
|
|
|
|
try_in_catch:
|
|
|
|
; CHECK: # %try_in_catch
|
|
|
|
; CHECK: [[L_before_f5:.+]]:
|
|
|
|
; CHECK-NEXT: movl $5, %ecx
|
|
|
|
; CHECK-NEXT: callq f
|
|
|
|
; CHECK-NEXT: [[L_after_f5:.+]]:
|
|
|
|
invoke void @f(i32 5)
|
|
|
|
to label %catch2.ret unwind label %fault.pad
|
|
|
|
fault.pad:
|
|
|
|
; CHECK: .seh_proc [[L_fault:[^ ]+]]
|
|
|
|
%fault = cleanuppad [i32 undef]
|
[WinEH] Find root frame correctly in CLR funclets
Summary:
The value that the CoreCLR personality passes to a funclet for the
establisher frame may be the root function's frame or may be the parent
funclet's (mostly empty) frame in the case of nested funclets. Each
funclet stores a pointer to the root frame in its own (mostly empty)
frame, as does the root function itself. All frames allocate this slot at
the same offset, measured from the post-prolog stack pointer, so that the
same sequence can accept any ancestor as an establisher frame parameter
value, and so that a single offset can be reported to the GC, which also
looks at this slot.
This change allocate the slot when processing function entry, and records
its frame index on the WinEHFuncInfo object, then inserts the code to
set/copy it during prolog emission.
Reviewers: majnemer, AndyAyers, pgavlin, rnk
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D14614
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252983 91177308-0d34-0410-b5e6-96231b3b80d8
2015-11-13 00:39:23 +00:00
|
|
|
; 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
|
2015-10-13 20:18:27 +00:00
|
|
|
; CHECK: .seh_endprologue
|
|
|
|
; CHECK: [[L_before_f6:.+]]:
|
|
|
|
; CHECK-NEXT: movl $6, %ecx
|
|
|
|
; CHECK-NEXT: callq f
|
|
|
|
; CHECK-NEXT: [[L_after_f6:.+]]:
|
|
|
|
invoke void @f(i32 6)
|
|
|
|
to label %fault.ret unwind label %fault.end
|
|
|
|
fault.ret:
|
|
|
|
cleanupret %fault unwind label %catch.end
|
|
|
|
fault.end:
|
|
|
|
cleanupendpad %fault unwind label %catch.end
|
|
|
|
catch2.ret:
|
|
|
|
catchret %catch2 to label %finally.clone
|
|
|
|
catch.end:
|
|
|
|
catchendpad unwind label %finally.pad
|
|
|
|
finally.clone:
|
|
|
|
call void @f(i32 7)
|
|
|
|
br label %tail
|
|
|
|
finally.pad:
|
|
|
|
; CHECK: .seh_proc [[L_finally:[^ ]+]]
|
|
|
|
%finally = cleanuppad []
|
[WinEH] Find root frame correctly in CLR funclets
Summary:
The value that the CoreCLR personality passes to a funclet for the
establisher frame may be the root function's frame or may be the parent
funclet's (mostly empty) frame in the case of nested funclets. Each
funclet stores a pointer to the root frame in its own (mostly empty)
frame, as does the root function itself. All frames allocate this slot at
the same offset, measured from the post-prolog stack pointer, so that the
same sequence can accept any ancestor as an establisher frame parameter
value, and so that a single offset can be reported to the GC, which also
looks at this slot.
This change allocate the slot when processing function entry, and records
its frame index on the WinEHFuncInfo object, then inserts the code to
set/copy it during prolog emission.
Reviewers: majnemer, AndyAyers, pgavlin, rnk
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D14614
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252983 91177308-0d34-0410-b5e6-96231b3b80d8
2015-11-13 00:39:23 +00:00
|
|
|
; 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
|
2015-10-13 20:18:27 +00:00
|
|
|
; CHECK: .seh_endprologue
|
|
|
|
; CHECK: [[L_before_f7:.+]]:
|
|
|
|
; CHECK-NEXT: movl $7, %ecx
|
|
|
|
; CHECK-NEXT: callq f
|
|
|
|
; CHECK-NEXT: [[L_after_f7:.+]]:
|
|
|
|
invoke void @f(i32 7)
|
|
|
|
to label %finally.ret unwind label %finally.end
|
|
|
|
finally.ret:
|
|
|
|
cleanupret %finally unwind to caller
|
|
|
|
finally.end:
|
|
|
|
cleanupendpad %finally unwind to caller
|
|
|
|
tail:
|
|
|
|
call void @f(i32 8)
|
|
|
|
ret void
|
|
|
|
; CHECK: [[L_end:.*func_end.*]]:
|
|
|
|
}
|
|
|
|
|
|
|
|
; Now check for EH table in xdata (following standard xdata)
|
|
|
|
; CHECK-LABEL: .section .xdata
|
|
|
|
; standard xdata comes here
|
|
|
|
; CHECK: .long 4{{$}}
|
|
|
|
; ^ number of funclets
|
|
|
|
; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]]
|
|
|
|
; ^ offset from L_begin to start of 1st funclet
|
|
|
|
; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
|
|
|
|
; ^ offset from L_begin to start of 2nd funclet
|
|
|
|
; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
|
|
|
|
; ^ offset from L_begin to start of 3rd funclet
|
|
|
|
; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
|
|
|
|
; ^ offset from L_begin to start of 4th funclet
|
|
|
|
; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
|
|
|
|
; ^ offset from L_begin to end of last funclet
|
|
|
|
; CHECK-NEXT: .long 7
|
|
|
|
; ^ number of EH clauses
|
|
|
|
; Clause 1: call f(2) is guarded by catch1
|
|
|
|
; CHECK-NEXT: .long 0
|
|
|
|
; ^ flags (0 => catch handler)
|
|
|
|
; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
|
|
|
|
; ^ offset of start of clause
|
|
|
|
; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
|
|
|
|
; ^ offset of end of clause
|
|
|
|
; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]]
|
|
|
|
; ^ offset of start of handler
|
|
|
|
; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
|
|
|
|
; ^ offset of end of handler
|
|
|
|
; CHECK-NEXT: .long 1
|
|
|
|
; ^ type token of catch (from catchpad)
|
|
|
|
; Clause 2: call f(2) is also guarded by catch2
|
|
|
|
; CHECK-NEXT: .long 0
|
|
|
|
; ^ flags (0 => catch handler)
|
|
|
|
; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
|
|
|
|
; ^ offset of start of clause
|
|
|
|
; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
|
|
|
|
; ^ offset of end of clause
|
|
|
|
; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
|
|
|
|
; ^ offset of start of handler
|
|
|
|
; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
|
|
|
|
; ^ offset of end of handler
|
|
|
|
; CHECK-NEXT: .long 2
|
|
|
|
; ^ type token of catch (from catchpad)
|
|
|
|
; Clause 3: calls f(1) and f(2) are guarded by finally
|
|
|
|
; CHECK-NEXT: .long 2
|
|
|
|
; ^ flags (2 => finally handler)
|
|
|
|
; CHECK-NEXT: .long ([[L_before_f1]]-[[L_begin]])+1
|
|
|
|
; ^ offset of start of clause
|
|
|
|
; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
|
|
|
|
; ^ offset of end of clause
|
|
|
|
; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
|
|
|
|
; ^ offset of start of handler
|
|
|
|
; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
|
|
|
|
; ^ offset of end of handler
|
|
|
|
; CHECK-NEXT: .long 0
|
|
|
|
; ^ type token slot (null for finally)
|
|
|
|
; Clause 4: call f(3) is guarded by finally
|
|
|
|
; This is a "duplicate" because the protected range (f(3))
|
|
|
|
; is in funclet catch1 but the finally's immediate parent
|
|
|
|
; is the main function, not that funclet.
|
|
|
|
; CHECK-NEXT: .long 10
|
|
|
|
; ^ flags (2 => finally handler | 8 => duplicate)
|
|
|
|
; CHECK-NEXT: .long ([[L_before_f3]]-[[L_begin]])+1
|
|
|
|
; ^ offset of start of clause
|
|
|
|
; CHECK-NEXT: .long ([[L_after_f3]]-[[L_begin]])+1
|
|
|
|
; ^ offset of end of clause
|
|
|
|
; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
|
|
|
|
; ^ offset of start of handler
|
|
|
|
; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
|
|
|
|
; ^ offset of end of handler
|
|
|
|
; CHECK-NEXT: .long 0
|
|
|
|
; ^ type token slot (null for finally)
|
|
|
|
; Clause 5: call f(5) is guarded by fault
|
|
|
|
; CHECK-NEXT: .long 4
|
|
|
|
; ^ flags (4 => fault handler)
|
|
|
|
; CHECK-NEXT: .long ([[L_before_f5]]-[[L_begin]])+1
|
|
|
|
; ^ offset of start of clause
|
|
|
|
; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
|
|
|
|
; ^ offset of end of clause
|
|
|
|
; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
|
|
|
|
; ^ offset of start of handler
|
|
|
|
; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
|
|
|
|
; ^ offset of end of handler
|
|
|
|
; CHECK-NEXT: .long 0
|
|
|
|
; ^ type token slot (null for fault)
|
|
|
|
; Clause 6: calls f(4) and f(5) are guarded by finally
|
|
|
|
; This is a "duplicate" because the protected range (f(4)-f(5))
|
|
|
|
; is in funclet catch2 but the finally's immediate parent
|
|
|
|
; is the main function, not that funclet.
|
|
|
|
; CHECK-NEXT: .long 10
|
|
|
|
; ^ flags (2 => finally handler | 8 => duplicate)
|
|
|
|
; CHECK-NEXT: .long ([[L_before_f4]]-[[L_begin]])+1
|
|
|
|
; ^ offset of start of clause
|
|
|
|
; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
|
|
|
|
; ^ offset of end of clause
|
|
|
|
; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
|
|
|
|
; ^ offset of start of handler
|
|
|
|
; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
|
|
|
|
; ^ offset of end of handler
|
|
|
|
; CHECK-NEXT: .long 0
|
|
|
|
; ^ type token slot (null for finally)
|
|
|
|
; Clause 7: call f(6) is guarded by finally
|
|
|
|
; This is a "duplicate" because the protected range (f(3))
|
|
|
|
; is in funclet catch1 but the finally's immediate parent
|
|
|
|
; is the main function, not that funclet.
|
|
|
|
; CHECK-NEXT: .long 10
|
|
|
|
; ^ flags (2 => finally handler | 8 => duplicate)
|
|
|
|
; CHECK-NEXT: .long ([[L_before_f6]]-[[L_begin]])+1
|
|
|
|
; ^ offset of start of clause
|
|
|
|
; CHECK-NEXT: .long ([[L_after_f6]]-[[L_begin]])+1
|
|
|
|
; ^ offset of end of clause
|
|
|
|
; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
|
|
|
|
; ^ offset of start of handler
|
|
|
|
; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
|
|
|
|
; ^ offset of end of handler
|
|
|
|
; CHECK-NEXT: .long 0
|
|
|
|
; ^ type token slot (null for finally)
|