This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch] RETURN_IN_MEMORY for cygwin and mingw32
- From: Danny Smith <danny_r_smith_2001 at yahoo dot co dot nz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 6 Feb 2003 10:16:10 +1100 (EST)
- Subject: [Patch] RETURN_IN_MEMORY for cygwin and mingw32
Hi
The default i386 definition of RETURN_IN_MEMORY causes incomapatibility with
objects produced by native Win32 MSVC compiler and hence the Win32api.
The following testcase illustrates. With other windows compilers, the
Large_IntAdd and longlongadd produce the same asm code
With GCC, Large_IntAdd pushes a pointer for the result to the stack and the
function uses this pointer to store the result, while longlongadd returns in
registers edx:eax
This is also a regression from 2.95.3, which produced the same code
for both functions on mingw32 and cygwin targets.
=======start======
/* large.c */
#ifndef __GNUC__
# define STDCALL __stdcall
# define LONGLONG __int64
#else
# define STDCALL __attribute__((stdcall))
# define LONGLONG long long
#endif
typedef union _LARGE_INT
{
struct
{
unsigned low;
unsigned high;
} parts;
LONGLONG quad;
} LARGE_INT;
LARGE_INT STDCALL
Large_IntAdd (LARGE_INT i1, LARGE_INT i2)
{
LARGE_INT res;
res.quad = i1.quad + i2.quad;
return res;
}
LONGLONG STDCALL
longlongadd (LONGLONG i1, LONGLONG i2)
{ return i1 + i2; }
=======end=======
gcc -S -O2 -fomit-frame-pointer large.c produces:
.file "large.c"
.text
.p2align 2,,3
.globl _Large_IntAdd@16
.def _Large_IntAdd@16; .scl 2; .type 32; .endef
_Large_IntAdd@16:
movl 16(%esp), %edx
addl 8(%esp), %edx
movl 20(%esp), %ecx
movl 4(%esp), %eax
adcl 12(%esp), %ecx
movl %edx, (%eax)
movl %ecx, 4(%eax)
ret $20
.p2align 2,,3
.globl _longlongadd@16
.def _longlongadd@16; .scl 2; .type 32; .endef
_longlongadd@16:
movl 12(%esp), %eax
movl 16(%esp), %edx
addl 4(%esp), %eax
adcl 8(%esp), %edx
ret $16
After adding the following patch to config/i386/cygwin.h (copied from
i386-interix.h), the asm ouput for Large_IntAdd is identical to that of
longlongadd and is consistent with the LARGE_INTEGER functions in the
win32 api.
However, given the recent discussion on RETURN_IN_MEMORY
(http://gcc.gnu.org/ml/gcc-patches/2003-02/msg00315.html)
I'm not sure if this is the "right thing". Is there a better way?
Danny
2003-02-05 Danny Smith <dannysmith@users.sourceforge.net>
* config/i386/cygwin.h (RETURN_IN_MEMORY): Override default
with MSVC compatible definition
Index: cygwin.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/cygwin.h,v
retrieving revision 1.76
diff -c -3 -p -r1.76 cygwin.h
*** cygwin.h 19 Dec 2002 22:00:32 -0000 1.76
--- cygwin.h 5 Feb 2003 22:02:25 -0000
*************** extern int i386_pe_dllimport_name_p PARA
*** 410,415 ****
--- 410,421 ----
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 0
+ /* MSVC returns aggregate types of up to 8 bytes via registers. */
+ #undef RETURN_IN_MEMORY
+ #define RETURN_IN_MEMORY(TYPE) \
+ (TYPE_MODE (TYPE) == BLKmode || \
+ (AGGREGATE_TYPE_P (TYPE) && int_size_in_bytes(TYPE) > 8 ))
+
/* No data type wants to be aligned rounder than this. */
#undef BIGGEST_ALIGNMENT
#define BIGGEST_ALIGNMENT 128
http://movies.yahoo.com.au - Yahoo! Movies
- What's on at your local cinema?