[fuzzer][wasm] Add support for reftypes in test generator

We add support for struct and arraytypes in wasm-fuzzer-common.
Also, we add addStruct and addArray while generating tests.
Other OptRef types like eqref/anyref have been supported.
Adding struct and arraytypes in wasm-compile has been placed
at the beginning in order to generate them in addSignature.

Bug: v8:11954
Change-Id: Ibe468dd4df70ad40367196c88353b28b7654f086
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3074463
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: Manos Koukoutos <manoskouk@chromium.org>
Commit-Queue: Rakhim Khismet <khismet@google.com>
Cr-Commit-Position: refs/heads/master@{#76137}
This commit is contained in:
Rakhim Khismet 2021-08-06 10:45:15 +00:00 committed by V8 LUCI CQ
parent 9b19cc5ca2
commit 7810ce0468
2 changed files with 100 additions and 29 deletions

View File

@ -1703,6 +1703,28 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
DataRange range(data);
std::vector<uint32_t> function_signatures;
// Add struct and array types first so that we get a chance to generate
// these types in function signatures
if (liftoff_as_reference) {
uint32_t count = 4;
StructType::Builder struct_builder(zone, count);
struct_builder.AddField(kWasmI32, false);
struct_builder.AddField(kWasmI64, false);
struct_builder.AddField(kWasmF32, false);
struct_builder.AddField(kWasmF64, false);
StructType* struct_fuz = struct_builder.Build();
builder.AddStructType(struct_fuz);
ArrayType* array_fuzI32 = zone->New<ArrayType>(kWasmI32, true);
ArrayType* array_fuzI64 = zone->New<ArrayType>(kWasmI64, true);
ArrayType* array_fuzF32 = zone->New<ArrayType>(kWasmF32, true);
ArrayType* array_fuzF64 = zone->New<ArrayType>(kWasmF64, true);
builder.AddArrayType(array_fuzI32);
builder.AddArrayType(array_fuzI64);
builder.AddArrayType(array_fuzF32);
builder.AddArrayType(array_fuzF64);
}
function_signatures.push_back(builder.AddSignature(sigs.i_iii()));
static_assert(kMaxFunctions >= 1, "need min. 1 function");
@ -1728,25 +1750,6 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
builder.AddException(sig);
}
if (liftoff_as_reference) {
uint32_t count = 4;
StructType::Builder struct_builder(zone, count);
struct_builder.AddField(kWasmI32, false);
struct_builder.AddField(kWasmI64, false);
struct_builder.AddField(kWasmF32, false);
struct_builder.AddField(kWasmF64, false);
StructType* struct_fuz = struct_builder.Build();
builder.AddStructType(struct_fuz);
ArrayType* array_fuzI32 = zone->New<ArrayType>(kWasmI32, true);
ArrayType* array_fuzI64 = zone->New<ArrayType>(kWasmI64, true);
ArrayType* array_fuzF32 = zone->New<ArrayType>(kWasmF32, true);
ArrayType* array_fuzF64 = zone->New<ArrayType>(kWasmF64, true);
builder.AddArrayType(array_fuzI32);
builder.AddArrayType(array_fuzI64);
builder.AddArrayType(array_fuzF32);
builder.AddArrayType(array_fuzF64);
}
for (int i = 0; i < num_globals; ++i) {
ValueType type =
GetValueType(builder.NumTypes(), &range, liftoff_as_reference);

View File

@ -11,6 +11,7 @@
#include "src/objects/objects-inl.h"
#include "src/utils/ostreams.h"
#include "src/wasm/baseline/liftoff-compiler.h"
#include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/module-instantiate.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-feature-flags.h"
@ -198,7 +199,7 @@ PrintSig PrintParameters(const FunctionSig* sig) {
PrintSig PrintReturns(const FunctionSig* sig) {
return {sig->return_count(), [=](size_t i) { return sig->GetReturn(i); }};
}
const char* ValueTypeToConstantName(ValueType type) {
std::string ValueTypeToConstantName(ValueType type) {
switch (type.kind()) {
case kI32:
return "kWasmI32";
@ -216,17 +217,44 @@ const char* ValueTypeToConstantName(ValueType type) {
return "kWasmExternRef";
case HeapType::kFunc:
return "kWasmFuncRef";
case HeapType::kEq:
return "kWasmEqRef";
case HeapType::kAny:
return "kWasmAnyRef";
case HeapType::kData:
return "wasmOptRefType(kWasmDataRef)";
case HeapType::kI31:
return "wasmOptRefType(kWasmI31Ref)";
case HeapType::kBottom:
default:
// TODO(7748): Implement these if fuzzing for them is enabled.
UNREACHABLE();
return "wasmOptRefType(" + std::to_string(type.ref_index()) + ")";
}
default:
UNREACHABLE();
}
}
std::string HeapTypeToConstantName(HeapType heap_type) {
switch (heap_type.representation()) {
case HeapType::kFunc:
return "kWasmFuncRef";
case HeapType::kExtern:
return "kWasmExternRef";
case HeapType::kEq:
return "kWasmEqRef";
case HeapType::kI31:
return "kWasmI31Ref";
case HeapType::kData:
return "kWasmDataRef";
case HeapType::kAny:
return "kWasmAnyRef";
case HeapType::kBottom:
UNREACHABLE();
default:
return std::to_string(heap_type.ref_index());
}
}
std::ostream& operator<<(std::ostream& os, const PrintSig& print) {
os << "[";
for (size_t i = 0; i < print.num; ++i) {
@ -292,10 +320,28 @@ void AppendInitExpr(std::ostream& os, ModuleWireBytes wire_bytes,
os << "F64Const(" << bit_cast<double>(result);
break;
}
case kSimdPrefix: {
DCHECK_LE(2 + kSimd128Size, expr.length());
DCHECK_EQ(static_cast<WasmOpcode>(pc[1]), kExprS128Const & 0xff);
os << "S128Const([";
for (int i = 0; i < kSimd128Size; i++) {
os << int(decoder.read_u8<Decoder::kNoValidation>(pc + 2 + i));
if (i + 1 < kSimd128Size) os << ", ";
}
os << "]";
break;
}
case kExprRefFunc:
os << "RefFunc("
<< decoder.read_u32v<Decoder::kNoValidation>(pc + 1, &length);
break;
case kExprRefNull: {
HeapType heap_type =
value_type_reader::read_heap_type<Decoder::kNoValidation>(
&decoder, pc + 1, &length, nullptr, WasmFeatures::All());
os << "RefNull(" << HeapTypeToConstantName(heap_type);
break;
}
default:
UNREACHABLE();
}
@ -334,7 +380,7 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes,
"can be\n"
"// found in the LICENSE file.\n"
"\n"
"// Flags: --wasm-staging\n"
"// Flags: --wasm-staging --experimental-wasm-gc\n"
"\n"
"load('test/mjsunit/wasm/wasm-module-builder.js');\n"
"\n"
@ -361,16 +407,38 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes,
os << ");\n";
}
// TODO(7748): Support array/struct types.
#if DEBUG
for (uint8_t kind : module->type_kinds) {
DCHECK_EQ(kWasmFunctionTypeCode, kind);
DCHECK(kWasmArrayTypeCode == kind || kWasmStructTypeCode == kind ||
kWasmFunctionTypeCode == kind);
}
#endif
for (TypeDefinition type : module->types) {
const FunctionSig* sig = type.function_sig;
os << "builder.addType(makeSig(" << PrintParameters(sig) << ", "
<< PrintReturns(sig) << "));\n";
for (int i = 0; i < static_cast<int>(module->types.size()); i++) {
if (module->has_struct(i)) {
const StructType* struct_type = module->types[i].struct_type;
os << "builder.addStruct([";
int field_count = struct_type->field_count();
for (int index = 0; index < field_count; index++) {
os << "makeField(" << ValueTypeToConstantName(struct_type->field(index))
<< ", " << (struct_type->mutability(index) ? "true" : "false")
<< ")";
if (index + 1 < field_count)
os << ", ";
else
os << "]);\n";
}
} else if (module->has_array(i)) {
const ArrayType* array_type = module->types[i].array_type;
os << "builder.addArray("
<< ValueTypeToConstantName(array_type->element_type()) << ","
<< (array_type->mutability() ? "true" : "false") << ");\n";
} else {
DCHECK(module->has_signature(i));
const FunctionSig* sig = module->types[i].function_sig;
os << "builder.addType(makeSig(" << PrintParameters(sig) << ", "
<< PrintReturns(sig) << "));\n";
}
}
Zone tmp_zone(isolate->allocator(), ZONE_NAME);