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