OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/compilation-info.h" | 7 #include "src/compilation-info.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 1590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1601 case kAtomicLoadWord32: | 1601 case kAtomicLoadWord32: |
1602 case kAtomicStoreWord8: | 1602 case kAtomicStoreWord8: |
1603 case kAtomicStoreWord16: | 1603 case kAtomicStoreWord16: |
1604 case kAtomicStoreWord32: | 1604 case kAtomicStoreWord32: |
1605 UNREACHABLE(); // Won't be generated by instruction selector. | 1605 UNREACHABLE(); // Won't be generated by instruction selector. |
1606 break; | 1606 break; |
1607 } | 1607 } |
1608 return kSuccess; | 1608 return kSuccess; |
1609 } // NOLINT(readability/fn_size) | 1609 } // NOLINT(readability/fn_size) |
1610 | 1610 |
| 1611 static Condition FlagsConditionToCondition(FlagsCondition condition) { |
| 1612 switch (condition) { |
| 1613 case kUnorderedEqual: |
| 1614 case kEqual: |
| 1615 return equal; |
| 1616 break; |
| 1617 case kUnorderedNotEqual: |
| 1618 case kNotEqual: |
| 1619 return not_equal; |
| 1620 break; |
| 1621 case kSignedLessThan: |
| 1622 return less; |
| 1623 break; |
| 1624 case kSignedGreaterThanOrEqual: |
| 1625 return greater_equal; |
| 1626 break; |
| 1627 case kSignedLessThanOrEqual: |
| 1628 return less_equal; |
| 1629 break; |
| 1630 case kSignedGreaterThan: |
| 1631 return greater; |
| 1632 break; |
| 1633 case kUnsignedLessThan: |
| 1634 return below; |
| 1635 break; |
| 1636 case kUnsignedGreaterThanOrEqual: |
| 1637 return above_equal; |
| 1638 break; |
| 1639 case kUnsignedLessThanOrEqual: |
| 1640 return below_equal; |
| 1641 break; |
| 1642 case kUnsignedGreaterThan: |
| 1643 return above; |
| 1644 break; |
| 1645 case kOverflow: |
| 1646 return overflow; |
| 1647 break; |
| 1648 case kNotOverflow: |
| 1649 return no_overflow; |
| 1650 break; |
| 1651 default: |
| 1652 UNREACHABLE(); |
| 1653 return no_condition; |
| 1654 break; |
| 1655 } |
| 1656 } |
1611 | 1657 |
1612 // Assembles a branch after an instruction. | 1658 // Assembles a branch after an instruction. |
1613 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 1659 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
1614 IA32OperandConverter i(this, instr); | |
1615 Label::Distance flabel_distance = | 1660 Label::Distance flabel_distance = |
1616 branch->fallthru ? Label::kNear : Label::kFar; | 1661 branch->fallthru ? Label::kNear : Label::kFar; |
1617 Label* tlabel = branch->true_label; | 1662 Label* tlabel = branch->true_label; |
1618 Label* flabel = branch->false_label; | 1663 Label* flabel = branch->false_label; |
1619 switch (branch->condition) { | 1664 if (branch->condition == kUnorderedEqual) { |
1620 case kUnorderedEqual: | 1665 __ j(parity_even, flabel, flabel_distance); |
1621 __ j(parity_even, flabel, flabel_distance); | 1666 } else if (branch->condition == kUnorderedNotEqual) { |
1622 // Fall through. | 1667 __ j(parity_even, tlabel); |
1623 case kEqual: | |
1624 __ j(equal, tlabel); | |
1625 break; | |
1626 case kUnorderedNotEqual: | |
1627 __ j(parity_even, tlabel); | |
1628 // Fall through. | |
1629 case kNotEqual: | |
1630 __ j(not_equal, tlabel); | |
1631 break; | |
1632 case kSignedLessThan: | |
1633 __ j(less, tlabel); | |
1634 break; | |
1635 case kSignedGreaterThanOrEqual: | |
1636 __ j(greater_equal, tlabel); | |
1637 break; | |
1638 case kSignedLessThanOrEqual: | |
1639 __ j(less_equal, tlabel); | |
1640 break; | |
1641 case kSignedGreaterThan: | |
1642 __ j(greater, tlabel); | |
1643 break; | |
1644 case kUnsignedLessThan: | |
1645 __ j(below, tlabel); | |
1646 break; | |
1647 case kUnsignedGreaterThanOrEqual: | |
1648 __ j(above_equal, tlabel); | |
1649 break; | |
1650 case kUnsignedLessThanOrEqual: | |
1651 __ j(below_equal, tlabel); | |
1652 break; | |
1653 case kUnsignedGreaterThan: | |
1654 __ j(above, tlabel); | |
1655 break; | |
1656 case kOverflow: | |
1657 __ j(overflow, tlabel); | |
1658 break; | |
1659 case kNotOverflow: | |
1660 __ j(no_overflow, tlabel); | |
1661 break; | |
1662 default: | |
1663 UNREACHABLE(); | |
1664 break; | |
1665 } | 1668 } |
| 1669 __ j(FlagsConditionToCondition(branch->condition), tlabel); |
| 1670 |
1666 // Add a jump if not falling through to the next block. | 1671 // Add a jump if not falling through to the next block. |
1667 if (!branch->fallthru) __ jmp(flabel); | 1672 if (!branch->fallthru) __ jmp(flabel); |
1668 } | 1673 } |
1669 | 1674 |
1670 | 1675 |
1671 void CodeGenerator::AssembleArchJump(RpoNumber target) { | 1676 void CodeGenerator::AssembleArchJump(RpoNumber target) { |
1672 if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target)); | 1677 if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target)); |
1673 } | 1678 } |
1674 | 1679 |
1675 void CodeGenerator::AssembleArchTrap(Instruction* instr, | 1680 void CodeGenerator::AssembleArchTrap(Instruction* instr, |
1676 FlagsCondition condition) { | 1681 FlagsCondition condition) { |
1677 UNREACHABLE(); | 1682 class OutOfLineTrap final : public OutOfLineCode { |
| 1683 public: |
| 1684 OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr) |
| 1685 : OutOfLineCode(gen), |
| 1686 frame_elided_(frame_elided), |
| 1687 instr_(instr), |
| 1688 gen_(gen) {} |
| 1689 |
| 1690 void Generate() final { |
| 1691 IA32OperandConverter i(gen_, instr_); |
| 1692 |
| 1693 Runtime::FunctionId trap_id = static_cast<Runtime::FunctionId>( |
| 1694 i.InputInt32(instr_->InputCount() - 1)); |
| 1695 bool old_has_frame = __ has_frame(); |
| 1696 if (frame_elided_) { |
| 1697 __ set_has_frame(true); |
| 1698 __ EnterFrame(StackFrame::WASM); |
| 1699 } |
| 1700 GenerateCallToTrap(trap_id); |
| 1701 if (frame_elided_) { |
| 1702 ReferenceMap* reference_map = |
| 1703 new (gen_->zone()) ReferenceMap(gen_->zone()); |
| 1704 gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, |
| 1705 Safepoint::kNoLazyDeopt); |
| 1706 __ set_has_frame(old_has_frame); |
| 1707 } |
| 1708 if (FLAG_debug_code) { |
| 1709 __ ud2(); |
| 1710 } |
| 1711 } |
| 1712 |
| 1713 private: |
| 1714 void GenerateCallToTrap(Runtime::FunctionId trap_id) { |
| 1715 if (trap_id == Runtime::kNumFunctions) { |
| 1716 // We cannot test calls to the runtime in cctest/test-run-wasm. |
| 1717 // Therefore we emit a call to C here instead of a call to the runtime. |
| 1718 __ PrepareCallCFunction(0, esi); |
| 1719 __ CallCFunction( |
| 1720 ExternalReference::wasm_call_trap_callback_for_testing(isolate()), |
| 1721 0); |
| 1722 } else { |
| 1723 __ Move(esi, isolate()->native_context()); |
| 1724 gen_->AssembleSourcePosition(instr_); |
| 1725 __ CallRuntime(trap_id); |
| 1726 } |
| 1727 } |
| 1728 |
| 1729 bool frame_elided_; |
| 1730 Instruction* instr_; |
| 1731 CodeGenerator* gen_; |
| 1732 }; |
| 1733 bool frame_elided = !frame_access_state()->has_frame(); |
| 1734 auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr); |
| 1735 Label* tlabel = ool->entry(); |
| 1736 Label end; |
| 1737 if (condition == kUnorderedEqual) { |
| 1738 __ j(parity_even, &end); |
| 1739 } else if (condition == kUnorderedNotEqual) { |
| 1740 __ j(parity_even, tlabel); |
| 1741 } |
| 1742 __ j(FlagsConditionToCondition(condition), tlabel); |
| 1743 __ bind(&end); |
1678 } | 1744 } |
1679 | 1745 |
1680 // Assembles boolean materializations after an instruction. | 1746 // Assembles boolean materializations after an instruction. |
1681 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 1747 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
1682 FlagsCondition condition) { | 1748 FlagsCondition condition) { |
1683 IA32OperandConverter i(this, instr); | 1749 IA32OperandConverter i(this, instr); |
1684 Label done; | 1750 Label done; |
1685 | 1751 |
1686 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 1752 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
1687 // last output of the instruction. | 1753 // last output of the instruction. |
1688 Label check; | 1754 Label check; |
1689 DCHECK_NE(0u, instr->OutputCount()); | 1755 DCHECK_NE(0u, instr->OutputCount()); |
1690 Register reg = i.OutputRegister(instr->OutputCount() - 1); | 1756 Register reg = i.OutputRegister(instr->OutputCount() - 1); |
1691 Condition cc = no_condition; | 1757 if (condition == kUnorderedEqual) { |
1692 switch (condition) { | 1758 __ j(parity_odd, &check, Label::kNear); |
1693 case kUnorderedEqual: | 1759 __ Move(reg, Immediate(0)); |
1694 __ j(parity_odd, &check, Label::kNear); | 1760 __ jmp(&done, Label::kNear); |
1695 __ Move(reg, Immediate(0)); | 1761 } else if (condition == kUnorderedNotEqual) { |
1696 __ jmp(&done, Label::kNear); | 1762 __ j(parity_odd, &check, Label::kNear); |
1697 // Fall through. | 1763 __ mov(reg, Immediate(1)); |
1698 case kEqual: | 1764 __ jmp(&done, Label::kNear); |
1699 cc = equal; | |
1700 break; | |
1701 case kUnorderedNotEqual: | |
1702 __ j(parity_odd, &check, Label::kNear); | |
1703 __ mov(reg, Immediate(1)); | |
1704 __ jmp(&done, Label::kNear); | |
1705 // Fall through. | |
1706 case kNotEqual: | |
1707 cc = not_equal; | |
1708 break; | |
1709 case kSignedLessThan: | |
1710 cc = less; | |
1711 break; | |
1712 case kSignedGreaterThanOrEqual: | |
1713 cc = greater_equal; | |
1714 break; | |
1715 case kSignedLessThanOrEqual: | |
1716 cc = less_equal; | |
1717 break; | |
1718 case kSignedGreaterThan: | |
1719 cc = greater; | |
1720 break; | |
1721 case kUnsignedLessThan: | |
1722 cc = below; | |
1723 break; | |
1724 case kUnsignedGreaterThanOrEqual: | |
1725 cc = above_equal; | |
1726 break; | |
1727 case kUnsignedLessThanOrEqual: | |
1728 cc = below_equal; | |
1729 break; | |
1730 case kUnsignedGreaterThan: | |
1731 cc = above; | |
1732 break; | |
1733 case kOverflow: | |
1734 cc = overflow; | |
1735 break; | |
1736 case kNotOverflow: | |
1737 cc = no_overflow; | |
1738 break; | |
1739 default: | |
1740 UNREACHABLE(); | |
1741 break; | |
1742 } | 1765 } |
| 1766 Condition cc = FlagsConditionToCondition(condition); |
| 1767 |
1743 __ bind(&check); | 1768 __ bind(&check); |
1744 if (reg.is_byte_register()) { | 1769 if (reg.is_byte_register()) { |
1745 // setcc for byte registers (al, bl, cl, dl). | 1770 // setcc for byte registers (al, bl, cl, dl). |
1746 __ setcc(cc, reg); | 1771 __ setcc(cc, reg); |
1747 __ movzx_b(reg, reg); | 1772 __ movzx_b(reg, reg); |
1748 } else { | 1773 } else { |
1749 // Emit a branch to set a register to either 1 or 0. | 1774 // Emit a branch to set a register to either 1 or 0. |
1750 Label set; | 1775 Label set; |
1751 __ j(cc, &set, Label::kNear); | 1776 __ j(cc, &set, Label::kNear); |
1752 __ Move(reg, Immediate(0)); | 1777 __ Move(reg, Immediate(0)); |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2278 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2303 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
2279 __ Nop(padding_size); | 2304 __ Nop(padding_size); |
2280 } | 2305 } |
2281 } | 2306 } |
2282 | 2307 |
2283 #undef __ | 2308 #undef __ |
2284 | 2309 |
2285 } // namespace compiler | 2310 } // namespace compiler |
2286 } // namespace internal | 2311 } // namespace internal |
2287 } // namespace v8 | 2312 } // namespace v8 |
OLD | NEW |