/* gcc430-tagged-ptr-bug.c * * This program illustrates a miscompilation with gcc-4.3.0. * * The failing code (try_a() below) initialises a Lisp-like * CONS cell in an on-stack mini-heap, then passes a tagged * pointer to this object in a tail-recursive call. * * With gcc-4.3.0, the reservation of space on the stack and * the initialisation of it is REMOVED. Instead the code just * constructs a pointer as an offset from the stack pointer * and passes that in the call, causing failures in the callee. * * This error has been observed on x86_64, sparc64, and powerpc. * It still occurs with the gcc-4.3-20080515 snapshot. * * Compiling with -fno-strict-aliasing does NOT fix the problem. * * This code works with all older gccs up to and including 4.2.4. * * The functions try_a(), try_b(), and try_c() explore different * ways of passing the object reference: * - try_c() passes it as a tagged (offset by 3) void* * this works * - try_b() passes it as an untagged uintptr_t * this works * - try_a() passes it as a tagged uintptr_t * this fails * * The original code which broke due to this problem is in the * virtual machine for the Erlang functional programming language, * specifically the ets_match_2() and ets_match_3() functions * in the erl_db.c module. */ #include <stdio.h> typedef unsigned long my_uintptr_t; int check_a(my_uintptr_t tagged_ptr); int check_b(my_uintptr_t untagged_ptr); int check_c(void *tagged_ptr); int __attribute__((noinline)) try_a(my_uintptr_t x) { my_uintptr_t heap[2]; my_uintptr_t *hp = heap; hp[0] = x; hp[1] = 0; return check_a((my_uintptr_t)(void*)((char*)hp + 1)); } int __attribute__((noinline)) check_a(my_uintptr_t tagged_ptr) { my_uintptr_t *hp = (my_uintptr_t*)(void*)((char*)tagged_ptr - 1); if (hp[0] == 42 && hp[1] == 0) return 0; printf("try_a() is broken\n"); return -1; } int __attribute__((noinline)) try_b(my_uintptr_t x) { my_uintptr_t heap[2]; my_uintptr_t *hp = heap; hp[0] = x; hp[1] = 0; return check_b((my_uintptr_t)(void*)hp + 0); } int __attribute__((noinline)) check_b(my_uintptr_t untagged_ptr) { my_uintptr_t *hp = (my_uintptr_t*)(void*)(untagged_ptr - 0); if (hp[0] == 43 && hp[1] == 0) return 0; printf("try_b() is broken\n"); return -1; } int __attribute__((noinline)) try_c(my_uintptr_t x) { my_uintptr_t heap[2]; my_uintptr_t *hp = heap; hp[0] = x; hp[1] = 0; return check_c((void*)((char*)hp + 3)); } int __attribute__((noinline)) check_c(void *tagged_ptr) { my_uintptr_t *hp = (my_uintptr_t*)((char*)tagged_ptr - 3); if (hp[0] == 27 && hp[1] == 0) return 0; printf("try_c() is broken\n"); return -1; } int main(void) { int ret = 0; if (try_a(42) < 0) /* fails with gcc-4.3.0 */ ret += 1; if (try_b(43) < 0) /* works */ ret += 2; if (try_c(27) < 0) /* works */ ret += 4; if (ret == 0) printf("OK\n"); return ret; }
Confirmed.
I'll have a look.
I have a patch.
Subject: Bug 36339 Author: rguenth Date: Tue May 27 13:21:07 2008 New Revision: 136030 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=136030 Log: 2008-05-27 Richard Guenther <rguenther@suse.de> PR tree-optimization/36339 * tree-ssa-alias.c (set_initial_properties): Escaped pt_anything pointers cause all addressable variables to be call clobbered. * gcc.c-torture/execute/pr36339.c: New testcase. * gcc.dg/tree-ssa/loadpre8.c: XFAIL. Added: trunk/gcc/testsuite/gcc.c-torture/execute/pr36339.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.dg/tree-ssa/loadpre8.c trunk/gcc/tree-ssa-alias.c
Subject: Bug 36339 Author: rguenth Date: Tue May 27 13:23:34 2008 New Revision: 136031 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=136031 Log: 2008-05-27 Richard Guenther <rguenther@suse.de> PR tree-optimization/36339 * tree-ssa-alias.c (set_initial_properties): Escaped pt_anything pointers cause all addressable variables to be call clobbered. * gcc.c-torture/execute/pr36339.c: New testcase. * gcc.dg/tree-ssa/loadpre8.c: XFAIL. Added: branches/gcc-4_3-branch/gcc/testsuite/gcc.c-torture/execute/pr36339.c Modified: branches/gcc-4_3-branch/gcc/ChangeLog branches/gcc-4_3-branch/gcc/testsuite/ChangeLog branches/gcc-4_3-branch/gcc/testsuite/gcc.dg/tree-ssa/loadpre8.c branches/gcc-4_3-branch/gcc/tree-ssa-alias.c
Fixed.
(In reply to comment #6) > Fixed. > I added the fix to the latest gcc-4.3 snapshot and bootstrapped it. I then tested both the original application that failed (Erlang) as well as the latest Linux kernel. Both built and worked fine. Thank you for fixing this so quickly.
Subject: Bug 36339 Author: rguenth Date: Wed May 28 14:45:57 2008 New Revision: 136100 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=136100 Log: 2008-05-28 Richard Guenther <rguenther@suse.de> PR tree-optimization/36339 * tree-ssa-alias.c (set_initial_properties): Move pt_anything and clobbering code out of the loop. Modified: trunk/gcc/ChangeLog trunk/gcc/tree-ssa-alias.c
Subject: Bug 36339 Author: rguenth Date: Wed May 28 14:52:07 2008 New Revision: 136101 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=136101 Log: 2008-05-28 Richard Guenther <rguenther@suse.de> PR tree-optimization/36339 * tree-ssa-alias.c (set_initial_properties): Move pt_anything and subvariable clobbering code out of the loop. Modified: branches/gcc-4_3-branch/gcc/ChangeLog branches/gcc-4_3-branch/gcc/tree-ssa-alias.c