From 545943db155acf1594dfe1a57e455f656fc15192 Mon Sep 17 00:00:00 2001 From: ahaas Date: Thu, 18 Feb 2016 07:18:41 -0800 Subject: [PATCH] [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} --- src/compiler/int64-lowering.cc | 259 ++++++++++++++++++++++++++---- src/compiler/int64-lowering.h | 26 ++- src/compiler/wasm-compiler.cc | 23 +-- src/compiler/wasm-linkage.cc | 119 ++++++++++++-- src/wasm/wasm-module.h | 2 + test/cctest/wasm/test-run-wasm.cc | 44 +++++ test/cctest/wasm/wasm-run-utils.h | 35 +++- 7 files changed, 438 insertions(+), 70 deletions(-) diff --git a/src/compiler/int64-lowering.cc b/src/compiler/int64-lowering.cc index c2952319be..c9c87b65d6 100644 --- a/src/compiler/int64-lowering.cc +++ b/src/compiler/int64-lowering.cc @@ -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* signature) + : zone_(zone), + graph_(graph), machine_(machine), common_(common), state_(graph, 4), stack_(zone), - replacements_(zone->NewArray(graph->NodeCount())) { + replacements_(zone->NewArray(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* 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* signature) { + return GetParameterIndexAfterLowering( + signature, static_cast(signature->parameter_count())); +} + +static int GetReturnCountAfterLowering( + Signature* signature) { + int result = static_cast(signature->return_count()); + for (int i = 0; i < static_cast(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(node); @@ -56,48 +94,207 @@ void Int64Lowering::ReduceNode(Node* node) { common()->Int32Constant(static_cast(value & 0xFFFFFFFF))); Node* high_node = graph()->NewNode( common()->Int32Constant(static_cast(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(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(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 diff --git a/src/compiler/int64-lowering.h b/src/compiler/int64-lowering.h index dcdeae243d..79a95dc195 100644 --- a/src/compiler/int64-lowering.h +++ b/src/compiler/int64-lowering.h @@ -18,12 +18,10 @@ namespace compiler { class Int64Lowering { public: Int64Lowering(Graph* graph, MachineOperatorBuilder* machine, - CommonOperatorBuilder* common, Zone* zone); + CommonOperatorBuilder* common, Zone* zone, + Signature* 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* 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_; ZoneStack stack_; Replacement* replacements_; + Signature* signature_; }; } // namespace compiler diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index 115f1962b1..109bfedd36 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -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(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 CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, } // Run the compiler pipeline to generate machine code. - CallDescriptor* descriptor = const_cast( - 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 = diff --git a/src/compiler/wasm-linkage.cc b/src/compiler/wasm-linkage.cc index 7dd36621e9..09a697ed8a 100644 --- a/src/compiler/wasm-linkage.cc +++ b/src/compiler/wasm-linkage.cc @@ -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(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(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(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 diff --git a/src/wasm/wasm-module.h b/src/wasm/wasm-module.h index cf9aebe7ba..8dc1abc222 100644 --- a/src/wasm/wasm-module.h +++ b/src/wasm/wasm-module.h @@ -191,6 +191,8 @@ struct ModuleEnv { Handle 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); }; diff --git a/test/cctest/wasm/test-run-wasm.cc b/test/cctest/wasm/test-run-wasm.cc index e4f20dd8fc..448cf96507 100644 --- a/test/cctest/wasm/test-run-wasm.cc +++ b/test/cctest/wasm/test-run-wasm.cc @@ -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 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 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; diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h index 732516feb6..a90d9c6150 100644 --- a/test/cctest/wasm/wasm-run-utils.h +++ b/test/cctest/wasm/wasm-run-utils.h @@ -46,6 +46,7 @@ CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast(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::Builder sig_builder(zone(), 1, 5); + // One additional parameter for the pointer to the return value memory. + Signature::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(4 + 3); + Node** parameters = + zone()->template NewArray(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().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::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 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 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 wrapper_;