Subject: bug#65727: bug#63365: bug#65727: 30.0.50; Build failure in MSYS2 when --with-native-compilation

From: Andrea Corallo <[email-masked]>
Date: Fri, 17 May 2024 08:06:56 -0400

Andrea Corallo <[email-masked]> writes:

> Cyril Arnould <[email-masked]> writes:
>
>>> it would be great if you could:
>>>
>>> $ cd src
>>> $ touch thread.c
>>> $ make thread.o V=1
>>>
>>> Get the exact GCC invocation and add there "-E -o thread.i". This way
>>> we are sure we are looking at the right thing.
>>
>> I did as you asked, but a diff with the previously sent files shows
>> that the new ones are identical.
>
> That's very good, is important we are sure we look at the right thing.
> I'll digest them later tomorrow and report then 😃

Okay it's finally clear what is going on here.

In Emacs we use (in order to have all callee saved registers pushed on
the stack before entering in the garbage collector)
'__builtin_unwind_init'.  Our code reduced looks like this:

test.c ====================

extern void flush_stack_call_func1 (void (*func) (void *arg), void *arg);
extern void mark_threads (void);
extern void
mark_threads_callback (void *ignore);

static inline void
flush_stack_call_func (void (*func) (void *arg), void *arg)
{
  __builtin_unwind_init ();
  flush_stack_call_func1 (func, arg);
}

void
mark_threads (void)
{
  flush_stack_call_func (mark_threads_callback, ((void *)0));
}
====================

We want to call 'flush_stack_call_func1' being sure that all callee
saved registers are pushed on the stack (so that the GC can scan the
whole stack correctly).

The idea in pseudo asm is like:

mark_threads:
	[...]
	push	# these pushs are from 'builtin_unwind_init'
	push
	push
        [...]
	call flush_stack_call_func1
	pop	# these pops are from 'builtin_unwind_init'
	pop
	pop
	ret

Sibling call optimization makes this:

mark_threads:
	[...]
	push
	push
	push
        [...]
	pop
	pop
	pop
	jmp flush_stack_call_func1

Which indeed does not work for us.

I believe this is a GCC bug as the sibling call optimizer should not run
in functions making use of 'builtin_unwind_init', even if this one is
undocumented (otherwise I can't see its reason of being 🙂).

So I filed a GCC bug [1].

Despite the fact that this will or not be recognized as a bug (and in
case fixed), I think we'll have to fix this on our codebase disabling
the sibling call optimizations on the sentive function(s).

Also note, this bug is not a native-comp specifc one, it's just most
likely non triggerable on most configuration.  IOW I think we see it
only on mingw+nativecomp by chance.

Thanks

  Andrea

[1] <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115132>