Next Generation WASM Microkernel Operating System
at trap_handler 158 lines 5.3 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::builtins::BuiltinFunctionIndex; 9use crate::wasm::compile::{FilePos, NS_BUILTIN, NS_WASM_FUNC}; 10use crate::wasm::indices::FuncIndex; 11use crate::wasm::trap::TrapKind; 12use cranelift_codegen::ir::{ExternalName, StackSlots, UserExternalName, UserExternalNameRef}; 13use cranelift_codegen::{ 14 Final, FinalizedMachReloc, FinalizedRelocTarget, MachBufferFinalized, ValueLabelsRanges, 15 binemit, 16}; 17use cranelift_entity::PrimaryMap; 18 19#[derive(Debug)] 20pub struct CompiledFunction { 21 /// The machine code buffer for this function. 22 buffer: MachBufferFinalized<Final>, 23 /// What names each name ref corresponds to. 24 name_map: PrimaryMap<UserExternalNameRef, UserExternalName>, 25 /// The alignment for the compiled function. 26 alignment: u32, 27 /// The metadata for the compiled function. 28 metadata: CompiledFunctionMetadata, 29} 30 31impl CompiledFunction { 32 pub fn new( 33 buffer: MachBufferFinalized<Final>, 34 name_map: PrimaryMap<UserExternalNameRef, UserExternalName>, 35 alignment: u32, 36 ) -> Self { 37 Self { 38 buffer, 39 name_map, 40 alignment, 41 metadata: CompiledFunctionMetadata::default(), 42 } 43 } 44 45 pub fn buffer(&self) -> &[u8] { 46 self.buffer.data() 47 } 48 49 pub fn alignment(&self) -> u32 { 50 self.alignment 51 } 52 53 pub fn relocations(&self) -> impl ExactSizeIterator<Item = Relocation> + use<'_> { 54 self.buffer 55 .relocs() 56 .iter() 57 .map(|r| Relocation::from_mach_reloc(r, &self.name_map)) 58 } 59 60 /// Returns an iterator to the function's traps. 61 pub fn traps(&self) -> impl ExactSizeIterator<Item = TrapInfo> + use<'_> { 62 self.buffer.traps().iter().map(|trap| TrapInfo { 63 trap: TrapKind::from_trap_code(trap.code).expect("unexpected trap code"), 64 offset: trap.offset, 65 }) 66 } 67 68 pub fn metadata(&self) -> &CompiledFunctionMetadata { 69 &self.metadata 70 } 71 72 pub fn metadata_mut(&mut self) -> &mut CompiledFunctionMetadata { 73 &mut self.metadata 74 } 75} 76 77#[derive(Debug, Default)] 78pub struct CompiledFunctionMetadata { 79 /// Mapping of value labels and their locations. 80 pub value_labels_ranges: ValueLabelsRanges, 81 /// Allocated stack slots. 82 pub sized_stack_slots: StackSlots, 83 /// Start source location. 84 pub start_srcloc: FilePos, 85 /// End source location. 86 pub end_srcloc: FilePos, 87 // /// An array of data for the instructions in this function, indicating where 88 // /// each instruction maps back to in the original function. 89 // /// 90 // /// This array is sorted least-to-greatest by the `code_offset` field. 91 // /// Additionally the span of each `InstructionAddressMap` is implicitly the 92 // /// gap between it and the next item in the array. 93 // pub address_map: Box<[InstructionAddressMapping]>, 94} 95 96#[derive(Debug)] 97pub struct Relocation { 98 pub kind: binemit::Reloc, 99 pub target: RelocationTarget, 100 pub addend: binemit::Addend, 101 pub offset: binemit::CodeOffset, 102} 103 104#[derive(Debug, Copy, Clone)] 105pub enum RelocationTarget { 106 Wasm(FuncIndex), 107 Builtin(BuiltinFunctionIndex), 108} 109 110impl Relocation { 111 fn from_mach_reloc( 112 reloc: &FinalizedMachReloc, 113 name_map: &PrimaryMap<UserExternalNameRef, UserExternalName>, 114 ) -> Self { 115 let &FinalizedMachReloc { 116 offset, 117 kind, 118 ref target, 119 addend, 120 } = reloc; 121 122 let target = match *target { 123 FinalizedRelocTarget::ExternalName(ExternalName::User(user_func_ref)) => { 124 let name = &name_map[user_func_ref]; 125 match name.namespace { 126 // A reference to another jit'ed WASM function 127 NS_WASM_FUNC => RelocationTarget::Wasm(FuncIndex::from_u32(name.index)), 128 // A reference to a WASM builtin 129 NS_BUILTIN => { 130 RelocationTarget::Builtin(BuiltinFunctionIndex::from_u32(name.index)) 131 } 132 _ => panic!("unknown namespace {}", name.namespace), 133 } 134 } 135 FinalizedRelocTarget::ExternalName(ExternalName::LibCall(libcall)) => { 136 // cranelift libcalls are a lot like wasm builtins, they are emitted for instructions 137 // that have no ISA equivalent and would be too complicated to emit as JIT code 138 todo!("libcalls {libcall:?}") 139 } 140 _ => panic!("unsupported relocation target {target:?}"), 141 }; 142 143 Self { 144 kind, 145 target, 146 addend, 147 offset, 148 } 149 } 150} 151 152/// Information about a trap in a compiled function. 153pub struct TrapInfo { 154 /// The offset relative to the function start of the trapping address. 155 pub offset: u32, 156 /// The trap code corresponding to the trapping instruction. 157 pub trap: TrapKind, 158}