https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113293
Bug ID: 113293
Summary: Incorrect code after inlining function containing
extended asm
Product: gcc
Version: 14.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: ipa
Assignee: unassigned at gcc dot gnu.org
Reporter: dories.spirits_0p at icloud dot com
CC: marxin at gcc dot gnu.org
Target Milestone: ---
GCC compiles the following code (with -O3 -std=gnu2x):
#include <stdint.h>
#define SYSCALL_GETCHAR 1
#define SYSCALL_THREAD_CREATE 2
typedef void (*thread_func)(void *);
static inline char getc() {
register char r0 asm("r0");
asm volatile ("svc %[syscall]"
: "=r" (r0)
: [syscall] "i" (SYSCALL_GETCHAR)
: "r1", "r2", "r3");
return r0;
}
static inline void thread_create(thread_func func, const void * args, uint32_t
args_size) {
register uint32_t r0 asm("r0") = (uint32_t) func;
register uint32_t r1 asm("r1") = (uint32_t) args;
register uint32_t r2 asm("r2") = args_size;
asm volatile ("svc %[syscall]"
: "+r" (r0), "+r" (r1), "+r" (r2)
: [syscall] "i" (SYSCALL_THREAD_CREATE), "r" (r0), "r" (r1),
"r" (r2)
: "r3");
}
void worker([[maybe_unused]] void *x) {}
void main() {
while (true) {
char arg = getc();
thread_create(worker, &arg, sizeof(arg));
}
}
into something like
main:
movw ip, #:lower16:worker
sub sp, sp, #8
movt ip, #:upper16:worker
.L4:
svc #1 //char getc()
mov r2, #1
mov r0, ip //return value of 'getc' svc call overwritten
add r1, sp, #7 //nothing in the stack here!
svc #2
b .L4
The return value of 'getc' is overwritten/not stored on the stack with -O1 and
higher (-Og and -O0 are not affected). I've tested on a local copy of
arm-none-eabi-gcc 10.2.0 as well as arm gcc trunk (arm-unknown-linux-gnueabihf
14.0.0 20240108) on compiler explorer.
I've also tested clang 17 targeting arm-none-eabi, which correctly stores the
result of the 'getc' svc call on the stack in all optimization levels:
.LBB1_1:
svc #1
strb r0, [sp, #3]
[...]
ARM GCC trunk and Clang trunk:
https://godbolt.org/z/ercEYfacM
If 'getc' is marked noinline, r0 is correctly saved to the stack:
.L5:
bl getc
strb r0, [sp, #7] //saved to stack
add r1, sp, #7
[...]
svc #2
b .L5
With [[gnu::noinline]]
https://godbolt.org/z/ETManW1hY
This is my first bug, so please let me know if there's anything else I need to
provide.