CVS commit: src/external/gpl3/gcc/dist/gcc/config/arm

"Taylor R Campbell" <[email protected]> Sat, 25 Jul 2026 19:01:48 +0000
Newsgroups gmane.os.netbsd.devel.cvs
Message-ID <[email protected]>
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.