Next Generation WASM Microkernel Operating System
at trap_handler 146 lines 4.9 kB view raw
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}