1use std::fmt;
2use wasmtime_environ::{ir, wasm, EntityIndex};
3
4#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
10pub enum Mutability {
11 Const,
13 Var,
15}
16
17#[derive(Debug, Clone, Hash, Eq, PartialEq)]
22pub struct Limits {
23 min: u32,
24 max: Option<u32>,
25}
26
27impl Limits {
28 pub fn new(min: u32, max: Option<u32>) -> Limits {
30 Limits { min, max }
31 }
32
33 pub fn at_least(min: u32) -> Limits {
35 Limits::new(min, None)
36 }
37
38 pub fn min(&self) -> u32 {
40 self.min
41 }
42
43 pub fn max(&self) -> Option<u32> {
45 self.max
46 }
47}
48
49#[derive(Debug, Clone, Hash, Eq, PartialEq)]
53pub enum ValType {
54 I32,
56 I64,
58 F32,
60 F64,
62 V128,
64 ExternRef, FuncRef,
68}
69
70impl fmt::Display for ValType {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 match self {
73 ValType::I32 => write!(f, "i32"),
74 ValType::I64 => write!(f, "i64"),
75 ValType::F32 => write!(f, "f32"),
76 ValType::F64 => write!(f, "f64"),
77 ValType::V128 => write!(f, "v128"),
78 ValType::ExternRef => write!(f, "externref"),
79 ValType::FuncRef => write!(f, "funcref"),
80 }
81 }
82}
83
84impl ValType {
85 pub fn is_num(&self) -> bool {
88 match self {
89 ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 => true,
90 _ => false,
91 }
92 }
93
94 pub fn is_ref(&self) -> bool {
96 match self {
97 ValType::ExternRef | ValType::FuncRef => true,
98 _ => false,
99 }
100 }
101
102 pub(crate) fn get_wasmtime_type(&self) -> ir::Type {
103 match self {
104 ValType::I32 => ir::types::I32,
105 ValType::I64 => ir::types::I64,
106 ValType::F32 => ir::types::F32,
107 ValType::F64 => ir::types::F64,
108 ValType::V128 => ir::types::I8X16,
109 ValType::ExternRef => wasmtime_runtime::ref_type(),
110 ValType::FuncRef => wasmtime_runtime::pointer_type(),
111 }
112 }
113
114 pub(crate) fn to_wasm_type(&self) -> wasm::WasmType {
115 match self {
116 Self::I32 => wasm::WasmType::I32,
117 Self::I64 => wasm::WasmType::I64,
118 Self::F32 => wasm::WasmType::F32,
119 Self::F64 => wasm::WasmType::F64,
120 Self::V128 => wasm::WasmType::V128,
121 Self::FuncRef => wasm::WasmType::FuncRef,
122 Self::ExternRef => wasm::WasmType::ExternRef,
123 }
124 }
125
126 pub(crate) fn from_wasm_type(ty: &wasm::WasmType) -> Self {
127 match ty {
128 wasm::WasmType::I32 => Self::I32,
129 wasm::WasmType::I64 => Self::I64,
130 wasm::WasmType::F32 => Self::F32,
131 wasm::WasmType::F64 => Self::F64,
132 wasm::WasmType::V128 => Self::V128,
133 wasm::WasmType::FuncRef => Self::FuncRef,
134 wasm::WasmType::ExternRef => Self::ExternRef,
135 }
136 }
137}
138
139#[derive(Debug, Clone, Hash, Eq, PartialEq)]
147pub enum ExternType {
148 Func(FuncType),
150 Global(GlobalType),
152 Table(TableType),
154 Memory(MemoryType),
156}
157
158macro_rules! accessors {
159 ($(($variant:ident($ty:ty) $get:ident $unwrap:ident))*) => ($(
160 pub fn $get(&self) -> Option<&$ty> {
163 if let ExternType::$variant(e) = self {
164 Some(e)
165 } else {
166 None
167 }
168 }
169
170 pub fn $unwrap(&self) -> &$ty {
177 self.$get().expect(concat!("expected ", stringify!($ty)))
178 }
179 )*)
180}
181
182impl ExternType {
183 accessors! {
184 (Func(FuncType) func unwrap_func)
185 (Global(GlobalType) global unwrap_global)
186 (Table(TableType) table unwrap_table)
187 (Memory(MemoryType) memory unwrap_memory)
188 }
189}
190
191impl From<FuncType> for ExternType {
192 fn from(ty: FuncType) -> ExternType {
193 ExternType::Func(ty)
194 }
195}
196
197impl From<GlobalType> for ExternType {
198 fn from(ty: GlobalType) -> ExternType {
199 ExternType::Global(ty)
200 }
201}
202
203impl From<MemoryType> for ExternType {
204 fn from(ty: MemoryType) -> ExternType {
205 ExternType::Memory(ty)
206 }
207}
208
209impl From<TableType> for ExternType {
210 fn from(ty: TableType) -> ExternType {
211 ExternType::Table(ty)
212 }
213}
214
215#[derive(Debug, Clone, Hash, Eq, PartialEq)]
219pub struct FuncType {
220 params: Box<[ValType]>,
221 results: Box<[ValType]>,
222}
223
224impl FuncType {
225 pub fn new(params: Box<[ValType]>, results: Box<[ValType]>) -> FuncType {
230 FuncType { params, results }
231 }
232
233 pub fn params(&self) -> &[ValType] {
235 &self.params
236 }
237
238 pub fn results(&self) -> &[ValType] {
240 &self.results
241 }
242
243 pub(crate) fn to_wasm_func_type(&self) -> wasm::WasmFuncType {
244 wasm::WasmFuncType {
245 params: self.params.iter().map(|p| p.to_wasm_type()).collect(),
246 returns: self.results.iter().map(|r| r.to_wasm_type()).collect(),
247 }
248 }
249
250 pub(crate) fn get_wasmtime_signature(&self, pointer_type: ir::Type) -> ir::Signature {
252 use wasmtime_environ::ir::{AbiParam, ArgumentPurpose, Signature};
253 use wasmtime_jit::native;
254 let call_conv = native::call_conv();
255 let mut params = self
256 .params
257 .iter()
258 .map(|p| AbiParam::new(p.get_wasmtime_type()))
259 .collect::<Vec<_>>();
260 let returns = self
261 .results
262 .iter()
263 .map(|p| AbiParam::new(p.get_wasmtime_type()))
264 .collect::<Vec<_>>();
265 params.insert(
266 0,
267 AbiParam::special(pointer_type, ArgumentPurpose::VMContext),
268 );
269 params.insert(1, AbiParam::new(pointer_type));
270
271 Signature {
272 params,
273 returns,
274 call_conv,
275 }
276 }
277
278 pub(crate) fn from_wasm_func_type(signature: &wasm::WasmFuncType) -> FuncType {
282 let params = signature
283 .params
284 .iter()
285 .map(|p| ValType::from_wasm_type(p))
286 .collect::<Vec<_>>();
287 let results = signature
288 .returns
289 .iter()
290 .map(|r| ValType::from_wasm_type(r))
291 .collect::<Vec<_>>();
292 FuncType {
293 params: params.into_boxed_slice(),
294 results: results.into_boxed_slice(),
295 }
296 }
297}
298
299#[derive(Debug, Clone, Hash, Eq, PartialEq)]
307pub struct GlobalType {
308 content: ValType,
309 mutability: Mutability,
310}
311
312impl GlobalType {
313 pub fn new(content: ValType, mutability: Mutability) -> GlobalType {
316 GlobalType {
317 content,
318 mutability,
319 }
320 }
321
322 pub fn content(&self) -> &ValType {
324 &self.content
325 }
326
327 pub fn mutability(&self) -> Mutability {
329 self.mutability
330 }
331
332 pub(crate) fn from_wasmtime_global(global: &wasm::Global) -> GlobalType {
335 let ty = ValType::from_wasm_type(&global.wasm_ty);
336 let mutability = if global.mutability {
337 Mutability::Var
338 } else {
339 Mutability::Const
340 };
341 GlobalType::new(ty, mutability)
342 }
343}
344
345#[derive(Debug, Clone, Hash, Eq, PartialEq)]
353pub struct TableType {
354 element: ValType,
355 limits: Limits,
356}
357
358impl TableType {
359 pub fn new(element: ValType, limits: Limits) -> TableType {
362 TableType { element, limits }
363 }
364
365 pub fn element(&self) -> &ValType {
367 &self.element
368 }
369
370 pub fn limits(&self) -> &Limits {
372 &self.limits
373 }
374
375 pub(crate) fn from_wasmtime_table(table: &wasm::Table) -> TableType {
376 let ty = match table.ty {
377 wasm::TableElementType::Func => ValType::FuncRef,
378 #[cfg(target_pointer_width = "64")]
379 wasm::TableElementType::Val(ir::types::R64) => ValType::ExternRef,
380 #[cfg(target_pointer_width = "32")]
381 wasm::TableElementType::Val(ir::types::R32) => ValType::ExternRef,
382 _ => panic!("only `funcref` and `externref` tables supported"),
383 };
384 let limits = Limits::new(table.minimum, table.maximum);
385 TableType::new(ty, limits)
386 }
387}
388
389#[derive(Debug, Clone, Hash, Eq, PartialEq)]
396pub struct MemoryType {
397 limits: Limits,
398}
399
400impl MemoryType {
401 pub fn new(limits: Limits) -> MemoryType {
404 MemoryType { limits }
405 }
406
407 pub fn limits(&self) -> &Limits {
409 &self.limits
410 }
411
412 pub(crate) fn from_wasmtime_memory(memory: &wasm::Memory) -> MemoryType {
413 MemoryType::new(Limits::new(memory.minimum, memory.maximum))
414 }
415}
416
417#[derive(Clone, Hash, Eq, PartialEq)]
420pub(crate) enum EntityType<'module> {
421 Function(&'module wasm::WasmFuncType),
422 Table(&'module wasm::Table),
423 Memory(&'module wasm::Memory),
424 Global(&'module wasm::Global),
425}
426
427impl<'module> EntityType<'module> {
428 pub(crate) fn new(
430 entity_index: &EntityIndex,
431 module: &'module wasmtime_environ::Module,
432 ) -> EntityType<'module> {
433 match entity_index {
434 EntityIndex::Function(func_index) => {
435 let sig = module.local.wasm_func_type(*func_index);
436 EntityType::Function(&sig)
437 }
438 EntityIndex::Table(table_index) => {
439 EntityType::Table(&module.local.table_plans[*table_index].table)
440 }
441 EntityIndex::Memory(memory_index) => {
442 EntityType::Memory(&module.local.memory_plans[*memory_index].memory)
443 }
444 EntityIndex::Global(global_index) => {
445 EntityType::Global(&module.local.globals[*global_index])
446 }
447 }
448 }
449
450 pub(crate) fn extern_type(&self) -> ExternType {
452 match self {
453 EntityType::Function(sig) => FuncType::from_wasm_func_type(sig).into(),
454 EntityType::Table(table) => TableType::from_wasmtime_table(table).into(),
455 EntityType::Memory(memory) => MemoryType::from_wasmtime_memory(memory).into(),
456 EntityType::Global(global) => GlobalType::from_wasmtime_global(global).into(),
457 }
458 }
459}
460
461#[derive(Clone, Hash, Eq, PartialEq)]
470pub struct ImportType<'module> {
471 module: &'module str,
473
474 name: &'module str,
476
477 ty: EntityType<'module>,
479}
480
481impl<'module> ImportType<'module> {
482 pub(crate) fn new(
485 module: &'module str,
486 name: &'module str,
487 ty: EntityType<'module>,
488 ) -> ImportType<'module> {
489 ImportType { module, name, ty }
490 }
491
492 pub fn module(&self) -> &'module str {
494 self.module
495 }
496
497 pub fn name(&self) -> &'module str {
500 self.name
501 }
502
503 pub fn ty(&self) -> ExternType {
505 self.ty.extern_type()
506 }
507}
508
509impl<'module> fmt::Debug for ImportType<'module> {
510 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
511 f.debug_struct("ImportType")
512 .field("module", &self.module().to_owned())
513 .field("name", &self.name().to_owned())
514 .field("ty", &self.ty())
515 .finish()
516 }
517}
518
519#[derive(Clone, Hash, Eq, PartialEq)]
528pub struct ExportType<'module> {
529 name: &'module str,
531
532 ty: EntityType<'module>,
534}
535
536impl<'module> ExportType<'module> {
537 pub(crate) fn new(name: &'module str, ty: EntityType<'module>) -> ExportType<'module> {
540 ExportType { name, ty }
541 }
542
543 pub fn name(&self) -> &'module str {
545 self.name
546 }
547
548 pub fn ty(&self) -> ExternType {
550 self.ty.extern_type()
551 }
552}
553
554impl<'module> fmt::Debug for ExportType<'module> {
555 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
556 f.debug_struct("ExportType")
557 .field("name", &self.name().to_owned())
558 .field("ty", &self.ty())
559 .finish()
560 }
561}