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]

[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?


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