|
14 | 14 | #include "ARMFrameLowering.h"
|
15 | 15 | #include "ARMBaseInstrInfo.h"
|
16 | 16 | #include "ARMBaseRegisterInfo.h"
|
| 17 | +#include "ARMConstantPoolValue.h" |
17 | 18 | #include "ARMInstrInfo.h"
|
18 | 19 | #include "ARMMachineFunctionInfo.h"
|
19 | 20 | #include "ARMTargetMachine.h"
|
@@ -1481,10 +1482,20 @@ static uint32_t AlignToARMConstant(uint32_t Value) {
|
1481 | 1482 | // stack limit.
|
1482 | 1483 | static const uint64_t kSplitStackAvailable = 256;
|
1483 | 1484 |
|
| 1485 | +void |
| 1486 | +ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { |
| 1487 | + const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>(); |
| 1488 | + if(ST->isThumb()) { |
| 1489 | + adjustForSegmentedStacksThumb(MF); |
| 1490 | + } else { |
| 1491 | + adjustForSegmentedStacksARM(MF); |
| 1492 | + } |
| 1493 | +} |
| 1494 | + |
1484 | 1495 | // Adjust function prologue to enable split stack.
|
1485 | 1496 | // Only support android and linux.
|
1486 | 1497 | void
|
1487 |
| -ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { |
| 1498 | +ARMFrameLowering::adjustForSegmentedStacksARM(MachineFunction &MF) const { |
1488 | 1499 | const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>();
|
1489 | 1500 |
|
1490 | 1501 | // Doesn't support vararg function.
|
@@ -1697,3 +1708,168 @@ ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
|
1697 | 1708 | MF.verify();
|
1698 | 1709 | #endif
|
1699 | 1710 | }
|
| 1711 | + |
| 1712 | +void |
| 1713 | +ARMFrameLowering::adjustForSegmentedStacksThumb(MachineFunction &MF) const { |
| 1714 | +// const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>(); |
| 1715 | + |
| 1716 | + // Doesn't support vararg function. |
| 1717 | + if (MF.getFunction()->isVarArg()) |
| 1718 | + report_fatal_error("Segmented stacks do not support vararg functions."); |
| 1719 | + |
| 1720 | + MachineBasicBlock &prologueMBB = MF.front(); |
| 1721 | + MachineFrameInfo* MFI = MF.getFrameInfo(); |
| 1722 | + const ARMBaseInstrInfo &TII = *TM.getInstrInfo(); |
| 1723 | + ARMFunctionInfo* ARMFI = MF.getInfo<ARMFunctionInfo>(); |
| 1724 | + DebugLoc DL; |
| 1725 | + |
| 1726 | + // Use R4 and R5 as scratch register. |
| 1727 | + // We should save R4 and R5 before use it and restore before |
| 1728 | + // leave the function. |
| 1729 | + unsigned ScratchReg0 = ARM::R4; |
| 1730 | + unsigned ScratchReg1 = ARM::R5; |
| 1731 | + uint64_t AlignedStackSize; |
| 1732 | + |
| 1733 | + MachineBasicBlock* prevStackMBB = MF.CreateMachineBasicBlock(); |
| 1734 | + MachineBasicBlock* postStackMBB = MF.CreateMachineBasicBlock(); |
| 1735 | + MachineBasicBlock* allocMBB = MF.CreateMachineBasicBlock(); |
| 1736 | + MachineBasicBlock* getMBB = MF.CreateMachineBasicBlock(); |
| 1737 | + MachineBasicBlock* mcrMBB = MF.CreateMachineBasicBlock(); |
| 1738 | + |
| 1739 | + for (MachineBasicBlock::livein_iterator i = prologueMBB.livein_begin(), |
| 1740 | + e = prologueMBB.livein_end(); i != e; ++i) { |
| 1741 | + allocMBB->addLiveIn(*i); |
| 1742 | + getMBB->addLiveIn(*i); |
| 1743 | + mcrMBB->addLiveIn(*i); |
| 1744 | + prevStackMBB->addLiveIn(*i); |
| 1745 | + postStackMBB->addLiveIn(*i); |
| 1746 | + } |
| 1747 | + |
| 1748 | + MF.push_front(postStackMBB); |
| 1749 | + MF.push_front(allocMBB); |
| 1750 | + MF.push_front(getMBB); |
| 1751 | + MF.push_front(mcrMBB); |
| 1752 | + MF.push_front(prevStackMBB); |
| 1753 | + |
| 1754 | + // The required stack size that is aligend to ARM constant critarion. |
| 1755 | + uint64_t StackSize = MFI->getStackSize(); |
| 1756 | + |
| 1757 | + AlignedStackSize = AlignToARMConstant(StackSize); |
| 1758 | + |
| 1759 | + // When the frame size is less than 256 we just compare the stack |
| 1760 | + // boundary directly to the value of the stack pointer, per gcc. |
| 1761 | + bool CompareStackPointer = AlignedStackSize < kSplitStackAvailable; |
| 1762 | + |
| 1763 | + // We will use two of callee save registers as scratch register so we |
| 1764 | + // need to save those registers into stack frame before use it. |
| 1765 | + // We will use SR0 to hold stack limit and SR1 to stack size requested. |
| 1766 | + // and arguments for __morestack(). |
| 1767 | + // SR0: Scratch Register #0 |
| 1768 | + // SR1: Scratch Register #1 |
| 1769 | + // push {SR0, SR1} |
| 1770 | + AddDefaultPred(BuildMI(prevStackMBB, DL, TII.get(ARM::tPUSH))) |
| 1771 | + .addReg(ScratchReg0) |
| 1772 | + .addReg(ScratchReg1); |
| 1773 | + |
| 1774 | + // mov SR1, sp |
| 1775 | + AddDefaultPred(BuildMI(mcrMBB, DL, TII.get(ARM::tMOVr), ScratchReg1) |
| 1776 | + .addReg(ARM::SP)); |
| 1777 | + |
| 1778 | + if (!CompareStackPointer) { |
| 1779 | + // sub SR1, #StackSize |
| 1780 | + AddDefaultPred(AddDefaultCC(BuildMI(mcrMBB, DL, TII.get(ARM::tSUBi8), ScratchReg1)) |
| 1781 | + .addReg(ScratchReg1).addImm(AlignedStackSize)); |
| 1782 | + } |
| 1783 | + |
| 1784 | + unsigned PCLabelId = ARMFI->createPICLabelUId(); |
| 1785 | + ARMConstantPoolValue *NewCPV = ARMConstantPoolSymbol:: |
| 1786 | + Create(MF.getFunction()->getContext(), "STACK_LIMIT", PCLabelId, 0); |
| 1787 | + MachineConstantPool *MCP = MF.getConstantPool(); |
| 1788 | + unsigned CPI = MCP->getConstantPoolIndex(NewCPV, MF.getAlignment()); |
| 1789 | + |
| 1790 | + //ldr SR0, [pc, offset(STACK_LIMIT)] |
| 1791 | + AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::tLDRpci), ScratchReg0) |
| 1792 | + .addConstantPoolIndex(CPI)); |
| 1793 | + |
| 1794 | + //ldr SR0, [SR0] |
| 1795 | + AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::tLDRi), ScratchReg0) |
| 1796 | + .addReg(ScratchReg0) |
| 1797 | + .addImm(0)); |
| 1798 | + |
| 1799 | + // Compare stack limit with stack size requested. |
| 1800 | + // cmp SR0, SR1 |
| 1801 | + AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::tCMPr)) |
| 1802 | + .addReg(ScratchReg0) |
| 1803 | + .addReg(ScratchReg1)); |
| 1804 | + |
| 1805 | + // This jump is taken if StackLimit < SP - stack required. |
| 1806 | + BuildMI(getMBB, DL, TII.get(ARM::tBcc)) |
| 1807 | + .addMBB(postStackMBB) |
| 1808 | + .addImm(ARMCC::LO) |
| 1809 | + .addReg(ARM::CPSR); |
| 1810 | + |
| 1811 | + |
| 1812 | + // Calling __morestack(StackSize, Size of stack arguments). |
| 1813 | + // __morestack knows that the stack size requested is in SR0(r4) |
| 1814 | + // and amount size of stack arguments is in SR1(r5). |
| 1815 | + |
| 1816 | + // Pass first argument for the __morestack by Scratch Register #0. |
| 1817 | + // The amount size of stack required |
| 1818 | + AddDefaultPred(AddDefaultCC(BuildMI(allocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg0)) |
| 1819 | + .addImm(AlignedStackSize)); |
| 1820 | + // Pass second argument for the __morestack by Scratch Register #1. |
| 1821 | + // The amount size of stack consumed to save function arguments. |
| 1822 | + AddDefaultPred(AddDefaultCC(BuildMI(allocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg1)) |
| 1823 | + .addImm(AlignToARMConstant(ARMFI->getArgumentStackSize()))); |
| 1824 | + |
| 1825 | + // push {lr} - Save return address of this function. |
| 1826 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPUSH))) |
| 1827 | + .addReg(ARM::LR); |
| 1828 | + |
| 1829 | + // Call __morestack(). |
| 1830 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tBL))) |
| 1831 | + .addExternalSymbol("__morestack"); |
| 1832 | + |
| 1833 | + // Restore return address of this original function. |
| 1834 | + // pop {SR0} |
| 1835 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPOP))) |
| 1836 | + .addReg(ScratchReg0); |
| 1837 | + |
| 1838 | + // mov lr, SR0 |
| 1839 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tMOVr), ARM::LR) |
| 1840 | + .addReg(ScratchReg0)); |
| 1841 | + |
| 1842 | + // Restore SR0 and SR1 in case of __morestack() was called. |
| 1843 | + // __morestack() will skip postStackMBB block so we need to restore |
| 1844 | + // scratch registers from here. |
| 1845 | + // pop {SR0, SR1} |
| 1846 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPOP))) |
| 1847 | + .addReg(ScratchReg0) |
| 1848 | + .addReg(ScratchReg1); |
| 1849 | + |
| 1850 | + // Return from this function. |
| 1851 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tMOVr), ARM::PC) |
| 1852 | + .addReg(ARM::LR)); |
| 1853 | + |
| 1854 | + // Restore SR0 and SR1 in case of __morestack() was not called. |
| 1855 | + // pop {SR0, SR1} |
| 1856 | + AddDefaultPred(BuildMI(postStackMBB, DL, TII.get(ARM::tPOP))) |
| 1857 | + .addReg(ScratchReg0) |
| 1858 | + .addReg(ScratchReg1); |
| 1859 | + |
| 1860 | + // Organizing MBB lists |
| 1861 | + postStackMBB->addSuccessor(&prologueMBB); |
| 1862 | + |
| 1863 | + allocMBB->addSuccessor(postStackMBB); |
| 1864 | + |
| 1865 | + getMBB->addSuccessor(postStackMBB); |
| 1866 | + getMBB->addSuccessor(allocMBB); |
| 1867 | + |
| 1868 | + mcrMBB->addSuccessor(getMBB); |
| 1869 | + |
| 1870 | + prevStackMBB->addSuccessor(mcrMBB); |
| 1871 | + |
| 1872 | +#ifdef XDEBUG |
| 1873 | + MF.verify(); |
| 1874 | +#endif |
| 1875 | +} |
0 commit comments