[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:
parent
a9143207f1
commit
44cd69a77d
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user