This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[x86-64 PATCH] PR target/26223: x86-64 ABI vs -mno-80387


Hi Honza,

The following patch resolves PR target/26223 which is an ICE on invalid
caused by compiling code to return long doubles on x86_64 when the user
explicitly specifies -mno-80387.  The problem is not in the splitters or
the machine description, but in the ABI machinery that insists that
XFmode be returned in REGNO 8, i.e. FIRST_STACK_REG, which isn't available
with -mno-80387.

One possible fix, for some point in the future?, is to change the code
in the i386 backend to instead use REGNO 0 in these cases, but this
would change the ABI and need to documented/ratified in the x86-64
ABI specification.

The alternative approach, implemented below, is to do the same for
-mno-80387 as we do for -mno-sse, and issue an error if a function's
prototype ever conflicts with the allowable registers.  This is useful
for building the kernel with -mno-80387 and -mno-sse, which will warn
if the programmer makes a simple mistake.

The new check below is a comprehensive test for any of the returned
classes being an x87 class.  In theory, one only needs to check the
first class, and X86_64_X87UP_CLASS should only occur after an
X86_64_X87_CLASS, but it seemed reasonable to be thorough here as
this code is guarded by the rare !TARGET_80387, and its better to
be explicit/clear if we're not on the critical path.

One clean-up/fallout of this patch is the rationalization of the
"error_issued" state in construct_container.  Given that we now need
to issue a separate error for x87, it made sense for these static
state variables, to be one per error message, such that we issue
only one error for each type of problem (SSE argument, SSE return and
x87 return) upon its first occurence.


The following patch has been tested on x86_64-unknown-linux-gnu, with
a full "make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.

Ok for mainline?



2006-06-03  Roger Sayle  <roger@eyesopen.com>

	PR target/26223
	* config/i386/i386.c (construct_container): Split static issued_error
	flag into issued_sse_arg_error, issued_sse_ret_error and
	issued_x87_ret_error.  Issue a daignostic if the x86-64 ABI
	requires the use of x87 registers and the user explicitly
	specified the -mno-80387 command line option.

	* gcc.target/i386/amd64-abi-2.c: New test case.


Index: config/i386/i386.c
===================================================================
*** config/i386/i386.c	(revision 114330)
--- config/i386/i386.c	(working copy)
*************** construct_container (enum machine_mode m
*** 3247,3252 ****
--- 3247,3257 ----
  		     tree type, int in_return, int nintregs, int nsseregs,
  		     const int *intreg, int sse_regno)
  {
+   /* The following variables hold the static issued_error state.  */
+   static bool issued_sse_arg_error;
+   static bool issued_sse_ret_error;
+   static bool issued_x87_ret_error;
+
    enum machine_mode tmpmode;
    int bytes =
      (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
*************** construct_container (enum machine_mode m
*** 3285,3302 ****
       some less clueful developer tries to use floating-point anyway.  */
    if (needed_sseregs && !TARGET_SSE)
      {
!       static bool issued_error;
!       if (!issued_error)
  	{
! 	  issued_error = true;
! 	  if (in_return)
! 	    error ("SSE register return with SSE disabled");
! 	  else
! 	    error ("SSE register argument with SSE disabled");
  	}
        return NULL;
      }

    /* First construct simple cases.  Avoid SCmode, since we want to use
       single register to pass this type.  */
    if (n == 1 && mode != SCmode)
--- 3290,3327 ----
       some less clueful developer tries to use floating-point anyway.  */
    if (needed_sseregs && !TARGET_SSE)
      {
!       if (in_return)
  	{
! 	  if (!issued_sse_ret_error)
! 	    {
! 	      error ("SSE register return with SSE disabled");
! 	      issued_sse_ret_error = true;
! 	    }
! 	}
!       else if (!issued_sse_arg_error)
! 	{
! 	  error ("SSE register argument with SSE disabled");
! 	  issued_sse_arg_error = true;
  	}
        return NULL;
      }

+   /* Likewise, error if the ABI requires us to return values in the
+      x87 registers and the user specified -mno-80387.  */
+   if (!TARGET_80387 && in_return)
+     for (i = 0; i < n; i++)
+       if (class[i] == X86_64_X87_CLASS
+ 	  || class[i] == X86_64_X87UP_CLASS
+ 	  || class[i] == X86_64_COMPLEX_X87_CLASS)
+ 	{
+ 	  if (!issued_x87_ret_error)
+ 	    {
+ 	      error ("x87 register return with x87 disabled");
+ 	      issued_x87_ret_error = true;
+ 	    }
+ 	  return NULL;
+ 	}
+
    /* First construct simple cases.  Avoid SCmode, since we want to use
       single register to pass this type.  */
    if (n == 1 && mode != SCmode)



/* PR target/26223 */
/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
/* { dg-options "-mno-80387" } */
long double foo(long double x) { return x; } /* { dg-error "x87 disabled" } */
long double bar(long double x) { return x; }


Roger
--


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]