OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/wasm-compiler.h" | 5 #include "src/compiler/wasm-compiler.h" |
6 | 6 |
7 #include "src/isolate-inl.h" | 7 #include "src/isolate-inl.h" |
8 | 8 |
9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
10 | 10 |
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 std::swap(left, right); | 690 std::swap(left, right); |
691 break; | 691 break; |
692 case wasm::kExprF32Min: | 692 case wasm::kExprF32Min: |
693 return BuildF32Min(left, right); | 693 return BuildF32Min(left, right); |
694 case wasm::kExprF64Min: | 694 case wasm::kExprF64Min: |
695 return BuildF64Min(left, right); | 695 return BuildF64Min(left, right); |
696 case wasm::kExprF32Max: | 696 case wasm::kExprF32Max: |
697 return BuildF32Max(left, right); | 697 return BuildF32Max(left, right); |
698 case wasm::kExprF64Max: | 698 case wasm::kExprF64Max: |
699 return BuildF64Max(left, right); | 699 return BuildF64Max(left, right); |
| 700 case wasm::kExprF64Pow: { |
| 701 return BuildF64Pow(left, right); |
| 702 } |
| 703 case wasm::kExprF64Atan2: { |
| 704 return BuildF64Atan2(left, right); |
| 705 } |
| 706 case wasm::kExprF64Mod: { |
| 707 return BuildF64Mod(left, right); |
| 708 } |
700 default: | 709 default: |
701 op = UnsupportedOpcode(opcode); | 710 op = UnsupportedOpcode(opcode); |
702 } | 711 } |
703 return graph()->NewNode(op, left, right); | 712 return graph()->NewNode(op, left, right); |
704 } | 713 } |
705 | 714 |
706 | 715 |
707 Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { | 716 Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { |
708 const Operator* op; | 717 const Operator* op; |
709 MachineOperatorBuilder* m = jsgraph()->machine(); | 718 MachineOperatorBuilder* m = jsgraph()->machine(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input); | 826 if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input); |
818 op = m->Float64RoundTruncate().op(); | 827 op = m->Float64RoundTruncate().op(); |
819 break; | 828 break; |
820 } | 829 } |
821 case wasm::kExprF64NearestInt: { | 830 case wasm::kExprF64NearestInt: { |
822 if (!m->Float64RoundTiesEven().IsSupported()) | 831 if (!m->Float64RoundTiesEven().IsSupported()) |
823 return BuildF64NearestInt(input); | 832 return BuildF64NearestInt(input); |
824 op = m->Float64RoundTiesEven().op(); | 833 op = m->Float64RoundTiesEven().op(); |
825 break; | 834 break; |
826 } | 835 } |
| 836 case wasm::kExprF64Acos: { |
| 837 return BuildF64Acos(input); |
| 838 } |
| 839 case wasm::kExprF64Asin: { |
| 840 return BuildF64Asin(input); |
| 841 } |
| 842 case wasm::kExprF64Atan: { |
| 843 return BuildF64Atan(input); |
| 844 } |
| 845 case wasm::kExprF64Cos: { |
| 846 return BuildF64Cos(input); |
| 847 } |
| 848 case wasm::kExprF64Sin: { |
| 849 return BuildF64Sin(input); |
| 850 } |
| 851 case wasm::kExprF64Tan: { |
| 852 return BuildF64Tan(input); |
| 853 } |
| 854 case wasm::kExprF64Exp: { |
| 855 return BuildF64Exp(input); |
| 856 } |
| 857 case wasm::kExprF64Log: { |
| 858 return BuildF64Log(input); |
| 859 } |
827 case wasm::kExprI32ConvertI64: | 860 case wasm::kExprI32ConvertI64: |
828 op = m->TruncateInt64ToInt32(); | 861 op = m->TruncateInt64ToInt32(); |
829 break; | 862 break; |
830 #if WASM_64 | 863 #if WASM_64 |
831 // Opcodes only supported on 64-bit platforms. | 864 // Opcodes only supported on 64-bit platforms. |
832 // TODO(titzer): query the machine operator builder here instead of #ifdef. | 865 // TODO(titzer): query the machine operator builder here instead of #ifdef. |
833 case wasm::kExprI64SConvertI32: | 866 case wasm::kExprI64SConvertI32: |
834 op = m->ChangeInt32ToInt64(); | 867 op = m->ChangeInt32ToInt64(); |
835 break; | 868 break; |
836 case wasm::kExprI64UConvertI32: | 869 case wasm::kExprI64UConvertI32: |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1411 Binop(wasm::kExprI64And, result, | 1444 Binop(wasm::kExprI64And, result, |
1412 jsgraph()->Int64Constant(0x00000000ffffffff))); | 1445 jsgraph()->Int64Constant(0x00000000ffffffff))); |
1413 | 1446 |
1414 return result; | 1447 return result; |
1415 } | 1448 } |
1416 | 1449 |
1417 Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { | 1450 Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { |
1418 MachineType type = MachineType::Float32(); | 1451 MachineType type = MachineType::Float32(); |
1419 ExternalReference ref = | 1452 ExternalReference ref = |
1420 ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate()); | 1453 ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate()); |
1421 return BuildRoundingInstruction(input, ref, type); | 1454 return BuildCFuncInstruction(ref, type, input); |
1422 } | 1455 } |
1423 | 1456 |
1424 Node* WasmGraphBuilder::BuildF32Floor(Node* input) { | 1457 Node* WasmGraphBuilder::BuildF32Floor(Node* input) { |
1425 MachineType type = MachineType::Float32(); | 1458 MachineType type = MachineType::Float32(); |
1426 ExternalReference ref = | 1459 ExternalReference ref = |
1427 ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate()); | 1460 ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate()); |
1428 return BuildRoundingInstruction(input, ref, type); | 1461 return BuildCFuncInstruction(ref, type, input); |
1429 } | 1462 } |
1430 | 1463 |
1431 Node* WasmGraphBuilder::BuildF32Ceil(Node* input) { | 1464 Node* WasmGraphBuilder::BuildF32Ceil(Node* input) { |
1432 MachineType type = MachineType::Float32(); | 1465 MachineType type = MachineType::Float32(); |
1433 ExternalReference ref = | 1466 ExternalReference ref = |
1434 ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate()); | 1467 ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate()); |
1435 return BuildRoundingInstruction(input, ref, type); | 1468 return BuildCFuncInstruction(ref, type, input); |
1436 } | 1469 } |
1437 | 1470 |
1438 Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) { | 1471 Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) { |
1439 MachineType type = MachineType::Float32(); | 1472 MachineType type = MachineType::Float32(); |
1440 ExternalReference ref = | 1473 ExternalReference ref = |
1441 ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate()); | 1474 ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate()); |
1442 return BuildRoundingInstruction(input, ref, type); | 1475 return BuildCFuncInstruction(ref, type, input); |
1443 } | 1476 } |
1444 | 1477 |
1445 Node* WasmGraphBuilder::BuildF64Trunc(Node* input) { | 1478 Node* WasmGraphBuilder::BuildF64Trunc(Node* input) { |
1446 MachineType type = MachineType::Float64(); | 1479 MachineType type = MachineType::Float64(); |
1447 ExternalReference ref = | 1480 ExternalReference ref = |
1448 ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate()); | 1481 ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate()); |
1449 return BuildRoundingInstruction(input, ref, type); | 1482 return BuildCFuncInstruction(ref, type, input); |
1450 } | 1483 } |
1451 | 1484 |
1452 Node* WasmGraphBuilder::BuildF64Floor(Node* input) { | 1485 Node* WasmGraphBuilder::BuildF64Floor(Node* input) { |
1453 MachineType type = MachineType::Float64(); | 1486 MachineType type = MachineType::Float64(); |
1454 ExternalReference ref = | 1487 ExternalReference ref = |
1455 ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate()); | 1488 ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate()); |
1456 return BuildRoundingInstruction(input, ref, type); | 1489 return BuildCFuncInstruction(ref, type, input); |
1457 } | 1490 } |
1458 | 1491 |
1459 Node* WasmGraphBuilder::BuildF64Ceil(Node* input) { | 1492 Node* WasmGraphBuilder::BuildF64Ceil(Node* input) { |
1460 MachineType type = MachineType::Float64(); | 1493 MachineType type = MachineType::Float64(); |
1461 ExternalReference ref = | 1494 ExternalReference ref = |
1462 ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate()); | 1495 ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate()); |
1463 return BuildRoundingInstruction(input, ref, type); | 1496 return BuildCFuncInstruction(ref, type, input); |
1464 } | 1497 } |
1465 | 1498 |
1466 Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) { | 1499 Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) { |
1467 MachineType type = MachineType::Float64(); | 1500 MachineType type = MachineType::Float64(); |
1468 ExternalReference ref = | 1501 ExternalReference ref = |
1469 ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate()); | 1502 ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate()); |
1470 return BuildRoundingInstruction(input, ref, type); | 1503 return BuildCFuncInstruction(ref, type, input); |
1471 } | 1504 } |
1472 | 1505 |
1473 Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input, | 1506 Node* WasmGraphBuilder::BuildF64Acos(Node* input) { |
1474 ExternalReference ref, | 1507 MachineType type = MachineType::Float64(); |
1475 MachineType type) { | 1508 ExternalReference ref = |
1476 // We do truncation by calling a C function which calculates the truncation | 1509 ExternalReference::f64_acos_wrapper_function(jsgraph()->isolate()); |
1477 // for us. The input is passed to the C function as a double* to avoid double | 1510 return BuildCFuncInstruction(ref, type, input); |
1478 // parameters. For this we reserve a slot on the stack, store the parameter in | 1511 } |
1479 // that slot, pass a pointer to the slot to the C function, and after calling | |
1480 // the C function we collect the return value from the stack slot. | |
1481 | 1512 |
1482 Node* stack_slot_param = | 1513 Node* WasmGraphBuilder::BuildF64Asin(Node* input) { |
| 1514 MachineType type = MachineType::Float64(); |
| 1515 ExternalReference ref = |
| 1516 ExternalReference::f64_asin_wrapper_function(jsgraph()->isolate()); |
| 1517 return BuildCFuncInstruction(ref, type, input); |
| 1518 } |
| 1519 |
| 1520 Node* WasmGraphBuilder::BuildF64Atan(Node* input) { |
| 1521 MachineType type = MachineType::Float64(); |
| 1522 ExternalReference ref = |
| 1523 ExternalReference::f64_atan_wrapper_function(jsgraph()->isolate()); |
| 1524 return BuildCFuncInstruction(ref, type, input); |
| 1525 } |
| 1526 |
| 1527 Node* WasmGraphBuilder::BuildF64Cos(Node* input) { |
| 1528 MachineType type = MachineType::Float64(); |
| 1529 ExternalReference ref = |
| 1530 ExternalReference::f64_cos_wrapper_function(jsgraph()->isolate()); |
| 1531 return BuildCFuncInstruction(ref, type, input); |
| 1532 } |
| 1533 |
| 1534 Node* WasmGraphBuilder::BuildF64Sin(Node* input) { |
| 1535 MachineType type = MachineType::Float64(); |
| 1536 ExternalReference ref = |
| 1537 ExternalReference::f64_sin_wrapper_function(jsgraph()->isolate()); |
| 1538 return BuildCFuncInstruction(ref, type, input); |
| 1539 } |
| 1540 |
| 1541 Node* WasmGraphBuilder::BuildF64Tan(Node* input) { |
| 1542 MachineType type = MachineType::Float64(); |
| 1543 ExternalReference ref = |
| 1544 ExternalReference::f64_tan_wrapper_function(jsgraph()->isolate()); |
| 1545 return BuildCFuncInstruction(ref, type, input); |
| 1546 } |
| 1547 |
| 1548 Node* WasmGraphBuilder::BuildF64Exp(Node* input) { |
| 1549 MachineType type = MachineType::Float64(); |
| 1550 ExternalReference ref = |
| 1551 ExternalReference::f64_exp_wrapper_function(jsgraph()->isolate()); |
| 1552 return BuildCFuncInstruction(ref, type, input); |
| 1553 } |
| 1554 |
| 1555 Node* WasmGraphBuilder::BuildF64Log(Node* input) { |
| 1556 MachineType type = MachineType::Float64(); |
| 1557 ExternalReference ref = |
| 1558 ExternalReference::f64_log_wrapper_function(jsgraph()->isolate()); |
| 1559 return BuildCFuncInstruction(ref, type, input); |
| 1560 } |
| 1561 |
| 1562 Node* WasmGraphBuilder::BuildF64Atan2(Node* left, Node* right) { |
| 1563 MachineType type = MachineType::Float64(); |
| 1564 ExternalReference ref = |
| 1565 ExternalReference::f64_atan2_wrapper_function(jsgraph()->isolate()); |
| 1566 return BuildCFuncInstruction(ref, type, left, right); |
| 1567 } |
| 1568 |
| 1569 Node* WasmGraphBuilder::BuildF64Pow(Node* left, Node* right) { |
| 1570 MachineType type = MachineType::Float64(); |
| 1571 ExternalReference ref = |
| 1572 ExternalReference::f64_pow_wrapper_function(jsgraph()->isolate()); |
| 1573 return BuildCFuncInstruction(ref, type, left, right); |
| 1574 } |
| 1575 |
| 1576 Node* WasmGraphBuilder::BuildF64Mod(Node* left, Node* right) { |
| 1577 MachineType type = MachineType::Float64(); |
| 1578 ExternalReference ref = |
| 1579 ExternalReference::f64_mod_wrapper_function(jsgraph()->isolate()); |
| 1580 return BuildCFuncInstruction(ref, type, left, right); |
| 1581 } |
| 1582 |
| 1583 Node* WasmGraphBuilder::BuildCFuncInstruction(ExternalReference ref, |
| 1584 MachineType type, Node* input0, |
| 1585 Node* input1) { |
| 1586 // We do truncation by calling a C function which calculates the result. |
| 1587 // The input is passed to the C function as a double*'s to avoid double |
| 1588 // parameters. For this we reserve slots on the stack, store the parameters |
| 1589 // in those slots, pass pointers to the slot to the C function, |
| 1590 // and after calling the C function we collect the return value from |
| 1591 // the stack slot. |
| 1592 |
| 1593 Node* stack_slot_param0 = |
1483 graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation())); | 1594 graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation())); |
1484 | 1595 |
1485 const Operator* store_op = jsgraph()->machine()->Store( | 1596 const Operator* store_op0 = jsgraph()->machine()->Store( |
1486 StoreRepresentation(type.representation(), kNoWriteBarrier)); | 1597 StoreRepresentation(type.representation(), kNoWriteBarrier)); |
1487 *effect_ = | 1598 *effect_ = graph()->NewNode(store_op0, stack_slot_param0, |
1488 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), | 1599 jsgraph()->Int32Constant(0), input0, *effect_, |
1489 input, *effect_, *control_); | 1600 *control_); |
1490 | 1601 |
1491 Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1); | 1602 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
| 1603 Node** args = Buffer(4); |
| 1604 args[0] = function; |
| 1605 args[1] = stack_slot_param0; |
| 1606 int input_count = 1; |
| 1607 |
| 1608 if (input1 != nullptr) { |
| 1609 Node* stack_slot_param1 = graph()->NewNode( |
| 1610 jsgraph()->machine()->StackSlot(type.representation())); |
| 1611 const Operator* store_op1 = jsgraph()->machine()->Store( |
| 1612 StoreRepresentation(type.representation(), kNoWriteBarrier)); |
| 1613 *effect_ = graph()->NewNode(store_op1, stack_slot_param1, |
| 1614 jsgraph()->Int32Constant(0), input1, *effect_, |
| 1615 *control_); |
| 1616 args = Realloc(args, 5); |
| 1617 args[2] = stack_slot_param1; |
| 1618 ++input_count; |
| 1619 } |
| 1620 |
| 1621 Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, |
| 1622 input_count); |
1492 sig_builder.AddParam(MachineType::Pointer()); | 1623 sig_builder.AddParam(MachineType::Pointer()); |
1493 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | 1624 if (input1 != nullptr) { |
1494 | 1625 sig_builder.AddParam(MachineType::Pointer()); |
1495 Node* args[] = {function, stack_slot_param}; | 1626 } |
1496 | |
1497 BuildCCall(sig_builder.Build(), args); | 1627 BuildCCall(sig_builder.Build(), args); |
1498 | 1628 |
1499 const Operator* load_op = jsgraph()->machine()->Load(type); | 1629 const Operator* load_op = jsgraph()->machine()->Load(type); |
1500 | 1630 |
1501 Node* load = | 1631 Node* load = |
1502 graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0), | 1632 graph()->NewNode(load_op, stack_slot_param0, jsgraph()->Int32Constant(0), |
1503 *effect_, *control_); | 1633 *effect_, *control_); |
1504 *effect_ = load; | 1634 *effect_ = load; |
1505 return load; | 1635 return load; |
1506 } | 1636 } |
1507 | 1637 |
1508 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { | 1638 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
1509 const size_t params = sig->parameter_count(); | 1639 const size_t params = sig->parameter_count(); |
1510 const size_t extra = 2; // effect and control inputs. | 1640 const size_t extra = 2; // effect and control inputs. |
1511 const size_t count = 1 + params + extra; | 1641 const size_t count = 1 + params + extra; |
1512 | 1642 |
(...skipping 27 matching lines...) Expand all Loading... |
1540 | 1670 |
1541 CallDescriptor* descriptor = | 1671 CallDescriptor* descriptor = |
1542 wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); | 1672 wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); |
1543 const Operator* op = jsgraph()->common()->Call(descriptor); | 1673 const Operator* op = jsgraph()->common()->Call(descriptor); |
1544 Node* call = graph()->NewNode(op, static_cast<int>(count), args); | 1674 Node* call = graph()->NewNode(op, static_cast<int>(count), args); |
1545 | 1675 |
1546 *effect_ = call; | 1676 *effect_ = call; |
1547 return call; | 1677 return call; |
1548 } | 1678 } |
1549 | 1679 |
1550 | |
1551 Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args) { | 1680 Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args) { |
1552 DCHECK_NULL(args[0]); | 1681 DCHECK_NULL(args[0]); |
1553 | 1682 |
1554 // Add code object as constant. | 1683 // Add code object as constant. |
1555 args[0] = Constant(module_->GetFunctionCode(index)); | 1684 args[0] = Constant(module_->GetFunctionCode(index)); |
1556 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); | 1685 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); |
1557 | 1686 |
1558 return BuildWasmCall(sig, args); | 1687 return BuildWasmCall(sig, args); |
1559 } | 1688 } |
1560 | 1689 |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2263 module_env->module->GetName(function.name_offset)); | 2392 module_env->module->GetName(function.name_offset)); |
2264 } | 2393 } |
2265 | 2394 |
2266 return code; | 2395 return code; |
2267 } | 2396 } |
2268 | 2397 |
2269 | 2398 |
2270 } // namespace compiler | 2399 } // namespace compiler |
2271 } // namespace internal | 2400 } // namespace internal |
2272 } // namespace v8 | 2401 } // namespace v8 |
OLD | NEW |