Miscompilation of glibc by GCC 3.5?

Andreas Jaeger aj@suse.de
Thu May 27 15:46:00 GMT 2004


glibc cannot be compiled by current 3.5 mainline on AMD64 (but same
situation on ia64).  I've reduced the error to the following example:

extern int __internal_getnetgrent_r (void);

static int
internal_getnetgrent_r (void)
{
  return 1;
}

extern __typeof (internal_getnetgrent_r) __internal_getnetgrent_r __attribute__ ((alias ("internal_getnetgrent_r")));

int
test (void)
{
  return internal_getnetgrent_r ();
  
}

With GCC 3.5 of today I get internal_getnetgrent_r undefined:

reger:/tmp:[0]$ /opt/gcc/3.5-devel/bin/gcc -O2 -c test.c
reger:/tmp:[0]$ nm test.o
                 U internal_getnetgrent_r
0000000000000000 T test
reger:/tmp:[0]$ /opt/gcc/3.5-devel/bin/gcc -O2 -c test.c
reger:/tmp:[0]$ nm test.o
                 U internal_getnetgrent_r
0000000000000000 T test

But older GCC versions (3.3 and 3.4.0) produce:

reger:/tmp:[0]$ gcc -O2 -c test.c
reger:/tmp:[0]$ nm test.o
0000000000000000 T __internal_getnetgrent_r
0000000000000000 t internal_getnetgrent_r
0000000000000010 T test
reger:/tmp:[0]$ /opt/gcc/3.4-devel/bin/gcc -O2 -c test.c
reger:/tmp:[0]$ nm test.o
0000000000000000 T __internal_getnetgrent_r
0000000000000000 t internal_getnetgrent_r
0000000000000010 T test

Is this a bug in glibc or in GCC?

3.5 inlines the code but 3.4 not, the difference in the assembler is:

--- test-3.5.s      2004-05-27 17:40:11.255202552 +0200
+++ test-3.4.s  2004-05-27 17:39:51.789864313 +0200
@@ -2,14 +2,20 @@
 .globl __internal_getnetgrent_r
        .set    __internal_getnetgrent_r,internal_getnetgrent_r
        .text
-       .align 4
+       .p2align 4,,15
+       .type   internal_getnetgrent_r, @function
+internal_getnetgrent_r:
+.LFB2:
+       movl    $1, %eax
+       ret
+.LFE2:
+       .size   internal_getnetgrent_r, .-internal_getnetgrent_r
        .p2align 4,,15
 .globl test
        .type   test, @function
 test:
 .LFB3:
-       movl    $1, %eax
-       ret
+       jmp     internal_getnetgrent_r
 .LFE3:
        .size   test, .-test
        .section        .eh_frame,"a",@progbits


It seems the following statement:
.set    __internal_getnetgrent_r,internal_getnetgrent_r

should not be emitted if the function is inlined.

Should I file a bugreport for 3.5?

Andreas
-- 
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQBAtgz2OJpWPMJyoSYRAmOdAJ9yrXE5SvKPv/H4mJum8TwL3gbkgwCeO2T2
aSgzwXVc0v+7UqCWU7eMpBw=
=v9sD
-----END PGP SIGNATURE-----From stevenb@suse.de Thu May 27 15:52:00 2004
From: Steven Bosscher <stevenb@suse.de>
To: Paolo Bonzini <bonzini@gnu.org>, Jan Hubicka <jh@suse.cz>
Cc: ebotcazou@act-europe.fr, mckinlay@redhat.com, jlquinn@optonline.net, "gcc@gcc.gnu.org" <gcc@gcc.gnu.org>, dnovillo@redhat.com
Subject: Re: Mainline broken on alpha and x86-64.  SPEC2000's eon does not build.
Date: Thu, 27 May 2004 15:52:00 -0000
Message-id: <200405271751.31247.stevenb@suse.de>
References: <1085667394.9713.217.camel@localhost.localdomain> <20040527144428.GE26500@kam.mff.cuni.cz> <40B60C9D.2080309@gnu.org>
X-SW-Source: 2004-05/msg01362.html
Content-length: 5011

On Thursday 27 May 2004 17:43, Paolo Bonzini wrote:
> I've got a lot of failures everywhere but in C, and it seems unlikely
> that the cause is the floating-point comparison patch I've been
> discussing with Roger.  I'm trying to apply that patch to a 2-days old
> tree and seeing what happens (though I'm leaving the office soon and
> will be able to look at the results only tomorrow morning).

It's EH related, I somehow overlooked the fact that tree-eh.c
also builds a SWITCH_EXPR for try-finally, and the label vector
for that switch isn't necessarily sorted.

I am trying the attached patch.  You might too.

Gr.
Steven

Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.6
diff -c -3 -p -r2.6 gimplify.c
*** gimplify.c	26 May 2004 22:36:49 -0000	2.6
--- gimplify.c	27 May 2004 15:46:51 -0000
*************** compare_case_labels (const void *p1, con
*** 994,999 ****
--- 994,1016 ----
    return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
  }
  
+ /* Sort the case labels in LABEL_VEC in ascending order.  */
+ 
+ void
+ sort_case_labels (tree label_vec)
+ {
+   size_t len = TREE_VEC_LENGTH (label_vec);
+   tree default_case = TREE_VEC_ELT (label_vec, len - 1);
+ 
+   if (CASE_LOW (default_case))
+     /* The last label in the vector should be the default case
+        but it is not.  */
+     abort ();
+ 
+   qsort (&TREE_VEC_ELT (label_vec, 0), len - 1, sizeof (tree),
+ 	 compare_case_labels);
+ }
+ 
  /* Gimplify a SWITCH_EXPR, and collect a TREE_VEC of the labels it can
     branch to.  */
  
*************** gimplify_switch_expr (tree *expr_p, tree
*** 1057,1068 ****
        else
  	*expr_p = SWITCH_BODY (switch_expr);
  
-       qsort (&VARRAY_TREE (labels, 0), len, sizeof (tree),
- 	     compare_case_labels);
        for (i = 0; i < len; ++i)
  	TREE_VEC_ELT (label_vec, i) = VARRAY_TREE (labels, i);
        TREE_VEC_ELT (label_vec, len) = default_case;
  
        SWITCH_BODY (switch_expr) = NULL;
      }
    else if (!SWITCH_LABELS (switch_expr))
--- 1074,1085 ----
        else
  	*expr_p = SWITCH_BODY (switch_expr);
  
        for (i = 0; i < len; ++i)
  	TREE_VEC_ELT (label_vec, i) = VARRAY_TREE (labels, i);
        TREE_VEC_ELT (label_vec, len) = default_case;
  
+       sort_case_labels (label_vec);
+ 
        SWITCH_BODY (switch_expr) = NULL;
      }
    else if (!SWITCH_LABELS (switch_expr))
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.4
diff -c -3 -p -r2.4 tree-cfg.c
*** tree-cfg.c	26 May 2004 22:36:49 -0000	2.4
--- tree-cfg.c	27 May 2004 15:47:10 -0000
*************** find_case_label_for_value (tree switch_e
*** 2051,2057 ****
        /* Cache the result of comparing CASE_LOW and val.  */
        cmp = tree_int_cst_compare (CASE_LOW (t), val);
  
!       if (cmp > 0)
  	high = i;
        else
  	low = i;
--- 2051,2057 ----
        /* Cache the result of comparing CASE_LOW and val.  */
        cmp = tree_int_cst_compare (CASE_LOW (t), val);
  
!       if (cmp >= 0)
  	high = i;
        else
  	low = i;
Index: tree-eh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-eh.c,v
retrieving revision 2.1
diff -c -3 -p -r2.1 tree-eh.c
*** tree-eh.c	13 May 2004 06:39:48 -0000	2.1
--- tree-eh.c	27 May 2004 15:47:10 -0000
*************** lower_try_finally_switch (struct leh_sta
*** 1200,1207 ****
    replace_goto_queue (tf);
    last_case_index += nlabels;
  
!   /* Make sure that we have a default label, as one is required.  */
    CASE_LOW (last_case) = NULL;
  
    /* Need to link switch_stmt after running replace_goto_queue due
       to not wanting to process the same goto stmts twice.  */
--- 1200,1211 ----
    replace_goto_queue (tf);
    last_case_index += nlabels;
  
!   /* Make sure that the last case is the default label, as one is required.
!      Then sort the labels, which is also required in GIMPLE.  */
!   last_case = TREE_VEC_ELT (case_label_vec,
! 			    TREE_VEC_LENGTH (case_label_vec) - 1);
    CASE_LOW (last_case) = NULL;
+   sort_case_labels (case_label_vec);
  
    /* Need to link switch_stmt after running replace_goto_queue due
       to not wanting to process the same goto stmts twice.  */
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.500
diff -c -3 -p -r1.500 tree.h
*** tree.h	26 May 2004 23:22:04 -0000	1.500
--- tree.h	27 May 2004 15:47:13 -0000
*************** extern tree create_artificial_label (voi
*** 3675,3680 ****
--- 3675,3681 ----
  extern void gimplify_function_tree (tree);
  extern const char *get_name (tree);
  extern tree unshare_expr (tree);
+ extern void sort_case_labels (tree);
  
  /* If KIND=='I', return a suitable global initializer (constructor) name.
     If KIND=='D', return a suitable global clean-up (destructor) name.  */


More information about the Gcc mailing list