Yes, if you use rust-llvm-2014-02-11 as the base of the PR I can merge it in and update the LLVM that rust is using.
On Sun, Feb 16, 2014 at 4:08 AM, Svetoslav Neykov <svetos...@neykov.name> wrote: > I don't find any of the ARM split stack changes in the LLVM tree, just a > single > patch to the llvm-commits a year ago with no followup. > (http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20130318/168838 > .html) > Since my changes depend on the ARM changes it doesn't make sense to try to > merge > them before the previous changes are accepted. > > I guess I should use the rust-llvm-2014-02-11 branch as the base for my PR? > > Svetoslav. > > > -----Original Message----- > From: alexc...@gmail.com [mailto:alexc...@gmail.com] On Behalf Of Alex > Crichton > Sent: Sunday, February 16, 2014 1:16 AM > To: Svetoslav Neykov > Cc: rust-dev@mozilla.org > Subject: Re: [rust-dev] [PATCH] Add stack overflow check for ARM Thumb > instruction set. > > For LLVM patches, we prefer if you have first attempted to upstream > the patch with LLVM before we push it to our local fork. This normally > entails emailing the llvm-commits mailing list. Once this upstream > attempt has been made, you can open a PR against the rust-lang/llvm > repo on github. > > This looks pretty awesome though, nice work! > > > On Sat, Feb 15, 2014 at 8:36 AM, Svetoslav Neykov <svetos...@neykov.name> > wrote: >> Hi, >> >> I am working on getting Rust to directly compile code for bare metal ARM >> devices working in Thumb mode. I created a patch for LLVM to emit >> the appropriate function prologue. Since I couldn't find instructions on > how >> to submit the change for review and inclusion in the Rust's copy of LLVM I >> am sending it here on the dev mailing list. >> >> Besides the mechanincal differences between the ARM and Thumb functions, >> because of the different instruction sets, there is difference in how the >> stack limit is located. The ARM version uses hardware which isn't > available >> on the lower-end Thumb processors (namely system co-processor and MMU) >> therefore I am looking for the stack limit at a predefined location in >> memory - STACK_LIMIT. It is the responsibility of the wrapping runtime >> to manage this location with the correct value. It can vary from a simple >> constant defined by the linker to actively managed variable by a RTOS >> implementation. >> (thanks to whitequark for discussing the possible approaches) >> >> There is an old pull request for Rust which was the precursor to this > change >> located at https://github.com/mozilla/rust/pull/10942. Once the patch is >> accepted I will try to update it to the latest changes in the repository. >> >> Here is the patch itself: >> > ============================================================================ > === >> >> Add stack overflow check for ARM Thumb instruction set. >> >> The code assumes that the stack limit will be located at the >> address labeled STACK_LIMIT. >> --- >> lib/Target/ARM/ARMFrameLowering.cpp | 184 > +++++++++++++++++++++++++++++++++++- >> lib/Target/ARM/ARMFrameLowering.h | 2 + >> 2 files changed, 185 insertions(+), 1 deletion(-) >> >> diff --git a/lib/Target/ARM/ARMFrameLowering.cpp > b/lib/Target/ARM/ARMFrameLowering.cpp >> index bdf0480..c286228 100644 >> --- a/lib/Target/ARM/ARMFrameLowering.cpp >> +++ b/lib/Target/ARM/ARMFrameLowering.cpp >> @@ -14,6 +14,7 @@ >> #include "ARMFrameLowering.h" >> #include "ARMBaseInstrInfo.h" >> #include "ARMBaseRegisterInfo.h" >> +#include "ARMConstantPoolValue.h" >> #include "ARMInstrInfo.h" >> #include "ARMMachineFunctionInfo.h" >> #include "ARMTargetMachine.h" >> @@ -1481,10 +1482,20 @@ static uint32_t AlignToARMConstant(uint32_t Value) > { >> // stack limit. >> static const uint64_t kSplitStackAvailable = 256; >> >> +void >> +ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { >> + const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>(); >> + if(ST->isThumb()) { >> + adjustForSegmentedStacksThumb(MF); >> + } else { >> + adjustForSegmentedStacksARM(MF); >> + } >> +} >> + >> // Adjust function prologue to enable split stack. >> // Only support android and linux. >> void >> -ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { >> +ARMFrameLowering::adjustForSegmentedStacksARM(MachineFunction &MF) const > { >> const ARMSubtarget *ST = &MF.getTarget().getSubtarget<ARMSubtarget>(); >> >> // Doesn't support vararg function. >> @@ -1697,3 +1708,174 @@ > ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { >> MF.verify(); >> #endif >> } >> + >> +void >> +ARMFrameLowering::adjustForSegmentedStacksThumb(MachineFunction &MF) > const { >> +// const ARMSubtarget *ST = > &MF.getTarget().getSubtarget<ARMSubtarget>(); >> + >> + // Doesn't support vararg function. >> + if (MF.getFunction()->isVarArg()) >> + report_fatal_error("Segmented stacks do not support vararg > functions."); >> + >> + MachineBasicBlock &prologueMBB = MF.front(); >> + MachineFrameInfo* MFI = MF.getFrameInfo(); >> + const ARMBaseInstrInfo &TII = *TM.getInstrInfo(); >> + ARMFunctionInfo* ARMFI = MF.getInfo<ARMFunctionInfo>(); >> + DebugLoc DL; >> + >> + // Use R4 and R5 as scratch register. >> + // We should save R4 and R5 before use it and restore before >> + // leave the function. >> + unsigned ScratchReg0 = ARM::R4; >> + unsigned ScratchReg1 = ARM::R5; >> + uint64_t AlignedStackSize; >> + >> + MachineBasicBlock* prevStackMBB = MF.CreateMachineBasicBlock(); >> + MachineBasicBlock* postStackMBB = MF.CreateMachineBasicBlock(); >> + MachineBasicBlock* allocMBB = MF.CreateMachineBasicBlock(); >> + MachineBasicBlock* getMBB = MF.CreateMachineBasicBlock(); >> + MachineBasicBlock* mcrMBB = MF.CreateMachineBasicBlock(); >> + MachineBasicBlock* magicMBB = MF.CreateMachineBasicBlock(); >> + >> + for (MachineBasicBlock::livein_iterator i = prologueMBB.livein_begin(), >> + e = prologueMBB.livein_end(); i != e; ++i) { >> + allocMBB->addLiveIn(*i); >> + getMBB->addLiveIn(*i); >> + magicMBB->addLiveIn(*i); >> + mcrMBB->addLiveIn(*i); >> + prevStackMBB->addLiveIn(*i); >> + postStackMBB->addLiveIn(*i); >> + } >> + >> + MF.push_front(postStackMBB); >> + MF.push_front(allocMBB); >> + MF.push_front(getMBB); >> + MF.push_front(magicMBB); >> + MF.push_front(mcrMBB); >> + MF.push_front(prevStackMBB); >> + >> + // The required stack size that is aligend to ARM constant critarion. >> + uint64_t StackSize = MFI->getStackSize(); >> + >> + AlignedStackSize = AlignToARMConstant(StackSize); >> + >> + // When the frame size is less than 256 we just compare the stack >> + // boundary directly to the value of the stack pointer, per gcc. >> + bool CompareStackPointer = AlignedStackSize < kSplitStackAvailable; >> + >> + // We will use two of callee save registers as scratch register so we >> + // need to save those registers into stack frame before use it. >> + // We will use SR0 to hold stack limit and SR1 to stack size requested. >> + // and arguments for __morestack(). >> + // SR0: Scratch Register #0 >> + // SR1: Scratch Register #1 >> + // push {SR0, SR1} >> + AddDefaultPred(BuildMI(prevStackMBB, DL, TII.get(ARM::tPUSH))) >> + .addReg(ScratchReg0) >> + .addReg(ScratchReg1); >> + >> + if (CompareStackPointer) { >> + // mov SR1, sp >> + AddDefaultPred(BuildMI(mcrMBB, DL, TII.get(ARM::tMOVr), ScratchReg1) >> + .addReg(ARM::SP)); >> + } else { >> + // sub SR1, sp, #StackSize >> + AddDefaultPred(BuildMI(mcrMBB, DL, TII.get(ARM::tSUBi8), ScratchReg1) >> + .addReg(ARM::SP).addImm(AlignedStackSize)); >> + } >> + >> + unsigned PCLabelId = ARMFI->createPICLabelUId(); >> + ARMConstantPoolValue *NewCPV = ARMConstantPoolSymbol:: >> + Create(MF.getFunction()->getContext(), "STACK_LIMIT", PCLabelId, 0); >> + MachineConstantPool *MCP = MF.getConstantPool(); >> + unsigned CPI = MCP->getConstantPoolIndex(NewCPV, MF.getAlignment()); >> + >> + //ldr SR0, [pc, offset(STACK_LIMIT)] >> + AddDefaultPred(BuildMI(magicMBB, DL, TII.get(ARM::tLDRpci), > ScratchReg0) >> + .addConstantPoolIndex(CPI)); >> + >> + //ldr SR0, [SR0] >> + AddDefaultPred(BuildMI(magicMBB, DL, TII.get(ARM::tLDRi), ScratchReg0) >> + .addReg(ScratchReg0) >> + .addImm(0)); >> + >> + // Compare stack limit with stack size requested. >> + // cmp SR0, SR1 >> + AddDefaultPred(BuildMI(getMBB, DL, TII.get(ARM::tCMPr)) >> + .addReg(ScratchReg0) >> + .addReg(ScratchReg1)); >> + >> + // This jump is taken if StackLimit < SP - stack required. >> + BuildMI(getMBB, DL, TII.get(ARM::tBcc)) >> + .addMBB(postStackMBB) >> + .addImm(ARMCC::LO) >> + .addReg(ARM::CPSR); >> + >> + >> + // Calling __morestack(StackSize, Size of stack arguments). >> + // __morestack knows that the stack size requested is in SR0(r4) >> + // and amount size of stack arguments is in SR1(r5). >> + >> + // Pass first argument for the __morestack by Scratch Register #0. >> + // The amount size of stack required >> + AddDefaultPred(AddDefaultCC(BuildMI(allocMBB, DL, TII.get(ARM::tMOVi8), > ScratchReg0)) >> + .addImm(AlignedStackSize)); >> + // Pass second argument for the __morestack by Scratch Register #1. >> + // The amount size of stack consumed to save function arguments. >> + AddDefaultPred(AddDefaultCC(BuildMI(allocMBB, DL, TII.get(ARM::tMOVi8), > ScratchReg1)) >> + > .addImm(AlignToARMConstant(ARMFI->getArgumentStackSize()))); >> + >> + // push {lr} - Save return address of this function. >> + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPUSH))) >> + .addReg(ARM::LR); >> + >> + // Call __morestack(). >> + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tBL))) >> + .addExternalSymbol("__morestack"); >> + >> + // Restore return address of this original function. >> + // pop {SR0} >> + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPOP))) >> + .addReg(ScratchReg0); >> + >> + // mov lr, SR0 >> + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tMOVr), ARM::LR) >> + .addReg(ScratchReg0)); >> + >> + // Restore SR0 and SR1 in case of __morestack() was called. >> + // __morestack() will skip postStackMBB block so we need to restore >> + // scratch registers from here. >> + // pop {SR0, SR1} >> + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tPOP))) >> + .addReg(ScratchReg0) >> + .addReg(ScratchReg1); >> + >> + // Return from this function. >> + AddDefaultPred(BuildMI(allocMBB, DL, TII.get(ARM::tMOVr), ARM::PC) >> + .addReg(ARM::LR)); >> + >> + // Restore SR0 and SR1 in case of __morestack() was not called. >> + // pop {SR0, SR1} >> + AddDefaultPred(BuildMI(postStackMBB, DL, TII.get(ARM::tPOP))) >> + .addReg(ScratchReg0) >> + .addReg(ScratchReg1); >> + >> + // Organizing MBB lists >> + postStackMBB->addSuccessor(&prologueMBB); >> + >> + allocMBB->addSuccessor(postStackMBB); >> + >> + getMBB->addSuccessor(postStackMBB); >> + getMBB->addSuccessor(allocMBB); >> + >> + magicMBB->addSuccessor(getMBB); >> + >> + mcrMBB->addSuccessor(getMBB); >> + mcrMBB->addSuccessor(magicMBB); >> + >> + prevStackMBB->addSuccessor(mcrMBB); >> + >> +#ifdef XDEBUG >> + MF.verify(); >> +#endif >> +} >> diff --git a/lib/Target/ARM/ARMFrameLowering.h > b/lib/Target/ARM/ARMFrameLowering.h >> index 16b477a..0cb8e5a 100644 >> --- a/lib/Target/ARM/ARMFrameLowering.h >> +++ b/lib/Target/ARM/ARMFrameLowering.h >> @@ -62,6 +62,8 @@ public: >> RegScavenger *RS) const; >> >> void adjustForSegmentedStacks(MachineFunction &MF) const; >> + void adjustForSegmentedStacksThumb(MachineFunction &MF) const; >> + void adjustForSegmentedStacksARM(MachineFunction &MF) const; >> >> private: >> void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator > MI, >> -- >> 1.8.3.2 >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev@mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > _______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev