1;; Test `call_indirect` operator 2 3(module 4 ;; Auxiliary definitions 5 (type $proc (func)) 6 (type $out-i32 (func (result i32))) 7 (type $out-i64 (func (result i64))) 8 (type $out-f32 (func (result f32))) 9 (type $out-f64 (func (result f64))) 10 (type $over-i32 (func (param i32) (result i32))) 11 (type $over-i64 (func (param i64) (result i64))) 12 (type $over-f32 (func (param f32) (result f32))) 13 (type $over-f64 (func (param f64) (result f64))) 14 (type $f32-i32 (func (param f32 i32) (result i32))) 15 (type $i32-i64 (func (param i32 i64) (result i64))) 16 (type $f64-f32 (func (param f64 f32) (result f32))) 17 (type $i64-f64 (func (param i64 f64) (result f64))) 18 (type $over-i32-duplicate (func (param i32) (result i32))) 19 (type $over-i64-duplicate (func (param i64) (result i64))) 20 (type $over-f32-duplicate (func (param f32) (result f32))) 21 (type $over-f64-duplicate (func (param f64) (result f64))) 22 23 (func $const-i32 (type $out-i32) (i32.const 0x132)) 24 (func $const-i64 (type $out-i64) (i64.const 0x164)) 25 (func $const-f32 (type $out-f32) (f32.const 0xf32)) 26 (func $const-f64 (type $out-f64) (f64.const 0xf64)) 27 28 (func $id-i32 (type $over-i32) (get_local 0)) 29 (func $id-i64 (type $over-i64) (get_local 0)) 30 (func $id-f32 (type $over-f32) (get_local 0)) 31 (func $id-f64 (type $over-f64) (get_local 0)) 32 33 (func $i32-i64 (type $i32-i64) (get_local 1)) 34 (func $i64-f64 (type $i64-f64) (get_local 1)) 35 (func $f32-i32 (type $f32-i32) (get_local 1)) 36 (func $f64-f32 (type $f64-f32) (get_local 1)) 37 38 (func $over-i32-duplicate (type $over-i32-duplicate) (get_local 0)) 39 (func $over-i64-duplicate (type $over-i64-duplicate) (get_local 0)) 40 (func $over-f32-duplicate (type $over-f32-duplicate) (get_local 0)) 41 (func $over-f64-duplicate (type $over-f64-duplicate) (get_local 0)) 42 43 (table anyfunc 44 (elem 45 $const-i32 $const-i64 $const-f32 $const-f64 46 $id-i32 $id-i64 $id-f32 $id-f64 47 $f32-i32 $i32-i64 $f64-f32 $i64-f64 48 $fac $fib $even $odd 49 $runaway $mutual-runaway1 $mutual-runaway2 50 $over-i32-duplicate $over-i64-duplicate 51 $over-f32-duplicate $over-f64-duplicate 52 ) 53 ) 54 55 ;; Typing 56 57 (func (export "type-i32") (result i32) (call_indirect $out-i32 (i32.const 0))) 58 (func (export "type-i64") (result i64) (call_indirect $out-i64 (i32.const 1))) 59 (func (export "type-f32") (result f32) (call_indirect $out-f32 (i32.const 2))) 60 (func (export "type-f64") (result f64) (call_indirect $out-f64 (i32.const 3))) 61 62 (func (export "type-index") (result i64) 63 (call_indirect $over-i64 (i64.const 100) (i32.const 5)) 64 ) 65 66 (func (export "type-first-i32") (result i32) 67 (call_indirect $over-i32 (i32.const 32) (i32.const 4)) 68 ) 69 (func (export "type-first-i64") (result i64) 70 (call_indirect $over-i64 (i64.const 64) (i32.const 5)) 71 ) 72 (func (export "type-first-f32") (result f32) 73 (call_indirect $over-f32 (f32.const 1.32) (i32.const 6)) 74 ) 75 (func (export "type-first-f64") (result f64) 76 (call_indirect $over-f64 (f64.const 1.64) (i32.const 7)) 77 ) 78 79 (func (export "type-second-i32") (result i32) 80 (call_indirect $f32-i32 (f32.const 32.1) (i32.const 32) (i32.const 8)) 81 ) 82 (func (export "type-second-i64") (result i64) 83 (call_indirect $i32-i64 (i32.const 32) (i64.const 64) (i32.const 9)) 84 ) 85 (func (export "type-second-f32") (result f32) 86 (call_indirect $f64-f32 (f64.const 64) (f32.const 32) (i32.const 10)) 87 ) 88 (func (export "type-second-f64") (result f64) 89 (call_indirect $i64-f64 (i64.const 64) (f64.const 64.1) (i32.const 11)) 90 ) 91 92 ;; Dispatch 93 94 (func (export "dispatch") (param i32 i64) (result i64) 95 (call_indirect $over-i64 (get_local 1) (get_local 0)) 96 ) 97 98 (func (export "dispatch-structural") (param i32) (result i64) 99 (call_indirect $over-i64-duplicate (i64.const 9) (get_local 0)) 100 ) 101 102 ;; Recursion 103 104 (func $fac (export "fac") (type $over-i64) 105 (if i64 (i64.eqz (get_local 0)) 106 (i64.const 1) 107 (i64.mul 108 (get_local 0) 109 (call_indirect $over-i64 110 (i64.sub (get_local 0) (i64.const 1)) 111 (i32.const 12) 112 ) 113 ) 114 ) 115 ) 116 117 (func $fib (export "fib") (type $over-i64) 118 (if i64 (i64.le_u (get_local 0) (i64.const 1)) 119 (i64.const 1) 120 (i64.add 121 (call_indirect $over-i64 122 (i64.sub (get_local 0) (i64.const 2)) 123 (i32.const 13) 124 ) 125 (call_indirect $over-i64 126 (i64.sub (get_local 0) (i64.const 1)) 127 (i32.const 13) 128 ) 129 ) 130 ) 131 ) 132 133 (func $even (export "even") (param i32) (result i32) 134 (if i32 (i32.eqz (get_local 0)) 135 (i32.const 44) 136 (call_indirect $over-i32 137 (i32.sub (get_local 0) (i32.const 1)) 138 (i32.const 15) 139 ) 140 ) 141 ) 142 (func $odd (export "odd") (param i32) (result i32) 143 (if i32 (i32.eqz (get_local 0)) 144 (i32.const 99) 145 (call_indirect $over-i32 146 (i32.sub (get_local 0) (i32.const 1)) 147 (i32.const 14) 148 ) 149 ) 150 ) 151 152 ;; Stack exhaustion 153 154 ;; Implementations are required to have every call consume some abstract 155 ;; resource towards exhausting some abstract finite limit, such that 156 ;; infinitely recursive test cases reliably trap in finite time. This is 157 ;; because otherwise applications could come to depend on it on those 158 ;; implementations and be incompatible with implementations that don't do 159 ;; it (or don't do it under the same circumstances). 160 161 (func $runaway (export "runaway") (call_indirect $proc (i32.const 16))) 162 163 (func $mutual-runaway1 (export "mutual-runaway") (call_indirect $proc (i32.const 18))) 164 (func $mutual-runaway2 (call_indirect $proc (i32.const 17))) 165) 166 167(assert_return (invoke "type-i32") (i32.const 0x132)) 168(assert_return (invoke "type-i64") (i64.const 0x164)) 169(assert_return (invoke "type-f32") (f32.const 0xf32)) 170(assert_return (invoke "type-f64") (f64.const 0xf64)) 171 172(assert_return (invoke "type-index") (i64.const 100)) 173 174(assert_return (invoke "type-first-i32") (i32.const 32)) 175(assert_return (invoke "type-first-i64") (i64.const 64)) 176(assert_return (invoke "type-first-f32") (f32.const 1.32)) 177(assert_return (invoke "type-first-f64") (f64.const 1.64)) 178 179(assert_return (invoke "type-second-i32") (i32.const 32)) 180(assert_return (invoke "type-second-i64") (i64.const 64)) 181(assert_return (invoke "type-second-f32") (f32.const 32)) 182(assert_return (invoke "type-second-f64") (f64.const 64.1)) 183 184(assert_return (invoke "dispatch" (i32.const 5) (i64.const 2)) (i64.const 2)) 185(assert_return (invoke "dispatch" (i32.const 5) (i64.const 5)) (i64.const 5)) 186(assert_return (invoke "dispatch" (i32.const 12) (i64.const 5)) (i64.const 120)) 187(assert_return (invoke "dispatch" (i32.const 13) (i64.const 5)) (i64.const 8)) 188(assert_return (invoke "dispatch" (i32.const 20) (i64.const 2)) (i64.const 2)) 189(assert_trap (invoke "dispatch" (i32.const 0) (i64.const 2)) "indirect call signature mismatch") 190(assert_trap (invoke "dispatch" (i32.const 15) (i64.const 2)) "indirect call signature mismatch") 191(assert_trap (invoke "dispatch" (i32.const 23) (i64.const 2)) "undefined element") 192(assert_trap (invoke "dispatch" (i32.const -1) (i64.const 2)) "undefined element") 193(assert_trap (invoke "dispatch" (i32.const 1213432423) (i64.const 2)) "undefined element") 194 195(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9)) 196(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9)) 197(assert_return (invoke "dispatch-structural" (i32.const 12)) (i64.const 362880)) 198(assert_return (invoke "dispatch-structural" (i32.const 20)) (i64.const 9)) 199(assert_trap (invoke "dispatch-structural" (i32.const 11)) "indirect call signature mismatch") 200(assert_trap (invoke "dispatch-structural" (i32.const 22)) "indirect call signature mismatch") 201 202(assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) 203(assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) 204(assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) 205(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) 206 207(assert_return (invoke "fib" (i64.const 0)) (i64.const 1)) 208(assert_return (invoke "fib" (i64.const 1)) (i64.const 1)) 209(assert_return (invoke "fib" (i64.const 2)) (i64.const 2)) 210(assert_return (invoke "fib" (i64.const 5)) (i64.const 8)) 211(assert_return (invoke "fib" (i64.const 20)) (i64.const 10946)) 212 213(assert_return (invoke "even" (i32.const 0)) (i32.const 44)) 214(assert_return (invoke "even" (i32.const 1)) (i32.const 99)) 215(assert_return (invoke "even" (i32.const 100)) (i32.const 44)) 216(assert_return (invoke "even" (i32.const 77)) (i32.const 99)) 217(assert_return (invoke "odd" (i32.const 0)) (i32.const 99)) 218(assert_return (invoke "odd" (i32.const 1)) (i32.const 44)) 219(assert_return (invoke "odd" (i32.const 200)) (i32.const 99)) 220(assert_return (invoke "odd" (i32.const 77)) (i32.const 44)) 221 222(assert_trap (invoke "runaway") "call stack exhausted") 223(assert_trap (invoke "mutual-runaway") "call stack exhausted") 224 225 226;; Invalid typing 227 228(assert_invalid 229 (module 230 (type (func)) 231 (func $no-table (call_indirect 0 (i32.const 0))) 232 ) 233 "unknown table" 234) 235 236(assert_invalid 237 (module 238 (type (func)) 239 (table 0 anyfunc) 240 (func $type-void-vs-num (i32.eqz (call_indirect 0 (i32.const 0)))) 241 ) 242 "type mismatch" 243) 244(assert_invalid 245 (module 246 (type (func (result i64))) 247 (table 0 anyfunc) 248 (func $type-num-vs-num (i32.eqz (call_indirect 0 (i32.const 0)))) 249 ) 250 "type mismatch" 251) 252 253(assert_invalid 254 (module 255 (type (func (param i32))) 256 (table 0 anyfunc) 257 (func $arity-0-vs-1 (call_indirect 0 (i32.const 0))) 258 ) 259 "type mismatch" 260) 261(assert_invalid 262 (module 263 (type (func (param f64 i32))) 264 (table 0 anyfunc) 265 (func $arity-0-vs-2 (call_indirect 0 (i32.const 0))) 266 ) 267 "type mismatch" 268) 269(assert_invalid 270 (module 271 (type (func)) 272 (table 0 anyfunc) 273 (func $arity-1-vs-0 (call_indirect 0 (i32.const 1) (i32.const 0))) 274 ) 275 "type mismatch" 276) 277(assert_invalid 278 (module 279 (type (func)) 280 (table 0 anyfunc) 281 (func $arity-2-vs-0 282 (call_indirect 0 (f64.const 2) (i32.const 1) (i32.const 0)) 283 ) 284 ) 285 "type mismatch" 286) 287 288(assert_invalid 289 (module 290 (type (func (param i32))) 291 (table 0 anyfunc) 292 (func $type-func-void-vs-i32 (call_indirect 0 (i32.const 1) (nop))) 293 ) 294 "type mismatch" 295) 296(assert_invalid 297 (module 298 (type (func (param i32))) 299 (table 0 anyfunc) 300 (func $type-func-num-vs-i32 (call_indirect 0 (i32.const 0) (i64.const 1))) 301 ) 302 "type mismatch" 303) 304 305(assert_invalid 306 (module 307 (type (func (param i32 i32))) 308 (table 0 anyfunc) 309 (func $type-first-void-vs-num 310 (call_indirect 0 (nop) (i32.const 1) (i32.const 0)) 311 ) 312 ) 313 "type mismatch" 314) 315(assert_invalid 316 (module 317 (type (func (param i32 i32))) 318 (table 0 anyfunc) 319 (func $type-second-void-vs-num 320 (call_indirect 0 (i32.const 1) (nop) (i32.const 0)) 321 ) 322 ) 323 "type mismatch" 324) 325(assert_invalid 326 (module 327 (type (func (param i32 f64))) 328 (table 0 anyfunc) 329 (func $type-first-num-vs-num 330 (call_indirect 0 (f64.const 1) (i32.const 1) (i32.const 0)) 331 ) 332 ) 333 "type mismatch" 334) 335(assert_invalid 336 (module 337 (type (func (param f64 i32))) 338 (table 0 anyfunc) 339 (func $type-second-num-vs-num 340 (call_indirect 0 (i32.const 1) (f64.const 1) (i32.const 0)) 341 ) 342 ) 343 "type mismatch" 344) 345 346 347;; Unbound type 348 349(assert_invalid 350 (module 351 (table 0 anyfunc) 352 (func $unbound-type (call_indirect 1 (i32.const 0))) 353 ) 354 "unknown type" 355) 356(assert_invalid 357 (module 358 (table 0 anyfunc) 359 (func $large-type (call_indirect 1012321300 (i32.const 0))) 360 ) 361 "unknown type" 362) 363