14c8edb95SAlex Crichton //! > **⚠️ Warning ⚠️**: this crate is an internal-only crate for the Wasmtime 24c8edb95SAlex Crichton //! > project and is not intended for general use. APIs are not strictly 34c8edb95SAlex Crichton //! > reviewed for safety and usage outside of Wasmtime may have bugs. If 44c8edb95SAlex Crichton //! > you're interested in using this feel free to file an issue on the 54c8edb95SAlex Crichton //! > Wasmtime repository to start a discussion about doing so, but otherwise 64c8edb95SAlex Crichton //! > be aware that your usage of this crate is not supported. 74c8edb95SAlex Crichton 8d8f7c77fSAlex Crichton #![no_std] 9d8f7c77fSAlex Crichton 107c67e620SJoel Dice /// Represents the possible sizes in bytes of the discriminant of a variant type in the component model 11bd70dbebSAlex Crichton #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 127c67e620SJoel Dice pub enum DiscriminantSize { 137c67e620SJoel Dice /// 8-bit discriminant 147c67e620SJoel Dice Size1, 157c67e620SJoel Dice /// 16-bit discriminant 167c67e620SJoel Dice Size2, 177c67e620SJoel Dice /// 32-bit discriminant 187c67e620SJoel Dice Size4, 197c67e620SJoel Dice } 207c67e620SJoel Dice 217c67e620SJoel Dice impl DiscriminantSize { 227c67e620SJoel Dice /// Calculate the size of discriminant needed to represent a variant with the specified number of cases. from_count(count: usize) -> Option<Self>23bd70dbebSAlex Crichton pub const fn from_count(count: usize) -> Option<Self> { 24*7d857e63SAlex Crichton if count <= 1 << 8 { 257c67e620SJoel Dice Some(Self::Size1) 26*7d857e63SAlex Crichton } else if count <= 1 << 16 { 277c67e620SJoel Dice Some(Self::Size2) 28*7d857e63SAlex Crichton } else if count as u64 <= 1 << 32 { 297c67e620SJoel Dice Some(Self::Size4) 307c67e620SJoel Dice } else { 317c67e620SJoel Dice None 327c67e620SJoel Dice } 337c67e620SJoel Dice } 34bd70dbebSAlex Crichton 35bd70dbebSAlex Crichton /// Returns the size, in bytes, of this discriminant byte_size(&self) -> u3236bd70dbebSAlex Crichton pub const fn byte_size(&self) -> u32 { 37bd70dbebSAlex Crichton match self { 38bd70dbebSAlex Crichton DiscriminantSize::Size1 => 1, 39bd70dbebSAlex Crichton DiscriminantSize::Size2 => 2, 40bd70dbebSAlex Crichton DiscriminantSize::Size4 => 4, 41bd70dbebSAlex Crichton } 42bd70dbebSAlex Crichton } 437c67e620SJoel Dice } 447c67e620SJoel Dice 457c67e620SJoel Dice impl From<DiscriminantSize> for u32 { 467c67e620SJoel Dice /// Size of the discriminant as a `u32` from(size: DiscriminantSize) -> u32477c67e620SJoel Dice fn from(size: DiscriminantSize) -> u32 { 48bd70dbebSAlex Crichton size.byte_size() 497c67e620SJoel Dice } 507c67e620SJoel Dice } 517c67e620SJoel Dice 527c67e620SJoel Dice impl From<DiscriminantSize> for usize { 537c67e620SJoel Dice /// Size of the discriminant as a `usize` from(size: DiscriminantSize) -> usize547c67e620SJoel Dice fn from(size: DiscriminantSize) -> usize { 557c67e620SJoel Dice match size { 567c67e620SJoel Dice DiscriminantSize::Size1 => 1, 577c67e620SJoel Dice DiscriminantSize::Size2 => 2, 587c67e620SJoel Dice DiscriminantSize::Size4 => 4, 597c67e620SJoel Dice } 607c67e620SJoel Dice } 617c67e620SJoel Dice } 627c67e620SJoel Dice 637c67e620SJoel Dice /// Represents the number of bytes required to store a flags value in the component model 647c67e620SJoel Dice pub enum FlagsSize { 65893fadb4SAlex Crichton /// There are no flags 66893fadb4SAlex Crichton Size0, 677c67e620SJoel Dice /// Flags can fit in a u8 687c67e620SJoel Dice Size1, 697c67e620SJoel Dice /// Flags can fit in a u16 707c67e620SJoel Dice Size2, 717c67e620SJoel Dice /// Flags can fit in a specified number of u32 fields 72bc8e36a6SAlex Crichton Size4Plus(u8), 737c67e620SJoel Dice } 747c67e620SJoel Dice 757c67e620SJoel Dice impl FlagsSize { 767c67e620SJoel Dice /// Calculate the size needed to represent a value with the specified number of flags. from_count(count: usize) -> FlagsSize77bd70dbebSAlex Crichton pub const fn from_count(count: usize) -> FlagsSize { 78893fadb4SAlex Crichton if count == 0 { 79893fadb4SAlex Crichton FlagsSize::Size0 80893fadb4SAlex Crichton } else if count <= 8 { 817c67e620SJoel Dice FlagsSize::Size1 827c67e620SJoel Dice } else if count <= 16 { 837c67e620SJoel Dice FlagsSize::Size2 847c67e620SJoel Dice } else { 851b4ea3a6SAlex Crichton let amt = count.div_ceil(32); 86bc8e36a6SAlex Crichton if amt > (u8::MAX as usize) { 87bc8e36a6SAlex Crichton panic!("too many flags"); 88bc8e36a6SAlex Crichton } 89bc8e36a6SAlex Crichton FlagsSize::Size4Plus(amt as u8) 907c67e620SJoel Dice } 917c67e620SJoel Dice } 927c67e620SJoel Dice } 937c67e620SJoel Dice 94ed8908efSJoel Dice /// A simple bump allocator which can be used with modules 95ed8908efSJoel Dice pub const REALLOC_AND_FREE: &str = r#" 96ed8908efSJoel Dice (global $last (mut i32) (i32.const 8)) 97ed8908efSJoel Dice (func $realloc (export "realloc") 98ed8908efSJoel Dice (param $old_ptr i32) 99ed8908efSJoel Dice (param $old_size i32) 100ed8908efSJoel Dice (param $align i32) 101ed8908efSJoel Dice (param $new_size i32) 102ed8908efSJoel Dice (result i32) 103ed8908efSJoel Dice 104650979aeSAlex Crichton (local $ret i32) 105650979aeSAlex Crichton 106ed8908efSJoel Dice ;; Test if the old pointer is non-null 107ed8908efSJoel Dice local.get $old_ptr 108ed8908efSJoel Dice if 109ed8908efSJoel Dice ;; If the old size is bigger than the new size then 110ed8908efSJoel Dice ;; this is a shrink and transparently allow it 111ed8908efSJoel Dice local.get $old_size 112ed8908efSJoel Dice local.get $new_size 113ed8908efSJoel Dice i32.gt_u 114ed8908efSJoel Dice if 115ed8908efSJoel Dice local.get $old_ptr 116ed8908efSJoel Dice return 117ed8908efSJoel Dice end 118ed8908efSJoel Dice 119650979aeSAlex Crichton ;; otherwise fall through to allocate a new chunk which will later 120650979aeSAlex Crichton ;; copy data over 121ed8908efSJoel Dice end 122ed8908efSJoel Dice 123ed8908efSJoel Dice ;; align up `$last` 124ed8908efSJoel Dice (global.set $last 125ed8908efSJoel Dice (i32.and 126ed8908efSJoel Dice (i32.add 127ed8908efSJoel Dice (global.get $last) 128ed8908efSJoel Dice (i32.add 129ed8908efSJoel Dice (local.get $align) 130ed8908efSJoel Dice (i32.const -1))) 131ed8908efSJoel Dice (i32.xor 132ed8908efSJoel Dice (i32.add 133ed8908efSJoel Dice (local.get $align) 134ed8908efSJoel Dice (i32.const -1)) 135ed8908efSJoel Dice (i32.const -1)))) 136ed8908efSJoel Dice 137ed8908efSJoel Dice ;; save the current value of `$last` as the return value 138ed8908efSJoel Dice global.get $last 139866ec466SAlex Crichton local.set $ret 140866ec466SAlex Crichton 141866ec466SAlex Crichton ;; bump our pointer 142866ec466SAlex Crichton (global.set $last 143866ec466SAlex Crichton (i32.add 144866ec466SAlex Crichton (global.get $last) 145866ec466SAlex Crichton (local.get $new_size))) 146866ec466SAlex Crichton 147866ec466SAlex Crichton ;; while `memory.size` is less than `$last`, grow memory 148866ec466SAlex Crichton ;; by one page 149866ec466SAlex Crichton (loop $loop 150866ec466SAlex Crichton (if 151866ec466SAlex Crichton (i32.lt_u 152866ec466SAlex Crichton (i32.mul (memory.size) (i32.const 65536)) 153866ec466SAlex Crichton (global.get $last)) 154866ec466SAlex Crichton (then 155866ec466SAlex Crichton i32.const 1 156866ec466SAlex Crichton memory.grow 157866ec466SAlex Crichton ;; test to make sure growth succeeded 158866ec466SAlex Crichton i32.const -1 159866ec466SAlex Crichton i32.eq 160866ec466SAlex Crichton if unreachable end 161866ec466SAlex Crichton 162866ec466SAlex Crichton br $loop))) 163866ec466SAlex Crichton 164ed8908efSJoel Dice 165ed8908efSJoel Dice ;; ensure anything necessary is set to valid data by spraying a bit 166ed8908efSJoel Dice ;; pattern that is invalid 167866ec466SAlex Crichton local.get $ret 168ed8908efSJoel Dice i32.const 0xde 169ed8908efSJoel Dice local.get $new_size 170ed8908efSJoel Dice memory.fill 171ed8908efSJoel Dice 172650979aeSAlex Crichton ;; If the old pointer is present then that means this was a reallocation 173650979aeSAlex Crichton ;; of an existing chunk which means the existing data must be copied. 174650979aeSAlex Crichton local.get $old_ptr 175650979aeSAlex Crichton if 176650979aeSAlex Crichton local.get $ret ;; destination 177650979aeSAlex Crichton local.get $old_ptr ;; source 178650979aeSAlex Crichton local.get $old_size ;; size 179650979aeSAlex Crichton memory.copy 180650979aeSAlex Crichton end 181650979aeSAlex Crichton 182866ec466SAlex Crichton local.get $ret 183ed8908efSJoel Dice ) 184ed8908efSJoel Dice "#; 185