[wasm][fuzzer] Adapt --wasm-fuzzer-gen-test to new format

In crrev.com/c/3714237, we changed the representation of constant
expressions in mjsunit wasm tests to byte arrays. This CL complements
this change by updating the output of --wasm-fuzzer-gen-test to the
new format.

Change-Id: I6a9d861b5abe13621ffd2ceb3a54863b0188b40c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3726294
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81414}
This commit is contained in:
Manos Koukoutos 2022-06-28 13:37:03 +00:00 committed by V8 LUCI CQ
parent a9143207f1
commit 44cd69a77d
4 changed files with 74 additions and 167 deletions

View File

@ -558,20 +558,21 @@ void WriteInitializerExpressionWithEnd(ZoneBuffer* buffer,
buffer->write_u32v(init.immediate().index);
break;
case WasmInitExpr::kArrayNewFixed:
case WasmInitExpr::kArrayNewFixedStatic:
case WasmInitExpr::kArrayNewFixedStatic: {
static_assert((kExprArrayNewFixed >> 8) == kGCPrefix);
static_assert((kExprArrayNewFixedStatic >> 8) == kGCPrefix);
bool is_static = init.kind() == WasmInitExpr::kArrayNewFixedStatic;
for (const WasmInitExpr& operand : *init.operands()) {
WriteInitializerExpressionWithEnd(buffer, operand, kWasmBottom);
}
buffer->write_u8(kGCPrefix);
buffer->write_u8(
static_cast<uint8_t>(init.kind() == WasmInitExpr::kArrayNewFixed
? kExprArrayNewFixed
: kExprArrayNewFixedStatic));
buffer->write_u8(static_cast<uint8_t>(is_static ? kExprArrayNewFixedStatic
: kExprArrayNewFixed));
buffer->write_u32v(init.immediate().index);
buffer->write_u32v(static_cast<uint32_t>(init.operands()->size() - 1));
buffer->write_u32v(
static_cast<uint32_t>(init.operands()->size() - (is_static ? 0 : 1)));
break;
}
case WasmInitExpr::kI31New:
WriteInitializerExpressionWithEnd(buffer, (*init.operands())[0],
kWasmI32);

View File

@ -865,17 +865,13 @@ class WasmGenerator {
[](ValueType type) -> bool { return type.is_defaultable(); });
if (new_default && can_be_defaultable) {
builder_->EmitWithPrefix(kExprRttCanon);
builder_->EmitU32V(index);
builder_->EmitWithPrefix(kExprStructNewDefaultWithRtt);
builder_->EmitWithPrefix(kExprStructNewDefault);
builder_->EmitU32V(index);
} else {
for (int i = 0; i < field_count; i++) {
Generate(struct_gen->field(i).Unpacked(), data);
}
builder_->EmitWithPrefix(kExprRttCanon);
builder_->EmitU32V(index);
builder_->EmitWithPrefix(kExprStructNewWithRtt);
builder_->EmitWithPrefix(kExprStructNew);
builder_->EmitU32V(index);
}
} else if (builder_->builder()->IsArrayType(index)) {
@ -887,9 +883,7 @@ class WasmGenerator {
Generate(kWasmI32, data);
builder_->EmitI32Const(kMaxArraySize);
builder_->Emit(kExprI32RemS);
builder_->EmitWithPrefix(kExprRttCanon);
builder_->EmitU32V(index);
builder_->EmitWithPrefix(kExprArrayNewDefaultWithRtt);
builder_->EmitWithPrefix(kExprArrayNewDefault);
builder_->EmitU32V(index);
} else {
Generate(
@ -898,9 +892,7 @@ class WasmGenerator {
Generate(kWasmI32, data);
builder_->EmitI32Const(kMaxArraySize);
builder_->Emit(kExprI32RemS);
builder_->EmitWithPrefix(kExprRttCanon);
builder_->EmitU32V(index);
builder_->EmitWithPrefix(kExprArrayNewWithRtt);
builder_->EmitWithPrefix(kExprArrayNew);
builder_->EmitU32V(index);
}
} else {
@ -2362,8 +2354,7 @@ WasmInitExpr GenerateStructNewInitExpr(Zone* zone, WasmModuleBuilder* builder,
struct_type->field(field_index),
num_struct_and_array_types));
}
elements->push_back(WasmInitExpr::RttCanon(index));
return WasmInitExpr::StructNewWithRtt(index, elements);
return WasmInitExpr::StructNew(index, elements);
}
WasmInitExpr GenerateInitExpr(Zone* zone, WasmModuleBuilder* builder,
@ -2413,8 +2404,7 @@ WasmInitExpr GenerateInitExpr(Zone* zone, WasmModuleBuilder* builder,
elements->push_back(GenerateInitExpr(
zone, builder, builder->GetArrayType(index)->element_type(),
num_struct_and_array_types));
elements->push_back(WasmInitExpr::RttCanon(index));
return WasmInitExpr::ArrayNewFixed(index, elements);
return WasmInitExpr::ArrayNewFixedStatic(index, elements);
}
if (builder->IsSignature(index)) {
// Transform from signature index to function index.

View File

@ -212,6 +212,34 @@ PrintSig PrintReturns(const FunctionSig* sig) {
return {sig->return_count(), [=](size_t i) { return sig->GetReturn(i); }};
}
std::string index_raw(uint32_t arg) {
return arg < 128 ? std::to_string(arg)
: "wasmUnsignedLeb(" + std::to_string(arg) + ")";
}
std::string index(uint32_t arg) { return index_raw(arg) + ", "; }
std::string HeapTypeToJSByteEncoding(HeapType heap_type) {
switch (heap_type.representation()) {
case HeapType::kFunc:
return "kFuncRefCode";
case HeapType::kEq:
return "kEqRefCode";
case HeapType::kI31:
return "kI31RefCode";
case HeapType::kData:
return "kDataRefCode";
case HeapType::kArray:
return "kArrayRefCode";
case HeapType::kAny:
return "kAnyRefCode";
case HeapType::kBottom:
UNREACHABLE();
default:
return index_raw(heap_type.ref_index());
}
}
std::string HeapTypeToConstantName(HeapType heap_type) {
switch (heap_type.representation()) {
case HeapType::kFunc:
@ -292,17 +320,14 @@ std::ostream& operator<<(std::ostream& os, const PrintName& name) {
return os.put('\'').write(name.name.begin(), name.name.size()).put('\'');
}
// An interface for WasmFullDecoder used to decode constant expressions. As
// opposed to the one in src/wasm/, this emits {WasmInitExpr} as opposed to a
// {ConstantExpression} (which evaluates to {WasmValue}).
// An interface for WasmFullDecoder which appends to a stream a textual
// representation of the expression, compatible with wasm-module-builder.js.
class InitExprInterface {
public:
static constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation;
static constexpr DecodingMode decoding_mode = kConstantExpression;
struct Value : public ValueBase<validate> {
WasmInitExpr init_expr;
template <typename... Args>
explicit Value(Args&&... args) V8_NOEXCEPT
: ValueBase(std::forward<Args>(args)...) {}
@ -312,7 +337,7 @@ class InitExprInterface {
using FullDecoder =
WasmFullDecoder<validate, InitExprInterface, decoding_mode>;
explicit InitExprInterface(Zone* zone) : zone_(zone) {}
explicit InitExprInterface(StdoutStream& os) : os_(os) { os_ << "["; }
#define EMPTY_INTERFACE_FUNCTION(name, ...) \
V8_INLINE void name(FullDecoder* decoder, ##__VA_ARGS__) {}
@ -324,24 +349,28 @@ class InitExprInterface {
#undef UNREACHABLE_INTERFACE_FUNCTION
void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
result->init_expr = WasmInitExpr(value);
os_ << "...wasmI32Const(" << value << "), ";
}
void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
result->init_expr = WasmInitExpr(value);
os_ << "...wasmI64Const(" << value << "), ";
}
void F32Const(FullDecoder* decoder, Value* result, float value) {
result->init_expr = WasmInitExpr(value);
os_ << "...wasmF32Const(" << value << "), ";
}
void F64Const(FullDecoder* decoder, Value* result, double value) {
result->init_expr = WasmInitExpr(value);
os_ << "...wasmF64Const(" << value << "), ";
}
void S128Const(FullDecoder* decoder, Simd128Immediate<validate>& imm,
Value* result) {
result->init_expr = WasmInitExpr(imm.value);
os_ << "kSimdPrefix, kExprS128Const, " << std::hex;
for (int i = 0; i < kSimd128Size; i++) {
os_ << "0x" << static_cast<int>(imm.value[i]) << ", ";
}
os_ << std::dec;
}
void BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs,
@ -351,57 +380,38 @@ class InitExprInterface {
}
void RefNull(FullDecoder* decoder, ValueType type, Value* result) {
result->init_expr = WasmInitExpr::RefNullConst(type.heap_representation());
os_ << "kExprRefNull, " << HeapTypeToJSByteEncoding(type.heap_type())
<< ", ";
}
void RefFunc(FullDecoder* decoder, uint32_t function_index, Value* result) {
result->init_expr = WasmInitExpr::RefFuncConst(function_index);
os_ << "kExprRefFunc, " << index(function_index);
}
void GlobalGet(FullDecoder* decoder, Value* result,
const GlobalIndexImmediate<validate>& imm) {
result->init_expr = WasmInitExpr::GlobalGet(imm.index);
os_ << "kWasmGlobalGet, " << index(imm.index);
}
// The following three operations assume non-rtt versions of the instructions.
void StructNewWithRtt(FullDecoder* decoder,
const StructIndexImmediate<validate>& imm,
const Value& rtt, const Value args[], Value* result) {
ZoneVector<WasmInitExpr>* elements =
zone_->New<ZoneVector<WasmInitExpr>>(zone_);
for (size_t i = 0; i < imm.struct_type->field_count(); i++) {
elements->push_back(args[i].init_expr);
}
bool nominal = decoder->module_->has_supertype(imm.index);
if (!nominal) elements->push_back(rtt.init_expr);
result->init_expr =
nominal ? WasmInitExpr::StructNew(imm.index, elements)
: WasmInitExpr::StructNewWithRtt(imm.index, elements);
os_ << "kGCPrefix, kExprStructNew, " << index(imm.index);
}
void StructNewDefault(FullDecoder* decoder,
const StructIndexImmediate<validate>& imm,
const Value& rtt, Value* result) {
bool nominal = decoder->module_->has_supertype(imm.index);
result->init_expr = nominal ? WasmInitExpr::StructNewDefault(imm.index)
: WasmInitExpr::StructNewDefaultWithRtt(
zone_, imm.index, rtt.init_expr);
os_ << "kGCPrefix, kExprStructNewDefault, " << index(imm.index);
}
void ArrayNewFixed(FullDecoder* decoder,
const ArrayIndexImmediate<validate>& imm,
const base::Vector<Value>& elements, const Value& rtt,
Value* result) {
ZoneVector<WasmInitExpr>* args =
zone_->New<ZoneVector<WasmInitExpr>>(zone_);
for (Value expr : elements) args->push_back(expr.init_expr);
bool nominal = decoder->module_->has_supertype(imm.index);
if (!nominal) args->push_back(rtt.init_expr);
result->init_expr = nominal
? WasmInitExpr::ArrayNewFixedStatic(imm.index, args)
: WasmInitExpr::ArrayNewFixed(imm.index, args);
os_ << "kGCPrefix, kExprArrayNewFixedStatic, " << index(imm.index)
<< index(static_cast<uint32_t>(elements.size()));
}
void ArrayNewSegment(FullDecoder* decoder,
@ -414,115 +424,23 @@ class InitExprInterface {
}
void I31New(FullDecoder* decoder, const Value& input, Value* result) {
result->init_expr = WasmInitExpr::I31New(zone_, input.init_expr);
os_ << "kGCPrefix, kExprI31New, ";
}
void RttCanon(FullDecoder* decoder, uint32_t type_index, Value* result) {
result->init_expr = WasmInitExpr::RttCanon(type_index);
}
// Since we treat all instructions as rtt-less, we should not print rtts.
void RttCanon(FullDecoder* decoder, uint32_t type_index, Value* result) {}
void StringConst(FullDecoder* decoder,
const StringConstImmediate<validate>& imm, Value* result) {
result->init_expr = WasmInitExpr::StringConst(imm.index);
os_ << "kGCPrefix, kExprStringConst, " << index(imm.index);
}
void DoReturn(FullDecoder* decoder, uint32_t /*drop_values*/) {
// End decoding on "end".
decoder->set_end(decoder->pc() + 1);
result_ = decoder->stack_value(1)->init_expr;
}
WasmInitExpr result() { return result_; }
void DoReturn(FullDecoder* decoder, uint32_t /*drop_values*/) { os_ << "]"; }
private:
WasmInitExpr result_;
Zone* zone_;
StdoutStream& os_;
};
// Appends an constant expression encoded in {wire_bytes}, in the offset
// contained in {expr}.
void AppendInitExpr(std::ostream& os, const WasmInitExpr& expr) {
os << "WasmInitExpr.";
bool append_operands = false;
switch (expr.kind()) {
case WasmInitExpr::kNone:
UNREACHABLE();
case WasmInitExpr::kGlobalGet:
os << "GlobalGet(" << expr.immediate().index;
break;
case WasmInitExpr::kI32Const:
os << "I32Const(" << expr.immediate().i32_const;
break;
case WasmInitExpr::kI64Const:
os << "I64Const(" << expr.immediate().i64_const;
break;
case WasmInitExpr::kF32Const:
os << "F32Const(" << expr.immediate().f32_const;
break;
case WasmInitExpr::kF64Const:
os << "F64Const(" << expr.immediate().f64_const;
break;
case WasmInitExpr::kS128Const:
os << "S128Const([";
for (int i = 0; i < kSimd128Size; i++) {
os << static_cast<int>(expr.immediate().s128_const[i]);
if (i < kSimd128Size - 1) os << ", ";
}
os << "]";
break;
case WasmInitExpr::kRefNullConst:
os << "RefNull("
<< HeapTypeToConstantName(HeapType(expr.immediate().heap_type));
break;
case WasmInitExpr::kRefFuncConst:
os << "RefFunc(" << expr.immediate().index;
break;
case WasmInitExpr::kStructNewWithRtt:
os << "StructNewWithRtt(" << expr.immediate().index;
append_operands = true;
break;
case WasmInitExpr::kStructNew:
os << "StructNew(" << expr.immediate().index;
append_operands = true;
break;
case WasmInitExpr::kStructNewDefaultWithRtt:
os << "StructNewDefaultWithRtt(" << expr.immediate().index << ", ";
AppendInitExpr(os, (*expr.operands())[0]);
break;
case WasmInitExpr::kStructNewDefault:
os << "StructNewDefault(" << expr.immediate().index;
break;
case WasmInitExpr::kArrayNewFixed:
os << "ArrayNewFixed(" << expr.immediate().index;
append_operands = true;
break;
case WasmInitExpr::kArrayNewFixedStatic:
os << "ArrayNewFixedStatic(" << expr.immediate().index;
append_operands = true;
break;
case WasmInitExpr::kI31New:
os << "I31New(" << expr.immediate().i32_const;
break;
case WasmInitExpr::kRttCanon:
os << "RttCanon(" << expr.immediate().index;
break;
case WasmInitExpr::kStringConst:
os << "StringConst(" << expr.immediate().index;
break;
}
if (append_operands) {
os << ", [";
for (size_t i = 0; i < expr.operands()->size(); i++) {
AppendInitExpr(os, (*expr.operands())[i]);
if (i < expr.operands()->size() - 1) os << ", ";
}
os << "]";
}
os << ")";
}
void DecodeAndAppendInitExpr(StdoutStream& os, Zone* zone,
const WasmModule* module,
ModuleWireBytes module_bytes,
@ -531,13 +449,14 @@ void DecodeAndAppendInitExpr(StdoutStream& os, Zone* zone,
case ConstantExpression::kEmpty:
UNREACHABLE();
case ConstantExpression::kI32Const:
AppendInitExpr(os, WasmInitExpr(init.i32_value()));
os << "wasmI32Const(" << init.i32_value() << ")";
break;
case ConstantExpression::kRefNull:
AppendInitExpr(os, WasmInitExpr::RefNullConst(init.repr()));
os << "[kExprRefNull, " << HeapTypeToJSByteEncoding(HeapType(init.repr()))
<< "]";
break;
case ConstantExpression::kRefFunc:
AppendInitExpr(os, WasmInitExpr::RefFuncConst(init.index()));
os << "[kExprRefFunc, " << index(init.index()) << "]";
break;
case ConstantExpression::kWireBytesRef: {
WireBytesRef ref = init.wire_bytes_ref();
@ -547,11 +466,8 @@ void DecodeAndAppendInitExpr(StdoutStream& os, Zone* zone,
WasmFeatures detected;
WasmFullDecoder<Decoder::kFullValidation, InitExprInterface,
kConstantExpression>
decoder(zone, module, WasmFeatures::All(), &detected, body, zone);
decoder(zone, module, WasmFeatures::All(), &detected, body, os);
decoder.DecodeFunctionBody();
AppendInitExpr(os, decoder.interface().result());
break;
}
}

View File

@ -1365,7 +1365,7 @@ class WasmModuleBuilder {
case kWasmF64:
return wasmF64Const(0.0);
case kWasmS128:
return [kSimdPrefix, kExprSimdConst, ...(new Array(16).fill(0))];
return [kSimdPrefix, kExprS128Const, ...(new Array(16).fill(0))];
default:
if ((typeof type) != 'number' && type.opcode != kWasmOptRef) {
throw new Error("Non-defaultable type");