Skip to content

Commit 19a3ec2

Browse files
authored
wasmparser: Allow exhaustive matching on wasm features (#1499)
* wasmparser: Allow exhaustive matching on wasm features * Change `WasmFeatures::CUSTOM_PAGE_SIZE` to `WasmFeatures::CUSTOM_PAGE_SIZES` This matches the old name before the bit-packing and also the proposal name. * fix compilation errors
1 parent 6c80824 commit 19a3ec2

File tree

4 files changed

+135
-62
lines changed

4 files changed

+135
-62
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn parser_features_from_config(config: &Config) -> WasmFeatures {
2626
features.set(WasmFeatures::FUNCTION_REFERENCES, config.gc_enabled);
2727
features.set(WasmFeatures::GC, config.gc_enabled);
2828
features.set(
29-
WasmFeatures::CUSTOM_PAGE_SIZE,
29+
WasmFeatures::CUSTOM_PAGE_SIZES,
3030
config.custom_page_sizes_enabled,
3131
);
3232
features

crates/wasmparser/src/validator.rs

Lines changed: 132 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -198,33 +198,110 @@ impl Default for State {
198198
}
199199
}
200200

201-
bitflags! {
201+
macro_rules! define_wasm_features {
202+
(
203+
$(#[$outer:meta])*
204+
pub struct WasmFeatures: $repr:ty {
205+
$(
206+
$(#[$inner:ident $($args:tt)*])*
207+
pub $field:ident: $const:ident($flag:expr) = $default:expr;
208+
)*
209+
}
210+
) => {
211+
bitflags! {
212+
$(#[$outer])*
213+
pub struct WasmFeatures: $repr {
214+
$(
215+
$(#[$inner $($args)*])*
216+
#[doc = "\nDefaults to `"]
217+
#[doc = stringify!($default)]
218+
#[doc = "`.\n"]
219+
const $const = $flag;
220+
)*
221+
}
222+
}
223+
224+
impl Default for WasmFeatures {
225+
#[inline]
226+
fn default() -> Self {
227+
let mut features = WasmFeatures::empty();
228+
$(
229+
features.set(WasmFeatures::$const, $default);
230+
)*
231+
features
232+
}
233+
}
234+
235+
impl WasmFeatures {
236+
/// Construct a bit-packed `WasmFeatures` from the inflated struct version.
237+
#[inline]
238+
pub fn from_inflated(inflated: WasmFeaturesInflated) -> Self {
239+
let mut features = WasmFeatures::empty();
240+
$(
241+
features.set(WasmFeatures::$const, inflated.$field);
242+
)*
243+
features
244+
}
245+
246+
/// Inflate these bit-packed features into a struct with a field per
247+
/// feature.
248+
///
249+
/// Although the inflated struct takes up much more memory than the
250+
/// bit-packed version, its fields can be exhaustively matched
251+
/// upon. This makes it useful for temporarily checking against,
252+
/// while keeping the bit-packed version as the method of storing
253+
/// the features for longer periods of time.
254+
#[inline]
255+
pub fn inflate(&self) -> WasmFeaturesInflated {
256+
WasmFeaturesInflated {
257+
$(
258+
$field: self.contains(WasmFeatures::$const),
259+
)*
260+
}
261+
}
262+
}
263+
264+
/// Inflated version of [`WasmFeatures`][crate::WasmFeatures] that
265+
/// allows for exhaustive matching on fields.
266+
pub struct WasmFeaturesInflated {
267+
$(
268+
$(#[$inner $($args)*])*
269+
#[doc = "\nDefaults to `"]
270+
#[doc = stringify!($default)]
271+
#[doc = "`.\n"]
272+
pub $field: bool,
273+
)*
274+
}
275+
};
276+
}
277+
278+
define_wasm_features! {
202279
/// Flags for features that are enabled for validation.
203280
#[derive(Hash, Debug, Copy, Clone)]
204281
pub struct WasmFeatures: u32 {
205-
/// The WebAssembly `mutable-global` proposal (enabled by default)
206-
const MUTABLE_GLOBAL = 1;
207-
/// The WebAssembly `saturating-float-to-int` proposal (enabled by default)
208-
const SATURATING_FLOAT_TO_INT = 1 << 1;
209-
/// The WebAssembly `sign-extension-ops` proposal (enabled by default)
210-
const SIGN_EXTENSION = 1 << 2;
211-
/// The WebAssembly reference types proposal (enabled by default)
212-
const REFERENCE_TYPES = 1 << 3;
213-
/// The WebAssembly multi-value proposal (enabled by default)
214-
const MULTI_VALUE = 1 << 4;
215-
/// The WebAssembly bulk memory operations proposal (enabled by default)
216-
const BULK_MEMORY = 1 << 5;
217-
/// The WebAssembly SIMD proposal (enabled by default)
218-
const SIMD = 1 << 6;
219-
/// The WebAssembly Relaxed SIMD proposal (enabled by default)
220-
const RELAXED_SIMD = 1 << 7;
221-
/// The WebAssembly threads proposal (enabled by default)
222-
const THREADS = 1 << 8;
282+
/// The WebAssembly `mutable-global` proposal.
283+
pub mutable_global: MUTABLE_GLOBAL(1) = true;
284+
/// The WebAssembly `saturating-float-to-int` proposal.
285+
pub saturating_float_to_int: SATURATING_FLOAT_TO_INT(1 << 1) = true;
286+
/// The WebAssembly `sign-extension-ops` proposal.
287+
pub sign_extension: SIGN_EXTENSION(1 << 2) = true;
288+
/// The WebAssembly reference types proposal.
289+
pub reference_types: REFERENCE_TYPES(1 << 3) = true;
290+
/// The WebAssembly multi-value proposal.
291+
pub multi_value: MULTI_VALUE(1 << 4) = true;
292+
/// The WebAssembly bulk memory operations proposal.
293+
pub bulk_memory: BULK_MEMORY(1 << 5) = true;
294+
/// The WebAssembly SIMD proposal.
295+
pub simd: SIMD(1 << 6) = true;
296+
/// The WebAssembly Relaxed SIMD proposal.
297+
pub relaxed_simd: RELAXED_SIMD(1 << 7) = true;
298+
/// The WebAssembly threads proposal.
299+
pub threads: THREADS(1 << 8) = true;
223300
/// The WebAssembly shared-everything-threads proposal; includes new
224301
/// component model built-ins.
225-
const SHARED_EVERYTHING_THREADS = 1 << 9;
226-
/// The WebAssembly tail-call proposal (enabled by default)
227-
const TAIL_CALL = 1 << 10;
302+
pub shared_everything_threads: SHARED_EVERYTHING_THREADS(1 << 9) = false;
303+
/// The WebAssembly tail-call proposal.
304+
pub tail_call: TAIL_CALL(1 << 10) = true;
228305
/// Whether or not floating-point instructions are enabled.
229306
///
230307
/// This is enabled by default can be used to disallow floating-point
@@ -235,30 +312,44 @@ bitflags! {
235312
/// about execution. Floats in WebAssembly can have different NaN patterns
236313
/// across hosts which can lead to host-dependent execution which some
237314
/// runtimes may not desire.
238-
const FLOATS = 1 << 11;
239-
/// The WebAssembly multi memory proposal (enabled by default)
240-
const MULTI_MEMORY = 1 << 12;
241-
/// The WebAssembly exception handling proposal
242-
const EXCEPTIONS = 1 << 13;
243-
/// The WebAssembly memory64 proposal
244-
const MEMORY64 = 1 << 14;
245-
/// The WebAssembly extended_const proposal
246-
const EXTENDED_CONST = 1 << 15;
315+
pub floats: FLOATS(1 << 11) = true;
316+
/// The WebAssembly multi memory proposal.
317+
pub multi_memory: MULTI_MEMORY(1 << 12) = true;
318+
/// The WebAssembly exception handling proposal.
319+
pub exceptions: EXCEPTIONS(1 << 13) = false;
320+
/// The WebAssembly memory64 proposal.
321+
pub memory64: MEMORY64(1 << 14) = false;
322+
/// The WebAssembly extended_const proposal.
323+
pub extended_const: EXTENDED_CONST(1 << 15) = false;
247324
/// The WebAssembly component model proposal.
248-
const COMPONENT_MODEL = 1 << 16;
249-
/// The WebAssembly typed function references proposal
250-
const FUNCTION_REFERENCES = 1 << 17;
251-
/// The WebAssembly memory control proposal
252-
const MEMORY_CONTROL = 1 << 18;
253-
/// The WebAssembly gc proposal
254-
const GC = 1 << 19;
325+
pub component_model: COMPONENT_MODEL(1 << 16) = true;
326+
/// The WebAssembly typed function references proposal.
327+
pub function_references: FUNCTION_REFERENCES(1 << 17) = false;
328+
/// The WebAssembly memory control proposal.
329+
pub memory_control: MEMORY_CONTROL(1 << 18) = false;
330+
/// The WebAssembly gc proposal.
331+
pub gc: GC(1 << 19) = false;
255332
/// The WebAssembly [custom-page-sizes
256333
/// proposal](https://github.com/WebAssembly/custom-page-sizes).
257-
const CUSTOM_PAGE_SIZE = 1 << 20;
334+
pub custom_page_sizes: CUSTOM_PAGE_SIZES(1 << 20) = false;
258335
/// Support for the `value` type in the component model proposal.
259-
const COMPONENT_MODEL_VALUES = 1 << 21;
336+
pub component_model_values: COMPONENT_MODEL_VALUES(1 << 21) = false;
260337
/// Support for the nested namespaces and projects in component model names.
261-
const COMPONENT_MODEL_NESTED_NAMES = 1 << 22;
338+
pub component_model_nested_names: COMPONENT_MODEL_NESTED_NAMES(1 << 22) = false;
339+
}
340+
}
341+
342+
impl From<WasmFeaturesInflated> for WasmFeatures {
343+
#[inline]
344+
fn from(inflated: WasmFeaturesInflated) -> Self {
345+
Self::from_inflated(inflated)
346+
}
347+
}
348+
349+
impl From<WasmFeatures> for WasmFeaturesInflated {
350+
#[inline]
351+
fn from(features: WasmFeatures) -> Self {
352+
features.inflate()
262353
}
263354
}
264355

@@ -347,24 +438,6 @@ impl WasmFeatures {
347438
}
348439
}
349440

350-
impl Default for WasmFeatures {
351-
fn default() -> WasmFeatures {
352-
Self::MUTABLE_GLOBAL
353-
| Self::SATURATING_FLOAT_TO_INT
354-
| Self::SIGN_EXTENSION
355-
| Self::REFERENCE_TYPES
356-
| Self::MULTI_VALUE
357-
| Self::BULK_MEMORY
358-
| Self::SIMD
359-
| Self::RELAXED_SIMD
360-
| Self::THREADS
361-
| Self::TAIL_CALL
362-
| Self::FLOATS
363-
| Self::MULTI_MEMORY
364-
| Self::COMPONENT_MODEL
365-
}
366-
}
367-
368441
/// Possible return values from [`Validator::payload`].
369442
#[allow(clippy::large_enum_variant)]
370443
pub enum ValidPayload<'a> {

crates/wasmparser/src/validator/core.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ impl Module {
878878
) -> Result<()> {
879879
self.check_limits(ty.initial, ty.maximum, offset)?;
880880
let (page_size, page_size_log2) = if let Some(page_size_log2) = ty.page_size_log2 {
881-
if !features.contains(WasmFeatures::CUSTOM_PAGE_SIZE) {
881+
if !features.contains(WasmFeatures::CUSTOM_PAGE_SIZES) {
882882
return Err(BinaryReaderError::new(
883883
"the custom page sizes proposal must be enabled to \
884884
customize a memory's page size",

tests/roundtrip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ impl TestState {
620620
features.insert(WasmFeatures::FUNCTION_REFERENCES);
621621
features.insert(WasmFeatures::GC);
622622
}
623-
"custom-page-sizes" => features.insert(WasmFeatures::CUSTOM_PAGE_SIZE),
623+
"custom-page-sizes" => features.insert(WasmFeatures::CUSTOM_PAGE_SIZES),
624624
"import-extended.wast" => {
625625
features.insert(WasmFeatures::COMPONENT_MODEL_NESTED_NAMES);
626626
}

0 commit comments

Comments
 (0)