2

I'm writing a microcontroller firmware which has a main loop function that never returns. It's called from the reset_handler function:

void reset_handler() { // relocate data section memcpy(&_data_vma, &_data_lma, (&_data_evma - &_data_vma) * sizeof(size_t)); main(); } 

Since main never returns, creating a stack frame for it would just waste RAM space (just 8 bytes, but still ...). I considered the following ways to reclaim this space:

  • mark function as inline (would have to put function definition in header file, which is not very nice);
  • add naked attribute to the function (breaks function calls inside main, which pass arguments on stack);
  • adjust sp manually (feels like a dirty hack)

but they bring more problems than they solve.

Is there a better way to instruct GCC not to create a stack frame for a particular function?

2
  • How do you determine whether GCC creates a stack frame? I'd guess that with optimizations turned on, it'd automatically inline main into reset_handler Commented Oct 14, 2022 at 14:32
  • 1
    Do you want to have no stack frame for main()? Are you going to use no variables in main? It is unclear to me, what exactly you're trying to achieve. You can always __asm volatile branch without link to main, if you don't want to set LR register. If you're planning to do context switching, then you can manually create pseudoframe that will be automatically loaded into xPSR, PC, R0-R3, R12 upon ISR exit. I've just written my first context switcher a pair of days ago, that's how I did it there. Alternatively, you can always move stack pointer on the first line in main before you put stuff there? Commented Oct 15, 2022 at 9:02

1 Answer 1

4

You can do a couple of things here (although the benefit is minimal):

First, set the noreturn attribute on main:

int main(void) __attribute__((noreturn)); 

Second, you can use __builtin_unreachable() anywhere the compiler can't work out that it cannot get to. For example:

int foo(int x) __attribute__((noreturn)); int foo(int x) { int y; if (x < 7) { y = 9; } else { y = 11; } while (y > 3) { printf("yes\n"); } __builtin_unreachable(); } 

In this case the compiler might not work out that the only possible values of y (9 and 11) are both always greater than 3, so the builtin helps it to know the loop never exits and the function doesn't need a return statement.

If you unconditionally call a function with the noreturn attribute then you don't need the builtin, the compiler should work it out.

Sign up to request clarification or add additional context in comments.

2 Comments

This didn't help with arm-none-eabi-gcc 10.3.1 20210621
I think this is the best you are going to do using a compiled language. The compiler isn't really meant for letting you penny-pinch every last instruction. If you know exactly the instructions you want it to output then you can just write it in assembly.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.