Index: src/compiler/wasm-compiler.cc |
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
index 559f894f8abf9d1c0e24a5c2ead29ed862655758..5b1ff409ad20e0bd9542d6b31ab355226d7bdded 100644 |
--- a/src/compiler/wasm-compiler.cc |
+++ b/src/compiler/wasm-compiler.cc |
@@ -500,9 +500,17 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, |
// kExprI64Sub: |
// kExprI64Mul: |
// kExprI64DivS: |
+ case wasm::kExprI64DivS: |
+ return BuildI64DivS(left, right); |
// kExprI64DivU: |
+ case wasm::kExprI64DivU: |
+ return BuildI64DivU(left, right); |
// kExprI64RemS: |
+ case wasm::kExprI64RemS: |
+ return BuildI64RemS(left, right); |
// kExprI64RemU: |
+ case wasm::kExprI64RemU: |
+ return BuildI64RemU(left, right); |
case wasm::kExprI64Ior: |
op = m->Word64Or(); |
break; |
@@ -568,44 +576,6 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, |
case wasm::kExprI64Mul: |
op = m->Int64Mul(); |
break; |
- case wasm::kExprI64DivS: { |
- trap_->ZeroCheck64(kTrapDivByZero, right); |
- Node* before = *control_; |
- Node* denom_is_m1; |
- Node* denom_is_not_m1; |
- Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
- jsgraph()->Int64Constant(-1)), |
- &denom_is_m1, &denom_is_not_m1); |
- *control_ = denom_is_m1; |
- trap_->TrapIfEq64(kTrapDivUnrepresentable, left, |
- std::numeric_limits<int64_t>::min()); |
- if (*control_ != denom_is_m1) { |
- *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), |
- denom_is_not_m1, *control_); |
- } else { |
- *control_ = before; |
- } |
- return graph()->NewNode(m->Int64Div(), left, right, *control_); |
- } |
- case wasm::kExprI64DivU: |
- op = m->Uint64Div(); |
- return graph()->NewNode(op, left, right, |
- trap_->ZeroCheck64(kTrapDivByZero, right)); |
- case wasm::kExprI64RemS: { |
- trap_->ZeroCheck64(kTrapRemByZero, right); |
- Diamond d(jsgraph()->graph(), jsgraph()->common(), |
- graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
- jsgraph()->Int64Constant(-1))); |
- |
- Node* rem = graph()->NewNode(m->Int64Mod(), left, right, d.if_false); |
- |
- return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), |
- rem); |
- } |
- case wasm::kExprI64RemU: |
- op = m->Uint64Mod(); |
- return graph()->NewNode(op, left, right, |
- trap_->ZeroCheck64(kTrapRemByZero, right)); |
case wasm::kExprI64Ror: |
op = m->Word64Ror(); |
break; |
@@ -1774,6 +1744,108 @@ Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction( |
return load; |
} |
+Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { |
+ if (jsgraph()->machine()->Is32()) { |
+ return BuildDiv64Call( |
+ left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), |
+ MachineType::Int64(), kTrapDivByZero); |
+ } |
+ trap_->ZeroCheck64(kTrapDivByZero, right); |
+ Node* before = *control_; |
+ Node* denom_is_m1; |
+ Node* denom_is_not_m1; |
+ Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
+ jsgraph()->Int64Constant(-1)), |
+ &denom_is_m1, &denom_is_not_m1); |
+ *control_ = denom_is_m1; |
+ trap_->TrapIfEq64(kTrapDivUnrepresentable, left, |
+ std::numeric_limits<int64_t>::min()); |
+ if (*control_ != denom_is_m1) { |
+ *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, |
+ *control_); |
+ } else { |
+ *control_ = before; |
+ } |
+ return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, |
+ *control_); |
+} |
+ |
+Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) { |
+ if (jsgraph()->machine()->Is32()) { |
+ return BuildDiv64Call( |
+ left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), |
+ MachineType::Int64(), kTrapRemByZero); |
+ } |
+ trap_->ZeroCheck64(kTrapRemByZero, right); |
+ Diamond d(jsgraph()->graph(), jsgraph()->common(), |
+ graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
+ jsgraph()->Int64Constant(-1))); |
+ |
+ Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, |
+ d.if_false); |
+ |
+ return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), |
+ rem); |
+} |
+ |
+Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) { |
+ if (jsgraph()->machine()->Is32()) { |
+ return BuildDiv64Call( |
+ left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), |
+ MachineType::Int64(), kTrapDivByZero); |
+ } |
+ return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right, |
+ trap_->ZeroCheck64(kTrapDivByZero, right)); |
+} |
+Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right) { |
+ if (jsgraph()->machine()->Is32()) { |
+ return BuildDiv64Call( |
+ left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()), |
+ MachineType::Int64(), kTrapRemByZero); |
+ } |
+ return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right, |
+ trap_->ZeroCheck64(kTrapRemByZero, right)); |
+} |
+ |
+Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, |
+ ExternalReference ref, |
+ MachineType result_type, int trap_zero) { |
+ Node* stack_slot_dst = graph()->NewNode( |
+ jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
+ Node* stack_slot_src = graph()->NewNode( |
+ jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
+ |
+ const Operator* store_op = jsgraph()->machine()->Store( |
+ StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier)); |
+ *effect_ = |
+ graph()->NewNode(store_op, stack_slot_dst, jsgraph()->Int32Constant(0), |
+ left, *effect_, *control_); |
+ *effect_ = |
+ graph()->NewNode(store_op, stack_slot_src, jsgraph()->Int32Constant(0), |
+ right, *effect_, *control_); |
+ |
+ MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); |
+ sig_builder.AddReturn(MachineType::Int32()); |
+ sig_builder.AddParam(MachineType::Pointer()); |
+ sig_builder.AddParam(MachineType::Pointer()); |
+ |
+ Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
+ Node* args[] = {function, stack_slot_dst, stack_slot_src}; |
+ |
+ Node* call = BuildCCall(sig_builder.Build(), args); |
+ |
+ // TODO(wasm): This can get simpler if we have a specialized runtime call to |
+ // throw WASM exceptions by trap code instead of by string. |
+ trap_->ZeroCheck32(static_cast<TrapReason>(trap_zero), call); |
+ trap_->TrapIfEq32(kTrapDivUnrepresentable, call, -1); |
+ const Operator* load_op = jsgraph()->machine()->Load(result_type); |
+ Node* load = |
+ graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), |
+ *effect_, *control_); |
+ *effect_ = load; |
+ return load; |
+} |
+ |
Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
const size_t params = sig->parameter_count(); |
const size_t extra = 2; // effect and control inputs. |