Chromium Code Reviews| 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 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 break; | 536 break; |
| 537 case wasm::kExprI64GtU: | 537 case wasm::kExprI64GtU: |
| 538 op = m->Uint64LessThan(); | 538 op = m->Uint64LessThan(); |
| 539 std::swap(left, right); | 539 std::swap(left, right); |
| 540 break; | 540 break; |
| 541 case wasm::kExprI64GeU: | 541 case wasm::kExprI64GeU: |
| 542 op = m->Uint64LessThanOrEqual(); | 542 op = m->Uint64LessThanOrEqual(); |
| 543 std::swap(left, right); | 543 std::swap(left, right); |
| 544 break; | 544 break; |
| 545 | 545 |
| 546 // kExprI32ConvertI64: | |
| 547 // kExprI64SConvertI32: | |
| 548 // kExprI64UConvertI32: | |
| 549 | |
| 550 // kExprF64ReinterpretI64: | |
| 551 // kExprI64ReinterpretF64: | |
| 552 | |
| 553 // kExprI64Clz: | |
| 554 // kExprI64Ctz: | |
| 555 // kExprI64Popcnt: | |
| 556 | |
| 557 // kExprF32SConvertI64: | |
| 558 // kExprF32UConvertI64: | |
| 559 // kExprF64SConvertI64: | |
| 560 // kExprF64UConvertI64: | |
| 561 // kExprI64SConvertF32: | |
| 562 // kExprI64SConvertF64: | |
| 563 // kExprI64UConvertF32: | |
| 564 // kExprI64UConvertF64: | |
| 565 #if WASM_64 | 546 #if WASM_64 |
| 566 // Opcodes only supported on 64-bit platforms. | 547 // Opcodes only supported on 64-bit platforms. |
| 567 // TODO(titzer): query the machine operator builder here instead of #ifdef. | 548 // TODO(titzer): query the machine operator builder here instead of #ifdef. |
| 568 case wasm::kExprI64Add: | 549 case wasm::kExprI64Add: |
| 569 op = m->Int64Add(); | 550 op = m->Int64Add(); |
| 570 break; | 551 break; |
| 571 case wasm::kExprI64Sub: | 552 case wasm::kExprI64Sub: |
| 572 op = m->Int64Sub(); | 553 op = m->Int64Sub(); |
| 573 break; | 554 break; |
| 574 case wasm::kExprI64Mul: | 555 case wasm::kExprI64Mul: |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 820 } | 801 } |
| 821 case wasm::kExprF64NearestInt: { | 802 case wasm::kExprF64NearestInt: { |
| 822 if (!m->Float64RoundTiesEven().IsSupported()) | 803 if (!m->Float64RoundTiesEven().IsSupported()) |
| 823 return BuildF64NearestInt(input); | 804 return BuildF64NearestInt(input); |
| 824 op = m->Float64RoundTiesEven().op(); | 805 op = m->Float64RoundTiesEven().op(); |
| 825 break; | 806 break; |
| 826 } | 807 } |
| 827 case wasm::kExprI32ConvertI64: | 808 case wasm::kExprI32ConvertI64: |
| 828 op = m->TruncateInt64ToInt32(); | 809 op = m->TruncateInt64ToInt32(); |
| 829 break; | 810 break; |
| 811 // kExprI32ConvertI64: | |
| 812 // kExprI64SConvertI32: | |
| 813 // kExprI64UConvertI32: | |
| 814 | |
| 815 // kExprF64ReinterpretI64: | |
| 816 // kExprI64ReinterpretF64: | |
| 817 | |
| 818 // kExprI64Clz: | |
| 819 // kExprI64Ctz: | |
| 820 // kExprI64Popcnt: | |
| 821 | |
| 822 // kExprF32SConvertI64: | |
| 823 case wasm::kExprF32SConvertI64: | |
| 824 if (kPointerSize == 4) { | |
| 825 return BuildF32SConvertI64(input); | |
| 826 } | |
| 827 op = m->RoundInt64ToFloat32(); | |
| 828 break; | |
| 829 // kExprF32UConvertI64: | |
| 830 case wasm::kExprF32UConvertI64: | |
| 831 if (kPointerSize == 4) { | |
| 832 return BuildF32UConvertI64(input); | |
| 833 } | |
| 834 op = m->RoundUint64ToFloat32(); | |
| 835 break; | |
| 836 // kExprF64SConvertI64: | |
| 837 case wasm::kExprF64SConvertI64: | |
| 838 if (kPointerSize == 4) { | |
| 839 return BuildF64SConvertI64(input); | |
| 840 } | |
| 841 op = m->RoundInt64ToFloat64(); | |
| 842 break; | |
| 843 // kExprF64UConvertI64: | |
| 844 case wasm::kExprF64UConvertI64: | |
| 845 if (kPointerSize == 4) { | |
| 846 return BuildF64UConvertI64(input); | |
| 847 } | |
| 848 op = m->RoundUint64ToFloat64(); | |
| 849 break; | |
| 850 // kExprI64SConvertF32: | |
| 851 // kExprI64SConvertF64: | |
| 852 // kExprI64UConvertF32: | |
| 853 // kExprI64UConvertF64: | |
| 854 | |
| 830 #if WASM_64 | 855 #if WASM_64 |
| 831 // Opcodes only supported on 64-bit platforms. | 856 // Opcodes only supported on 64-bit platforms. |
| 832 // TODO(titzer): query the machine operator builder here instead of #ifdef. | 857 // TODO(titzer): query the machine operator builder here instead of #ifdef. |
| 833 case wasm::kExprI64SConvertI32: | 858 case wasm::kExprI64SConvertI32: |
| 834 op = m->ChangeInt32ToInt64(); | 859 op = m->ChangeInt32ToInt64(); |
| 835 break; | 860 break; |
| 836 case wasm::kExprI64UConvertI32: | 861 case wasm::kExprI64UConvertI32: |
| 837 op = m->ChangeUint32ToUint64(); | 862 op = m->ChangeUint32ToUint64(); |
| 838 break; | 863 break; |
| 839 case wasm::kExprF32SConvertI64: | |
| 840 op = m->RoundInt64ToFloat32(); | |
| 841 break; | |
| 842 case wasm::kExprF32UConvertI64: | |
| 843 op = m->RoundUint64ToFloat32(); | |
| 844 break; | |
| 845 case wasm::kExprF64SConvertI64: | |
| 846 op = m->RoundInt64ToFloat64(); | |
| 847 break; | |
| 848 case wasm::kExprF64UConvertI64: | |
| 849 op = m->RoundUint64ToFloat64(); | |
| 850 break; | |
| 851 case wasm::kExprI64SConvertF32: { | 864 case wasm::kExprI64SConvertF32: { |
| 852 Node* trunc = graph()->NewNode(m->TryTruncateFloat32ToInt64(), input); | 865 Node* trunc = graph()->NewNode(m->TryTruncateFloat32ToInt64(), input); |
| 853 Node* result = | 866 Node* result = |
| 854 graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 867 graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
| 855 Node* overflow = | 868 Node* overflow = |
| 856 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 869 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
| 857 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 870 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); |
| 858 return result; | 871 return result; |
| 859 } | 872 } |
| 860 case wasm::kExprI64SConvertF64: { | 873 case wasm::kExprI64SConvertF64: { |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1394 jsgraph()->Int64Constant(0x00000000ffffffff)), | 1407 jsgraph()->Int64Constant(0x00000000ffffffff)), |
| 1395 Binop(wasm::kExprI64And, result, | 1408 Binop(wasm::kExprI64And, result, |
| 1396 jsgraph()->Int64Constant(0x00000000ffffffff))); | 1409 jsgraph()->Int64Constant(0x00000000ffffffff))); |
| 1397 | 1410 |
| 1398 return result; | 1411 return result; |
| 1399 } | 1412 } |
| 1400 | 1413 |
| 1401 Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { | 1414 Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { |
| 1402 MachineType type = MachineType::Float32(); | 1415 MachineType type = MachineType::Float32(); |
| 1403 ExternalReference ref = | 1416 ExternalReference ref = |
| 1404 ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate()); | 1417 ExternalReference::wasm_f32_trunc(jsgraph()->isolate()); |
| 1405 return BuildRoundingInstruction(input, ref, type); | 1418 return BuildRoundingInstruction(input, ref, type); |
| 1406 } | 1419 } |
| 1407 | 1420 |
| 1408 Node* WasmGraphBuilder::BuildF32Floor(Node* input) { | 1421 Node* WasmGraphBuilder::BuildF32Floor(Node* input) { |
| 1409 MachineType type = MachineType::Float32(); | 1422 MachineType type = MachineType::Float32(); |
| 1410 ExternalReference ref = | 1423 ExternalReference ref = |
| 1411 ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate()); | 1424 ExternalReference::wasm_f32_floor(jsgraph()->isolate()); |
| 1412 return BuildRoundingInstruction(input, ref, type); | 1425 return BuildRoundingInstruction(input, ref, type); |
| 1413 } | 1426 } |
| 1414 | 1427 |
| 1415 Node* WasmGraphBuilder::BuildF32Ceil(Node* input) { | 1428 Node* WasmGraphBuilder::BuildF32Ceil(Node* input) { |
| 1416 MachineType type = MachineType::Float32(); | 1429 MachineType type = MachineType::Float32(); |
| 1417 ExternalReference ref = | 1430 ExternalReference ref = |
| 1418 ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate()); | 1431 ExternalReference::wasm_f32_ceil(jsgraph()->isolate()); |
| 1419 return BuildRoundingInstruction(input, ref, type); | 1432 return BuildRoundingInstruction(input, ref, type); |
| 1420 } | 1433 } |
| 1421 | 1434 |
| 1422 Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) { | 1435 Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) { |
| 1423 MachineType type = MachineType::Float32(); | 1436 MachineType type = MachineType::Float32(); |
| 1424 ExternalReference ref = | 1437 ExternalReference ref = |
| 1425 ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate()); | 1438 ExternalReference::wasm_f32_nearest_int(jsgraph()->isolate()); |
| 1426 return BuildRoundingInstruction(input, ref, type); | 1439 return BuildRoundingInstruction(input, ref, type); |
| 1427 } | 1440 } |
| 1428 | 1441 |
| 1429 Node* WasmGraphBuilder::BuildF64Trunc(Node* input) { | 1442 Node* WasmGraphBuilder::BuildF64Trunc(Node* input) { |
| 1430 MachineType type = MachineType::Float64(); | 1443 MachineType type = MachineType::Float64(); |
| 1431 ExternalReference ref = | 1444 ExternalReference ref = |
| 1432 ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate()); | 1445 ExternalReference::wasm_f64_trunc(jsgraph()->isolate()); |
| 1433 return BuildRoundingInstruction(input, ref, type); | 1446 return BuildRoundingInstruction(input, ref, type); |
| 1434 } | 1447 } |
| 1435 | 1448 |
| 1436 Node* WasmGraphBuilder::BuildF64Floor(Node* input) { | 1449 Node* WasmGraphBuilder::BuildF64Floor(Node* input) { |
| 1437 MachineType type = MachineType::Float64(); | 1450 MachineType type = MachineType::Float64(); |
| 1438 ExternalReference ref = | 1451 ExternalReference ref = |
| 1439 ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate()); | 1452 ExternalReference::wasm_f64_floor(jsgraph()->isolate()); |
| 1440 return BuildRoundingInstruction(input, ref, type); | 1453 return BuildRoundingInstruction(input, ref, type); |
| 1441 } | 1454 } |
| 1442 | 1455 |
| 1443 Node* WasmGraphBuilder::BuildF64Ceil(Node* input) { | 1456 Node* WasmGraphBuilder::BuildF64Ceil(Node* input) { |
| 1444 MachineType type = MachineType::Float64(); | 1457 MachineType type = MachineType::Float64(); |
| 1445 ExternalReference ref = | 1458 ExternalReference ref = |
| 1446 ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate()); | 1459 ExternalReference::wasm_f64_ceil(jsgraph()->isolate()); |
| 1447 return BuildRoundingInstruction(input, ref, type); | 1460 return BuildRoundingInstruction(input, ref, type); |
| 1448 } | 1461 } |
| 1449 | 1462 |
| 1450 Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) { | 1463 Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) { |
| 1451 MachineType type = MachineType::Float64(); | 1464 MachineType type = MachineType::Float64(); |
| 1452 ExternalReference ref = | 1465 ExternalReference ref = |
| 1453 ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate()); | 1466 ExternalReference::wasm_f64_nearest_int(jsgraph()->isolate()); |
| 1454 return BuildRoundingInstruction(input, ref, type); | 1467 return BuildRoundingInstruction(input, ref, type); |
| 1455 } | 1468 } |
| 1456 | 1469 |
| 1457 Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input, | 1470 Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input, |
| 1458 ExternalReference ref, | 1471 ExternalReference ref, |
| 1459 MachineType type) { | 1472 MachineType type) { |
| 1460 // We do truncation by calling a C function which calculates the truncation | 1473 // We do truncation by calling a C function which calculates the truncation |
| 1461 // for us. The input is passed to the C function as a double* to avoid double | 1474 // for us. The input is passed to the C function as a double* to avoid double |
| 1462 // parameters. For this we reserve a slot on the stack, store the parameter in | 1475 // parameters. For this we reserve a slot on the stack, store the parameter in |
| 1463 // that slot, pass a pointer to the slot to the C function, and after calling | 1476 // that slot, pass a pointer to the slot to the C function, and after calling |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1482 | 1495 |
| 1483 const Operator* load_op = jsgraph()->machine()->Load(type); | 1496 const Operator* load_op = jsgraph()->machine()->Load(type); |
| 1484 | 1497 |
| 1485 Node* load = | 1498 Node* load = |
| 1486 graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0), | 1499 graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0), |
| 1487 *effect_, *control_); | 1500 *effect_, *control_); |
| 1488 *effect_ = load; | 1501 *effect_ = load; |
| 1489 return load; | 1502 return load; |
| 1490 } | 1503 } |
| 1491 | 1504 |
| 1505 Node* WasmGraphBuilder::BuildF32SConvertI64(Node* input) { | |
| 1506 ExternalReference ref = | |
| 1507 ExternalReference::wasm_int64_to_float32(jsgraph()->isolate()); | |
| 1508 MachineRepresentation parameter_representation = | |
|
titzer
2016/02/25 17:04:33
You can shorten this code up a bit by inlining the
ahaas
2016/02/25 18:29:18
Done.
| |
| 1509 MachineRepresentation::kWord64; | |
| 1510 MachineType result_type = MachineType::Float32(); | |
| 1511 | |
| 1512 return BuildConversionInstruction(input, ref, parameter_representation, | |
| 1513 result_type); | |
| 1514 } | |
| 1515 | |
| 1516 Node* WasmGraphBuilder::BuildF32UConvertI64(Node* input) { | |
| 1517 ExternalReference ref = | |
| 1518 ExternalReference::wasm_uint64_to_float32(jsgraph()->isolate()); | |
| 1519 MachineRepresentation parameter_representation = | |
| 1520 MachineRepresentation::kWord64; | |
| 1521 MachineType result_type = MachineType::Float32(); | |
| 1522 | |
| 1523 return BuildConversionInstruction(input, ref, parameter_representation, | |
| 1524 result_type); | |
| 1525 } | |
| 1526 | |
| 1527 Node* WasmGraphBuilder::BuildF64SConvertI64(Node* input) { | |
| 1528 ExternalReference ref = | |
| 1529 ExternalReference::wasm_int64_to_float64(jsgraph()->isolate()); | |
| 1530 MachineRepresentation parameter_representation = | |
| 1531 MachineRepresentation::kWord64; | |
| 1532 MachineType result_type = MachineType::Float64(); | |
| 1533 | |
| 1534 return BuildConversionInstruction(input, ref, parameter_representation, | |
| 1535 result_type); | |
| 1536 } | |
| 1537 | |
| 1538 Node* WasmGraphBuilder::BuildF64UConvertI64(Node* input) { | |
| 1539 ExternalReference ref = | |
| 1540 ExternalReference::wasm_uint64_to_float64(jsgraph()->isolate()); | |
| 1541 MachineRepresentation parameter_representation = | |
| 1542 MachineRepresentation::kWord64; | |
| 1543 MachineType result_type = MachineType::Float64(); | |
| 1544 | |
| 1545 return BuildConversionInstruction(input, ref, parameter_representation, | |
| 1546 result_type); | |
| 1547 } | |
| 1548 | |
| 1549 Node* WasmGraphBuilder::BuildConversionInstruction( | |
| 1550 Node* input, ExternalReference ref, | |
| 1551 MachineRepresentation parameter_representation, | |
| 1552 const MachineType result_type) { | |
| 1553 Node* stack_slot_param = graph()->NewNode( | |
| 1554 jsgraph()->machine()->StackSlot(parameter_representation)); | |
| 1555 Node* stack_slot_result = graph()->NewNode( | |
| 1556 jsgraph()->machine()->StackSlot(result_type.representation())); | |
| 1557 const Operator* store_op = jsgraph()->machine()->Store( | |
| 1558 StoreRepresentation(parameter_representation, kNoWriteBarrier)); | |
| 1559 *effect_ = | |
| 1560 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), | |
| 1561 input, *effect_, *control_); | |
| 1562 Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 2); | |
| 1563 sig_builder.AddParam(MachineType::Pointer()); | |
| 1564 sig_builder.AddParam(MachineType::Pointer()); | |
| 1565 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | |
| 1566 Node* args[] = {function, stack_slot_param, stack_slot_result}; | |
| 1567 BuildCCall(sig_builder.Build(), args); | |
| 1568 const Operator* load_op = jsgraph()->machine()->Load(result_type); | |
| 1569 Node* load = | |
| 1570 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | |
| 1571 *effect_, *control_); | |
| 1572 *effect_ = load; | |
| 1573 return load; | |
| 1574 } | |
| 1575 | |
| 1492 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { | 1576 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
| 1493 const size_t params = sig->parameter_count(); | 1577 const size_t params = sig->parameter_count(); |
| 1494 const size_t extra = 2; // effect and control inputs. | 1578 const size_t extra = 2; // effect and control inputs. |
| 1495 const size_t count = 1 + params + extra; | 1579 const size_t count = 1 + params + extra; |
| 1496 | 1580 |
| 1497 // Reallocate the buffer to make space for extra inputs. | 1581 // Reallocate the buffer to make space for extra inputs. |
| 1498 args = Realloc(args, count); | 1582 args = Realloc(args, count); |
| 1499 | 1583 |
| 1500 // Add effect and control inputs. | 1584 // Add effect and control inputs. |
| 1501 args[params + 1] = *effect_; | 1585 args[params + 1] = *effect_; |
| (...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2247 module_env->module->GetName(function.name_offset)); | 2331 module_env->module->GetName(function.name_offset)); |
| 2248 } | 2332 } |
| 2249 | 2333 |
| 2250 return code; | 2334 return code; |
| 2251 } | 2335 } |
| 2252 | 2336 |
| 2253 | 2337 |
| 2254 } // namespace compiler | 2338 } // namespace compiler |
| 2255 } // namespace internal | 2339 } // namespace internal |
| 2256 } // namespace v8 | 2340 } // namespace v8 |
| OLD | NEW |