i686 pic & DCmode

Nathan Sidwell nathan@acm.org
Wed Aug 7 15:52:00 GMT 2013


In poking at another set of fails encountered with an i686-elf toolchain 
(http://gcc.gnu.org/ml/gcc/2013-08/msg00081.html), I find that complex double 
returns and PIC do not play together.

Libgcc's __muldc3 was attempting to return the value in registers, whereas every 
caller expected it to be returned via pointer-to-aggregate parm.  Turned out to 
be PIC at fault -- libgcc is built as PIC, the callers weren't.

To determine if the return value should go in memory, function.c contains 
aggregate_value_p, which really means 'can't return in registers'.  That calls 
the backend return_in_mem hook, which for i686-elf simply forces BLKmode things 
to memory (the bundle of fun I refer to in the link).  As this is DCmode, we 
fall through to the default behaviour, which after a few other checks, picks the 
return register and then looks to see if the span of registers needed for the 
object are all call clobbered.

On x86, the registers are numbered eax, edx, ecx, ebx.  The first 3 are call 
clobbered and ebx is call preserved.  Hence (in non PIC), DCmode objects can't 
be placed there and a pointer-to-result parm is added.  In PIC mode, ebx remains 
call preserved, but becomes a fixed regs.  A fixed reg must also set call_used, 
and hey presto, we suddenly think all 4 are call clobbered.

This causes the result to be placed in those 4 registers -- and then the 
epilogue code restores the incoming ebx value, for extra brokenness.

The usual x86 ports avoid this, because their must_return_in_mem hooks DTRT 
already and we never fall into the default case.

I am very surprised this hasn't bitten someone before -- I presume this never 
worked with i686-elf.  It is possible this'll change some other ABI where a 
fixed reg was permitted to be used in the manner that this now prohibits, but I 
have a hard time thinking that happens.  Shout if you know of one.

Anyhow, I've not run a full regression test with this patch, but it does 
indicate that the i686-elf config's ABI is a bunch of accidents, rather than a 
coherent design.

nathan
-------------- next part --------------
2013-08-07  Nathan Sidwell  <nathan@codesourcery.com>

	gcc/
	* function.c (aggregate_value_p): Don't use a fixed reg either.

Index: gcc/function.c
===================================================================
--- gcc/function.c	(revision 417583)
+++ gcc/function.c	(working copy)
@@ -2031,7 +2031,7 @@ aggregate_value_p (const_tree exp, const
   regno = REGNO (reg);
   nregs = hard_regno_nregs[regno][TYPE_MODE (type)];
   for (i = 0; i < nregs; i++)
-    if (! call_used_regs[regno + i])
+    if (! call_used_regs[regno + i] || fixed_regs[regno + i])
       return 1;
 
   return 0;


More information about the Gcc-patches mailing list