Path: blob/main/crates/cranelift/src/func_environ/gc.rs
1693 views
//! Interface to compiling GC-related things.1//!2//! This module and its interface are implemented twice: once when the `gc`3//! cargo feature is enabled and once when the feature is disabled. The goal is4//! to have just a single `cfg(feature = "gc")` for the whole crate, which5//! selects between these two implementations.67use crate::func_environ::FuncEnvironment;8use cranelift_codegen::ir;9use cranelift_frontend::FunctionBuilder;10use wasmtime_environ::{GcTypeLayouts, TagIndex, TypeIndex, WasmRefType, WasmResult};1112#[cfg(feature = "gc")]13mod enabled;14#[cfg(feature = "gc")]15use enabled as imp;1617#[cfg(not(feature = "gc"))]18mod disabled;19#[cfg(not(feature = "gc"))]20use disabled as imp;2122// Re-export the GC compilation interface from the implementation that we chose23// based on the compile-time features enabled.24pub use imp::*;2526/// How to initialize a newly-allocated array's elements.27#[derive(Clone, Copy)]28#[cfg_attr(not(feature = "gc"), expect(dead_code))]29pub enum ArrayInit<'a> {30/// Initialize the array's elements with the given values.31Elems(&'a [ir::Value]),3233/// Initialize the array's elements with `elem` repeated `len` times.34Fill { elem: ir::Value, len: ir::Value },35}3637/// A trait for different collectors to emit any GC barriers they might require.38pub trait GcCompiler {39/// Get the GC type layouts for this GC compiler.40#[cfg_attr(not(feature = "gc"), allow(dead_code))]41fn layouts(&self) -> &dyn GcTypeLayouts;4243/// Emit code to allocate a new array.44///45/// The array should be of the given type and its elements initialized as46/// described by the given `ArrayInit`.47#[cfg_attr(not(feature = "gc"), allow(dead_code))]48fn alloc_array(49&mut self,50func_env: &mut FuncEnvironment<'_>,51builder: &mut FunctionBuilder<'_>,52array_type_index: TypeIndex,53init: ArrayInit<'_>,54) -> WasmResult<ir::Value>;5556/// Emit code to allocate a new struct.57///58/// The struct should be of the given type and its fields initialized to the59/// given values.60#[cfg_attr(not(feature = "gc"), allow(dead_code))]61fn alloc_struct(62&mut self,63func_env: &mut FuncEnvironment<'_>,64builder: &mut FunctionBuilder<'_>,65struct_type_index: TypeIndex,66fields: &[ir::Value],67) -> WasmResult<ir::Value>;6869/// Emit code to allocate a new exception object.70///71/// The exception object should be of the given type and its72/// fields initialized to the given values. The tag field is left73/// uninitialized; that is the responsibility of generated code to74/// fill in. `tag_index` is used only to look up the appropriate75/// exception object type.76#[cfg_attr(not(feature = "gc"), allow(dead_code))]77fn alloc_exn(78&mut self,79func_env: &mut FuncEnvironment<'_>,80builder: &mut FunctionBuilder<'_>,81tag_index: TagIndex,82fields: &[ir::Value],83instance_id: ir::Value,84tag: ir::Value,85) -> WasmResult<ir::Value>;8687/// Emit a read barrier for when we are cloning a GC reference onto the Wasm88/// stack.89///90/// This is used, for example, when reading from a global or a table91/// element.92///93/// In pseudocode, this is the following operation:94///95/// ```ignore96/// x = *src;97/// ```98///99/// Parameters:100///101/// * `func_env`: The function environment that this GC compiler is102/// operating within.103///104/// * `builder`: Function builder. Currently at the position where the read105/// should be inserted. Upon return, should be positioned where control106/// continues just after the read completes. Any intermediate blocks107/// created in the process of emitting the read barrier should be added to108/// the layout and sealed.109///110/// * `ty`: The Wasm reference type that is being read.111///112/// * `src`: A pointer to the GC reference that should be read; this is an113/// instance of a `*mut Option<VMGcRef>`.114///115/// * `flags`: The memory flags that should be used when accessing `src`.116///117/// This method should return the cloned GC reference (an instance of118/// `VMGcRef`) of type `i32`.119fn translate_read_gc_reference(120&mut self,121func_env: &mut FuncEnvironment<'_>,122builder: &mut FunctionBuilder,123ty: WasmRefType,124src: ir::Value,125flags: ir::MemFlags,126) -> WasmResult<ir::Value>;127128/// Emit a write barrier for when we are writing a GC reference over another129/// GC reference.130///131/// This is used, for example, when writing to a global or a table element.132///133/// In pseudocode, this is the following operation:134///135/// ```ignore136/// *dst = new_val;137/// ```138///139/// Parameters:140///141/// * `func_env`: The function environment that this GC compiler is142/// operating within.143///144/// * `builder`: Function builder. Currently at the position where the write145/// should be inserted. Upon return, should be positioned where control146/// continues just after the write completes. Any intermediate blocks147/// created in the process of emitting the read barrier should be added to148/// the layout and sealed.149///150/// * `ty`: The Wasm reference type that is being written.151///152/// * `dst`: A pointer to the GC reference that will be overwritten; note153/// that is this is an instance of a `*mut VMGcRef`, *not* a `VMGcRef`154/// itself or a `*mut VMGcHeader`!155///156/// * `new_val`: The new value that should be written into `dst`. This is a157/// `VMGcRef` of Cranelift type `i32`; not a `*mut VMGcRef`.158///159/// * `flags`: The memory flags that should be used when accessing `dst`.160fn translate_write_gc_reference(161&mut self,162func_env: &mut FuncEnvironment<'_>,163builder: &mut FunctionBuilder,164ty: WasmRefType,165dst: ir::Value,166new_val: ir::Value,167flags: ir::MemFlags,168) -> WasmResult<()>;169}170171pub mod builtins {172use super::*;173174macro_rules! define_builtin_accessors {175( $( $name:ident , )* ) => {176$(177#[inline]178pub fn $name(179func_env: &mut FuncEnvironment<'_>,180func: &mut ir::Function,181) -> WasmResult<ir::FuncRef> {182#[cfg(feature = "gc")]183{184func_env.needs_gc_heap = true;185return Ok(func_env.builtin_functions.$name(func));186}187188#[cfg(not(feature = "gc"))]189{190let _ = (func, func_env);191return Err(wasmtime_environ::wasm_unsupported!(192"support for Wasm GC disabled at compile time because the `gc` cargo \193feature was not enabled"194));195}196}197)*198};199}200201define_builtin_accessors! {202table_grow_gc_ref,203table_fill_gc_ref,204array_new_data,205array_new_elem,206array_copy,207array_init_data,208array_init_elem,209}210}211212213