1; RUN: opt %s -passes='cgscc(inline)' -S | FileCheck %s 2; RUN: opt %s -passes='module-inline' -S | FileCheck %s 3 4declare void @external_func() 5declare void @abort() 6 7@exception_inner = external global i8 8@exception_outer = external global i8 9@condition = external global i1 10 11 12; Check for a bug in which multiple "resume" instructions in the 13; inlined function caused "catch ptr @exception_outer" to appear 14; multiple times in the resulting landingpad. 15 16define internal void @inner_multiple_resume() personality ptr null { 17 invoke void @external_func() 18 to label %cont unwind label %lpad 19cont: 20 ret void 21lpad: 22 %lp = landingpad i32 23 catch ptr @exception_inner 24 %cond = load i1, ptr @condition 25 br i1 %cond, label %resume1, label %resume2 26resume1: 27 resume i32 1 28resume2: 29 resume i32 2 30} 31 32define void @outer_multiple_resume() personality ptr null { 33 invoke void @inner_multiple_resume() 34 to label %cont unwind label %lpad 35cont: 36 ret void 37lpad: 38 %lp = landingpad i32 39 catch ptr @exception_outer 40 resume i32 %lp 41} 42; CHECK: define void @outer_multiple_resume() 43; CHECK: %lp.i = landingpad 44; CHECK-NEXT: catch ptr @exception_inner 45; CHECK-NEXT: catch ptr @exception_outer 46; Check that there isn't another "catch" clause: 47; CHECK-NEXT: load 48 49 50; Check for a bug in which having a "resume" and a "call" in the 51; inlined function caused "catch ptr @exception_outer" to appear 52; multiple times in the resulting landingpad. 53 54define internal void @inner_resume_and_call() personality ptr null { 55 call void @external_func() 56 invoke void @external_func() 57 to label %cont unwind label %lpad 58cont: 59 ret void 60lpad: 61 %lp = landingpad i32 62 catch ptr @exception_inner 63 resume i32 %lp 64} 65 66define void @outer_resume_and_call() personality ptr null { 67 invoke void @inner_resume_and_call() 68 to label %cont unwind label %lpad 69cont: 70 ret void 71lpad: 72 %lp = landingpad i32 73 catch ptr @exception_outer 74 resume i32 %lp 75} 76; CHECK: define void @outer_resume_and_call() 77; CHECK: %lp.i = landingpad 78; CHECK-NEXT: catch ptr @exception_inner 79; CHECK-NEXT: catch ptr @exception_outer 80; Check that there isn't another "catch" clause: 81; CHECK-NEXT: br 82 83 84; Check what happens if the inlined function contains an "invoke" but 85; no "resume". In this case, the inlined landingpad does not need to 86; include the "catch ptr @exception_outer" clause from the outer 87; function (since the outer function's landingpad will not be 88; reachable), but it's OK to include this clause. 89 90define internal void @inner_no_resume_or_call() personality ptr null { 91 invoke void @external_func() 92 to label %cont unwind label %lpad 93cont: 94 ret void 95lpad: 96 %lp = landingpad i32 97 catch ptr @exception_inner 98 ; A landingpad might have no "resume" if a C++ destructor aborts. 99 call void @abort() noreturn nounwind 100 unreachable 101} 102 103define void @outer_no_resume_or_call() personality ptr null { 104 invoke void @inner_no_resume_or_call() 105 to label %cont unwind label %lpad 106cont: 107 ret void 108lpad: 109 %lp = landingpad i32 110 catch ptr @exception_outer 111 resume i32 %lp 112} 113; CHECK: define void @outer_no_resume_or_call() 114; CHECK: %lp.i = landingpad 115; CHECK-NEXT: catch ptr @exception_inner 116; CHECK-NEXT: catch ptr @exception_outer 117; Check that there isn't another "catch" clause: 118; CHECK-NEXT: call void @abort() 119