This is a first cut at supporting -mcpu=native/-mtune=native on Solaris/SPARC. Unlike it's Tru64 UNIX/Alpha and IRIX/MIPS (to be submitted soon) counterparts, it's a bit more involved:
* There's no support for -mcpu=native in the SPARC port yet. * Access to the %ver register is privileged, so we need OS interfaces to access the information. I couldn't find anything in libc. While the AT_SUN_CPU file from <sys/auxv.h> might fill the bill, it isn't actually set according to pargs -x. There seem to be two options: libkstat and libpicl. The former has the advantage that it's a tad better documented and talks directly to the kernel, while the latter needs picld, which seems overkill. Both are present in Solaris 8, though. I prefer the cpu_info:::brand kstat over cpu_info:::implementation: The former looks like (from kstat -p cpu_info:::brand): cpu_info:0:cpu_info0:brand UltraSPARC-T2 compared to cpu_info:0:cpu_info0:implementation UltraSPARC-T2 (chipid 0, clock 1165 MHz) but brand was only introduced in Solaris 10. Before that, only implementation existed with this contents: cpu_info:0:cpu_info0:implementation UltraSPARC-IIIi * Unlike IRIX and Tru64 UNIX, where the respective interfaces return a numeric identifier for the cpu type from a finite range, on SPARC we get string names, and I'm having some trouble determining the complete set. The patch below is based on what I've found so far, but certainly needs to be augmented for sun4m cpus which I don't have any longer. * The requirement to link the drivers with an additional library (-lkstat) prompted me to introduce GCC_EXTRA_LIBS. I didn't want to link the backends with -lkstat since they don't need it. The build maintainers may not like the way this was done, though. * Right now, this is Solaris-only since I have no idea what /proc/cpuinfo on Linux/SPARC contains. With all those caveats, the patch has been run through a C-only non-bootstrap build on sparc-sun-solaris2.11 so far. -mcpu=native/-mtune=native seem to work as expected, though I'll have to broaden the range of OS versions tested. I'm seeing tons of testsuite failures for -gdwarf-2 -g3 tests, but suppose they are related to recent debug patches. Comments, suggestions? Thanks. Rainer 2011-07-27 Rainer Orth <r...@cebitec.uni-bielefeld.de> gcc: * config/sparc/driver-sparc.c: New file. * config/sparc/x-sparc: New file. * config.host: Use driver-sparc.o, sparc/x-sparc on sparc*-*-solaris2*. * config/sparc/sparc.opt (native): New value for enum processor_type. * config/sparc/sparc-opts.h (PROCESSOR_NATIVE): Declare. * config/sparc/sol2.h [__sparc__] (host_detect_local_cpu): Declare. (EXTRA_SPEC_FUNCTIONS, MCPU_MTUNE_NATIVE_SPECS, DRIVER_SELF_SPECS): Define. * configure.ac (EXTRA_GCC_LIBS): Check for libkstat. Substitute result. * configure: Regenerate. * Makefile.in (EXTRA_GCC_LIBS): Set. (xgcc$(exeext)): Add $(EXTRA_GCC_LIBS). (cpp$(exeext)): Likewise. gcc/cp: * Make-lang.in (g++$(exeext)): Add $(EXTRA_GCC_LIBS). gcc/fortran: * Make-lang.in (gfortran$(exeext)): Add $(EXTRA_GCC_LIBS). gcc/go: * Make-lang.in (gccgo$(exeext)): Add $(EXTRA_GCC_LIBS). gcc/java: * Make-lang.in ($(XGCJ)$(exeext)): Add $(EXTRA_GCC_LIBS). diff --git a/gcc/Makefile.in b/gcc/Makefile.in --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -723,6 +723,9 @@ EXTRA_OBJS = @extra_objs@ # the gcc driver. EXTRA_GCC_OBJS =@extra_gcc_objs@ +# List of extra libraries that should be linked with the gcc driver. +EXTRA_GCC_LIBS = @EXTRA_GCC_LIBS@ + # List of additional header files to install. EXTRA_HEADERS =@extra_headers_list@ @@ -1828,7 +1831,8 @@ libcommon.a: $(OBJS-libcommon) xgcc$(exeext): $(GCC_OBJS) gccspec.o libcommon-target.a $(LIBDEPS) \ $(EXTRA_GCC_OBJS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \ - gccspec.o $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS) + gccspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \ + $(EXTRA_GCC_LIBS) $(LIBS) # cpp is to cpp0 as gcc is to cc1. # The only difference from xgcc is that it's linked with cppspec.o @@ -1836,7 +1840,8 @@ xgcc$(exeext): $(GCC_OBJS) gccspec.o lib cpp$(exeext): $(GCC_OBJS) cppspec.o libcommon-target.a $(LIBDEPS) \ $(EXTRA_GCC_OBJS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \ - cppspec.o $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS) + cppspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \ + $(EXTRA_GCC_LIBS) $(LIBS) # Dump a specs file to make -B./ read these specs over installed ones. $(SPECS): xgcc$(exeext) diff --git a/gcc/config.host b/gcc/config.host --- a/gcc/config.host +++ b/gcc/config.host @@ -157,6 +157,14 @@ case ${host} in ;; esac ;; + sparc*-*-solaris2*) + case ${target} in + sparc*-*-solaris2*) + host_extra_gcc_objs="driver-sparc.o" + host_xmake_file="${host_xmake_file} sparc/x-sparc" + ;; + esac + ;; esac # Machine-specific settings. diff --git a/gcc/config/sparc/driver-sparc.c b/gcc/config/sparc/driver-sparc.c new file mode 100644 --- /dev/null +++ b/gcc/config/sparc/driver-sparc.c @@ -0,0 +1,171 @@ +/* Subroutines for the gcc driver. + Copyright (C) 2011 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC 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, or (at your option) + any later version. + + GCC 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 GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" + +static const struct cpu_names { + const char *const name; + const char *const cpu; +} cpu_names[] = { +#if defined __sun__ && defined __svr4__ +/* FIXME: Possible values for pre-UltraSPARC CPUs? + + SuperSPARC + SuperSPARC II + microSPARC + microSPARC II + hyperSPARC + hyperSPARC II + + FMI,MB86904 + FMI,MB86907=FMI,MB86904 + Ross,RT623=Ross,RT625 + Ross,RT625 + Ross,RT626=Ross,RT625 + TI,TMS390S10 + TI,TMS390Z50=TI,TMS390Z55 + TI,TMS390Z55 */ + + { "", "v7" }, /* Generic cpu values probably unnecessary. */ + { "", "cypress" }, /* Irrelevant for Solaris 8+. */ + { "", "v8" }, + { "SuperSPARC", "supersparc" }, + { "hyperSPARC", "hypersparc" }, + { "", "leon" }, /* Probably irrelevant for Solaris. */ + { "", "sparclite" }, + { "", "f930" }, + { "", "f934" }, + { "", "sparclite86x" }, + { "", "tsc701" }, + { "", "v9" }, + { "UltraSPARC-I", "ultrasparc" }, + { "UltraSPARC-II", "ultrasparc" }, + { "UltraSPARC-IIe", "ultrasparc" }, + { "UltraSPARC-IIi", "ultrasparc" }, + { "SPARC64-III", "ultrasparc" }, + { "SPARC64-IV", "ultrasparc" }, + { "UltraSPARC-III", "ultrasparc3" }, + { "UltraSPARC-III+", "ultrasparc3" }, + { "UltraSPARC-IIIi", "ultrasparc3" }, + { "UltraSPARC-IIIi+", "ultrasparc3" }, + { "UltraSPARC-IV", "ultrasparc3" }, + { "UltraSPARC-IV+", "ultrasparc3" }, + { "SPARC64-V", "ultrasparc3" }, + { "SPARC64-VI", "ultrasparc3" }, + { "SPARC64-VII", "ultrasparc3" }, + { "UltraSPARC-T1", "niagara" }, + { "UltraSPARC-T2", "niagara2" }, + { "UltraSPARC-T2", "niagara2" }, + { "UltraSPARC-T2+", "niagara2" }, + { "SPARC-T3", "niagara2" }, + { "SPARC-T4", "niagara2" }, +#else + /* FIXME: Provide Linux/SPARC values. */ +#endif + { NULL, NULL } + }; + +#if defined __sun__ && defined __svr4__ +#include <kstat.h> +#endif + +/* This will be called by the spec parser in gcc.c when it sees + a %:local_cpu_detect(args) construct. Currently it will be called + with either "cpu" or "tune" as argument depending on if -mcpu=native + or -mtune=native is to be substituted. + + It returns a string containing new command line parameters to be + put at the place of the above two options, depending on what CPU + this is executed. E.g. "-mcpu=ultrasparc3" on an UltraSPARC III for + -mcpu=native. If the routine can't detect a known processor, + the -mcpu or -mtune option is discarded. + + ARGC and ARGV are set depending on the actual arguments given + in the spec. */ +const char * +host_detect_local_cpu (int argc, const char **argv) +{ + const char *cpu = NULL; +#if defined __sun__ && defined __svr4__ + char *buf = NULL; + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *brand = NULL; +#else + char buf[128]; + FILE *f; +#endif + int i; + + if (argc < 1) + return NULL; + + if (strcmp (argv[0], "cpu") && strcmp (argv[0], "tune")) + return NULL; + +#if defined __sun__ && defined __svr4__ + kc = kstat_open (); + if (kc != NULL) + { + ksp = kstat_lookup (kc, CONST_CAST2 (char *, const char *, "cpu_info"), + -1, NULL); + if (ksp != NULL && kstat_read (kc, ksp, NULL) != -1) + brand = (kstat_named_t *) + kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *, "brand")); + /* "brand" was only introduced in Solaris 10. */ + if (brand == NULL) + brand = (kstat_named_t *) + kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *, + "implementation")); + if (brand != NULL && brand->data_type == KSTAT_DATA_STRING) + buf = KSTAT_NAMED_STR_PTR (brand); + } + kstat_close (kc); + + for (i = 0; cpu_names[i].name != NULL; i++) + if (strcmp (buf, cpu_names[i].name) == 0) + cpu = cpu_names[i].cpu; +#else + f = fopen ("/proc/cpuinfo", "r"); + if (f == NULL) + return NULL; + + while (fgets (buf, sizeof (buf), f) != NULL) + if (strncmp (buf, "cpu model", sizeof ("cpu model") - 1) == 0) + { + for (i = 0; cpu_names [i].name; i++) + if (strstr (buf, cpu_names [i].name) != NULL) + { + cpu = cpu_names [i].cpu; + break; + } + break; + } + + fclose (f); +#endif + + if (cpu == NULL) + return NULL; + + return concat ("-m", argv[0], "=", cpu, NULL); +} diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -157,6 +157,22 @@ along with GCC; see the file COPYING3. %{!m32:%{!m64:%(cpp_arch_default)}} \ " +/* -mcpu=native handling only makes sense with compiler running on + a SPARC chip. */ +#if defined(__sparc__) +extern const char *host_detect_local_cpu (int argc, const char **argv); +# define EXTRA_SPEC_FUNCTIONS \ + { "local_cpu_detect", host_detect_local_cpu }, + +# define MCPU_MTUNE_NATIVE_SPECS \ + " %{mcpu=native:%<mcpu=native %:local_cpu_detect(cpu)}" \ + " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}" +#else +# define MCPU_MTUNE_NATIVE_SPECS "" +#endif + +#define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS + #undef CC1_SPEC #if DEFAULT_ARCH32_P #define CC1_SPEC "\ diff --git a/gcc/config/sparc/sparc-opts.h b/gcc/config/sparc/sparc-opts.h --- a/gcc/config/sparc/sparc-opts.h +++ b/gcc/config/sparc/sparc-opts.h @@ -41,7 +41,8 @@ enum processor_type { PROCESSOR_ULTRASPARC, PROCESSOR_ULTRASPARC3, PROCESSOR_NIAGARA, - PROCESSOR_NIAGARA2 + PROCESSOR_NIAGARA2, + PROCESSOR_NATIVE }; #endif diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt --- a/gcc/config/sparc/sparc.opt +++ b/gcc/config/sparc/sparc.opt @@ -101,6 +101,9 @@ Enum Name(sparc_processor_type) Type(enum processor_type) EnumValue +Enum(sparc_processor_type) String(native) Value(PROCESSOR_NATIVE) DriverOnly + +EnumValue Enum(sparc_processor_type) String(v7) Value(PROCESSOR_V7) EnumValue diff --git a/gcc/config/sparc/x-sparc b/gcc/config/sparc/x-sparc new file mode 100644 --- /dev/null +++ b/gcc/config/sparc/x-sparc @@ -0,0 +1,3 @@ +driver-sparc.o: $(srcdir)/config/sparc/driver-sparc.c \ + $(CONFIG_H) $(SYSTEM_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< diff --git a/gcc/configure.ac b/gcc/configure.ac --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -970,6 +970,14 @@ GNAT_LIBEXC="$LIBS" LIBS="$save_LIBS" AC_SUBST(GNAT_LIBEXC) +# To support -mcpu=native on Solaris/SPARC, we need libkstat. +save_LIBS="$LIBS" +LIBS= +AC_SEARCH_LIBS(kstat_open, kstat) +EXTRA_GCC_LIBS="$LIBS" +LIBS="$save_LIBS" +AC_SUBST(EXTRA_GCC_LIBS) + # Some systems put ldexp and frexp in libm instead of libc; assume # they're both in the same place. jcf-dump needs them. save_LIBS="$LIBS" diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -63,7 +63,8 @@ g++spec.o: $(srcdir)/cp/g++spec.c $(SYST GXX_OBJS = $(GCC_OBJS) g++spec.o g++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS) + $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ + $(EXTRA_GCC_LIBS) $(LIBS) # Create a version of the g++ driver which calls the cross-compiler. g++-cross$(exeext): g++$(exeext) diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in --- a/gcc/fortran/Make-lang.in +++ b/gcc/fortran/Make-lang.in @@ -88,7 +88,8 @@ GFORTRAN_D_OBJS = $(GCC_OBJS) gfortransp gfortran$(exeext): $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS) + $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ + $(EXTRA_GCC_LIBS) $(LIBS) # Create a version of the gfortran driver which calls the cross-compiler. gfortran-cross$(exeext): gfortran$(exeext) diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in --- a/gcc/go/Make-lang.in +++ b/gcc/go/Make-lang.in @@ -39,7 +39,8 @@ gospec.o: $(srcdir)/go/gospec.c $(SYSTEM GCCGO_OBJS = $(GCC_OBJS) gospec.o gccgo$(exeext): $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ - $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS) + $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \ + $(EXTRA_GCC_LIBS) $(LIBS) # Use strict warnings. go-warn = $(STRICT_WARN) diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -66,7 +66,8 @@ jvspec.o: $(srcdir)/java/jvspec.c $(SYST $(XGCJ)$(exeext): $(GCC_OBJS) jvspec.o java/jcf-path.o \ libcommon-target.a $(LIBDEPS) $(EXTRA_GCC_OBJS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \ - jvspec.o java/jcf-path.o $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS) + jvspec.o java/jcf-path.o $(EXTRA_GCC_OBJS) libcommon-target.a \ + $(EXTRA_GCC_LIBS) $(LIBS) # Create a version of the $(XGCJ) driver which calls the cross-compiler. $(XGCJ)-cross$(exeext): $(XGCJ)$(exeext) -- ----------------------------------------------------------------------------- Rainer Orth, Center for Biotechnology, Bielefeld University