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

Reply via email to