This is the mail archive of the gcc@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]

Re: gcc.dg/compat/struct-layout-1.exp does not supported installed-compilertesting


Ian Lance Taylor wrote:

1. Remove the use of config.h and HAVE_*_H.

2. Modify the generator not to depend on libiberty headers, including
hashtab.h, by substituting a simple dictonary object.

3. Adjust struct-layout-1.exp accordingly.
This is what I would recommend anyhow.

Done with the attached patch. Tested on x86_64-unknown-linux-gnu by comparing the generated files with and without the patch, as well as by running the testsuite. The time taken to run the struct layout tests (including their generation) was not measurably different before and after the change. Applied to 4.0 and mainline.


I cribbed a bit from libiberty, but didn't take all of hashtab.c, as that just seemed excessive.

Please report any problems to me, of course.

(There's still a POSIX-ism in the generator, in that it tries to write to "/dev/null". On Windows systems, I bet this will often work, but create a real file with that name. It would be better, and avoid portability problems, to guard the calls to fwrite, etc., with "if (file)" rather than spew to "/dev/null", but that's for another day.)

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
(916) 791-8304
2005-05-16  Mark Mitchell  <mark@codesourcery.com>

	* gcc.dg/compat/generate-random.c (config.h): Do not include.
	(limits.h): Include unconditionally.
	(stdlib.h): Likewise.
	* gcc.dg/compat/generate-random_r.c (config.h): Do not include.
	(limits.h): Include unconditionally.
	(stdlib.h): Likewise.
	* gcc.dg/compat/struct-layout-1.exp: Do not link with libiberty.
	* gcc.dg/compat/struct-layout-1_generate.c (config.h): Do not include.
	(limits.h): Include unconditionally.
	(stdlib.h): Likewise. 
	(hashtab.h): Do not include.
	(getopt.h): Likewise.
	(stddef.h): Include.
	(hashval_t): Define.
	(struct entry): Add "next" field.
	(HASH_SIZE): New macro.
	(hash_table): New variable.
	(switchfiles): Do not use xmalloc.
	(mix): New macro.
	(iterative_hash): New function.
	(hasht): Remove.
	(e_exists): New function.
	(e_insert): Likewise.
	(output): Use, instead of libiberty hashtable functions.
	(main): Do not use getopt.  Do not call htab_create.
	
Index: gcc.dg/compat/generate-random.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/compat/generate-random.c,v
retrieving revision 1.2
diff -c -5 -p -r1.2 generate-random.c
*** gcc.dg/compat/generate-random.c	6 Nov 2004 19:28:43 -0000	1.2
--- gcc.dg/compat/generate-random.c	16 May 2005 22:45:12 -0000
***************
*** 49,66 ****
     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     SUCH DAMAGE.*/
  
- #include "config.h"
- #ifdef HAVE_LIMITS_H
  #include <limits.h>
- #endif
  #include "libiberty.h"
- #ifdef HAVE_STDLIB_H
  #include <stdlib.h>
- #endif
  #include "generate-random.h"
  
  
  /* An improved random number generation package.  In addition to the standard
     rand()/srand() like interface, this package also has a special state info
--- 49,61 ----
Index: gcc.dg/compat/generate-random_r.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/compat/generate-random_r.c,v
retrieving revision 1.1
diff -c -5 -p -r1.1 generate-random_r.c
*** gcc.dg/compat/generate-random_r.c	23 Jul 2004 22:36:46 -0000	1.1
--- gcc.dg/compat/generate-random_r.c	16 May 2005 22:45:12 -0000
***************
*** 50,67 ****
   *	@(#)random.c	5.5 (Berkeley) 7/6/88
   * It was reworked for the GNU C Library by Roland McGrath.
   * Rewritten to be reentrant by Ulrich Drepper, 1995
   */
  
- #include "config.h"
- #ifdef HAVE_LIMITS_H
  #include <limits.h>
- #endif
  #include "libiberty.h"
- #ifdef HAVE_STDLIB_H
  #include <stdlib.h>
- #endif
  #include "generate-random.h"
  
  
  /* An improved random number generation package.  In addition to the standard
     rand()/srand() like interface, this package also has a special state info
--- 50,62 ----
Index: gcc.dg/compat/struct-layout-1.exp
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/compat/struct-layout-1.exp,v
retrieving revision 1.2
diff -c -5 -p -r1.2 struct-layout-1.exp
*** gcc.dg/compat/struct-layout-1.exp	4 Aug 2004 01:43:30 -0000	1.2
--- gcc.dg/compat/struct-layout-1.exp	16 May 2005 22:45:12 -0000
*************** set tstobjdir "$tmpdir/gcc.dg-struct-lay
*** 100,113 ****
  set generator "$tmpdir/gcc.dg-struct-layout-1_generate"
  
  set generator_src "$srcdir/$subdir/struct-layout-1_generate.c"
  set generator_src "$generator_src $srcdir/$subdir/generate-random.c"
  set generator_src "$generator_src $srcdir/$subdir/generate-random_r.c"
! set generator_inc "-I$srcdir/$subdir -I$srcdir/../../include"
! set generator_inc "$generator_inc -I$rootme/../libiberty"
! set generator_lib "-L$rootme/../libiberty -liberty"
! set generator_cmd "-o $generator $generator_src $generator_inc $generator_lib"
  
  set status [remote_exec host "$HOSTCC $HOSTCFLAGS $generator_cmd"]
  set status [lindex $status 0]
  if { $status == 0 } then {
      file delete -force $tstobjdir
--- 100,110 ----
  set generator "$tmpdir/gcc.dg-struct-layout-1_generate"
  
  set generator_src "$srcdir/$subdir/struct-layout-1_generate.c"
  set generator_src "$generator_src $srcdir/$subdir/generate-random.c"
  set generator_src "$generator_src $srcdir/$subdir/generate-random_r.c"
! set generator_cmd "-o $generator $generator_src"
  
  set status [remote_exec host "$HOSTCC $HOSTCFLAGS $generator_cmd"]
  set status [lindex $status 0]
  if { $status == 0 } then {
      file delete -force $tstobjdir
Index: gcc.dg/compat/struct-layout-1_generate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c,v
retrieving revision 1.4
diff -c -5 -p -r1.4 struct-layout-1_generate.c
*** gcc.dg/compat/struct-layout-1_generate.c	24 Apr 2005 22:01:53 -0000	1.4
--- gcc.dg/compat/struct-layout-1_generate.c	16 May 2005 22:45:12 -0000
*************** for more details.
*** 17,51 ****
  You should have received a copy of the GNU General Public License
  along with GCC; see the file COPYING.  If not, write to the Free
  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.  */
  
! /* Compile with gcc -I$(srcdir)/../include -{I,L}$(objdir)/../libiberty/ \
!    -o struct-layout-1_generate{,.c} generate_random{,_r}.c -liberty */
  
! #include "config.h"
! #ifdef HAVE_LIMITS_H
  #include <limits.h>
- #endif
- #include "libiberty.h"
  #include <stdio.h>
- #ifdef HAVE_STDLIB_H
  #include <stdlib.h>
- #endif
- #ifdef HAVE_STRING_H
  #include <string.h>
! #endif
! #include "hashtab.h"
! #include "getopt.h"
  /* We use our own pseudo-random number generator, so that it gives the same
     values on all hosts.  */
  #include "generate-random.h"
  
  #if LLONG_MAX != 9223372036854775807LL && __LONG_LONG_MAX__ != 9223372036854775807LL
  # error Need 64-bit long long
  #endif
  
  enum TYPE
  {
    TYPE_INT,
    TYPE_UINT,
    TYPE_CINT,
--- 17,45 ----
  You should have received a copy of the GNU General Public License
  along with GCC; see the file COPYING.  If not, write to the Free
  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.  */
  
! /* Compile with gcc -o struct-layout-1_generate{,.c} generate_random{,_r}.c */
  
! /* N.B. -- This program cannot use libiberty as that will not work
!    when testing an installed compiler.  */
  #include <limits.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
! #include <stddef.h>
  /* We use our own pseudo-random number generator, so that it gives the same
     values on all hosts.  */
  #include "generate-random.h"
  
  #if LLONG_MAX != 9223372036854775807LL && __LONG_LONG_MAX__ != 9223372036854775807LL
  # error Need 64-bit long long
  #endif
  
+ typedef unsigned int hashval_t;
+ 
  enum TYPE
  {
    TYPE_INT,
    TYPE_UINT,
    TYPE_CINT,
*************** struct entry
*** 652,663 ****
--- 646,663 ----
  #endif
    unsigned short len;
    unsigned char arr_len;
    struct types *type;
    const char *attrib;
+   /* Used to chain together entries in the hash table.  */
+   struct entry *next;
  };
  
+ /* A prime number giving the number of slots in the hash table.  */ 
+ #define HASH_SIZE 32749 
+ static struct entry *hash_table[HASH_SIZE];
+ 
  static int idx, limidx, output_one;
  static const char *destdir;
  static const char *srcdir;
  FILE *outfile;
  
*************** switchfiles (int fields)
*** 675,685 ****
        return;
      }
    if (destbuf == NULL)
      {
        size_t len = strlen (destdir);
!       destbuf = xmalloc (len + 20);
        memcpy (destbuf, destdir, len);
        if (!len || destbuf[len - 1] != '/')
  	destbuf[len++] = '/';
        destptr = destbuf + len;
      }
--- 675,687 ----
        return;
      }
    if (destbuf == NULL)
      {
        size_t len = strlen (destdir);
!       destbuf = malloc (len + 20);
!       if (!destbuf)
! 	abort ();
        memcpy (destbuf, destdir, len);
        if (!len || destbuf[len - 1] != '/')
  	destbuf[len++] = '/';
        destptr = destbuf + len;
      }
*************** subvalues (struct entry *e, char *p, cha
*** 1129,1138 ****
--- 1131,1279 ----
  	output_FNB ('B', e);
        return 1;
      }
  }
  
+ /* DERIVED FROM:
+ --------------------------------------------------------------------
+ lookup2.c, by Bob Jenkins, December 1996, Public Domain.
+ hash(), hash2(), hash3, and mix() are externally useful functions.
+ Routines to test the hash are included if SELF_TEST is defined.
+ You can use this free for any purpose.  It has no warranty.
+ --------------------------------------------------------------------
+ */
+ 
+ /*
+ --------------------------------------------------------------------
+ mix -- mix 3 32-bit values reversibly.
+ For every delta with one or two bit set, and the deltas of all three
+   high bits or all three low bits, whether the original value of a,b,c
+   is almost all zero or is uniformly distributed,
+ * If mix() is run forward or backward, at least 32 bits in a,b,c
+   have at least 1/4 probability of changing.
+ * If mix() is run forward, every bit of c will change between 1/3 and
+   2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
+ mix() was built out of 36 single-cycle latency instructions in a 
+   structure that could supported 2x parallelism, like so:
+       a -= b; 
+       a -= c; x = (c>>13);
+       b -= c; a ^= x;
+       b -= a; x = (a<<8);
+       c -= a; b ^= x;
+       c -= b; x = (b>>13);
+       ...
+   Unfortunately, superscalar Pentiums and Sparcs can't take advantage 
+   of that parallelism.  They've also turned some of those single-cycle
+   latency instructions into multi-cycle latency instructions.  Still,
+   this is the fastest good hash I could find.  There were about 2^^68
+   to choose from.  I only looked at a billion or so.
+ --------------------------------------------------------------------
+ */
+ /* same, but slower, works on systems that might have 8 byte hashval_t's */
+ #define mix(a,b,c) \
+ { \
+   a -= b; a -= c; a ^= (c>>13); \
+   b -= c; b -= a; b ^= (a<< 8); \
+   c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
+   a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
+   b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
+   c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
+   a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
+   b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
+   c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
+ }
+ 
+ /*
+ --------------------------------------------------------------------
+ hash() -- hash a variable-length key into a 32-bit value
+   k     : the key (the unaligned variable-length array of bytes)
+   len   : the length of the key, counting by bytes
+   level : can be any 4-byte value
+ Returns a 32-bit value.  Every bit of the key affects every bit of
+ the return value.  Every 1-bit and 2-bit delta achieves avalanche.
+ About 36+6len instructions.
+ 
+ The best hash table sizes are powers of 2.  There is no need to do
+ mod a prime (mod is sooo slow!).  If you need less than 32 bits,
+ use a bitmask.  For example, if you need only 10 bits, do
+   h = (h & hashmask(10));
+ In which case, the hash table should have hashsize(10) elements.
+ 
+ If you are hashing n strings (ub1 **)k, do it like this:
+   for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
+ 
+ By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.  You may use this
+ code any way you wish, private, educational, or commercial.  It's free.
+ 
+ See http://burtleburtle.net/bob/hash/evahash.html
+ Use for hash table lookup, or anything where one collision in 2^32 is
+ acceptable.  Do NOT use for cryptographic purposes.
+ --------------------------------------------------------------------
+ */
+ 
+ static hashval_t
+ iterative_hash (const void *k_in /* the key */,
+                 register size_t  length /* the length of the key */,
+                 register hashval_t initval /* the previous hash, or
+                                               an arbitrary value */)
+ {
+   register const unsigned char *k = (const unsigned char *)k_in;
+   register hashval_t a,b,c,len;
+ 
+   /* Set up the internal state */
+   len = length;
+   a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
+   c = initval;           /* the previous hash value */
+ 
+   /*---------------------------------------- handle most of the key */
+ #ifndef WORDS_BIGENDIAN
+   /* On a little-endian machine, if the data is 4-byte aligned we can hash
+      by word for better speed.  This gives nondeterministic results on
+      big-endian machines.  */
+   if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
+     while (len >= 12)    /* aligned */
+       {
+ 	a += *(hashval_t *)(k+0);
+ 	b += *(hashval_t *)(k+4);
+ 	c += *(hashval_t *)(k+8);
+ 	mix(a,b,c);
+ 	k += 12; len -= 12;
+       }
+   else /* unaligned */
+ #endif
+     while (len >= 12)
+       {
+ 	a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
+ 	b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
+ 	c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
+ 	mix(a,b,c);
+ 	k += 12; len -= 12;
+       }
+ 
+   /*------------------------------------- handle the last 11 bytes */
+   c += length;
+   switch(len)              /* all the case statements fall through */
+     {
+     case 11: c+=((hashval_t)k[10]<<24);
+     case 10: c+=((hashval_t)k[9]<<16);
+     case 9 : c+=((hashval_t)k[8]<<8);
+       /* the first byte of c is reserved for the length */
+     case 8 : b+=((hashval_t)k[7]<<24);
+     case 7 : b+=((hashval_t)k[6]<<16);
+     case 6 : b+=((hashval_t)k[5]<<8);
+     case 5 : b+=k[4];
+     case 4 : a+=((hashval_t)k[3]<<24);
+     case 3 : a+=((hashval_t)k[2]<<16);
+     case 2 : a+=((hashval_t)k[1]<<8);
+     case 1 : a+=k[0];
+       /* case 0: nothing left to add */
+     }
+   mix(a,b,c);
+   /*-------------------------------------------- report the result */
+   return c;
+ }
+ 
  hashval_t
  e_hash (const void *a)
  {
    const struct entry *e = a;
    hashval_t ret = 0;
*************** e_eq (const void *a, const void *b)
*** 1174,1202 ****
  	return 0;
      }
    return 1;
  }
  
! htab_t hasht;
  
  void
  output (struct entry *e)
  {
    int i;
    char c;
!   void **p;
    const char *skip_cint = "";
  
    if (e[0].etype != ETYPE_STRUCT && e[0].etype != ETYPE_UNION)
      abort ();
  
!   p = htab_find_slot (hasht, e, INSERT);
!   if (*p != NULL)
      return;
  
!   *p = malloc ((e[0].len + 1) * sizeof (struct entry));
!   memcpy (*p, e, (e[0].len + 1) * sizeof (struct entry));
  
    if (idx == limidx)
      switchfiles (e[0].len);
  
    for (i = 1; i <= e[0].len; ++i)
--- 1315,1364 ----
  	return 0;
      }
    return 1;
  }
  
! static int 
! e_exists (const struct entry *e) 
! {
!   struct entry *h;
!   hashval_t hval;
! 
!   hval = e_hash (e);
!   for (h = hash_table[hval % HASH_SIZE]; h; h = h->next)
!     if (e_eq (e, h))
!       return 1;
!   return 0;
! }
! 
! static void
! e_insert (struct entry *e)
! {
!   hashval_t hval;
! 
!   hval = e_hash (e);
!   e->next = hash_table[hval % HASH_SIZE];
!   hash_table[hval % HASH_SIZE] = e;
! }
  
  void
  output (struct entry *e)
  {
    int i;
    char c;
!   struct entry *n;
    const char *skip_cint = "";
  
    if (e[0].etype != ETYPE_STRUCT && e[0].etype != ETYPE_UNION)
      abort ();
  
!   if (e_exists (e))
      return;
  
!   n = (struct entry *) malloc ((e[0].len + 1) * sizeof (struct entry));
!   memcpy (n, e, (e[0].len + 1) * sizeof (struct entry));
!   e_insert (n);
  
    if (idx == limidx)
      switchfiles (e[0].len);
  
    for (i = 1; i <= e[0].len; ++i)
*************** features[] = {
*** 1643,1675 ****
  
  int
  main (int argc, char **argv)
  {
    int i, j, count, c, n = 3000;
  
    if (sizeof (int) != 4 || sizeof (long long) != 8)
      return 1;
! 
!   while ((c = getopt (argc, argv, "d:i:n:s:")) != -1)
!     switch (c)
!       {
!       case 'n':
! 	n = atoi (optarg);
! 	break;
!       case 'd':
! 	destdir = optarg;
! 	break;
!       case 's':
! 	srcdir = optarg;
! 	break;
!       case 'i':
! 	output_one = 1;
! 	limidx = atoi (optarg);
! 	break;
!       default:
  	goto usage;
        }
  
    if (output_one)
      {
        outfile = fopen ("/dev/null", "w");
        if (outfile == NULL)
--- 1805,1849 ----
  
  int
  main (int argc, char **argv)
  {
    int i, j, count, c, n = 3000;
+   char *optarg;
  
    if (sizeof (int) != 4 || sizeof (long long) != 8)
      return 1;
!   
!   i = 1;
!   while (i < argc) 
!     {
!       c = '\0';
!       if (argv[i][0] == '-' && argv[i][2] == '\0')
! 	c = argv[i][1];
!       optarg = argv[i + 1];
!       if (!optarg)
  	goto usage;
+       switch (c)
+ 	{
+ 	case 'n':
+ 	  n = atoi (optarg);
+ 	  break;
+ 	case 'd':
+ 	  destdir = optarg;
+ 	  break;
+ 	case 's':
+ 	  srcdir = optarg;
+ 	  break;
+ 	case 'i':
+ 	  output_one = 1;
+ 	  limidx = atoi (optarg);
+ 	  break;
+ 	default:
+ 	  fprintf (stderr, "unrecognized option %s\n", argv[i]);
+ 	  goto usage;
        }
+       i += 2;
+     }
  
    if (output_one)
      {
        outfile = fopen ("/dev/null", "w");
        if (outfile == NULL)
*************** Either -s srcdir -d destdir or -i idx mu
*** 1690,1700 ****
      }
  
    if (srcdir == NULL && !output_one)
      goto usage;
  
-   hasht = htab_create (40000, e_hash, e_eq, NULL);
    for (i = 0; i < NTYPES2; ++i)
      if (base_types[i].bitfld)
        bitfld_types[n_bitfld_types++] = base_types[i];
    for (i = 0; i < NATYPES2; ++i)
      if (attrib_types[i].bitfld)
--- 1864,1873 ----

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