control-flow.js (27516B)
1 const RuntimeError = WebAssembly.RuntimeError; 2 3 // ---------------------------------------------------------------------------- 4 // if 5 6 // Condition is an int32 7 wasmFailValidateText('(module (func (local f32) (if (local.get 0) (then (i32.const 1)))))', mismatchError("f32", "i32")); 8 wasmFailValidateText('(module (func (local f32) (if (local.get 0) (then (i32.const 1)) (else (i32.const 0)))))', mismatchError("f32", "i32")); 9 wasmFailValidateText('(module (func (local f64) (if (local.get 0) (then (i32.const 1)) (else (i32.const 0)))))', mismatchError("f64", "i32")); 10 wasmEvalText('(module (func (local i32) (if (local.get 0) (then (nop)))) (export "" (func 0)))'); 11 wasmEvalText('(module (func (local i32) (if (local.get 0) (then (nop)) (else (nop)))) (export "" (func 0)))'); 12 13 // Expression values types are consistent 14 // Also test that we support (result t) for `if` 15 wasmFailValidateText('(module (func (result i32) (local f32) (if (result f32) (i32.const 42) (then (local.get 0)) (else (i32.const 0)))))', mismatchError("i32", "f32")); 16 wasmFailValidateText('(module (func (result i32) (local f64) (if (result i32) (i32.const 42) (then (i32.const 0)) (else (local.get 0)))))', mismatchError("f64", "i32")); 17 wasmFailValidateText('(module (func (result i64) (if (result i64) (i32.const 0) (then (i32.const 1)) (else (i32.const 2)))))', mismatchError("i32", "i64")); 18 assertEq(wasmEvalText('(module (func (result i32) (if (result i32) (i32.const 42) (then (i32.const 1)) (else (i32.const 2)))) (export "" (func 0)))').exports[""](), 1); 19 assertEq(wasmEvalText('(module (func (result i32) (if (result i32) (i32.const 0) (then (i32.const 1)) (else (i32.const 2)))) (export "" (func 0)))').exports[""](), 2); 20 21 // Even if we don't yield, sub expressions types still have to match. 22 wasmFailValidateText('(module (func (param f32) (if (result i32) (i32.const 42) (then (i32.const 1)) (else (local.get 0)))) (export "" (func 0)))', mismatchError('f32', 'i32')); 23 wasmFailValidateText('(module (func (if (result i32) (i32.const 42) (then (i32.const 1)) (else (i32.const 0)))) (export "" (func 0)))', /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/); 24 wasmFullPass('(module (func (drop (if (result i32) (i32.const 42) (then (i32.const 1)) (else (i32.const 0))))) (export "run" (func 0)))', undefined); 25 wasmFullPass('(module (func (param f32) (if (i32.const 42) (then (drop (i32.const 1))) (else (drop (local.get 0))))) (export "run" (func 0)))', undefined, {}, 13.37); 26 27 // Sub-expression values are returned 28 // Also test that we support (result t) for `block` 29 wasmFullPass(`(module 30 (func 31 (result i32) 32 (if (result i32) 33 (i32.const 42) 34 (then 35 (block (result i32) 36 (if (result i32) 37 (block (result i32) 38 (drop (i32.const 3)) 39 (drop (i32.const 5)) 40 (i32.const 0) 41 ) 42 (then (i32.const 1)) 43 (else (i32.const 2)) 44 ) 45 ) 46 ) 47 (else (i32.const 0)) 48 ) 49 ) 50 (export "run" (func 0)) 51 )`, 2); 52 53 // The if (resp. else) branch is taken iff the condition is true (resp. false) 54 counter = 0; 55 var imports = { "":{inc() { counter++ }} }; 56 wasmFullPass(`(module 57 (import "" "inc" (func (result i32))) 58 (func 59 (result i32) 60 (if (result i32) 61 (i32.const 42) 62 (then (i32.const 1)) 63 (else (call 0)) 64 ) 65 ) 66 (export "run" (func 1)) 67 )`, 1, imports); 68 assertEq(counter, 0); 69 70 wasmFullPass(`(module 71 (import "" "inc" (func (result i32))) 72 (func 73 (result i32) 74 (if (result i32) 75 (i32.const 0) 76 (then (call 0)) 77 (else (i32.const 1)) 78 ) 79 ) 80 (export "run" (func 1)) 81 )`, 1, imports); 82 assertEq(counter, 0); 83 84 wasmFullPass(`(module 85 (import "" "inc" (func (result i32))) 86 (func 87 (if 88 (i32.const 0) 89 (then (drop (call 0))) 90 ) 91 ) 92 (export "run" (func 1)) 93 )`, undefined, imports); 94 assertEq(counter, 0); 95 96 assertEq(wasmEvalText(`(module 97 (import "" "inc" (func (result i32))) 98 (func 99 (if 100 (i32.const 1) 101 (then (drop (call 0))) 102 ) 103 ) 104 (export "" (func 1)) 105 )`, imports).exports[""](), undefined); 106 assertEq(counter, 1); 107 108 wasmFullPass(`(module 109 (func 110 (result i32) 111 (if (result i32) 112 (i32.const 0) 113 (then (br 0 (i32.const 0))) 114 (else (br 0 (i32.const 1))) 115 ) 116 ) 117 (export "run" (func 0)) 118 )`, 1); 119 assertEq(counter, 1); 120 121 wasmFullPass(`(module 122 (func 123 (if 124 (i32.const 1) 125 (then (br 0)) 126 ) 127 ) 128 (export "run" (func 0)) 129 )`, undefined); 130 assertEq(counter, 1); 131 132 // One can chain if with if/if 133 counter = 0; 134 wasmFullPass(`(module 135 (import "" "inc" (func (result i32))) 136 (func 137 (result i32) 138 (if (result i32) 139 (i32.const 1) 140 (then 141 (if (result i32) 142 (i32.const 2) 143 (then 144 (if (result i32) 145 (i32.const 3) 146 (then 147 (if (result i32) 148 (i32.const 0) 149 (then (call 0)) 150 (else (i32.const 42)) 151 ) 152 ) 153 (else (call 0)) 154 ) 155 ) 156 (else (call 0)) 157 ) 158 ) 159 (else (call 0)) 160 ) 161 ) 162 (export "run" (func 1)) 163 )`, 42, imports); 164 assertEq(counter, 0); 165 166 // "if" doesn't return an expression value 167 wasmFailValidateText('(module (func (result i32) (if (result i32) (i32.const 42) (then (i32.const 0)))))', /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/); 168 wasmFailValidateText('(module (func (result i32) (if (result i32) (i32.const 42) (then (drop (i32.const 0))))))', emptyStackError); 169 wasmFailValidateText('(module (func (result i32) (if (result i32) (i32.const 1) (then (i32.const 0)) (else (if (result i32) (i32.const 1) (then (i32.const 1)))))))', /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/); 170 wasmFailValidateText('(module (func (result i32) (if (result i32) (i32.const 1) (then (drop (i32.const 0))) (else (if (i32.const 1) (then (drop (i32.const 1))))))))', emptyStackError); 171 wasmFailValidateText('(module (func (if (result i32) (i32.const 1) (then (i32.const 0)) (else (if (result i32) (i32.const 1) (then (i32.const 1)))))))', /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/); 172 wasmFailValidateText('(module (func (if (result i32) (i32.const 1) (then (i32.const 0)) (else (if (i32.const 1) (then (drop (i32.const 1))))))))', emptyStackError); 173 wasmFailValidateText('(module (func (if (i32.const 1) (then (drop (i32.const 0))) (else (if (result i32) (i32.const 1) (then (i32.const 1)))))))', /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/); 174 wasmEvalText('(module (func (if (i32.const 1) (then (drop (i32.const 0))) (else (if (i32.const 1) (then (drop (i32.const 1))))))))'); 175 176 // ---------------------------------------------------------------------------- 177 // return 178 179 wasmFullPass('(module (func (return)) (export "run" (func 0)))', undefined); 180 wasmFullPass('(module (func (result i32) (return (i32.const 1))) (export "run" (func 0)))', 1); 181 wasmFailValidateText('(module (func (if (return) (then (i32.const 0)))) (export "run" (func 0)))', unusedValuesError); 182 wasmFailValidateText('(module (func (result i32) (return)) (export "" (func 0)))', emptyStackError); 183 wasmFullPass('(module (func (return (i32.const 1))) (export "run" (func 0)))', undefined); 184 wasmFailValidateText('(module (func (result f32) (return (i32.const 1))) (export "" (func 0)))', mismatchError("i32", "f32")); 185 wasmFailValidateText('(module (func (result i32) (return)) (export "" (func 0)))', emptyStackError); 186 187 // ---------------------------------------------------------------------------- 188 // br / br_if 189 190 wasmFailValidateText('(module (func (result i32) (block (br 0))) (export "" (func 0)))', emptyStackError); 191 wasmFailValidateText('(module (func (result i32) (br 0)) (export "" (func 0)))', emptyStackError); 192 wasmFailValidateText('(module (func (result i32) (block (br_if 0 (i32.const 0)))) (export "" (func 0)))', emptyStackError); 193 194 const DEPTH_OUT_OF_BOUNDS = /(branch depth exceeds current nesting level)|(branch depth too large)/; 195 196 wasmFailValidateText('(module (func (br 1)))', DEPTH_OUT_OF_BOUNDS); 197 wasmFailValidateText('(module (func (block (br 2))))', DEPTH_OUT_OF_BOUNDS); 198 wasmFailValidateText('(module (func (loop (br 2))))', DEPTH_OUT_OF_BOUNDS); 199 wasmFailValidateText('(module (func (if (i32.const 0) (then (br 2)))))', DEPTH_OUT_OF_BOUNDS); 200 wasmFailValidateText('(module (func (if (i32.const 0) (then (br 1)) (else (br 2)))))', DEPTH_OUT_OF_BOUNDS); 201 wasmFailValidateText('(module (func (if (i32.const 0) (then (br 2)) (else (br 1)))))', DEPTH_OUT_OF_BOUNDS); 202 203 wasmFailValidateText('(module (func (br_if 1 (i32.const 0))))', DEPTH_OUT_OF_BOUNDS); 204 wasmFailValidateText('(module (func (block (br_if 2 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS); 205 wasmFailValidateText('(module (func (loop (br_if 2 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS); 206 207 wasmFailValidateText(`(module (func (result i32) 208 block 209 br 0 210 if 211 i32.const 0 212 i32.const 2 213 end 214 end 215 ) (export "" (func 0)))`, unusedValuesError); 216 217 wasmFullPass(`(module (func (block $out (br_if $out (br 0)))) (export "run" (func 0)))`, undefined); 218 219 wasmFullPass('(module (func (br 0)) (export "run" (func 0)))', undefined); 220 wasmFullPass('(module (func (block (br 0))) (export "run" (func 0)))', undefined); 221 wasmFullPass('(module (func (block $l (br $l))) (export "run" (func 0)))', undefined); 222 223 wasmFullPass('(module (func (block (block (br 1)))) (export "run" (func 0)))', undefined); 224 wasmFullPass('(module (func (block $l (block (br $l)))) (export "run" (func 0)))', undefined); 225 226 wasmFullPass('(module (func (block $l (block $m (br $l)))) (export "run" (func 0)))', undefined); 227 wasmFullPass('(module (func (block $l (block $m (br $m)))) (export "run" (func 0)))', undefined); 228 229 wasmFullPass(`(module (func (result i32) 230 (block 231 (br 0) 232 (return (i32.const 0)) 233 ) 234 (return (i32.const 1)) 235 ) (export "run" (func 0)))`, 1); 236 237 wasmFullPass(`(module (func (result i32) 238 (block 239 (block 240 (br 0) 241 (return (i32.const 0)) 242 ) 243 (return (i32.const 1)) 244 ) 245 (return (i32.const 2)) 246 ) (export "run" (func 0)))`, 1); 247 248 wasmFullPass(`(module (func (result i32) 249 (block $outer 250 (block $inner 251 (br $inner) 252 (return (i32.const 0)) 253 ) 254 (return (i32.const 1)) 255 ) 256 (return (i32.const 2)) 257 ) (export "run" (func 0)))`, 1); 258 259 var notcalled = false; 260 var called = false; 261 var imports = {"": { 262 notcalled() {notcalled = true}, 263 called() {called = true} 264 }}; 265 wasmFullPass(`(module 266 (import "" "notcalled" (func)) 267 (import "" "called" (func)) 268 (func 269 (block 270 (return (br 0)) 271 (call 0) 272 ) 273 (call 1) 274 ) (export "run" (func 2)))`, undefined, imports); 275 assertEq(notcalled, false); 276 assertEq(called, true); 277 278 wasmFullPass(`(module (func 279 (block 280 (i32.add 281 (i32.const 0) 282 (return (br 0)) 283 ) 284 drop 285 ) 286 (return) 287 ) (export "run" (func 0)))`, undefined); 288 289 wasmFullPass(`(module (func (result i32) 290 (block 291 (if 292 (i32.const 1) 293 (then (br 0)) 294 (else (return (i32.const 0))) 295 ) 296 ) 297 (return (i32.const 1)) 298 ) (export "run" (func 0)))`, 1); 299 300 wasmFullPass('(module (func (br_if 0 (i32.const 1))) (export "run" (func 0)))', undefined); 301 wasmFullPass('(module (func (br_if 0 (i32.const 0))) (export "run" (func 0)))', undefined); 302 wasmFullPass('(module (func (block (br_if 0 (i32.const 1)))) (export "run" (func 0)))', undefined); 303 wasmFullPass('(module (func (block (br_if 0 (i32.const 0)))) (export "run" (func 0)))', undefined); 304 wasmFullPass('(module (func (block $l (br_if $l (i32.const 1)))) (export "run" (func 0)))', undefined); 305 306 var isNonZero = wasmEvalText(`(module (func (param i32) (result i32) 307 (block 308 (br_if 0 (local.get 0)) 309 (return (i32.const 0)) 310 ) 311 (return (i32.const 1)) 312 ) (export "" (func 0)))`).exports[""]; 313 314 assertEq(isNonZero(0), 0); 315 assertEq(isNonZero(1), 1); 316 assertEq(isNonZero(-1), 1); 317 318 // branches with values 319 // br/br_if and block 320 wasmFailValidateText('(module (func (result i32) (br 0)))', emptyStackError); 321 wasmFailValidateText('(module (func (result i32) (br 0 (f32.const 42))))', mismatchError("f32", "i32")); 322 wasmFailValidateText('(module (func (result i32) (block (br 0))))', emptyStackError); 323 wasmFailValidateText('(module (func (result i32) (block (result f32) (br 0 (f32.const 42)))))', mismatchError("f32", "i32")); 324 325 wasmFailValidateText(`(module (func (param i32) (result i32) (block (if (result i32) (local.get 0) (then (br 0 (i32.const 42)))))) (export "" (func 0)))`, /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/); 326 wasmFailValidateText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (drop (i32.const 42)))) (else (br 0 (f32.const 42))))) (export "" (func 0)))`, mismatchError("f32", "i32")); 327 328 wasmFullPass('(module (func (result i32) (br 0 (i32.const 42)) (i32.const 13)) (export "run" (func 0)))', 42); 329 wasmFullPass('(module (func (result i32) (block (result i32) (br 0 (i32.const 42)) (i32.const 13))) (export "run" (func 0)))', 42); 330 331 wasmFailValidateText('(module (func) (func (block (result i32) (br 0 (call 0)) (i32.const 13))) (export "" (func 0)))', emptyStackError); 332 wasmFailValidateText('(module (func) (func (block (result i32) (br_if 0 (call 0) (i32.const 1)) (i32.const 13))) (export "" (func 0)))', emptyStackError); 333 334 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (drop (i32.const 42)))) (i32.const 43))) (export "" (func 0)))`).exports[""]; 335 assertEq(f(0), 43); 336 assertEq(f(1), 43); 337 338 wasmFailValidateText(`(module (func (param i32) (result i32) (block (result i32) (if (result i32) (local.get 0) (then (br 0 (i32.const 42)))) (i32.const 43))) (export "" (func 0)))`, /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/); 339 340 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (br 1 (i32.const 42)))) (i32.const 43))) (export "" (func 0)))`).exports[""]; 341 assertEq(f(0), 43); 342 assertEq(f(1), 42); 343 344 wasmFailValidateText(`(module (func (param i32) (result i32) (block (br_if 0 (i32.const 42) (local.get 0)) (i32.const 43))) (export "" (func 0)))`, /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/); 345 346 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (drop (br_if 0 (i32.const 42) (local.get 0))) (i32.const 43))) (export "" (func 0)))`).exports[""]; 347 assertEq(f(0), 43); 348 assertEq(f(1), 42); 349 350 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (drop (i32.const 42)))) (br 0 (i32.const 43)))) (export "" (func 0)))`).exports[""]; 351 assertEq(f(0), 43); 352 assertEq(f(1), 43); 353 354 wasmFailValidateText(`(module (func (param i32) (result i32) (block (result i32) (if (result i32) (local.get 0) (then (br 0 (i32.const 42)))) (br 0 (i32.const 43)))) (export "" (func 0)))`, /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/); 355 356 var f = wasmEvalText(`(module (func (param i32) (result i32) (if (local.get 0) (then (br 1 (i32.const 42)))) (br 0 (i32.const 43))) (export "" (func 0)))`).exports[""]; 357 assertEq(f(0), 43); 358 assertEq(f(1), 42); 359 360 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (br 1 (i32.const 42)))) (br 0 (i32.const 43)))) (export "" (func 0)))`).exports[""]; 361 assertEq(f(0), 43); 362 assertEq(f(1), 42); 363 364 var f = wasmEvalText(`(module (func (param i32) (result i32) (br_if 0 (i32.const 42) (local.get 0)) (br 0 (i32.const 43))) (export "" (func 0)))`).exports[""]; 365 assertEq(f(0), 43); 366 assertEq(f(1), 42); 367 368 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (br_if 0 (i32.const 42) (local.get 0)) (br 0 (i32.const 43)))) (export "" (func 0)))`).exports[""]; 369 assertEq(f(0), 43); 370 assertEq(f(1), 42); 371 372 var f = wasmEvalText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (result i32) (if (local.get 0) (then (drop (i32.const 99)))) (i32.const -1)))) (export "" (func 0)))`).exports[""]; 373 assertEq(f(0), 0); 374 assertEq(f(1), 0); 375 376 wasmFailValidateText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (result i32) (if (result i32) (local.get 0) (then (br 0 (i32.const 99)))) (i32.const -1)))) (export "" (func 0)))`, /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/); 377 378 var f = wasmEvalText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (result i32) (if (local.get 0) (then (br 1 (i32.const 99)))) (i32.const -1)))) (export "" (func 0)))`).exports[""]; 379 assertEq(f(0), 0); 380 assertEq(f(1), 100); 381 382 wasmFailValidateText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (br_if 0 (i32.const 99) (local.get 0)) (i32.const -1)))) (export "" (func 0)))`, /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/); 383 384 var f = wasmEvalText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (result i32) (drop (br_if 0 (i32.const 99) (local.get 0))) (i32.const -1)))) (export "" (func 0)))`).exports[""]; 385 assertEq(f(0), 0); 386 assertEq(f(1), 100); 387 388 wasmFullPass(`(module (func (result i32) (block (result i32) (br 0 (return (i32.const 42))) (i32.const 0))) (export "run" (func 0)))`, 42); 389 wasmFullPass(`(module (func (result i32) (block (result i32) (return (br 0 (i32.const 42))))) (export "run" (func 0)))`, 42); 390 wasmFullPass(`(module (func (result i32) (block (result i32) (return (br 0 (i32.const 42))) (i32.const 0))) (export "run" (func 0)))`, 42); 391 392 wasmFullPass(`(module (func (result f32) (drop (block (result i32) (br 0 (i32.const 0)))) (block (result f32) (br 0 (f32.const 42)))) (export "run" (func 0)))`, 42); 393 394 var called = 0; 395 var imports = { 396 sideEffects: { 397 ifTrue(x) {assertEq(x, 13); called++;}, 398 ifFalse(x) {assertEq(x, 37); called--;} 399 } 400 } 401 var f = wasmEvalText(`(module 402 (import "sideEffects" "ifTrue" (func (param i32))) 403 (import "sideEffects" "ifFalse" (func (param i32))) 404 (func 405 (param i32) (result i32) 406 (block $outer 407 (if 408 (local.get 0) 409 (then (block (call 0 (i32.const 13)) (br $outer))) 410 ) 411 (if 412 (i32.eqz (local.get 0)) 413 (then (block (call 1 (i32.const 37)) (br $outer))) 414 ) 415 ) 416 (i32.const 42) 417 ) 418 (export "" (func 2)))`, imports).exports[""]; 419 assertEq(f(0), 42); 420 assertEq(called, -1); 421 assertEq(f(1), 42); 422 assertEq(called, 0); 423 424 // br/br_if and loop 425 wasmFullPass(`(module (func (param i32) (result i32) (block $out (result i32) (loop $in (result i32) (br $out (local.get 0))))) (export "run" (func 0)))`, 1, {}, 1); 426 wasmFullPass(`(module (func (param i32) (result i32) (loop $in (result i32) (br 1 (local.get 0)))) (export "run" (func 0)))`, 1, {}, 1); 427 wasmFullPass(`(module (func (param i32) (result i32) (block $out (result i32) (loop $in (result i32) (br $out (local.get 0))))) (export "run" (func 0)))`, 1, {}, 1); 428 429 wasmFailValidateText(`(module (func (param i32) (result i32) 430 (block $out 431 (loop $in 432 (if (local.get 0) (then (br $in (i32.const 1)))) 433 (if (local.get 0) (then (br $in (f32.const 2)))) 434 (if (local.get 0) (then (br $in (f64.const 3)))) 435 (if (local.get 0) (then (br $in))) 436 (i32.const 7) 437 ) 438 ) 439 ) (export "" (func 0)))`, /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/); 440 441 wasmFullPass(`(module 442 (func 443 (result i32) 444 (local i32) 445 (block $out (result i32) 446 (loop $in (result i32) 447 (local.set 0 (i32.add (local.get 0) (i32.const 1))) 448 (if 449 (i32.ge_s (local.get 0) (i32.const 7)) 450 (then (br $out (local.get 0))) 451 ) 452 (br $in) 453 ) 454 ) 455 ) 456 (export "run" (func 0)))`, 7); 457 458 wasmFullPass(`(module 459 (func 460 (result i32) 461 (local i32) 462 (block $out (result i32) 463 (loop $in (result i32) 464 (local.set 0 (i32.add (local.get 0) (i32.const 1))) 465 (br_if $out (local.get 0) (i32.ge_s (local.get 0) (i32.const 7))) 466 (br $in) 467 ) 468 ) 469 ) 470 (export "run" (func 0)))`, 7); 471 472 // ---------------------------------------------------------------------------- 473 // loop 474 475 wasmFailValidateText('(module (func (loop (br 2))))', DEPTH_OUT_OF_BOUNDS); 476 477 wasmFailValidateText('(module (func (result i32) (drop (loop (i32.const 2))) (i32.const 1)) (export "" (func 0)))', /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/); 478 wasmFullPass('(module (func (loop)) (export "run" (func 0)))', undefined); 479 wasmFullPass('(module (func (result i32) (loop (drop (i32.const 2))) (i32.const 1)) (export "run" (func 0)))', 1); 480 481 wasmFullPass('(module (func (loop (br 1))) (export "run" (func 0)))', undefined); 482 wasmFullPass('(module (func (loop $a (br 1))) (export "run" (func 0)))', undefined); 483 wasmFullPass('(module (func (loop $a (br_if $a (i32.const 0)))) (export "run" (func 0)))', undefined); 484 wasmFullPass('(module (func (block $a (loop $b (br $a)))) (export "run" (func 0)))', undefined); 485 wasmFullPass('(module (func (result i32) (loop (result i32) (i32.const 1))) (export "run" (func 0)))', 1); 486 487 wasmFullPass(`(module (func (result i32) (local i32) 488 (block 489 $break 490 (loop 491 $continue 492 (if 493 (i32.gt_u (local.get 0) (i32.const 5)) 494 (then (br $break)) 495 ) 496 (local.set 0 (i32.add (local.get 0) (i32.const 1))) 497 (br $continue) 498 ) 499 ) 500 (return (local.get 0)) 501 ) (export "run" (func 0)))`, 6); 502 503 wasmFullPass(`(module (func (result i32) (local i32) 504 (block 505 $break 506 (loop 507 $continue 508 (br_if 509 $break 510 (i32.gt_u (local.get 0) (i32.const 5)) 511 ) 512 (local.set 0 (i32.add (local.get 0) (i32.const 1))) 513 (br $continue) 514 ) 515 ) 516 (return (local.get 0)) 517 ) (export "run" (func 0)))`, 6); 518 519 wasmFullPass(`(module (func (result i32) (local i32) 520 (block 521 $break 522 (loop 523 $continue 524 (local.set 0 (i32.add (local.get 0) (i32.const 1))) 525 (br_if 526 $continue 527 (i32.le_u (local.get 0) (i32.const 5)) 528 ) 529 ) 530 ) 531 (return (local.get 0)) 532 ) (export "run" (func 0)))`, 6); 533 534 wasmFullPass(`(module (func (result i32) (local i32) 535 (block 536 $break 537 (loop 538 $continue 539 (br_if 540 $break 541 (i32.gt_u (local.get 0) (i32.const 5)) 542 ) 543 (local.set 0 (i32.add (local.get 0) (i32.const 1))) 544 (loop 545 (br $continue) 546 ) 547 (return (i32.const 42)) 548 ) 549 ) 550 (return (local.get 0)) 551 ) (export "run" (func 0)))`, 6); 552 553 wasmFullPass(`(module (func (result i32) (local i32) 554 (block 555 $break 556 (loop 557 $continue 558 (local.set 0 (i32.add (local.get 0) (i32.const 1))) 559 (loop 560 (br_if 561 $continue 562 (i32.le_u (local.get 0) (i32.const 5)) 563 ) 564 ) 565 (br $break) 566 ) 567 ) 568 (return (local.get 0)) 569 ) (export "run" (func 0)))`, 6); 570 571 // ---------------------------------------------------------------------------- 572 // br_table 573 574 wasmFailValidateText('(module (func (br_table 1 (i32.const 0))))', DEPTH_OUT_OF_BOUNDS); 575 wasmFailValidateText('(module (func (br_table 1 0 (i32.const 0))))', DEPTH_OUT_OF_BOUNDS); 576 wasmFailValidateText('(module (func (br_table 0 1 (i32.const 0))))', DEPTH_OUT_OF_BOUNDS); 577 wasmFailValidateText('(module (func (block (br_table 2 0 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS); 578 wasmFailValidateText('(module (func (block (br_table 0 2 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS); 579 wasmFailValidateText('(module (func (block (br_table 0 (f32.const 0)))))', mismatchError("f32", "i32")); 580 wasmFailValidateText('(module (func (loop (br_table 2 0 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS); 581 wasmFailValidateText('(module (func (loop (br_table 0 2 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS); 582 wasmFailValidateText('(module (func (loop (br_table 0 (f32.const 0)))))', mismatchError("f32", "i32")); 583 584 wasmFullPass(`(module (func (param i32) (result i32) 585 (block $default 586 (br_table $default (local.get 0)) 587 (return (i32.const 0)) 588 ) 589 (return (i32.const 1)) 590 ) (export "run" (func 0)))`, 1); 591 592 wasmFullPass(`(module (func (param i32) (result i32) 593 (block $default 594 (br_table $default (return (i32.const 1))) 595 (return (i32.const 0)) 596 ) 597 (return (i32.const 2)) 598 ) (export "run" (func 0)))`, 1); 599 600 wasmFullPass(`(module (func (param i32) (result i32) 601 (block $outer 602 (block $inner 603 (br_table $inner (local.get 0)) 604 (return (i32.const 0)) 605 ) 606 (return (i32.const 1)) 607 ) 608 (return (i32.const 2)) 609 ) (export "run" (func 0)))`, 1); 610 611 var f = wasmEvalText(`(module (func (param i32) (result i32) 612 (block $0 613 (block $1 614 (block $2 615 (block $default 616 (br_table $0 $1 $2 $default (local.get 0)) 617 ) 618 (return (i32.const -1)) 619 ) 620 (return (i32.const 2)) 621 ) 622 ) 623 (return (i32.const 0)) 624 ) (export "" (func 0)))`).exports[""]; 625 626 assertEq(f(-2), -1); 627 assertEq(f(-1), -1); 628 assertEq(f(0), 0); 629 assertEq(f(1), 0); 630 assertEq(f(2), 2); 631 assertEq(f(3), -1); 632 633 // br_table with values 634 wasmFailValidateText('(module (func (result i32) (block (result i32) (br_table 0 (i32.const 0)))))', emptyStackError); 635 wasmFailValidateText('(module (func (result i32) (block (result i32) (br_table 0 (f32.const 0) (i32.const 0)))))', mismatchError("f32", "i32")); 636 637 wasmFailValidateText(`(module 638 (func 639 (result i32) 640 (block $outer (result f32) 641 (block $inner (result f32) 642 (br_table $outer $inner (f32.const 13.37) (i32.const 1)) 643 ) 644 (br $outer (i32.const 42)) 645 ) 646 ) 647 (export "" (func 0)))`, mismatchError("i32", "f32")); 648 649 wasmFullPass(`(module (func (result i32) (block $default (result i32) (br_table $default (i32.const 42) (i32.const 1)))) (export "run" (func 0)))`, 42); 650 651 var f = wasmEvalText(`(module (func (param i32) (result i32) 652 (i32.add 653 (block $1 (result i32) 654 (drop (block $0 (result i32) 655 (drop (block $default (result i32) 656 (br_table $0 $1 $default (local.get 0) (local.get 0)) 657 )) 658 (local.tee 0 (i32.mul (i32.const 2) (local.get 0))) 659 )) 660 (local.tee 0 (i32.add (i32.const 4) (local.get 0))) 661 ) 662 (i32.const 1) 663 ) 664 ) (export "" (func 0)))`).exports[""]; 665 666 assertEq(f(0), 5); 667 assertEq(f(1), 2); 668 assertEq(f(2), 9); 669 assertEq(f(3), 11); 670 assertEq(f(4), 13); 671 672 // ---------------------------------------------------------------------------- 673 // unreachable 674 675 const UNREACHABLE = /unreachable/; 676 assertErrorMessage(wasmEvalText(`(module (func (unreachable)) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE); 677 assertErrorMessage(wasmEvalText(`(module (func (if (unreachable) (then (nop)))) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE); 678 assertErrorMessage(wasmEvalText(`(module (func (block (br_if 0 (unreachable)))) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE); 679 assertErrorMessage(wasmEvalText(`(module (func (block (br_table 0 (unreachable)))) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE); 680 assertErrorMessage(wasmEvalText(`(module (func (result i32) (i32.add (i32.const 0) (unreachable))) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE);