When building code with -mregparm=x on i?86 which uses libgcc functions (eg. udivdi3), the calls to the libgcc functions use the calling convention as given by mregparm, even though libgcc is internal to the compiler (and the user has no ultimate control about when it is used). Adding the compiler-native calling convention as regparm attribute to all calls that are synthesized by the compiler might fix the problem. The following shell script exhibits the problem. cat > test.c << EOF int main() { long long a= 4000000000; return a / 43937; } EOF gcc -S test.c mv test.s test.default.s gcc -mregparm=3 -S test.c mv test.s test.mregparm3.s diff -u test.default.s test.mregparm3.s exit 0 # there should be no difference in the calling convention # as __divdi3 is taken from libgcc, but I get the result: --- test.default.s Do. Aug 13 15:47:28 2009 +++ test.mregparm3.s Do. Aug 13 15:47:28 2009 -18,10 +18,9 @@ movl $0, -4(%ebp) movl -8(%ebp), %eax movl -4(%ebp), %edx + subl $8, %esp pushl $0 pushl $43937 - pushl %edx - pushl %eax call __divdi3 addl $16, %esp leave
-mregparm changes the ABI, you have to rebuild libgcc with -mregparm to be able to use it.
So we have to rebuild parts of the compiler in order to get a working compiler, depending on the compiler flags we use? That sounds pretty broken to me. In my opinion, since -mregparm is a gcc run time option, not a compile time option, the compiler should provide libgcc for every possible ABI and choose among those. Closing this bug is especially weird since #12081 implies that building the compiler with -mregparm=3 is broken.
(In reply to comment #1) > -mregparm changes the ABI, you have to rebuild libgcc with -mregparm to be > able to use it. > I agree with that notion for general purpose libraries as used by the user. But libgcc is an implementation artefact of GCC. I'd prefer not to use it, but GCC forces me to. If I use __divdi3 myself, GCC can expect that I fix up the call myself (using some __attribute__((regparm))), but if GCC uses it, I think it's not to much to ask for it to fix it up itself (as I don't have the means to do so, short of rewriting assembler code) I see three good solutions: 1. GCC calls its own libgcc calls in a proper way (and it should be able to do so, if I as a user can change calling conventions per function call) 2. It refuses to use libgcc with mregparm, as it will break. 3. GCC supports multiple libgccs, choosing the right one automatically. My guess is that solution 1 is the easiest. Hacks like http://trac.nchc.org.tw/grid/browser/gpfs_3.1_ker2.6.20/lpp/mmfs/src/gpl-linux/mmwrap.c shouldn't be necessary.
I agree with the reporters. libgcc isn't some random library, GCC should call it correctly even in the presence of -mregparm.
Created attachment 45858 [details] Test case (C)
Created attachment 45860 [details] Test case (preprocessed)
Created attachment 45861 [details] Test case (assembly output)
Created attachment 45862 [details] Test code (object output)
I can confirm this bug is still present as of gcc 8.2.1. I have attached a test case which clearly shows __udivdi3 called with the regparm convention, but libgcc definitely does not expect it: objdump -dr `gcc -m32 -march=i386 -mregparm=3 -O3 -fomit-frame-pointer --print-libgcc` 00000000 <__udivdi3>: 0: f3 0f 1e fb endbr32 4: 55 push %ebp 5: 57 push %edi 6: 56 push %esi 7: 53 push %ebx 8: 83 ec 1c sub $0x1c,%esp b: 8b 54 24 3c mov 0x3c(%esp),%edx f: 8b 6c 24 30 mov 0x30(%esp),%ebp 13: 8b 74 24 34 mov 0x34(%esp),%esi 17: 8b 5c 24 38 mov 0x38(%esp),%ebx ... As far as I can tell, there are four possible options: a. Build a libgcc for any combination of runtime options. b. Add multiple functions to libgcc for each combination of runtime options which matter. c. Force using a single ABI for libgcc functions (in which case it might as well use the most efficient ABI, e.g. -mregparm=3 -freg-struct-return); as the libgcc functions are private to gcc anyway there is no reason they need to use the main calling convention. d. Emit these functions in a link-once section, similar to the way __x86.get_pc_thunk.* are generated. This has upsides and downsides: the upsides are that they are inherently correct, that they can rely on arch/optimize flags, a dynamic library can't get out of sync with the compiler if these functions are changed, and these functions can be marked hidden, which means that they can be called directly. Downsides are link time and some heavy lifting in implementation. It also means that each dynamic library carries its own copy, but since libgcc already marks its symbols HIDDEN, this is already the case.