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 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 } | 735 } |
736 case wasm::kExprI32Popcnt: { | 736 case wasm::kExprI32Popcnt: { |
737 if (m->Word32Popcnt().IsSupported()) { | 737 if (m->Word32Popcnt().IsSupported()) { |
738 op = m->Word32Popcnt().op(); | 738 op = m->Word32Popcnt().op(); |
739 break; | 739 break; |
740 } else { | 740 } else { |
741 return BuildI32Popcnt(input); | 741 return BuildI32Popcnt(input); |
742 } | 742 } |
743 } | 743 } |
744 case wasm::kExprF32Floor: { | 744 case wasm::kExprF32Floor: { |
745 if (m->Float32RoundDown().IsSupported()) { | 745 if (!m->Float32RoundDown().IsSupported()) return BuildF32Floor(input); |
746 op = m->Float32RoundDown().op(); | 746 op = m->Float32RoundDown().op(); |
747 break; | 747 break; |
748 } else { | |
749 op = UnsupportedOpcode(opcode); | |
750 break; | |
751 } | |
752 } | 748 } |
753 case wasm::kExprF32Ceil: { | 749 case wasm::kExprF32Ceil: { |
754 if (m->Float32RoundUp().IsSupported()) { | 750 if (!m->Float32RoundUp().IsSupported()) return BuildF32Ceil(input); |
755 op = m->Float32RoundUp().op(); | 751 op = m->Float32RoundUp().op(); |
756 break; | 752 break; |
757 } else { | |
758 op = UnsupportedOpcode(opcode); | |
759 break; | |
760 } | |
761 } | 753 } |
762 case wasm::kExprF32Trunc: { | 754 case wasm::kExprF32Trunc: { |
763 if (m->Float32RoundTruncate().IsSupported()) { | 755 if (!m->Float32RoundTruncate().IsSupported()) return BuildF32Trunc(input); |
764 op = m->Float32RoundTruncate().op(); | 756 op = m->Float32RoundTruncate().op(); |
765 } else { | |
766 return BuildF32Trunc(input); | |
767 } | |
768 break; | 757 break; |
769 } | 758 } |
770 case wasm::kExprF32NearestInt: { | 759 case wasm::kExprF32NearestInt: { |
771 if (m->Float32RoundTiesEven().IsSupported()) { | 760 if (!m->Float32RoundTiesEven().IsSupported()) |
772 op = m->Float32RoundTiesEven().op(); | 761 return BuildF32NearestInt(input); |
773 break; | 762 op = m->Float32RoundTiesEven().op(); |
774 } else { | 763 break; |
775 op = UnsupportedOpcode(opcode); | |
776 break; | |
777 } | |
778 } | 764 } |
779 case wasm::kExprF64Floor: { | 765 case wasm::kExprF64Floor: { |
780 if (m->Float64RoundDown().IsSupported()) { | 766 if (!m->Float64RoundDown().IsSupported()) return BuildF64Floor(input); |
781 op = m->Float64RoundDown().op(); | 767 op = m->Float64RoundDown().op(); |
782 break; | 768 break; |
783 } else { | |
784 op = UnsupportedOpcode(opcode); | |
785 break; | |
786 } | |
787 } | 769 } |
788 case wasm::kExprF64Ceil: { | 770 case wasm::kExprF64Ceil: { |
789 if (m->Float64RoundUp().IsSupported()) { | 771 if (!m->Float64RoundUp().IsSupported()) return BuildF64Ceil(input); |
790 op = m->Float64RoundUp().op(); | 772 op = m->Float64RoundUp().op(); |
791 break; | 773 break; |
792 } else { | |
793 op = UnsupportedOpcode(opcode); | |
794 break; | |
795 } | |
796 } | 774 } |
797 case wasm::kExprF64Trunc: { | 775 case wasm::kExprF64Trunc: { |
798 if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input); | 776 if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input); |
799 op = m->Float64RoundTruncate().op(); | 777 op = m->Float64RoundTruncate().op(); |
800 break; | 778 break; |
801 } | 779 } |
802 case wasm::kExprF64NearestInt: { | 780 case wasm::kExprF64NearestInt: { |
803 if (m->Float64RoundTiesEven().IsSupported()) { | 781 if (!m->Float64RoundTiesEven().IsSupported()) |
804 op = m->Float64RoundTiesEven().op(); | 782 return BuildF64NearestInt(input); |
805 break; | 783 op = m->Float64RoundTiesEven().op(); |
806 } else { | 784 break; |
807 op = UnsupportedOpcode(opcode); | |
808 break; | |
809 } | |
810 } | 785 } |
811 | 786 |
812 #if WASM_64 | 787 #if WASM_64 |
813 // Opcodes only supported on 64-bit platforms. | 788 // Opcodes only supported on 64-bit platforms. |
814 // TODO(titzer): query the machine operator builder here instead of #ifdef. | 789 // TODO(titzer): query the machine operator builder here instead of #ifdef. |
815 case wasm::kExprI32ConvertI64: | 790 case wasm::kExprI32ConvertI64: |
816 op = m->TruncateInt64ToInt32(); | 791 op = m->TruncateInt64ToInt32(); |
817 break; | 792 break; |
818 case wasm::kExprI64SConvertI32: | 793 case wasm::kExprI64SConvertI32: |
819 op = m->ChangeInt32ToInt64(); | 794 op = m->ChangeInt32ToInt64(); |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 result = Binop(wasm::kExprI64Add, | 1333 result = Binop(wasm::kExprI64Add, |
1359 Binop(wasm::kExprI64And, Binop(wasm::kExprI64ShrU, result, | 1334 Binop(wasm::kExprI64And, Binop(wasm::kExprI64ShrU, result, |
1360 jsgraph()->Int64Constant(32)), | 1335 jsgraph()->Int64Constant(32)), |
1361 jsgraph()->Int64Constant(0x00000000ffffffff)), | 1336 jsgraph()->Int64Constant(0x00000000ffffffff)), |
1362 Binop(wasm::kExprI64And, result, | 1337 Binop(wasm::kExprI64And, result, |
1363 jsgraph()->Int64Constant(0x00000000ffffffff))); | 1338 jsgraph()->Int64Constant(0x00000000ffffffff))); |
1364 | 1339 |
1365 return result; | 1340 return result; |
1366 } | 1341 } |
1367 | 1342 |
| 1343 Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { |
| 1344 MachineType type = MachineType::Float32(); |
| 1345 ExternalReference ref = |
| 1346 ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate()); |
| 1347 return BuildRoundingInstruction(input, ref, type); |
| 1348 } |
1368 | 1349 |
1369 Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { | 1350 Node* WasmGraphBuilder::BuildF32Floor(Node* input) { |
1370 // int32_t int_input = bitftoi(input); | 1351 MachineType type = MachineType::Float32(); |
1371 // int32_t exponent = int_input & 0x7f800000; | 1352 ExternalReference ref = |
1372 // if (exponent >= ((23 + 127) << 23)) { | 1353 ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate()); |
1373 // if (input != input) { | 1354 return BuildRoundingInstruction(input, ref, type); |
1374 // return bititof(int_input | (1 << 22)); | 1355 } |
1375 // } | |
1376 // return input; | |
1377 // } | |
1378 // int32_t sign = int_input & 0x80000000; | |
1379 // if (exponent < (127 << 23)) { | |
1380 // return bititof(sign); | |
1381 // } | |
1382 // int32_t mantissa = int_input & 0x007fffff; | |
1383 // int32_t shift = (127 + 23) - (exponent >> 23); | |
1384 // int32_t new_mantissa = (mantissa >> shift) << shift; | |
1385 // int32_t result = new_mantissa | exponent | sign; | |
1386 // return bititof(result); | |
1387 | 1356 |
1388 Node* int_input = Unop(wasm::kExprI32ReinterpretF32, input); | 1357 Node* WasmGraphBuilder::BuildF32Ceil(Node* input) { |
1389 Node* exponent = | 1358 MachineType type = MachineType::Float32(); |
1390 Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x7f800000)); | 1359 ExternalReference ref = |
| 1360 ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate()); |
| 1361 return BuildRoundingInstruction(input, ref, type); |
| 1362 } |
1391 | 1363 |
1392 Node* sign = | 1364 Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) { |
1393 Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x80000000)); | 1365 MachineType type = MachineType::Float32(); |
1394 | 1366 ExternalReference ref = |
1395 Node* result_out_of_range = int_input; | 1367 ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate()); |
1396 | 1368 return BuildRoundingInstruction(input, ref, type); |
1397 Node* result_nan = | |
1398 Binop(wasm::kExprI32Ior, int_input, jsgraph()->Int32Constant(1 << 22)); | |
1399 | |
1400 Node* result_zero = sign; | |
1401 | |
1402 Node* mantissa = | |
1403 Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x007fffff)); | |
1404 Node* shift = | |
1405 Binop(wasm::kExprI32Sub, jsgraph()->Int32Constant(23 + 127), | |
1406 Binop(wasm::kExprI32ShrU, exponent, jsgraph()->Int32Constant(23))); | |
1407 Node* new_mantissa = Binop(wasm::kExprI32Shl, | |
1408 Binop(wasm::kExprI32ShrU, mantissa, shift), shift); | |
1409 Node* result_truncate = | |
1410 Binop(wasm::kExprI32Ior, Binop(wasm::kExprI32Ior, new_mantissa, exponent), | |
1411 sign); | |
1412 | |
1413 Diamond is_zero( | |
1414 graph(), jsgraph()->common(), | |
1415 Binop(wasm::kExprI32LtU, exponent, jsgraph()->Int32Constant(127 << 23))); | |
1416 | |
1417 Node* result_within_range = | |
1418 is_zero.Phi(wasm::kAstI32, result_zero, result_truncate); | |
1419 | |
1420 Diamond input_nan(graph(), jsgraph()->common(), | |
1421 Binop(wasm::kExprF32Ne, input, input)); | |
1422 Node* result_exponent_geq_23 = | |
1423 input_nan.Phi(wasm::kAstI32, result_nan, result_out_of_range); | |
1424 | |
1425 Diamond exponent_geq_23(graph(), jsgraph()->common(), | |
1426 Binop(wasm::kExprI32GeU, exponent, | |
1427 jsgraph()->Int32Constant((23 + 127) << 23))); | |
1428 | |
1429 Node* result = exponent_geq_23.Phi(wasm::kAstI32, result_exponent_geq_23, | |
1430 result_within_range); | |
1431 | |
1432 return Unop(wasm::kExprF32ReinterpretI32, result); | |
1433 } | 1369 } |
1434 | 1370 |
1435 Node* WasmGraphBuilder::BuildF64Trunc(Node* input) { | 1371 Node* WasmGraphBuilder::BuildF64Trunc(Node* input) { |
| 1372 MachineType type = MachineType::Float64(); |
| 1373 ExternalReference ref = |
| 1374 ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate()); |
| 1375 return BuildRoundingInstruction(input, ref, type); |
| 1376 } |
| 1377 |
| 1378 Node* WasmGraphBuilder::BuildF64Floor(Node* input) { |
| 1379 MachineType type = MachineType::Float64(); |
| 1380 ExternalReference ref = |
| 1381 ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate()); |
| 1382 return BuildRoundingInstruction(input, ref, type); |
| 1383 } |
| 1384 |
| 1385 Node* WasmGraphBuilder::BuildF64Ceil(Node* input) { |
| 1386 MachineType type = MachineType::Float64(); |
| 1387 ExternalReference ref = |
| 1388 ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate()); |
| 1389 return BuildRoundingInstruction(input, ref, type); |
| 1390 } |
| 1391 |
| 1392 Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) { |
| 1393 MachineType type = MachineType::Float64(); |
| 1394 ExternalReference ref = |
| 1395 ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate()); |
| 1396 return BuildRoundingInstruction(input, ref, type); |
| 1397 } |
| 1398 |
| 1399 Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input, |
| 1400 ExternalReference ref, |
| 1401 MachineType type) { |
1436 // We do truncation by calling a C function which calculates the truncation | 1402 // We do truncation by calling a C function which calculates the truncation |
1437 // for us. The input is passed to the C function as a double* to avoid double | 1403 // for us. The input is passed to the C function as a double* to avoid double |
1438 // parameters. For this we reserve a slot on the stack, store the parameter in | 1404 // parameters. For this we reserve a slot on the stack, store the parameter in |
1439 // that slot, pass a pointer to the slot to the C function, and after calling | 1405 // that slot, pass a pointer to the slot to the C function, and after calling |
1440 // the C function we collect the return value from the stack slot. | 1406 // the C function we collect the return value from the stack slot. |
1441 | 1407 |
1442 Node* stack_slot_param = graph()->NewNode( | 1408 Node* stack_slot_param = |
1443 jsgraph()->machine()->StackSlot(MachineRepresentation::kFloat64)); | 1409 graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation())); |
1444 | 1410 |
1445 const Operator* store_op = jsgraph()->machine()->Store( | 1411 const Operator* store_op = jsgraph()->machine()->Store( |
1446 StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier)); | 1412 StoreRepresentation(type.representation(), kNoWriteBarrier)); |
1447 *effect_ = | 1413 *effect_ = |
1448 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), | 1414 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), |
1449 input, *effect_, *control_); | 1415 input, *effect_, *control_); |
1450 | 1416 |
1451 Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1); | 1417 Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1); |
1452 sig_builder.AddParam(MachineType::Pointer()); | 1418 sig_builder.AddParam(MachineType::Pointer()); |
1453 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant( | 1419 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
1454 ExternalReference::trunc64_wrapper_function(jsgraph()->isolate()))); | |
1455 | 1420 |
1456 Node* args[] = {function, stack_slot_param}; | 1421 Node* args[] = {function, stack_slot_param}; |
1457 | 1422 |
1458 BuildCCall(sig_builder.Build(), args); | 1423 BuildCCall(sig_builder.Build(), args); |
1459 | 1424 |
1460 const Operator* load_op = jsgraph()->machine()->Load(MachineType::Float64()); | 1425 const Operator* load_op = jsgraph()->machine()->Load(type); |
1461 | 1426 |
1462 Node* load = | 1427 Node* load = |
1463 graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0), | 1428 graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0), |
1464 *effect_, *control_); | 1429 *effect_, *control_); |
1465 *effect_ = load; | 1430 *effect_ = load; |
1466 return load; | 1431 return load; |
1467 } | 1432 } |
1468 | 1433 |
1469 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { | 1434 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
1470 const size_t params = sig->parameter_count(); | 1435 const size_t params = sig->parameter_count(); |
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2165 module_env->module->GetName(function.name_offset)); | 2130 module_env->module->GetName(function.name_offset)); |
2166 } | 2131 } |
2167 | 2132 |
2168 return code; | 2133 return code; |
2169 } | 2134 } |
2170 | 2135 |
2171 | 2136 |
2172 } // namespace compiler | 2137 } // namespace compiler |
2173 } // namespace internal | 2138 } // namespace internal |
2174 } // namespace v8 | 2139 } // namespace v8 |
OLD | NEW |