I am working on porting some code used on a STM32F4 based device from C to Rust. I am puzzled why the Rust equivalent is inserting an extra bx lr compared to the C version. Following is an excerpt from the C code:
This is not a big deal, as bx lr on memory location 2000000c is never reached, due to the branch to main preceding it. I still would like to understand the reason for this difference.
I suspect the difference isn't the language but rather the compiler, were you using GCC or Clang for the C code? Regardless, the solution is probably to add mem::unreachable at the end of your function.
That's right @parched, of course I should mention which compiler I was using. It's gcc 7.2.1.
Adding core::mem::unreachable() after the assembler block removes the branch and link instruction, but instead inserts an permanently undefined instruction:
As said, this is no big concern, I'm just interested in understanding why Rust/LLVM adds this extra instruction while C/gcc don't. Somehow gcc understands that this function is never called and can optimize away the branch and exchange instruction, right?
This seems to be a real difference between Rust and Clang. Rust always inserts a "return;" at the end of a naked function, whereas Clang does not. Clang always inserts the "unreachable" instruction at the end, Rust does not. I don't think much thought was given to this behavior when implementing naked functions, if you have a particular opinion one way or another, you should voice it in the naked functions tracking issue
It's identical to the file produced by gcc, at least for this excerpt (the main function is different between gcc/Clang, but that's another story). So at least in this case, Clang does not insert the udf instruction which appeared after the adding of unreachable().
As far as I understand naked functions, this seems very strange. Is not the purpose of these to skip all prologue/epilogue? I would guess this included returning. I guess I will voice it in the tracking issue, thanks to pointing me there.
I am compiling in release mode, I'm still in a early phase of my Rust coding for bare metal and want to learn what it really compiles down to, as stripped down as possible.