Skip to content

Commit 366f320

Browse files
authored
Update wasm spec test suite, add exception feature flags (#10553)
* Update wasm spec test suite, add exception feature flags This commit performs an update of the spec test suite submodule to the next-to-latest commit. The latest commit will require updating the `wast` dependency which isn't published yet. This update brings in the `wasm-3.0` folder of tests since it's been awhile since the last update. That update notably means that the exception-handling proposal is mixed in with all the others with various tests. Getting tests as flagged as passing or failing as a result was unexpectedly difficult. The solution I ended up settling on was to preemptively implement some infrastructure for the exceptions proposal: * `wasmtime::Config` methods * `wasmtime` CLI flags * integration with wast testing * various updates to `should_fail` It turns out we can run a few tests with the exception proposal, notably due to tags being implemented for stack switching. That meant that this couldn't blanket ignore the exceptions proposal and say it's expected to fail. Instead the proposal is said "this passes!" and tests are individually listed as "this is expected to fail". This then required changing an `unsupported!` panic to plumbing errors around to avoid actually implementing the exceptions proposal here. * Review comments
1 parent bdce217 commit 366f320

File tree

20 files changed

+209
-129
lines changed

20 files changed

+209
-129
lines changed

crates/cli-flags/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,10 @@ wasmtime_option_group! {
380380
pub wide_arithmetic: Option<bool>,
381381
/// Configure support for the extended-const proposal.
382382
pub extended_const: Option<bool>,
383+
/// Configure support for the exceptions proposal.
384+
pub exceptions: Option<bool>,
385+
/// DEPRECATED: Configure support for the legacy exceptions proposal.
386+
pub legacy_exceptions: Option<bool>,
383387
}
384388

385389
enum Wasm {
@@ -983,6 +987,13 @@ impl CommonOptions {
983987
if let Some(enable) = self.wasm.extended_const.or(all) {
984988
config.wasm_extended_const(enable);
985989
}
990+
if let Some(enable) = self.wasm.exceptions.or(all) {
991+
config.wasm_exceptions(enable);
992+
}
993+
if let Some(enable) = self.wasm.legacy_exceptions.or(all) {
994+
#[expect(deprecated, reason = "forwarding CLI flag")]
995+
config.wasm_legacy_exceptions(enable);
996+
}
986997

987998
macro_rules! handle_conditionally_compiled {
988999
($(($feature:tt, $field:tt, $method:tt))*) => ($(

crates/cranelift/src/translate/code_translator.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,7 @@ pub fn translate_operator(
12371237
translate_fcmp(FloatCC::LessThanOrEqual, builder, state)
12381238
}
12391239
Operator::RefNull { hty } => {
1240-
let hty = environ.convert_heap_type(*hty);
1240+
let hty = environ.convert_heap_type(*hty)?;
12411241
state.push1(environ.translate_ref_null(builder.cursor(), hty)?)
12421242
}
12431243
Operator::RefIsNull => {
@@ -2748,7 +2748,7 @@ pub fn translate_operator(
27482748
}
27492749
Operator::RefTestNonNull { hty } => {
27502750
let r = state.pop1();
2751-
let heap_type = environ.convert_heap_type(*hty);
2751+
let heap_type = environ.convert_heap_type(*hty)?;
27522752
let result = environ.translate_ref_test(
27532753
builder,
27542754
WasmRefType {
@@ -2761,7 +2761,7 @@ pub fn translate_operator(
27612761
}
27622762
Operator::RefTestNullable { hty } => {
27632763
let r = state.pop1();
2764-
let heap_type = environ.convert_heap_type(*hty);
2764+
let heap_type = environ.convert_heap_type(*hty)?;
27652765
let result = environ.translate_ref_test(
27662766
builder,
27672767
WasmRefType {
@@ -2774,7 +2774,7 @@ pub fn translate_operator(
27742774
}
27752775
Operator::RefCastNonNull { hty } => {
27762776
let r = state.pop1();
2777-
let heap_type = environ.convert_heap_type(*hty);
2777+
let heap_type = environ.convert_heap_type(*hty)?;
27782778
let cast_okay = environ.translate_ref_test(
27792779
builder,
27802780
WasmRefType {
@@ -2788,7 +2788,7 @@ pub fn translate_operator(
27882788
}
27892789
Operator::RefCastNullable { hty } => {
27902790
let r = state.pop1();
2791-
let heap_type = environ.convert_heap_type(*hty);
2791+
let heap_type = environ.convert_heap_type(*hty)?;
27922792
let cast_okay = environ.translate_ref_test(
27932793
builder,
27942794
WasmRefType {
@@ -2809,7 +2809,7 @@ pub fn translate_operator(
28092809
} => {
28102810
let r = state.peek1();
28112811

2812-
let to_ref_type = environ.convert_ref_type(*to_ref_type);
2812+
let to_ref_type = environ.convert_ref_type(*to_ref_type)?;
28132813
let cast_is_okay = environ.translate_ref_test(builder, to_ref_type, r)?;
28142814

28152815
let (cast_succeeds_block, inputs) = translate_br_if_args(*relative_depth, state);
@@ -2842,7 +2842,7 @@ pub fn translate_operator(
28422842
} => {
28432843
let r = state.peek1();
28442844

2845-
let to_ref_type = environ.convert_ref_type(*to_ref_type);
2845+
let to_ref_type = environ.convert_ref_type(*to_ref_type)?;
28462846
let cast_is_okay = environ.translate_ref_test(builder, to_ref_type, r)?;
28472847

28482848
let (cast_fails_block, inputs) = translate_br_if_args(*relative_depth, state);

crates/cranelift/src/translate/func_translator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ fn declare_locals(
202202
)
203203
}
204204
Ref(rt) => {
205-
let hty = environ.convert_heap_type(rt.heap_type());
205+
let hty = environ.convert_heap_type(rt.heap_type())?;
206206
let (ty, needs_stack_map) = environ.reference_type(hty);
207207
let init = if rt.is_nullable() {
208208
Some(environ.translate_ref_null(builder.cursor(), hty)?)

crates/cranelift/src/translate/translation_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub fn block_with_params<PE: TargetEnvironment + ?Sized>(
6363
builder.append_block_param(block, ir::types::F64);
6464
}
6565
wasmparser::ValType::Ref(rt) => {
66-
let hty = environ.convert_heap_type(rt.heap_type());
66+
let hty = environ.convert_heap_type(rt.heap_type())?;
6767
let (ty, needs_stack_map) = environ.reference_type(hty);
6868
let val = builder.append_block_param(block, ty);
6969
if needs_stack_map {

crates/environ/src/compile/module_environ.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
312312
}
313313
TypeRef::Global(ty) => {
314314
self.result.module.num_imported_globals += 1;
315-
EntityType::Global(self.convert_global_type(&ty))
315+
EntityType::Global(self.convert_global_type(&ty)?)
316316
}
317317
TypeRef::Table(ty) => {
318318
self.result.module.num_imported_tables += 1;
@@ -408,7 +408,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
408408
for f in escaped {
409409
self.flag_func_escaped(f);
410410
}
411-
let ty = self.convert_global_type(&ty);
411+
let ty = self.convert_global_type(&ty)?;
412412
self.result.module.globals.push(ty);
413413
self.result.module.global_initializers.push(initializer);
414414
}
@@ -545,7 +545,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
545545
let mut locals = Vec::new();
546546
for pair in body.get_locals_reader()? {
547547
let (cnt, ty) = pair?;
548-
let ty = self.convert_valtype(ty);
548+
let ty = self.convert_valtype(ty)?;
549549
locals.push((cnt, ty));
550550
}
551551
self.result

crates/environ/src/compile/module_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl ModuleTypesBuilder {
114114
unreachable!("no need to lookup indexes; we already have core type IDs")
115115
})
116116
.with_rec_group(validator_types, rec_group_id)
117-
.convert_sub_type(ty);
117+
.convert_sub_type(ty)?;
118118
self.wasm_sub_type_in_rec_group(id, wasm_ty);
119119
}
120120

crates/environ/src/component/translate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ impl<'a, 'data> Translator<'a, 'data> {
540540
for ty in s {
541541
match ty? {
542542
wasmparser::ComponentType::Resource { rep, dtor } => {
543-
let rep = self.types.convert_valtype(rep);
543+
let rep = self.types.convert_valtype(rep)?;
544544
let id = types
545545
.component_any_type_at(component_type_index)
546546
.unwrap_resource();

crates/environ/src/component/types_builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ impl ComponentTypesBuilder {
382382
}),
383383
Table(ty) => EntityType::Table(self.convert_table_type(ty)?),
384384
Memory(ty) => EntityType::Memory((*ty).into()),
385-
Global(ty) => EntityType::Global(self.convert_global_type(ty)),
385+
Global(ty) => EntityType::Global(self.convert_global_type(ty)?),
386386
Tag(_) => bail!("exceptions proposal not implemented"),
387387
})
388388
}

crates/environ/src/types.rs

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,11 +2089,11 @@ impl TypeTrace for Tag {
20892089
#[expect(missing_docs, reason = "self-describing functions")]
20902090
pub trait TypeConvert {
20912091
/// Converts a wasmparser table type into a wasmtime type
2092-
fn convert_global_type(&self, ty: &wasmparser::GlobalType) -> Global {
2093-
Global {
2094-
wasm_ty: self.convert_valtype(ty.content_type),
2092+
fn convert_global_type(&self, ty: &wasmparser::GlobalType) -> WasmResult<Global> {
2093+
Ok(Global {
2094+
wasm_ty: self.convert_valtype(ty.content_type)?,
20952095
mutability: ty.mutable,
2096-
}
2096+
})
20972097
}
20982098

20992099
/// Converts a wasmparser table type into a wasmtime type
@@ -2109,37 +2109,40 @@ pub trait TypeConvert {
21092109
Ok(Table {
21102110
idx_type,
21112111
limits,
2112-
ref_type: self.convert_ref_type(ty.element_type),
2112+
ref_type: self.convert_ref_type(ty.element_type)?,
21132113
})
21142114
}
21152115

2116-
fn convert_sub_type(&self, ty: &wasmparser::SubType) -> WasmSubType {
2117-
WasmSubType {
2116+
fn convert_sub_type(&self, ty: &wasmparser::SubType) -> WasmResult<WasmSubType> {
2117+
Ok(WasmSubType {
21182118
is_final: ty.is_final,
21192119
supertype: ty.supertype_idx.map(|i| self.lookup_type_index(i.unpack())),
2120-
composite_type: self.convert_composite_type(&ty.composite_type),
2121-
}
2120+
composite_type: self.convert_composite_type(&ty.composite_type)?,
2121+
})
21222122
}
21232123

2124-
fn convert_composite_type(&self, ty: &wasmparser::CompositeType) -> WasmCompositeType {
2124+
fn convert_composite_type(
2125+
&self,
2126+
ty: &wasmparser::CompositeType,
2127+
) -> WasmResult<WasmCompositeType> {
21252128
let inner = match &ty.inner {
21262129
wasmparser::CompositeInnerType::Func(f) => {
2127-
WasmCompositeInnerType::Func(self.convert_func_type(f))
2130+
WasmCompositeInnerType::Func(self.convert_func_type(f)?)
21282131
}
21292132
wasmparser::CompositeInnerType::Array(a) => {
2130-
WasmCompositeInnerType::Array(self.convert_array_type(a))
2133+
WasmCompositeInnerType::Array(self.convert_array_type(a)?)
21312134
}
21322135
wasmparser::CompositeInnerType::Struct(s) => {
2133-
WasmCompositeInnerType::Struct(self.convert_struct_type(s))
2136+
WasmCompositeInnerType::Struct(self.convert_struct_type(s)?)
21342137
}
21352138
wasmparser::CompositeInnerType::Cont(c) => {
21362139
WasmCompositeInnerType::Cont(self.convert_cont_type(c))
21372140
}
21382141
};
2139-
WasmCompositeType {
2142+
Ok(WasmCompositeType {
21402143
inner,
21412144
shared: ty.shared,
2142-
}
2145+
})
21432146
}
21442147

21452148
/// Converts a wasmparser continuation type to a wasmtime type
@@ -2151,73 +2154,73 @@ pub trait TypeConvert {
21512154
}
21522155
}
21532156

2154-
fn convert_struct_type(&self, ty: &wasmparser::StructType) -> WasmStructType {
2155-
WasmStructType {
2157+
fn convert_struct_type(&self, ty: &wasmparser::StructType) -> WasmResult<WasmStructType> {
2158+
Ok(WasmStructType {
21562159
fields: ty
21572160
.fields
21582161
.iter()
21592162
.map(|f| self.convert_field_type(f))
2160-
.collect(),
2161-
}
2163+
.collect::<WasmResult<_>>()?,
2164+
})
21622165
}
21632166

2164-
fn convert_array_type(&self, ty: &wasmparser::ArrayType) -> WasmArrayType {
2165-
WasmArrayType(self.convert_field_type(&ty.0))
2167+
fn convert_array_type(&self, ty: &wasmparser::ArrayType) -> WasmResult<WasmArrayType> {
2168+
Ok(WasmArrayType(self.convert_field_type(&ty.0)?))
21662169
}
21672170

2168-
fn convert_field_type(&self, ty: &wasmparser::FieldType) -> WasmFieldType {
2169-
WasmFieldType {
2170-
element_type: self.convert_storage_type(&ty.element_type),
2171+
fn convert_field_type(&self, ty: &wasmparser::FieldType) -> WasmResult<WasmFieldType> {
2172+
Ok(WasmFieldType {
2173+
element_type: self.convert_storage_type(&ty.element_type)?,
21712174
mutable: ty.mutable,
2172-
}
2175+
})
21732176
}
21742177

2175-
fn convert_storage_type(&self, ty: &wasmparser::StorageType) -> WasmStorageType {
2176-
match ty {
2178+
fn convert_storage_type(&self, ty: &wasmparser::StorageType) -> WasmResult<WasmStorageType> {
2179+
Ok(match ty {
21772180
wasmparser::StorageType::I8 => WasmStorageType::I8,
21782181
wasmparser::StorageType::I16 => WasmStorageType::I16,
2179-
wasmparser::StorageType::Val(v) => WasmStorageType::Val(self.convert_valtype(*v)),
2180-
}
2182+
wasmparser::StorageType::Val(v) => WasmStorageType::Val(self.convert_valtype(*v)?),
2183+
})
21812184
}
21822185

21832186
/// Converts a wasmparser function type to a wasmtime type
2184-
fn convert_func_type(&self, ty: &wasmparser::FuncType) -> WasmFuncType {
2187+
fn convert_func_type(&self, ty: &wasmparser::FuncType) -> WasmResult<WasmFuncType> {
21852188
let params = ty
21862189
.params()
21872190
.iter()
21882191
.map(|t| self.convert_valtype(*t))
2189-
.collect();
2192+
.collect::<WasmResult<_>>()?;
21902193
let results = ty
21912194
.results()
21922195
.iter()
21932196
.map(|t| self.convert_valtype(*t))
2194-
.collect();
2195-
WasmFuncType::new(params, results)
2197+
.collect::<WasmResult<_>>()?;
2198+
Ok(WasmFuncType::new(params, results))
21962199
}
21972200

21982201
/// Converts a wasmparser value type to a wasmtime type
2199-
fn convert_valtype(&self, ty: wasmparser::ValType) -> WasmValType {
2200-
match ty {
2202+
fn convert_valtype(&self, ty: wasmparser::ValType) -> WasmResult<WasmValType> {
2203+
Ok(match ty {
22012204
wasmparser::ValType::I32 => WasmValType::I32,
22022205
wasmparser::ValType::I64 => WasmValType::I64,
22032206
wasmparser::ValType::F32 => WasmValType::F32,
22042207
wasmparser::ValType::F64 => WasmValType::F64,
22052208
wasmparser::ValType::V128 => WasmValType::V128,
2206-
wasmparser::ValType::Ref(t) => WasmValType::Ref(self.convert_ref_type(t)),
2207-
}
2209+
wasmparser::ValType::Ref(t) => WasmValType::Ref(self.convert_ref_type(t)?),
2210+
})
22082211
}
22092212

22102213
/// Converts a wasmparser reference type to a wasmtime type
2211-
fn convert_ref_type(&self, ty: wasmparser::RefType) -> WasmRefType {
2212-
WasmRefType {
2214+
fn convert_ref_type(&self, ty: wasmparser::RefType) -> WasmResult<WasmRefType> {
2215+
Ok(WasmRefType {
22132216
nullable: ty.is_nullable(),
2214-
heap_type: self.convert_heap_type(ty.heap_type()),
2215-
}
2217+
heap_type: self.convert_heap_type(ty.heap_type())?,
2218+
})
22162219
}
22172220

22182221
/// Converts a wasmparser heap type to a wasmtime type
2219-
fn convert_heap_type(&self, ty: wasmparser::HeapType) -> WasmHeapType {
2220-
match ty {
2222+
fn convert_heap_type(&self, ty: wasmparser::HeapType) -> WasmResult<WasmHeapType> {
2223+
Ok(match ty {
22212224
wasmparser::HeapType::Concrete(i) => self.lookup_heap_type(i),
22222225
wasmparser::HeapType::Abstract { ty, shared: false } => match ty {
22232226
wasmparser::AbstractHeapType::Extern => WasmHeapType::Extern,
@@ -2235,11 +2238,11 @@ pub trait TypeConvert {
22352238
| wasmparser::AbstractHeapType::NoExn
22362239
| wasmparser::AbstractHeapType::Cont
22372240
| wasmparser::AbstractHeapType::NoCont => {
2238-
unimplemented!("unsupported heap type {ty:?}");
2241+
return Err(wasm_unsupported!("unsupported heap type {ty:?}"))
22392242
}
22402243
},
2241-
_ => unimplemented!("unsupported heap type {ty:?}"),
2242-
}
2244+
_ => return Err(wasm_unsupported!("unsupported heap type {ty:?}")),
2245+
})
22432246
}
22442247

22452248
/// Converts the specified type index from a heap type into a canonicalized

crates/fuzzing/src/generators/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ impl Config {
142142
component_model_async_builtins,
143143
component_model_async_stackful,
144144
simd,
145+
exceptions,
146+
legacy_exceptions,
145147

146148
hogs_memory: _,
147149
nan_canonicalization: _,
@@ -157,6 +159,7 @@ impl Config {
157159
component_model_async_builtins.unwrap_or(false);
158160
self.module_config.component_model_async_stackful =
159161
component_model_async_stackful.unwrap_or(false);
162+
self.module_config.legacy_exceptions = legacy_exceptions.unwrap_or(false);
160163

161164
// Enable/disable proposals that wasm-smith has knobs for which will be
162165
// read when creating `wasmtime::Config`.
@@ -175,6 +178,7 @@ impl Config {
175178
|| self.module_config.function_references_enabled
176179
|| reference_types.unwrap_or(false);
177180
config.extended_const_enabled = extended_const.unwrap_or(false);
181+
config.exceptions_enabled = exceptions.unwrap_or(false);
178182
if multi_memory.unwrap_or(false) {
179183
config.max_memories = limits::MEMORIES_PER_MODULE as usize;
180184
} else {
@@ -294,6 +298,8 @@ impl Config {
294298
cfg.wasm.tail_call = Some(self.module_config.config.tail_call_enabled);
295299
cfg.wasm.threads = Some(self.module_config.config.threads_enabled);
296300
cfg.wasm.wide_arithmetic = Some(self.module_config.config.wide_arithmetic_enabled);
301+
cfg.wasm.exceptions = Some(self.module_config.config.exceptions_enabled);
302+
cfg.wasm.legacy_exceptions = Some(self.module_config.legacy_exceptions);
297303
if !self.module_config.config.simd_enabled {
298304
cfg.wasm.relaxed_simd = Some(false);
299305
}

0 commit comments

Comments
 (0)