| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include "src/compilation-info.h" | 6 #include "src/compilation-info.h" |
| 7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
| 8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
| 9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
| 10 #include "src/compiler/osr.h" | 10 #include "src/compiler/osr.h" |
| (...skipping 1610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1621 return true; | 1621 return true; |
| 1622 case kUnsignedGreaterThan: | 1622 case kUnsignedGreaterThan: |
| 1623 cc = ugt; | 1623 cc = ugt; |
| 1624 return true; | 1624 return true; |
| 1625 default: | 1625 default: |
| 1626 break; | 1626 break; |
| 1627 } | 1627 } |
| 1628 return false; | 1628 return false; |
| 1629 } | 1629 } |
| 1630 | 1630 |
| 1631 void AssembleBranchToLabels(CodeGenerator* gen, MacroAssembler* masm, |
| 1632 Instruction* instr, FlagsCondition condition, |
| 1633 Label* tlabel, Label* flabel, bool fallthru) { |
| 1634 #undef __ |
| 1635 #define __ masm-> |
| 1631 | 1636 |
| 1632 // Assembles branches after an instruction. | |
| 1633 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | |
| 1634 MipsOperandConverter i(this, instr); | |
| 1635 Label* tlabel = branch->true_label; | |
| 1636 Label* flabel = branch->false_label; | |
| 1637 Condition cc = kNoCondition; | 1637 Condition cc = kNoCondition; |
| 1638 // MIPS does not have condition code flags, so compare and branch are | 1638 // MIPS does not have condition code flags, so compare and branch are |
| 1639 // implemented differently than on the other arch's. The compare operations | 1639 // implemented differently than on the other arch's. The compare operations |
| 1640 // emit mips pseudo-instructions, which are handled here by branch | 1640 // emit mips pseudo-instructions, which are handled here by branch |
| 1641 // instructions that do the actual comparison. Essential that the input | 1641 // instructions that do the actual comparison. Essential that the input |
| 1642 // registers to compare pseudo-op are not modified before this branch op, as | 1642 // registers to compare pseudo-op are not modified before this branch op, as |
| 1643 // they are tested here. | 1643 // they are tested here. |
| 1644 | 1644 |
| 1645 MipsOperandConverter i(gen, instr); |
| 1645 if (instr->arch_opcode() == kMipsTst) { | 1646 if (instr->arch_opcode() == kMipsTst) { |
| 1646 cc = FlagsConditionToConditionTst(branch->condition); | 1647 cc = FlagsConditionToConditionTst(condition); |
| 1647 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 1648 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 1648 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 1649 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
| 1649 } else if (instr->arch_opcode() == kMipsAddOvf) { | 1650 } else if (instr->arch_opcode() == kMipsAddOvf) { |
| 1650 switch (branch->condition) { | 1651 switch (condition) { |
| 1651 case kOverflow: | 1652 case kOverflow: |
| 1652 __ AddBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1653 __ AddBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1653 i.InputOperand(1), tlabel, flabel); | 1654 i.InputOperand(1), tlabel, flabel); |
| 1654 break; | 1655 break; |
| 1655 case kNotOverflow: | 1656 case kNotOverflow: |
| 1656 __ AddBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1657 __ AddBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1657 i.InputOperand(1), flabel, tlabel); | 1658 i.InputOperand(1), flabel, tlabel); |
| 1658 break; | 1659 break; |
| 1659 default: | 1660 default: |
| 1660 UNSUPPORTED_COND(kMipsAddOvf, branch->condition); | 1661 UNSUPPORTED_COND(kMipsAddOvf, condition); |
| 1661 break; | 1662 break; |
| 1662 } | 1663 } |
| 1663 } else if (instr->arch_opcode() == kMipsSubOvf) { | 1664 } else if (instr->arch_opcode() == kMipsSubOvf) { |
| 1664 switch (branch->condition) { | 1665 switch (condition) { |
| 1665 case kOverflow: | 1666 case kOverflow: |
| 1666 __ SubBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1667 __ SubBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1667 i.InputOperand(1), tlabel, flabel); | 1668 i.InputOperand(1), tlabel, flabel); |
| 1668 break; | 1669 break; |
| 1669 case kNotOverflow: | 1670 case kNotOverflow: |
| 1670 __ SubBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1671 __ SubBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1671 i.InputOperand(1), flabel, tlabel); | 1672 i.InputOperand(1), flabel, tlabel); |
| 1672 break; | 1673 break; |
| 1673 default: | 1674 default: |
| 1674 UNSUPPORTED_COND(kMipsAddOvf, branch->condition); | 1675 UNSUPPORTED_COND(kMipsAddOvf, condition); |
| 1675 break; | 1676 break; |
| 1676 } | 1677 } |
| 1677 } else if (instr->arch_opcode() == kMipsMulOvf) { | 1678 } else if (instr->arch_opcode() == kMipsMulOvf) { |
| 1678 switch (branch->condition) { | 1679 switch (condition) { |
| 1679 case kOverflow: | 1680 case kOverflow: |
| 1680 __ MulBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1681 __ MulBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1681 i.InputOperand(1), tlabel, flabel); | 1682 i.InputOperand(1), tlabel, flabel); |
| 1682 break; | 1683 break; |
| 1683 case kNotOverflow: | 1684 case kNotOverflow: |
| 1684 __ MulBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1685 __ MulBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1685 i.InputOperand(1), flabel, tlabel); | 1686 i.InputOperand(1), flabel, tlabel); |
| 1686 break; | 1687 break; |
| 1687 default: | 1688 default: |
| 1688 UNSUPPORTED_COND(kMipsMulOvf, branch->condition); | 1689 UNSUPPORTED_COND(kMipsMulOvf, condition); |
| 1689 break; | 1690 break; |
| 1690 } | 1691 } |
| 1691 } else if (instr->arch_opcode() == kMipsCmp) { | 1692 } else if (instr->arch_opcode() == kMipsCmp) { |
| 1692 cc = FlagsConditionToConditionCmp(branch->condition); | 1693 cc = FlagsConditionToConditionCmp(condition); |
| 1693 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); | 1694 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
| 1694 } else if (instr->arch_opcode() == kMipsCmpS) { | 1695 } else if (instr->arch_opcode() == kMipsCmpS) { |
| 1695 if (!convertCondition(branch->condition, cc)) { | 1696 if (!convertCondition(condition, cc)) { |
| 1696 UNSUPPORTED_COND(kMips64CmpS, branch->condition); | 1697 UNSUPPORTED_COND(kMips64CmpS, condition); |
| 1697 } | 1698 } |
| 1698 FPURegister left = i.InputOrZeroSingleRegister(0); | 1699 FPURegister left = i.InputOrZeroSingleRegister(0); |
| 1699 FPURegister right = i.InputOrZeroSingleRegister(1); | 1700 FPURegister right = i.InputOrZeroSingleRegister(1); |
| 1700 if ((left.is(kDoubleRegZero) || right.is(kDoubleRegZero)) && | 1701 if ((left.is(kDoubleRegZero) || right.is(kDoubleRegZero)) && |
| 1701 !__ IsDoubleZeroRegSet()) { | 1702 !__ IsDoubleZeroRegSet()) { |
| 1702 __ Move(kDoubleRegZero, 0.0); | 1703 __ Move(kDoubleRegZero, 0.0); |
| 1703 } | 1704 } |
| 1704 __ BranchF32(tlabel, nullptr, cc, left, right); | 1705 __ BranchF32(tlabel, nullptr, cc, left, right); |
| 1705 } else if (instr->arch_opcode() == kMipsCmpD) { | 1706 } else if (instr->arch_opcode() == kMipsCmpD) { |
| 1706 if (!convertCondition(branch->condition, cc)) { | 1707 if (!convertCondition(condition, cc)) { |
| 1707 UNSUPPORTED_COND(kMips64CmpD, branch->condition); | 1708 UNSUPPORTED_COND(kMips64CmpD, condition); |
| 1708 } | 1709 } |
| 1709 FPURegister left = i.InputOrZeroDoubleRegister(0); | 1710 FPURegister left = i.InputOrZeroDoubleRegister(0); |
| 1710 FPURegister right = i.InputOrZeroDoubleRegister(1); | 1711 FPURegister right = i.InputOrZeroDoubleRegister(1); |
| 1711 if ((left.is(kDoubleRegZero) || right.is(kDoubleRegZero)) && | 1712 if ((left.is(kDoubleRegZero) || right.is(kDoubleRegZero)) && |
| 1712 !__ IsDoubleZeroRegSet()) { | 1713 !__ IsDoubleZeroRegSet()) { |
| 1713 __ Move(kDoubleRegZero, 0.0); | 1714 __ Move(kDoubleRegZero, 0.0); |
| 1714 } | 1715 } |
| 1715 __ BranchF64(tlabel, nullptr, cc, left, right); | 1716 __ BranchF64(tlabel, nullptr, cc, left, right); |
| 1716 } else { | 1717 } else { |
| 1717 PrintF("AssembleArchBranch Unimplemented arch_opcode: %d\n", | 1718 PrintF("AssembleArchBranch Unimplemented arch_opcode: %d\n", |
| 1718 instr->arch_opcode()); | 1719 instr->arch_opcode()); |
| 1719 UNIMPLEMENTED(); | 1720 UNIMPLEMENTED(); |
| 1720 } | 1721 } |
| 1721 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. | 1722 if (!fallthru) __ Branch(flabel); // no fallthru to flabel. |
| 1723 #undef __ |
| 1724 #define __ masm()-> |
| 1725 } |
| 1726 |
| 1727 // Assembles branches after an instruction. |
| 1728 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 1729 Label* tlabel = branch->true_label; |
| 1730 Label* flabel = branch->false_label; |
| 1731 AssembleBranchToLabels(this, masm(), instr, branch->condition, tlabel, flabel, |
| 1732 branch->fallthru); |
| 1722 } | 1733 } |
| 1723 | 1734 |
| 1724 | 1735 |
| 1725 void CodeGenerator::AssembleArchJump(RpoNumber target) { | 1736 void CodeGenerator::AssembleArchJump(RpoNumber target) { |
| 1726 if (!IsNextInAssemblyOrder(target)) __ Branch(GetLabel(target)); | 1737 if (!IsNextInAssemblyOrder(target)) __ Branch(GetLabel(target)); |
| 1727 } | 1738 } |
| 1728 | 1739 |
| 1729 void CodeGenerator::AssembleArchTrap(Instruction* instr, | 1740 void CodeGenerator::AssembleArchTrap(Instruction* instr, |
| 1730 FlagsCondition condition) { | 1741 FlagsCondition condition) { |
| 1731 UNREACHABLE(); | 1742 class OutOfLineTrap final : public OutOfLineCode { |
| 1743 public: |
| 1744 OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr) |
| 1745 : OutOfLineCode(gen), |
| 1746 frame_elided_(frame_elided), |
| 1747 instr_(instr), |
| 1748 gen_(gen) {} |
| 1749 |
| 1750 void Generate() final { |
| 1751 MipsOperandConverter i(gen_, instr_); |
| 1752 |
| 1753 Runtime::FunctionId trap_id = static_cast<Runtime::FunctionId>( |
| 1754 i.InputInt32(instr_->InputCount() - 1)); |
| 1755 bool old_has_frame = __ has_frame(); |
| 1756 if (frame_elided_) { |
| 1757 __ set_has_frame(true); |
| 1758 __ EnterFrame(StackFrame::WASM_COMPILED); |
| 1759 } |
| 1760 GenerateCallToTrap(trap_id); |
| 1761 if (frame_elided_) { |
| 1762 __ set_has_frame(old_has_frame); |
| 1763 } |
| 1764 if (FLAG_debug_code) { |
| 1765 __ stop(GetBailoutReason(kUnexpectedReturnFromWasmTrap)); |
| 1766 } |
| 1767 } |
| 1768 |
| 1769 private: |
| 1770 void GenerateCallToTrap(Runtime::FunctionId trap_id) { |
| 1771 if (trap_id == Runtime::kNumFunctions) { |
| 1772 // We cannot test calls to the runtime in cctest/test-run-wasm. |
| 1773 // Therefore we emit a call to C here instead of a call to the runtime. |
| 1774 // We use the context register as the scratch register, because we do |
| 1775 // not have a context here. |
| 1776 __ PrepareCallCFunction(0, 0, cp); |
| 1777 __ CallCFunction( |
| 1778 ExternalReference::wasm_call_trap_callback_for_testing(isolate()), |
| 1779 0); |
| 1780 } else { |
| 1781 __ Move(cp, isolate()->native_context()); |
| 1782 gen_->AssembleSourcePosition(instr_); |
| 1783 __ CallRuntime(trap_id); |
| 1784 } |
| 1785 ReferenceMap* reference_map = |
| 1786 new (gen_->zone()) ReferenceMap(gen_->zone()); |
| 1787 gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, |
| 1788 Safepoint::kNoLazyDeopt); |
| 1789 } |
| 1790 |
| 1791 bool frame_elided_; |
| 1792 Instruction* instr_; |
| 1793 CodeGenerator* gen_; |
| 1794 }; |
| 1795 bool frame_elided = !frame_access_state()->has_frame(); |
| 1796 auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr); |
| 1797 Label* tlabel = ool->entry(); |
| 1798 AssembleBranchToLabels(this, masm(), instr, condition, tlabel, nullptr, true); |
| 1732 } | 1799 } |
| 1733 | 1800 |
| 1734 // Assembles boolean materializations after an instruction. | 1801 // Assembles boolean materializations after an instruction. |
| 1735 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 1802 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
| 1736 FlagsCondition condition) { | 1803 FlagsCondition condition) { |
| 1737 MipsOperandConverter i(this, instr); | 1804 MipsOperandConverter i(this, instr); |
| 1738 Label done; | 1805 Label done; |
| 1739 | 1806 |
| 1740 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 1807 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
| 1741 // last output of the instruction. | 1808 // last output of the instruction. |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2306 padding_size -= v8::internal::Assembler::kInstrSize; | 2373 padding_size -= v8::internal::Assembler::kInstrSize; |
| 2307 } | 2374 } |
| 2308 } | 2375 } |
| 2309 } | 2376 } |
| 2310 | 2377 |
| 2311 #undef __ | 2378 #undef __ |
| 2312 | 2379 |
| 2313 } // namespace compiler | 2380 } // namespace compiler |
| 2314 } // namespace internal | 2381 } // namespace internal |
| 2315 } // namespace v8 | 2382 } // namespace v8 |
| OLD | NEW |