diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index 3bc74eb0f1a..af8e235e442 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -19,7 +19,6 @@ #include "ir/gc-type-utils.h" #include "ir/subtypes.h" -#include "support/insert_ordered.h" #include "tools/fuzzing.h" #include "tools/fuzzing/heap-types.h" @@ -275,12 +274,13 @@ struct HeapTypeGeneratorImpl { builder[index].setOpen(subtypeIndices[index].size() > 1 || rand.oneIn(2)); auto kind = typeKinds[index]; auto share = HeapType(builder[index]).getShared(); + bool isDesc = describedIndices[index].has_value(); if (!supertypeIndices[index]) { // No nontrivial supertype, so create a root type. if (std::get_if(&kind)) { builder[index] = generateSignature(); } else if (std::get_if(&kind)) { - builder[index] = generateStruct(share); + builder[index] = generateStruct(share, isDesc); } else if (std::get_if(&kind)) { builder[index] = generateArray(share); } else { @@ -415,7 +415,13 @@ struct HeapTypeGeneratorImpl { return {params, generateReturnType()}; } - Field generateField(Shareability share) { + Field generateField(Shareability share, bool isPrototypeField = false) { + // If this field could configure a prototype, then we want to give it a type + // that lets it do so a significant portion of the time. + if (isPrototypeField && share == Unshared && rand.oneIn(2)) { + auto nullability = rand.oneIn(2) ? NonNullable : Nullable; + return {Type(HeapType::ext, nullability), Immutable}; + } auto mutability = rand.oneIn(2) ? Mutable : Immutable; if (rand.oneIn(6)) { return {rand.oneIn(2) ? Field::i8 : Field::i16, mutability}; @@ -424,10 +430,13 @@ struct HeapTypeGeneratorImpl { } } - Struct generateStruct(Shareability share) { + Struct generateStruct(Shareability share, bool isDesc) { std::vector fields(rand.upTo(params.MAX_STRUCT_SIZE + 1)); + // Prototypes are configured on the first field of descriptors types. + bool isPrototypeField = isDesc; for (auto& field : fields) { - field = generateField(share); + field = generateField(share, isPrototypeField); + isPrototypeField = false; } return {fields}; } diff --git a/test/lit/fuzz-types.test b/test/lit/fuzz-types.test index 840fc1bb36b..44d475f6e3d 100644 --- a/test/lit/fuzz-types.test +++ b/test/lit/fuzz-types.test @@ -1,64 +1,56 @@ -;; RUN: wasm-fuzz-types -v --seed=0 | filecheck %s +;; RUN: wasm-fuzz-types -v --seed=2 | filecheck %s -;; CHECK: Running with seed 0 +;; CHECK: Running with seed 2 ;; CHECK-NEXT: Built 20 types: -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $0 (sub (shared (array i8)))) -;; CHECK-NEXT: (type $1 (shared (array (ref $1)))) -;; CHECK-NEXT: (type $2 (sub (shared (func (param i64 (ref null $5) i64) (result (ref $2)))))) -;; CHECK-NEXT: (type $3 (sub $0 (shared (array i8)))) -;; CHECK-NEXT: (type $4 (sub (array (ref null $9)))) -;; CHECK-NEXT: (type $5 (sub final $0 (shared (array i8)))) -;; CHECK-NEXT: (type $6 (sub $2 (shared (func (param i64 (ref null (shared eq)) i64) (result (ref $8)))))) -;; CHECK-NEXT: (type $7 (sub (shared (descriptor $9) (struct (field (ref null $7)) (field (mut i64)) (field (mut i8)) (field i32) (field (mut i32)))))) -;; CHECK-NEXT: (type $8 (sub $2 (shared (func (param i64 (ref null $0) i64) (result (ref $8)))))) -;; CHECK-NEXT: (type $9 (shared (describes $7) (descriptor $12) (struct (field i32) (field (mut (ref $8))) (field f64)))) -;; CHECK-NEXT: (type $10 (sub (array (mut externref)))) -;; CHECK-NEXT: (type $11 (sub $4 (array (ref $9)))) -;; CHECK-NEXT: (type $12 (sub (shared (describes $9) (struct (field (mut f64)) (field (mut i32)) (field (mut f64)))))) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $13 (sub (struct (field (mut i16)) (field i64) (field (mut (ref (shared func))))))) -;; CHECK-NEXT: (type $14 (sub (shared (array (ref null $14))))) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $15 (shared (array (ref null (shared extern))))) -;; CHECK-NEXT: (type $16 (sub final $14 (shared (array (ref null $16))))) +;; CHECK-NEXT: (type $0 (shared (struct))) +;; CHECK-NEXT: (rec +;; CHECK-NEXT: (type $1 (array (ref $2))) +;; CHECK-NEXT: (type $2 (sub (shared (array (mut i16))))) +;; CHECK-NEXT: (type $3 (sub (shared (array i32)))) +;; CHECK-NEXT: (type $4 (sub (descriptor $5) (struct (field (mut (ref $0)))))) +;; CHECK-NEXT: (type $5 (sub (describes $4) (struct (field f64) (field (mut i64))))) +;; CHECK-NEXT: (type $6 (sub (array v128))) +;; CHECK-NEXT: (type $7 (shared (struct (field f32) (field (mut (ref $0)))))) +;; CHECK-NEXT: (type $8 (sub (shared (struct (field f64) (field (mut (ref (shared struct)))) (field (mut f64)) (field i16) (field i32) (field i64))))) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $17 (shared (struct (field (mut (ref null $2))) (field i32) (field (mut (ref $14)))))) -;; CHECK-NEXT: (type $18 (sub $11 (array (ref $9)))) -;; CHECK-NEXT: (type $19 (sub $2 (shared (func (param i64 (ref null $0) i64) (result (ref $6)))))) +;; CHECK-NEXT: (type $9 (descriptor $12) (struct (field i64) (field i16))) +;; CHECK-NEXT: (type $10 (array (mut (ref null $5)))) +;; CHECK-NEXT: (type $11 (sub (shared (func (param (ref $7) f64 (ref $9)) (result (ref null $10)))))) +;; CHECK-NEXT: (type $12 (sub (describes $9) (descriptor $13) (struct (field (ref (shared any))) (field (mut (ref extern))) (field v128) (field (ref null $17))))) +;; CHECK-NEXT: (type $13 (sub (describes $12) (descriptor $17) (struct (field externref) (field (mut i8)) (field (mut i32)) (field (mut f32)) (field i16) (field (mut (ref null $6)))))) +;; CHECK-NEXT: (type $14 (sub (func (result i64)))) +;; CHECK-NEXT: (type $15 (sub (shared (func)))) +;; CHECK-NEXT: (type $16 (shared (func (result (ref null $0))))) +;; CHECK-NEXT: (type $17 (sub (describes $13) (struct (field (ref extern))))) +;; CHECK-NEXT: (type $18 (sub (func (param v128 (ref null $10))))) +;; CHECK-NEXT: (type $19 (sub final $11 (shared (func (param (ref null (shared any)) f64 (ref any)) (result (ref $10)))))) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ;; CHECK-NEXT: Inhabitable types: ;; CHECK-NEXT: ;; CHECK-NEXT: Built 20 types: -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $0 (sub (shared (array i8)))) -;; CHECK-NEXT: (type $1 (shared (array (ref null $1)))) -;; CHECK-NEXT: (type $2 (sub (shared (func (param i64 (ref null $5) i64) (result (ref $2)))))) -;; CHECK-NEXT: (type $3 (sub $0 (shared (array i8)))) -;; CHECK-NEXT: (type $4 (sub (array (ref null $9)))) -;; CHECK-NEXT: (type $5 (sub final $0 (shared (array i8)))) -;; CHECK-NEXT: (type $6 (sub $2 (shared (func (param i64 (ref null (shared eq)) i64) (result (ref $8)))))) -;; CHECK-NEXT: (type $7 (sub (shared (descriptor $9) (struct (field (ref null $7)) (field (mut i64)) (field (mut i8)) (field i32) (field (mut i32)))))) -;; CHECK-NEXT: (type $8 (sub $2 (shared (func (param i64 (ref null $0) i64) (result (ref $8)))))) -;; CHECK-NEXT: (type $9 (shared (describes $7) (descriptor $12) (struct (field i32) (field (mut (ref $8))) (field f64)))) -;; CHECK-NEXT: (type $10 (sub (array (mut externref)))) -;; CHECK-NEXT: (type $11 (sub $4 (array (ref $9)))) -;; CHECK-NEXT: (type $12 (sub (shared (describes $9) (struct (field (mut f64)) (field (mut i32)) (field (mut f64)))))) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $13 (sub (struct (field (mut i16)) (field i64) (field (mut (ref (shared func))))))) -;; CHECK-NEXT: (type $14 (sub (shared (array (ref null $14))))) +;; CHECK-NEXT: (type $0 (shared (struct))) +;; CHECK-NEXT: (rec +;; CHECK-NEXT: (type $1 (array (ref $2))) +;; CHECK-NEXT: (type $2 (sub (shared (array (mut i16))))) +;; CHECK-NEXT: (type $3 (sub (shared (array i32)))) +;; CHECK-NEXT: (type $4 (sub (descriptor $5) (struct (field (mut (ref $0)))))) +;; CHECK-NEXT: (type $5 (sub (describes $4) (struct (field f64) (field (mut i64))))) +;; CHECK-NEXT: (type $6 (sub (array v128))) +;; CHECK-NEXT: (type $7 (shared (struct (field f32) (field (mut (ref $0)))))) +;; CHECK-NEXT: (type $8 (sub (shared (struct (field f64) (field (mut (ref (shared struct)))) (field (mut f64)) (field i16) (field i32) (field i64))))) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $15 (shared (array (ref null (shared extern))))) -;; CHECK-NEXT: (type $16 (sub final $14 (shared (array (ref null $16))))) +;; CHECK-NEXT: (type $9 (descriptor $12) (struct (field i64) (field i16))) +;; CHECK-NEXT: (type $10 (array (mut (ref null $5)))) +;; CHECK-NEXT: (type $11 (sub (shared (func (param (ref $7) f64 (ref $9)) (result (ref null $10)))))) +;; CHECK-NEXT: (type $12 (sub (describes $9) (descriptor $13) (struct (field (ref (shared any))) (field (mut externref)) (field v128) (field (ref null $17))))) +;; CHECK-NEXT: (type $13 (sub (describes $12) (descriptor $17) (struct (field externref) (field (mut i8)) (field (mut i32)) (field (mut f32)) (field i16) (field (mut (ref null $6)))))) +;; CHECK-NEXT: (type $14 (sub (func (result i64)))) +;; CHECK-NEXT: (type $15 (sub (shared (func)))) +;; CHECK-NEXT: (type $16 (shared (func (result (ref null $0))))) +;; CHECK-NEXT: (type $17 (sub (describes $13) (struct (field externref)))) +;; CHECK-NEXT: (type $18 (sub (func (param v128 (ref null $10))))) +;; CHECK-NEXT: (type $19 (sub final $11 (shared (func (param (ref null (shared any)) f64 (ref any)) (result (ref $10)))))) ;; CHECK-NEXT: ) -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $17 (shared (struct (field (mut (ref null $2))) (field i32) (field (mut (ref $14)))))) -;; CHECK-NEXT: (type $18 (sub $11 (array (ref $9)))) -;; CHECK-NEXT: (type $19 (sub $2 (shared (func (param i64 (ref null $0) i64) (result (ref $6)))))) -;; CHECK-NEXT: ) \ No newline at end of file