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