This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[x86-64 PATCH] PR target/26223: x86-64 ABI vs -mno-80387
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jan Hubicka <jh at suse dot cz>
- Date: Sat, 3 Jun 2006 15:23:51 -0600 (MDT)
- Subject: [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
--