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.
box_future<'a, F, T, E>(future: F) -> Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'a>> where F: Future<Output = Result<T, E>> + Send + 'a, T: 'a, E: From<OutOfMemory> + 'a,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 
_assertions_runtime()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