Index: src/compiler/wasm-compiler.cc |
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
index 395a8d4f168d6f7b5891c30c6659c8f6728e47cd..dd0dfe3873bca5de94a28196a0072b44184f0d85 100644 |
--- a/src/compiler/wasm-compiler.cc |
+++ b/src/compiler/wasm-compiler.cc |
@@ -795,13 +795,9 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { |
} |
} |
case wasm::kExprF64Trunc: { |
- if (m->Float64RoundTruncate().IsSupported()) { |
- op = m->Float64RoundTruncate().op(); |
- break; |
- } else { |
- op = UnsupportedOpcode(opcode); |
- break; |
- } |
+ if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input); |
+ op = m->Float64RoundTruncate().op(); |
+ break; |
} |
case wasm::kExprF64NearestInt: { |
if (m->Float64RoundTiesEven().IsSupported()) { |
@@ -1436,6 +1432,60 @@ Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { |
return Unop(wasm::kExprF32ReinterpretI32, result); |
} |
+Node* WasmGraphBuilder::BuildF64Trunc(Node* input) { |
+ // We do truncation by calling a C function which calculates the truncation |
+ // for us. The input is passed to the C function as a double* to avoid double |
+ // parameters. For this we reserve a slot on the stack, store the parameter in |
+ // that slot, pass a pointer to the slot to the C function, and after calling |
+ // the C function we collect the return value from the stack slot. |
+ |
+ Node* stack_slot_param = graph()->NewNode( |
+ jsgraph()->machine()->StackSlot(MachineRepresentation::kFloat64)); |
+ |
+ const Operator* store_op = jsgraph()->machine()->Store( |
+ StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier)); |
+ *effect_ = |
+ graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), |
+ input, *effect_, *control_); |
+ |
+ Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1); |
+ sig_builder.AddParam(MachineType::Pointer()); |
+ Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant( |
+ ExternalReference::trunc64_wrapper_function(jsgraph()->isolate()))); |
+ |
+ Node* args[] = {function, stack_slot_param}; |
+ |
+ BuildCCall(sig_builder.Build(), args); |
+ |
+ const Operator* load_op = jsgraph()->machine()->Load(MachineType::Float64()); |
+ |
+ Node* load = |
+ graph()->NewNode(load_op, stack_slot_param, 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. |
+ const size_t count = 1 + params + extra; |
+ |
+ // Reallocate the buffer to make space for extra inputs. |
+ args = Realloc(args, count); |
+ |
+ // Add effect and control inputs. |
+ args[params + 1] = *effect_; |
+ args[params + 2] = *control_; |
+ |
+ CallDescriptor* desc = |
+ Linkage::GetSimplifiedCDescriptor(jsgraph()->zone(), sig); |
+ |
+ const Operator* op = jsgraph()->common()->Call(desc); |
+ Node* call = graph()->NewNode(op, static_cast<int>(count), args); |
+ *effect_ = call; |
+ return call; |
+} |
Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) { |
const size_t params = sig->parameter_count(); |