1 use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t}; 2 use crate::{wasm_instancetype_t, wasm_store_t, wasmtime_error_t}; 3 use anyhow::Result; 4 use std::ptr; 5 use wasmtime::{Extern, Instance, Trap}; 6 7 #[derive(Clone)] 8 #[repr(transparent)] 9 pub struct wasm_instance_t { 10 ext: wasm_extern_t, 11 } 12 13 wasmtime_c_api_macros::declare_ref!(wasm_instance_t); 14 15 impl wasm_instance_t { 16 pub(crate) fn new(instance: Instance) -> wasm_instance_t { 17 wasm_instance_t { 18 ext: wasm_extern_t { 19 which: instance.into(), 20 }, 21 } 22 } 23 24 pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_instance_t> { 25 match &e.which { 26 Extern::Instance(_) => Some(unsafe { &*(e as *const _ as *const _) }), 27 _ => None, 28 } 29 } 30 31 pub(crate) fn instance(&self) -> &Instance { 32 match &self.ext.which { 33 Extern::Instance(i) => i, 34 _ => unreachable!(), 35 } 36 } 37 } 38 39 #[no_mangle] 40 pub unsafe extern "C" fn wasm_instance_new( 41 store: &wasm_store_t, 42 wasm_module: &wasm_module_t, 43 imports: *const wasm_extern_vec_t, 44 result: Option<&mut *mut wasm_trap_t>, 45 ) -> Option<Box<wasm_instance_t>> { 46 let mut instance = ptr::null_mut(); 47 let mut trap = ptr::null_mut(); 48 let err = _wasmtime_instance_new( 49 store, 50 wasm_module, 51 (*imports).as_slice(), 52 &mut instance, 53 &mut trap, 54 ); 55 match err { 56 Some(err) => { 57 assert!(trap.is_null()); 58 assert!(instance.is_null()); 59 if let Some(result) = result { 60 *result = Box::into_raw(err.to_trap()); 61 } 62 None 63 } 64 None => { 65 if instance.is_null() { 66 assert!(!trap.is_null()); 67 if let Some(result) = result { 68 *result = trap; 69 } else { 70 drop(Box::from_raw(trap)) 71 } 72 None 73 } else { 74 assert!(trap.is_null()); 75 Some(Box::from_raw(instance)) 76 } 77 } 78 } 79 } 80 81 #[no_mangle] 82 pub unsafe extern "C" fn wasmtime_instance_new( 83 store: &wasm_store_t, 84 module: &wasm_module_t, 85 imports: *const wasm_extern_vec_t, 86 instance_ptr: &mut *mut wasm_instance_t, 87 trap_ptr: &mut *mut wasm_trap_t, 88 ) -> Option<Box<wasmtime_error_t>> { 89 _wasmtime_instance_new(store, module, (*imports).as_slice(), instance_ptr, trap_ptr) 90 } 91 92 fn _wasmtime_instance_new( 93 store: &wasm_store_t, 94 module: &wasm_module_t, 95 imports: &[Option<Box<wasm_extern_t>>], 96 instance_ptr: &mut *mut wasm_instance_t, 97 trap_ptr: &mut *mut wasm_trap_t, 98 ) -> Option<Box<wasmtime_error_t>> { 99 let store = &store.store; 100 let imports = imports 101 .iter() 102 .filter_map(|import| match import { 103 Some(i) => Some(i.which.clone()), 104 None => None, 105 }) 106 .collect::<Vec<_>>(); 107 handle_instantiate( 108 Instance::new(store, module.module(), &imports), 109 instance_ptr, 110 trap_ptr, 111 ) 112 } 113 114 pub fn handle_instantiate( 115 instance: Result<Instance>, 116 instance_ptr: &mut *mut wasm_instance_t, 117 trap_ptr: &mut *mut wasm_trap_t, 118 ) -> Option<Box<wasmtime_error_t>> { 119 fn write<T>(ptr: &mut *mut T, val: T) { 120 *ptr = Box::into_raw(Box::new(val)) 121 } 122 123 match instance { 124 Ok(instance) => { 125 write(instance_ptr, wasm_instance_t::new(instance)); 126 None 127 } 128 Err(e) => match e.downcast::<Trap>() { 129 Ok(trap) => { 130 write(trap_ptr, wasm_trap_t::new(trap)); 131 None 132 } 133 Err(e) => Some(Box::new(e.into())), 134 }, 135 } 136 } 137 138 #[no_mangle] 139 pub extern "C" fn wasm_instance_as_extern(m: &wasm_instance_t) -> &wasm_extern_t { 140 &m.ext 141 } 142 143 #[no_mangle] 144 pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) { 145 out.set_buffer( 146 instance 147 .instance() 148 .exports() 149 .map(|e| { 150 Some(Box::new(wasm_extern_t { 151 which: e.into_extern(), 152 })) 153 }) 154 .collect(), 155 ); 156 } 157 158 #[no_mangle] 159 pub extern "C" fn wasm_instance_type(f: &wasm_instance_t) -> Box<wasm_instancetype_t> { 160 Box::new(wasm_instancetype_t::new(f.instance().ty())) 161 } 162