https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107500
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Last reconfirmed| |2022-11-02
Ever confirmed|0 |1
--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to R. Diez from comment #0)
> The check above fails with GCC 12.2. Apparently, a destructor called
> constant_init::~constant_init() gets added to the atexit table on start-up.
This was done to make the global object in that file immortal. The
constant_init wrapper gets destroyed, but its subobject doesn't, so code that
refers to it later is ... slightly less undefined.
> Because of the way that Newlib works, that wastes 400 bytes of SRAM, which
> corresponds to sizeof( _global_atexit0 ). The structure has room for 32
> atexit calls (because of some ANSI conformance), but we are only using 1
> entry.
>
> The interesting thing is that the destructor is supposed to be empty, see:
>
> https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/
> eh_globals.cc
>
> ~constant_init() { /* do nothing, union member is not destroyed */ }
>
> GCC generates the following code for that empty destructor:
>
> 0008da68 <(anonymous namespace)::constant_init::~constant_init()>:
> 8da68: b580 push {r7, lr}
> 8da6a: af00 add r7, sp, #0
> 8da6c: bd80 pop {r7, pc}
>
> That does not make any sense. Is there a way to prevent GCC from registering
> such an empty atexit function? Failing that, is there a way to prevent GCC
> from registering a particular atexit function, even if it is not empty?
If we had clang's no_destroy attribute then we could use that on those
constant_init wrappers:
https://clang.llvm.org/docs/AttributeReference.html#no-destroy
> I find surprising that GCC emits such code. My project is building its own
> GCC/Newlib toolchain with optimisation level "-Os", so I would expect at
> least the "add r7, sp, #0" to be optimised away.
Agreed, I don't think we should be emitting cleanup if it's a no-op. But I
don't know if the compiler is able to tell it's a no-op at the point where it
emits that code. The attribute would tell the compiler it's OK to do that.