Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/cranelift/src/func_environ/gc.rs
1693 views
1
//! Interface to compiling GC-related things.
2
//!
3
//! This module and its interface are implemented twice: once when the `gc`
4
//! cargo feature is enabled and once when the feature is disabled. The goal is
5
//! to have just a single `cfg(feature = "gc")` for the whole crate, which
6
//! selects between these two implementations.
7
8
use crate::func_environ::FuncEnvironment;
9
use cranelift_codegen::ir;
10
use cranelift_frontend::FunctionBuilder;
11
use wasmtime_environ::{GcTypeLayouts, TagIndex, TypeIndex, WasmRefType, WasmResult};
12
13
#[cfg(feature = "gc")]
14
mod enabled;
15
#[cfg(feature = "gc")]
16
use enabled as imp;
17
18
#[cfg(not(feature = "gc"))]
19
mod disabled;
20
#[cfg(not(feature = "gc"))]
21
use disabled as imp;
22
23
// Re-export the GC compilation interface from the implementation that we chose
24
// based on the compile-time features enabled.
25
pub use imp::*;
26
27
/// How to initialize a newly-allocated array's elements.
28
#[derive(Clone, Copy)]
29
#[cfg_attr(not(feature = "gc"), expect(dead_code))]
30
pub enum ArrayInit<'a> {
31
/// Initialize the array's elements with the given values.
32
Elems(&'a [ir::Value]),
33
34
/// Initialize the array's elements with `elem` repeated `len` times.
35
Fill { elem: ir::Value, len: ir::Value },
36
}
37
38
/// A trait for different collectors to emit any GC barriers they might require.
39
pub trait GcCompiler {
40
/// Get the GC type layouts for this GC compiler.
41
#[cfg_attr(not(feature = "gc"), allow(dead_code))]
42
fn layouts(&self) -> &dyn GcTypeLayouts;
43
44
/// Emit code to allocate a new array.
45
///
46
/// The array should be of the given type and its elements initialized as
47
/// described by the given `ArrayInit`.
48
#[cfg_attr(not(feature = "gc"), allow(dead_code))]
49
fn alloc_array(
50
&mut self,
51
func_env: &mut FuncEnvironment<'_>,
52
builder: &mut FunctionBuilder<'_>,
53
array_type_index: TypeIndex,
54
init: ArrayInit<'_>,
55
) -> WasmResult<ir::Value>;
56
57
/// Emit code to allocate a new struct.
58
///
59
/// The struct should be of the given type and its fields initialized to the
60
/// given values.
61
#[cfg_attr(not(feature = "gc"), allow(dead_code))]
62
fn alloc_struct(
63
&mut self,
64
func_env: &mut FuncEnvironment<'_>,
65
builder: &mut FunctionBuilder<'_>,
66
struct_type_index: TypeIndex,
67
fields: &[ir::Value],
68
) -> WasmResult<ir::Value>;
69
70
/// Emit code to allocate a new exception object.
71
///
72
/// The exception object should be of the given type and its
73
/// fields initialized to the given values. The tag field is left
74
/// uninitialized; that is the responsibility of generated code to
75
/// fill in. `tag_index` is used only to look up the appropriate
76
/// exception object type.
77
#[cfg_attr(not(feature = "gc"), allow(dead_code))]
78
fn alloc_exn(
79
&mut self,
80
func_env: &mut FuncEnvironment<'_>,
81
builder: &mut FunctionBuilder<'_>,
82
tag_index: TagIndex,
83
fields: &[ir::Value],
84
instance_id: ir::Value,
85
tag: ir::Value,
86
) -> WasmResult<ir::Value>;
87
88
/// Emit a read barrier for when we are cloning a GC reference onto the Wasm
89
/// stack.
90
///
91
/// This is used, for example, when reading from a global or a table
92
/// element.
93
///
94
/// In pseudocode, this is the following operation:
95
///
96
/// ```ignore
97
/// x = *src;
98
/// ```
99
///
100
/// Parameters:
101
///
102
/// * `func_env`: The function environment that this GC compiler is
103
/// operating within.
104
///
105
/// * `builder`: Function builder. Currently at the position where the read
106
/// should be inserted. Upon return, should be positioned where control
107
/// continues just after the read completes. Any intermediate blocks
108
/// created in the process of emitting the read barrier should be added to
109
/// the layout and sealed.
110
///
111
/// * `ty`: The Wasm reference type that is being read.
112
///
113
/// * `src`: A pointer to the GC reference that should be read; this is an
114
/// instance of a `*mut Option<VMGcRef>`.
115
///
116
/// * `flags`: The memory flags that should be used when accessing `src`.
117
///
118
/// This method should return the cloned GC reference (an instance of
119
/// `VMGcRef`) of type `i32`.
120
fn translate_read_gc_reference(
121
&mut self,
122
func_env: &mut FuncEnvironment<'_>,
123
builder: &mut FunctionBuilder,
124
ty: WasmRefType,
125
src: ir::Value,
126
flags: ir::MemFlags,
127
) -> WasmResult<ir::Value>;
128
129
/// Emit a write barrier for when we are writing a GC reference over another
130
/// GC reference.
131
///
132
/// This is used, for example, when writing to a global or a table element.
133
///
134
/// In pseudocode, this is the following operation:
135
///
136
/// ```ignore
137
/// *dst = new_val;
138
/// ```
139
///
140
/// Parameters:
141
///
142
/// * `func_env`: The function environment that this GC compiler is
143
/// operating within.
144
///
145
/// * `builder`: Function builder. Currently at the position where the write
146
/// should be inserted. Upon return, should be positioned where control
147
/// continues just after the write completes. Any intermediate blocks
148
/// created in the process of emitting the read barrier should be added to
149
/// the layout and sealed.
150
///
151
/// * `ty`: The Wasm reference type that is being written.
152
///
153
/// * `dst`: A pointer to the GC reference that will be overwritten; note
154
/// that is this is an instance of a `*mut VMGcRef`, *not* a `VMGcRef`
155
/// itself or a `*mut VMGcHeader`!
156
///
157
/// * `new_val`: The new value that should be written into `dst`. This is a
158
/// `VMGcRef` of Cranelift type `i32`; not a `*mut VMGcRef`.
159
///
160
/// * `flags`: The memory flags that should be used when accessing `dst`.
161
fn translate_write_gc_reference(
162
&mut self,
163
func_env: &mut FuncEnvironment<'_>,
164
builder: &mut FunctionBuilder,
165
ty: WasmRefType,
166
dst: ir::Value,
167
new_val: ir::Value,
168
flags: ir::MemFlags,
169
) -> WasmResult<()>;
170
}
171
172
pub mod builtins {
173
use super::*;
174
175
macro_rules! define_builtin_accessors {
176
( $( $name:ident , )* ) => {
177
$(
178
#[inline]
179
pub fn $name(
180
func_env: &mut FuncEnvironment<'_>,
181
func: &mut ir::Function,
182
) -> WasmResult<ir::FuncRef> {
183
#[cfg(feature = "gc")]
184
{
185
func_env.needs_gc_heap = true;
186
return Ok(func_env.builtin_functions.$name(func));
187
}
188
189
#[cfg(not(feature = "gc"))]
190
{
191
let _ = (func, func_env);
192
return Err(wasmtime_environ::wasm_unsupported!(
193
"support for Wasm GC disabled at compile time because the `gc` cargo \
194
feature was not enabled"
195
));
196
}
197
}
198
)*
199
};
200
}
201
202
define_builtin_accessors! {
203
table_grow_gc_ref,
204
table_fill_gc_ref,
205
array_new_data,
206
array_new_elem,
207
array_copy,
208
array_init_data,
209
array_init_elem,
210
}
211
}
212
213