OLD | NEW |
(Empty) | |
| 1 ; RUN: opt %s -pnacl-sjlj-eh -S | FileCheck %s |
| 2 |
| 3 ; This must be declared for expanding "invoke" and "landingpad" instructions. |
| 4 @__pnacl_eh_stack = external thread_local global i8* |
| 5 |
| 6 ; This must be declared for expanding "resume" instructions. |
| 7 declare void @__pnacl_eh_resume(i32* %exception) |
| 8 |
| 9 declare i32 @external_func(i64 %arg) |
| 10 |
| 11 |
| 12 ; CHECK: %ExceptionFrame = type { [1024 x i8], %ExceptionFrame*, i32 } |
| 13 |
| 14 define i32 @invoke_test(i64 %arg) { |
| 15 %result = invoke i32 @external_func(i64 %arg) |
| 16 to label %cont unwind label %lpad |
| 17 cont: |
| 18 ret i32 %result |
| 19 lpad: |
| 20 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 21 ret i32 999 |
| 22 } |
| 23 ; CHECK: define i32 @invoke_test |
| 24 ; CHECK-NEXT: %invoke_frame = alloca %ExceptionFrame, align 8 |
| 25 ; CHECK-NEXT: %exc_info_ptr = getelementptr %ExceptionFrame* %invoke_frame, i32
0, i32 2 |
| 26 ; CHECK-NEXT: %invoke_next = getelementptr %ExceptionFrame* %invoke_frame, i32 0
, i32 1 |
| 27 ; CHECK-NEXT: %invoke_jmp_buf = getelementptr %ExceptionFrame* %invoke_frame, i3
2 0, i32 0, i32 0 |
| 28 ; CHECK-NEXT: %pnacl_eh_stack = bitcast i8** @__pnacl_eh_stack to %ExceptionFram
e** |
| 29 ; CHECK-NEXT: %invoke_sj = call i32 @llvm.nacl.setjmp(i8* %invoke_jmp_buf) |
| 30 ; CHECK-NEXT: %invoke_sj_is_zero = icmp eq i32 %invoke_sj, 0 |
| 31 ; CHECK-NEXT: br i1 %invoke_sj_is_zero, label %invoke_do_call, label %lpad |
| 32 ; CHECK: invoke_do_call: |
| 33 ; CHECK-NEXT: %old_eh_stack = load %ExceptionFrame** %pnacl_eh_stack |
| 34 ; CHECK-NEXT: store %ExceptionFrame* %old_eh_stack, %ExceptionFrame** %invoke_ne
xt |
| 35 ; CHECK-NEXT: store i32 {{[0-9]+}}, i32* %exc_info_ptr |
| 36 ; CHECK-NEXT: store %ExceptionFrame* %invoke_frame, %ExceptionFrame** %pnacl_eh_
stack |
| 37 ; CHECK-NEXT: %result = call i32 @external_func(i64 %arg) |
| 38 ; CHECK-NEXT: store %ExceptionFrame* %old_eh_stack, %ExceptionFrame** %pnacl_eh_
stack |
| 39 ; CHECK-NEXT: br label %cont |
| 40 ; CHECK: cont: |
| 41 ; CHECK-NEXT: ret i32 %result |
| 42 ; CHECK: lpad: |
| 43 ; CHECK-NEXT: %landingpad_ptr = bitcast i8* %invoke_jmp_buf to { i8*, i32 }* |
| 44 ; CHECK-NEXT: %lp = load { i8*, i32 }* %landingpad_ptr |
| 45 ; CHECK-NEXT: ret i32 999 |
| 46 |
| 47 |
| 48 ; A landingpad block may be used by multiple "invoke" instructions. |
| 49 define i32 @shared_landingpad(i64 %arg) { |
| 50 %result1 = invoke i32 @external_func(i64 %arg) |
| 51 to label %cont1 unwind label %lpad |
| 52 cont1: |
| 53 %result2 = invoke i32 @external_func(i64 %arg) |
| 54 to label %cont2 unwind label %lpad |
| 55 cont2: |
| 56 ret i32 %result2 |
| 57 lpad: |
| 58 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 59 ret i32 999 |
| 60 } |
| 61 ; CHECK: define i32 @shared_landingpad |
| 62 ; CHECK: br i1 %invoke_sj_is_zero, label %invoke_do_call, label %lpad |
| 63 ; CHECK: br i1 %invoke_sj_is_zero2, label %invoke_do_call3, label %lpad |
| 64 |
| 65 |
| 66 ; Check that the pass can handle a landingpad appearing before an invoke. |
| 67 define i32 @landingpad_before_invoke() { |
| 68 ret i32 123 |
| 69 |
| 70 dead_block: |
| 71 %lp = landingpad i32 personality i8* null cleanup |
| 72 ret i32 %lp |
| 73 } |
| 74 ; CHECK: define i32 @landingpad_before_invoke |
| 75 ; CHECK: %lp = load i32* %landingpad_ptr |
| 76 |
| 77 |
| 78 ; Test the expansion of the "resume" instruction. |
| 79 define void @test_resume({ i8*, i32 } %arg) { |
| 80 resume { i8*, i32 } %arg |
| 81 } |
| 82 ; CHECK: define void @test_resume |
| 83 ; CHECK-NEXT: %resume_exc = extractvalue { i8*, i32 } %arg, 0 |
| 84 ; CHECK-NEXT: %resume_cast = bitcast i8* %resume_exc to i32* |
| 85 ; CHECK-NEXT: call void @__pnacl_eh_resume(i32* %resume_cast) |
| 86 ; CHECK-NEXT: unreachable |
| 87 |
| 88 |
| 89 ; Check that call attributes are preserved. |
| 90 define i32 @call_attrs(i64 %arg) { |
| 91 %result = invoke fastcc i32 @external_func(i64 inreg %arg) noreturn |
| 92 to label %cont unwind label %lpad |
| 93 cont: |
| 94 ret i32 %result |
| 95 lpad: |
| 96 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 97 ret i32 999 |
| 98 } |
| 99 ; CHECK: define i32 @call_attrs |
| 100 ; CHECK: %result = call fastcc i32 @external_func(i64 inreg %arg) [[NORETURN:#[0
-9]+]] |
| 101 |
| 102 |
| 103 ; Check that any PHI nodes referring to the result of an "invoke" are |
| 104 ; updated to refer to the correct basic block. |
| 105 define i32 @invoke_with_phi_nodes(i64 %arg) { |
| 106 entry: |
| 107 %result = invoke i32 @external_func(i64 %arg) |
| 108 to label %cont unwind label %lpad |
| 109 cont: |
| 110 %cont_phi = phi i32 [ 100, %entry ] |
| 111 ret i32 %cont_phi |
| 112 lpad: |
| 113 %lpad_phi = phi i32 [ 200, %entry ] |
| 114 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 115 ret i32 %lpad_phi |
| 116 } |
| 117 ; CHECK: define i32 @invoke_with_phi_nodes |
| 118 ; CHECK: %result = call i32 @external_func(i64 %arg) |
| 119 ; CHECK: cont: |
| 120 ; CHECK-NEXT: %cont_phi = phi i32 [ 100, %invoke_do_call ] |
| 121 ; CHECK-NEXT: ret i32 %cont_phi |
| 122 ; CHECK: lpad: |
| 123 ; CHECK-NEXT: %lpad_phi = phi i32 [ 200, %entry ] |
| 124 ; CHECK: ret i32 %lpad_phi |
| 125 |
| 126 |
| 127 ; CHECK: attributes [[NORETURN]] = { noreturn } |
OLD | NEW |