[wasm] Make multi-return tests wasm-specific
The multi-return tests and fuzzer used a custom call descriptor which was based on the default RegisterConfiguration. This meant that for the tests, all available registers could be used to pass parameters and to return values. This caused a problem, because in some cases we need a scratch register in the frame deconstruction. With this CL I change both the tests and the fuzzer to use the WebAssembly call descriptor. Thereby we only use 2 registers for returns, and one of the other registers can be used as scratch register. WebAssembly is the only use case at the moment which wants to return values not only through registers but also over the stack. Therefore I think it's acceptable to only test the WebAssembly usecase. R=mstarzinger@chromium.org Bug: chromium:813288 Change-Id: I31bed757af5f3e8589d2b3dfb6f0112ddecd1a20 Reviewed-on: https://chromium-review.googlesource.com/970656 Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Commit-Queue: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#52099}
This commit is contained in:
parent
3ba29d5590
commit
ba5409a6fd
@ -12,9 +12,13 @@
|
||||
#include "src/codegen.h"
|
||||
#include "src/compiler.h"
|
||||
#include "src/compiler/linkage.h"
|
||||
#include "src/compiler/wasm-compiler.h"
|
||||
#include "src/machine-type.h"
|
||||
#include "src/macro-assembler.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/wasm/wasm-engine.h"
|
||||
#include "src/wasm/wasm-objects-inl.h"
|
||||
#include "src/wasm/wasm-opcodes.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
#include "test/cctest/compiler/codegen-tester.h"
|
||||
#include "test/cctest/compiler/value-helper.h"
|
||||
@ -25,89 +29,18 @@ namespace compiler {
|
||||
|
||||
namespace {
|
||||
|
||||
int size(MachineType type) {
|
||||
return 1 << ElementSizeLog2Of(type.representation());
|
||||
}
|
||||
CallDescriptor* CreateCallDescriptor(Zone* zone, int return_count,
|
||||
int param_count, MachineType type) {
|
||||
wasm::FunctionSig::Builder builder(zone, return_count, param_count);
|
||||
|
||||
int num_registers(MachineType type) {
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
switch (type.representation()) {
|
||||
case MachineRepresentation::kWord32:
|
||||
case MachineRepresentation::kWord64:
|
||||
return config->num_allocatable_general_registers();
|
||||
case MachineRepresentation::kFloat32:
|
||||
return config->num_allocatable_float_registers();
|
||||
case MachineRepresentation::kFloat64:
|
||||
return config->num_allocatable_double_registers();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
const int* codes(MachineType type) {
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
switch (type.representation()) {
|
||||
case MachineRepresentation::kWord32:
|
||||
case MachineRepresentation::kWord64:
|
||||
return config->allocatable_general_codes();
|
||||
case MachineRepresentation::kFloat32:
|
||||
return config->allocatable_float_codes();
|
||||
case MachineRepresentation::kFloat64:
|
||||
return config->allocatable_double_codes();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
CallDescriptor* CreateMonoCallDescriptor(Zone* zone, int return_count,
|
||||
int param_count, MachineType type) {
|
||||
LocationSignature::Builder locations(zone, return_count, param_count);
|
||||
|
||||
int span = std::max(1, size(type) / kPointerSize);
|
||||
int stack_params = 0;
|
||||
for (int i = 0; i < param_count; i++) {
|
||||
LinkageLocation location = LinkageLocation::ForAnyRegister();
|
||||
if (i < num_registers(type)) {
|
||||
location = LinkageLocation::ForRegister(codes(type)[i], type);
|
||||
} else {
|
||||
int slot = span * (i - param_count);
|
||||
location = LinkageLocation::ForCallerFrameSlot(slot, type);
|
||||
stack_params += span;
|
||||
}
|
||||
locations.AddParam(location);
|
||||
builder.AddParam(type.representation());
|
||||
}
|
||||
|
||||
int stack_returns = 0;
|
||||
for (int i = 0; i < return_count; i++) {
|
||||
LinkageLocation location = LinkageLocation::ForAnyRegister();
|
||||
if (i < num_registers(type)) {
|
||||
location = LinkageLocation::ForRegister(codes(type)[i], type);
|
||||
} else {
|
||||
int slot = span * (num_registers(type) - i) - stack_params - 1;
|
||||
location = LinkageLocation::ForCallerFrameSlot(slot, type);
|
||||
stack_returns += span;
|
||||
}
|
||||
locations.AddReturn(location);
|
||||
builder.AddReturn(type.representation());
|
||||
}
|
||||
|
||||
const RegList kCalleeSaveRegisters = 0;
|
||||
const RegList kCalleeSaveFPRegisters = 0;
|
||||
|
||||
MachineType target_type = MachineType::AnyTagged();
|
||||
LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
|
||||
return new (zone) CallDescriptor( // --
|
||||
CallDescriptor::kCallCodeObject, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
locations.Build(), // location_sig
|
||||
stack_params, // on-stack parameter count
|
||||
compiler::Operator::kNoProperties, // properties
|
||||
kCalleeSaveRegisters, // callee-saved registers
|
||||
kCalleeSaveFPRegisters, // callee-saved fp regs
|
||||
CallDescriptor::kNoFlags, // flags
|
||||
"c-call", // debug name
|
||||
0, // allocatable registers
|
||||
stack_returns); // on-stack return count
|
||||
return compiler::GetWasmCallDescriptor(zone, builder.Build());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -187,6 +120,26 @@ Node* ToInt32(RawMachineAssembler& m, MachineType type, Node* a) {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<wasm::NativeModule> AllocateNativeModule(Isolate* isolate,
|
||||
size_t code_size) {
|
||||
// We have to add the code object to a NativeModule, because the
|
||||
// WasmCallDescriptor assumes that code is on the native heap and not
|
||||
// within a code object.
|
||||
std::unique_ptr<wasm::NativeModule> module =
|
||||
isolate->wasm_engine()->code_manager()->NewNativeModule(code_size, 1, 0,
|
||||
false);
|
||||
|
||||
// TODO(mstarzinger): Remove the WasmCompiledModule here as soon as source
|
||||
// positions are stored in the WasmCode directly.
|
||||
Handle<WasmCompiledModule> compiled_module = Handle<WasmCompiledModule>::cast(
|
||||
isolate->factory()->NewStruct(WASM_COMPILED_MODULE_TYPE, TENURED));
|
||||
Handle<FixedArray> source_positions =
|
||||
isolate->factory()->NewFixedArray(1, TENURED);
|
||||
compiled_module->set_source_positions(*source_positions);
|
||||
module->SetCompiledModule(compiled_module);
|
||||
return module;
|
||||
}
|
||||
|
||||
void TestReturnMultipleValues(MachineType type) {
|
||||
const int kMaxCount = 20;
|
||||
for (int count = 0; count < kMaxCount; ++count) {
|
||||
@ -194,15 +147,16 @@ void TestReturnMultipleValues(MachineType type) {
|
||||
MachineReprToString(type.representation()), count);
|
||||
v8::internal::AccountingAllocator allocator;
|
||||
Zone zone(&allocator, ZONE_NAME);
|
||||
CallDescriptor* desc = CreateMonoCallDescriptor(&zone, count, 2, type);
|
||||
CallDescriptor* desc = CreateCallDescriptor(&zone, count, 2, type);
|
||||
HandleAndZoneScope handles;
|
||||
RawMachineAssembler m(handles.main_isolate(),
|
||||
new (handles.main_zone()) Graph(handles.main_zone()),
|
||||
desc, MachineType::PointerRepresentation(),
|
||||
InstructionSelector::SupportedMachineOperatorFlags());
|
||||
|
||||
Node* p0 = m.Parameter(0);
|
||||
Node* p1 = m.Parameter(1);
|
||||
// m.Parameter(0) is the WasmContext.
|
||||
Node* p0 = m.Parameter(1);
|
||||
Node* p1 = m.Parameter(2);
|
||||
typedef Node* Node_ptr;
|
||||
std::unique_ptr<Node_ptr[]> returns(new Node_ptr[count]);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
@ -232,11 +186,21 @@ void TestReturnMultipleValues(MachineType type) {
|
||||
if (i % 4 == 0) sign = -sign;
|
||||
}
|
||||
|
||||
std::unique_ptr<wasm::NativeModule> module =
|
||||
AllocateNativeModule(handles.main_isolate(), code->instruction_size());
|
||||
byte* code_start = module->AddCodeCopy(code, wasm::WasmCode::kFunction, 0)
|
||||
->instructions()
|
||||
.start();
|
||||
|
||||
RawMachineAssemblerTester<int32_t> mt;
|
||||
Node* na = Constant(mt, type, a);
|
||||
Node* nb = Constant(mt, type, b);
|
||||
Node* ret_multi =
|
||||
mt.AddNode(mt.common()->Call(desc), mt.HeapConstant(code), na, nb);
|
||||
Node* call_inputs[] = {mt.PointerConstant(code_start),
|
||||
// WasmContext dummy
|
||||
mt.PointerConstant(nullptr),
|
||||
// Inputs
|
||||
Constant(mt, type, a), Constant(mt, type, b)};
|
||||
|
||||
Node* ret_multi = mt.AddNode(mt.common()->Call(desc),
|
||||
arraysize(call_inputs), call_inputs);
|
||||
Node* ret = Constant(mt, type, 0);
|
||||
bool sign = false;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
@ -275,10 +239,11 @@ void ReturnLastValue(MachineType type) {
|
||||
for (auto slot_count : slot_counts) {
|
||||
v8::internal::AccountingAllocator allocator;
|
||||
Zone zone(&allocator, ZONE_NAME);
|
||||
const int return_count = num_registers(type) + slot_count;
|
||||
// The wasm-linkage provides 2 return registers at the moment, on all
|
||||
// platforms.
|
||||
const int return_count = 2 + slot_count;
|
||||
|
||||
CallDescriptor* desc =
|
||||
CreateMonoCallDescriptor(&zone, return_count, 0, type);
|
||||
CallDescriptor* desc = CreateCallDescriptor(&zone, return_count, 0, type);
|
||||
|
||||
HandleAndZoneScope handles;
|
||||
RawMachineAssembler m(handles.main_isolate(),
|
||||
@ -299,12 +264,20 @@ void ReturnLastValue(MachineType type) {
|
||||
Handle<Code> code = Pipeline::GenerateCodeForTesting(
|
||||
&info, handles.main_isolate(), desc, m.graph(), m.Export());
|
||||
|
||||
std::unique_ptr<wasm::NativeModule> module =
|
||||
AllocateNativeModule(handles.main_isolate(), code->instruction_size());
|
||||
byte* code_start = module->AddCodeCopy(code, wasm::WasmCode::kFunction, 0)
|
||||
->instructions()
|
||||
.start();
|
||||
|
||||
// Generate caller.
|
||||
int expect = return_count - 1;
|
||||
RawMachineAssemblerTester<int32_t> mt;
|
||||
Node* code_node = mt.HeapConstant(code);
|
||||
Node* inputs[] = {mt.PointerConstant(code_start),
|
||||
// WasmContext dummy
|
||||
mt.PointerConstant(nullptr)};
|
||||
|
||||
Node* call = mt.AddNode(mt.common()->Call(desc), 1, &code_node);
|
||||
Node* call = mt.AddNode(mt.common()->Call(desc), 2, inputs);
|
||||
|
||||
mt.Return(ToInt32(
|
||||
mt, type, mt.AddNode(mt.common()->Projection(return_count - 1), call)));
|
||||
@ -326,10 +299,11 @@ void ReturnSumOfReturns(MachineType type) {
|
||||
v8::internal::AccountingAllocator allocator;
|
||||
Zone zone(&allocator, ZONE_NAME);
|
||||
// Let {unused_stack_slots + 1} returns be on the stack.
|
||||
const int return_count = num_registers(type) + unused_stack_slots + 1;
|
||||
// The wasm-linkage provides 2 return registers at the moment, on all
|
||||
// platforms.
|
||||
const int return_count = 2 + unused_stack_slots + 1;
|
||||
|
||||
CallDescriptor* desc =
|
||||
CreateMonoCallDescriptor(&zone, return_count, 0, type);
|
||||
CallDescriptor* desc = CreateCallDescriptor(&zone, return_count, 0, type);
|
||||
|
||||
HandleAndZoneScope handles;
|
||||
RawMachineAssembler m(handles.main_isolate(),
|
||||
@ -350,11 +324,19 @@ void ReturnSumOfReturns(MachineType type) {
|
||||
Handle<Code> code = Pipeline::GenerateCodeForTesting(
|
||||
&info, handles.main_isolate(), desc, m.graph(), m.Export());
|
||||
|
||||
std::unique_ptr<wasm::NativeModule> module =
|
||||
AllocateNativeModule(handles.main_isolate(), code->instruction_size());
|
||||
byte* code_start = module->AddCodeCopy(code, wasm::WasmCode::kFunction, 0)
|
||||
->instructions()
|
||||
.start();
|
||||
|
||||
// Generate caller.
|
||||
RawMachineAssemblerTester<int32_t> mt;
|
||||
Node* code_node = mt.HeapConstant(code);
|
||||
Node* call_inputs[] = {mt.PointerConstant(code_start),
|
||||
// WasmContext dummy
|
||||
mt.PointerConstant(nullptr)};
|
||||
|
||||
Node* call = mt.AddNode(mt.common()->Call(desc), 1, &code_node);
|
||||
Node* call = mt.AddNode(mt.common()->Call(desc), 2, call_inputs);
|
||||
|
||||
uint32_t expect = 0;
|
||||
Node* result = mt.Int32Constant(0);
|
||||
|
@ -13,11 +13,16 @@
|
||||
#include "src/compiler/operator.h"
|
||||
#include "src/compiler/pipeline.h"
|
||||
#include "src/compiler/raw-machine-assembler.h"
|
||||
#include "src/compiler/wasm-compiler.h"
|
||||
#include "src/machine-type.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/objects.h"
|
||||
#include "src/simulator.h"
|
||||
#include "src/wasm/wasm-engine.h"
|
||||
#include "src/wasm/wasm-limits.h"
|
||||
#include "src/wasm/wasm-objects-inl.h"
|
||||
#include "src/wasm/wasm-objects.h"
|
||||
#include "src/wasm/wasm-opcodes.h"
|
||||
#include "src/zone/accounting-allocator.h"
|
||||
#include "src/zone/zone.h"
|
||||
#include "test/fuzzer/fuzzer-support.h"
|
||||
@ -91,49 +96,8 @@ int num_registers(MachineType type) {
|
||||
}
|
||||
}
|
||||
|
||||
int size(MachineType type) {
|
||||
return 1 << ElementSizeLog2Of(type.representation());
|
||||
}
|
||||
|
||||
int index(MachineType type) { return static_cast<int>(type.representation()); }
|
||||
|
||||
const int* codes(MachineType type) {
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
switch (type.representation()) {
|
||||
case MachineRepresentation::kWord32:
|
||||
case MachineRepresentation::kWord64:
|
||||
return config->allocatable_general_codes();
|
||||
case MachineRepresentation::kFloat32:
|
||||
return config->allocatable_float_codes();
|
||||
case MachineRepresentation::kFloat64:
|
||||
return config->allocatable_double_codes();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
LinkageLocation AllocateLocation(MachineType type, int* int_count,
|
||||
int* float_count, int* stack_slots) {
|
||||
int* count = IsFloatingPoint(type.representation()) ? float_count : int_count;
|
||||
int reg_code = *count;
|
||||
#if V8_TARGET_ARCH_ARM
|
||||
// Allocate floats using a double register, but modify the code to
|
||||
// reflect how ARM FP registers alias.
|
||||
if (type == MachineType::Float32()) {
|
||||
reg_code *= 2;
|
||||
}
|
||||
#endif
|
||||
LinkageLocation location = LinkageLocation::ForAnyRegister(); // Dummy.
|
||||
if (reg_code < num_registers(type)) {
|
||||
location = LinkageLocation::ForRegister(codes(type)[reg_code], type);
|
||||
} else {
|
||||
location = LinkageLocation::ForCallerFrameSlot(-*stack_slots - 1, type);
|
||||
*stack_slots += std::max(1, size(type) / kPointerSize);
|
||||
}
|
||||
++*count;
|
||||
return location;
|
||||
}
|
||||
|
||||
Node* Constant(RawMachineAssembler& m, MachineType type, int value) {
|
||||
switch (type.representation()) {
|
||||
case MachineRepresentation::kWord32:
|
||||
@ -167,51 +131,40 @@ Node* ToInt32(RawMachineAssembler& m, MachineType type, Node* a) {
|
||||
CallDescriptor* CreateRandomCallDescriptor(Zone* zone, size_t return_count,
|
||||
size_t param_count,
|
||||
InputProvider* input) {
|
||||
LocationSignature::Builder locations(zone, return_count, param_count);
|
||||
|
||||
int stack_slots = 0;
|
||||
int int_params = 0;
|
||||
int float_params = 0;
|
||||
wasm::FunctionSig::Builder builder(zone, return_count, param_count);
|
||||
for (size_t i = 0; i < param_count; i++) {
|
||||
MachineType type = RandomType(input);
|
||||
LinkageLocation location =
|
||||
AllocateLocation(type, &int_params, &float_params, &stack_slots);
|
||||
locations.AddParam(location);
|
||||
builder.AddParam(type.representation());
|
||||
}
|
||||
// Read the end byte of the parameters.
|
||||
input->NextInt8(1);
|
||||
|
||||
int stack_params = stack_slots;
|
||||
#if V8_TARGET_ARCH_ARM64
|
||||
// Align the stack slots.
|
||||
stack_slots = stack_slots + (stack_slots % 2);
|
||||
#endif
|
||||
int aligned_stack_params = stack_slots;
|
||||
int int_returns = 0;
|
||||
int float_returns = 0;
|
||||
for (size_t i = 0; i < return_count; i++) {
|
||||
MachineType type = RandomType(input);
|
||||
LinkageLocation location =
|
||||
AllocateLocation(type, &int_returns, &float_returns, &stack_slots);
|
||||
locations.AddReturn(location);
|
||||
builder.AddReturn(type.representation());
|
||||
}
|
||||
int stack_returns = stack_slots - aligned_stack_params;
|
||||
|
||||
MachineType target_type = MachineType::AnyTagged();
|
||||
LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
|
||||
return new (zone) CallDescriptor( // --
|
||||
CallDescriptor::kCallCodeObject, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
locations.Build(), // location_sig
|
||||
stack_params, // on-stack parameter count
|
||||
compiler::Operator::kNoProperties, // properties
|
||||
0, // callee-saved registers
|
||||
0, // callee-saved fp regs
|
||||
CallDescriptor::kNoFlags, // flags
|
||||
"c-call", // debug name
|
||||
0, // allocatable registers
|
||||
stack_returns); // on-stack return count
|
||||
return compiler::GetWasmCallDescriptor(zone, builder.Build());
|
||||
}
|
||||
|
||||
std::unique_ptr<wasm::NativeModule> AllocateNativeModule(i::Isolate* isolate,
|
||||
size_t code_size) {
|
||||
// We have to add the code object to a NativeModule, because the
|
||||
// WasmCallDescriptor assumes that code is on the native heap and not
|
||||
// within a code object.
|
||||
std::unique_ptr<wasm::NativeModule> module =
|
||||
isolate->wasm_engine()->code_manager()->NewNativeModule(code_size, 1, 0,
|
||||
false);
|
||||
|
||||
// TODO(mstarzinger): Remove the WasmCompiledModule here as soon as source
|
||||
// positions are stored in the WasmCode directly.
|
||||
Handle<WasmCompiledModule> compiled_module = Handle<WasmCompiledModule>::cast(
|
||||
isolate->factory()->NewStruct(WASM_COMPILED_MODULE_TYPE, TENURED));
|
||||
Handle<FixedArray> source_positions =
|
||||
isolate->factory()->NewFixedArray(1, TENURED);
|
||||
compiled_module->set_source_positions(*source_positions);
|
||||
module->SetCompiledModule(compiled_module);
|
||||
return module;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
@ -239,9 +192,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (FLAG_wasm_fuzzer_gen_test) {
|
||||
// Print some debugging output which describes the produced signature.
|
||||
printf("[");
|
||||
for (size_t j = 0; j < desc->ParameterCount(); ++j) {
|
||||
printf(" %s",
|
||||
MachineReprToString(desc->GetParameterType(j).representation()));
|
||||
for (size_t j = 0; j < param_count; ++j) {
|
||||
// Parameter 0 is the WasmContext.
|
||||
printf(" %s", MachineReprToString(
|
||||
desc->GetParameterType(j + 1).representation()));
|
||||
}
|
||||
printf(" ] -> [");
|
||||
for (size_t j = 0; j < desc->ReturnCount(); ++j) {
|
||||
@ -258,14 +212,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// Trivial hash table for the number of occurrences of parameter types. The
|
||||
// MachineRepresentation of the parameter types is used as hash code.
|
||||
int counts[kNumMachineRepresentations] = {0};
|
||||
for (size_t i = 0; i < desc->ParameterCount(); ++i) {
|
||||
++counts[index(desc->GetParameterType(i))];
|
||||
for (size_t i = 0; i < param_count; ++i) {
|
||||
// Parameter 0 is the WasmContext.
|
||||
++counts[index(desc->GetParameterType(i + 1))];
|
||||
}
|
||||
|
||||
// Generate random inputs.
|
||||
std::unique_ptr<int[]> inputs(new int[desc->ParameterCount()]);
|
||||
std::unique_ptr<int[]> inputs(new int[param_count]);
|
||||
std::unique_ptr<int[]> outputs(new int[desc->ReturnCount()]);
|
||||
for (size_t i = 0; i < desc->ParameterCount(); ++i) {
|
||||
for (size_t i = 0; i < param_count; ++i) {
|
||||
inputs[i] = input.NextInt32(10000);
|
||||
}
|
||||
|
||||
@ -275,11 +230,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
InstructionSelector::SupportedMachineOperatorFlags());
|
||||
|
||||
// Generate callee, returning random picks of its parameters.
|
||||
std::unique_ptr<Node* []> params(new Node*[desc->ParameterCount() + 1]);
|
||||
std::unique_ptr<Node* []> returns(new Node*[desc->ReturnCount()]);
|
||||
for (size_t i = 0; i < desc->ParameterCount(); ++i) {
|
||||
params[i] = callee.Parameter(i);
|
||||
std::unique_ptr<Node* []> params(new Node*[desc->ParameterCount() + 2]);
|
||||
// The first input of a return is the number of stack slots that should be
|
||||
// popped before returning.
|
||||
std::unique_ptr<Node* []> returns(new Node*[desc->ReturnCount() + 1]);
|
||||
for (size_t i = 0; i < param_count; ++i) {
|
||||
// Parameter(0) is the WasmContext.
|
||||
params[i] = callee.Parameter(i + 1);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < desc->ReturnCount(); ++i) {
|
||||
MachineType type = desc->GetReturnType(i);
|
||||
// Find a random same-type parameter to return. Use a constant if none.
|
||||
@ -289,7 +248,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
} else {
|
||||
int n = input.NextInt32(counts[index(type)]);
|
||||
int k = 0;
|
||||
while (desc->GetParameterType(k) != desc->GetReturnType(i) || --n > 0) {
|
||||
while (desc->GetParameterType(k + 1) != desc->GetReturnType(i) ||
|
||||
--n > 0) {
|
||||
++k;
|
||||
}
|
||||
returns[i] = params[k];
|
||||
@ -302,6 +262,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
Handle<Code> code = Pipeline::GenerateCodeForTesting(
|
||||
&info, i_isolate, desc, callee.graph(), callee.Export());
|
||||
|
||||
std::unique_ptr<wasm::NativeModule> module =
|
||||
AllocateNativeModule(i_isolate, code->instruction_size());
|
||||
byte* code_start = module->AddCodeCopy(code, wasm::WasmCode::kFunction, 0)
|
||||
->instructions()
|
||||
.start();
|
||||
// Generate wrapper.
|
||||
int expect = 0;
|
||||
|
||||
@ -315,13 +280,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
MachineType::PointerRepresentation(),
|
||||
InstructionSelector::SupportedMachineOperatorFlags());
|
||||
|
||||
params[0] = caller.HeapConstant(code);
|
||||
for (size_t i = 0; i < desc->ParameterCount(); ++i) {
|
||||
params[i + 1] = Constant(caller, desc->GetParameterType(i), inputs[i]);
|
||||
params[0] = caller.PointerConstant(code_start);
|
||||
// WasmContext dummy.
|
||||
params[1] = caller.PointerConstant(nullptr);
|
||||
for (size_t i = 0; i < param_count; ++i) {
|
||||
params[i + 2] = Constant(caller, desc->GetParameterType(i + 1), inputs[i]);
|
||||
}
|
||||
Node* call = caller.AddNode(caller.common()->Call(desc),
|
||||
static_cast<int>(desc->ParameterCount() + 1),
|
||||
params.get());
|
||||
static_cast<int>(param_count + 2), params.get());
|
||||
Node* ret = Constant(caller, MachineType::Int32(), 0);
|
||||
for (size_t i = 0; i < desc->ReturnCount(); ++i) {
|
||||
// Skip roughly one third of the outputs.
|
||||
|
Loading…
Reference in New Issue
Block a user