ARMFrameLowering::adjustForSegmentedStacks is broken in several places

I’m working with rust based embedded stack, and I got a few issues with current implementation of ARMFrameLowering::adjustForSegmentedStacks.

There are two places where prologue expects to find the stack limit. If the CPU supports thumb 1 only, stack limit is loaded from a global symbol __STACK_LIMIT. Otherwise it’s read from the coprocessor (two available platform-specific options are linux and android).

There is a problem with a bunch of Cortex-M MCUs, as all of them support at least a few thumb 2 instructions but don’t have a coprocessor, so the first way to get stack limit should be used.

The first thing that must be changed is that if CPU is a cortex-m, the stack limit should be taken from a global symbol __STACK_LIMIT. I have a trivial patch for this, albeit without tests. As of now, llvm produces machine code, which is not executable and results in cpu fault.

The second problem is that llvm expects that there is at least 256 bytes (defined in kSplitStackAvailable) after the stack end available for scratch purposes. I don’t really see the reasoning behind this check at all, it’s not that it drastically reduces the size of prologue. The problem is that each stack must be 256 bytes bigger, a big price if you have stacks of 512 bytes.

As I don’t see a reason to have this check in a first place, I suggest to completely remove it. Alternatively, it should be some kind of a flag, that could be passed down to specify the “scratch size”.

Here’s the trivial patch for the first issue:

diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp
index c18e741…325a124 100644
— a/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/lib/Target/ARM/ARMFrameLowering.cpp
@@ -1774,7 +1774,8 @@ void ARMFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {

  • if (Thumb && ST->isThumb1Only()) {
  • if ((Thumb && ST->isThumb1Only()) ||
  • ST->getCPUString().find(“cortex-m”) == 0) {
    unsigned PCLabelId = ARMFI->createPICLabelUId();
    ARMConstantPoolValue *NewCPV = ARMConstantPoolSymbol::Create(
    MF.getFunction()->getContext(), “__STACK_LIMIT”, PCLabelId, 0);

Please advice on what do I need to do to get this submitted or otherwise fixed.