|
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"
|
@@ -1639,10 +1640,20 @@ static uint32_t AlignToARMConstant(uint32_t Value) {
|
1639 | 1640 | // stack limit.
|
1640 | 1641 | static const uint64_t kSplitStackAvailable = 256;
|
1641 | 1642 |
|
| 1643 | +void |
| 1644 | +ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { |
| 1645 | + const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>(); |
| 1646 | + if(ST->isThumb()) { |
| 1647 | + adjustForSegmentedStacksThumb(MF); |
| 1648 | + } else { |
| 1649 | + adjustForSegmentedStacksARM(MF); |
| 1650 | + } |
| 1651 | +} |
| 1652 | + |
1642 | 1653 | // Adjust function prologue to enable split stack.
|
1643 | 1654 | // Only support android and linux.
|
1644 | 1655 | void
|
1645 |
| -ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { |
| 1656 | +ARMFrameLowering::adjustForSegmentedStacksARM(MachineFunction &MF) const { |
1646 | 1657 | const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>();
|
1647 | 1658 |
|
1648 | 1659 | // Doesn't support vararg function.
|
@@ -1855,3 +1866,168 @@ ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
|
1855 | 1866 | MF.verify();
|
1856 | 1867 | #endif
|
1857 | 1868 | }
|
| 1869 | + |
| 1870 | +void |
| 1871 | +ARMFrameLowering::adjustForSegmentedStacksThumb(MachineFunction &MF) const { |
| 1872 | +// const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>(); |
| 1873 | + |
| 1874 | + // Doesn't support vararg function. |
| 1875 | + if (MF.getFunction()->isVarArg()) |
| 1876 | + report_fatal_error("Segmented stacks do not support vararg functions."); |
| 1877 | + |
| 1878 | + MachineBasicBlock &prologueMBB = MF.front(); |
| 1879 | + MachineFrameInfo* MFI = MF.getFrameInfo(); |
| 1880 | + const ARMBaseInstrInfo &TII = *TM.getInstrInfo(); |
| 1881 | + ARMFunctionInfo* ARMFI = MF.getInfo<ARMFunctionInfo>(); |
| 1882 | + DebugLoc DL; |
| 1883 | + |
| 1884 | + // Use R4 and R5 as scratch register. |
| 1885 | + // We should save R4 and R5 before use it and restore before |
| 1886 | + // leave the function. |
| 1887 | + unsigned ScratchReg0 = ARM::R4; |
| 1888 | + unsigned ScratchReg1 = ARM::R5; |
| 1889 | + uint64_t AlignedStackSize; |
| 1890 | + |
| 1891 | + MachineBasicBlock* prevStackMBB = MF.CreateMachineBasicBlock(); |
| 1892 | + MachineBasicBlock* postStackMBB = MF.CreateMachineBasicBlock(); |
| 1893 | + MachineBasicBlock* allocMBB = MF.CreateMachineBasicBlock(); |
| 1894 | + MachineBasicBlock* getMBB = MF.CreateMachineBasicBlock(); |
| 1895 | + MachineBasicBlock* mcrMBB = MF.CreateMachineBasicBlock(); |
| 1896 | + |
| 1897 | + for (MachineBasicBlock::livein_iterator i = prologueMBB.livein_begin(), |
| 1898 | + e = prologueMBB.livein_end(); i != e; ++i) { |
| 1899 | + allocMBB->addLiveIn(*i); |
| 1900 | + getMBB->addLiveIn(*i); |
| 1901 | + mcrMBB->addLiveIn(*i); |
| 1902 | + prevStackMBB->addLiveIn(*i); |
| 1903 | + postStackMBB->addLiveIn(*i); |
| 1904 | + } |
| 1905 | + |
| 1906 | + MF.push_front(postStackMBB); |
| 1907 | + MF.push_front(allocMBB); |
| 1908 | + MF.push_front(getMBB); |
| 1909 | + MF.push_front(mcrMBB); |
| 1910 | + MF.push_front(prevStackMBB); |
| 1911 | + |
| 1912 | + // The required stack size that is aligend to ARM constant critarion. |
| 1913 | + uint64_t StackSize = MFI->getStackSize(); |
| 1914 | + |
| 1915 | + AlignedStackSize = AlignToARMConstant(StackSize); |
| 1916 | + |
| 1917 | + // When the frame size is less than 256 we just compare the stack |
| 1918 | + // boundary directly to the value of the stack pointer, per gcc. |
| 1919 | + bool CompareStackPointer = AlignedStackSize < kSplitStackAvailable; |
| 1920 | + |
| 1921 | + // We will use two of callee save registers as scratch register so we |
| 1922 | + // need to save those registers into stack frame before use it. |
| 1923 | + // We will use SR0 to hold stack limit and SR1 to stack size requested. |
| 1924 | + // and arguments for __morestack(). |
| 1925 | + // SR0: Scratch Register #0 |
| 1926 | + // SR1: Scratch Register #1 |
| 1927 | + // push {SR0, SR1} |
| 1928 | + AddDefaultPred(BuildMI(prevStackMBB, DL, TII.get(ARM::tPUSH))) |
| 1929 | + .addReg(ScratchReg0) |
| 1930 | + .addReg(ScratchReg1); |
| 1931 | + |
| 1932 | + // mov SR1, sp |
| 1933 | + AddDefaultPred(BuildMI(mcrMBB, DL, TII.get(ARM::tMOVr), ScratchReg1) |
| 1934 | + .addReg(ARM::SP)); |
| 1935 | + |
| 1936 | + if (!CompareStackPointer) { |
| 1937 | + // sub SR1, #StackSize |
| 1938 | + AddDefaultPred(AddDefaultCC(BuildMI(mcrMBB, DL, TII.get(ARM::tSUBi8), ScratchReg1)) |
| 1939 | + .addReg(ScratchReg1).addImm(AlignedStackSize)); |
| 1940 | + } |
| 1941 | + |
| 1942 | + unsigned PCLabelId = ARMFI->createPICLabelUId(); |
| 1943 | + ARMConstantPoolValue *NewCPV = ARMConstantPoolSymbol:: |
| 1944 | + Create(MF.getFunction()->getContext(), "STACK_LIMIT", PCLabelId, 0); |
| 1945 | + MachineConstantPool *MCP = MF.getConstantPool(); |
| 1946 | + unsigned CPI = MCP->getConstantPoolIndex(NewCPV, MF.getAlignment()); |
| 1947 | + |
| 1948 | + //ldr SR0, [pc, offset(STACK_LIMIT)] |
| 1949 | + AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::tLDRpci), ScratchReg0) |
| 1950 | + .addConstantPoolIndex(CPI)); |
| 1951 | + |
| 1952 | + //ldr SR0, [SR0] |
| 1953 | + AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::tLDRi), ScratchReg0) |
| 1954 | + .addReg(ScratchReg0) |
| 1955 | + .addImm(0)); |
| 1956 | + |
| 1957 | + // Compare stack limit with stack size requested. |
| 1958 | + // cmp SR0, SR1 |
| 1959 | + AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::tCMPr)) |
| 1960 | + .addReg(ScratchReg0) |
| 1961 | + .addReg(ScratchReg1)); |
| 1962 | + |
| 1963 | + // This jump is taken if StackLimit < SP - stack required. |
| 1964 | + BuildMI(getMBB, DL, TII.get(ARM::tBcc)) |
| 1965 | + .addMBB(postStackMBB) |
| 1966 | + .addImm(ARMCC::LO) |
| 1967 | + .addReg(ARM::CPSR); |
| 1968 | + |
| 1969 | + |
| 1970 | + // Calling __morestack(StackSize, Size of stack arguments). |
| 1971 | + // __morestack knows that the stack size requested is in SR0(r4) |
| 1972 | + // and amount size of stack arguments is in SR1(r5). |
| 1973 | + |
| 1974 | + // Pass first argument for the __morestack by Scratch Register #0. |
| 1975 | + // The amount size of stack required |
| 1976 | + AddDefaultPred(AddDefaultCC(BuildMI(allocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg0)) |
| 1977 | + .addImm(AlignedStackSize)); |
| 1978 | + // Pass second argument for the __morestack by Scratch Register #1. |
| 1979 | + // The amount size of stack consumed to save function arguments. |
| 1980 | + AddDefaultPred(AddDefaultCC(BuildMI(allocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg1)) |
| 1981 | + .addImm(AlignToARMConstant(ARMFI->getArgumentStackSize()))); |
| 1982 | + |
| 1983 | + // push {lr} - Save return address of this function. |
| 1984 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPUSH))) |
| 1985 | + .addReg(ARM::LR); |
| 1986 | + |
| 1987 | + // Call __morestack(). |
| 1988 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tBL))) |
| 1989 | + .addExternalSymbol("__morestack"); |
| 1990 | + |
| 1991 | + // Restore return address of this original function. |
| 1992 | + // pop {SR0} |
| 1993 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPOP))) |
| 1994 | + .addReg(ScratchReg0); |
| 1995 | + |
| 1996 | + // mov lr, SR0 |
| 1997 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tMOVr), ARM::LR) |
| 1998 | + .addReg(ScratchReg0)); |
| 1999 | + |
| 2000 | + // Restore SR0 and SR1 in case of __morestack() was called. |
| 2001 | + // __morestack() will skip postStackMBB block so we need to restore |
| 2002 | + // scratch registers from here. |
| 2003 | + // pop {SR0, SR1} |
| 2004 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPOP))) |
| 2005 | + .addReg(ScratchReg0) |
| 2006 | + .addReg(ScratchReg1); |
| 2007 | + |
| 2008 | + // Return from this function. |
| 2009 | + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tMOVr), ARM::PC) |
| 2010 | + .addReg(ARM::LR)); |
| 2011 | + |
| 2012 | + // Restore SR0 and SR1 in case of __morestack() was not called. |
| 2013 | + // pop {SR0, SR1} |
| 2014 | + AddDefaultPred(BuildMI(postStackMBB, DL, TII.get(ARM::tPOP))) |
| 2015 | + .addReg(ScratchReg0) |
| 2016 | + .addReg(ScratchReg1); |
| 2017 | + |
| 2018 | + // Organizing MBB lists |
| 2019 | + postStackMBB->addSuccessor(&prologueMBB); |
| 2020 | + |
| 2021 | + allocMBB->addSuccessor(postStackMBB); |
| 2022 | + |
| 2023 | + getMBB->addSuccessor(postStackMBB); |
| 2024 | + getMBB->addSuccessor(allocMBB); |
| 2025 | + |
| 2026 | + mcrMBB->addSuccessor(getMBB); |
| 2027 | + |
| 2028 | + prevStackMBB->addSuccessor(mcrMBB); |
| 2029 | + |
| 2030 | +#ifdef XDEBUG |
| 2031 | + MF.verify(); |
| 2032 | +#endif |
| 2033 | +} |
0 commit comments