1 use crate::{ 2 WasmtimeStoreContext, WasmtimeStoreContextMut, bad_utf8, handle_result, wasm_engine_t, 3 wasm_functype_t, wasm_trap_t, wasmtime_error_t, wasmtime_extern_t, wasmtime_instance_pre_t, 4 wasmtime_module_t, 5 }; 6 use std::ffi::c_void; 7 use std::mem::MaybeUninit; 8 use std::str; 9 use wasmtime::{Func, Instance, Linker}; 10 11 #[repr(C)] 12 pub struct wasmtime_linker_t { 13 pub(crate) linker: Linker<crate::WasmtimeStoreData>, 14 } 15 16 wasmtime_c_api_macros::declare_own!(wasmtime_linker_t); 17 18 #[unsafe(no_mangle)] 19 pub extern "C" fn wasmtime_linker_new(engine: &wasm_engine_t) -> Box<wasmtime_linker_t> { 20 Box::new(wasmtime_linker_t { 21 linker: Linker::new(&engine.engine), 22 }) 23 } 24 25 #[unsafe(no_mangle)] 26 pub extern "C" fn wasmtime_linker_clone(linker: &wasmtime_linker_t) -> Box<wasmtime_linker_t> { 27 Box::new(wasmtime_linker_t { 28 linker: linker.linker.clone(), 29 }) 30 } 31 32 #[unsafe(no_mangle)] 33 pub extern "C" fn wasmtime_linker_allow_shadowing( 34 linker: &mut wasmtime_linker_t, 35 allow_shadowing: bool, 36 ) { 37 linker.linker.allow_shadowing(allow_shadowing); 38 } 39 40 macro_rules! to_str { 41 ($ptr:expr, $len:expr) => { 42 match str::from_utf8(crate::slice_from_raw_parts($ptr, $len)) { 43 Ok(s) => s, 44 Err(_) => return bad_utf8(), 45 } 46 }; 47 } 48 49 #[cfg(feature = "async")] 50 pub(crate) use to_str; 51 52 #[unsafe(no_mangle)] 53 pub unsafe extern "C" fn wasmtime_linker_define( 54 linker: &mut wasmtime_linker_t, 55 store: WasmtimeStoreContext<'_>, 56 module: *const u8, 57 module_len: usize, 58 name: *const u8, 59 name_len: usize, 60 item: &wasmtime_extern_t, 61 ) -> Option<Box<wasmtime_error_t>> { 62 let linker = &mut linker.linker; 63 let module = to_str!(module, module_len); 64 let name = to_str!(name, name_len); 65 let item = item.to_extern(); 66 handle_result(linker.define(&store, module, name, item), |_linker| ()) 67 } 68 69 #[unsafe(no_mangle)] 70 pub unsafe extern "C" fn wasmtime_linker_define_func( 71 linker: &mut wasmtime_linker_t, 72 module: *const u8, 73 module_len: usize, 74 name: *const u8, 75 name_len: usize, 76 ty: &wasm_functype_t, 77 callback: crate::wasmtime_func_callback_t, 78 data: *mut c_void, 79 finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, 80 ) -> Option<Box<wasmtime_error_t>> { 81 let ty = ty.ty().ty(linker.linker.engine()); 82 let module = to_str!(module, module_len); 83 let name = to_str!(name, name_len); 84 let cb = crate::func::c_callback_to_rust_fn(callback, data, finalizer); 85 handle_result(linker.linker.func_new(module, name, ty, cb), |_linker| ()) 86 } 87 88 #[unsafe(no_mangle)] 89 pub unsafe extern "C" fn wasmtime_linker_define_func_unchecked( 90 linker: &mut wasmtime_linker_t, 91 module: *const u8, 92 module_len: usize, 93 name: *const u8, 94 name_len: usize, 95 ty: &wasm_functype_t, 96 callback: crate::wasmtime_func_unchecked_callback_t, 97 data: *mut c_void, 98 finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, 99 ) -> Option<Box<wasmtime_error_t>> { 100 let ty = ty.ty().ty(linker.linker.engine()); 101 let module = to_str!(module, module_len); 102 let name = to_str!(name, name_len); 103 let cb = crate::func::c_unchecked_callback_to_rust_fn(callback, data, finalizer); 104 handle_result( 105 linker.linker.func_new_unchecked(module, name, ty, cb), 106 |_linker| (), 107 ) 108 } 109 110 #[cfg(feature = "wasi")] 111 #[unsafe(no_mangle)] 112 pub extern "C" fn wasmtime_linker_define_wasi( 113 linker: &mut wasmtime_linker_t, 114 ) -> Option<Box<wasmtime_error_t>> { 115 handle_result( 116 wasmtime_wasi::p1::add_to_linker_sync(&mut linker.linker, |ctx| { 117 ctx.wasi.as_mut().expect("wasi context must be populated") 118 }), 119 |_linker| (), 120 ) 121 } 122 123 #[unsafe(no_mangle)] 124 pub unsafe extern "C" fn wasmtime_linker_define_instance( 125 linker: &mut wasmtime_linker_t, 126 store: WasmtimeStoreContextMut<'_>, 127 name: *const u8, 128 name_len: usize, 129 instance: &Instance, 130 ) -> Option<Box<wasmtime_error_t>> { 131 let linker = &mut linker.linker; 132 let name = to_str!(name, name_len); 133 handle_result(linker.instance(store, name, *instance), |_linker| ()) 134 } 135 136 #[unsafe(no_mangle)] 137 pub extern "C" fn wasmtime_linker_instantiate( 138 linker: &wasmtime_linker_t, 139 store: WasmtimeStoreContextMut<'_>, 140 module: &wasmtime_module_t, 141 instance_ptr: &mut Instance, 142 trap_ptr: &mut *mut wasm_trap_t, 143 ) -> Option<Box<wasmtime_error_t>> { 144 let result = linker.linker.instantiate(store, &module.module); 145 super::instance::handle_instantiate(result, instance_ptr, trap_ptr) 146 } 147 148 #[unsafe(no_mangle)] 149 pub unsafe extern "C" fn wasmtime_linker_instantiate_pre( 150 linker: &wasmtime_linker_t, 151 module: &wasmtime_module_t, 152 instance_ptr: &mut *mut wasmtime_instance_pre_t, 153 ) -> Option<Box<wasmtime_error_t>> { 154 let linker = &linker.linker; 155 handle_result(linker.instantiate_pre(&module.module), |i| { 156 let instance_pre = Box::new(wasmtime_instance_pre_t { underlying: i }); 157 *instance_ptr = Box::into_raw(instance_pre) 158 }) 159 } 160 161 #[unsafe(no_mangle)] 162 pub unsafe extern "C" fn wasmtime_linker_module( 163 linker: &mut wasmtime_linker_t, 164 store: WasmtimeStoreContextMut<'_>, 165 name: *const u8, 166 name_len: usize, 167 module: &wasmtime_module_t, 168 ) -> Option<Box<wasmtime_error_t>> { 169 let linker = &mut linker.linker; 170 let name = to_str!(name, name_len); 171 handle_result(linker.module(store, name, &module.module), |_linker| ()) 172 } 173 174 #[unsafe(no_mangle)] 175 pub unsafe extern "C" fn wasmtime_linker_get_default( 176 linker: &wasmtime_linker_t, 177 store: WasmtimeStoreContextMut<'_>, 178 name: *const u8, 179 name_len: usize, 180 func: &mut Func, 181 ) -> Option<Box<wasmtime_error_t>> { 182 let linker = &linker.linker; 183 let name = to_str!(name, name_len); 184 handle_result(linker.get_default(store, name), |f| *func = f) 185 } 186 187 #[unsafe(no_mangle)] 188 pub unsafe extern "C" fn wasmtime_linker_get( 189 linker: &wasmtime_linker_t, 190 store: WasmtimeStoreContextMut<'_>, 191 module: *const u8, 192 module_len: usize, 193 name: *const u8, 194 name_len: usize, 195 item_ptr: &mut MaybeUninit<wasmtime_extern_t>, 196 ) -> bool { 197 let linker = &linker.linker; 198 let module = match str::from_utf8(crate::slice_from_raw_parts(module, module_len)) { 199 Ok(s) => s, 200 Err(_) => return false, 201 }; 202 let name = match str::from_utf8(crate::slice_from_raw_parts(name, name_len)) { 203 Ok(s) => s, 204 Err(_) => return false, 205 }; 206 match linker.get(store, module, name) { 207 Some(which) => { 208 crate::initialize(item_ptr, which.into()); 209 true 210 } 211 None => false, 212 } 213 } 214 215 #[unsafe(no_mangle)] 216 pub unsafe extern "C" fn wasmtime_linker_define_unknown_imports_as_traps( 217 linker: &mut wasmtime_linker_t, 218 module: &wasmtime_module_t, 219 ) -> Option<Box<wasmtime_error_t>> { 220 handle_result( 221 linker 222 .linker 223 .define_unknown_imports_as_traps(&module.module), 224 |_| (), 225 ) 226 } 227 228 #[unsafe(no_mangle)] 229 pub unsafe extern "C" fn wasmtime_linker_define_unknown_imports_as_default_values( 230 linker: &mut wasmtime_linker_t, 231 store: WasmtimeStoreContextMut<'_>, 232 module: &wasmtime_module_t, 233 ) -> Option<Box<wasmtime_error_t>> { 234 handle_result( 235 linker 236 .linker 237 .define_unknown_imports_as_default_values(store, &module.module), 238 |_| (), 239 ) 240 } 241