[wasm] WasmRunner can run tests with I64 parameters and return value.

I extended the Int64Lowering to lower calls, loads, stores, returns, and
parameters and apply the lowering on both the test function TF graph and
the WasmRunner TF graph.

The lowering of calls also requires an adjustment of the call descriptor.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/1704033002

Cr-Commit-Position: refs/heads/master@{#34121}
This commit is contained in:
ahaas 2016-02-18 07:18:41 -08:00 committed by Commit bot
parent 5363486d8e
commit 545943db15
7 changed files with 438 additions and 70 deletions

View File

@ -5,8 +5,12 @@
#include "src/compiler/int64-lowering.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node.h"
#include "src/wasm/wasm-module.h"
#include "src/zone.h"
namespace v8 {
@ -14,17 +18,23 @@ namespace internal {
namespace compiler {
Int64Lowering::Int64Lowering(Graph* graph, MachineOperatorBuilder* machine,
CommonOperatorBuilder* common, Zone* zone)
: graph_(graph),
CommonOperatorBuilder* common, Zone* zone,
Signature<MachineRepresentation>* signature)
: zone_(zone),
graph_(graph),
machine_(machine),
common_(common),
state_(graph, 4),
stack_(zone),
replacements_(zone->NewArray<Replacement>(graph->NodeCount())) {
replacements_(zone->NewArray<Replacement>(graph->NodeCount())),
signature_(signature) {
memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount());
}
void Int64Lowering::ReduceGraph() {
void Int64Lowering::LowerGraph() {
if (4 != kPointerSize) {
return;
}
stack_.push(graph()->end());
state_.Set(graph()->end(), State::kOnStack);
@ -34,7 +44,7 @@ void Int64Lowering::ReduceGraph() {
stack_.pop();
state_.Set(top, State::kVisited);
// All inputs of top have already been reduced, now reduce top.
ReduceNode(top);
LowerNode(top);
} else {
// Push all children onto the stack.
for (Node* input : top->inputs()) {
@ -48,7 +58,35 @@ void Int64Lowering::ReduceGraph() {
}
}
void Int64Lowering::ReduceNode(Node* node) {
static int GetParameterIndexAfterLowering(
Signature<MachineRepresentation>* signature, int old_index) {
int result = old_index;
for (int i = 0; i < old_index; i++) {
if (signature->GetParam(i) == MachineRepresentation::kWord64) {
result++;
}
}
return result;
}
static int GetParameterCountAfterLowering(
Signature<MachineRepresentation>* signature) {
return GetParameterIndexAfterLowering(
signature, static_cast<int>(signature->parameter_count()));
}
static int GetReturnCountAfterLowering(
Signature<MachineRepresentation>* signature) {
int result = static_cast<int>(signature->return_count());
for (int i = 0; i < static_cast<int>(signature->return_count()); i++) {
if (signature->GetReturn(i) == MachineRepresentation::kWord64) {
result++;
}
}
return result;
}
void Int64Lowering::LowerNode(Node* node) {
switch (node->opcode()) {
case IrOpcode::kInt64Constant: {
int64_t value = OpParameter<int64_t>(node);
@ -56,48 +94,207 @@ void Int64Lowering::ReduceNode(Node* node) {
common()->Int32Constant(static_cast<int32_t>(value & 0xFFFFFFFF)));
Node* high_node = graph()->NewNode(
common()->Int32Constant(static_cast<int32_t>(value >> 32)));
replacements_[node->id()].low = low_node;
replacements_[node->id()].high = high_node;
ReplaceNode(node, low_node, high_node);
break;
}
case IrOpcode::kLoad: {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
if (load_rep.representation() == MachineRepresentation::kWord64) {
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* index_high =
graph()->NewNode(machine()->Int32Add(), index,
graph()->NewNode(common()->Int32Constant(4)));
const Operator* load_op = machine()->Load(MachineType::Int32());
Node* high_node;
if (node->InputCount() > 2) {
Node* effect_high = node->InputAt(2);
Node* control_high = node->InputAt(3);
high_node = graph()->NewNode(load_op, base, index_high, effect_high,
control_high);
// change the effect change from old_node --> old_effect to
// old_node --> high_node --> old_effect.
node->ReplaceInput(2, high_node);
} else {
high_node = graph()->NewNode(load_op, base, index_high);
}
NodeProperties::ChangeOp(node, load_op);
ReplaceNode(node, node, high_node);
}
break;
}
case IrOpcode::kStore: {
StoreRepresentation store_rep = StoreRepresentationOf(node->op());
if (store_rep.representation() == MachineRepresentation::kWord64) {
// We change the original store node to store the low word, and create
// a new store node to store the high word. The effect and control edges
// are copied from the original store to the new store node, the effect
// edge of the original store is redirected to the new store.
WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind();
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* index_high =
graph()->NewNode(machine()->Int32Add(), index,
graph()->NewNode(common()->Int32Constant(4)));
Node* value = node->InputAt(2);
DCHECK(HasReplacementLow(value));
DCHECK(HasReplacementHigh(value));
const Operator* store_op = machine()->Store(StoreRepresentation(
MachineRepresentation::kWord32, write_barrier_kind));
Node* high_node;
if (node->InputCount() > 3) {
Node* effect_high = node->InputAt(3);
Node* control_high = node->InputAt(4);
high_node = graph()->NewNode(store_op, base, index_high,
GetReplacementHigh(value), effect_high,
control_high);
node->ReplaceInput(3, high_node);
} else {
high_node = graph()->NewNode(store_op, base, index_high,
GetReplacementHigh(value));
}
node->ReplaceInput(2, GetReplacementLow(value));
NodeProperties::ChangeOp(node, store_op);
ReplaceNode(node, node, high_node);
}
break;
}
case IrOpcode::kWord64And: {
DCHECK(node->InputCount() == 2);
Node* left = node->InputAt(0);
DCHECK(replacements_[left->id()].low);
Node* left_low = replacements_[left->id()].low;
Node* left_high = replacements_[left->id()].high;
Node* right = node->InputAt(1);
DCHECK(replacements_[right->id()].low);
Node* right_low = replacements_[right->id()].low;
Node* right_high = replacements_[right->id()].high;
replacements_[node->id()].low =
graph()->NewNode(machine()->Word32And(), left_low, right_low);
replacements_[node->id()].high =
graph()->NewNode(machine()->Word32And(), left_high, right_high);
Node* low_node =
graph()->NewNode(machine()->Word32And(), GetReplacementLow(left),
GetReplacementLow(right));
Node* high_node =
graph()->NewNode(machine()->Word32And(), GetReplacementHigh(left),
GetReplacementHigh(right));
ReplaceNode(node, low_node, high_node);
break;
}
case IrOpcode::kTruncateInt64ToInt32: {
DCHECK(node->InputCount() == 1);
Node* input = node->InputAt(0);
DCHECK(replacements_[input->id()].low);
replacements_[node->id()].low = replacements_[input->id()].low;
ReplaceNode(node, GetReplacementLow(input), nullptr);
node->NullAllInputs();
break;
}
default: {
// Also the inputs of nodes can change which do not expect int64 inputs.
for (int i = 0; i < node->InputCount(); i++) {
Node* input = node->InputAt(i);
// The input has changed altough it was not an int64 input. This can
// happen e.g. if the input node is IrOpcode::kTruncateInt64ToInt32. We
// use the low word replacement as the new input.
if (replacements_[input->id()].low) {
node->ReplaceInput(i, replacements_[input->id()].low);
}
case IrOpcode::kStart: {
int parameter_count = GetParameterCountAfterLowering(signature());
// Only exchange the node if the parameter count actually changed.
if (parameter_count != signature()->parameter_count()) {
int delta =
parameter_count - static_cast<int>(signature()->parameter_count());
int new_output_count = node->op()->ValueOutputCount() + delta;
NodeProperties::ChangeOp(node, common()->Start(new_output_count));
}
break;
}
case IrOpcode::kParameter: {
DCHECK(node->InputCount() == 1);
// Only exchange the node if the parameter count actually changed. We do
// not even have to do the default lowering because the the start node,
// the only input of a parameter node, only changes if the parameter count
// changes.
if (GetParameterCountAfterLowering(signature()) !=
signature()->parameter_count()) {
int old_index = ParameterIndexOf(node->op());
int new_index = GetParameterIndexAfterLowering(signature(), old_index);
Node* low_node =
graph()->NewNode(common()->Parameter(new_index), graph()->start());
Node* high_node = nullptr;
if (signature()->GetParam(old_index) ==
MachineRepresentation::kWord64) {
high_node = graph()->NewNode(common()->Parameter(new_index + 1),
graph()->start());
}
ReplaceNode(node, low_node, high_node);
}
break;
}
case IrOpcode::kReturn: {
DefaultLowering(node);
int new_return_count = GetReturnCountAfterLowering(signature());
if (signature()->return_count() != new_return_count) {
NodeProperties::ChangeOp(node, common()->Return(new_return_count));
}
break;
}
case IrOpcode::kCall: {
CallDescriptor* descriptor = OpParameter<CallDescriptor*>(node);
if (DefaultLowering(node) ||
(descriptor->ReturnCount() == 1 &&
descriptor->GetReturnType(0) == MachineType::Int64())) {
// We have to adjust the call descriptor.
const Operator* op = common()->Call(
wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), descriptor));
NodeProperties::ChangeOp(node, op);
}
if (descriptor->ReturnCount() == 1 &&
descriptor->GetReturnType(0) == MachineType::Int64()) {
// We access the additional return values through projections.
Node* low_node = graph()->NewNode(common()->Projection(0), node);
Node* high_node = graph()->NewNode(common()->Projection(1), node);
ReplaceNode(node, low_node, high_node);
}
break;
}
default: { DefaultLowering(node); }
}
}
bool Int64Lowering::DefaultLowering(Node* node) {
bool something_changed = false;
for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
Node* input = node->InputAt(i);
if (HasReplacementLow(input)) {
something_changed = true;
node->ReplaceInput(i, GetReplacementLow(input));
}
if (HasReplacementHigh(input)) {
something_changed = true;
node->InsertInput(zone(), i + 1, GetReplacementHigh(input));
}
}
return something_changed;
}
void Int64Lowering::ReplaceNode(Node* old, Node* new_low, Node* new_high) {
// if new_low == nullptr, then also new_high == nullptr.
DCHECK(new_low != nullptr || new_high == nullptr);
replacements_[old->id()].low = new_low;
replacements_[old->id()].high = new_high;
}
bool Int64Lowering::HasReplacementLow(Node* node) {
return replacements_[node->id()].low != nullptr;
}
Node* Int64Lowering::GetReplacementLow(Node* node) {
Node* result = replacements_[node->id()].low;
DCHECK(result);
return result;
}
bool Int64Lowering::HasReplacementHigh(Node* node) {
return replacements_[node->id()].high != nullptr;
}
Node* Int64Lowering::GetReplacementHigh(Node* node) {
Node* result = replacements_[node->id()].high;
DCHECK(result);
return result;
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -18,12 +18,10 @@ namespace compiler {
class Int64Lowering {
public:
Int64Lowering(Graph* graph, MachineOperatorBuilder* machine,
CommonOperatorBuilder* common, Zone* zone);
CommonOperatorBuilder* common, Zone* zone,
Signature<MachineRepresentation>* signature);
void ReduceGraph();
Graph* graph() const { return graph_; }
MachineOperatorBuilder* machine() const { return machine_; }
CommonOperatorBuilder* common() const { return common_; }
void LowerGraph();
private:
enum class State : uint8_t { kUnvisited, kOnStack, kInputsPushed, kVisited };
@ -33,15 +31,29 @@ class Int64Lowering {
Node* high;
};
void ReduceTop();
void ReduceNode(Node* node);
Zone* zone() const { return zone_; }
Graph* graph() const { return graph_; }
MachineOperatorBuilder* machine() const { return machine_; }
CommonOperatorBuilder* common() const { return common_; }
Signature<MachineRepresentation>* signature() const { return signature_; }
void LowerNode(Node* node);
bool DefaultLowering(Node* node);
void ReplaceNode(Node* old, Node* new_low, Node* new_high);
bool HasReplacementLow(Node* node);
Node* GetReplacementLow(Node* node);
bool HasReplacementHigh(Node* node);
Node* GetReplacementHigh(Node* node);
Zone* zone_;
Graph* const graph_;
MachineOperatorBuilder* machine_;
CommonOperatorBuilder* common_;
NodeMarker<State> state_;
ZoneStack<Node*> stack_;
Replacement* replacements_;
Signature<MachineRepresentation>* signature_;
};
} // namespace compiler

View File

@ -1484,8 +1484,9 @@ Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) {
args[params + 1] = *effect_;
args[params + 2] = *control_;
const Operator* op = jsgraph()->common()->Call(
module_->GetWasmCallDescriptor(jsgraph()->zone(), sig));
CallDescriptor* descriptor =
module_->GetWasmCallDescriptor(jsgraph()->zone(), sig);
const Operator* op = jsgraph()->common()->Call(descriptor);
Node* call = graph()->NewNode(op, static_cast<int>(count), args);
*effect_ = call;
@ -1909,11 +1910,12 @@ Node* WasmGraphBuilder::String(const char* string) {
Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); }
void WasmGraphBuilder::Int64LoweringForTesting() {
#if !WASM_64
Int64Lowering r(jsgraph()->graph(), jsgraph()->machine(), jsgraph()->common(),
jsgraph()->zone());
r.ReduceGraph();
#endif
if (kPointerSize == 4) {
Int64Lowering r(jsgraph()->graph(), jsgraph()->machine(),
jsgraph()->common(), jsgraph()->zone(),
function_signature_);
r.LowerGraph();
}
}
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
@ -2127,8 +2129,11 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
}
// Run the compiler pipeline to generate machine code.
CallDescriptor* descriptor = const_cast<CallDescriptor*>(
module_env->GetWasmCallDescriptor(&zone, function.sig));
CallDescriptor* descriptor =
module_env->GetWasmCallDescriptor(&zone, function.sig);
if (kPointerSize == 4) {
descriptor = module_env->GetI32WasmCallDescriptor(&zone, descriptor);
}
Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
// add flags here if a meaningful name is helpful for debugging.
bool debugging =

View File

@ -191,15 +191,7 @@ struct Allocator {
};
} // namespace
// General code uses the above configuration data.
CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone,
FunctionSig* fsig) {
MachineSignature::Builder msig(zone, fsig->return_count(),
fsig->parameter_count());
LocationSignature::Builder locations(zone, fsig->return_count(),
fsig->parameter_count());
static Allocator GetReturnRegisters() {
#ifdef GP_RETURN_REGISTERS
static const Register kGPReturnRegisters[] = {GP_RETURN_REGISTERS};
static const int kGPReturnRegistersCount =
@ -221,14 +213,10 @@ CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone,
Allocator rets(kGPReturnRegisters, kGPReturnRegistersCount,
kFPReturnRegisters, kFPReturnRegistersCount);
// Add return location(s).
const int return_count = static_cast<int>(locations.return_count_);
for (int i = 0; i < return_count; i++) {
LocalType ret = fsig->GetReturn(i);
msig.AddReturn(MachineTypeFor(ret));
locations.AddReturn(rets.Next(ret));
}
return rets;
}
static Allocator GetParameterRegisters() {
#ifdef GP_PARAM_REGISTERS
static const Register kGPParamRegisters[] = {GP_PARAM_REGISTERS};
static const int kGPParamRegistersCount =
@ -250,6 +238,29 @@ CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone,
Allocator params(kGPParamRegisters, kGPParamRegistersCount, kFPParamRegisters,
kFPParamRegistersCount);
return params;
}
// General code uses the above configuration data.
CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone,
FunctionSig* fsig) {
MachineSignature::Builder msig(zone, fsig->return_count(),
fsig->parameter_count());
LocationSignature::Builder locations(zone, fsig->return_count(),
fsig->parameter_count());
Allocator rets = GetReturnRegisters();
// Add return location(s).
const int return_count = static_cast<int>(locations.return_count_);
for (int i = 0; i < return_count; i++) {
LocalType ret = fsig->GetReturn(i);
msig.AddReturn(MachineTypeFor(ret));
locations.AddReturn(rets.Next(ret));
}
Allocator params = GetParameterRegisters();
// Add register and/or stack parameter(s).
const int parameter_count = static_cast<int>(fsig->parameter_count());
for (int i = 0; i < parameter_count; i++) {
@ -276,8 +287,82 @@ CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone,
kCalleeSaveRegisters, // callee-saved registers
kCalleeSaveFPRegisters, // callee-saved fp regs
CallDescriptor::kUseNativeStack, // flags
"c-call");
"wasm-call");
}
CallDescriptor* ModuleEnv::GetI32WasmCallDescriptor(
Zone* zone, CallDescriptor* descriptor) {
const MachineSignature* signature = descriptor->GetMachineSignature();
size_t parameter_count = signature->parameter_count();
size_t return_count = signature->return_count();
for (size_t i = 0; i < signature->parameter_count(); i++) {
if (signature->GetParam(i) == MachineType::Int64()) {
// For each int64 input we get two int32 inputs.
parameter_count++;
}
}
for (size_t i = 0; i < signature->return_count(); i++) {
if (signature->GetReturn(i) == MachineType::Int64()) {
// For each int64 return we get two int32 returns.
return_count++;
}
}
if (parameter_count == signature->parameter_count() &&
return_count == signature->return_count()) {
// If there is no int64 parameter or return value, we can just return the
// original descriptor.
return descriptor;
}
MachineSignature::Builder msig(zone, return_count, parameter_count);
LocationSignature::Builder locations(zone, return_count, parameter_count);
Allocator rets = GetReturnRegisters();
for (size_t i = 0; i < signature->return_count(); i++) {
if (signature->GetReturn(i) == MachineType::Int64()) {
// For each int64 return we get two int32 returns.
msig.AddReturn(MachineType::Int32());
msig.AddReturn(MachineType::Int32());
locations.AddReturn(rets.Next(MachineRepresentation::kWord32));
locations.AddReturn(rets.Next(MachineRepresentation::kWord32));
} else {
msig.AddReturn(signature->GetReturn(i));
locations.AddReturn(rets.Next(signature->GetReturn(i).representation()));
}
}
Allocator params = GetParameterRegisters();
for (size_t i = 0; i < signature->parameter_count(); i++) {
if (signature->GetParam(i) == MachineType::Int64()) {
// For each int64 input we get two int32 inputs.
msig.AddParam(MachineType::Int32());
msig.AddParam(MachineType::Int32());
locations.AddParam(params.Next(MachineRepresentation::kWord32));
locations.AddParam(params.Next(MachineRepresentation::kWord32));
} else {
msig.AddParam(signature->GetParam(i));
locations.AddParam(params.Next(signature->GetParam(i).representation()));
}
}
return new (zone) CallDescriptor( // --
descriptor->kind(), // kind
descriptor->GetInputType(0), // target MachineType
descriptor->GetInputLocation(0), // target location
msig.Build(), // machine_sig
locations.Build(), // location_sig
params.stack_offset, // stack_parameter_count
descriptor->properties(), // properties
descriptor->CalleeSavedRegisters(), // callee-saved registers
descriptor->CalleeSavedFPRegisters(), // callee-saved fp regs
descriptor->flags(), // flags
descriptor->debug_name());
return descriptor;
}
} // namespace wasm
} // namespace internal
} // namespace v8

View File

@ -191,6 +191,8 @@ struct ModuleEnv {
Handle<FixedArray> GetFunctionTable();
compiler::CallDescriptor* GetWasmCallDescriptor(Zone* zone, FunctionSig* sig);
static compiler::CallDescriptor* GetI32WasmCallDescriptor(
Zone* zone, compiler::CallDescriptor* descriptor);
compiler::CallDescriptor* GetCallDescriptor(Zone* zone, uint32_t index);
};

View File

@ -2473,6 +2473,50 @@ TEST(Run_WasmCallF64StackParameter) {
CHECK_EQ(256.5, result);
}
TEST(Run_WasmCallI64Parameter) {
// Build the target function.
LocalType param_types[20];
for (int i = 0; i < 20; i++) param_types[i] = kAstI64;
param_types[3] = kAstI32;
param_types[4] = kAstI32;
FunctionSig sig(1, 19, param_types);
for (int i = 0; i < 19; i++) {
TestingModule module;
WasmFunctionCompiler t(&sig);
if (i == 2 || i == 3) {
continue;
} else {
BUILD(t, WASM_GET_LOCAL(i));
}
uint32_t index = t.CompileAndAdd(&module);
// Build the calling function.
WasmRunner<int32_t> r;
r.env()->module = &module;
BUILD(r,
WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
index, WASM_I64(0xbcd12340000000b), WASM_I64(0xbcd12340000000c),
WASM_I32(0xd), WASM_I32_CONVERT_I64(WASM_I64(0xbcd12340000000e)),
WASM_I64(0xbcd12340000000f), WASM_I64(0xbcd1234000000010),
WASM_I64(0xbcd1234000000011), WASM_I64(0xbcd1234000000012),
WASM_I64(0xbcd1234000000013), WASM_I64(0xbcd1234000000014),
WASM_I64(0xbcd1234000000015), WASM_I64(0xbcd1234000000016),
WASM_I64(0xbcd1234000000017), WASM_I64(0xbcd1234000000018),
WASM_I64(0xbcd1234000000019), WASM_I64(0xbcd123400000001a),
WASM_I64(0xbcd123400000001b), WASM_I64(0xbcd123400000001c),
WASM_I64(0xbcd123400000001d))));
CHECK_EQ(i + 0xb, r.Call());
}
}
TEST(Run_WasmI64And) {
WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT64_INPUTS(i) {
FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); }
}
}
TEST(Run_WasmCallVoid) {
const byte kMemOffset = 8;

View File

@ -46,6 +46,7 @@
CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
#define CHECK_TRAP(x) CHECK_TRAP32(x)
#define WASM_RUNNER_MAX_NUM_PARAMETERS 4
#define WASM_WRAPPER_RETURN_VALUE 8754
namespace {
@ -260,10 +261,12 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
: GraphAndBuilders(main_zone()),
inner_code_node_(nullptr),
signature_(nullptr) {
Signature<MachineType>::Builder sig_builder(zone(), 1, 5);
// One additional parameter for the pointer to the return value memory.
Signature<MachineType>::Builder sig_builder(
zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
sig_builder.AddReturn(MachineType::Int32());
for (int i = 0; i < 5; i++) {
for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
sig_builder.AddParam(MachineType::Pointer());
}
signature_ = sig_builder.Build();
@ -278,7 +281,8 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
// the actual test function.
// Function, effect, and control.
Node** parameters = zone()->template NewArray<Node*>(4 + 3);
Node** parameters =
zone()->template NewArray<Node*>(WASM_RUNNER_MAX_NUM_PARAMETERS + 3);
graph()->SetStart(graph()->NewNode(common()->Start(6)));
Node* effect = graph()->start();
int parameter_count = 0;
@ -329,7 +333,8 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
machine()->Store(
StoreRepresentation(MachineTypeForC<ReturnType>().representation(),
WriteBarrierKind::kNoWriteBarrier)),
graph()->NewNode(common()->Parameter(4), graph()->start()),
graph()->NewNode(common()->Parameter(WASM_RUNNER_MAX_NUM_PARAMETERS),
graph()->start()),
graph()->NewNode(common()->Int32Constant(0)), call, effect,
graph()->start());
Node* r = graph()->NewNode(
@ -351,6 +356,20 @@ class WasmFunctionWrapper : public HandleAndZoneScope,
CallDescriptor* descriptor =
Linkage::GetSimplifiedCDescriptor(zone(), signature_, true);
if (kPointerSize == 4) {
// One additional parameter for the pointer of the return value.
Signature<MachineRepresentation>::Builder rep_builder(
zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
rep_builder.AddReturn(MachineRepresentation::kWord32);
for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
rep_builder.AddParam(MachineRepresentation::kWord32);
}
Int64Lowering r(graph(), machine(), common(), zone(),
rep_builder.Build());
r.LowerGraph();
}
CompilationInfo info("testing", isolate, graph()->zone());
code_ =
Pipeline::GenerateCodeForTesting(&info, descriptor, graph(), nullptr);
@ -418,9 +437,13 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
Handle<Code> Compile(ModuleEnv* module) {
InitializeDescriptor();
CallDescriptor* desc = descriptor_;
if (kPointerSize == 4) {
desc = module->GetI32WasmCallDescriptor(this->zone(), desc);
}
CompilationInfo info("wasm compile", this->isolate(), this->zone());
Handle<Code> result =
Pipeline::GenerateCodeForTesting(&info, descriptor_, this->graph());
Pipeline::GenerateCodeForTesting(&info, desc, this->graph());
#ifdef ENABLE_DISASSEMBLER
if (!result.is_null() && FLAG_print_opt_code) {
OFStream os(stdout);
@ -529,7 +552,7 @@ class WasmRunner {
}
private:
LocalType storage_[5];
LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS];
FunctionSig signature_;
WasmFunctionCompiler compiler_;
WasmFunctionWrapper<ReturnType> wrapper_;