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