wasmtime_types/
lib.rs

1//! Internal dependency of Wasmtime and Cranelift that defines types for
2//! WebAssembly.
3
4pub use wasmparser;
5
6use cranelift_entity::entity_impl;
7
8use serde::{Deserialize, Serialize};
9use std::convert::{TryFrom, TryInto};
10use std::fmt;
11
12mod error;
13pub use error::*;
14
15/// WebAssembly value type -- equivalent of `wasmparser`'s Type.
16#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub enum WasmType {
18    /// I32 type
19    I32,
20    /// I64 type
21    I64,
22    /// F32 type
23    F32,
24    /// F64 type
25    F64,
26    /// V128 type
27    V128,
28    /// FuncRef type
29    FuncRef,
30    /// ExternRef type
31    ExternRef,
32}
33
34impl TryFrom<wasmparser::ValType> for WasmType {
35    type Error = WasmError;
36    fn try_from(ty: wasmparser::ValType) -> Result<Self, Self::Error> {
37        use wasmparser::ValType::*;
38        match ty {
39            I32 => Ok(WasmType::I32),
40            I64 => Ok(WasmType::I64),
41            F32 => Ok(WasmType::F32),
42            F64 => Ok(WasmType::F64),
43            V128 => Ok(WasmType::V128),
44            Ref(r) => r.try_into(),
45        }
46    }
47}
48
49impl TryFrom<wasmparser::RefType> for WasmType {
50    type Error = WasmError;
51    fn try_from(ty: wasmparser::RefType) -> Result<Self, Self::Error> {
52        match ty {
53            wasmparser::RefType::FUNCREF => Ok(WasmType::FuncRef),
54            wasmparser::RefType::EXTERNREF => Ok(WasmType::ExternRef),
55            _ => Err(WasmError::Unsupported(
56                "function references proposal".to_string(),
57            )),
58        }
59    }
60}
61
62impl TryFrom<wasmparser::HeapType> for WasmType {
63    type Error = WasmError;
64    fn try_from(ty: wasmparser::HeapType) -> Result<Self, Self::Error> {
65        match ty {
66            wasmparser::HeapType::Func => Ok(WasmType::FuncRef),
67            wasmparser::HeapType::Extern => Ok(WasmType::ExternRef),
68            // NB: when the function-references proposal is implemented this
69            // entire `impl` should probably go away to remove the need for not
70            // only this `unsupported` but everything.
71            _ => Err(WasmError::Unsupported(
72                "function references proposal".to_string(),
73            )),
74        }
75    }
76}
77
78impl From<WasmType> for wasmparser::ValType {
79    fn from(ty: WasmType) -> wasmparser::ValType {
80        match ty {
81            WasmType::I32 => wasmparser::ValType::I32,
82            WasmType::I64 => wasmparser::ValType::I64,
83            WasmType::F32 => wasmparser::ValType::F32,
84            WasmType::F64 => wasmparser::ValType::F64,
85            WasmType::V128 => wasmparser::ValType::V128,
86            WasmType::FuncRef => wasmparser::ValType::FUNCREF,
87            WasmType::ExternRef => wasmparser::ValType::EXTERNREF,
88        }
89    }
90}
91
92impl fmt::Display for WasmType {
93    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94        match self {
95            WasmType::I32 => write!(f, "i32"),
96            WasmType::I64 => write!(f, "i64"),
97            WasmType::F32 => write!(f, "f32"),
98            WasmType::F64 => write!(f, "f64"),
99            WasmType::V128 => write!(f, "v128"),
100            WasmType::ExternRef => write!(f, "externref"),
101            WasmType::FuncRef => write!(f, "funcref"),
102        }
103    }
104}
105
106/// WebAssembly function type -- equivalent of `wasmparser`'s FuncType.
107#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
108pub struct WasmFuncType {
109    params: Box<[WasmType]>,
110    externref_params_count: usize,
111    returns: Box<[WasmType]>,
112    externref_returns_count: usize,
113}
114
115impl WasmFuncType {
116    #[inline]
117    pub fn new(params: Box<[WasmType]>, returns: Box<[WasmType]>) -> Self {
118        let externref_params_count = params.iter().filter(|p| **p == WasmType::ExternRef).count();
119        let externref_returns_count = returns
120            .iter()
121            .filter(|r| **r == WasmType::ExternRef)
122            .count();
123        WasmFuncType {
124            params,
125            externref_params_count,
126            returns,
127            externref_returns_count,
128        }
129    }
130
131    /// Function params types.
132    #[inline]
133    pub fn params(&self) -> &[WasmType] {
134        &self.params
135    }
136
137    /// How many `externref`s are in this function's params?
138    #[inline]
139    pub fn externref_params_count(&self) -> usize {
140        self.externref_params_count
141    }
142
143    /// Returns params types.
144    #[inline]
145    pub fn returns(&self) -> &[WasmType] {
146        &self.returns
147    }
148
149    /// How many `externref`s are in this function's returns?
150    #[inline]
151    pub fn externref_returns_count(&self) -> usize {
152        self.externref_returns_count
153    }
154}
155
156impl TryFrom<wasmparser::FuncType> for WasmFuncType {
157    type Error = WasmError;
158    fn try_from(ty: wasmparser::FuncType) -> Result<Self, Self::Error> {
159        let params = ty
160            .params()
161            .iter()
162            .copied()
163            .map(WasmType::try_from)
164            .collect::<Result<_, Self::Error>>()?;
165        let returns = ty
166            .results()
167            .iter()
168            .copied()
169            .map(WasmType::try_from)
170            .collect::<Result<_, Self::Error>>()?;
171        Ok(Self::new(params, returns))
172    }
173}
174
175/// Index type of a function (imported or defined) inside the WebAssembly module.
176#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
177pub struct FuncIndex(u32);
178entity_impl!(FuncIndex);
179
180/// Index type of a defined function inside the WebAssembly module.
181#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
182pub struct DefinedFuncIndex(u32);
183entity_impl!(DefinedFuncIndex);
184
185/// Index type of a defined table inside the WebAssembly module.
186#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
187pub struct DefinedTableIndex(u32);
188entity_impl!(DefinedTableIndex);
189
190/// Index type of a defined memory inside the WebAssembly module.
191#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
192pub struct DefinedMemoryIndex(u32);
193entity_impl!(DefinedMemoryIndex);
194
195/// Index type of a defined memory inside the WebAssembly module.
196#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
197pub struct OwnedMemoryIndex(u32);
198entity_impl!(OwnedMemoryIndex);
199
200/// Index type of a defined global inside the WebAssembly module.
201#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
202pub struct DefinedGlobalIndex(u32);
203entity_impl!(DefinedGlobalIndex);
204
205/// Index type of a table (imported or defined) inside the WebAssembly module.
206#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
207pub struct TableIndex(u32);
208entity_impl!(TableIndex);
209
210/// Index type of a global variable (imported or defined) inside the WebAssembly module.
211#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
212pub struct GlobalIndex(u32);
213entity_impl!(GlobalIndex);
214
215/// Index type of a linear memory (imported or defined) inside the WebAssembly module.
216#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
217pub struct MemoryIndex(u32);
218entity_impl!(MemoryIndex);
219
220/// Index type of a signature (imported or defined) inside the WebAssembly module.
221#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
222pub struct SignatureIndex(u32);
223entity_impl!(SignatureIndex);
224
225/// Index type of a passive data segment inside the WebAssembly module.
226#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
227pub struct DataIndex(u32);
228entity_impl!(DataIndex);
229
230/// Index type of a passive element segment inside the WebAssembly module.
231#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
232pub struct ElemIndex(u32);
233entity_impl!(ElemIndex);
234
235/// Index type of a type inside the WebAssembly module.
236#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
237pub struct TypeIndex(u32);
238entity_impl!(TypeIndex);
239
240/// Index type of an event inside the WebAssembly module.
241#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
242pub struct TagIndex(u32);
243entity_impl!(TagIndex);
244
245/// An index of an entity.
246#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
247pub enum EntityIndex {
248    /// Function index.
249    Function(FuncIndex),
250    /// Table index.
251    Table(TableIndex),
252    /// Memory index.
253    Memory(MemoryIndex),
254    /// Global index.
255    Global(GlobalIndex),
256}
257
258impl From<FuncIndex> for EntityIndex {
259    fn from(idx: FuncIndex) -> EntityIndex {
260        EntityIndex::Function(idx)
261    }
262}
263
264impl From<TableIndex> for EntityIndex {
265    fn from(idx: TableIndex) -> EntityIndex {
266        EntityIndex::Table(idx)
267    }
268}
269
270impl From<MemoryIndex> for EntityIndex {
271    fn from(idx: MemoryIndex) -> EntityIndex {
272        EntityIndex::Memory(idx)
273    }
274}
275
276impl From<GlobalIndex> for EntityIndex {
277    fn from(idx: GlobalIndex) -> EntityIndex {
278        EntityIndex::Global(idx)
279    }
280}
281
282/// A type of an item in a wasm module where an item is typically something that
283/// can be exported.
284#[allow(missing_docs)]
285#[derive(Clone, Debug, Serialize, Deserialize)]
286pub enum EntityType {
287    /// A global variable with the specified content type
288    Global(Global),
289    /// A linear memory with the specified limits
290    Memory(Memory),
291    /// An event definition.
292    Tag(Tag),
293    /// A table with the specified element type and limits
294    Table(Table),
295    /// A function type where the index points to the type section and records a
296    /// function signature.
297    Function(SignatureIndex),
298}
299
300/// A WebAssembly global.
301///
302/// Note that we record both the original Wasm type and the Cranelift IR type
303/// used to represent it. This is because multiple different kinds of Wasm types
304/// might be represented with the same Cranelift IR type. For example, both a
305/// Wasm `i64` and a `funcref` might be represented with a Cranelift `i64` on
306/// 64-bit architectures, and when GC is not required for func refs.
307#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
308pub struct Global {
309    /// The Wasm type of the value stored in the global.
310    pub wasm_ty: crate::WasmType,
311    /// A flag indicating whether the value may change at runtime.
312    pub mutability: bool,
313    /// The source of the initial value.
314    pub initializer: GlobalInit,
315}
316
317/// Globals are initialized via the `const` operators or by referring to another import.
318#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
319pub enum GlobalInit {
320    /// An `i32.const`.
321    I32Const(i32),
322    /// An `i64.const`.
323    I64Const(i64),
324    /// An `f32.const`.
325    F32Const(u32),
326    /// An `f64.const`.
327    F64Const(u64),
328    /// A `vconst`.
329    V128Const(u128),
330    /// A `global.get` of another global.
331    GetGlobal(GlobalIndex),
332    /// A `ref.null`.
333    RefNullConst,
334    /// A `ref.func <index>`.
335    RefFunc(FuncIndex),
336    ///< The global is imported from, and thus initialized by, a different module.
337    Import,
338}
339
340impl Global {
341    /// Creates a new `Global` type from wasmparser's representation.
342    pub fn new(ty: wasmparser::GlobalType, initializer: GlobalInit) -> WasmResult<Global> {
343        Ok(Global {
344            wasm_ty: ty.content_type.try_into()?,
345            mutability: ty.mutable,
346            initializer,
347        })
348    }
349}
350
351/// WebAssembly table.
352#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
353pub struct Table {
354    /// The table elements' Wasm type.
355    pub wasm_ty: WasmType,
356    /// The minimum number of elements in the table.
357    pub minimum: u32,
358    /// The maximum number of elements in the table.
359    pub maximum: Option<u32>,
360}
361
362impl TryFrom<wasmparser::TableType> for Table {
363    type Error = WasmError;
364
365    fn try_from(ty: wasmparser::TableType) -> WasmResult<Table> {
366        Ok(Table {
367            wasm_ty: ty.element_type.try_into()?,
368            minimum: ty.initial,
369            maximum: ty.maximum,
370        })
371    }
372}
373
374/// WebAssembly linear memory.
375#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
376pub struct Memory {
377    /// The minimum number of pages in the memory.
378    pub minimum: u64,
379    /// The maximum number of pages in the memory.
380    pub maximum: Option<u64>,
381    /// Whether the memory may be shared between multiple threads.
382    pub shared: bool,
383    /// Whether or not this is a 64-bit memory
384    pub memory64: bool,
385}
386
387impl From<wasmparser::MemoryType> for Memory {
388    fn from(ty: wasmparser::MemoryType) -> Memory {
389        Memory {
390            minimum: ty.initial,
391            maximum: ty.maximum,
392            shared: ty.shared,
393            memory64: ty.memory64,
394        }
395    }
396}
397
398/// WebAssembly event.
399#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
400pub struct Tag {
401    /// The event signature type.
402    pub ty: TypeIndex,
403}
404
405impl From<wasmparser::TagType> for Tag {
406    fn from(ty: wasmparser::TagType) -> Tag {
407        match ty.kind {
408            wasmparser::TagKind::Exception => Tag {
409                ty: TypeIndex::from_u32(ty.func_type_idx),
410            },
411        }
412    }
413}