diff options
author | Thomas Lively <tlively@google.com> | 2022-12-02 10:14:17 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-02 08:14:17 -0800 |
commit | ed06104c6f342d14653932b02d5b060654db0d1d (patch) | |
tree | 02d88fb5414f051a3b0b9aa885fad9dd8a303048 | |
parent | 197b6da7afe6ec317011800abf9453402e6beaa5 (diff) | |
download | binaryen-ed06104c6f342d14653932b02d5b060654db0d1d.tar.gz binaryen-ed06104c6f342d14653932b02d5b060654db0d1d.tar.bz2 binaryen-ed06104c6f342d14653932b02d5b060654db0d1d.zip |
Support `array` and `struct` types in the type fuzzer (#5308)
Since `data` has been removed from the upstream proposal and `struct` has been
added in its place, update the type fuzzer to be structured around `struct` and
`array` (which it had not previously been updated to support) rather than
`data`. A follow-on PR will make the broader change of removing `data` and
adding `struct`.
-rw-r--r-- | src/tools/fuzzing/heap-types.cpp | 94 | ||||
-rw-r--r-- | test/lit/fuzz-types/isorecursive.test | 50 | ||||
-rw-r--r-- | test/lit/fuzz-types/nominal.test | 38 |
3 files changed, 101 insertions, 81 deletions
diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index e93aae56c..7d7b4cb8d 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -39,8 +39,10 @@ struct HeapTypeGeneratorImpl { // before we actually generate the types. using BasicKind = HeapType::BasicHeapType; struct SignatureKind {}; - struct DataKind {}; - using HeapTypeKind = std::variant<BasicKind, SignatureKind, DataKind>; + struct StructKind {}; + struct ArrayKind {}; + using HeapTypeKind = + std::variant<BasicKind, SignatureKind, StructKind, ArrayKind>; std::vector<HeapTypeKind> typeKinds; // For each type, the index one past the end of its recursion group, used to @@ -122,12 +124,10 @@ struct HeapTypeGeneratorImpl { // No nontrivial supertype, so create a root type. if (std::get_if<SignatureKind>(&kind)) { builder[index] = generateSignature(); - } else if (std::get_if<DataKind>(&kind)) { - if (rand.oneIn(2)) { - builder[index] = generateStruct(); - } else { - builder[index] = generateArray(); - } + } else if (std::get_if<StructKind>(&kind)) { + builder[index] = generateStruct(); + } else if (std::get_if<ArrayKind>(&kind)) { + builder[index] = generateArray(); } else { WASM_UNREACHABLE("unexpected kind"); } @@ -152,13 +152,14 @@ struct HeapTypeGeneratorImpl { if (rand.oneIn(16)) { return rand.pick(HeapType::noext, HeapType::nofunc, HeapType::none); } - // TODO: strings and array + // TODO: string types return rand.pick(HeapType::func, HeapType::ext, HeapType::any, HeapType::eq, HeapType::i31, - HeapType::data); + HeapType::data, + HeapType::array); } Type::BasicType generateBasicType() { @@ -266,8 +267,8 @@ struct HeapTypeGeneratorImpl { } } - HeapType pickSubData() { - if (auto type = pickKind<DataKind>()) { + HeapType pickSubStruct() { + if (auto type = pickKind<StructKind>()) { return *type; } else if (rand.oneIn(2)) { return HeapType::none; @@ -276,12 +277,26 @@ struct HeapTypeGeneratorImpl { } } - HeapType pickSubEq() { - if (rand.oneIn(2)) { - return HeapType::i31; + HeapType pickSubArray() { + if (auto type = pickKind<ArrayKind>()) { + return *type; + } else if (rand.oneIn(2)) { + return HeapType::none; } else { - return pickSubData(); + return HeapType::array; + } + } + + HeapType pickSubEq() { + switch (rand.upTo(3)) { + case 0: + return HeapType::i31; + case 1: + return pickSubStruct(); + case 2: + return pickSubArray(); } + WASM_UNREACHABLE("unexpected index"); } HeapType pickSubAny() { @@ -325,9 +340,9 @@ struct HeapTypeGeneratorImpl { case HeapType::i31: return HeapType::i31; case HeapType::data: - return pickSubData(); + return pickSubStruct(); case HeapType::array: - WASM_UNREACHABLE("TODO: fuzz array"); + return pickSubArray(); case HeapType::string: case HeapType::stringview_wtf8: case HeapType::stringview_wtf16: @@ -412,8 +427,10 @@ struct HeapTypeGeneratorImpl { case 0: return SignatureKind{}; case 1: - return DataKind{}; + return StructKind{}; case 2: + return ArrayKind{}; + case 3: return BasicKind{generateBasicHeapType()}; } WASM_UNREACHABLE("unexpected index"); @@ -426,7 +443,9 @@ struct HeapTypeGeneratorImpl { return HeapType(*basic).getBottom(); } else if (std::get_if<SignatureKind>(&super)) { return HeapType::nofunc; - } else if (std::get_if<DataKind>(&super)) { + } else if (std::get_if<StructKind>(&super)) { + return HeapType::none; + } else if (std::get_if<ArrayKind>(&super)) { return HeapType::none; } WASM_UNREACHABLE("unexpected kind"); @@ -442,31 +461,26 @@ struct HeapTypeGeneratorImpl { case HeapType::i31: return super; case HeapType::any: - if (rand.oneIn(4)) { - switch (rand.upTo(3)) { - case 0: - return HeapType::eq; - case 1: - return HeapType::i31; - case 2: - return HeapType::data; - } + if (rand.oneIn(5)) { + return HeapType::eq; } - return DataKind{}; + [[fallthrough]]; case HeapType::eq: - if (rand.oneIn(4)) { - switch (rand.upTo(2)) { - case 0: - return HeapType::i31; - case 1: - return HeapType::data; - } + switch (rand.upTo(4)) { + case 0: + return HeapType::i31; + case 1: + return HeapType::data; + case 2: + return StructKind{}; + case 3: + return ArrayKind{}; } - return DataKind{}; + WASM_UNREACHABLE("unexpected index"); case HeapType::data: - return DataKind{}; + return StructKind{}; case HeapType::array: - WASM_UNREACHABLE("TODO: fuzz array"); + return ArrayKind{}; case HeapType::string: case HeapType::stringview_wtf8: case HeapType::stringview_wtf16: diff --git a/test/lit/fuzz-types/isorecursive.test b/test/lit/fuzz-types/isorecursive.test index 4a1725c07..f670104f5 100644 --- a/test/lit/fuzz-types/isorecursive.test +++ b/test/lit/fuzz-types/isorecursive.test @@ -1,26 +1,32 @@ -;; RUN: wasm-fuzz-types --hybrid -v --seed=0 | filecheck %s +;; RUN: wasm-fuzz-types --hybrid -v --seed=1 | filecheck %s -;; CHECK: (rec -;; CHECK-NEXT: (type $0 (array (mut i64))) -;; CHECK-NEXT: (type $1 (func (param i32 (ref eq) (ref null $3)) (result v128))) -;; CHECK-NEXT: (type $2 (array (mut v128))) -;; CHECK-NEXT: (type $3 (array_subtype (mut i64) $0)) -;; CHECK-NEXT: (type $4 (array i32)) -;; CHECK-NEXT: (type $5 none) -;; CHECK-NEXT: (type $6 extern) +;; CHECK: (type $0 (struct)) +;; CHECK-NEXT: (rec +;; CHECK-NEXT: (type $1 (struct)) +;; CHECK-NEXT: (type $2 (array i16)) +;; CHECK-NEXT: (type $3 (func)) +;; CHECK-NEXT: (type $4 (func (param (ref $5) i32 i64 f64 f64 (ref eq) v128) (result i64))) +;; CHECK-NEXT: (type $5 (array (mut i32))) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $7 (array_subtype (mut i64) $3)) -;; CHECK-NEXT: (type $8 (func (result v128))) -;; CHECK-NEXT: (type $9 (array_subtype (mut v128) $2)) -;; CHECK-NEXT: (type $10 none) -;; CHECK-NEXT: (type $11 none) -;; CHECK-NEXT: (type $12 (array_subtype (mut v128) $2)) -;; CHECK-NEXT: (type $13 (func (param f32 (ref none) (ref null $3)) (result eqref))) -;; CHECK-NEXT: (type $14 (array_subtype (mut i64) $7)) -;; CHECK-NEXT: (type $15 (func (param (ref null $17) v128 (ref i31)))) -;; CHECK-NEXT: (type $16 (array i32)) -;; CHECK-NEXT: (type $17 (func (param (ref i31)) (result v128))) -;; CHECK-NEXT: (type $18 (func (param f32))) -;; CHECK-NEXT: (type $19 (array_subtype (mut i64) $3)) +;; CHECK-NEXT: (type $6 (array (mut funcref))) +;; CHECK-NEXT: (type $7 (func (param f64) (result i64))) ;; CHECK-NEXT: ) +;; CHECK-NEXT: (rec +;; CHECK-NEXT: (type $8 (struct_subtype $1)) +;; CHECK-NEXT: (type $9 (func_subtype (param (ref $5) i32 i64 f64 f64 (ref eq) v128) (result i64) $4)) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (rec +;; CHECK-NEXT: (type $10 (func_subtype (param (ref $5) i32 i64 f64 f64 (ref eq) v128) (result i64) $9)) +;; CHECK-NEXT: (type $11 (array_subtype (mut funcref) $6)) +;; CHECK-NEXT: (type $12 (array f64)) +;; CHECK-NEXT: (type $13 none) +;; CHECK-NEXT: (type $14 (array arrayref)) +;; CHECK-NEXT: (type $15 (array (mut i8))) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (rec +;; CHECK-NEXT: (type $16 (array_subtype f64 $12)) +;; CHECK-NEXT: (type $17 (func (param (ref $5) (ref null $3) (ref null $0) (ref null $2) (ref $8) v128) (result v128))) +;; CHECK-NEXT: (type $18 none) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (type $19 (func_subtype (param (ref $5) i32 i64 f64 f64 (ref eq) v128) (result i64) $9)) diff --git a/test/lit/fuzz-types/nominal.test b/test/lit/fuzz-types/nominal.test index 26802a4ba..c127105bb 100644 --- a/test/lit/fuzz-types/nominal.test +++ b/test/lit/fuzz-types/nominal.test @@ -1,22 +1,22 @@ ;; RUN: wasm-fuzz-types --nominal -v --seed=0 | filecheck %s -;; CHECK: (type $0 (array (mut (ref null $8)))) -;; CHECK-NEXT: (type $1 (func (param nullref) (result v128))) -;; CHECK-NEXT: (type $2 (struct (field (mut i64) (mut i8) (mut (ref $12)) (mut f32)))) -;; CHECK-NEXT: (type $3 (array_subtype (mut (ref null $8)) $0)) -;; CHECK-NEXT: (type $4 (array (mut i64))) +;; CHECK: (type $0 (struct (field (mut i16) i31ref f32 f32 f64))) +;; CHECK-NEXT: (type $1 (func (param f64 v128))) +;; CHECK-NEXT: (type $2 (struct (field (mut (ref null $19)) f64 arrayref))) +;; CHECK-NEXT: (type $3 (struct_subtype (field (mut i16) (ref i31) f32 f32 f64) $0)) +;; CHECK-NEXT: (type $4 (struct (field (mut (ref null $11)) (mut i8)))) ;; CHECK-NEXT: (type $5 none) -;; CHECK-NEXT: (type $6 extern) -;; CHECK-NEXT: (type $7 (array_subtype (mut (ref null $8)) $3)) -;; CHECK-NEXT: (type $8 (func (result (ref $9)))) -;; CHECK-NEXT: (type $9 (struct_subtype (field (mut i64) (mut i8) (mut (ref $12)) (mut f32) i16) $2)) -;; CHECK-NEXT: (type $10 none) -;; CHECK-NEXT: (type $11 none) -;; CHECK-NEXT: (type $12 (struct_subtype (field (mut i64) (mut i8) (mut (ref $12)) (mut f32) (mut f32) (mut (ref $4))) $2)) -;; CHECK-NEXT: (type $13 (func (param dataref))) -;; CHECK-NEXT: (type $14 (array_subtype (mut (ref null $8)) $7)) -;; CHECK-NEXT: (type $15 (func (param externref))) -;; CHECK-NEXT: (type $16 (array v128)) -;; CHECK-NEXT: (type $17 (func (result (ref extern)))) -;; CHECK-NEXT: (type $18 (func (param v128 i64))) -;; CHECK-NEXT: (type $19 (array_subtype (mut (ref null $8)) $3)) +;; CHECK-NEXT: (type $6 (array (ref null $18))) +;; CHECK-NEXT: (type $7 (func_subtype (param f64 v128) $1)) +;; CHECK-NEXT: (type $8 (array (mut (ref null $19)))) +;; CHECK-NEXT: (type $9 (array (mut f64))) +;; CHECK-NEXT: (type $10 (struct_subtype (field (mut i16) i31ref f32 f32 f64) $0)) +;; CHECK-NEXT: (type $11 (func (param i32 f64) (result (ref null $8)))) +;; CHECK-NEXT: (type $12 (func_subtype (param f64 v128) $1)) +;; CHECK-NEXT: (type $13 (func_subtype (param f64 v128) $12)) +;; CHECK-NEXT: (type $14 (func_subtype (param i32 f64) (result (ref null $8)) $11)) +;; CHECK-NEXT: (type $15 (func_subtype (param i32 f64) (result (ref null $8)) $14)) +;; CHECK-NEXT: (type $16 (func (result v128))) +;; CHECK-NEXT: (type $17 (array f32)) +;; CHECK-NEXT: (type $18 (array i64)) +;; CHECK-NEXT: (type $19 (struct_subtype (field (mut i16) (ref none) f32 f32 f64 (ref $2)) $0)) |