From 961b7009ee1561d8a7aeb1c3b2a005baf9898610 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Mon, 12 Aug 1996 16:36:42 +0000 Subject: [PATCH] Speed up genmultilib; Add MULTIB_EXTRA_OPTS From-SVN: r12623 --- gcc/Makefile.in | 15 +++-- gcc/gcc.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++-------- gcc/genmultilib | 51 ++++++++++------ 3 files changed, 202 insertions(+), 50 deletions(-) diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 76616a8..71e8971 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -550,7 +550,7 @@ CCCP=cccp STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \ insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \ insn-attr.h insn-attrtab.c insn-opinit.c \ - stamp-flags stamp-config stamp-codes \ + stamp-flags stamp-config stamp-codes stamp-mlib \ stamp-output stamp-recog stamp-emit stamp-extract stamp-peep \ stamp-attr stamp-attrtab stamp-opinit stamp-proto stamp-crt stamp-crtS stamp-crt0 \ genemit$(exeext) genoutput$(exeext) genrecog$(exeext) genextract$(exeext) \ @@ -955,9 +955,16 @@ libgcc.a: $(LIBGCC1) $(LIBGCC2) # Use the genmultilib shell script to generate the information the gcc # driver program needs to select the library directory based on the # switches. -multilib.h: $(srcdir)/genmultilib Makefile - $(SHELL) $(srcdir)/genmultilib "$(MULTILIB_OPTIONS)" \ - "$(MULTILIB_DIRNAMES)" "$(MULTILIB_MATCHES)" "$(MULTILIB_EXCEPTIONS)" > multilib.h +multilib.h: stamp-mlib; @true +stamp-mlib: $(srcdir)/genmultilib Makefile + $(SHELL) $(srcdir)/genmultilib \ + "$(MULTILIB_OPTIONS)" \ + "$(MULTILIB_DIRNAMES)" \ + "$(MULTILIB_MATCHES)" \ + "$(MULTILIB_EXCEPTIONS)" \ + "$(MULTILIB_EXTRA_OPTS)" > tmp-mlib.h + $(srcdir)/move-if-change tmp-mlib.h multilib.h + touch stamp-mlib # Build multiple copies of libgcc.a, one for each target switch. stmp-multilib: $(LIBGCC1) libgcc2.c libgcc2.ready $(CONFIG_H) \ diff --git a/gcc/gcc.c b/gcc/gcc.c index 940c8e8..46ca22b 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -491,12 +491,21 @@ static char *startfile_spec = STARTFILE_SPEC; static char *switches_need_spaces = SWITCHES_NEED_SPACES; /* Some compilers have limits on line lengths, and the multilib_select - string can be very long, so we build it at run time. */ + and/or multilib_matches strings can be very long, so we build them at + run time. */ static struct obstack multilib_obstack; -static char *multilib_raw[] = { -#include "multilib.h" -}; static char *multilib_select; +static char *multilib_matches; +static char *multilib_defaults; +#include "multilib.h" + +/* Check whether a particular argument is a default argument. */ + +#ifndef MULTILIB_DEFAULTS +#define MULTILIB_DEFAULTS { "" } +#endif + +static char *multilib_defaults_raw[] = MULTILIB_DEFAULTS; #ifdef EXTRA_SPECS static struct { char *name, *spec; } extra_specs[] = { EXTRA_SPECS }; @@ -1223,6 +1232,12 @@ set_spec (name, spec) cross_compile = atoi (sl->spec); else if (! strcmp (name, "multilib")) multilib_select = sl->spec; + else if (! strcmp (name, "multilib_matches")) + multilib_matches = sl->spec; + else if (! strcmp (name, "multilib_extra")) + multilib_extra = sl->spec; + else if (! strcmp (name, "multilib_defaults")) + multilib_defaults = sl->spec; #ifdef EXTRA_SPECS else { @@ -2244,6 +2259,9 @@ process_command (argc, argv) printf ("*predefines:\n%s\n\n", cpp_predefines); printf ("*cross_compile:\n%d\n\n", cross_compile); printf ("*multilib:\n%s\n\n", multilib_select); + printf ("*multilib_defaults:\n%s\n\n", multilib_defaults); + printf ("*multilib_extra:\n%s\n\n", multilib_extra); + printf ("*multilib_matches:\n%s\n\n", multilib_matches); #ifdef EXTRA_SPECS { @@ -4027,10 +4045,11 @@ main (argc, argv) obstack_init (&obstack); - /* Build multilib_select from the separate lines that make up each multilib - selection. */ + /* Build multilib_select, et. al from the separate lines that make up each + multilib selection. */ { char **q = multilib_raw; + int need_space; obstack_init (&multilib_obstack); while ((p = *q++) != (char *) 0) @@ -4038,6 +4057,29 @@ main (argc, argv) obstack_1grow (&multilib_obstack, 0); multilib_select = obstack_finish (&multilib_obstack); + + q = multilib_matches_raw; + while ((p = *q++) != (char *) 0) + obstack_grow (&multilib_obstack, p, strlen (p)); + + obstack_1grow (&multilib_obstack, 0); + multilib_matches = obstack_finish (&multilib_obstack); + + need_space = FALSE; + for (i = 0; + i < sizeof (multilib_defaults_raw) / sizeof (multilib_defaults_raw[0]); + i++) + { + if (need_space) + obstack_1grow (&multilib_obstack, ' '); + obstack_grow (&multilib_obstack, + multilib_defaults_raw[i], + strlen (multilib_defaults_raw[i])); + need_space = TRUE; + } + + obstack_1grow (&multilib_obstack, 0); + multilib_defaults = obstack_finish (&multilib_obstack); } /* Set up to remember the pathname of gcc and any options @@ -4825,43 +4867,114 @@ validate_switches (start) } } -/* Check whether a particular argument was used. */ +/* Check whether a particular argument was used. The first time we + canonialize the switches to keep only the ones we care about. */ static int used_arg (p, len) char *p; int len; { - int i; + struct mswitchstr { + char *str; + char *replace; + int len; + int rep_len; + }; + + static struct mswitchstr *mswitches; + static int n_mswitches; + int i, j; + + if (!mswitches) + { + struct mswitchstr *matches; + char *q; + int cnt = (*multilib_matches != '\0'); + + /* Break multilib_matches into the component strings of string and replacement + string */ + for (p = multilib_matches; *p != '\0'; p++) + if (*p == ';') + cnt++; + + matches = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt); + i = 0; + q = multilib_matches; + while (*q != '\0') + { + matches[i].str = q; + while (*q != ' ') + { + if (*q == '\0') + abort (); + q++; + } + *q = '\0'; + matches[i].len = q - matches[i].str; - for (i = 0; i < n_switches; i++) - if (! strncmp (switches[i].part1, p, len) - && strlen (switches[i].part1) == len) - return 1; - return 0; -} + matches[i].replace = ++q; + while (*q != ';' && *q != '\0') + { + if (*q == ' ') + abort (); + q++; + } + matches[i].rep_len = q - matches[i].replace; + i++; + if (*q == ';') + *q++ = '\0'; + else + break; + } -/* Check whether a particular argument is a default argument. */ + /* Now build a list of the replacement string for switches that we care about */ + mswitches = (struct mswitchstr *) xmalloc ((sizeof (struct mswitchstr)) * n_switches); + for (i = 0; i < n_switches; i++) + { + int xlen = strlen (switches[i].part1); + for (j = 0; j < cnt; j++) + if (xlen == matches[j].len && ! strcmp (switches[i].part1, matches[j].str)) + { + mswitches[n_mswitches].str = matches[j].replace; + mswitches[n_mswitches].len = matches[j].rep_len; + mswitches[n_mswitches].replace = (char *)0; + mswitches[n_mswitches].rep_len = 0; + n_mswitches++; + break; + } + } + } -#ifndef MULTILIB_DEFAULTS -#define MULTILIB_DEFAULTS { NULL } -#endif + for (i = 0; i < n_mswitches; i++) + if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len)) + return 1; -static char *multilib_defaults[] = MULTILIB_DEFAULTS; + return 0; +} static int default_arg (p, len) char *p; int len; { - int count = sizeof multilib_defaults / sizeof multilib_defaults[0]; + char *start, *end; int i; - for (i = 0; i < count; i++) - if (multilib_defaults[i] != NULL - && strncmp (multilib_defaults[i], p, len) == 0 - && multilib_defaults[i][len] == '\0') - return 1; + for (start = multilib_defaults; *start != '\0'; start = end+1) + { + while (*start == ' ' || *start == '\t') + start++; + + if (*start == '\0') + break; + + for (end = start+1; *end != ' ' && *end != '\t' && *end != '\0'; end++) + ; + + if ((end - start) == len && strncmp (p, start, len) == 0) + return 1; + } return 0; } @@ -5089,7 +5202,28 @@ print_multilib_info () } if (! skip) - putchar ('\n'); + { + /* If there are extra options, print them now */ + if (multilib_extra && *multilib_extra) + { + int print_at = TRUE; + char *q; + + for (q = multilib_extra; *q != '\0'; q++) + { + if (*q == ' ') + print_at = TRUE; + else + { + if (print_at) + putchar ('@'); + putchar (*q); + print_at = FALSE; + } + } + } + putchar ('\n'); + } ++p; } diff --git a/gcc/genmultilib b/gcc/genmultilib index e66106f..1ae690b 100644 --- a/gcc/genmultilib +++ b/gcc/genmultilib @@ -1,6 +1,6 @@ #!/bin/sh # Generates multilib.h. -# Copyright (C) 1994, 1995 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. #This file is part of GNU CC. @@ -45,6 +45,9 @@ # The optional fourth argument is a list of multilib directory # combinations that should not be built. +# The optional fifth argument is a list of options that should be +# used whenever building multilib libraries. + # The output looks like # #define MULTILIB_MATCHES "\ # SUBDIRECTORY OPTIONS;\ @@ -81,6 +84,9 @@ options=$1 dirnames=$2 matches=$3 exceptions=$4 +extra=$5 + +echo "static char *multilib_raw[] = {" # What we want to do is select all combinations of the sets in # options. Each combination which includes a set of mutually @@ -158,16 +164,6 @@ if [ -n "${dirnames}" ]; then done fi -# Construct a sed pattern which will add negations based on the -# matches. The semicolons are easier than getting the shell to accept -# quoted spaces when expanding a variable. -matchnegations= -for i in ${matches}; do - l=`echo $i | sed -e 's/=.*$//' -e 's/?/=/g'` - r=`echo $i | sed -e 's/^.*=//' -e 's/?/=/g'` - matchnegations="${matchnegations} -e s/;!${l};/;!${l};!${r};/" -done - # We need another recursive shell script to correctly handle positive # matches. If we are invoked as # genmultilib "opt1 opt2" "" "opt1=nopt1 opt2=nopt2" @@ -207,9 +203,6 @@ for set in ${options}; do done done optout=`echo ${optout} | sed -e 's/^ //'` -if [ -n "${matchnegations}" ]; then - optout=`echo ";${optout};" | sed -e 's/ /;/g' ${matchnegations} -e 's/^;//' -e 's/;$//' -e 's/;/ /g'` -fi echo "\". ${optout};\"," # Work over the list of combinations. We have to translate each one @@ -241,18 +234,36 @@ for combo in ${combinations}; do done optout=`echo ${optout} | sed -e 's/^ //'` - # Add any negations of matches. - if [ -n "${matchnegations}" ]; then - optout=`echo ";${optout};" | sed -e 's/ /;/g' ${matchnegations} -e 's/^;//' -e 's/;$//' -e 's/;/ /g'` - fi - # Output the line with all appropriate matches. - dirout="${dirout}" optout="${optout}" ./tmpmultilib2 ${matches} + dirout="${dirout}" optout="${optout}" ./tmpmultilib2 done # Terminate the list of string. echo "NULL" +echo "};" + +# Output all of the matches now as option and that is the same as that, with +# a semicolan trailer. Include all of the normal options as well. +# Note, the format of the matches is reversed compared +# to what we want, so switch them around. +echo "" +echo "static char *multilib_matches_raw[] = {" +for match in ${matches}; do + l=`echo ${match} | sed -e 's/=.*$//' -e 's/?/=/g'` + r=`echo ${match} | sed -e 's/^.*=//' -e 's/?/=/g'` + echo "\"${r} ${l};\"," +done +for set in ${options}; do + for opt in `echo ${set} | sed -e 's|/| |'g`; do + echo "\"${opt} ${opt};\"," + done +done +echo "NULL" +echo "};" +# Output the default options now +echo "" +echo "static char *multilib_extra = \"${extra}\";" rm -f tmpmultilib2 exit 0 -- 2.7.4