This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: static-after-extern tests vs. mips explicit relocs
"Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> writes:
> > Richard, I'd be inclined to simply remove the "static" from each of
> > these declarations, rather than have that [static_after_extern] tcl
> > check.
> > r~
>
> As I recall, we ran into problems when they were extern because if the
> abort-ified function is called from a startup module before `main'
> we'll get a spurious crash.
>
> [dig dig dig] ah here we are, it was you (rth) who did it ;-)
> http://gcc.gnu.org/ml/gcc-patches/2000-11/msg00466.html
I suppose one way of getting around this would be to introduce a
variable such as "inside_main" that is set at the beginning of main()
and cleared at the end. The library functions would then only abort
while inside_main is true. At other times they would behave normally.
I tried that with the patch below. Unfortunately, making the functions
extern causes the tests to fail at -O3 (i686-pc-linux-gnu as well as mips
targets). The problem is that we're seeing the definition of the library
functions before expanding main(). And duplicate_decls() says:
if (DECL_BUILT_IN (olddecl))
{
/* Get rid of any built-in function if new arg types don't match it
or if we have a function definition. */
When the definitions were static, they didn't override the builtins.
Now they do, so they're no longer builtins within main().
Any suggestions?
Richard
Index: testsuite/gcc.c-torture/execute/string-opt-3.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/string-opt-3.c,v
retrieving revision 1.6
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.6 string-opt-3.c
*** testsuite/gcc.c-torture/execute/string-opt-3.c 21 Jan 2003 19:43:53 -0000 1.6
--- testsuite/gcc.c-torture/execute/string-opt-3.c 8 May 2003 17:13:14 -0000
*************** extern char *rindex (const char *, int);
*** 13,23 ****
--- 13,26 ----
int x = 6;
char *bar = "hi world";
+ int inside_main;
int main()
{
const char *const foo = "hello world";
+ inside_main = 1;
+
if (strlen (foo) != 11)
abort ();
if (strlen (foo + 4) != 7)
*************** int main()
*** 84,127 ****
if (__builtin_strcmp (foo, "hello") <= 0)
abort ();
return 0;
}
! static char *
rindex (const char *s, int c)
{
- /* For systems which don't have rindex, we ensure no link failures
- occur by always providing a backup definition. During
- optimization this function aborts to catch errors. */
#ifdef __OPTIMIZE__
! abort ();
! #else
! return strrchr(s, c);
#endif
}
- #ifdef __OPTIMIZE__
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
__attribute__ ((noinline))
! static __SIZE_TYPE__
strlen (const char *s)
{
! abort ();
}
__attribute__ ((noinline))
! static int
strcmp (const char *s1, const char *s2)
{
! abort ();
}
__attribute__ ((noinline))
! static char *
strrchr (const char *s, int c)
{
! abort ();
! }
#endif
--- 87,162 ----
if (__builtin_strcmp (foo, "hello") <= 0)
abort ();
+ inside_main = 0;
return 0;
}
! __attribute__ ((noinline))
! char *
rindex (const char *s, int c)
{
#ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
#endif
+ return strrchr (s, c);
}
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
__attribute__ ((noinline))
! __SIZE_TYPE__
strlen (const char *s)
{
! __SIZE_TYPE__ i;
!
! #ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
! #endif
!
! for (i = 0; s[i] != 0; i++)
! continue;
! return i;
}
__attribute__ ((noinline))
! int
strcmp (const char *s1, const char *s2)
{
! #ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
! #endif
!
! while (*s1 != 0 && *s1 == *s2)
! s1++, s2++;
!
! if (*s1 == 0 || *s2 == 0)
! return (unsigned char) *s1 - (unsigned char) *s2;
! return *s1 - *s2;
}
__attribute__ ((noinline))
! char *
strrchr (const char *s, int c)
{
! __SIZE_TYPE__ i;
!
! #ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
#endif
+
+ i = 0;
+ while (s[i] != 0)
+ i++;
+
+ do
+ if (s[i] == c)
+ return (char *) s + i;
+ while (i-- != 0);
+
+ return 0;
+ }
Index: testsuite/gcc.c-torture/execute/string-opt-4.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/string-opt-4.c,v
retrieving revision 1.5
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.5 string-opt-4.c
*** testsuite/gcc.c-torture/execute/string-opt-4.c 21 Jan 2003 19:43:53 -0000 1.5
--- testsuite/gcc.c-torture/execute/string-opt-4.c 8 May 2003 17:13:14 -0000
*************** extern void abort (void);
*** 9,18 ****
--- 9,22 ----
extern char *strchr (const char *, int);
extern char *index (const char *, int);
+ int inside_main;
+
int main()
{
const char *const foo = "hello world";
+ inside_main = 1;
+
if (strchr (foo, 'x'))
abort ();
if (strchr (foo, 'o') != foo + 4)
*************** int main()
*** 33,62 ****
if (__builtin_index (foo, 'o') != foo + 4)
abort ();
return 0;
}
! static char *
index (const char *s, int c)
{
- /* For systems which don't have index, we ensure no link failures
- occur by always providing a backup definition. During
- optimization this function aborts to catch errors. */
#ifdef __OPTIMIZE__
! abort ();
! #else
! return strchr(s, c);
#endif
}
- #ifdef __OPTIMIZE__
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
__attribute__ ((noinline))
! static char *
strchr (const char *s, int c)
{
! abort ();
! }
#endif
--- 37,74 ----
if (__builtin_index (foo, 'o') != foo + 4)
abort ();
+ inside_main = 0;
return 0;
}
! char *
index (const char *s, int c)
{
#ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
#endif
+ return strchr (s, c);
}
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
__attribute__ ((noinline))
! char *
strchr (const char *s, int c)
{
! #ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
#endif
+
+ for (;;)
+ {
+ if (*s == c)
+ return s;
+ if (*s == 0)
+ return 0;
+ s++;
+ }
+ }
Index: testsuite/gcc.c-torture/execute/string-opt-17.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/string-opt-17.c,v
retrieving revision 1.2
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.2 string-opt-17.c
*** testsuite/gcc.c-torture/execute/string-opt-17.c 21 Jan 2003 19:43:53 -0000 1.2
--- testsuite/gcc.c-torture/execute/string-opt-17.c 8 May 2003 17:13:14 -0000
*************** typedef __SIZE_TYPE__ size_t;
*** 10,19 ****
--- 10,22 ----
extern void *memset (void *, int, size_t);
char buffer[32];
+ int inside_main;
int
main (int argc)
{
+ inside_main = 1;
+
memset (buffer, argc, 0);
memset (buffer, argc, 1);
memset (buffer, argc, 2);
*************** main (int argc)
*** 33,51 ****
memset (buffer, argc, 16);
memset (buffer, argc, 17);
return 0;
}
- #ifdef __OPTIMIZE__
/* When optimizing, most of the above cases should be transformed into
something else. So any remaining calls to the original function
for short lengths should abort. */
__attribute__ ((noinline))
! static void *
memset (void *dst, int c, size_t len)
{
! if (len < 2)
abort ();
- }
#endif
--- 36,59 ----
memset (buffer, argc, 16);
memset (buffer, argc, 17);
+ inside_main = 0;
return 0;
}
/* When optimizing, most of the above cases should be transformed into
something else. So any remaining calls to the original function
for short lengths should abort. */
__attribute__ ((noinline))
! void *
memset (void *dst, int c, size_t len)
{
! #ifdef __OPTIMIZE__
! if (inside_main && len < 2)
abort ();
#endif
+
+ while (len-- > 0)
+ len[(char *) dst] = c;
+ return dst;
+ }
Index: testsuite/gcc.c-torture/execute/string-opt-18.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/string-opt-18.c,v
retrieving revision 1.3
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.3 string-opt-18.c
*** testsuite/gcc.c-torture/execute/string-opt-18.c 5 May 2003 19:31:35 -0000 1.3
--- testsuite/gcc.c-torture/execute/string-opt-18.c 8 May 2003 17:13:14 -0000
*************** char p[32] = "";
*** 18,29 ****
--- 18,32 ----
char *s2 = "defg";
char *s3 = "FGH";
size_t l1 = 1;
+ int inside_main;
int main()
{
int i;
const char *s;
+ inside_main = 1;
+
if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
abort ();
if (stpcpy (p + 16, "vwxyz" + 1) != p + 16 + 4 || memcmp (p + 16, "wxyz", 5))
*************** int main()
*** 74,104 ****
mempcpy (p + 6, s3 + 1, l1);
if (memcmp (p, "ABCdeFG", 8))
abort ();
return 0;
}
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
! should abort. When not optimizing, we provide fallback funcs for
! platforms that don't have mempcpy or stpcpy in libc.*/
__attribute__ ((noinline))
! static char *
stpcpy (char *d, const char *s)
{
#ifdef __OPTIMIZE__
! abort ();
! #else
! return strcpy (d, s) + strlen (s);
#endif
}
__attribute__ ((noinline))
! static void *
mempcpy (void *dst, const void *src, size_t sz)
{
#ifdef __OPTIMIZE__
! abort ();
! #else
! return (char *) memcpy (dst, src, sz) + sz;
#endif
}
--- 77,108 ----
mempcpy (p + 6, s3 + 1, l1);
if (memcmp (p, "ABCdeFG", 8))
abort ();
+
+ inside_main = 0;
return 0;
}
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
! should abort. */
__attribute__ ((noinline))
! char *
stpcpy (char *d, const char *s)
{
#ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
#endif
+ return strcpy (d, s) + strlen (s);
}
__attribute__ ((noinline))
! void *
mempcpy (void *dst, const void *src, size_t sz)
{
#ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
#endif
+ return (char *) memcpy (dst, src, sz) + sz;
}
Index: testsuite/gcc.c-torture/execute/string-opt-19.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/string-opt-19.c,v
retrieving revision 1.2
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.2 string-opt-19.c
*** testsuite/gcc.c-torture/execute/string-opt-19.c 8 May 2003 13:45:38 -0000 1.2
--- testsuite/gcc.c-torture/execute/string-opt-19.c 8 May 2003 17:13:14 -0000
*************** extern int memcmp (const void *, const v
*** 12,17 ****
--- 12,18 ----
const char s1[] = "123";
char p[32] = "";
+ int inside_main;
static const struct foo
{
*************** int main()
*** 61,66 ****
--- 62,69 ----
struct bar b1[sizeof bar/sizeof*bar];
int bz[sizeof baz/sizeof*baz];
+ inside_main = 1;
+
if (memmove (f1, foo, sizeof (foo)) != f1 || memcmp (f1, foo, sizeof(foo)))
abort();
if (memmove (b1, bar, sizeof (bar)) != b1 || memcmp (b1, bar, sizeof(bar)))
*************** int main()
*** 87,106 ****
if (memcmp (p, "abfgAi", 7))
abort ();
return 0;
}
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
! should abort. When not optimizing, provide memmove/bcopy implementation
! just in case target lacks these in its libc. */
__attribute__ ((noinline))
! static void *
memmove (void *d, const void *s, size_t n)
{
#ifdef __OPTIMIZE__
! abort ();
! #else
char *dst = (char *) d;
const char *src = (const char *) s;
if (src < dst)
--- 90,110 ----
if (memcmp (p, "abfgAi", 7))
abort ();
+ inside_main = 0;
return 0;
}
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
! should abort. */
__attribute__ ((noinline))
! void *
memmove (void *d, const void *s, size_t n)
{
#ifdef __OPTIMIZE__
! if (inside_main)
! abort ();
! #endif
char *dst = (char *) d;
const char *src = (const char *) s;
if (src < dst)
*************** #else
*** 114,124 ****
while (n--)
*dst++ = *src++;
return (char *) d;
- #endif
}
__attribute__ ((noinline))
! static void
bcopy (const void *s, void *d, size_t n)
{
memmove (d, s, n);
--- 118,127 ----
while (n--)
*dst++ = *src++;
return (char *) d;
}
__attribute__ ((noinline))
! void
bcopy (const void *s, void *d, size_t n)
{
memmove (d, s, n);
Index: testsuite/gcc.c-torture/execute/builtin-noret-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/builtin-noret-1.c,v
retrieving revision 1.2
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.2 builtin-noret-1.c
*** testsuite/gcc.c-torture/execute/builtin-noret-1.c 11 Jul 2002 12:29:07 -0000 1.2
--- testsuite/gcc.c-torture/execute/builtin-noret-1.c 8 May 2003 17:13:14 -0000
*************** t_exit (void)
*** 50,55 ****
--- 50,56 ----
link_failure ();
}
+ #if !(defined (__mips) && defined (__linux__))
/* Some non-Unix libcs might not have _exit. This version should never
get called. */
static void
*************** _exit (int i)
*** 57,62 ****
--- 58,64 ----
{
abort ();
}
+ #endif
void
t_Exit (void)
*************** t_Exit (void)
*** 65,76 ****
--- 67,80 ----
link_failure ();
}
+ #if !(defined (__mips) && defined (__linux__))
/* Some libcs might not have _Exit. This version should never get called. */
static void
_Exit (int i)
{
abort ();
}
+ #endif
/* When optimizing, no calls to link_failure should remain. In any case,
link_failure should not be called. */
Index: testsuite/gcc.c-torture/execute/builtin-noret-2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/builtin-noret-2.c,v
retrieving revision 1.1
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.1 builtin-noret-2.c
*** testsuite/gcc.c-torture/execute/builtin-noret-2.c 11 Apr 2003 04:26:54 -0000 1.1
--- testsuite/gcc.c-torture/execute/builtin-noret-2.c 8 May 2003 17:13:14 -0000
*************** t_exit (void)
*** 49,54 ****
--- 49,55 ----
link_failure ();
}
+ #if !(defined (__mips) && defined (__linux__))
/* Some non-Unix libcs might not have _exit. This version should never
get called. */
static void
*************** _exit (int i)
*** 56,61 ****
--- 57,63 ----
{
abort ();
}
+ #endif
void
t_Exit (void)
*************** t_Exit (void)
*** 65,76 ****
--- 67,80 ----
link_failure ();
}
+ #if !(defined (__mips) && defined (__linux__))
/* Some libcs might not have _Exit. This version should never get called. */
static void
_Exit (int i)
{
abort ();
}
+ #endif
/* When optimizing, no calls to link_failure should remain. In any case,
link_failure should not be called. */
Index: testsuite/gcc.dg/no-builtin-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/no-builtin-1.c,v
retrieving revision 1.1
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.1 no-builtin-1.c
*** testsuite/gcc.dg/no-builtin-1.c 18 Nov 2001 03:30:57 -0000 1.1
--- testsuite/gcc.dg/no-builtin-1.c 8 May 2003 17:13:14 -0000
***************
*** 2,7 ****
--- 2,8 ----
/* Origin: Joseph Myers <jsm28@cam.ac.uk>. */
/* { dg-do run } */
/* { dg-options "-fno-builtin-abs" } */
+ /* { dg-options "-fno-builtin-abs -mno-explicit-relocs" { target mips*-*-* } } */
/* GCC normally handles abs and labs as built-in functions even without
optimization. So test that with -fno-builtin-abs, labs is so handled