diff --git a/ld/testsuite/ld-plugin/dummy.c b/ld/testsuite/ld-plugin/dummy.c new file mode 100644 index 0000000..5c03287 --- /dev/null +++ b/ld/testsuite/ld-plugin/dummy.c @@ -0,0 +1 @@ +/* An empty file. */ diff --git a/ld/testsuite/ld-plugin/dummy.s b/ld/testsuite/ld-plugin/dummy.s new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ld/testsuite/ld-plugin/dummy.s @@ -0,0 +1 @@ + diff --git a/ld/testsuite/ld-plugin/func1p.c b/ld/testsuite/ld-plugin/func1p.c new file mode 100644 index 0000000..917dcbb --- /dev/null +++ b/ld/testsuite/ld-plugin/func1p.c @@ -0,0 +1,8 @@ +extern int retval; + +int +__attribute__ ((visibility ("protected"))) +func1 (void) +{ + return retval; +} diff --git a/ld/testsuite/ld-plugin/func2.c b/ld/testsuite/ld-plugin/func2.c new file mode 100644 index 0000000..d233fcf --- /dev/null +++ b/ld/testsuite/ld-plugin/func2.c @@ -0,0 +1,7 @@ + +extern int retval; + +int func2 (void) +{ + return retval; +} diff --git a/ld/testsuite/ld-plugin/func2i.c b/ld/testsuite/ld-plugin/func2i.c new file mode 100644 index 0000000..00d7cdd --- /dev/null +++ b/ld/testsuite/ld-plugin/func2i.c @@ -0,0 +1,8 @@ +extern int retval; + +int +__attribute__ ((visibility ("internal"))) +func2 (void) +{ + return retval; +} diff --git a/ld/testsuite/ld-plugin/func3h.c b/ld/testsuite/ld-plugin/func3h.c new file mode 100644 index 0000000..525de63 --- /dev/null +++ b/ld/testsuite/ld-plugin/func3h.c @@ -0,0 +1,8 @@ +extern int retval; + +int +__attribute__ ((visibility ("hidden"))) +func3 (void) +{ + return retval; +} diff --git a/ld/testsuite/ld-plugin/lto-10.out b/ld/testsuite/ld-plugin/lto-10.out new file mode 100644 index 0000000..ce01362 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-10.out @@ -0,0 +1 @@ +hello diff --git a/ld/testsuite/ld-plugin/lto-10a.c b/ld/testsuite/ld-plugin/lto-10a.c new file mode 100644 index 0000000..93d57b5 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-10a.c @@ -0,0 +1,6 @@ +extern int foo(void); + +int main(void) +{ + return foo(); +} diff --git a/ld/testsuite/ld-plugin/lto-10b.c b/ld/testsuite/ld-plugin/lto-10b.c new file mode 100644 index 0000000..507055b --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-10b.c @@ -0,0 +1,7 @@ +#include + +int foo(void) +{ + printf ("hello\n"); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-10r.d b/ld/testsuite/ld-plugin/lto-10r.d new file mode 100644 index 0000000..689e6ec --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-10r.d @@ -0,0 +1,7 @@ +#ld: -r tmpdir/lto-10a.o tmpdir/lto-10b.o +#source: dummy.s +#nm: -p + +#... +[0-9a-f]+ C __gnu_lto_v.* +#pass diff --git a/ld/testsuite/ld-plugin/lto-11.out b/ld/testsuite/ld-plugin/lto-11.out new file mode 100644 index 0000000..899682a --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-11.out @@ -0,0 +1,2 @@ +Hello from foo! +Hello from bar! diff --git a/ld/testsuite/ld-plugin/lto-11a.c b/ld/testsuite/ld-plugin/lto-11a.c new file mode 100644 index 0000000..5193972 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-11a.c @@ -0,0 +1,9 @@ +extern void foo(void); +extern void bar(void); + +int main(void) +{ + foo(); + bar(); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-11b.c b/ld/testsuite/ld-plugin/lto-11b.c new file mode 100644 index 0000000..62d61ec --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-11b.c @@ -0,0 +1,6 @@ +extern int printf(const char *, ...); + +void foo(void) +{ + printf("Hello from %s!\n", __FUNCTION__); +} diff --git a/ld/testsuite/ld-plugin/lto-11c.c b/ld/testsuite/ld-plugin/lto-11c.c new file mode 100644 index 0000000..8cd40b9 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-11c.c @@ -0,0 +1,6 @@ +extern int printf(const char *, ...); + +void bar(void) +{ + printf("Hello from %s!\n", __FUNCTION__); +} diff --git a/ld/testsuite/ld-plugin/lto-12.out b/ld/testsuite/ld-plugin/lto-12.out new file mode 100644 index 0000000..d86bac9 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-12.out @@ -0,0 +1 @@ +OK diff --git a/ld/testsuite/ld-plugin/lto-12a.c b/ld/testsuite/ld-plugin/lto-12a.c new file mode 100644 index 0000000..30ff3d9 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-12a.c @@ -0,0 +1,16 @@ +#include +#include + +extern int value; + +int +main (int argc, char **argv) +{ + int n = 10 * (argc + 1); + char *p = malloc (n); + __builtin_memcpy (p, argv[0], n); + if (value != -1) + abort (); + printf ("OK\n"); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-12b.c b/ld/testsuite/ld-plugin/lto-12b.c new file mode 100644 index 0000000..c2b00e4 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-12b.c @@ -0,0 +1 @@ +int value = -1; diff --git a/ld/testsuite/ld-plugin/lto-12c.c b/ld/testsuite/ld-plugin/lto-12c.c new file mode 100644 index 0000000..ecd1bd4 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-12c.c @@ -0,0 +1,15 @@ +#include + +extern int value; + +void *memcpy(void *dest, const void *src, size_t n) +{ + char *d = (char *) dest; + const char *s = (const char *) src; + + while (n--) + *d++ = *s++; + + value = 1; + return dest; +} diff --git a/ld/testsuite/ld-plugin/lto-13.out b/ld/testsuite/ld-plugin/lto-13.out new file mode 100644 index 0000000..3bd1f0e --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-13.out @@ -0,0 +1,2 @@ +foo +bar diff --git a/ld/testsuite/ld-plugin/lto-13a.c b/ld/testsuite/ld-plugin/lto-13a.c new file mode 100644 index 0000000..5193972 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-13a.c @@ -0,0 +1,9 @@ +extern void foo(void); +extern void bar(void); + +int main(void) +{ + foo(); + bar(); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-13b.c b/ld/testsuite/ld-plugin/lto-13b.c new file mode 100644 index 0000000..7c87a5e --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-13b.c @@ -0,0 +1,7 @@ +#include + +void +bar (void) +{ + printf ("bar\n"); +} diff --git a/ld/testsuite/ld-plugin/lto-13c.c b/ld/testsuite/ld-plugin/lto-13c.c new file mode 100644 index 0000000..4859019 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-13c.c @@ -0,0 +1,7 @@ +#include + +void +foo (void) +{ + printf ("foo\n"); +} diff --git a/ld/testsuite/ld-plugin/lto-1a.c b/ld/testsuite/ld-plugin/lto-1a.c new file mode 100644 index 0000000..b775d0a --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-1a.c @@ -0,0 +1,4 @@ +unsigned long long bar (unsigned long long y) +{ + return 30 / y; +} diff --git a/ld/testsuite/ld-plugin/lto-1b.c b/ld/testsuite/ld-plugin/lto-1b.c new file mode 100644 index 0000000..8a961ef --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-1b.c @@ -0,0 +1,8 @@ +extern unsigned long long bar (unsigned long long); + +int +main (int argc, char **argv) +{ + unsigned long long d = bar ((unsigned long long) (argc + 1)); + return d; +} diff --git a/ld/testsuite/ld-plugin/lto-2.c b/ld/testsuite/ld-plugin/lto-2.c new file mode 100644 index 0000000..f0eacf4 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-2.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int +main (int argc, char **argv) +{ + int d = atoi (argv[1]); + printf ("%f\n", sin (d)); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-3.d b/ld/testsuite/ld-plugin/lto-3.d new file mode 100644 index 0000000..c3a9a16 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-3.d @@ -0,0 +1,4 @@ +#failif +#... +[0-9a-f]+ T foo +#... diff --git a/ld/testsuite/ld-plugin/lto-3.out b/ld/testsuite/ld-plugin/lto-3.out new file mode 100644 index 0000000..a69f8f3 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-3.out @@ -0,0 +1,2 @@ +hello foo +hello bar diff --git a/ld/testsuite/ld-plugin/lto-3a.c b/ld/testsuite/ld-plugin/lto-3a.c new file mode 100644 index 0000000..5193972 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-3a.c @@ -0,0 +1,9 @@ +extern void foo(void); +extern void bar(void); + +int main(void) +{ + foo(); + bar(); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-3b.c b/ld/testsuite/ld-plugin/lto-3b.c new file mode 100644 index 0000000..c24f6d4 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-3b.c @@ -0,0 +1,6 @@ +#include + +void foo(void) +{ + printf ("hello foo\n"); +} diff --git a/ld/testsuite/ld-plugin/lto-3c.c b/ld/testsuite/ld-plugin/lto-3c.c new file mode 100644 index 0000000..95b3bc0 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-3c.c @@ -0,0 +1,6 @@ +#include + +void bar(void) +{ + printf ("hello bar\n"); +} diff --git a/ld/testsuite/ld-plugin/lto-3r.d b/ld/testsuite/ld-plugin/lto-3r.d new file mode 100644 index 0000000..1d1befe --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-3r.d @@ -0,0 +1,7 @@ +#ld: -r tmpdir/lto-3b.o +#source: dummy.s +#nm: -p + +#... +[0-9a-f]+ C __gnu_lto_v.* +#pass diff --git a/ld/testsuite/ld-plugin/lto-4.out b/ld/testsuite/ld-plugin/lto-4.out new file mode 100644 index 0000000..8d8cc92 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-4.out @@ -0,0 +1,2 @@ +hello bar +hello foo diff --git a/ld/testsuite/ld-plugin/lto-4a.c b/ld/testsuite/ld-plugin/lto-4a.c new file mode 100644 index 0000000..2d07cf5 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-4a.c @@ -0,0 +1,7 @@ +extern void foo(void); + +int main(void) +{ + foo(); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-4b.c b/ld/testsuite/ld-plugin/lto-4b.c new file mode 100644 index 0000000..bb4a68b --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-4b.c @@ -0,0 +1,9 @@ +#include + +extern void bar (void); + +void foo(void) +{ + bar (); + printf ("hello foo\n"); +} diff --git a/ld/testsuite/ld-plugin/lto-4c.c b/ld/testsuite/ld-plugin/lto-4c.c new file mode 100644 index 0000000..317e6fc --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-4c.c @@ -0,0 +1,6 @@ +#include + +void bar (void) +{ + printf ("hello bar\n"); +} diff --git a/ld/testsuite/ld-plugin/lto-4r-a.d b/ld/testsuite/ld-plugin/lto-4r-a.d new file mode 100644 index 0000000..c618cff --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-4r-a.d @@ -0,0 +1,7 @@ +#ld: -r tmpdir/lto-4a.o tmpdir/lto-4b.o tmpdir/lto-4c.o +#source: dummy.s +#objdump: -h + +#... +.* .gnu_object_only.* +#pass diff --git a/ld/testsuite/ld-plugin/lto-4r-b.d b/ld/testsuite/ld-plugin/lto-4r-b.d new file mode 100644 index 0000000..07d71cb --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-4r-b.d @@ -0,0 +1,7 @@ +#ld: -r tmpdir/lto-4a.o tmpdir/lto-4b.o +#source: dummy.s +#objdump: -h + +#... +.* .gnu_object_only.* +#pass diff --git a/ld/testsuite/ld-plugin/lto-4r-c.d b/ld/testsuite/ld-plugin/lto-4r-c.d new file mode 100644 index 0000000..ada50c0 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-4r-c.d @@ -0,0 +1,7 @@ +#ld: -r tmpdir/lto-4r-b.o tmpdir/lto-4c.o +#source: dummy.s +#objdump: -h + +#... +.* .gnu_object_only.* +#pass diff --git a/ld/testsuite/ld-plugin/lto-4r-d.d b/ld/testsuite/ld-plugin/lto-4r-d.d new file mode 100644 index 0000000..d4c5852 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-4r-d.d @@ -0,0 +1,7 @@ +#ld: -r --whole-archive tmpdir/liblto-4.a +#source: dummy.s +#objdump: -h + +#... +.* .gnu_object_only.* +#pass diff --git a/ld/testsuite/ld-plugin/lto-5.d b/ld/testsuite/ld-plugin/lto-5.d new file mode 100644 index 0000000..c3a9a16 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-5.d @@ -0,0 +1,4 @@ +#failif +#... +[0-9a-f]+ T foo +#... diff --git a/ld/testsuite/ld-plugin/lto-5.out b/ld/testsuite/ld-plugin/lto-5.out new file mode 100644 index 0000000..dfbb215 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-5.out @@ -0,0 +1 @@ +hello foo diff --git a/ld/testsuite/ld-plugin/lto-5a.c b/ld/testsuite/ld-plugin/lto-5a.c new file mode 100644 index 0000000..2d07cf5 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-5a.c @@ -0,0 +1,7 @@ +extern void foo(void); + +int main(void) +{ + foo(); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-5b.c b/ld/testsuite/ld-plugin/lto-5b.c new file mode 100644 index 0000000..c24f6d4 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-5b.c @@ -0,0 +1,6 @@ +#include + +void foo(void) +{ + printf ("hello foo\n"); +} diff --git a/ld/testsuite/ld-plugin/lto-5r.d b/ld/testsuite/ld-plugin/lto-5r.d new file mode 100644 index 0000000..43e9a5c --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-5r.d @@ -0,0 +1,7 @@ +#ld: -r tmpdir/lto-5a.o tmpdir/lto-5b.o +#source: dummy.s +#nm: -p + +#... +[0-9a-f]+ C __gnu_lto_v.* +#pass diff --git a/ld/testsuite/ld-plugin/lto-6.c b/ld/testsuite/ld-plugin/lto-6.c new file mode 100644 index 0000000..749e4e0 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-6.c @@ -0,0 +1,9 @@ +#include + +extern char _etext[]; + +int main(void) +{ + printf ("%p: %d\n", _etext, _etext[0]); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-7.out b/ld/testsuite/ld-plugin/lto-7.out new file mode 100644 index 0000000..d86bac9 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-7.out @@ -0,0 +1 @@ +OK diff --git a/ld/testsuite/ld-plugin/lto-7a.c b/ld/testsuite/ld-plugin/lto-7a.c new file mode 100644 index 0000000..d277a43 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-7a.c @@ -0,0 +1,14 @@ +#include +#include + +int foo = -1; + +extern void bar (); + +int +main (int argc, char **argv) +{ + bar (); + printf ("OK\n"); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-7b.c b/ld/testsuite/ld-plugin/lto-7b.c new file mode 100644 index 0000000..1798130 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-7b.c @@ -0,0 +1,8 @@ +extern int foo; + +static void +__attribute__ ((unused, constructor)) +set_foo (void) +{ + foo = 30; +} diff --git a/ld/testsuite/ld-plugin/lto-7c.c b/ld/testsuite/ld-plugin/lto-7c.c new file mode 100644 index 0000000..5236f57 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-7c.c @@ -0,0 +1,9 @@ +extern int foo; +extern int foo2; + +static void +__attribute__ ((unused, constructor)) +set_foo (void) +{ + foo = foo2; +} diff --git a/ld/testsuite/ld-plugin/lto-7d.c b/ld/testsuite/ld-plugin/lto-7d.c new file mode 100644 index 0000000..7fc1ff1 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-7d.c @@ -0,0 +1,11 @@ +#include + +extern int foo; +int foo2 = 2; + +void +bar (void) +{ + if (foo != 30) + abort (); +} diff --git a/ld/testsuite/ld-plugin/lto-8.out b/ld/testsuite/ld-plugin/lto-8.out new file mode 100644 index 0000000..35c5d69 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-8.out @@ -0,0 +1 @@ +baz: 42 diff --git a/ld/testsuite/ld-plugin/lto-8a.c b/ld/testsuite/ld-plugin/lto-8a.c new file mode 100644 index 0000000..6901fb3 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-8a.c @@ -0,0 +1,12 @@ +#include + +void baz(int i) +{ + printf ("baz: %d\n", i); +} + +int main(void) +{ + foo(42); + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-8b.c b/ld/testsuite/ld-plugin/lto-8b.c new file mode 100644 index 0000000..3b6db5f --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-8b.c @@ -0,0 +1,14 @@ +extern int bar(void) __attribute__((__visibility__("hidden"), __const__)); +extern void baz(int); + +void foo(char c) +{ + int i; + + if (bar()) + i = c; + else + i = c; + + baz(i); +} diff --git a/ld/testsuite/ld-plugin/lto-9.cc b/ld/testsuite/ld-plugin/lto-9.cc new file mode 100644 index 0000000..2a4dcde --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-9.cc @@ -0,0 +1,9 @@ +struct Foooo { + virtual ~Foooo () { } +}; + +int main(void) +{ + Foooo t; + return 0; +} diff --git a/ld/testsuite/ld-plugin/lto-9.d b/ld/testsuite/ld-plugin/lto-9.d new file mode 100644 index 0000000..4b5bcf8 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-9.d @@ -0,0 +1,4 @@ +#failif +#... +[0-9a-f]+ . .*Foooo::Foooo.* +#... diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp new file mode 100644 index 0000000..0c49cec --- /dev/null +++ b/ld/testsuite/ld-plugin/lto.exp @@ -0,0 +1,233 @@ +# Expect script for ld-plugin LTO tests +# Copyright 2011 +# Free Software Foundation, Inc. +# +# This file is part of the GNU Binutils. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# These tests require plugin and LTO. +if { ![check_plugin_api_available] + || ![check_lto_available] } { + return +} + +# Simple LTO tests and generate input files for complex LTO tests. +set lto_link_tests { + {"LTO 1" + "-O2 -flto -fuse-linker-plugin" "-flto -fuse-linker-plugin" + {lto-1a.c lto-1b.c} {} "lto-1.exe"} + {"Build libdummy.a 2" + "" "-O2 -flto -fuse-linker-plugin" + {lto-2.c} {} "libdummy.a"} + {"LTO 2" + "-static -O2 -flto -fuse-linker-plugin tmpdir/lto-2.o -lm" "" + {dummy.c} {} "lto-2.exe"} + {"Build libdummy.a 3a" + "" "-flto" + {lto-3a.c} {} "libdummy.a"} + {"Build libdummy.a 3c" + "" "-O2" + {lto-3c.c} {} "libdummy.a"} + {"Build liblto-3.a" + "" "-flto" + {lto-3b.c} {} "liblto-3.a"} + {"Build libdummy.a 4a" + "" "-flto" + {lto-4a.c} {} "libdummy.a"} + {"Build libdummy.a 4b" + "" "-O2" + {lto-4b.c} {} "libdummy.a"} + {"Build libdummy.a 4c" + "" "-O2" + {lto-4c.c} {} "libdummy.a"} + {"Build libdummy.a 5a" + "" "-flto" + {lto-5a.c} {} "libdummy.a"} + {"Build libdummy.a 5b" + "" "-flto" + {lto-5b.c} {} "libdummy.a"} + {"LTO 6" + "-O2 -flto -fuse-linker-plugin" "" + {lto-6.c} {} "lto-6.exe" "c"} + {"Build libdummy.a PR ld/12365" + "" "-flto -O2" + {pr12365a.c pr12365b.c pr12365c.c} {} "libdummy.a"} + {"Build libdummy.a 9" + "" "-O2 -flto" + {lto-9.cc} {} "libdummy.a"} + {"Build libdummy.a 10a" + "" "-O2" + {lto-10a.c} {} "libdummy.a"} + {"Build libdummy.a 10b" + "" "-O2 -flto" + {lto-10b.c} {} "libdummy.a"} + {"Build libdummy.a 11a" + "" "-O -flto" + {lto-11a.c} {} "libdummy.a"} + {"Build libdummy.a 11b" + "" "-O -flto" + {lto-11b.c} {} "libdummy.a"} + {"Build libdummy.a 11c" + "" "-O" + {lto-11c.c} {} "libdummy.a"} + {"Build liblto-12.a" + "" "-O2 -flto" + {lto-12c.c} {} "liblto-12.a"} + {"Build libdummy.a 12" + "" "-O2 -flto" + {lto-12a.c lto-12b.c} {} "libdummy.a"} + {"Build libdummy.a 13" + "" "-O2 -flto" + {lto-13a.c lto-13b.c} {} "libdummy.a"} + {"Build liblto-13.a" + "" "-O2" + {lto-13c.c} {} "liblto-13.a"} +} + +# Generate input files for complex LTO tests for ELF. +set lto_link_elf_tests { + {"Build libdummy.a 7" + "" "-flto -O2" + {lto-7a.c lto-7b.c lto-7c.c} {} "libdummy.a"} + {"Build liblto-7.so" + "-shared" "-O2 -fpic" + {lto-7d.c} {} "liblto-7.so" "c"} + {"Build libdummy.a 8a" + "" "-O2" + {lto-8a.c} {} "libdummy.a"} + {"Build libdummy.a 8b" + "" "-flto -O2" + {lto-8b.c} {} "libdummy.a"} +} + +# Check final symbols in executables. +set lto_link_symbol_tests { + {"LTO 3 symbol" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/liblto-3.a" "" + {dummy.c} {{"nm" {} "lto-3.d"}} "lto-3.exe" "c"} + {"LTO 5 symbol" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-5.o" "" + {dummy.c} {{"nm" {} "lto-5.d"}} "lto-5.exe" "c"} + {"LTO 9 symbol" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-9.o" "" + {dummy.c} {{"nm" {-C} "lto-9.d"}} "lto-9.exe" "c++"} +} + +# LTO run-time tests. +set lto_run_tests { + {"LTO 3a" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/liblto-3.a" "" + {dummy.c} "lto-3b.exe" "lto-3.out" "" "c"} + {"LTO 3b" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/lto-3.o" "" + {dummy.c} "lto-3c.exe" "lto-3.out" "" "c"} + {"LTO 3c" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o -Wl,--whole-archive tmpdir/liblto-3.a -Wl,--no-whole-archive tmpdir/liblto-3.a" "" + {dummy.c} "lto-3d.exe" "lto-3.out" "" "c"} + {"LTO 4a" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-a.o" "" + {dummy.c} "lto-4a.exe" "lto-4.out" "" "c"} + {"LTO 4c" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-c.o" "" + {dummy.c} "lto-4c.exe" "lto-4.out" "" "c"} + {"LTO 4d" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-d.o" "" + {dummy.c} "lto-4d.exe" "lto-4.out" "" "c"} + {"LTO 5" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-5.o" "" + {dummy.c} "lto-5.exe" "lto-5.out" "" "c"} + {"LTO 10" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-10.o" "" + {dummy.c} "lto-10.exe" "lto-10.out" "" "c"} + {"LTO 11" + "-O -flto -fuse-linker-plugin tmpdir/liblto-11.a" "" + {dummy.c} "lto-11.exe" "lto-11.out" "" "c"} + {"LTO 12a" + "-O -flto -fuse-linker-plugin tmpdir/lto-12a.o tmpdir/liblto-12.a tmpdir/lto-12b.o" "" + {dummy.c} "lto-12a.exe" "lto-12.out" "" "c"} + {"LTO 12b" + "-O -flto -fuse-linker-plugin tmpdir/lto-12a.o tmpdir/lto-12b.o tmpdir/liblto-12.a" "" + {dummy.c} "lto-12b.exe" "lto-12.out" "" "c"} + {"LTO 13" + "-O -flto -fuse-linker-plugin tmpdir/lto-13a.o tmpdir/liblto-13.a tmpdir/lto-13b.o" "" + {dummy.c} "lto-13.exe" "lto-13.out" "" "c"} +} + +# LTO run-time tests for ELF +set lto_run_elf_tests { + {"LTO 7" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-7b.o tmpdir/lto-7c.o tmpdir/lto-7a.o tmpdir/liblto-7.so" "" + {dummy.c} "lto-7.exe" "lto-7.out" "" "c"} + {"LTO 8" + "-O2 -flto -fuse-linker-plugin tmpdir/lto-8b.o tmpdir/lto-8a.o" "" + {dummy.c} "lto-8.exe" "lto-8.out" "" "c"} +} + +run_cc_link_tests $lto_link_tests + +if { [is_elf_format] } { + run_cc_link_tests $lto_link_elf_tests +} + +set testname "Build liblto-4.a" +remote_file host delete "tmpdir/liblto-4.a" +set catch_output [run_host_cmd "$ar" "rc tmpdir/liblto-4.a tmpdir/lto-4a.o tmpdir/lto-4b.o tmpdir/lto-4c.o"] +if {![string match "" $catch_output]} { + unresolved $testname + return +} + +set testname "Build liblto-11.a" +remote_file host delete "tmpdir/liblto-11.a" +set catch_output [run_host_cmd "$ar" "rc tmpdir/liblto-11.a tmpdir/lto-11a.o tmpdir/lto-11b.o tmpdir/lto-11c.o"] +if {![string match "" $catch_output]} { + unresolved $testname + return +} + +# Check exported LTO linker errors. +set testname "PR ld/12365" +set exec_output [run_host_cmd "$CC" "-O2 -flto -fuse-linker-plugin tmpdir/pr12365a.o tmpdir/pr12365b.o tmpdir/pr12365c.o"] +if { [ regexp "undefined reference to `my_bcopy'" $exec_output ] } { + pass $testname +} { + fail $testname +} + +# Run "ld -r" to generate inputs for complex LTO tests. +run_dump_test "lto-3r" +remote_exec host "mv" "tmpdir/dump tmpdir/lto-3.o" +run_dump_test "lto-4r-a" +remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-a.o" +run_dump_test "lto-4r-b" +remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-b.o" +run_dump_test "lto-4r-c" +remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-c.o" +run_dump_test "lto-4r-d" +remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-d.o" +run_dump_test "lto-5r" +remote_exec host "mv" "tmpdir/dump tmpdir/lto-5.o" +run_dump_test "lto-10r" +remote_exec host "mv" "tmpdir/dump tmpdir/lto-10.o" + +run_cc_link_tests $lto_link_symbol_tests + +run_ld_link_exec_tests [] $lto_run_tests + +if { [is_elf_format] } { + run_ld_link_exec_tests [] $lto_run_elf_tests +} diff --git a/ld/testsuite/ld-plugin/plugin-7.d b/ld/testsuite/ld-plugin/plugin-7.d index 75f25e0..ee7a6eb 100644 --- a/ld/testsuite/ld-plugin/plugin-7.d +++ b/ld/testsuite/ld-plugin/plugin-7.d @@ -19,7 +19,8 @@ tv\[16\]: LDPT_OPTION 'registerallsymbolsread' tv\[17\]: LDPT_OPTION 'registercleanup' tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o' tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0' -tv\[20\]: LDPT_NULL value 0x0 \(0\) +tv\[20\]: LDPT_OPTION 'add:tmpdir/func.o' +tv\[21\]: LDPT_NULL value 0x0 \(0\) #... hook called: claim_file tmpdir/main.o \[@0/.* not claimed hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED diff --git a/ld/testsuite/ld-plugin/plugin-8.d b/ld/testsuite/ld-plugin/plugin-8.d index e72b039..a4db899 100644 --- a/ld/testsuite/ld-plugin/plugin-8.d +++ b/ld/testsuite/ld-plugin/plugin-8.d @@ -21,7 +21,9 @@ tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o' tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0' tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0' tv\[21\]: LDPT_OPTION 'dumpresolutions' -tv\[22\]: LDPT_NULL value 0x0 \(0\) +tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o' +tv\[23\]: LDPT_OPTION 'add:tmpdir/func2.o' +tv\[24\]: LDPT_NULL value 0x0 \(0\) #... hook called: claim_file tmpdir/main.o \[@0/.* not claimed hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED diff --git a/ld/testsuite/ld-plugin/plugin-9.d b/ld/testsuite/ld-plugin/plugin-9.d index b74f4a6..a4db899 100644 --- a/ld/testsuite/ld-plugin/plugin-9.d +++ b/ld/testsuite/ld-plugin/plugin-9.d @@ -22,7 +22,8 @@ tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0' tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0' tv\[21\]: LDPT_OPTION 'dumpresolutions' tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o' -tv\[23\]: LDPT_NULL value 0x0 \(0\) +tv\[23\]: LDPT_OPTION 'add:tmpdir/func2.o' +tv\[24\]: LDPT_NULL value 0x0 \(0\) #... hook called: claim_file tmpdir/main.o \[@0/.* not claimed hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED diff --git a/ld/testsuite/ld-plugin/plugin.exp b/ld/testsuite/ld-plugin/plugin.exp index 8952f1d..fd0f939 100644 --- a/ld/testsuite/ld-plugin/plugin.exp +++ b/ld/testsuite/ld-plugin/plugin.exp @@ -70,6 +70,7 @@ set plugin_nm_output "" if { $can_compile && \ (![ld_compile "$CC $CFLAGS" $srcdir/$subdir/main.c tmpdir/main.o] \ || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func.c tmpdir/func.o] \ + || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func2.c tmpdir/func2.o] \ || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/text.c tmpdir/text.o]) } { # Defer fail until we have list of tests set. set failed_compile 1 @@ -108,12 +109,15 @@ set plugin_tests [list \ [list "plugin claimfile replace symbol" "-plugin $plugin_path $regclm \ $regas $regcln -plugin-opt claim:tmpdir/func.o \ -plugin-opt sym:${_}func::0:0:0 \ + -plugin-opt add:tmpdir/func.o \ $testobjfiles $libs" "" "" {{ld plugin-7.d}} "main.x" ] \ [list "plugin claimfile resolve symbol" "-plugin $plugin_path $regclm \ $regas $regcln -plugin-opt claim:tmpdir/func.o \ -plugin-opt sym:${_}func::0:0:0 \ -plugin-opt sym:${_}func2::0:0:0 \ -plugin-opt dumpresolutions \ + -plugin-opt add:tmpdir/func.o \ + -plugin-opt add:tmpdir/func2.o \ $testobjfiles $libs" "" "" {{ld plugin-8.d}} "main.x" ] \ [list "plugin claimfile replace file" "-plugin $plugin_path $regclm \ $regas $regcln -plugin-opt claim:tmpdir/func.o \ @@ -121,6 +125,7 @@ set plugin_tests [list \ -plugin-opt sym:${_}func2::0:0:0 \ -plugin-opt dumpresolutions \ -plugin-opt add:tmpdir/func.o \ + -plugin-opt add:tmpdir/func2.o \ $testobjfiles $libs" "" "" {{ld plugin-9.d}} "main.x" ] \ ] @@ -152,6 +157,10 @@ set plugin_extra_elf_tests [list \ -plugin-opt sym:${_}func2::0:2:0 \ -plugin-opt sym:${_}func3::0:3:0 \ -plugin-opt dumpresolutions \ + -plugin-opt add:tmpdir/func.o \ + -plugin-opt add:tmpdir/func1p.o \ + -plugin-opt add:tmpdir/func2i.o \ + -plugin-opt add:tmpdir/func3h.o \ $testobjfiles $libs" "" "" {{ld plugin-ignore.d} \ {readelf -s plugin-vis-1.d}} "main.x" ] \ ] @@ -170,7 +179,10 @@ if { !$can_compile || $failed_compile } { run_ld_link_tests $plugin_tests -if { [is_elf_format] } { +if { [is_elf_format] \ + && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func1p.c tmpdir/func1p.o] \ + && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func2i.c tmpdir/func2i.o] \ + && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func3h.c tmpdir/func3h.o] } { run_ld_link_tests $plugin_extra_elf_tests } diff --git a/ld/testsuite/ld-plugin/pr12365a.c b/ld/testsuite/ld-plugin/pr12365a.c new file mode 100644 index 0000000..a9bb6c6 --- /dev/null +++ b/ld/testsuite/ld-plugin/pr12365a.c @@ -0,0 +1,25 @@ +extern void abort(void); +extern void main_test (void); +extern void abort (void); +int inside_main; + +int +main () +{ + inside_main = 1; + main_test (); + inside_main = 0; + return 0; +} + +/* When optimizing, all the constant cases should have been + constant folded, so no calls to link_error should remain. + In any case, link_error should not be called. */ + +#ifndef __OPTIMIZE__ +void +link_error (void) +{ + abort (); +} +#endif diff --git a/ld/testsuite/ld-plugin/pr12365b.c b/ld/testsuite/ld-plugin/pr12365b.c new file mode 100644 index 0000000..3e86e06 --- /dev/null +++ b/ld/testsuite/ld-plugin/pr12365b.c @@ -0,0 +1,47 @@ +#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname) +#define ASMNAME2(prefix, cname) STRING (prefix) cname +#define STRING(x) #x + +typedef __SIZE_TYPE__ size_t; +extern void abort (void); +extern void *memcpy (void *, const void *, size_t) + __asm (ASMNAME ("my_memcpy")); +extern void bcopy (const void *, void *, size_t) + __asm (ASMNAME ("my_bcopy")); +extern void *memset (void *, int, size_t) + __asm (ASMNAME ("my_memset")); +extern void bzero (void *, size_t) + __asm (ASMNAME ("my_bzero")); +extern int memcmp (const void *, const void *, size_t); + +struct A { char c[32]; } a = { "foobar" }; +char x[64] = "foobar", y[64]; +int i = 39, j = 6, k = 4; + +extern int inside_main; + +void +main_test (void) +{ + struct A b = a; + struct A c = { { 'x' } }; + + inside_main = 1; + + if (memcmp (b.c, x, 32) || c.c[0] != 'x' || memcmp (c.c + 1, x + 32, 31)) + abort (); + if (__builtin_memcpy (y, x, i) != y || memcmp (x, y, 64)) + abort (); + if (memcpy (y + 6, x, j) != y + 6 + || memcmp (x, y, 6) || memcmp (x, y + 6, 58)) + abort (); + if (__builtin_memset (y + 2, 'X', k) != y + 2 + || memcmp (y, "foXXXXfoobar", 13)) + abort (); + bcopy (y + 1, y + 2, 6); + if (memcmp (y, "fooXXXXfobar", 13)) + abort (); + __builtin_bzero (y + 4, 2); + if (memcmp (y, "fooX\0\0Xfobar", 13)) + abort (); +} diff --git a/ld/testsuite/ld-plugin/pr12365c.c b/ld/testsuite/ld-plugin/pr12365c.c new file mode 100644 index 0000000..2edd0ff --- /dev/null +++ b/ld/testsuite/ld-plugin/pr12365c.c @@ -0,0 +1,79 @@ +extern void abort (void); +extern int inside_main; +typedef __SIZE_TYPE__ size_t; + +#define TEST_ABORT if (inside_main) abort() + +void * +my_memcpy (void *d, const void *s, size_t n) +{ + char *dst = (char *) d; + const char *src = (const char *) s; + while (n--) + *dst++ = *src++; + return (char *) d; +} + +void +my_bcopy (const void *s, void *d, size_t n) +{ + char *dst = (char *) d; + const char *src = (const char *) s; + if (src >= dst) + while (n--) + *dst++ = *src++; + else + { + dst += n; + src += n; + while (n--) + *--dst = *--src; + } +} + +void * +my_memset (void *d, int c, size_t n) +{ + char *dst = (char *) d; + while (n--) + *dst++ = c; + return (char *) d; +} + +void +my_bzero (void *d, size_t n) +{ + char *dst = (char *) d; + while (n--) + *dst++ = '\0'; +} + +void * +memcpy (void *d, const void *s, size_t n) +{ + void *result = my_memcpy (d, s, n); + TEST_ABORT; + return result; +} + +void +bcopy (const void *s, void *d, size_t n) +{ + my_bcopy (s, d, n); + TEST_ABORT; +} + +void * +memset (void *d, int c, size_t n) +{ + void *result = my_memset (d, c, n); + TEST_ABORT; + return result; +} + +void +bzero (void *d, size_t n) +{ + my_bzero (d, n); + TEST_ABORT; +} diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp index 48e9635..74bad74 100644 --- a/ld/testsuite/lib/ld-lib.exp +++ b/ld/testsuite/lib/ld-lib.exp @@ -1461,6 +1461,34 @@ proc check_plugin_api_available { } { return $plugin_api_available_saved } +# Returns true if the target compiler supports LTO +proc check_lto_available { } { + global lto_available_saved + global CC + if {![info exists lto_available_saved]} { + # Check if gcc supports -flto -fuse-linker-plugin + if { [which $CC] == 0 } { + set lto_available_saved 0 + return 0 + } + set basename "lto" + set src ${basename}[pid].c + set output ${basename}[pid].s + set f [open $src "w"] + puts $f "" + close $f + set status [remote_exec host $CC "-S -flto -fuse-linker-plugin $src -o $output"] + if { [lindex $status 0] == 0 } { + set lto_available_saved 1 + } else { + set lto_available_saved 0 + } + file delete $src + file delete $output + } + return $lto_available_saved +} + # Check if the assembler supports CFI statements. proc check_as_cfi { } {