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