1 // Wasmtime's runtime has lots of fiddly bits where we're doing operations like 2 // casting between wasm i32/i64 and host `usize` values. There's also in general 3 // just lots of pieces of low-level manipulation of memory and internals of VM 4 // runtime state. To help keep all the integer casts correct be a bit more 5 // strict than the default settings to help weed out bugs ahead of time. 6 // 7 // This inevitably leads to wordier code than might otherwise be used because, 8 // for example, `u64 as usize` is warned against and will be an error on CI. 9 // This happens pretty frequently and needs to be replaced with `val.try_into()` 10 // or `usize::try_from(val)` where the error is handled. In some cases the 11 // correct thing to do is to `.unwrap()` the error to indicate a fatal mistake, 12 // but in some cases the correct thing is to propagate the error. 13 // 14 // Some niche cases that explicitly want truncation are recommended to have a 15 // function along the lines of 16 // 17 // #[allow(clippy::cast_possible_truncation)] 18 // fn truncate_i32_to_i8(a: i32) -> i8 { a as i8 } 19 // 20 // as this explicitly indicates the intent of truncation is desired. Other 21 // locations should use fallible conversions. 22 // 23 // If performance is absolutely critical then it's recommended to use `#[allow]` 24 // with a comment indicating why performance is critical as well as a short 25 // explanation of why truncation shouldn't be happening at runtime. This 26 // situation should be pretty rare though. 27 #![warn(clippy::cast_possible_truncation)] 28 29 use crate::prelude::*; 30 use core::marker; 31 use core::pin::Pin; 32 use core::task::{Context, Poll}; 33 34 #[cfg(feature = "component-model-async")] 35 mod bug; 36 37 #[macro_use] 38 pub(crate) mod func; 39 40 pub(crate) mod code; 41 pub(crate) mod code_memory; 42 #[cfg(feature = "debug")] 43 pub(crate) mod debug; 44 #[cfg(feature = "gc")] 45 pub(crate) mod exception; 46 pub(crate) mod externals; 47 #[cfg(feature = "async")] 48 pub(crate) mod fiber; 49 pub(crate) mod gc; 50 pub(crate) mod instance; 51 pub(crate) mod instantiate; 52 pub(crate) mod limits; 53 pub(crate) mod linker; 54 pub(crate) mod memory; 55 pub(crate) mod module; 56 #[cfg(feature = "debug-builtins")] 57 pub(crate) mod native_debug; 58 pub(crate) mod resources; 59 pub(crate) mod store; 60 pub(crate) mod trampoline; 61 pub(crate) mod trap; 62 pub(crate) mod type_registry; 63 pub(crate) mod types; 64 pub(crate) mod v128; 65 pub(crate) mod values; 66 pub(crate) mod vm; 67 68 #[cfg(feature = "component-model")] 69 pub mod component; 70 71 cfg_if::cfg_if! { 72 if #[cfg(miri)] { 73 // no extensions on miri 74 } else if #[cfg(not(feature = "std"))] { 75 // no extensions on no-std 76 } else if #[cfg(unix)] { 77 pub mod unix; 78 } else if #[cfg(windows)] { 79 pub mod windows; 80 } else { 81 // ... unknown os! 82 } 83 } 84 85 #[cfg(feature = "component-model-async")] 86 pub use bug::WasmtimeBug; 87 #[cfg(feature = "component-model-async")] 88 pub(crate) use bug::bail_bug; 89 pub use code_memory::CodeMemory; 90 #[cfg(feature = "debug")] 91 pub use debug::*; 92 #[cfg(feature = "gc")] 93 pub use exception::*; 94 pub use externals::*; 95 pub use func::*; 96 pub use gc::*; 97 pub use instance::{Instance, InstancePre}; 98 pub use instantiate::CompiledModule; 99 pub use limits::*; 100 pub use linker::*; 101 pub use memory::*; 102 pub use module::{Module, ModuleExport}; 103 pub use resources::*; 104 #[cfg(all(feature = "async", feature = "call-hook"))] 105 pub use store::CallHookHandler; 106 pub use store::{ 107 AsContext, AsContextMut, CallHook, Store, StoreContext, StoreContextMut, UpdateDeadline, 108 }; 109 pub use trap::*; 110 pub use types::*; 111 pub use v128::V128; 112 pub use values::*; 113 114 #[cfg(feature = "pooling-allocator")] 115 pub use vm::{PoolConcurrencyLimitError, PoolingAllocatorMetrics}; 116 117 #[cfg(feature = "profiling")] 118 mod profiling; 119 #[cfg(feature = "profiling")] 120 pub use profiling::GuestProfiler; 121 122 #[cfg(feature = "async")] 123 pub(crate) mod stack; 124 #[cfg(feature = "async")] 125 pub use stack::*; 126 127 #[cfg(feature = "coredump")] 128 mod coredump; 129 #[cfg(feature = "coredump")] 130 pub use coredump::*; 131 132 #[cfg(feature = "wave")] 133 mod wave; 134 135 /// Helper method to create a future trait object from the future `F` provided. 136 /// 137 /// This requires that the output of `F` is a result where the error can be 138 /// created from `OutOfMemory`. This will handle OOM when allocation of `F` on 139 /// the heap fails. 140 fn box_future<'a, F, T, E>(future: F) -> Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'a>> 141 where 142 F: Future<Output = Result<T, E>> + Send + 'a, 143 T: 'a, 144 E: From<OutOfMemory> + 'a, 145 { 146 if let Ok(future) = try_new::<Box<F>>(future) { 147 return Pin::from(future); 148 } 149 150 // Use a custom guaranteed-zero-size struct to implement a future that 151 // returns an OOM error which satisfies the type signature of this function. 152 struct OomFuture<F, T, E>(marker::PhantomData<fn() -> (T, F, E)>); 153 154 impl<F, T, E> Future for OomFuture<F, T, E> 155 where 156 E: From<OutOfMemory>, 157 { 158 type Output = Result<T, E>; 159 160 fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { 161 Poll::Ready(Err(OutOfMemory::new(size_of::<F>()).into())) 162 } 163 } 164 165 // Zero-size allocations don't actually allocate memory with a `Box`, so 166 // it's ok to use the standard `Box::pin` here and not worry about OOM. 167 let future = OomFuture::<F, T, E>(marker::PhantomData); 168 assert_eq!(size_of_val(&future), 0); 169 Box::pin(future) 170 } 171 172 fn _assertions_runtime() { 173 use crate::_assert_send_and_sync; 174 175 #[cfg(feature = "async")] 176 fn _assert_send<T: Send>(_t: T) {} 177 178 _assert_send_and_sync::<Caller<'_, ()>>(); 179 _assert_send_and_sync::<ExternRef>(); 180 _assert_send_and_sync::<(Func, TypedFunc<(), ()>, Global, Table, Memory)>(); 181 _assert_send_and_sync::<Instance>(); 182 _assert_send_and_sync::<InstancePre<()>>(); 183 _assert_send_and_sync::<InstancePre<*mut u8>>(); 184 _assert_send_and_sync::<Linker<()>>(); 185 _assert_send_and_sync::<Linker<*mut u8>>(); 186 _assert_send_and_sync::<Module>(); 187 _assert_send_and_sync::<Store<()>>(); 188 _assert_send_and_sync::<StoreContext<'_, ()>>(); 189 _assert_send_and_sync::<StoreContextMut<'_, ()>>(); 190 191 #[cfg(feature = "async")] 192 fn _call_async(s: &mut Store<()>, f: Func) { 193 _assert_send(f.call_async(&mut *s, &[], &mut [])) 194 } 195 #[cfg(feature = "async")] 196 fn _typed_call_async(s: &mut Store<()>, f: TypedFunc<(), ()>) { 197 _assert_send(f.call_async(&mut *s, ())) 198 } 199 #[cfg(feature = "async")] 200 fn _instantiate_async(s: &mut Store<()>, m: &Module) { 201 _assert_send(Instance::new_async(s, m, &[])) 202 } 203 } 204