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

Reply via email to