Skip to content

Commit c5bd644

Browse files
authored
Add a feature for disabling GC types (#1731)
* Add a feature for disabling GC types This commit adds support for a new wasm feature named `WasmFeatures::GC_TYPES`. This does not correspond to any upstream proposal and is intended for use in Wasmtime for disabling the runtime garbage collector at compile time. This serves as a finer-grained switch to disable the runtime dependency at validation time on a garbage collector without disabling all the features that were added in other proposals. For example the `reference-types` proposal also added support for multi-table which disabling a runtime garbage collector doesn't need to disable. * Fix wasm-smith tests * Fix test expectation
1 parent 56cf001 commit c5bd644

10 files changed

Lines changed: 134 additions & 8 deletions

File tree

crates/wasm-smith/tests/common/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use wasm_smith::Config;
22
use wasmparser::{types::Types, Validator, WasmFeatures};
33

44
pub fn parser_features_from_config(config: &Config) -> WasmFeatures {
5-
let mut features = WasmFeatures::MUTABLE_GLOBAL | WasmFeatures::FLOATS;
5+
let mut features = WasmFeatures::MUTABLE_GLOBAL | WasmFeatures::wasm1();
66
features.set(
77
WasmFeatures::SATURATING_FLOAT_TO_INT,
88
config.saturating_float_to_int_enabled,

crates/wasmparser/src/features.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,31 @@ define_wasm_features! {
157157
/// Support this feature as long as all leading browsers also support it
158158
/// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md
159159
pub legacy_exceptions: LEGACY_EXCEPTIONS(1 << 25) = false;
160+
/// Whether or not gc types are enabled.
161+
///
162+
/// This feature does not correspond to any WebAssembly proposal nor
163+
/// concept in the specification itself. This is intended to assist
164+
/// embedders in disabling support for GC types at validation time. For
165+
/// example if an engine wants to support all of WebAssembly except
166+
/// a runtime garbage collector it could disable this feature.
167+
///
168+
/// This features is enabled by default and is used to gate types such
169+
/// as `externref` or `anyref`. Note that the requisite WebAssembly
170+
/// proposal must also be enabled for types like `externref`, meaning
171+
/// that it requires both `REFERENCE_TYPES` and `GC_TYPE` to be enabled.
172+
///
173+
/// Note that the `funcref` and `exnref` types are not gated by this
174+
/// feature. Those are expected to not require a full garbage collector
175+
/// so are not gated by this.
176+
pub gc_types: GC_TYPES(1 << 26) = true;
160177
}
161178
}
162179

163180
impl WasmFeatures {
164181
/// Returns the feature set associated with the 1.0 version of the
165182
/// WebAssembly specification or the "MVP" feature set.
166183
pub fn wasm1() -> WasmFeatures {
167-
WasmFeatures::FLOATS
184+
WasmFeatures::FLOATS | WasmFeatures::GC_TYPES
168185
}
169186

170187
/// Returns the feature set associated with the 2.0 version of the

crates/wasmparser/src/validator.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ impl WasmFeatures {
251251
}
252252
match r.heap_type() {
253253
HeapType::Concrete(_) => {
254+
// Note that `self.gc_types()` is not checked here because
255+
// concrete pointers to function types are allowed. GC types
256+
// are disallowed by instead rejecting the definition of
257+
// array/struct types and only allowing the definition of
258+
// function types.
259+
254260
// Indexed types require either the function-references or gc
255261
// proposal as gc implies function references here.
256262
if self.function_references() || self.gc() {
@@ -266,6 +272,13 @@ impl WasmFeatures {
266272
"shared reference types require the shared-everything-threads proposal",
267273
);
268274
}
275+
276+
// Apply the "gc-types" feature which disallows all heap types
277+
// except exnref/funcref.
278+
if !self.gc_types() && ty != Func && ty != Exn {
279+
return Err("gc types are disallowed but found type which requires gc");
280+
}
281+
269282
match (ty, r.is_nullable()) {
270283
// funcref/externref only require `reference-types`.
271284
(Func, true) | (Extern, true) => Ok(()),

crates/wasmparser/src/validator/core.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -699,10 +699,16 @@ impl Module {
699699
}
700700
CompositeInnerType::Array(t) => {
701701
if !features.gc() {
702-
return Err(BinaryReaderError::new(
702+
bail!(
703+
offset,
703704
"array indexed types not supported without the gc feature",
705+
);
706+
}
707+
if !features.gc_types() {
708+
bail!(
704709
offset,
705-
));
710+
"cannot define array types when gc types are disabled",
711+
);
706712
}
707713
match &t.0.element_type {
708714
StorageType::I8 | StorageType::I16 => {
@@ -713,10 +719,16 @@ impl Module {
713719
}
714720
CompositeInnerType::Struct(t) => {
715721
if !features.gc() {
716-
return Err(BinaryReaderError::new(
722+
bail!(
723+
offset,
717724
"struct indexed types not supported without the gc feature",
725+
);
726+
}
727+
if !features.gc_types() {
728+
bail!(
718729
offset,
719-
));
730+
"cannot define struct types when gc types are disabled",
731+
);
720732
}
721733
for ft in t.fields.iter() {
722734
match &ft.element_type {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
error: invalid value 'unknown' for '--features <FEATURES>': unknown feature `unknown`
2-
Valid features: mutable-global, saturating-float-to-int, sign-extension, reference-types, multi-value, bulk-memory, simd, relaxed-simd, threads, shared-everything-threads, tail-call, floats, multi-memory, exceptions, memory64, extended-const, component-model, function-references, memory-control, gc, custom-page-sizes, component-model-values, component-model-nested-names, component-model-more-flags, component-model-multiple-returns, legacy-exceptions
2+
Valid features: mutable-global, saturating-float-to-int, sign-extension, reference-types, multi-value, bulk-memory, simd, relaxed-simd, threads, shared-everything-threads, tail-call, floats, multi-memory, exceptions, memory64, extended-const, component-model, function-references, memory-control, gc, custom-page-sizes, component-model-values, component-model-nested-names, component-model-more-flags, component-model-multiple-returns, legacy-exceptions, gc-types
33

44
For more information, try '--help'.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
(assert_invalid
2+
(module
3+
(type (func (result externref)))
4+
)
5+
"gc types are disallowed")
6+
7+
(assert_invalid
8+
(module
9+
(type (func (result (ref any))))
10+
)
11+
"gc types are disallowed")
12+
13+
(module
14+
(table 1 funcref)
15+
)
16+
17+
(module
18+
(type $t (func))
19+
(table 1 (ref null $t))
20+
)
21+
22+
(assert_invalid
23+
(module
24+
(type (array i8))
25+
)
26+
"cannot define array types")
27+
28+
(assert_invalid
29+
(module
30+
(type (struct))
31+
)
32+
"cannot define struct types")

tests/roundtrip.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,9 +610,11 @@ impl TestState {
610610
features.remove(WasmFeatures::THREADS);
611611
}
612612
"missing-features" => {
613-
features = WasmFeatures::empty() | WasmFeatures::FLOATS;
613+
features =
614+
WasmFeatures::empty() | WasmFeatures::FLOATS | WasmFeatures::GC_TYPES;
614615
}
615616
"floats-disabled.wast" => features.remove(WasmFeatures::FLOATS),
617+
"gc-types-disabled.wast" => features.remove(WasmFeatures::GC_TYPES),
616618
"threads" => {
617619
features.insert(WasmFeatures::THREADS);
618620
features.remove(WasmFeatures::BULK_MEMORY);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"source_filename": "tests/local/missing-features/gc/gc-types-disabled.wast",
3+
"commands": [
4+
{
5+
"type": "assert_invalid",
6+
"line": 2,
7+
"filename": "gc-types-disabled.0.wasm",
8+
"text": "gc types are disallowed",
9+
"module_type": "binary"
10+
},
11+
{
12+
"type": "assert_invalid",
13+
"line": 8,
14+
"filename": "gc-types-disabled.1.wasm",
15+
"text": "gc types are disallowed",
16+
"module_type": "binary"
17+
},
18+
{
19+
"type": "module",
20+
"line": 13,
21+
"filename": "gc-types-disabled.2.wasm"
22+
},
23+
{
24+
"type": "module",
25+
"line": 17,
26+
"filename": "gc-types-disabled.3.wasm"
27+
},
28+
{
29+
"type": "assert_invalid",
30+
"line": 23,
31+
"filename": "gc-types-disabled.4.wasm",
32+
"text": "cannot define array types",
33+
"module_type": "binary"
34+
},
35+
{
36+
"type": "assert_invalid",
37+
"line": 29,
38+
"filename": "gc-types-disabled.5.wasm",
39+
"text": "cannot define struct types",
40+
"module_type": "binary"
41+
}
42+
]
43+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(module
2+
(table (;0;) 1 funcref)
3+
)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(module
2+
(type $t (;0;) (func))
3+
(table (;0;) 1 (ref null $t))
4+
)

0 commit comments

Comments
 (0)