1 use anyhow::bail; 2 use std::sync::Arc; 3 use std::sync::atomic::Ordering; 4 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst}; 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) -> anyhow::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) -> anyhow::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() -> anyhow::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) -> anyhow::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) -> anyhow::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() -> anyhow::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) -> anyhow::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) -> anyhow::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() -> anyhow::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) -> anyhow::Result<()> { 1265 fn test<T>(store: &mut Store<()>, t: T) -> anyhow::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))] 1429 #[cfg_attr(miri, ignore)] 1430 fn trampoline_for_declared_elem(config: &mut Config) -> anyhow::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<(), anyhow::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(config: &mut Config) -> anyhow::Result<()> { 1516 let engine = Engine::new(&config)?; 1517 let mut store = Store::<()>::new(&engine, ()); 1518 let module = Module::new( 1519 store.engine(), 1520 r#" 1521 (module 1522 (func (export "f") (param i32 i32)) 1523 ) 1524 1525 "#, 1526 )?; 1527 let instance = Instance::new(&mut store, &module, &[])?; 1528 1529 // Too few parameters. 1530 match instance.get_typed_func::<(), ()>(&mut store, "f") { 1531 Ok(_) => panic!("should be wrong signature"), 1532 Err(e) => { 1533 let msg = format!("{e:?}"); 1534 assert!(dbg!(msg).contains("expected 0 types, found 2")) 1535 } 1536 } 1537 match instance.get_typed_func::<(i32,), ()>(&mut store, "f") { 1538 Ok(_) => panic!("should be wrong signature"), 1539 Err(e) => { 1540 let msg = format!("{e:?}"); 1541 assert!(dbg!(msg).contains("expected 1 types, found 2")) 1542 } 1543 } 1544 1545 // Too many parameters. 1546 match instance.get_typed_func::<(i32, i32, i32), ()>(&mut store, "f") { 1547 Ok(_) => panic!("should be wrong signature"), 1548 Err(e) => { 1549 let msg = format!("{e:?}"); 1550 assert!(dbg!(msg).contains("expected 3 types, found 2")) 1551 } 1552 } 1553 1554 Ok(()) 1555 } 1556 1557 #[wasmtime_test(wasm_features(reference_types, gc_types))] 1558 #[cfg_attr(miri, ignore)] 1559 fn calls_with_funcref_and_externref(config: &mut Config) -> anyhow::Result<()> { 1560 let engine = Engine::new(&config)?; 1561 let mut store = Store::<()>::new(&engine, ()); 1562 let module = Module::new( 1563 store.engine(), 1564 r#" 1565 (module 1566 (import "" "witness" (func $witness (param funcref externref))) 1567 (func (export "f") (param funcref externref) (result externref funcref) 1568 local.get 0 1569 local.get 1 1570 call $witness 1571 local.get 1 1572 local.get 0 1573 ) 1574 ) 1575 1576 "#, 1577 )?; 1578 let mut linker = Linker::new(store.engine()); 1579 linker.func_wrap( 1580 "", 1581 "witness", 1582 |mut caller: Caller<'_, ()>, func: Option<Func>, externref: Option<Rooted<ExternRef>>| { 1583 if func.is_some() { 1584 assert_my_funcref(&mut caller, func.as_ref())?; 1585 } 1586 if externref.is_some() { 1587 assert_my_externref(&caller, externref); 1588 } 1589 Ok(()) 1590 }, 1591 )?; 1592 let instance = linker.instantiate(&mut store, &module)?; 1593 1594 let typed = instance 1595 .get_typed_func::<(Option<Func>, Option<Rooted<ExternRef>>), (Option<Rooted<ExternRef>>, Option<Func>)>( 1596 &mut store, "f", 1597 )?; 1598 let untyped = typed.func(); 1599 1600 let my_funcref = Func::wrap(&mut store, || 100u32); 1601 let my_externref = ExternRef::new(&mut store, 99u32)?; 1602 let mut results = [Val::I32(0), Val::I32(0)]; 1603 1604 fn assert_my_funcref(mut store: impl AsContextMut, func: Option<&Func>) -> Result<()> { 1605 let mut store = store.as_context_mut(); 1606 let func = func.unwrap(); 1607 assert_eq!(func.typed::<(), u32>(&store)?.call(&mut store, ())?, 100); 1608 Ok(()) 1609 } 1610 fn assert_my_externref(store: impl AsContext, externref: Option<Rooted<ExternRef>>) { 1611 assert_eq!( 1612 externref 1613 .unwrap() 1614 .data(&store) 1615 .unwrap() 1616 .unwrap() 1617 .downcast_ref(), 1618 Some(&99u32) 1619 ); 1620 } 1621 1622 // funcref=null, externref=null 1623 let (a, b) = typed.call(&mut store, (None, None))?; 1624 assert!(a.is_none()); 1625 assert!(b.is_none()); 1626 untyped.call( 1627 &mut store, 1628 &[Val::FuncRef(None), Val::ExternRef(None)], 1629 &mut results, 1630 )?; 1631 assert!(results[0].unwrap_externref().is_none()); 1632 assert!(results[1].unwrap_funcref().is_none()); 1633 1634 // funcref=Some, externref=null 1635 let (a, b) = typed.call(&mut store, (Some(my_funcref), None))?; 1636 assert!(a.is_none()); 1637 assert_my_funcref(&mut store, b.as_ref())?; 1638 untyped.call( 1639 &mut store, 1640 &[Val::FuncRef(Some(my_funcref)), Val::ExternRef(None)], 1641 &mut results, 1642 )?; 1643 assert!(results[0].unwrap_externref().is_none()); 1644 assert_my_funcref(&mut store, results[1].unwrap_funcref())?; 1645 1646 // funcref=null, externref=Some 1647 let (a, b) = typed.call(&mut store, (None, Some(my_externref)))?; 1648 assert_my_externref(&store, a); 1649 assert!(b.is_none()); 1650 untyped.call( 1651 &mut store, 1652 &[Val::FuncRef(None), Val::ExternRef(Some(my_externref))], 1653 &mut results, 1654 )?; 1655 assert_my_externref(&store, results[0].unwrap_externref().copied()); 1656 assert!(results[1].unwrap_funcref().is_none()); 1657 1658 // funcref=Some, externref=Some 1659 let (a, b) = typed.call(&mut store, (Some(my_funcref), Some(my_externref)))?; 1660 assert_my_externref(&store, a); 1661 assert_my_funcref(&mut store, b.as_ref())?; 1662 untyped.call( 1663 &mut store, 1664 &[ 1665 Val::FuncRef(Some(my_funcref)), 1666 Val::ExternRef(Some(my_externref)), 1667 ], 1668 &mut results, 1669 )?; 1670 assert_my_externref(&store, results[0].unwrap_externref().copied()); 1671 assert_my_funcref(&mut store, results[1].unwrap_funcref())?; 1672 1673 Ok(()) 1674 } 1675 1676 #[wasmtime_test(wasm_features(function_references))] 1677 #[cfg_attr(miri, ignore)] 1678 fn typed_concrete_param(config: &mut Config) -> anyhow::Result<()> { 1679 let engine = Engine::new(&config)?; 1680 let module = Module::new( 1681 &engine, 1682 r#" 1683 (module 1684 (type $t (func)) 1685 (func (export "f") (param (ref null $t))) 1686 ) 1687 "#, 1688 )?; 1689 let mut store = Store::new(&engine, ()); 1690 let instance = Instance::new(&mut store, &module, &[])?; 1691 1692 let nop = Func::new( 1693 &mut store, 1694 FuncType::new(&engine, None, None), 1695 |_caller, _params, _results| Ok(()), 1696 ); 1697 1698 let f = instance.get_func(&mut store, "f").unwrap(); 1699 1700 // Can type with a subtype, which should avoid all dynamic type checks after 1701 // successful construction. 1702 let a = f.typed::<Option<NoFunc>, ()>(&store)?; 1703 a.call(&mut store, None)?; 1704 // NB: Cannot call with Some(_) as `NoFunc` is uninhabited. 1705 1706 // Can call `typed` with a supertype, falling back to dynamic type checks on 1707 // each call. 1708 let a = f.typed::<Option<Func>, ()>(&store)?; 1709 a.call(&mut store, None)?; 1710 a.call(&mut store, Some(nop))?; 1711 let e = a.call(&mut store, Some(f)).expect_err( 1712 "should return an error because while we did pass an instance of \ 1713 `Option<Func>`, it was not an instance of `(ref null $t)`", 1714 ); 1715 let e = format!("{e:?}"); 1716 assert!(e.contains("argument type mismatch for reference to concrete type")); 1717 assert!(e.contains( 1718 "type mismatch: expected (type (func)), \ 1719 found (type (func (param (ref null (concrete func VMSharedTypeIndex(0))))))" 1720 )); 1721 1722 // And dynamic checks also work with a non-nullable super type. 1723 let a = f.typed::<Func, ()>(&store)?; 1724 a.call(&mut store, nop)?; 1725 let e = a.call(&mut store, f).expect_err( 1726 "should return an error because while we did pass an instance of \ 1727 `Func`, it was not an instance of `(ref null $t)`", 1728 ); 1729 let e = format!("{e:?}"); 1730 assert!(e.contains("argument type mismatch for reference to concrete type")); 1731 assert!(e.contains( 1732 "type mismatch: expected (type (func)), \ 1733 found (type (func (param (ref null (concrete func VMSharedTypeIndex(0))))))" 1734 )); 1735 1736 // Calling `typed` with a type that is not a supertype nor a subtype fails 1737 // the initial type check. 1738 let e = f 1739 .typed::<Option<Rooted<ExternRef>>, ()>(&store) 1740 .err() 1741 .unwrap(); 1742 let e = format!("{e:?}"); 1743 assert!(e.contains("type mismatch with parameters")); 1744 assert!(e.contains("type mismatch: expected func, found extern")); 1745 1746 Ok(()) 1747 } 1748 1749 #[wasmtime_test(wasm_features(function_references))] 1750 #[cfg_attr(miri, ignore)] 1751 fn typed_concrete_result(config: &mut Config) -> anyhow::Result<()> { 1752 let engine = Engine::new(&config)?; 1753 let module = Module::new( 1754 &engine, 1755 r#" 1756 (module 1757 (type $t (func)) 1758 (func $nop) 1759 (elem declare func $nop) 1760 (func (export "f") (result (ref $t)) 1761 ref.func $nop 1762 ) 1763 ) 1764 "#, 1765 )?; 1766 let mut store = Store::new(&engine, ()); 1767 let instance = Instance::new(&mut store, &module, &[])?; 1768 1769 let f = instance.get_func(&mut store, "f").unwrap(); 1770 1771 // Can type `f` with a supertype of the declared result type, and we get the 1772 // expected return value. 1773 let a = f.typed::<(), Func>(&store)?; 1774 let g = a.call(&mut store, ())?; 1775 g.typed::<(), ()>(&store)?.call(&mut store, ())?; 1776 1777 // Also works with a nullable supertype. 1778 let a = f.typed::<(), Option<Func>>(&store)?; 1779 let g = a.call(&mut store, ())?; 1780 g.unwrap().typed::<(), ()>(&store)?.call(&mut store, ())?; 1781 1782 // But we can't claim that `f` returns a particular subtype of its actual 1783 // return type. 1784 let e = f.typed::<(), NoFunc>(&store).err().unwrap(); 1785 let e = format!("{e:?}"); 1786 assert!(e.contains("type mismatch with results")); 1787 assert!(e.contains( 1788 "type mismatch: expected (ref nofunc), found (ref (concrete func VMSharedTypeIndex(0)))" 1789 )); 1790 1791 // Nor some unrelated type that it is neither a subtype or supertype of. 1792 let e = f.typed::<(), Rooted<ExternRef>>(&store).err().unwrap(); 1793 let e = format!("{e:?}"); 1794 assert!(e.contains("type mismatch with results")); 1795 assert!(e.contains( 1796 "type mismatch: expected (ref extern), found (ref (concrete func VMSharedTypeIndex(0)))" 1797 )); 1798 1799 Ok(()) 1800 } 1801 1802 #[test] 1803 #[cfg_attr(miri, ignore)] 1804 fn wrap_subtype_param() -> anyhow::Result<()> { 1805 let mut store = Store::<()>::default(); 1806 let f = Func::wrap(&mut store, |_caller: Caller<'_, ()>, _: Option<Func>| { 1807 // No-op. 1808 }); 1809 1810 // Precise type. 1811 let a = f.typed::<Option<Func>, ()>(&store)?; 1812 a.call(&mut store, None)?; 1813 a.call(&mut store, Some(f))?; 1814 1815 // Subtype via heap type. 1816 let a = f.typed::<Option<NoFunc>, ()>(&store)?; 1817 a.call(&mut store, None)?; 1818 1819 // Subtype via non-null. 1820 let a = f.typed::<Func, ()>(&store)?; 1821 a.call(&mut store, f)?; 1822 1823 Ok(()) 1824 } 1825 1826 #[test] 1827 #[cfg_attr(miri, ignore)] 1828 fn wrap_supertype_result() -> anyhow::Result<()> { 1829 let mut store = Store::<()>::default(); 1830 let f = Func::wrap(&mut store, |_caller: Caller<'_, ()>| -> NoFunc { 1831 unreachable!() 1832 }); 1833 1834 // Precise type. 1835 let _ = f.typed::<(), NoFunc>(&store)?; 1836 1837 // Supertype via heap type. 1838 let _ = f.typed::<(), Func>(&store)?; 1839 1840 // Supertype via nullability. 1841 let _ = f.typed::<(), Option<NoFunc>>(&store)?; 1842 1843 Ok(()) 1844 } 1845 1846 #[wasmtime_test(wasm_features(function_references))] 1847 #[cfg_attr(miri, ignore)] 1848 fn call_wasm_passing_subtype_func_param(config: &mut Config) -> anyhow::Result<()> { 1849 config.wasm_function_references(true); 1850 let engine = Engine::new(&config)?; 1851 let mut store = Store::new(&engine, ()); 1852 1853 let module = Module::new( 1854 &engine, 1855 r#" 1856 (module 1857 (type $ty (func (result funcref))) 1858 (func (export "f") (param (ref null $ty)) (result funcref) 1859 ;; Return null if the funcref is null. 1860 ref.null func 1861 local.get 0 1862 ref.is_null 1863 br_if 0 1864 drop 1865 1866 ;; Otherwise, call it. 1867 local.get 0 1868 call_ref $ty 1869 ) 1870 ) 1871 "#, 1872 )?; 1873 1874 let instance = Instance::new(&mut store, &module, &[])?; 1875 let f = instance.get_func(&mut store, "f").unwrap(); 1876 1877 let g_ty = FuncType::new(&engine, None, Some(ValType::I32)); 1878 let g = Func::new(&mut store, g_ty.clone(), |_caller, _params, results| { 1879 results[0] = Val::I32(0x1234_5678); 1880 Ok(()) 1881 }); 1882 1883 // h's type is a subtype of the Wasm-defined `$ty`: 1884 // 1885 // (func (result (ref null g_ty))) <: (func (result funcref)) 1886 let h_ty = FuncType::new( 1887 &engine, 1888 None, 1889 Some(ValType::Ref(RefType::new( 1890 true, 1891 HeapType::ConcreteFunc(g_ty), 1892 ))), 1893 ); 1894 let h = Func::new(&mut store, h_ty, move |_caller, _params, results| { 1895 results[0] = Val::FuncRef(Some(g)); 1896 Ok(()) 1897 }); 1898 1899 // Array call, passing in a subtype of the expected parameter. 1900 1901 let mut results = vec![Val::I32(0)]; 1902 f.call(&mut store, &[Val::null_func_ref()], &mut results)?; 1903 assert!(results[0].unwrap_func_ref().is_none()); 1904 1905 f.call(&mut store, &[h.into()], &mut results)?; 1906 let g = results[0]; 1907 let g = g.unwrap_func_ref().unwrap(); 1908 g.call(&mut store, &[], &mut results)?; 1909 assert_eq!(results[0].unwrap_i32(), 0x1234_5678); 1910 1911 // Native call, passing in a subtype of the expected parameter. 1912 1913 let f = f.typed::<Option<Func>, Option<Func>>(&store)?; 1914 let r = f.call(&mut store, None)?; 1915 assert!(r.is_none()); 1916 1917 let g = f.call(&mut store, Some(h))?; 1918 let g = g.unwrap().typed::<(), u32>(&mut store)?; 1919 let x = g.call(&mut store, ())?; 1920 assert_eq!(x, 0x1234_5678); 1921 1922 Ok(()) 1923 } 1924 1925 #[wasmtime_test(wasm_features(gc, function_references))] 1926 #[cfg_attr(miri, ignore)] 1927 fn call_wasm_getting_subtype_func_return(config: &mut Config) -> anyhow::Result<()> { 1928 let engine = Engine::new(&config)?; 1929 let mut store = Store::new(&engine, ()); 1930 1931 let module = Module::new( 1932 &engine, 1933 r#" 1934 (module 1935 (type $ty (func (result funcref))) 1936 1937 (func $a (result i32) 1938 i32.const 0x12345678 1939 ) 1940 1941 (func $b (result funcref) 1942 ref.func $a 1943 ) 1944 1945 (elem declare func $a $b) 1946 1947 ;; Returns a `(ref null nofunc)` if called with `0`, otherwise 1948 ;; returns `(ref null $ty)`, both of which are subtypes of 1949 ;; `funcref`. 1950 (func (export "f") (param i32) (result funcref) 1951 block 1952 local.get 0 1953 br_if 0 1954 ref.null nofunc 1955 return 1956 end 1957 ref.func $b 1958 ) 1959 ) 1960 "#, 1961 )?; 1962 1963 let instance = Instance::new(&mut store, &module, &[])?; 1964 let f = instance.get_func(&mut store, "f").unwrap(); 1965 1966 // Array call, receiving a subtype of the expected result. 1967 1968 let mut results = vec![Val::I32(0)]; 1969 f.call(&mut store, &[Val::I32(0)], &mut results)?; 1970 assert!(results[0].unwrap_func_ref().is_none()); 1971 1972 f.call(&mut store, &[Val::I32(1)], &mut results)?; 1973 let b = results[0]; 1974 let b = b.unwrap_func_ref().unwrap(); 1975 b.call(&mut store, &[], &mut results)?; 1976 let a = results[0]; 1977 let a = a.unwrap_func_ref().unwrap(); 1978 a.call(&mut store, &[], &mut results)?; 1979 assert_eq!(results[0].unwrap_i32(), 0x1234_5678); 1980 1981 // Native call, receiving a subtype of the expected result. 1982 1983 let f = f.typed::<u32, Option<Func>>(&store)?; 1984 let r = f.call(&mut store, 0)?; 1985 assert!(r.is_none()); 1986 1987 let b = f.call(&mut store, 1)?; 1988 let b = b.unwrap().typed::<(), Option<Func>>(&store)?; 1989 let a = b.call(&mut store, ())?; 1990 let a = a.unwrap().typed::<(), u32>(&store)?; 1991 let x = a.call(&mut store, ())?; 1992 assert_eq!(x, 0x1234_5678); 1993 1994 Ok(()) 1995 } 1996 1997 #[wasmtime_test(wasm_features(simd), strategies(not(Winch)))] 1998 #[cfg_attr(miri, ignore)] 1999 fn typed_v128(config: &mut Config) -> anyhow::Result<()> { 2000 let engine = Engine::new(&config)?; 2001 let mut store = Store::<()>::new(&engine, ()); 2002 let module = Module::new( 2003 store.engine(), 2004 r#" 2005 (module 2006 (func (export "a") (param v128) (result v128) 2007 local.get 0) 2008 (func (export "b") (param v128 v128) (result v128 v128) 2009 local.get 0 2010 local.get 1) 2011 (func (export "c") (param v128 v128 v128 v128 v128 v128 v128 v128) (result v128) 2012 local.get 0 2013 local.get 1 2014 local.get 2 2015 local.get 3 2016 local.get 4 2017 local.get 5 2018 local.get 6 2019 local.get 7 2020 i64x2.add 2021 i64x2.add 2022 i64x2.add 2023 i64x2.add 2024 i64x2.add 2025 i64x2.add 2026 i64x2.add) 2027 ) 2028 2029 "#, 2030 )?; 2031 let instance = Instance::new(&mut store, &module, &[])?; 2032 2033 let a = instance.get_typed_func::<V128, V128>(&mut store, "a")?; 2034 assert_eq!(a.call(&mut store, V128::from(1))?, V128::from(1)); 2035 assert_eq!(a.call(&mut store, V128::from(2))?, V128::from(2)); 2036 2037 let b = instance.get_typed_func::<(V128, V128), (V128, V128)>(&mut store, "b")?; 2038 assert_eq!( 2039 b.call(&mut store, (V128::from(1), V128::from(2)))?, 2040 (V128::from(1), V128::from(2)) 2041 ); 2042 2043 let c = instance.get_typed_func::<(V128, V128, V128, V128, V128, V128, V128, V128), V128>( 2044 &mut store, "c", 2045 )?; 2046 assert_eq!( 2047 c.call( 2048 &mut store, 2049 ( 2050 V128::from(1), 2051 V128::from(2), 2052 V128::from(3), 2053 V128::from(4), 2054 V128::from(5), 2055 V128::from(6), 2056 V128::from(7), 2057 V128::from(8), 2058 ) 2059 )?, 2060 V128::from(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8), 2061 ); 2062 2063 Ok(()) 2064 } 2065 2066 #[wasmtime_test(wasm_features(simd))] 2067 #[cfg_attr(miri, ignore)] 2068 fn typed_v128_imports(config: &mut Config) -> anyhow::Result<()> { 2069 let engine = Engine::new(&config)?; 2070 let mut store = Store::<()>::new(&engine, ()); 2071 let module = Module::new( 2072 store.engine(), 2073 r#" 2074 (module 2075 (import "" "a" (func $a (param v128) (result i32))) 2076 (import "" "b" (func $b (param i32) (result v128))) 2077 (import "" "c" (func $c (param v128 f64 v128) (result v128 i32 v128))) 2078 (import "" "d" (func $d (param v128 v128 v128 v128 v128 v128 v128 v128) (result i32))) 2079 2080 (func (export "a") (param v128) (result i32) 2081 local.get 0 2082 call $a) 2083 2084 (func (export "b") (param i32) (result v128) 2085 local.get 0 2086 call $b) 2087 2088 (func (export "c") (param v128 f64 v128) (result v128 i32 v128) 2089 local.get 0 2090 local.get 1 2091 local.get 2 2092 call $c) 2093 2094 (func (export "d") (param v128 v128 v128 v128 v128 v128 v128 v128) (result i32) 2095 local.get 0 2096 local.get 1 2097 local.get 2 2098 local.get 3 2099 local.get 4 2100 local.get 5 2101 local.get 6 2102 local.get 7 2103 call $d) 2104 ) 2105 2106 "#, 2107 )?; 2108 2109 let mut l = Linker::new(store.engine()); 2110 l.func_wrap("", "a", |x: V128| { 2111 let x = x.as_u128(); 2112 (x >> 0) as u32 + (x >> 32) as u32 + (x >> 64) as u32 + (x >> 96) as u32 2113 })?; 2114 l.func_wrap("", "b", |x: u32| { 2115 let x = u128::from(x); 2116 V128::from(x | ((x + 1) << 32) | ((x + 2) << 64) | ((x + 3) << 96)) 2117 })?; 2118 l.func_wrap("", "c", |x: V128, y: f64, z: V128| (x, y as i32, z))?; 2119 l.func_wrap( 2120 "", 2121 "d", 2122 |a0: V128, a1: V128, a2: V128, a3: V128, a4: V128, a5: V128, a6: V128, a7: V128| { 2123 let tmp = a0.as_u128() 2124 + a1.as_u128() 2125 + a2.as_u128() 2126 + a3.as_u128() 2127 + a4.as_u128() 2128 + a5.as_u128() 2129 + a6.as_u128() 2130 + a7.as_u128(); 2131 (tmp >> 0) as u32 + (tmp >> 32) as u32 + (tmp >> 64) as u32 + (tmp >> 96) as u32 2132 }, 2133 )?; 2134 2135 let i = l.instantiate(&mut store, &module)?; 2136 let a = i.get_typed_func::<V128, i32>(&mut store, "a")?; 2137 let b = i.get_typed_func::<i32, V128>(&mut store, "b")?; 2138 let c = i.get_typed_func::<(V128, f64, V128), (V128, i32, V128)>(&mut store, "c")?; 2139 let d = 2140 i.get_typed_func::<(V128, V128, V128, V128, V128, V128, V128, V128), i32>(&mut store, "d")?; 2141 2142 assert_eq!( 2143 a.call(&mut store, 0x00000004_00000003_00000002_00000001.into())?, 2144 1 + 2 + 3 + 4 2145 ); 2146 assert_eq!( 2147 b.call(&mut store, 0x10)?, 2148 V128::from(0x00000013_00000012_00000011_00000010), 2149 ); 2150 assert_eq!( 2151 c.call(&mut store, (1.into(), 2., 3.into()))?, 2152 (V128::from(1), 2, V128::from(3)), 2153 ); 2154 assert_eq!( 2155 d.call( 2156 &mut store, 2157 ( 2158 1.into(), 2159 2.into(), 2160 3.into(), 2161 4.into(), 2162 5.into(), 2163 6.into(), 2164 7.into(), 2165 8.into(), 2166 ) 2167 )?, 2168 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 2169 ); 2170 2171 Ok(()) 2172 } 2173 2174 #[wasmtime_test(wasm_features(function_references, gc))] 2175 #[cfg_attr(miri, ignore)] 2176 fn wrap_and_typed_i31ref(config: &mut Config) -> Result<()> { 2177 let engine = Engine::new(&config)?; 2178 let mut store = Store::<AtomicUsize>::new(&engine, AtomicUsize::new(0)); 2179 2180 let mut linker = Linker::new(&engine); 2181 linker.func_wrap( 2182 "env", 2183 "i31ref", 2184 |caller: Caller<'_, AtomicUsize>, x: Option<I31>| -> Option<I31> { 2185 assert_eq!(caller.data().fetch_add(1, Ordering::SeqCst), 0); 2186 x 2187 }, 2188 )?; 2189 linker.func_wrap( 2190 "env", 2191 "ref-i31", 2192 |caller: Caller<'_, AtomicUsize>, x: I31| -> I31 { 2193 assert_eq!(caller.data().fetch_add(1, Ordering::SeqCst), 1); 2194 x 2195 }, 2196 )?; 2197 2198 let module = Module::new( 2199 &engine, 2200 r#" 2201 (module 2202 (import "env" "i31ref" (func (param i31ref) (result i31ref))) 2203 (import "env" "ref-i31" (func (param (ref i31)) (result (ref i31)))) 2204 2205 (func (export "i31ref") (param i31ref) (result i31ref) 2206 local.get 0 2207 call 0 2208 ) 2209 2210 (func (export "ref-i31") (param (ref i31)) (result (ref i31)) 2211 local.get 0 2212 call 1 2213 ) 2214 ) 2215 "#, 2216 )?; 2217 2218 let instance = linker.instantiate(&mut store, &module)?; 2219 2220 let i31ref = instance.get_typed_func::<Option<I31>, Option<I31>>(&mut store, "i31ref")?; 2221 let x = i31ref.call(&mut store, Some(I31::wrapping_u32(42)))?; 2222 assert_eq!(x, Some(I31::wrapping_u32(42))); 2223 2224 let ref_i31 = instance.get_typed_func::<I31, I31>(&mut store, "ref-i31")?; 2225 let x = ref_i31.call(&mut store, I31::wrapping_u32(0x1234))?; 2226 assert_eq!(x, I31::wrapping_u32(0x1234)); 2227 2228 assert_eq!(store.data().load(Ordering::SeqCst), 2); 2229 Ok(()) 2230 } 2231 2232 #[wasmtime_test(wasm_features(function_references, gc))] 2233 fn call_func_with_funcref_both_typed_and_untyped(config: &mut Config) -> Result<()> { 2234 let engine = Engine::new(&config)?; 2235 let mut store = Store::new(&engine, ()); 2236 2237 let f1 = Func::wrap(&mut store, |_: Option<Func>| {}); 2238 let f2 = Func::wrap(&mut store, || {}); 2239 2240 f1.typed::<Func, ()>(&mut store)?.call(&mut store, f2)?; 2241 f1.call(&mut store, &[Val::FuncRef(Some(f2))], &mut [])?; 2242 Ok(()) 2243 } 2244 2245 #[wasmtime_test(wasm_features(function_references, gc))] 2246 #[cfg_attr(miri, ignore)] 2247 fn wasm_to_host_trampolines_and_subtyping(config: &mut Config) -> Result<()> { 2248 let _ = env_logger::try_init(); 2249 2250 let engine = Engine::new(&config)?; 2251 2252 let ft0 = FuncType::with_finality_and_supertype( 2253 &engine, 2254 Finality::NonFinal, 2255 None, 2256 [], 2257 [ValType::Ref(RefType::new(true, HeapType::Extern))], 2258 )?; 2259 let ft1 = FuncType::with_finality_and_supertype( 2260 &engine, 2261 Finality::NonFinal, 2262 Some(&ft0), 2263 [], 2264 [ValType::Ref(RefType::new(false, HeapType::Extern))], 2265 )?; 2266 2267 let module = Module::new( 2268 &engine, 2269 r#" 2270 (module 2271 (type $ft0 (sub (func (result (ref null extern))))) 2272 2273 (import "" "a" (func $imported_func (type $ft0))) 2274 (import "" "return_func" (func $return_func (result (ref $ft0)))) 2275 (global $g (export "g") (mut (ref null $ft0)) (ref.null $ft0)) 2276 (table $t (export "t") 10 10 (ref null $ft0)) 2277 2278 (func (export "f") 2279 (drop (call $imported_func)) 2280 (drop (call_ref $ft0 (call $return_func))) 2281 (drop (call_ref $ft0 (global.get $g))) 2282 (drop (call_ref $ft0 (table.get $t (i32.const 0)))) 2283 ) 2284 ) 2285 "#, 2286 )?; 2287 2288 // This defines a function of type `(func (result (ref extern)))` and not of 2289 // type `(func (result (ref null extern)))` that the Wasm imports. But it is 2290 // still a subtype of the Wasm import's type, so we should be able to use 2291 // the Wasm's precompiled trampolines with this host function. 2292 // 2293 // But this means we also need to look up the trampoline by the caller's 2294 // type, rather than the callee's type. 2295 // 2296 // So give it to Wasm in every way that Wasm can receive a function, and 2297 // make sure we find the correct trampolines in all cases and everything 2298 // works. 2299 let make_func = |store: &mut Store<_>| { 2300 Func::new( 2301 store, 2302 ft1.clone(), 2303 |mut caller: Caller<'_, ()>, _args, results| { 2304 results[0] = ExternRef::new(&mut caller, 200)?.into(); 2305 Ok(()) 2306 }, 2307 ) 2308 }; 2309 2310 let return_func_ty = module.imports().nth(1).unwrap().ty().unwrap_func().clone(); 2311 2312 let mut store = Store::new(&engine, ()); 2313 2314 let imported_func = make_func(&mut store); 2315 assert!(FuncType::eq(&imported_func.ty(&store), &ft1)); 2316 2317 let returned_func = make_func(&mut store); 2318 assert!(FuncType::eq(&returned_func.ty(&store), &ft1)); 2319 2320 let return_func = Func::new( 2321 &mut store, 2322 return_func_ty.clone(), 2323 move |_caller, _args, results| { 2324 results[0] = returned_func.into(); 2325 Ok(()) 2326 }, 2327 ); 2328 2329 let instance = Instance::new( 2330 &mut store, 2331 &module, 2332 &[imported_func.into(), return_func.into()], 2333 )?; 2334 2335 let g = make_func(&mut store); 2336 assert!(FuncType::eq(&g.ty(&store), &ft1)); 2337 instance 2338 .get_global(&mut store, "g") 2339 .unwrap() 2340 .set(&mut store, g.into())?; 2341 2342 let t = make_func(&mut store); 2343 assert!(FuncType::eq(&t.ty(&store), &ft1)); 2344 instance 2345 .get_table(&mut store, "t") 2346 .unwrap() 2347 .set(&mut store, 0, t.into())?; 2348 2349 let f = instance.get_typed_func::<(), ()>(&mut store, "f")?; 2350 f.call(&mut store, ())?; 2351 2352 Ok(()) 2353 } 2354