1; TODO Reenable disabled lines after updating the backend to the new spec 2; R UN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling | FileCheck -allow-deprecated-dag-overlap %s 3 4; FIXME A temporary RUN line to make the test pass. Remove this later. 5; RUN: true 6 7target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 8target triple = "wasm32-unknown-unknown" 9 10@_ZTIi = external constant i8* 11@_ZTIf = external constant i8* 12@_ZTId = external constant i8* 13 14; Single catch (...) does not need an exception table. 15; 16; try { 17; may_throw(); 18; } catch (...) { 19; } 20; CHECK-LABEL: test0: 21; CHECK-NOT: GCC_except_table 22define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { 23entry: 24 invoke void @may_throw() 25 to label %try.cont unwind label %catch.dispatch 26 27catch.dispatch: ; preds = %entry 28 %0 = catchswitch within none [label %catch.start] unwind to caller 29 30catch.start: ; preds = %catch.dispatch 31 %1 = catchpad within %0 [i8* null] 32 %2 = call i8* @llvm.wasm.get.exception(token %1) 33 %3 = call i32 @llvm.wasm.get.ehselector(token %1) 34 %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ] 35 call void @__cxa_end_catch() [ "funclet"(token %1) ] 36 catchret from %1 to label %try.cont 37 38try.cont: ; preds = %entry, %catch.start 39 ret void 40} 41 42; Exception table generation + shared action test. 43; 44; try { 45; may_throw(); 46; } catch (int) { 47; } catch (float) { 48; } catch (double) { 49; } catch (...) { 50; } 51; 52; try { 53; may_throw(); 54; } catch (double) { 55; } catch (...) { 56; } 57; 58; try { 59; may_throw(); 60; } catch (int) { 61; } catch (float) { 62; } 63; 64; There are three landing pads. The second landing pad should share action table 65; entries with the first landing pad because they end with the same sequence 66; (double -> ...). But the third landing table cannot share action table entries 67; with others, so it should create its own entries. 68; CHECK-LABEL: test1: 69; CHECK: .section .rodata.gcc_except_table,"",@ 70; CHECK-NEXT: .p2align 2 71; CHECK-NEXT: GCC_except_table[[START:[0-9]+]]: 72; CHECK-NEXT: .Lexception0: 73; CHECK-NEXT: .int8 255 # @LPStart Encoding = omit 74; CHECK-NEXT: .int8 0 # @TType Encoding = absptr 75; CHECK-NEXT: .uleb128 .Lttbase0-.Lttbaseref0 76; CHECK-NEXT: .Lttbaseref0: 77; CHECK-NEXT: .int8 1 # Call site Encoding = uleb128 78; CHECK-NEXT: .uleb128 .Lcst_end0-.Lcst_begin0 79; CHECK-NEXT: .Lcst_begin0: 80; CHECK-NEXT: .int8 0 # >> Call Site 0 << 81; CHECK-NEXT: # On exception at call site 0 82; CHECK-NEXT: .int8 7 # Action: 4 83; CHECK-NEXT: .int8 1 # >> Call Site 1 << 84; CHECK-NEXT: # On exception at call site 1 85; CHECK-NEXT: .int8 3 # Action: 2 86; CHECK-NEXT: .int8 2 # >> Call Site 2 << 87; CHECK-NEXT: # On exception at call site 2 88; CHECK-NEXT: .int8 11 # Action: 6 89; CHECK-NEXT: .Lcst_end0: 90; CHECK-NEXT: .int8 1 # >> Action Record 1 << 91; CHECK-NEXT: # Catch TypeInfo 1 92; CHECK-NEXT: .int8 0 # No further actions 93; CHECK-NEXT: .int8 2 # >> Action Record 2 << 94; CHECK-NEXT: # Catch TypeInfo 2 95; CHECK-NEXT: .int8 125 # Continue to action 1 96; CHECK-NEXT: .int8 3 # >> Action Record 3 << 97; CHECK-NEXT: # Catch TypeInfo 3 98; CHECK-NEXT: .int8 125 # Continue to action 2 99; CHECK-NEXT: .int8 4 # >> Action Record 4 << 100; CHECK-NEXT: # Catch TypeInfo 4 101; CHECK-NEXT: .int8 125 # Continue to action 3 102; CHECK-NEXT: .int8 3 # >> Action Record 5 << 103; CHECK-NEXT: # Catch TypeInfo 3 104; CHECK-NEXT: .int8 0 # No further actions 105; CHECK-NEXT: .int8 4 # >> Action Record 6 << 106; CHECK-NEXT: # Catch TypeInfo 4 107; CHECK-NEXT: .int8 125 # Continue to action 5 108; CHECK-NEXT: .p2align 2 109; CHECK-NEXT: # >> Catch TypeInfos << 110; CHECK-NEXT: .int32 _ZTIi # TypeInfo 4 111; CHECK-NEXT: .int32 _ZTIf # TypeInfo 3 112; CHECK-NEXT: .int32 _ZTId # TypeInfo 2 113; CHECK-NEXT: .int32 0 # TypeInfo 1 114; CHECK-NEXT: .Lttbase0: 115; CHECK-NEXT: .p2align 2 116; CHECK-NEXT: .LGCC_except_table_end[[END:[0-9]+]]: 117; CHECK-NEXT: .size GCC_except_table[[START]], .LGCC_except_table_end[[END]]-GCC_except_table[[START]] 118define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { 119entry: 120 invoke void @may_throw() 121 to label %try.cont unwind label %catch.dispatch 122 123catch.dispatch: ; preds = %entry 124 %0 = catchswitch within none [label %catch.start] unwind to caller 125 126catch.start: ; preds = %catch.dispatch 127 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTIf to i8*), i8* bitcast (i8** @_ZTId to i8*), i8* null] 128 %2 = call i8* @llvm.wasm.get.exception(token %1) 129 %3 = call i32 @llvm.wasm.get.ehselector(token %1) 130 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 131 %matches = icmp eq i32 %3, %4 132 br i1 %matches, label %catch10, label %catch.fallthrough 133 134catch10: ; preds = %catch.start 135 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ] 136 %6 = bitcast i8* %5 to i32* 137 %7 = load i32, i32* %6, align 4 138 call void @__cxa_end_catch() [ "funclet"(token %1) ] 139 catchret from %1 to label %try.cont 140 141try.cont: ; preds = %entry, %catch, %catch4, %catch7, %catch10 142 invoke void @may_throw() 143 to label %try.cont23 unwind label %catch.dispatch14 144 145catch.dispatch14: ; preds = %try.cont 146 %8 = catchswitch within none [label %catch.start15] unwind to caller 147 148catch.start15: ; preds = %catch.dispatch14 149 %9 = catchpad within %8 [i8* bitcast (i8** @_ZTId to i8*), i8* null] 150 %10 = call i8* @llvm.wasm.get.exception(token %9) 151 %11 = call i32 @llvm.wasm.get.ehselector(token %9) 152 %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) 153 %matches16 = icmp eq i32 %11, %12 154 %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ] 155 br i1 %matches16, label %catch20, label %catch17 156 157catch20: ; preds = %catch.start15 158 %14 = bitcast i8* %13 to double* 159 %15 = load double, double* %14, align 8 160 call void @__cxa_end_catch() [ "funclet"(token %9) ] 161 catchret from %9 to label %try.cont23 162 163try.cont23: ; preds = %try.cont, %catch17, %catch20 164 invoke void @may_throw() 165 to label %try.cont36 unwind label %catch.dispatch25 166 167catch.dispatch25: ; preds = %try.cont23 168 %16 = catchswitch within none [label %catch.start26] unwind to caller 169 170catch.start26: ; preds = %catch.dispatch25 171 %17 = catchpad within %16 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTIf to i8*)] 172 %18 = call i8* @llvm.wasm.get.exception(token %17) 173 %19 = call i32 @llvm.wasm.get.ehselector(token %17) 174 %20 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 175 %matches27 = icmp eq i32 %19, %20 176 br i1 %matches27, label %catch33, label %catch.fallthrough28 177 178catch33: ; preds = %catch.start26 179 %21 = call i8* @__cxa_begin_catch(i8* %18) [ "funclet"(token %17) ] 180 %22 = bitcast i8* %21 to i32* 181 %23 = load i32, i32* %22, align 4 182 call void @__cxa_end_catch() [ "funclet"(token %17) ] 183 catchret from %17 to label %try.cont36 184 185catch.fallthrough28: ; preds = %catch.start26 186 %24 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIf to i8*)) 187 %matches29 = icmp eq i32 %19, %24 188 br i1 %matches29, label %catch30, label %rethrow 189 190catch30: ; preds = %catch.fallthrough28 191 %25 = call i8* @__cxa_begin_catch(i8* %18) [ "funclet"(token %17) ] 192 %26 = bitcast i8* %25 to float* 193 %27 = load float, float* %26, align 4 194 call void @__cxa_end_catch() [ "funclet"(token %17) ] 195 catchret from %17 to label %try.cont36 196 197rethrow: ; preds = %catch.fallthrough28 198 call void @__cxa_rethrow() [ "funclet"(token %17) ] 199 unreachable 200 201try.cont36: ; preds = %try.cont23, %catch30, %catch33 202 ret void 203 204catch17: ; preds = %catch.start15 205 call void @__cxa_end_catch() [ "funclet"(token %9) ] 206 catchret from %9 to label %try.cont23 207 208catch.fallthrough: ; preds = %catch.start 209 %28 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIf to i8*)) 210 %matches1 = icmp eq i32 %3, %28 211 br i1 %matches1, label %catch7, label %catch.fallthrough2 212 213catch7: ; preds = %catch.fallthrough 214 %29 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ] 215 %30 = bitcast i8* %29 to float* 216 %31 = load float, float* %30, align 4 217 call void @__cxa_end_catch() [ "funclet"(token %1) ] 218 catchret from %1 to label %try.cont 219 220catch.fallthrough2: ; preds = %catch.fallthrough 221 %32 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) 222 %matches3 = icmp eq i32 %3, %32 223 %33 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ] 224 br i1 %matches3, label %catch4, label %catch 225 226catch4: ; preds = %catch.fallthrough2 227 %34 = bitcast i8* %33 to double* 228 %35 = load double, double* %34, align 8 229 call void @__cxa_end_catch() [ "funclet"(token %1) ] 230 catchret from %1 to label %try.cont 231 232catch: ; preds = %catch.fallthrough2 233 call void @__cxa_end_catch() [ "funclet"(token %1) ] 234 catchret from %1 to label %try.cont 235} 236 237declare void @may_throw() 238declare i32 @llvm.eh.typeid.for(i8*) 239declare i8* @llvm.wasm.get.exception(token) 240declare i32 @llvm.wasm.get.ehselector(token) 241declare void @__cxa_rethrow() 242declare i8* @__cxa_begin_catch(i8*) 243declare void @__cxa_end_catch() 244declare i32 @__gxx_wasm_personality_v0(...) 245