PR/57638 CVS commit: src/external/gpl3/gcc/dist/gcc/config/arm
"Taylor R Campbell" <[email protected]> Sat, 25 Jul 2026 19:05:02 +0000 (UTC)
| Newsgroups | gmane.os.netbsd.bugs |
|---|---|
| Message-ID | <[email protected]> |
The following reply was made to PR lib/57638; it has been noted by GNATS. From: "Taylor R Campbell" <[email protected]> To: [email protected] Cc: Subject: PR/57638 CVS commit: src/external/gpl3/gcc/dist/gcc/config/arm Date: Sat, 25 Jul 2026 19:01:48 +0000 Module Name: src Committed By: riastradh Date: Sat Jul 25 19:01:48 UTC 2026 Modified Files: src/external/gpl3/gcc/dist/gcc/config/arm: arm.cc Log Message: gcc/arm: For -mtp=soft, ensure stack alignment even in leaves. The option -mtp=soft, which is the default on earmv5, makes queries to the thread pointer, for access to static (`initial-exec') thread-local storage, go through the C runtime subroutine __aeabi_read_tp. (For earmv>=6, we use the cp15 register via a single instruction.) Thus procedures which gcc thinks of as leaf procedures that use __aeabi_read_tp are not really leaf procedures -- and even though __aeabi_read_tp itself doesn't use the stack pointer at all, resolving the symbol may take a detour through the dynamic linker, which does rely on an aligned stack pointer. Without this change, code like __thread int x = 0; int * get_x(void) { return &x; } is compiled into: 00000000 <get_x>: get_x(): 0: e52de004 push {lr} @ (str lr, [sp, #-4]!) 4: ebfffffe bl 0 <__aeabi_read_tp> 4: R_ARM_CALL __aeabi_read_tp 8: e59f3004 ldr r3, [pc, #4] @ 14 <get_x+0x14> c: e0830000 add r0, r3, r0 10: e49df004 pop {pc} @ (ldr pc, [sp], #4) 14: 00000000 .word 0x00000000 14: R_ARM_TLS_LE32 .LANCHOR0 With this change, extend the _existing_ push and pop instructions in the prologue and epilogue to save and restore r4 arbitrarily (not that the content is useful for anything; it just keeps the stack pointer aligned to multiple of 8): 00000000 <get_x>: get_x(): 0: e92d4010 push {r4, lr} 4: ebfffffe bl 0 <__aeabi_read_tp> 4: R_ARM_CALL __aeabi_read_tp 8: e59f3004 ldr r3, [pc, #4] @ 14 <get_x+0x14> c: e0830000 add r0, r3, r0 10: e8bd8010 pop {r4, pc} 14: 00000000 .word 0x00000000 14: R_ARM_TLS_LE32 .LANCHOR0 Ideally, we would ensure stack alignment only for `leaf' procedures that actually use __aeabi_read_tp. But I don't know how to query that in this context. And in any case, this change only applies to subroutines that are already saving 2n+1 registers for some n, picking some arbitrary register to round it up to 2n+2. For example: int y; int * get_y(void) { return &y; } int * get_y_with_r4(void) { asm volatile("" ::: "r4"); return &y; } With this change, we get: 00000018 <get_y>: get_y(): 18: e59f0000 ldr r0, [pc] @ 20 <get_y+0x8> 1c: e12fff1e bx lr 20: 00000000 .word 0x00000000 20: R_ARM_ABS32 .bss 00000024 <get_y_with_r4>: get_y_with_r4(): 24: e92d0030 push {r4, r5} 28: e8bd0030 pop {r4, r5} 2c: e59f0000 ldr r0, [pc] @ 34 <get_y_with_r4+0x10> 30: e12fff1e bx lr 34: 00000000 .word 0x00000000 34: R_ARM_ABS32 .bss In contrast, with earmv>=6, get_y would be unchanged, but get_y_with_r4 would be: 00000020 <get_y_with_r4>: get_y_with_r4(): 20: e52d4004 push {r4} @ (str r4, [sp, #-4]!) 24: e59f0004 ldr r0, [pc, #4] @ 30 <get_y_with_r4+0x10> 28: e49d4004 pop {r4} @ (ldr r4, [sp], #4) 2c: e12fff1e bx lr 30: 00000000 .word 0x00000000 30: R_ARM_ABS32 .bss Note that the number of instructions hasn't changed; all that has changed is whether we save and restore one or two registers in the function prologue and epilogue (or more generally, 2n+1 vs 2n+2 registers). PR lib/57638: thread local storage broken on evbarm (armv5) Upstream bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126394 ok skrll@ To generate a diff of this commit: cvs rdiff -u -r1.1.1.4 -r1.2 src/external/gpl3/gcc/dist/gcc/config/arm/arm.cc Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.