Next Generation WASM Microkernel Operating System
1// Copyright 2025 Jonas Kruckenberg
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::wasm::cranelift::env::TranslationEnvironment;
9use crate::wasm::translate::IndexType;
10use cranelift_codegen::ir;
11use cranelift_codegen::ir::types;
12use cranelift_frontend::FunctionBuilder;
13use wasmparser::{FuncValidator, WasmModuleResources};
14
15/// Get the parameter and result types for the given Wasm blocktype.
16pub fn blocktype_params_results<T>(
17 validator: &FuncValidator<T>,
18 ty: wasmparser::BlockType,
19) -> (
20 impl ExactSizeIterator<Item = wasmparser::ValType> + Clone + '_,
21 impl ExactSizeIterator<Item = wasmparser::ValType> + Clone + '_,
22)
23where
24 T: WasmModuleResources,
25{
26 match ty {
27 wasmparser::BlockType::Empty => (
28 BlockTypeParamsOrReturns::Empty,
29 BlockTypeParamsOrReturns::Empty,
30 ),
31 wasmparser::BlockType::Type(ty) => (
32 BlockTypeParamsOrReturns::Empty,
33 BlockTypeParamsOrReturns::One(ty),
34 ),
35 wasmparser::BlockType::FuncType(ty_index) => {
36 let ty = validator
37 .resources()
38 .sub_type_at(ty_index)
39 .expect("should be valid")
40 .unwrap_func();
41
42 (
43 BlockTypeParamsOrReturns::Many(ty.params(), 0),
44 BlockTypeParamsOrReturns::Many(ty.results(), 0),
45 )
46 }
47 }
48}
49
50/// Iterator over the parameters or return types of a block.
51#[derive(Debug, Clone)]
52pub enum BlockTypeParamsOrReturns<'a> {
53 Empty,
54 One(wasmparser::ValType),
55 Many(&'a [wasmparser::ValType], usize),
56}
57
58impl Iterator for BlockTypeParamsOrReturns<'_> {
59 type Item = wasmparser::ValType;
60
61 fn next(&mut self) -> Option<Self::Item> {
62 match self {
63 BlockTypeParamsOrReturns::Empty => None,
64 BlockTypeParamsOrReturns::One(ty) => {
65 let ty = *ty;
66 *self = Self::Empty;
67 Some(ty)
68 }
69 BlockTypeParamsOrReturns::Many(slice, offset) => {
70 let val = *slice.get(*offset)?;
71 *offset += 1;
72 Some(val)
73 }
74 }
75 }
76
77 fn size_hint(&self) -> (usize, Option<usize>) {
78 match self {
79 BlockTypeParamsOrReturns::Empty => (0, Some(0)),
80 BlockTypeParamsOrReturns::One(_) => (1, Some(1)),
81 BlockTypeParamsOrReturns::Many(slice, _) => (slice.len(), Some(slice.len())),
82 }
83 }
84}
85
86impl ExactSizeIterator for BlockTypeParamsOrReturns<'_> {}
87
88/// Create a `Block` with the given Wasm parameters.
89pub fn block_with_params(
90 builder: &mut FunctionBuilder,
91 params: impl IntoIterator<Item = wasmparser::ValType>,
92 env: &mut TranslationEnvironment,
93) -> ir::Block {
94 let block = builder.create_block();
95 for ty in params {
96 match ty {
97 wasmparser::ValType::I32 => {
98 builder.append_block_param(block, ir::types::I32);
99 }
100 wasmparser::ValType::I64 => {
101 builder.append_block_param(block, ir::types::I64);
102 }
103 wasmparser::ValType::F32 => {
104 builder.append_block_param(block, ir::types::F32);
105 }
106 wasmparser::ValType::F64 => {
107 builder.append_block_param(block, ir::types::F64);
108 }
109 wasmparser::ValType::Ref(rt) => {
110 let hty = env.convert_heap_type(rt.heap_type());
111 let (ty, needs_stack_map) = env.reference_type(&hty);
112 let val = builder.append_block_param(block, ty);
113 if needs_stack_map {
114 builder.declare_value_needs_stack_map(val);
115 }
116 }
117 wasmparser::ValType::V128 => {
118 builder.append_block_param(block, ir::types::I8X16);
119 }
120 }
121 }
122 block
123}
124
125/// Turns a `wasmparser` `f32` into a `Cranelift` one.
126pub fn f32_translation(x: wasmparser::Ieee32) -> ir::immediates::Ieee32 {
127 ir::immediates::Ieee32::with_bits(x.bits())
128}
129
130/// Turns a `wasmparser` `f64` into a `Cranelift` one.
131pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
132 ir::immediates::Ieee64::with_bits(x.bits())
133}
134
135/// Special `VMContext` value label. It is tracked as `0xffff_fffe` label.
136pub fn get_vmctx_value_label() -> ir::ValueLabel {
137 const VMCTX_LABEL: u32 = 0xffff_fffe;
138 ir::ValueLabel::from_u32(VMCTX_LABEL)
139}
140
141pub fn index_type_to_ir_type(index_type: IndexType) -> ir::Type {
142 match index_type {
143 IndexType::I32 => types::I32,
144 IndexType::I64 => types::I64,
145 }
146}