1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
|
# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+exception-handling < %s | FileCheck %s
# Check that it converts to .o without errors, but don't check any output:
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+exception-handling -o %t.o < %s
.tagtype __cpp_exception i32
.tagtype __c_longjmp i32
.functype foo () -> ()
eh_test:
.functype eh_test (exnref) -> ()
# try_table with all four kinds of catch clauses
block exnref
block
block () -> (i32, exnref)
block i32
try_table (catch __cpp_exception 0) (catch_ref __c_longjmp 1) (catch_all 2) (catch_all_ref 3)
i32.const 0
throw __cpp_exception
end_try_table
return
end_block
drop
return
end_block
throw_ref
end_block
return
end_block
drop
# You can use the same kind of catch clause more than once
block
block exnref
block
try_table (catch_all 0) (catch_all_ref 1) (catch_all 2)
call foo
end_try_table
end_block
return
end_block
drop
end_block
# Two catch clauses targeting the same block
block
try_table (catch_all 0) (catch_all 0)
end_try_table
end_block
# try_table with a return type
block
try_table f32 (catch_all 0)
f32.const 0.0
end_try_table
drop
end_block
# try_table with a multivalue type return
block
try_table () -> (i32, f32) (catch_all 0)
i32.const 0
f32.const 0.0
end_try_table
drop
drop
end_block
# catch-less try_tables
try_table
call foo
end_try_table
try_table i32
i32.const 0
end_try_table
drop
try_table () -> (i32, f32)
i32.const 0
f32.const 0.0
end_try_table
drop
drop
# try_table targeting loops
i32.const 0
loop (i32) -> ()
local.get 0
loop (exnref) -> ()
try_table (catch __cpp_exception 1) (catch_all_ref 0)
end_try_table
drop
end_loop
drop
end_loop
end_function
eh_legacy_test:
.functype eh_legacy_test () -> ()
# try-catch with catch, catch_all, throw, and rethrow
try
i32.const 3
throw __cpp_exception
catch __cpp_exception
drop
rethrow 0
catch __c_longjmp
drop
catch_all
rethrow 0
end_try
# Nested try-catch with a rethrow
try
call foo
catch_all
try
catch_all
rethrow 1
end_try
end_try
# try-catch with a single return value
try i32
i32.const 0
catch __cpp_exception
end_try
drop
# try-catch with a mulvivalue return
try () -> (i32, f32)
i32.const 0
f32.const 0.0
catch __cpp_exception
f32.const 1.0
end_try
drop
drop
# Catch-less try
try
call foo
end_try
end_function
# CHECK-LABEL: eh_test:
# CHECK: block exnref
# CHECK-NEXT: block
# CHECK-NEXT: block () -> (i32, exnref)
# CHECK-NEXT: block i32
# CHECK-NEXT: try_table (catch __cpp_exception 0) (catch_ref __c_longjmp 1) (catch_all 2) (catch_all_ref 3)
# CHECK: i32.const 0
# CHECK-NEXT: throw __cpp_exception
# CHECK-NEXT: end_try_table
# CHECK-NEXT: return
# CHECK-NEXT: end_block
# CHECK-NEXT: drop
# CHECK-NEXT: return
# CHECK-NEXT: end_block
# CHECK-NEXT: throw_ref
# CHECK-NEXT: end_block
# CHECK-NEXT: return
# CHECK-NEXT: end_block
# CHECK-NEXT: drop
# CHECK: block
# CHECK-NEXT: block exnref
# CHECK-NEXT: block
# CHECK-NEXT: try_table (catch_all 0) (catch_all_ref 1) (catch_all 2)
# CHECK: call foo
# CHECK-NEXT: end_try_table
# CHECK-NEXT: end_block
# CHECK-NEXT: return
# CHECK-NEXT: end_block
# CHECK-NEXT: drop
# CHECK-NEXT: end_block
# CHECK: block
# CHECK-NEXT: try_table (catch_all 0) (catch_all 0)
# CHECK: end_try_table
# CHECK-NEXT: end_block
# CHECK: block
# CHECK-NEXT: try_table f32 (catch_all 0)
# CHECK: f32.const 0x0p0
# CHECK-NEXT: end_try_table
# CHECK-NEXT: drop
# CHECK-NEXT: end_block
# CHECK: block
# CHECK-NEXT: try_table () -> (i32, f32) (catch_all 0)
# CHECK: i32.const 0
# CHECK-NEXT: f32.const 0x0p0
# CHECK-NEXT: end_try_table
# CHECK-NEXT: drop
# CHECK-NEXT: drop
# CHECK-NEXT: end_block
# CHECK: try_table
# CHECK-NEXT: call foo
# CHECK-NEXT: end_try_table
# CHECK: try_table i32
# CHECK-NEXT: i32.const 0
# CHECK-NEXT: end_try_table
# CHECK-NEXT: drop
# CHECK: try_table () -> (i32, f32)
# CHECK-NEXT: i32.const 0
# CHECK-NEXT: f32.const 0x0p0
# CHECK-NEXT: end_try_table
# CHECK-NEXT: drop
# CHECK-NEXT: drop
# CHECK: i32.const 0
# CHECK-NEXT: loop (i32) -> ()
# CHECK-NEXT: local.get 0
# CHECK-NEXT: loop (exnref) -> ()
# CHECK-NEXT: try_table (catch __cpp_exception 1) (catch_all_ref 0)
# CHECK: end_try_table
# CHECK-NEXT: drop
# CHECK-NEXT: end_loop
# CHECK-NEXT: drop
# CHECK-NEXT: end_loop
# CHECK: eh_legacy_test:
# CHECK: try
# CHECK-NEXT: i32.const 3
# CHECK-NEXT: throw __cpp_exception
# CHECK-NEXT: catch __cpp_exception
# CHECK-NEXT: drop
# CHECK-NEXT: rethrow 0
# CHECK-NEXT: catch __c_longjmp
# CHECK-NEXT: drop
# CHECK-NEXT: catch_all
# CHECK-NEXT: rethrow 0
# CHECK-NEXT: end_try
# CHECK: try
# CHECK-NEXT: call foo
# CHECK-NEXT: catch_all
# CHECK-NEXT: try
# CHECK-NEXT: catch_all
# CHECK-NEXT: rethrow 1
# CHECK-NEXT: end_try
# CHECK-NEXT: end_try
# CHECK: try i32
# CHECK-NEXT: i32.const 0
# CHECK-NEXT: catch __cpp_exception
# CHECK-NEXT: end_try
# CHECK-NEXT: drop
# CHECK: try () -> (i32, f32)
# CHECK-NEXT: i32.const 0
# CHECK-NEXT: f32.const 0x0p0
# CHECK-NEXT: catch __cpp_exception
# CHECK-NEXT: f32.const 0x1p0
# CHECK-NEXT: end_try
# CHECK-NEXT: drop
# CHECK-NEXT: drop
# CHECK: try
# CHECK-NEXT: call foo
# CHECK-NEXT: end_try
|