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