Skip to content

Commit

Permalink
Add a feature for disabling GC types (#1731)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
alexcrichton authored Aug 21, 2024
1 parent 56cf001 commit c5bd644
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 8 deletions.
2 changes: 1 addition & 1 deletion crates/wasm-smith/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use wasm_smith::Config;
use wasmparser::{types::Types, Validator, WasmFeatures};

pub fn parser_features_from_config(config: &Config) -> WasmFeatures {
let mut features = WasmFeatures::MUTABLE_GLOBAL | WasmFeatures::FLOATS;
let mut features = WasmFeatures::MUTABLE_GLOBAL | WasmFeatures::wasm1();
features.set(
WasmFeatures::SATURATING_FLOAT_TO_INT,
config.saturating_float_to_int_enabled,
Expand Down
19 changes: 18 additions & 1 deletion crates/wasmparser/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,31 @@ define_wasm_features! {
/// Support this feature as long as all leading browsers also support it
/// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md
pub legacy_exceptions: LEGACY_EXCEPTIONS(1 << 25) = false;
/// Whether or not gc types are enabled.
///
/// This feature does not correspond to any WebAssembly proposal nor
/// concept in the specification itself. This is intended to assist
/// embedders in disabling support for GC types at validation time. For
/// example if an engine wants to support all of WebAssembly except
/// a runtime garbage collector it could disable this feature.
///
/// This features is enabled by default and is used to gate types such
/// as `externref` or `anyref`. Note that the requisite WebAssembly
/// proposal must also be enabled for types like `externref`, meaning
/// that it requires both `REFERENCE_TYPES` and `GC_TYPE` to be enabled.
///
/// Note that the `funcref` and `exnref` types are not gated by this
/// feature. Those are expected to not require a full garbage collector
/// so are not gated by this.
pub gc_types: GC_TYPES(1 << 26) = true;
}
}

impl WasmFeatures {
/// Returns the feature set associated with the 1.0 version of the
/// WebAssembly specification or the "MVP" feature set.
pub fn wasm1() -> WasmFeatures {
WasmFeatures::FLOATS
WasmFeatures::FLOATS | WasmFeatures::GC_TYPES
}

/// Returns the feature set associated with the 2.0 version of the
Expand Down
13 changes: 13 additions & 0 deletions crates/wasmparser/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ impl WasmFeatures {
}
match r.heap_type() {
HeapType::Concrete(_) => {
// Note that `self.gc_types()` is not checked here because
// concrete pointers to function types are allowed. GC types
// are disallowed by instead rejecting the definition of
// array/struct types and only allowing the definition of
// function types.

// Indexed types require either the function-references or gc
// proposal as gc implies function references here.
if self.function_references() || self.gc() {
Expand All @@ -266,6 +272,13 @@ impl WasmFeatures {
"shared reference types require the shared-everything-threads proposal",
);
}

// Apply the "gc-types" feature which disallows all heap types
// except exnref/funcref.
if !self.gc_types() && ty != Func && ty != Exn {
return Err("gc types are disallowed but found type which requires gc");
}

match (ty, r.is_nullable()) {
// funcref/externref only require `reference-types`.
(Func, true) | (Extern, true) => Ok(()),
Expand Down
20 changes: 16 additions & 4 deletions crates/wasmparser/src/validator/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,10 +699,16 @@ impl Module {
}
CompositeInnerType::Array(t) => {
if !features.gc() {
return Err(BinaryReaderError::new(
bail!(
offset,
"array indexed types not supported without the gc feature",
);
}
if !features.gc_types() {
bail!(
offset,
));
"cannot define array types when gc types are disabled",
);
}
match &t.0.element_type {
StorageType::I8 | StorageType::I16 => {
Expand All @@ -713,10 +719,16 @@ impl Module {
}
CompositeInnerType::Struct(t) => {
if !features.gc() {
return Err(BinaryReaderError::new(
bail!(
offset,
"struct indexed types not supported without the gc feature",
);
}
if !features.gc_types() {
bail!(
offset,
));
"cannot define struct types when gc types are disabled",
);
}
for ft in t.fields.iter() {
match &ft.element_type {
Expand Down
2 changes: 1 addition & 1 deletion tests/cli/validate-unknown-features.wat.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: invalid value 'unknown' for '--features <FEATURES>': unknown feature `unknown`
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
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

For more information, try '--help'.
32 changes: 32 additions & 0 deletions tests/local/missing-features/gc/gc-types-disabled.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
(assert_invalid
(module
(type (func (result externref)))
)
"gc types are disallowed")

(assert_invalid
(module
(type (func (result (ref any))))
)
"gc types are disallowed")

(module
(table 1 funcref)
)

(module
(type $t (func))
(table 1 (ref null $t))
)

(assert_invalid
(module
(type (array i8))
)
"cannot define array types")

(assert_invalid
(module
(type (struct))
)
"cannot define struct types")
4 changes: 3 additions & 1 deletion tests/roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,9 +610,11 @@ impl TestState {
features.remove(WasmFeatures::THREADS);
}
"missing-features" => {
features = WasmFeatures::empty() | WasmFeatures::FLOATS;
features =
WasmFeatures::empty() | WasmFeatures::FLOATS | WasmFeatures::GC_TYPES;
}
"floats-disabled.wast" => features.remove(WasmFeatures::FLOATS),
"gc-types-disabled.wast" => features.remove(WasmFeatures::GC_TYPES),
"threads" => {
features.insert(WasmFeatures::THREADS);
features.remove(WasmFeatures::BULK_MEMORY);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"source_filename": "tests/local/missing-features/gc/gc-types-disabled.wast",
"commands": [
{
"type": "assert_invalid",
"line": 2,
"filename": "gc-types-disabled.0.wasm",
"text": "gc types are disallowed",
"module_type": "binary"
},
{
"type": "assert_invalid",
"line": 8,
"filename": "gc-types-disabled.1.wasm",
"text": "gc types are disallowed",
"module_type": "binary"
},
{
"type": "module",
"line": 13,
"filename": "gc-types-disabled.2.wasm"
},
{
"type": "module",
"line": 17,
"filename": "gc-types-disabled.3.wasm"
},
{
"type": "assert_invalid",
"line": 23,
"filename": "gc-types-disabled.4.wasm",
"text": "cannot define array types",
"module_type": "binary"
},
{
"type": "assert_invalid",
"line": 29,
"filename": "gc-types-disabled.5.wasm",
"text": "cannot define struct types",
"module_type": "binary"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(module
(table (;0;) 1 funcref)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(module
(type $t (;0;) (func))
(table (;0;) 1 (ref null $t))
)

0 comments on commit c5bd644

Please sign in to comment.