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