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]

3.0.1 PATCH: Band-aid for IRIX 6 N32/N64 structure passing bug (version 2)


This is an updated version of

	http://gcc.gnu.org/ml/gcc-patches/2001-06/msg00418.html

rewritten (and heavily commented) to avoid copyright problems with the
original submission, as far as the nature of the bug being worked around
allows a different expression of the basic aproach.  At the same time, I've
added a patch to install.texi to mention the workaround being in place, and
a testcase to make sure the structure passing bug isn't fixed and the
workaround left in place.

Bootstrapped on mips-sgi-irix6.5 without regressions, checked in on branch
and mainline, based on Mark's approval in private mail.

Unfortunately, there's currently a problem in the repository which inhibits
a checkin of the testcase:

> cvs ci ChangeLog gcc.c-torture/execute/20010724-1.c gcc.c-torture/execute/20010724-1.x
[edit commit message]
cvs server: [05:31:57] waiting for ro's lock in /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute

So here's a deadlock which can probably only be fixed by someone with shell
access to gcc.gnu.org.  I've no idea what caused this ;-(

	Rainer

-----------------------------------------------------------------------------
Rainer Orth, Faculty of Technology, Bielefeld University

Email: ro@TechFak.Uni-Bielefeld.DE


2001-07-24  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>

	* config/mips/irix6-libc-compat.c: New file.
	* config/mips/t-iris6 (LIB2FUNCS_STATIC_EXTRA): Use it.
	* doc/install.texi (Specific, mips*-sgi-irix6): Mention structure
	passing workaround.

	testsuite:
	* gcc.c-torture/execute/20010724-1.c: New file.
	* gcc.c-torture/execute/20010724-1.x: New file.

Index: config/mips/irix6-libc-compat.c
===================================================================
RCS file: irix6-libc-compat.c
diff -N irix6-libc-compat.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ irix6-libc-compat.c	Tue Jul 24 04:59:38 2001
@@ -0,0 +1,140 @@
+/* Compensate for inconsistent structure passing conventions on IRIX 6.  */
+/* Compile this one with gcc.  */
+/* Copyright (C) 2001  Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* GCC doesn't correctly implement the structure and union passing and return
+   conventions of the N32 and N64 ABIs on IRIX 6, as described in the
+   MIPSpro N32 ABI Handbook, ch. 2, Calling Convention Implementations, p.7.
+   The ABI requires that structures (or trailing parts of structures) smaller
+   than 8 bytes (a 64-bit register) are left-justified, whereas GCC
+   right-justifies them.
+
+   While GCC is internally consistent, calling routines compiled with a
+   compiler that does implement the documented ABI (like SGIs MIPSpro C
+   compiler) doesn't work.  This is primarily an issue for system libraries
+   like libc.  Fortunately, there exist only very few routines that take
+   structure value arguments or return structures by value, so until the
+   underlying bug is fixed, it is possible to work around it by providing
+   wrapper functions for the few affected routines that compensate for the
+   inconsistent alignment.
+
+   These wrappers rely on the fact that e.g. libc contains weak versions of
+   those routines, and the real implementation is provided by _-prefixed
+   variants.  So we can provide our own versions, which will only be linked
+   if the application uses any of the affected functions, calling the private
+   variants after shifting the arguments or results as required.
+
+   This is a rewrite of code created by Andy Polyakov.  */
+
+#include "config.h"
+#include "system.h"
+
+/* This must only be used for the N32 and N64 ABIs.  O32 is correct.  */
+
+#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
+
+/* The affected arguments need to be shifted by
+
+	BITS_PER_WORD - (sizeof (arg) * BITS_PER_UNIT).
+
+   Since only 32-bit args and results are involved, the shift count is
+   always 32.  */
+#define SHIFT_BITS	32
+
+extern machreg_t _inet_ntoa	PARAMS ((machreg_t));
+extern machreg_t _inet_lnaof	PARAMS ((machreg_t));
+extern machreg_t _inet_netof	PARAMS ((machreg_t));
+extern machreg_t _inet_makeaddr	PARAMS ((machreg_t, machreg_t));
+
+/* <arpa/inet.h> has
+
+	char *inet_ntoa (struct in_addr);
+
+   on both IRIX 6.2 and 6.5, with struct in_addr containing a 32-bit int.  */
+
+machreg_t
+inet_ntoa (machreg_t in)
+{
+  return _inet_ntoa (in << SHIFT_BITS);
+}
+
+/* <arpa/inet.h> has
+
+	unsigned long inet_lnaof (struct in_addr);		(IRIX 6.2)
+	in_addr_t inet_lnaof (struct in_addr);			(IRIX 6.5)
+
+   in_addr_t is a 32-bit int.  */
+
+machreg_t
+inet_lnaof (machreg_t in)
+{
+  return _inet_lnaof (in << SHIFT_BITS);
+}
+
+/* <arpa/inet.h> has
+
+	unsigned long inet_netof (struct in_addr);		(IRIX 6.2)
+	in_addr_t inet_netof (struct in_addr);			(IRIX 6.5)  */
+
+machreg_t
+inet_netof (machreg_t in)
+{
+  return _inet_netof (in << SHIFT_BITS);
+}
+
+/* <arpa/inet.h> has
+
+	struct in_addr inet_makeaddr (int, int);		(IRIX 6.2)
+	struct in_addr inet_makeaddr (in_addr_t, in_addr_t);	(IRIX 6.5)  */
+
+machreg_t
+inet_makeaddr (machreg_t net, machreg_t lna)
+{
+  return _inet_makeaddr (net, lna) >> SHIFT_BITS;
+}
+
+#if _MIPS_SIM == _ABIN32
+extern machreg_t _semctl	PARAMS ((machreg_t, machreg_t, machreg_t, machreg_t));
+
+/* <sys/sem.h> has
+
+	int semctl (int, int, int, ...);
+
+   where the variadic argument is union semun if used.  union semun contains
+   an int and two pointers, so the union is already 64 bits wide under the
+   N64 ABI and alignment is not an issue.  */
+
+machreg_t
+semctl (machreg_t semid, machreg_t semnum, machreg_t cmd, machreg_t arg)
+{
+  return _semctl(semid, semnum, cmd, arg << SHIFT_BITS);
+}
+#endif /* _ABIN32 */
+
+#endif /* _ABIN32 || _ABI64 */
Index: config/mips/t-iris6
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/t-iris6,v
retrieving revision 1.8.4.1
diff -u -p -r1.8.4.1 t-iris6
--- t-iris6	2001/06/13 05:05:41	1.8.4.1
+++ t-iris6	2001/07/24 11:59:38
@@ -53,3 +53,7 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
 	echo '#define FLOAT' > fp-bit.c
 	echo '#undef US_SOFTWARE_GOFAST' >> fp-bit.c
 	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+# This is only needed in the static libgcc as a band-aid until gcc correctly
+# implements the N32/N64 ABI structure passing conventions
+LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/irix6-libc-compat.c
Index: doc/install.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/install.texi,v
retrieving revision 1.1.2.43
diff -u -p -r1.1.2.43 install.texi
--- install.texi	2001/07/20 16:35:55	1.1.2.43
+++ install.texi	2001/07/24 11:59:39
@@ -2779,7 +2779,8 @@ GCC is consistent with itself, but not c
 happen are when there are library functions that take/return such
 structures. There are very few such library functions.  Currently this
 is known to affect @code{inet_ntoa}, @code{inet_lnaof},
-@code{inet_netof}, @code{inet_makeaddr}, and @code{semctl}.
+@code{inet_netof}, @code{inet_makeaddr}, and @code{semctl}.  Until the
+bug is fixed, GCC contains workarounds for the known affected functions.
 
 See @uref{http://freeware.sgi.com/,,http://freeware.sgi.com/} for more
 information about using GCC on IRIX platforms.
Index: testsuite/gcc.c-torture/execute/20010724-1.c
===================================================================
RCS file: 20010724-1.c
diff -N 20010724-1.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ 20010724-1.c	Tue Jul 24 04:59:40 2001
@@ -0,0 +1,59 @@
+/* Verify that the workarounds in config/mips/irix6-libc-compat.c are still
+   needed.  */
+
+/* IRIX 6, unlike other Unix systems, defines union semun in <sys/sem.h>.
+   Inhibit this definition to be able to run this test on other platforms.  */
+#define _XOPEN_SOURCE
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+union semun {
+  int val;
+  struct semid_ds *buf;
+  ushort_t *array;
+};
+
+int
+main (void)
+{
+  struct in_addr ia;
+  int semid;
+  union semun su;
+
+  ia.s_addr = INADDR_BROADCAST;
+
+  if (strcmp (inet_ntoa (ia), "255.255.255.255") != 0)
+    abort ();
+
+  ia.s_addr = INADDR_LOOPBACK;
+
+  if (inet_lnaof (ia) != 1)
+    abort ();
+
+  if (inet_netof (ia) != IN_LOOPBACKNET)
+    abort ();
+
+  ia = inet_makeaddr (IN_LOOPBACKNET, 1);
+  if (ia.s_addr != INADDR_LOOPBACK)
+    abort ();
+
+  if ((semid = semget (IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | SEM_R | SEM_A)) < 0)
+    abort ();
+
+  su.val = 10;
+
+  if (semctl (semid, 0, SETVAL, su) != 0)
+    abort ();
+
+  if (semctl (semid, 0, GETVAL) != 10)
+    abort ();
+
+  if (semctl (semid, 0, IPC_RMID) != 0)
+    abort ();
+
+  return 0;
+}
Index: testsuite/gcc.c-torture/execute/20010724-1.x
===================================================================
RCS file: 20010724-1.x
diff -N 20010724-1.x
--- /dev/null	Tue May  5 13:32:27 1998
+++ 20010724-1.x	Tue Jul 24 04:59:40 2001
@@ -0,0 +1,3 @@
+# This test is only needed on IRIX 6
+if { ! [istarget "mips*-sgi-irix6*"] } { return 1 }
+return 0


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