1 use std::sync::Arc; 2 use std::sync::atomic::Ordering; 3 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst}; 4 use wasmtime::bail; 5 use wasmtime::*; 6 use wasmtime_test_macros::wasmtime_test; 7 8 #[wasmtime_test] 9 #[cfg_attr(miri, ignore)] 10 fn call_wasm_to_wasm(config: &mut Config) -> Result<()> { 11 let wasm = wat::parse_str( 12 r#" 13 (module 14 (func (result i32 i32 i32) 15 i32.const 1 16 i32.const 2 17 i32.const 3 18 ) 19 (func (export "run") (result i32 i32 i32) 20 call 0 21 ) 22 ) 23 "#, 24 )?; 25 let engine = Engine::new(&config)?; 26 let mut store = Store::<()>::new(&engine, ()); 27 let module = Module::new(store.engine(), &wasm)?; 28 let instance = Instance::new(&mut store, &module, &[])?; 29 let func = instance 30 .get_typed_func::<(), (i32, i32, i32)>(&mut store, "run") 31 .unwrap(); 32 let results = func.call(&mut store, ())?; 33 assert_eq!(results, (1, 2, 3)); 34 Ok(()) 35 } 36 37 #[wasmtime_test] 38 #[cfg_attr(miri, ignore)] 39 fn call_wasm_to_native(config: &mut Config) -> Result<()> { 40 let wasm = wat::parse_str( 41 r#" 42 (module 43 (import "" "" (func (result i32 i32 i32))) 44 (func (export "run") (result i32 i32 i32) 45 call 0 46 ) 47 ) 48 "#, 49 )?; 50 let engine = Engine::new(&config)?; 51 let mut store = Store::<()>::new(&engine, ()); 52 let module = Module::new(store.engine(), &wasm)?; 53 let import_func = Func::wrap(&mut store, || (1_i32, 2_i32, 3_i32)); 54 let instance = Instance::new(&mut store, &module, &[import_func.into()])?; 55 let func = instance 56 .get_typed_func::<(), (i32, i32, i32)>(&mut store, "run") 57 .unwrap(); 58 let results = func.call(&mut store, ())?; 59 assert_eq!(results, (1, 2, 3)); 60 Ok(()) 61 } 62 63 #[wasmtime_test] 64 #[cfg_attr(miri, ignore)] 65 fn call_wasm_to_array(config: &mut Config) -> Result<()> { 66 let wasm = wat::parse_str( 67 r#" 68 (module 69 (import "" "" (func (result i32 i32 i32))) 70 (func (export "run") (result i32 i32 i32) 71 call 0 72 ) 73 ) 74 "#, 75 )?; 76 let engine = Engine::new(&config)?; 77 let mut store = Store::<()>::new(&engine, ()); 78 let module = Module::new(store.engine(), &wasm)?; 79 let func_ty = FuncType::new( 80 store.engine(), 81 vec![], 82 vec![ValType::I32, ValType::I32, ValType::I32], 83 ); 84 let import_func = Func::new(&mut store, func_ty, |_, _params, results| { 85 results[0] = Val::I32(1); 86 results[1] = Val::I32(2); 87 results[2] = Val::I32(3); 88 Ok(()) 89 }); 90 let instance = Instance::new(&mut store, &module, &[import_func.into()])?; 91 let func = instance 92 .get_typed_func::<(), (i32, i32, i32)>(&mut store, "run") 93 .unwrap(); 94 let results = func.call(&mut store, ())?; 95 assert_eq!(results, (1, 2, 3)); 96 Ok(()) 97 } 98 99 #[wasmtime_test] 100 #[cfg_attr(miri, ignore)] 101 fn call_native_to_wasm(config: &mut Config) -> Result<()> { 102 let wasm = wat::parse_str( 103 r#" 104 (module 105 (func (export "run") (result i32 i32 i32) 106 i32.const 42 107 i32.const 420 108 i32.const 4200 109 ) 110 ) 111 "#, 112 )?; 113 let engine = Engine::new(&config)?; 114 let mut store = Store::<()>::new(&engine, ()); 115 let module = Module::new(store.engine(), &wasm)?; 116 let instance = Instance::new(&mut store, &module, &[])?; 117 let func = instance 118 .get_typed_func::<(), (i32, i32, i32)>(&mut store, "run") 119 .unwrap(); 120 let results = func.call(&mut store, ())?; 121 assert_eq!(results, (42, 420, 4200)); 122 Ok(()) 123 } 124 125 #[test] 126 fn call_native_to_native() -> Result<()> { 127 let mut store = Store::<()>::default(); 128 129 let func = Func::wrap(&mut store, |a: i32, b: i32, c: i32| -> (i32, i32, i32) { 130 (b, c, a) 131 }); 132 let func = func.typed::<(i32, i32, i32), (i32, i32, i32)>(&store)?; 133 let results = func.call(&mut store, (1, 2, 3))?; 134 assert_eq!(results, (2, 3, 1)); 135 Ok(()) 136 } 137 138 #[test] 139 #[cfg_attr(miri, ignore)] 140 fn call_native_to_array() -> Result<()> { 141 let mut store = Store::<()>::default(); 142 143 let func_ty = FuncType::new( 144 store.engine(), 145 [ValType::I32, ValType::I32, ValType::I32], 146 [ValType::I32, ValType::I32, ValType::I32], 147 ); 148 let func = Func::new(&mut store, func_ty, |_caller, params, results| { 149 results[0] = params[2]; 150 results[1] = params[0]; 151 results[2] = params[1]; 152 Ok(()) 153 }); 154 let func = func.typed::<(i32, i32, i32), (i32, i32, i32)>(&store)?; 155 let results = func.call(&mut store, (1, 2, 3))?; 156 assert_eq!(results, (3, 1, 2)); 157 Ok(()) 158 } 159 160 #[wasmtime_test] 161 #[cfg_attr(miri, ignore)] 162 fn call_array_to_wasm(config: &mut Config) -> Result<()> { 163 let wasm = wat::parse_str( 164 r#" 165 (module 166 (func (export "run") (param i32 i32 i32) (result i32 i32 i32) 167 local.get 1 168 local.get 2 169 local.get 0 170 ) 171 ) 172 "#, 173 )?; 174 let engine = Engine::new(&config)?; 175 let mut store = Store::<()>::new(&engine, ()); 176 let module = Module::new(store.engine(), &wasm)?; 177 let instance = Instance::new(&mut store, &module, &[])?; 178 let func = instance.get_func(&mut store, "run").unwrap(); 179 let mut results = [Val::I32(0), Val::I32(0), Val::I32(0)]; 180 func.call( 181 &mut store, 182 &[Val::I32(10), Val::I32(20), Val::I32(30)], 183 &mut results, 184 )?; 185 assert_eq!(results[0].i32(), Some(20)); 186 assert_eq!(results[1].i32(), Some(30)); 187 assert_eq!(results[2].i32(), Some(10)); 188 Ok(()) 189 } 190 191 #[test] 192 fn call_array_to_native() -> Result<()> { 193 let mut store = Store::<()>::default(); 194 let func = Func::wrap(&mut store, |a: i32, b: i32, c: i32| -> (i32, i32, i32) { 195 (a * 10, b * 10, c * 10) 196 }); 197 let mut results = [Val::I32(0), Val::I32(0), Val::I32(0)]; 198 func.call( 199 &mut store, 200 &[Val::I32(10), Val::I32(20), Val::I32(30)], 201 &mut results, 202 )?; 203 assert_eq!(results[0].i32(), Some(100)); 204 assert_eq!(results[1].i32(), Some(200)); 205 assert_eq!(results[2].i32(), Some(300)); 206 Ok(()) 207 } 208 209 #[test] 210 #[cfg_attr(miri, ignore)] 211 fn call_array_to_array() -> Result<()> { 212 let mut store = Store::<()>::default(); 213 let func_ty = FuncType::new( 214 store.engine(), 215 [ValType::I32, ValType::I32, ValType::I32], 216 [ValType::I32, ValType::I32, ValType::I32], 217 ); 218 let func = Func::new(&mut store, func_ty, |_caller, params, results| { 219 results[0] = params[2]; 220 results[1] = params[0]; 221 results[2] = params[1]; 222 Ok(()) 223 }); 224 let mut results = [Val::I32(0), Val::I32(0), Val::I32(0)]; 225 func.call( 226 &mut store, 227 &[Val::I32(10), Val::I32(20), Val::I32(30)], 228 &mut results, 229 )?; 230 assert_eq!(results[0].i32(), Some(30)); 231 assert_eq!(results[1].i32(), Some(10)); 232 assert_eq!(results[2].i32(), Some(20)); 233 Ok(()) 234 } 235 236 #[wasmtime_test(wasm_features(reference_types))] 237 #[cfg_attr(miri, ignore)] 238 fn call_indirect_native_from_wasm_import_global(config: &mut Config) -> Result<()> { 239 let wasm = wat::parse_str( 240 r#" 241 (module 242 (import "" "" (global funcref)) 243 (table 1 1 funcref) 244 (func (export "run") (result i32 i32 i32) 245 i32.const 0 246 global.get 0 247 table.set 248 i32.const 0 249 call_indirect (result i32 i32 i32) 250 ) 251 ) 252 "#, 253 )?; 254 let engine = Engine::new(&config)?; 255 let mut store = Store::<()>::new(&engine, ()); 256 let module = Module::new(store.engine(), &wasm)?; 257 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) }); 258 let global = Global::new( 259 &mut store, 260 GlobalType::new(ValType::FUNCREF, Mutability::Const), 261 Val::FuncRef(Some(func)), 262 )?; 263 let instance = Instance::new(&mut store, &module, &[global.into()])?; 264 let func = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?; 265 let results = func.call(&mut store, ())?; 266 assert_eq!(results, (10, 20, 30)); 267 Ok(()) 268 } 269 270 #[wasmtime_test] 271 #[cfg_attr(miri, ignore)] 272 fn call_indirect_native_from_wasm_import_table(config: &mut Config) -> Result<()> { 273 let wasm = wat::parse_str( 274 r#" 275 (module 276 (import "" "" (table 1 1 funcref)) 277 (func (export "run") (result i32 i32 i32) 278 i32.const 0 279 call_indirect (result i32 i32 i32) 280 ) 281 ) 282 "#, 283 )?; 284 let engine = Engine::new(&config)?; 285 let mut store = Store::<()>::new(&engine, ()); 286 let module = Module::new(store.engine(), &wasm)?; 287 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) }); 288 let table = Table::new( 289 &mut store, 290 TableType::new(RefType::FUNCREF, 1, Some(1)), 291 Ref::Func(Some(func)), 292 )?; 293 let instance = Instance::new(&mut store, &module, &[table.into()])?; 294 let func = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?; 295 let results = func.call(&mut store, ())?; 296 assert_eq!(results, (10, 20, 30)); 297 Ok(()) 298 } 299 300 #[wasmtime_test(wasm_features(reference_types))] 301 #[cfg_attr(miri, ignore)] 302 fn call_indirect_native_from_wasm_import_func_returns_funcref(config: &mut Config) -> Result<()> { 303 let wasm = wat::parse_str( 304 r#" 305 (module 306 (import "" "" (func (result funcref))) 307 (table 1 1 funcref) 308 (func (export "run") (result i32 i32 i32) 309 i32.const 0 310 call 0 311 table.set 312 i32.const 0 313 call_indirect (result i32 i32 i32) 314 ) 315 ) 316 "#, 317 )?; 318 let engine = Engine::new(&config)?; 319 let mut store = Store::<()>::new(&engine, ()); 320 let module = Module::new(store.engine(), &wasm)?; 321 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) }); 322 let get_func = Func::wrap(&mut store, move || -> Option<Func> { Some(func) }); 323 let instance = Instance::new(&mut store, &module, &[get_func.into()])?; 324 let func = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?; 325 let results = func.call(&mut store, ())?; 326 assert_eq!(results, (10, 20, 30)); 327 Ok(()) 328 } 329 330 #[wasmtime_test] 331 #[cfg_attr(miri, ignore)] 332 fn call_indirect_native_from_exported_table(config: &mut Config) -> Result<()> { 333 let wasm = wat::parse_str( 334 r#" 335 (module 336 (table (export "table") 1 1 funcref) 337 (func (export "run") (result i32 i32 i32) 338 i32.const 0 339 call_indirect (result i32 i32 i32) 340 ) 341 ) 342 "#, 343 )?; 344 let engine = Engine::new(&config)?; 345 let mut store = Store::<()>::new(&engine, ()); 346 let module = Module::new(store.engine(), &wasm)?; 347 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) }); 348 let instance = Instance::new(&mut store, &module, &[])?; 349 let table = instance.get_table(&mut store, "table").unwrap(); 350 table.set(&mut store, 0, func.into())?; 351 let run = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?; 352 let results = run.call(&mut store, ())?; 353 assert_eq!(results, (10, 20, 30)); 354 Ok(()) 355 } 356 357 // wasm exports global, host puts native-call funcref in global, wasm calls funcref 358 #[wasmtime_test(wasm_features(reference_types))] 359 #[cfg_attr(miri, ignore)] 360 fn call_indirect_native_from_exported_global(config: &mut Config) -> Result<()> { 361 let wasm = wat::parse_str( 362 r#" 363 (module 364 (global (export "global") (mut funcref) (ref.null func)) 365 (table 1 1 funcref) 366 (func (export "run") (result i32 i32 i32) 367 i32.const 0 368 global.get 0 369 table.set 370 i32.const 0 371 call_indirect (result i32 i32 i32) 372 ) 373 ) 374 "#, 375 )?; 376 let engine = Engine::new(&config)?; 377 let mut store = Store::<()>::new(&engine, ()); 378 let module = Module::new(store.engine(), &wasm)?; 379 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) }); 380 let instance = Instance::new(&mut store, &module, &[])?; 381 let global = instance.get_global(&mut store, "global").unwrap(); 382 global.set(&mut store, func.into())?; 383 let run = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?; 384 let results = run.call(&mut store, ())?; 385 assert_eq!(results, (10, 20, 30)); 386 Ok(()) 387 } 388 389 #[test] 390 fn func_constructors() { 391 let mut store = Store::<()>::default(); 392 Func::wrap(&mut store, || {}); 393 Func::wrap(&mut store, |_: i32| {}); 394 Func::wrap(&mut store, |_: i32, _: i64| {}); 395 Func::wrap(&mut store, |_: f32, _: f64| {}); 396 Func::wrap(&mut store, || -> i32 { 0 }); 397 Func::wrap(&mut store, || -> i64 { 0 }); 398 Func::wrap(&mut store, || -> f32 { 0.0 }); 399 Func::wrap(&mut store, || -> f64 { 0.0 }); 400 Func::wrap(&mut store, || -> Rooted<ExternRef> { 401 loop {} 402 }); 403 Func::wrap(&mut store, || -> Option<Rooted<ExternRef>> { None }); 404 Func::wrap(&mut store, || -> OwnedRooted<ExternRef> { 405 loop {} 406 }); 407 Func::wrap(&mut store, || -> Option<OwnedRooted<ExternRef>> { None }); 408 Func::wrap(&mut store, || -> Rooted<AnyRef> { 409 loop {} 410 }); 411 Func::wrap(&mut store, || -> Option<Rooted<AnyRef>> { None }); 412 Func::wrap(&mut store, || -> OwnedRooted<AnyRef> { 413 loop {} 414 }); 415 Func::wrap(&mut store, || -> Option<OwnedRooted<AnyRef>> { None }); 416 Func::wrap(&mut store, || -> I31 { 417 loop {} 418 }); 419 Func::wrap(&mut store, || -> Option<I31> { None }); 420 Func::wrap(&mut store, || -> Func { 421 loop {} 422 }); 423 Func::wrap(&mut store, || -> Option<Func> { None }); 424 Func::wrap(&mut store, || -> NoFunc { 425 loop {} 426 }); 427 Func::wrap(&mut store, || -> Option<NoFunc> { None }); 428 Func::wrap(&mut store, || -> NoExtern { 429 loop {} 430 }); 431 Func::wrap(&mut store, || -> Option<NoExtern> { None }); 432 Func::wrap(&mut store, || -> NoneRef { 433 loop {} 434 }); 435 Func::wrap(&mut store, || -> Option<NoneRef> { None }); 436 437 Func::wrap(&mut store, || -> Result<()> { 438 loop {} 439 }); 440 Func::wrap(&mut store, || -> Result<i32> { 441 loop {} 442 }); 443 Func::wrap(&mut store, || -> Result<i64> { 444 loop {} 445 }); 446 Func::wrap(&mut store, || -> Result<f32> { 447 loop {} 448 }); 449 Func::wrap(&mut store, || -> Result<f64> { 450 loop {} 451 }); 452 Func::wrap(&mut store, || -> Result<Rooted<ExternRef>> { 453 loop {} 454 }); 455 Func::wrap(&mut store, || -> Result<Option<Rooted<ExternRef>>> { 456 loop {} 457 }); 458 Func::wrap(&mut store, || -> Result<OwnedRooted<ExternRef>> { 459 loop {} 460 }); 461 Func::wrap(&mut store, || -> Result<Option<OwnedRooted<ExternRef>>> { 462 loop {} 463 }); 464 Func::wrap(&mut store, || -> Result<Rooted<AnyRef>> { 465 loop {} 466 }); 467 Func::wrap(&mut store, || -> Result<Option<Rooted<AnyRef>>> { 468 loop {} 469 }); 470 Func::wrap(&mut store, || -> Result<OwnedRooted<AnyRef>> { 471 loop {} 472 }); 473 Func::wrap(&mut store, || -> Result<Option<OwnedRooted<AnyRef>>> { 474 loop {} 475 }); 476 Func::wrap(&mut store, || -> Result<I31> { 477 loop {} 478 }); 479 Func::wrap(&mut store, || -> Result<Option<I31>> { 480 loop {} 481 }); 482 Func::wrap(&mut store, || -> Result<Func> { 483 loop {} 484 }); 485 Func::wrap(&mut store, || -> Result<Option<Func>> { 486 loop {} 487 }); 488 Func::wrap(&mut store, || -> Result<NoFunc> { 489 loop {} 490 }); 491 Func::wrap(&mut store, || -> Result<Option<NoFunc>> { 492 loop {} 493 }); 494 Func::wrap(&mut store, || -> Result<NoExtern> { 495 loop {} 496 }); 497 Func::wrap(&mut store, || -> Result<Option<NoExtern>> { 498 loop {} 499 }); 500 Func::wrap(&mut store, || -> Result<NoneRef> { 501 loop {} 502 }); 503 Func::wrap(&mut store, || -> Result<Option<NoneRef>> { 504 loop {} 505 }); 506 } 507 508 #[test] 509 fn dtor_runs() { 510 static HITS: AtomicUsize = AtomicUsize::new(0); 511 512 struct A; 513 514 impl Drop for A { 515 fn drop(&mut self) { 516 HITS.fetch_add(1, SeqCst); 517 } 518 } 519 520 let mut store = Store::<()>::default(); 521 let a = A; 522 assert_eq!(HITS.load(SeqCst), 0); 523 Func::wrap(&mut store, move || { 524 let _ = &a; 525 }); 526 drop(store); 527 assert_eq!(HITS.load(SeqCst), 1); 528 } 529 530 #[test] 531 #[cfg_attr(miri, ignore)] 532 fn dtor_delayed() -> Result<()> { 533 static HITS: AtomicUsize = AtomicUsize::new(0); 534 535 struct A; 536 537 impl Drop for A { 538 fn drop(&mut self) { 539 HITS.fetch_add(1, SeqCst); 540 } 541 } 542 543 let mut store = Store::<()>::default(); 544 let a = A; 545 let func = Func::wrap(&mut store, move || { 546 let _ = &a; 547 }); 548 549 assert_eq!(HITS.load(SeqCst), 0); 550 let wasm = wat::parse_str(r#"(import "" "" (func))"#)?; 551 let module = Module::new(store.engine(), &wasm)?; 552 let _instance = Instance::new(&mut store, &module, &[func.into()])?; 553 assert_eq!(HITS.load(SeqCst), 0); 554 drop(store); 555 assert_eq!(HITS.load(SeqCst), 1); 556 Ok(()) 557 } 558 559 #[test] 560 fn signatures_match() { 561 let mut store = Store::<()>::default(); 562 563 let f = Func::wrap(&mut store, || {}); 564 assert_eq!(f.ty(&store).params().len(), 0); 565 assert_eq!(f.ty(&store).results().len(), 0); 566 567 let f = Func::wrap(&mut store, || -> i32 { 568 loop {} 569 }); 570 assert_eq!(f.ty(&store).params().len(), 0); 571 assert_eq!(f.ty(&store).results().len(), 1); 572 assert!(f.ty(&store).results().nth(0).unwrap().is_i32()); 573 574 let f = Func::wrap(&mut store, || -> i64 { 575 loop {} 576 }); 577 assert_eq!(f.ty(&store).params().len(), 0); 578 assert_eq!(f.ty(&store).results().len(), 1); 579 assert!(f.ty(&store).results().nth(0).unwrap().is_i64()); 580 581 let f = Func::wrap(&mut store, || -> f32 { 582 loop {} 583 }); 584 assert_eq!(f.ty(&store).params().len(), 0); 585 assert_eq!(f.ty(&store).results().len(), 1); 586 assert!(f.ty(&store).results().nth(0).unwrap().is_f32()); 587 588 let f = Func::wrap(&mut store, || -> f64 { 589 loop {} 590 }); 591 assert_eq!(f.ty(&store).params().len(), 0); 592 assert_eq!(f.ty(&store).results().len(), 1); 593 assert!(f.ty(&store).results().nth(0).unwrap().is_f64()); 594 595 let f = Func::wrap( 596 &mut store, 597 |_: f32, 598 _: f64, 599 _: i32, 600 _: i64, 601 _: i32, 602 _: Option<Rooted<ExternRef>>, 603 _: Option<OwnedRooted<ExternRef>>, 604 _: Option<Rooted<AnyRef>>, 605 _: Option<OwnedRooted<AnyRef>>, 606 _: Option<Func>| 607 -> f64 { loop {} }, 608 ); 609 610 assert_eq!(f.ty(&store).params().len(), 10); 611 assert!(f.ty(&store).params().nth(0).unwrap().is_f32()); 612 assert!(f.ty(&store).params().nth(1).unwrap().is_f64()); 613 assert!(f.ty(&store).params().nth(2).unwrap().is_i32()); 614 assert!(f.ty(&store).params().nth(3).unwrap().is_i64()); 615 assert!(f.ty(&store).params().nth(4).unwrap().is_i32()); 616 assert!(f.ty(&store).params().nth(5).unwrap().is_externref()); 617 assert!(f.ty(&store).params().nth(6).unwrap().is_externref()); 618 assert!(f.ty(&store).params().nth(7).unwrap().is_anyref()); 619 assert!(f.ty(&store).params().nth(8).unwrap().is_anyref()); 620 assert!(f.ty(&store).params().nth(9).unwrap().is_funcref()); 621 622 assert_eq!(f.ty(&store).results().len(), 1); 623 assert!(f.ty(&store).results().nth(0).unwrap().is_f64()); 624 } 625 626 #[test] 627 #[cfg_attr(miri, ignore)] 628 fn import_works() -> Result<()> { 629 let _ = env_logger::try_init(); 630 631 static HITS: AtomicUsize = AtomicUsize::new(0); 632 633 let wasm = wat::parse_str( 634 r#" 635 (import "" "" (func)) 636 (import "" "" (func (param i32) (result i32))) 637 (import "" "" (func (param i32) (param i64))) 638 (import "" "" (func (param i32 i64 i32 f32 f64 externref externref funcref anyref anyref i31ref))) 639 640 (func (export "run") (param externref externref funcref) 641 call 0 642 i32.const 0 643 call 1 644 i32.const 1 645 i32.add 646 i64.const 3 647 call 2 648 649 i32.const 100 650 i64.const 200 651 i32.const 300 652 f32.const 400 653 f64.const 500 654 local.get 0 655 local.get 1 656 local.get 2 657 (ref.i31 (i32.const 36)) 658 (ref.i31 (i32.const 42)) 659 (ref.i31 (i32.const 0x1234)) 660 call 3 661 ) 662 "#, 663 )?; 664 665 let mut config = Config::new(); 666 config.wasm_reference_types(true); 667 config.wasm_function_references(true); 668 config.wasm_gc(true); 669 670 let engine = Engine::new(&config)?; 671 let mut store = Store::new(&engine, ()); 672 let module = Module::new(&engine, &wasm)?; 673 674 let imports = [ 675 Func::wrap(&mut store, || { 676 assert_eq!(HITS.fetch_add(1, SeqCst), 0); 677 }) 678 .into(), 679 Func::wrap(&mut store, |x: i32| -> i32 { 680 assert_eq!(x, 0); 681 assert_eq!(HITS.fetch_add(1, SeqCst), 1); 682 1 683 }) 684 .into(), 685 Func::wrap(&mut store, |x: i32, y: i64| { 686 assert_eq!(x, 2); 687 assert_eq!(y, 3); 688 assert_eq!(HITS.fetch_add(1, SeqCst), 2); 689 }) 690 .into(), 691 Func::wrap( 692 &mut store, 693 |mut caller: Caller<'_, ()>, 694 a: i32, 695 b: i64, 696 c: i32, 697 d: f32, 698 e: f64, 699 f: Option<Rooted<ExternRef>>, 700 g: Option<OwnedRooted<ExternRef>>, 701 h: Option<Func>, 702 i: Option<Rooted<AnyRef>>, 703 j: Option<OwnedRooted<AnyRef>>, 704 k: Option<I31>| 705 -> Result<()> { 706 assert_eq!(a, 100); 707 assert_eq!(b, 200); 708 assert_eq!(c, 300); 709 assert_eq!(d, 400.0); 710 assert_eq!(e, 500.0); 711 assert_eq!( 712 f.as_ref() 713 .unwrap() 714 .data(&caller)? 715 .unwrap() 716 .downcast_ref::<String>() 717 .unwrap(), 718 "hello" 719 ); 720 assert_eq!( 721 g.as_ref() 722 .unwrap() 723 .data(&caller)? 724 .unwrap() 725 .downcast_ref::<String>() 726 .unwrap(), 727 "goodbye" 728 ); 729 assert_eq!( 730 i.unwrap().as_i31(&caller).unwrap().unwrap(), 731 I31::wrapping_u32(36) 732 ); 733 assert_eq!( 734 j.unwrap().as_i31(&caller).unwrap().unwrap(), 735 I31::wrapping_u32(42) 736 ); 737 assert_eq!(k, Some(I31::wrapping_u32(0x1234))); 738 let mut results = [Val::I32(0)]; 739 h.as_ref() 740 .unwrap() 741 .call(&mut caller, &[], &mut results) 742 .unwrap(); 743 assert_eq!(results[0].unwrap_i32(), 42); 744 assert_eq!(HITS.fetch_add(1, SeqCst), 3); 745 Ok(()) 746 }, 747 ) 748 .into(), 749 ]; 750 751 let instance = Instance::new(&mut store, &module, &imports)?; 752 let run = instance.get_func(&mut store, "run").unwrap(); 753 let hello = Val::ExternRef(Some(ExternRef::new(&mut store, "hello".to_string())?)); 754 let goodbye = Val::ExternRef(Some(ExternRef::new(&mut store, "goodbye".to_string())?)); 755 let funcref = Val::FuncRef(Some(Func::wrap(&mut store, || -> i32 { 42 }))); 756 run.call(&mut store, &[hello, goodbye, funcref], &mut [])?; 757 758 assert_eq!(HITS.load(SeqCst), 4); 759 Ok(()) 760 } 761 762 #[test] 763 #[cfg_attr(miri, ignore)] 764 fn trap_smoke() -> Result<()> { 765 let mut store = Store::<()>::default(); 766 let f = Func::wrap(&mut store, || -> Result<()> { bail!("test") }); 767 let err = f.call(&mut store, &[], &mut []).unwrap_err(); 768 assert!(err.to_string().contains("test")); 769 Ok(()) 770 } 771 772 #[wasmtime_test] 773 #[cfg_attr(miri, ignore)] 774 fn trap_import(config: &mut Config) -> Result<()> { 775 let wasm = wat::parse_str( 776 r#" 777 (import "" "" (func)) 778 (start 0) 779 "#, 780 )?; 781 let engine = Engine::new(&config)?; 782 let mut store = Store::<()>::new(&engine, ()); 783 let module = Module::new(store.engine(), &wasm)?; 784 let import = Func::wrap(&mut store, || -> Result<()> { bail!("foo") }); 785 let trap = Instance::new(&mut store, &module, &[import.into()]).unwrap_err(); 786 assert!(trap.to_string().contains("foo")); 787 Ok(()) 788 } 789 790 #[test] 791 fn get_from_wrapper() { 792 let mut store = Store::<()>::default(); 793 let f = Func::wrap(&mut store, || {}); 794 assert!(f.typed::<(), ()>(&store).is_ok()); 795 assert!(f.typed::<(), i32>(&store).is_err()); 796 assert!(f.typed::<(), ()>(&store).is_ok()); 797 assert!(f.typed::<i32, ()>(&store).is_err()); 798 assert!(f.typed::<i32, i32>(&store).is_err()); 799 assert!(f.typed::<(i32, i32), ()>(&store).is_err()); 800 assert!(f.typed::<(i32, i32), i32>(&store).is_err()); 801 802 let f = Func::wrap(&mut store, || -> i32 { 803 loop {} 804 }); 805 assert!(f.typed::<(), i32>(&store).is_ok()); 806 let f = Func::wrap(&mut store, || -> f32 { 807 loop {} 808 }); 809 assert!(f.typed::<(), f32>(&store).is_ok()); 810 let f = Func::wrap(&mut store, || -> f64 { 811 loop {} 812 }); 813 assert!(f.typed::<(), f64>(&store).is_ok()); 814 let f = Func::wrap(&mut store, || -> Rooted<ExternRef> { 815 loop {} 816 }); 817 assert!(f.typed::<(), Rooted<ExternRef>>(&store).is_ok()); 818 let f = Func::wrap(&mut store, || -> Option<Rooted<ExternRef>> { 819 loop {} 820 }); 821 assert!(f.typed::<(), Option<Rooted<ExternRef>>>(&store).is_ok()); 822 let f = Func::wrap(&mut store, || -> OwnedRooted<ExternRef> { 823 loop {} 824 }); 825 assert!(f.typed::<(), OwnedRooted<ExternRef>>(&store).is_ok()); 826 let f = Func::wrap(&mut store, || -> Option<OwnedRooted<ExternRef>> { 827 loop {} 828 }); 829 assert!( 830 f.typed::<(), Option<OwnedRooted<ExternRef>>>(&store) 831 .is_ok() 832 ); 833 let f = Func::wrap(&mut store, || -> Rooted<AnyRef> { 834 loop {} 835 }); 836 assert!(f.typed::<(), Rooted<AnyRef>>(&store).is_ok()); 837 let f = Func::wrap(&mut store, || -> Option<Rooted<AnyRef>> { 838 loop {} 839 }); 840 assert!(f.typed::<(), Option<Rooted<AnyRef>>>(&store).is_ok()); 841 let f = Func::wrap(&mut store, || -> OwnedRooted<AnyRef> { 842 loop {} 843 }); 844 assert!(f.typed::<(), OwnedRooted<AnyRef>>(&store).is_ok()); 845 let f = Func::wrap(&mut store, || -> Option<OwnedRooted<AnyRef>> { 846 loop {} 847 }); 848 assert!(f.typed::<(), Option<OwnedRooted<AnyRef>>>(&store).is_ok()); 849 let f = Func::wrap(&mut store, || -> I31 { 850 loop {} 851 }); 852 assert!(f.typed::<(), I31>(&store).is_ok()); 853 let f = Func::wrap(&mut store, || -> Option<I31> { 854 loop {} 855 }); 856 assert!(f.typed::<(), Option<I31>>(&store).is_ok()); 857 let f = Func::wrap(&mut store, || -> Func { 858 loop {} 859 }); 860 assert!(f.typed::<(), Func>(&store).is_ok()); 861 let f = Func::wrap(&mut store, || -> Option<Func> { 862 loop {} 863 }); 864 assert!(f.typed::<(), Option<Func>>(&store).is_ok()); 865 866 let f = Func::wrap(&mut store, |_: i32| {}); 867 assert!(f.typed::<i32, ()>(&store).is_ok()); 868 assert!(f.typed::<i64, ()>(&store).is_err()); 869 assert!(f.typed::<f32, ()>(&store).is_err()); 870 assert!(f.typed::<f64, ()>(&store).is_err()); 871 let f = Func::wrap(&mut store, |_: i64| {}); 872 assert!(f.typed::<i64, ()>(&store).is_ok()); 873 let f = Func::wrap(&mut store, |_: f32| {}); 874 assert!(f.typed::<f32, ()>(&store).is_ok()); 875 let f = Func::wrap(&mut store, |_: f64| {}); 876 assert!(f.typed::<f64, ()>(&store).is_ok()); 877 let f = Func::wrap(&mut store, |_: Rooted<ExternRef>| {}); 878 assert!(f.typed::<Rooted<ExternRef>, ()>(&store).is_ok()); 879 let f = Func::wrap(&mut store, |_: Option<Rooted<ExternRef>>| {}); 880 assert!(f.typed::<Option<Rooted<ExternRef>>, ()>(&store).is_ok()); 881 let f = Func::wrap(&mut store, |_: OwnedRooted<ExternRef>| {}); 882 assert!(f.typed::<OwnedRooted<ExternRef>, ()>(&store).is_ok()); 883 let f = Func::wrap(&mut store, |_: Option<OwnedRooted<ExternRef>>| {}); 884 assert!( 885 f.typed::<Option<OwnedRooted<ExternRef>>, ()>(&store) 886 .is_ok() 887 ); 888 let f = Func::wrap(&mut store, |_: Rooted<AnyRef>| {}); 889 assert!(f.typed::<Rooted<AnyRef>, ()>(&store).is_ok()); 890 let f = Func::wrap(&mut store, |_: Option<Rooted<AnyRef>>| {}); 891 assert!(f.typed::<Option<Rooted<AnyRef>>, ()>(&store).is_ok()); 892 let f = Func::wrap(&mut store, |_: OwnedRooted<AnyRef>| {}); 893 assert!(f.typed::<OwnedRooted<AnyRef>, ()>(&store).is_ok()); 894 let f = Func::wrap(&mut store, |_: Option<OwnedRooted<AnyRef>>| {}); 895 assert!(f.typed::<Option<OwnedRooted<AnyRef>>, ()>(&store).is_ok()); 896 let f = Func::wrap(&mut store, |_: I31| {}); 897 assert!(f.typed::<I31, ()>(&store).is_ok()); 898 let f = Func::wrap(&mut store, |_: Option<I31>| {}); 899 assert!(f.typed::<Option<I31>, ()>(&store).is_ok()); 900 let f = Func::wrap(&mut store, |_: Func| {}); 901 assert!(f.typed::<Func, ()>(&store).is_ok()); 902 let f = Func::wrap(&mut store, |_: Option<Func>| {}); 903 assert!(f.typed::<Option<Func>, ()>(&store).is_ok()); 904 } 905 906 #[test] 907 #[cfg_attr(miri, ignore)] 908 fn get_from_signature() { 909 let mut store = Store::<()>::default(); 910 let ty = FuncType::new(store.engine(), None, None); 911 let f = Func::new(&mut store, ty, |_, _, _| panic!()); 912 assert!(f.typed::<(), ()>(&store).is_ok()); 913 assert!(f.typed::<(), i32>(&store).is_err()); 914 assert!(f.typed::<i32, ()>(&store).is_err()); 915 916 let ty = FuncType::new(store.engine(), Some(ValType::I32), Some(ValType::F64)); 917 let f = Func::new(&mut store, ty, |_, _, _| panic!()); 918 assert!(f.typed::<(), ()>(&store).is_err()); 919 assert!(f.typed::<(), i32>(&store).is_err()); 920 assert!(f.typed::<i32, ()>(&store).is_err()); 921 assert!(f.typed::<i32, f64>(&store).is_ok()); 922 } 923 924 #[wasmtime_test] 925 #[cfg_attr(miri, ignore)] 926 fn get_from_module(config: &mut Config) -> wasmtime::Result<()> { 927 let engine = Engine::new(&config)?; 928 let mut store = Store::<()>::new(&engine, ()); 929 let module = Module::new( 930 store.engine(), 931 r#" 932 (module 933 (func (export "f0")) 934 (func (export "f1") (param i32)) 935 (func (export "f2") (result i32) 936 i32.const 0) 937 ) 938 939 "#, 940 )?; 941 let instance = Instance::new(&mut store, &module, &[])?; 942 let f0 = instance.get_func(&mut store, "f0").unwrap(); 943 assert!(f0.typed::<(), ()>(&store).is_ok()); 944 assert!(f0.typed::<(), i32>(&store).is_err()); 945 let f1 = instance.get_func(&mut store, "f1").unwrap(); 946 assert!(f1.typed::<(), ()>(&store).is_err()); 947 assert!(f1.typed::<i32, ()>(&store).is_ok()); 948 assert!(f1.typed::<i32, f32>(&store).is_err()); 949 let f2 = instance.get_func(&mut store, "f2").unwrap(); 950 assert!(f2.typed::<(), ()>(&store).is_err()); 951 assert!(f2.typed::<(), i32>(&store).is_ok()); 952 assert!(f2.typed::<i32, ()>(&store).is_err()); 953 assert!(f2.typed::<i32, f32>(&store).is_err()); 954 Ok(()) 955 } 956 957 #[test] 958 fn call_wrapped_func() -> Result<()> { 959 let mut store = Store::<()>::default(); 960 let f = Func::wrap(&mut store, |a: i32, b: i64, c: f32, d: f64| { 961 assert_eq!(a, 1); 962 assert_eq!(b, 2); 963 assert_eq!(c, 3.0); 964 assert_eq!(d, 4.0); 965 }); 966 f.call( 967 &mut store, 968 &[Val::I32(1), Val::I64(2), 3.0f32.into(), 4.0f64.into()], 969 &mut [], 970 )?; 971 f.typed::<(i32, i64, f32, f64), ()>(&store)? 972 .call(&mut store, (1, 2, 3.0, 4.0))?; 973 974 let mut results = [Val::I32(0)]; 975 let f = Func::wrap(&mut store, || 1i32); 976 f.call(&mut store, &[], &mut results)?; 977 assert_eq!(results[0].unwrap_i32(), 1); 978 assert_eq!(f.typed::<(), i32>(&store)?.call(&mut store, ())?, 1); 979 980 let f = Func::wrap(&mut store, || 2i64); 981 f.call(&mut store, &[], &mut results)?; 982 assert_eq!(results[0].unwrap_i64(), 2); 983 assert_eq!(f.typed::<(), i64>(&store)?.call(&mut store, ())?, 2); 984 985 let f = Func::wrap(&mut store, || 3.0f32); 986 f.call(&mut store, &[], &mut results)?; 987 assert_eq!(results[0].unwrap_f32(), 3.0); 988 assert_eq!(f.typed::<(), f32>(&store)?.call(&mut store, ())?, 3.0); 989 990 let f = Func::wrap(&mut store, || 4.0f64); 991 f.call(&mut store, &[], &mut results)?; 992 assert_eq!(results[0].unwrap_f64(), 4.0); 993 assert_eq!(f.typed::<(), f64>(&store)?.call(&mut store, ())?, 4.0); 994 Ok(()) 995 } 996 997 #[wasmtime_test] 998 #[cfg_attr(miri, ignore)] 999 fn caller_memory(config: &mut Config) -> wasmtime::Result<()> { 1000 let engine = Engine::new(config)?; 1001 let mut store = Store::<()>::new(&engine, ()); 1002 let f = Func::wrap(&mut store, |mut c: Caller<'_, ()>| { 1003 assert!(c.get_export("x").is_none()); 1004 assert!(c.get_export("y").is_none()); 1005 assert!(c.get_export("z").is_none()); 1006 }); 1007 f.call(&mut store, &[], &mut [])?; 1008 1009 let f = Func::wrap(&mut store, |mut c: Caller<'_, ()>| { 1010 assert!(c.get_export("x").is_none()); 1011 }); 1012 let module = Module::new( 1013 store.engine(), 1014 r#" 1015 (module 1016 (import "" "" (func $f)) 1017 (start $f) 1018 ) 1019 1020 "#, 1021 )?; 1022 Instance::new(&mut store, &module, &[f.into()])?; 1023 1024 let f = Func::wrap(&mut store, |mut c: Caller<'_, ()>| { 1025 assert!(c.get_export("memory").is_some()); 1026 }); 1027 let module = Module::new( 1028 store.engine(), 1029 r#" 1030 (module 1031 (import "" "" (func $f)) 1032 (memory (export "memory") 1) 1033 (start $f) 1034 ) 1035 1036 "#, 1037 )?; 1038 Instance::new(&mut store, &module, &[f.into()])?; 1039 1040 let f = Func::wrap(&mut store, |mut c: Caller<'_, ()>| { 1041 assert!(c.get_export("m").is_some()); 1042 assert!(c.get_export("f").is_some()); 1043 assert!(c.get_export("g").is_some()); 1044 assert!(c.get_export("t").is_some()); 1045 }); 1046 let module = Module::new( 1047 store.engine(), 1048 r#" 1049 (module 1050 (import "" "" (func $f)) 1051 (memory (export "m") 1) 1052 (func (export "f")) 1053 (global (export "g") i32 (i32.const 0)) 1054 (table (export "t") 1 funcref) 1055 (start $f) 1056 ) 1057 1058 "#, 1059 )?; 1060 Instance::new(&mut store, &module, &[f.into()])?; 1061 Ok(()) 1062 } 1063 1064 #[test] 1065 #[cfg_attr(miri, ignore)] 1066 fn func_write_nothing() -> wasmtime::Result<()> { 1067 let mut store = Store::<()>::default(); 1068 let ty = FuncType::new(store.engine(), None, Some(ValType::I32)); 1069 let f = Func::new(&mut store, ty, |_, _, _| Ok(())); 1070 let err = f.call(&mut store, &[], &mut [Val::I32(0)]).unwrap_err(); 1071 assert!( 1072 err.to_string() 1073 .contains("function attempted to return an incompatible value") 1074 ); 1075 Ok(()) 1076 } 1077 1078 #[wasmtime_test(wasm_features(reference_types))] 1079 #[cfg_attr(miri, ignore)] 1080 fn return_cross_store_value(config: &mut Config) -> wasmtime::Result<()> { 1081 let _ = env_logger::try_init(); 1082 1083 let wasm = wat::parse_str( 1084 r#" 1085 (import "" "" (func (result funcref))) 1086 1087 (func (export "run") (result funcref) 1088 call 0 1089 ) 1090 "#, 1091 )?; 1092 let engine = Engine::new(&config)?; 1093 let module = Module::new(&engine, &wasm)?; 1094 1095 let mut store1 = Store::new(&engine, ()); 1096 let mut store2 = Store::new(&engine, ()); 1097 1098 let store2_func = Func::wrap(&mut store2, || {}); 1099 let return_cross_store_func = Func::wrap(&mut store1, move || Some(store2_func)); 1100 1101 let instance = Instance::new(&mut store1, &module, &[return_cross_store_func.into()])?; 1102 1103 let run = instance.get_func(&mut store1, "run").unwrap(); 1104 let result = run.call(&mut store1, &[], &mut [Val::I32(0)]); 1105 assert!(result.is_err()); 1106 assert!(format!("{:?}", result.unwrap_err()).contains("cross-`Store`")); 1107 1108 Ok(()) 1109 } 1110 1111 #[wasmtime_test(wasm_features(reference_types))] 1112 fn pass_cross_store_arg(config: &mut Config) -> wasmtime::Result<()> { 1113 let engine = Engine::new(&config)?; 1114 1115 let mut store1 = Store::new(&engine, ()); 1116 let mut store2 = Store::new(&engine, ()); 1117 1118 let store1_func = Func::wrap(&mut store1, |_: Option<Func>| {}); 1119 let store2_func = Func::wrap(&mut store2, || {}); 1120 1121 // Using regular `.call` fails with cross-Store arguments. 1122 assert!( 1123 store1_func 1124 .call(&mut store1, &[Val::FuncRef(Some(store2_func))], &mut []) 1125 .is_err() 1126 ); 1127 1128 // And using `.get` followed by a function call also fails with cross-Store 1129 // arguments. 1130 let f = store1_func.typed::<Option<Func>, ()>(&store1)?; 1131 let result = f.call(&mut store1, Some(store2_func)); 1132 assert!(result.is_err()); 1133 assert!(result.unwrap_err().to_string().contains("cross-`Store`")); 1134 1135 Ok(()) 1136 } 1137 1138 #[test] 1139 #[cfg_attr(miri, ignore)] 1140 fn externref_signature_no_reference_types() -> wasmtime::Result<()> { 1141 let mut config = Config::new(); 1142 config.wasm_reference_types(false); 1143 let mut store = Store::new(&Engine::new(&config)?, ()); 1144 Func::wrap(&mut store, |_: Option<Func>| {}); 1145 let func_ty = FuncType::new( 1146 store.engine(), 1147 [ValType::FUNCREF, ValType::EXTERNREF].iter().cloned(), 1148 [ValType::FUNCREF, ValType::EXTERNREF].iter().cloned(), 1149 ); 1150 Func::new(&mut store, func_ty, |_, _, _| Ok(())); 1151 Ok(()) 1152 } 1153 1154 #[wasmtime_test] 1155 #[cfg_attr(miri, ignore)] 1156 fn trampolines_always_valid(config: &mut Config) -> wasmtime::Result<()> { 1157 // Compile two modules up front 1158 let engine = Engine::new(&config)?; 1159 let mut store = Store::<()>::new(&engine, ()); 1160 let module1 = Module::new(store.engine(), "(module (import \"\" \"\" (func)))")?; 1161 let module2 = Module::new(store.engine(), "(module (func (export \"\")))")?; 1162 // Start instantiating the first module, but this will fail. 1163 // Historically this registered the module's trampolines with `Store` 1164 // before the failure, but then after the failure the `Store` didn't 1165 // hold onto the trampoline. 1166 drop(Instance::new(&mut store, &module1, &[])); 1167 drop(module1); 1168 1169 // Then instantiate another module which has the same function type (no 1170 // parameters or results) which tries to use the trampoline defined in 1171 // the previous module. Then we extract the function and, after we drop the 1172 // module's reference, we call the func. 1173 let i = Instance::new(&mut store, &module2, &[])?; 1174 let func = i.get_func(&mut store, "").unwrap(); 1175 drop(module2); 1176 1177 // ... and no segfaults! right? right? ... 1178 func.call(&mut store, &[], &mut [])?; 1179 Ok(()) 1180 } 1181 1182 #[wasmtime_test] 1183 #[cfg_attr(miri, ignore)] 1184 fn typed_multiple_results(config: &mut Config) -> wasmtime::Result<()> { 1185 let engine = Engine::new(&config)?; 1186 let mut store = Store::<()>::new(&engine, ()); 1187 let module = Module::new( 1188 store.engine(), 1189 r#" 1190 (module 1191 (func (export "f0") (result i32 i64) 1192 i32.const 0 1193 i64.const 1) 1194 (func (export "f1") (param i32 i32 i32) (result f32 f64) 1195 f32.const 2 1196 f64.const 3) 1197 ) 1198 1199 "#, 1200 )?; 1201 let instance = Instance::new(&mut store, &module, &[])?; 1202 let f0 = instance.get_func(&mut store, "f0").unwrap(); 1203 assert!(f0.typed::<(), ()>(&store).is_err()); 1204 assert!(f0.typed::<(), (i32, f32)>(&store).is_err()); 1205 assert!(f0.typed::<(), i32>(&store).is_err()); 1206 assert_eq!( 1207 f0.typed::<(), (i32, i64)>(&store)?.call(&mut store, ())?, 1208 (0, 1) 1209 ); 1210 1211 let f1 = instance.get_func(&mut store, "f1").unwrap(); 1212 assert_eq!( 1213 f1.typed::<(i32, i32, i32), (f32, f64)>(&store)? 1214 .call(&mut store, (1, 2, 3))?, 1215 (2., 3.) 1216 ); 1217 Ok(()) 1218 } 1219 1220 #[test] 1221 #[cfg_attr(miri, ignore)] 1222 fn trap_doesnt_leak() -> wasmtime::Result<()> { 1223 #[derive(Default)] 1224 struct Canary(Arc<AtomicBool>); 1225 1226 impl Drop for Canary { 1227 fn drop(&mut self) { 1228 self.0.store(true, SeqCst); 1229 } 1230 } 1231 1232 let mut store = Store::<()>::default(); 1233 1234 // test that `Func::wrap` is correct 1235 let canary1 = Canary::default(); 1236 let dtor1_run = canary1.0.clone(); 1237 let f1 = Func::wrap(&mut store, move || -> Result<()> { 1238 let _ = &canary1; 1239 bail!("") 1240 }); 1241 assert!(f1.typed::<(), ()>(&store)?.call(&mut store, ()).is_err()); 1242 assert!(f1.call(&mut store, &[], &mut []).is_err()); 1243 1244 // test that `Func::new` is correct 1245 let canary2 = Canary::default(); 1246 let dtor2_run = canary2.0.clone(); 1247 let func_ty = FuncType::new(store.engine(), None, None); 1248 let f2 = Func::new(&mut store, func_ty, move |_, _, _| { 1249 let _ = &canary2; 1250 bail!("") 1251 }); 1252 assert!(f2.typed::<(), ()>(&store)?.call(&mut store, ()).is_err()); 1253 assert!(f2.call(&mut store, &[], &mut []).is_err()); 1254 1255 // drop everything and ensure dtors are run 1256 drop(store); 1257 assert!(dtor1_run.load(SeqCst)); 1258 assert!(dtor2_run.load(SeqCst)); 1259 Ok(()) 1260 } 1261 1262 #[wasmtime_test] 1263 #[cfg_attr(miri, ignore)] 1264 fn wrap_multiple_results(config: &mut Config) -> wasmtime::Result<()> { 1265 fn test<T>(store: &mut Store<()>, t: T) -> wasmtime::Result<()> 1266 where 1267 T: WasmRet 1268 + WasmResults 1269 + PartialEq 1270 + Copy 1271 + std::fmt::Debug 1272 + EqualToValues 1273 + 'static 1274 + Send 1275 + Sync, 1276 { 1277 let f = Func::wrap(&mut *store, move || t); 1278 let mut results = vec![Val::I32(0); f.ty(&store).results().len()]; 1279 assert_eq!(f.typed::<(), T>(&store)?.call(&mut *store, ())?, t); 1280 f.call(&mut *store, &[], &mut results)?; 1281 assert!(t.eq_values(&results)); 1282 1283 let module = Module::new(store.engine(), &T::gen_wasm())?; 1284 let instance = Instance::new(&mut *store, &module, &[f.into()])?; 1285 let f = instance.get_func(&mut *store, "foo").unwrap(); 1286 1287 assert_eq!(f.typed::<(), T>(&store)?.call(&mut *store, ())?, t); 1288 f.call(&mut *store, &[], &mut results)?; 1289 assert!(t.eq_values(&results)); 1290 Ok(()) 1291 } 1292 1293 let engine = Engine::new(&config)?; 1294 let mut store = Store::new(&engine, ()); 1295 // 0 element 1296 test(&mut store, ())?; 1297 1298 // 1 element 1299 test(&mut store, (1i32,))?; 1300 test(&mut store, (2u32,))?; 1301 test(&mut store, (3i64,))?; 1302 test(&mut store, (4u64,))?; 1303 test(&mut store, (5.0f32,))?; 1304 test(&mut store, (6.0f64,))?; 1305 1306 // 2 element ... 1307 test(&mut store, (7i32, 8i32))?; 1308 test(&mut store, (7i32, 8i64))?; 1309 test(&mut store, (7i32, 8f32))?; 1310 test(&mut store, (7i32, 8f64))?; 1311 1312 test(&mut store, (7i64, 8i32))?; 1313 test(&mut store, (7i64, 8i64))?; 1314 test(&mut store, (7i64, 8f32))?; 1315 test(&mut store, (7i64, 8f64))?; 1316 1317 test(&mut store, (7f32, 8i32))?; 1318 test(&mut store, (7f32, 8i64))?; 1319 test(&mut store, (7f32, 8f32))?; 1320 test(&mut store, (7f32, 8f64))?; 1321 1322 test(&mut store, (7f64, 8i32))?; 1323 test(&mut store, (7f64, 8i64))?; 1324 test(&mut store, (7f64, 8f32))?; 1325 test(&mut store, (7f64, 8f64))?; 1326 1327 // and beyond... 1328 test(&mut store, (1i32, 2i32, 3i32))?; 1329 test(&mut store, (1i32, 2f32, 3i32))?; 1330 test(&mut store, (1f64, 2f32, 3i32))?; 1331 test(&mut store, (1f64, 2i64, 3i32))?; 1332 test(&mut store, (1f32, 2f32, 3i64, 4f64))?; 1333 test(&mut store, (1f64, 2i64, 3i32, 4i64, 5f32))?; 1334 test(&mut store, (1i32, 2f64, 3i64, 4f64, 5f64, 6f32))?; 1335 test(&mut store, (1i64, 2i32, 3i64, 4f32, 5f32, 6i32, 7u64))?; 1336 test(&mut store, (1u32, 2f32, 3u64, 4f64, 5i32, 6f32, 7u64, 8u32))?; 1337 test( 1338 &mut store, 1339 (1f32, 2f64, 3f32, 4i32, 5u32, 6i64, 7f32, 8i32, 9u64), 1340 )?; 1341 return Ok(()); 1342 1343 trait EqualToValues { 1344 fn eq_values(&self, values: &[Val]) -> bool; 1345 fn gen_wasm() -> String; 1346 } 1347 1348 macro_rules! equal_tuples { 1349 ($($cnt:tt ($($a:ident),*))*) => ($( 1350 #[allow(non_snake_case, reason = "macro-generated code")] 1351 impl<$($a: EqualToValue,)*> EqualToValues for ($($a,)*) { 1352 fn eq_values(&self, values: &[Val]) -> bool { 1353 let ($($a,)*) = self; 1354 let mut _values = values.iter(); 1355 _values.len() == $cnt && 1356 $($a.eq_value(_values.next().unwrap()) &&)* 1357 true 1358 } 1359 1360 fn gen_wasm() -> String { 1361 let mut wasm = String::new(); 1362 wasm.push_str("(module "); 1363 wasm.push_str("(type $t (func (result "); 1364 $( 1365 wasm.push_str($a::wasm_ty()); 1366 wasm.push_str(" "); 1367 )* 1368 wasm.push_str(")))"); 1369 1370 wasm.push_str("(import \"\" \"\" (func $host (type $t)))"); 1371 wasm.push_str("(func (export \"foo\") (type $t)"); 1372 wasm.push_str("call $host"); 1373 wasm.push_str(")"); 1374 wasm.push_str(")"); 1375 1376 wasm 1377 } 1378 } 1379 )*) 1380 } 1381 1382 equal_tuples! { 1383 0 () 1384 1 (A1) 1385 2 (A1, A2) 1386 3 (A1, A2, A3) 1387 4 (A1, A2, A3, A4) 1388 5 (A1, A2, A3, A4, A5) 1389 6 (A1, A2, A3, A4, A5, A6) 1390 7 (A1, A2, A3, A4, A5, A6, A7) 1391 8 (A1, A2, A3, A4, A5, A6, A7, A8) 1392 9 (A1, A2, A3, A4, A5, A6, A7, A8, A9) 1393 } 1394 1395 trait EqualToValue { 1396 fn eq_value(&self, value: &Val) -> bool; 1397 fn wasm_ty() -> &'static str; 1398 } 1399 1400 macro_rules! equal_values { 1401 ($a:ident $($ty:ident $wasm:tt $variant:ident $e:expr,)*) => ($( 1402 impl EqualToValue for $ty { 1403 fn eq_value(&self, val: &Val) -> bool { 1404 if let Val::$variant($a) = *val { 1405 return *self == $e; 1406 } 1407 false 1408 } 1409 1410 fn wasm_ty() -> &'static str { 1411 $wasm 1412 } 1413 } 1414 )*) 1415 } 1416 1417 equal_values! { 1418 a 1419 i32 "i32" I32 a, 1420 u32 "i32" I32 a as u32, 1421 i64 "i64" I64 a, 1422 u64 "i64" I64 a as u64, 1423 f32 "f32" F32 f32::from_bits(a), 1424 f64 "f64" F64 f64::from_bits(a), 1425 } 1426 } 1427 1428 #[wasmtime_test(wasm_features(reference_types, gc_types, bulk_memory))] 1429 #[cfg_attr(miri, ignore)] 1430 fn trampoline_for_declared_elem(config: &mut Config) -> wasmtime::Result<()> { 1431 let engine = Engine::new(&config)?; 1432 1433 let module = Module::new( 1434 &engine, 1435 r#" 1436 (module 1437 (elem declare func $f) 1438 (func $f) 1439 (func (export "g") (result funcref) 1440 (ref.func $f) 1441 ) 1442 ) 1443 "#, 1444 )?; 1445 1446 let mut store = Store::new(&engine, ()); 1447 let instance = Instance::new(&mut store, &module, &[])?; 1448 1449 let g = instance.get_typed_func::<(), Option<Func>>(&mut store, "g")?; 1450 1451 let func = g.call(&mut store, ())?; 1452 func.unwrap().call(&mut store, &[], &mut [])?; 1453 Ok(()) 1454 } 1455 1456 #[wasmtime_test] 1457 #[cfg_attr(miri, ignore)] 1458 fn wasm_ty_roundtrip(config: &mut Config) -> Result<(), wasmtime::Error> { 1459 let engine = Engine::new(&config)?; 1460 let mut store = Store::<()>::new(&engine, ()); 1461 let debug = Func::wrap( 1462 &mut store, 1463 |a: i32, b: u32, c: f32, d: i64, e: u64, f: f64| { 1464 assert_eq!(a, -1); 1465 assert_eq!(b, 1); 1466 assert_eq!(c, 2.0); 1467 assert_eq!(d, -3); 1468 assert_eq!(e, 3); 1469 assert_eq!(f, 4.0); 1470 }, 1471 ); 1472 let module = Module::new( 1473 store.engine(), 1474 r#" 1475 (module 1476 (import "" "" (func $debug (param i32 i32 f32 i64 i64 f64))) 1477 (func (export "foo") (param i32 i32 f32 i64 i64 f64) 1478 (if (i32.ne (local.get 0) (i32.const -1)) 1479 (then unreachable) 1480 ) 1481 (if (i32.ne (local.get 1) (i32.const 1)) 1482 (then unreachable) 1483 ) 1484 (if (f32.ne (local.get 2) (f32.const 2)) 1485 (then unreachable) 1486 ) 1487 (if (i64.ne (local.get 3) (i64.const -3)) 1488 (then unreachable) 1489 ) 1490 (if (i64.ne (local.get 4) (i64.const 3)) 1491 (then unreachable) 1492 ) 1493 (if (f64.ne (local.get 5) (f64.const 4)) 1494 (then unreachable) 1495 ) 1496 local.get 0 1497 local.get 1 1498 local.get 2 1499 local.get 3 1500 local.get 4 1501 local.get 5 1502 call $debug 1503 ) 1504 ) 1505 "#, 1506 )?; 1507 let instance = Instance::new(&mut store, &module, &[debug.into()])?; 1508 let foo = instance.get_typed_func::<(i32, u32, f32, i64, u64, f64), ()>(&mut store, "foo")?; 1509 foo.call(&mut store, (-1, 1, 2.0, -3, 3, 4.0))?; 1510 Ok(()) 1511 } 1512 1513 #[wasmtime_test] 1514 #[cfg_attr(miri, ignore)] 1515 fn typed_funcs_count_params_correctly_in_error_messages( 1516 config: &mut Config, 1517 ) -> wasmtime::Result<()> { 1518 let engine = Engine::new(&config)?; 1519 let mut store = Store::<()>::new(&engine, ()); 1520 let module = Module::new( 1521 store.engine(), 1522 r#" 1523 (module 1524 (func (export "f") (param i32 i32)) 1525 ) 1526 1527 "#, 1528 )?; 1529 let instance = Instance::new(&mut store, &module, &[])?; 1530 1531 // Too few parameters. 1532 match instance.get_typed_func::<(), ()>(&mut store, "f") { 1533 Ok(_) => panic!("should be wrong signature"), 1534 Err(e) => { 1535 let msg = format!("{e:?}"); 1536 assert!(dbg!(msg).contains("expected 0 types, found 2")) 1537 } 1538 } 1539 match instance.get_typed_func::<(i32,), ()>(&mut store, "f") { 1540 Ok(_) => panic!("should be wrong signature"), 1541 Err(e) => { 1542 let msg = format!("{e:?}"); 1543 assert!(dbg!(msg).contains("expected 1 types, found 2")) 1544 } 1545 } 1546 1547 // Too many parameters. 1548 match instance.get_typed_func::<(i32, i32, i32), ()>(&mut store, "f") { 1549 Ok(_) => panic!("should be wrong signature"), 1550 Err(e) => { 1551 let msg = format!("{e:?}"); 1552 assert!(dbg!(msg).contains("expected 3 types, found 2")) 1553 } 1554 } 1555 1556 Ok(()) 1557 } 1558 1559 #[wasmtime_test(wasm_features(reference_types, gc_types))] 1560 #[cfg_attr(miri, ignore)] 1561 fn calls_with_funcref_and_externref(config: &mut Config) -> wasmtime::Result<()> { 1562 let engine = Engine::new(&config)?; 1563 let mut store = Store::<()>::new(&engine, ()); 1564 let module = Module::new( 1565 store.engine(), 1566 r#" 1567 (module 1568 (import "" "witness" (func $witness (param funcref externref))) 1569 (func (export "f") (param funcref externref) (result externref funcref) 1570 local.get 0 1571 local.get 1 1572 call $witness 1573 local.get 1 1574 local.get 0 1575 ) 1576 ) 1577 1578 "#, 1579 )?; 1580 let mut linker = Linker::new(store.engine()); 1581 linker.func_wrap( 1582 "", 1583 "witness", 1584 |mut caller: Caller<'_, ()>, func: Option<Func>, externref: Option<Rooted<ExternRef>>| { 1585 if func.is_some() { 1586 assert_my_funcref(&mut caller, func.as_ref())?; 1587 } 1588 if externref.is_some() { 1589 assert_my_externref(&caller, externref); 1590 } 1591 Ok(()) 1592 }, 1593 )?; 1594 let instance = linker.instantiate(&mut store, &module)?; 1595 1596 let typed = instance 1597 .get_typed_func::<(Option<Func>, Option<Rooted<ExternRef>>), (Option<Rooted<ExternRef>>, Option<Func>)>( 1598 &mut store, "f", 1599 )?; 1600 let untyped = typed.func(); 1601 1602 let my_funcref = Func::wrap(&mut store, || 100u32); 1603 let my_externref = ExternRef::new(&mut store, 99u32)?; 1604 let mut results = [Val::I32(0), Val::I32(0)]; 1605 1606 fn assert_my_funcref(mut store: impl AsContextMut, func: Option<&Func>) -> Result<()> { 1607 let mut store = store.as_context_mut(); 1608 let func = func.unwrap(); 1609 assert_eq!(func.typed::<(), u32>(&store)?.call(&mut store, ())?, 100); 1610 Ok(()) 1611 } 1612 fn assert_my_externref(store: impl AsContext, externref: Option<Rooted<ExternRef>>) { 1613 assert_eq!( 1614 externref 1615 .unwrap() 1616 .data(&store) 1617 .unwrap() 1618 .unwrap() 1619 .downcast_ref(), 1620 Some(&99u32) 1621 ); 1622 } 1623 1624 // funcref=null, externref=null 1625 let (a, b) = typed.call(&mut store, (None, None))?; 1626 assert!(a.is_none()); 1627 assert!(b.is_none()); 1628 untyped.call( 1629 &mut store, 1630 &[Val::FuncRef(None), Val::ExternRef(None)], 1631 &mut results, 1632 )?; 1633 assert!(results[0].unwrap_externref().is_none()); 1634 assert!(results[1].unwrap_funcref().is_none()); 1635 1636 // funcref=Some, externref=null 1637 let (a, b) = typed.call(&mut store, (Some(my_funcref), None))?; 1638 assert!(a.is_none()); 1639 assert_my_funcref(&mut store, b.as_ref())?; 1640 untyped.call( 1641 &mut store, 1642 &[Val::FuncRef(Some(my_funcref)), Val::ExternRef(None)], 1643 &mut results, 1644 )?; 1645 assert!(results[0].unwrap_externref().is_none()); 1646 assert_my_funcref(&mut store, results[1].unwrap_funcref())?; 1647 1648 // funcref=null, externref=Some 1649 let (a, b) = typed.call(&mut store, (None, Some(my_externref)))?; 1650 assert_my_externref(&store, a); 1651 assert!(b.is_none()); 1652 untyped.call( 1653 &mut store, 1654 &[Val::FuncRef(None), Val::ExternRef(Some(my_externref))], 1655 &mut results, 1656 )?; 1657 assert_my_externref(&store, results[0].unwrap_externref().copied()); 1658 assert!(results[1].unwrap_funcref().is_none()); 1659 1660 // funcref=Some, externref=Some 1661 let (a, b) = typed.call(&mut store, (Some(my_funcref), Some(my_externref)))?; 1662 assert_my_externref(&store, a); 1663 assert_my_funcref(&mut store, b.as_ref())?; 1664 untyped.call( 1665 &mut store, 1666 &[ 1667 Val::FuncRef(Some(my_funcref)), 1668 Val::ExternRef(Some(my_externref)), 1669 ], 1670 &mut results, 1671 )?; 1672 assert_my_externref(&store, results[0].unwrap_externref().copied()); 1673 assert_my_funcref(&mut store, results[1].unwrap_funcref())?; 1674 1675 Ok(()) 1676 } 1677 1678 #[wasmtime_test(wasm_features(function_references, bulk_memory))] 1679 #[cfg_attr(miri, ignore)] 1680 fn typed_concrete_param(config: &mut Config) -> wasmtime::Result<()> { 1681 let engine = Engine::new(&config)?; 1682 let module = Module::new( 1683 &engine, 1684 r#" 1685 (module 1686 (type $t (func)) 1687 (func (export "f") (param (ref null $t))) 1688 ) 1689 "#, 1690 )?; 1691 let mut store = Store::new(&engine, ()); 1692 let instance = Instance::new(&mut store, &module, &[])?; 1693 1694 let nop = Func::new( 1695 &mut store, 1696 FuncType::new(&engine, None, None), 1697 |_caller, _params, _results| Ok(()), 1698 ); 1699 1700 let f = instance.get_func(&mut store, "f").unwrap(); 1701 1702 // Can type with a subtype, which should avoid all dynamic type checks after 1703 // successful construction. 1704 let a = f.typed::<Option<NoFunc>, ()>(&store)?; 1705 a.call(&mut store, None)?; 1706 // NB: Cannot call with Some(_) as `NoFunc` is uninhabited. 1707 1708 // Can call `typed` with a supertype, falling back to dynamic type checks on 1709 // each call. 1710 let a = f.typed::<Option<Func>, ()>(&store)?; 1711 a.call(&mut store, None)?; 1712 a.call(&mut store, Some(nop))?; 1713 let e = a.call(&mut store, Some(f)).expect_err( 1714 "should return an error because while we did pass an instance of \ 1715 `Option<Func>`, it was not an instance of `(ref null $t)`", 1716 ); 1717 let e = format!("{e:?}"); 1718 assert!(e.contains("argument type mismatch for reference to concrete type")); 1719 assert!(e.contains( 1720 "type mismatch: expected (type (func)), \ 1721 found (type (func (param (ref null (concrete func VMSharedTypeIndex(0))))))" 1722 )); 1723 1724 // And dynamic checks also work with a non-nullable super type. 1725 let a = f.typed::<Func, ()>(&store)?; 1726 a.call(&mut store, nop)?; 1727 let e = a.call(&mut store, f).expect_err( 1728 "should return an error because while we did pass an instance of \ 1729 `Func`, it was not an instance of `(ref null $t)`", 1730 ); 1731 let e = format!("{e:?}"); 1732 assert!(e.contains("argument type mismatch for reference to concrete type")); 1733 assert!(e.contains( 1734 "type mismatch: expected (type (func)), \ 1735 found (type (func (param (ref null (concrete func VMSharedTypeIndex(0))))))" 1736 )); 1737 1738 // Calling `typed` with a type that is not a supertype nor a subtype fails 1739 // the initial type check. 1740 let e = f 1741 .typed::<Option<Rooted<ExternRef>>, ()>(&store) 1742 .err() 1743 .unwrap(); 1744 let e = format!("{e:?}"); 1745 assert!(e.contains("type mismatch with parameters")); 1746 assert!(e.contains("type mismatch: expected func, found extern")); 1747 1748 Ok(()) 1749 } 1750 1751 #[wasmtime_test(wasm_features(function_references, bulk_memory))] 1752 #[cfg_attr(miri, ignore)] 1753 fn typed_concrete_result(config: &mut Config) -> wasmtime::Result<()> { 1754 let engine = Engine::new(&config)?; 1755 let module = Module::new( 1756 &engine, 1757 r#" 1758 (module 1759 (type $t (func)) 1760 (func $nop) 1761 (elem declare func $nop) 1762 (func (export "f") (result (ref $t)) 1763 ref.func $nop 1764 ) 1765 ) 1766 "#, 1767 )?; 1768 let mut store = Store::new(&engine, ()); 1769 let instance = Instance::new(&mut store, &module, &[])?; 1770 1771 let f = instance.get_func(&mut store, "f").unwrap(); 1772 1773 // Can type `f` with a supertype of the declared result type, and we get the 1774 // expected return value. 1775 let a = f.typed::<(), Func>(&store)?; 1776 let g = a.call(&mut store, ())?; 1777 g.typed::<(), ()>(&store)?.call(&mut store, ())?; 1778 1779 // Also works with a nullable supertype. 1780 let a = f.typed::<(), Option<Func>>(&store)?; 1781 let g = a.call(&mut store, ())?; 1782 g.unwrap().typed::<(), ()>(&store)?.call(&mut store, ())?; 1783 1784 // But we can't claim that `f` returns a particular subtype of its actual 1785 // return type. 1786 let e = f.typed::<(), NoFunc>(&store).err().unwrap(); 1787 let e = format!("{e:?}"); 1788 assert!(e.contains("type mismatch with results")); 1789 assert!(e.contains( 1790 "type mismatch: expected (ref nofunc), found (ref (concrete func VMSharedTypeIndex(0)))" 1791 )); 1792 1793 // Nor some unrelated type that it is neither a subtype or supertype of. 1794 let e = f.typed::<(), Rooted<ExternRef>>(&store).err().unwrap(); 1795 let e = format!("{e:?}"); 1796 assert!(e.contains("type mismatch with results")); 1797 assert!(e.contains( 1798 "type mismatch: expected (ref extern), found (ref (concrete func VMSharedTypeIndex(0)))" 1799 )); 1800 1801 Ok(()) 1802 } 1803 1804 #[test] 1805 #[cfg_attr(miri, ignore)] 1806 fn wrap_subtype_param() -> wasmtime::Result<()> { 1807 let mut store = Store::<()>::default(); 1808 let f = Func::wrap(&mut store, |_caller: Caller<'_, ()>, _: Option<Func>| { 1809 // No-op. 1810 }); 1811 1812 // Precise type. 1813 let a = f.typed::<Option<Func>, ()>(&store)?; 1814 a.call(&mut store, None)?; 1815 a.call(&mut store, Some(f))?; 1816 1817 // Subtype via heap type. 1818 let a = f.typed::<Option<NoFunc>, ()>(&store)?; 1819 a.call(&mut store, None)?; 1820 1821 // Subtype via non-null. 1822 let a = f.typed::<Func, ()>(&store)?; 1823 a.call(&mut store, f)?; 1824 1825 Ok(()) 1826 } 1827 1828 #[test] 1829 #[cfg_attr(miri, ignore)] 1830 fn wrap_supertype_result() -> wasmtime::Result<()> { 1831 let mut store = Store::<()>::default(); 1832 let f = Func::wrap(&mut store, |_caller: Caller<'_, ()>| -> NoFunc { 1833 unreachable!() 1834 }); 1835 1836 // Precise type. 1837 let _ = f.typed::<(), NoFunc>(&store)?; 1838 1839 // Supertype via heap type. 1840 let _ = f.typed::<(), Func>(&store)?; 1841 1842 // Supertype via nullability. 1843 let _ = f.typed::<(), Option<NoFunc>>(&store)?; 1844 1845 Ok(()) 1846 } 1847 1848 #[wasmtime_test(wasm_features(function_references))] 1849 #[cfg_attr(miri, ignore)] 1850 fn call_wasm_passing_subtype_func_param(config: &mut Config) -> wasmtime::Result<()> { 1851 config.wasm_function_references(true); 1852 let engine = Engine::new(&config)?; 1853 let mut store = Store::new(&engine, ()); 1854 1855 let module = Module::new( 1856 &engine, 1857 r#" 1858 (module 1859 (type $ty (func (result funcref))) 1860 (func (export "f") (param (ref null $ty)) (result funcref) 1861 ;; Return null if the funcref is null. 1862 ref.null func 1863 local.get 0 1864 ref.is_null 1865 br_if 0 1866 drop 1867 1868 ;; Otherwise, call it. 1869 local.get 0 1870 call_ref $ty 1871 ) 1872 ) 1873 "#, 1874 )?; 1875 1876 let instance = Instance::new(&mut store, &module, &[])?; 1877 let f = instance.get_func(&mut store, "f").unwrap(); 1878 1879 let g_ty = FuncType::new(&engine, None, Some(ValType::I32)); 1880 let g = Func::new(&mut store, g_ty.clone(), |_caller, _params, results| { 1881 results[0] = Val::I32(0x1234_5678); 1882 Ok(()) 1883 }); 1884 1885 // h's type is a subtype of the Wasm-defined `$ty`: 1886 // 1887 // (func (result (ref null g_ty))) <: (func (result funcref)) 1888 let h_ty = FuncType::new( 1889 &engine, 1890 None, 1891 Some(ValType::Ref(RefType::new( 1892 true, 1893 HeapType::ConcreteFunc(g_ty), 1894 ))), 1895 ); 1896 let h = Func::new(&mut store, h_ty, move |_caller, _params, results| { 1897 results[0] = Val::FuncRef(Some(g)); 1898 Ok(()) 1899 }); 1900 1901 // Array call, passing in a subtype of the expected parameter. 1902 1903 let mut results = vec![Val::I32(0)]; 1904 f.call(&mut store, &[Val::null_func_ref()], &mut results)?; 1905 assert!(results[0].unwrap_func_ref().is_none()); 1906 1907 f.call(&mut store, &[h.into()], &mut results)?; 1908 let g = results[0]; 1909 let g = g.unwrap_func_ref().unwrap(); 1910 g.call(&mut store, &[], &mut results)?; 1911 assert_eq!(results[0].unwrap_i32(), 0x1234_5678); 1912 1913 // Native call, passing in a subtype of the expected parameter. 1914 1915 let f = f.typed::<Option<Func>, Option<Func>>(&store)?; 1916 let r = f.call(&mut store, None)?; 1917 assert!(r.is_none()); 1918 1919 let g = f.call(&mut store, Some(h))?; 1920 let g = g.unwrap().typed::<(), u32>(&mut store)?; 1921 let x = g.call(&mut store, ())?; 1922 assert_eq!(x, 0x1234_5678); 1923 1924 Ok(()) 1925 } 1926 1927 #[wasmtime_test(wasm_features(gc, function_references, bulk_memory))] 1928 #[cfg_attr(miri, ignore)] 1929 fn call_wasm_getting_subtype_func_return(config: &mut Config) -> wasmtime::Result<()> { 1930 let engine = Engine::new(&config)?; 1931 let mut store = Store::new(&engine, ()); 1932 1933 let module = Module::new( 1934 &engine, 1935 r#" 1936 (module 1937 (type $ty (func (result funcref))) 1938 1939 (func $a (result i32) 1940 i32.const 0x12345678 1941 ) 1942 1943 (func $b (result funcref) 1944 ref.func $a 1945 ) 1946 1947 (elem declare func $a $b) 1948 1949 ;; Returns a `(ref null nofunc)` if called with `0`, otherwise 1950 ;; returns `(ref null $ty)`, both of which are subtypes of 1951 ;; `funcref`. 1952 (func (export "f") (param i32) (result funcref) 1953 block 1954 local.get 0 1955 br_if 0 1956 ref.null nofunc 1957 return 1958 end 1959 ref.func $b 1960 ) 1961 ) 1962 "#, 1963 )?; 1964 1965 let instance = Instance::new(&mut store, &module, &[])?; 1966 let f = instance.get_func(&mut store, "f").unwrap(); 1967 1968 // Array call, receiving a subtype of the expected result. 1969 1970 let mut results = vec![Val::I32(0)]; 1971 f.call(&mut store, &[Val::I32(0)], &mut results)?; 1972 assert!(results[0].unwrap_func_ref().is_none()); 1973 1974 f.call(&mut store, &[Val::I32(1)], &mut results)?; 1975 let b = results[0]; 1976 let b = b.unwrap_func_ref().unwrap(); 1977 b.call(&mut store, &[], &mut results)?; 1978 let a = results[0]; 1979 let a = a.unwrap_func_ref().unwrap(); 1980 a.call(&mut store, &[], &mut results)?; 1981 assert_eq!(results[0].unwrap_i32(), 0x1234_5678); 1982 1983 // Native call, receiving a subtype of the expected result. 1984 1985 let f = f.typed::<u32, Option<Func>>(&store)?; 1986 let r = f.call(&mut store, 0)?; 1987 assert!(r.is_none()); 1988 1989 let b = f.call(&mut store, 1)?; 1990 let b = b.unwrap().typed::<(), Option<Func>>(&store)?; 1991 let a = b.call(&mut store, ())?; 1992 let a = a.unwrap().typed::<(), u32>(&store)?; 1993 let x = a.call(&mut store, ())?; 1994 assert_eq!(x, 0x1234_5678); 1995 1996 Ok(()) 1997 } 1998 1999 #[wasmtime_test(wasm_features(simd), strategies(not(Winch)))] 2000 #[cfg_attr(miri, ignore)] 2001 fn typed_v128(config: &mut Config) -> wasmtime::Result<()> { 2002 let engine = Engine::new(&config)?; 2003 let mut store = Store::<()>::new(&engine, ()); 2004 let module = Module::new( 2005 store.engine(), 2006 r#" 2007 (module 2008 (func (export "a") (param v128) (result v128) 2009 local.get 0) 2010 (func (export "b") (param v128 v128) (result v128 v128) 2011 local.get 0 2012 local.get 1) 2013 (func (export "c") (param v128 v128 v128 v128 v128 v128 v128 v128) (result v128) 2014 local.get 0 2015 local.get 1 2016 local.get 2 2017 local.get 3 2018 local.get 4 2019 local.get 5 2020 local.get 6 2021 local.get 7 2022 i64x2.add 2023 i64x2.add 2024 i64x2.add 2025 i64x2.add 2026 i64x2.add 2027 i64x2.add 2028 i64x2.add) 2029 ) 2030 2031 "#, 2032 )?; 2033 let instance = Instance::new(&mut store, &module, &[])?; 2034 2035 let a = instance.get_typed_func::<V128, V128>(&mut store, "a")?; 2036 assert_eq!(a.call(&mut store, V128::from(1))?, V128::from(1)); 2037 assert_eq!(a.call(&mut store, V128::from(2))?, V128::from(2)); 2038 2039 let b = instance.get_typed_func::<(V128, V128), (V128, V128)>(&mut store, "b")?; 2040 assert_eq!( 2041 b.call(&mut store, (V128::from(1), V128::from(2)))?, 2042 (V128::from(1), V128::from(2)) 2043 ); 2044 2045 let c = instance.get_typed_func::<(V128, V128, V128, V128, V128, V128, V128, V128), V128>( 2046 &mut store, "c", 2047 )?; 2048 assert_eq!( 2049 c.call( 2050 &mut store, 2051 ( 2052 V128::from(1), 2053 V128::from(2), 2054 V128::from(3), 2055 V128::from(4), 2056 V128::from(5), 2057 V128::from(6), 2058 V128::from(7), 2059 V128::from(8), 2060 ) 2061 )?, 2062 V128::from(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8), 2063 ); 2064 2065 Ok(()) 2066 } 2067 2068 #[wasmtime_test(wasm_features(simd))] 2069 #[cfg_attr(miri, ignore)] 2070 fn typed_v128_imports(config: &mut Config) -> wasmtime::Result<()> { 2071 let engine = Engine::new(&config)?; 2072 let mut store = Store::<()>::new(&engine, ()); 2073 let module = Module::new( 2074 store.engine(), 2075 r#" 2076 (module 2077 (import "" "a" (func $a (param v128) (result i32))) 2078 (import "" "b" (func $b (param i32) (result v128))) 2079 (import "" "c" (func $c (param v128 f64 v128) (result v128 i32 v128))) 2080 (import "" "d" (func $d (param v128 v128 v128 v128 v128 v128 v128 v128) (result i32))) 2081 2082 (func (export "a") (param v128) (result i32) 2083 local.get 0 2084 call $a) 2085 2086 (func (export "b") (param i32) (result v128) 2087 local.get 0 2088 call $b) 2089 2090 (func (export "c") (param v128 f64 v128) (result v128 i32 v128) 2091 local.get 0 2092 local.get 1 2093 local.get 2 2094 call $c) 2095 2096 (func (export "d") (param v128 v128 v128 v128 v128 v128 v128 v128) (result i32) 2097 local.get 0 2098 local.get 1 2099 local.get 2 2100 local.get 3 2101 local.get 4 2102 local.get 5 2103 local.get 6 2104 local.get 7 2105 call $d) 2106 ) 2107 2108 "#, 2109 )?; 2110 2111 let mut l = Linker::new(store.engine()); 2112 l.func_wrap("", "a", |x: V128| { 2113 let x = x.as_u128(); 2114 (x >> 0) as u32 + (x >> 32) as u32 + (x >> 64) as u32 + (x >> 96) as u32 2115 })?; 2116 l.func_wrap("", "b", |x: u32| { 2117 let x = u128::from(x); 2118 V128::from(x | ((x + 1) << 32) | ((x + 2) << 64) | ((x + 3) << 96)) 2119 })?; 2120 l.func_wrap("", "c", |x: V128, y: f64, z: V128| (x, y as i32, z))?; 2121 l.func_wrap( 2122 "", 2123 "d", 2124 |a0: V128, a1: V128, a2: V128, a3: V128, a4: V128, a5: V128, a6: V128, a7: V128| { 2125 let tmp = a0.as_u128() 2126 + a1.as_u128() 2127 + a2.as_u128() 2128 + a3.as_u128() 2129 + a4.as_u128() 2130 + a5.as_u128() 2131 + a6.as_u128() 2132 + a7.as_u128(); 2133 (tmp >> 0) as u32 + (tmp >> 32) as u32 + (tmp >> 64) as u32 + (tmp >> 96) as u32 2134 }, 2135 )?; 2136 2137 let i = l.instantiate(&mut store, &module)?; 2138 let a = i.get_typed_func::<V128, i32>(&mut store, "a")?; 2139 let b = i.get_typed_func::<i32, V128>(&mut store, "b")?; 2140 let c = i.get_typed_func::<(V128, f64, V128), (V128, i32, V128)>(&mut store, "c")?; 2141 let d = 2142 i.get_typed_func::<(V128, V128, V128, V128, V128, V128, V128, V128), i32>(&mut store, "d")?; 2143 2144 assert_eq!( 2145 a.call(&mut store, 0x00000004_00000003_00000002_00000001.into())?, 2146 1 + 2 + 3 + 4 2147 ); 2148 assert_eq!( 2149 b.call(&mut store, 0x10)?, 2150 V128::from(0x00000013_00000012_00000011_00000010), 2151 ); 2152 assert_eq!( 2153 c.call(&mut store, (1.into(), 2., 3.into()))?, 2154 (V128::from(1), 2, V128::from(3)), 2155 ); 2156 assert_eq!( 2157 d.call( 2158 &mut store, 2159 ( 2160 1.into(), 2161 2.into(), 2162 3.into(), 2163 4.into(), 2164 5.into(), 2165 6.into(), 2166 7.into(), 2167 8.into(), 2168 ) 2169 )?, 2170 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 2171 ); 2172 2173 Ok(()) 2174 } 2175 2176 #[wasmtime_test(wasm_features(function_references, gc))] 2177 #[cfg_attr(miri, ignore)] 2178 fn wrap_and_typed_i31ref(config: &mut Config) -> Result<()> { 2179 let engine = Engine::new(&config)?; 2180 let mut store = Store::<AtomicUsize>::new(&engine, AtomicUsize::new(0)); 2181 2182 let mut linker = Linker::new(&engine); 2183 linker.func_wrap( 2184 "env", 2185 "i31ref", 2186 |caller: Caller<'_, AtomicUsize>, x: Option<I31>| -> Option<I31> { 2187 assert_eq!(caller.data().fetch_add(1, Ordering::SeqCst), 0); 2188 x 2189 }, 2190 )?; 2191 linker.func_wrap( 2192 "env", 2193 "ref-i31", 2194 |caller: Caller<'_, AtomicUsize>, x: I31| -> I31 { 2195 assert_eq!(caller.data().fetch_add(1, Ordering::SeqCst), 1); 2196 x 2197 }, 2198 )?; 2199 2200 let module = Module::new( 2201 &engine, 2202 r#" 2203 (module 2204 (import "env" "i31ref" (func (param i31ref) (result i31ref))) 2205 (import "env" "ref-i31" (func (param (ref i31)) (result (ref i31)))) 2206 2207 (func (export "i31ref") (param i31ref) (result i31ref) 2208 local.get 0 2209 call 0 2210 ) 2211 2212 (func (export "ref-i31") (param (ref i31)) (result (ref i31)) 2213 local.get 0 2214 call 1 2215 ) 2216 ) 2217 "#, 2218 )?; 2219 2220 let instance = linker.instantiate(&mut store, &module)?; 2221 2222 let i31ref = instance.get_typed_func::<Option<I31>, Option<I31>>(&mut store, "i31ref")?; 2223 let x = i31ref.call(&mut store, Some(I31::wrapping_u32(42)))?; 2224 assert_eq!(x, Some(I31::wrapping_u32(42))); 2225 2226 let ref_i31 = instance.get_typed_func::<I31, I31>(&mut store, "ref-i31")?; 2227 let x = ref_i31.call(&mut store, I31::wrapping_u32(0x1234))?; 2228 assert_eq!(x, I31::wrapping_u32(0x1234)); 2229 2230 assert_eq!(store.data().load(Ordering::SeqCst), 2); 2231 Ok(()) 2232 } 2233 2234 #[wasmtime_test(wasm_features(function_references, gc))] 2235 fn call_func_with_funcref_both_typed_and_untyped(config: &mut Config) -> Result<()> { 2236 let engine = Engine::new(&config)?; 2237 let mut store = Store::new(&engine, ()); 2238 2239 let f1 = Func::wrap(&mut store, |_: Option<Func>| {}); 2240 let f2 = Func::wrap(&mut store, || {}); 2241 2242 f1.typed::<Func, ()>(&mut store)?.call(&mut store, f2)?; 2243 f1.call(&mut store, &[Val::FuncRef(Some(f2))], &mut [])?; 2244 Ok(()) 2245 } 2246 2247 #[wasmtime_test(wasm_features(function_references, gc))] 2248 #[cfg_attr(miri, ignore)] 2249 fn wasm_to_host_trampolines_and_subtyping(config: &mut Config) -> Result<()> { 2250 let _ = env_logger::try_init(); 2251 2252 let engine = Engine::new(&config)?; 2253 2254 let ft0 = FuncType::with_finality_and_supertype( 2255 &engine, 2256 Finality::NonFinal, 2257 None, 2258 [], 2259 [ValType::Ref(RefType::new(true, HeapType::Extern))], 2260 )?; 2261 let ft1 = FuncType::with_finality_and_supertype( 2262 &engine, 2263 Finality::NonFinal, 2264 Some(&ft0), 2265 [], 2266 [ValType::Ref(RefType::new(false, HeapType::Extern))], 2267 )?; 2268 2269 let module = Module::new( 2270 &engine, 2271 r#" 2272 (module 2273 (type $ft0 (sub (func (result (ref null extern))))) 2274 2275 (import "" "a" (func $imported_func (type $ft0))) 2276 (import "" "return_func" (func $return_func (result (ref $ft0)))) 2277 (global $g (export "g") (mut (ref null $ft0)) (ref.null $ft0)) 2278 (table $t (export "t") 10 10 (ref null $ft0)) 2279 2280 (func (export "f") 2281 (drop (call $imported_func)) 2282 (drop (call_ref $ft0 (call $return_func))) 2283 (drop (call_ref $ft0 (global.get $g))) 2284 (drop (call_ref $ft0 (table.get $t (i32.const 0)))) 2285 ) 2286 ) 2287 "#, 2288 )?; 2289 2290 // This defines a function of type `(func (result (ref extern)))` and not of 2291 // type `(func (result (ref null extern)))` that the Wasm imports. But it is 2292 // still a subtype of the Wasm import's type, so we should be able to use 2293 // the Wasm's precompiled trampolines with this host function. 2294 // 2295 // But this means we also need to look up the trampoline by the caller's 2296 // type, rather than the callee's type. 2297 // 2298 // So give it to Wasm in every way that Wasm can receive a function, and 2299 // make sure we find the correct trampolines in all cases and everything 2300 // works. 2301 let make_func = |store: &mut Store<_>| { 2302 Func::new( 2303 store, 2304 ft1.clone(), 2305 |mut caller: Caller<'_, ()>, _args, results| { 2306 results[0] = ExternRef::new(&mut caller, 200)?.into(); 2307 Ok(()) 2308 }, 2309 ) 2310 }; 2311 2312 let return_func_ty = module.imports().nth(1).unwrap().ty().unwrap_func().clone(); 2313 2314 let mut store = Store::new(&engine, ()); 2315 2316 let imported_func = make_func(&mut store); 2317 assert!(FuncType::eq(&imported_func.ty(&store), &ft1)); 2318 2319 let returned_func = make_func(&mut store); 2320 assert!(FuncType::eq(&returned_func.ty(&store), &ft1)); 2321 2322 let return_func = Func::new( 2323 &mut store, 2324 return_func_ty.clone(), 2325 move |_caller, _args, results| { 2326 results[0] = returned_func.into(); 2327 Ok(()) 2328 }, 2329 ); 2330 2331 let instance = Instance::new( 2332 &mut store, 2333 &module, 2334 &[imported_func.into(), return_func.into()], 2335 )?; 2336 2337 let g = make_func(&mut store); 2338 assert!(FuncType::eq(&g.ty(&store), &ft1)); 2339 instance 2340 .get_global(&mut store, "g") 2341 .unwrap() 2342 .set(&mut store, g.into())?; 2343 2344 let t = make_func(&mut store); 2345 assert!(FuncType::eq(&t.ty(&store), &ft1)); 2346 instance 2347 .get_table(&mut store, "t") 2348 .unwrap() 2349 .set(&mut store, 0, t.into())?; 2350 2351 let f = instance.get_typed_func::<(), ()>(&mut store, "f")?; 2352 f.call(&mut store, ())?; 2353 2354 Ok(()) 2355 } 2356