From e7f49d92ca829a0a51c1cb3ae26ebb0cb08f0fed Mon Sep 17 00:00:00 2001 From: Terry Guo Date: Sun, 13 Jan 2013 10:12:07 +0000 Subject: [PATCH] Makefile.in (s-mlib): New argument MULTILIB_REUSE. 2013-01-13 Terry Guo * gcc/Makefile.in (s-mlib): New argument MULTILIB_REUSE. * gcc/doc/fragments.texi: Document MULTILIB_REUSE. * gcc/gcc.c (multilib_reuse): New internal spec. (set_multilib_dir): Also search multilib from multilib_reuse. * gcc/genmultilib (tmpmultilib3): Refactor code. (tmpmultilib4): Ditto. (multilib_reuse): New multilib argument. From-SVN: r195134 --- gcc/ChangeLog | 10 +++ gcc/Makefile.in | 4 +- gcc/doc/fragments.texi | 29 +++++++++ gcc/gcc.c | 19 +++++- gcc/genmultilib | 162 ++++++++++++++++++++++++++++++++++--------------- 5 files changed, 173 insertions(+), 51 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index db65bea..c470658 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2013-01-13 Terry Guo + + * gcc/Makefile.in (s-mlib): New argument MULTILIB_REUSE. + * gcc/doc/fragments.texi: Document MULTILIB_REUSE. + * gcc/gcc.c (multilib_reuse): New internal spec. + (set_multilib_dir): Also search multilib from multilib_reuse. + * gcc/genmultilib (tmpmultilib3): Refactor code. + (tmpmultilib4): Ditto. + (multilib_reuse): New multilib argument. + 2013-01-13 Richard Sandiford * Makefile.in: Update copyright. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 3b2cf3c..55b4d2d 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1828,10 +1828,12 @@ s-mlib: $(srcdir)/genmultilib Makefile "$(MULTILIB_OSDIRNAMES)" \ "$(MULTILIB_REQUIRED)" \ "$(MULTIARCH_DIRNAME)" \ + "$(MULTILIB_REUSE)" \ "@enable_multilib@" \ > tmp-mlib.h; \ else \ - $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' '' "$(MULTIARCH_DIRNAME)" no \ + $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' '' \ + "$(MULTIARCH_DIRNAME)" '' no \ > tmp-mlib.h; \ fi $(SHELL) $(srcdir)/../move-if-change tmp-mlib.h multilib.h diff --git a/gcc/doc/fragments.texi b/gcc/doc/fragments.texi index a108ab0..b9a0c34 100644 --- a/gcc/doc/fragments.texi +++ b/gcc/doc/fragments.texi @@ -148,6 +148,35 @@ The @code{MULTILIB_REQUIRED} can be used together with @code{MULTILIB_OPTIONS} will be filtered by @code{MULTILIB_EXCEPTIONS} and then by @code{MULTILIB_REQUIRED}. +@findex MULTILIB_REUSE +@item MULTILIB_REUSE +Sometimes it is desirable to reuse one existing multilib for different +sets of options. Such kind of reuse can minimize the number of multilib +variants. And for some targets it is better to reuse an existing multilib +than to fall back to default multilib when there is no corresponding multilib. +This can be done by adding reuse rules to @code{MULTILIB_REUSE}. + +A reuse rule is comprised of two parts connected by equality sign. The left part +is option set used to build multilib and the right part is option set that will +reuse this multilib. The order of options in the left part matters and should be +same with those specified in @code{MULTILIB_REQUIRED} or aligned with order in +@code{MULTILIB_OPTIONS}. There is no such limitation for options in right part +as we don't build multilib from them. But the equality sign in both parts should +be replaced with period. + +The @code{MULTILIB_REUSE} is different from @code{MULTILIB_MATCHES} in that it +sets up relations between two option sets rather than two options. Here is an +example to demo how we reuse libraries built in Thumb mode for applications built +in ARM mode: +@smallexample +@code{MULTILIB_REUSE} = mthumb/march.armv7-r=marm/march.armv7-r +@end smallexample + +Before the advent of @code{MULTILIB_REUSE}, GCC select multilib by comparing command +line options with options used to build multilib. The @code{MULTILIB_REUSE} is +complementary to that way. Only when the original comparison matches nothing it will +work to see if it is OK to reuse some existing multilib. + @findex MULTILIB_EXTRA_OPTS @item MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building multiple versions of diff --git a/gcc/gcc.c b/gcc/gcc.c index 8bdb6bc..ff0f584 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -855,6 +855,7 @@ static const char *multilib_select; static const char *multilib_matches; static const char *multilib_defaults; static const char *multilib_exclusions; +static const char *multilib_reuse; /* Check whether a particular argument is a default argument. */ @@ -1248,6 +1249,7 @@ static struct spec_list static_specs[] = INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), INIT_STATIC_SPEC ("multilib_options", &multilib_options), + INIT_STATIC_SPEC ("multilib_reuse", &multilib_reuse), INIT_STATIC_SPEC ("linker", &linker_name_spec), INIT_STATIC_SPEC ("linker_plugin_file", &linker_plugin_file_spec), INIT_STATIC_SPEC ("lto_wrapper", <o_wrapper_spec), @@ -6323,6 +6325,13 @@ main (int argc, char **argv) obstack_1grow (&multilib_obstack, 0); multilib_exclusions = XOBFINISH (&multilib_obstack, const char *); + q = multilib_reuse_raw; + while ((p = *q++) != (char *) 0) + obstack_grow (&multilib_obstack, p, strlen (p)); + + obstack_1grow (&multilib_obstack, 0); + multilib_reuse = XOBFINISH (&multilib_obstack, const char *); + need_space = FALSE; for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++) { @@ -7536,6 +7545,12 @@ set_multilib_dir (void) first = 1; p = multilib_select; + + /* Append multilib reuse rules if any. With those rules, we can reuse + one multilib for certain different options sets. */ + if (strlen (multilib_reuse) > 0) + p = concat (p, multilib_reuse, NULL); + while (*p != '\0') { /* Ignore newlines. */ @@ -7552,8 +7567,8 @@ set_multilib_dir (void) if (*p == '\0') { invalid_select: - fatal_error ("multilib select %qs is invalid", - multilib_select); + fatal_error ("multilib select %qs %qs is invalid", + multilib_select, multilib_reuse); } ++p; } diff --git a/gcc/genmultilib b/gcc/genmultilib index 5afc6b5..4dca65d 100644 --- a/gcc/genmultilib +++ b/gcc/genmultilib @@ -85,6 +85,9 @@ # The optional ninth argument is the multiarch name. +# The optional tenth argument specifies how to reuse multilib for different +# option sets. + # The last option should be "yes" if multilibs are enabled. If it is not # "yes", all GCC multilib dir names will be ".". @@ -105,7 +108,7 @@ # genmultilib 'm64/m32 mno-app-regs|mcmodel=medany' '64 32 alt' # 'mcmodel?medany=mcmodel?medmid' 'm32/mno-app-regs* m32/mcmodel=*' # '' 'm32/!m64/mno-app-regs m32/!m64/mcmodel=medany' -# '../lib64 ../lib32 alt' '' yes +# '../lib64 ../lib32 alt' '' '' '' yes # This produces: # ". !m64 !m32 !mno-app-regs !mcmodel=medany;", # "64:../lib64 m64 !m32 !mno-app-regs !mcmodel=medany;", @@ -135,7 +138,8 @@ exclusions=$6 osdirnames=$7 multilib_required=$8 multiarch=$9 -enable_multilib=${10} +multilib_reuse=${10} +enable_multilib=${11} echo "static const char *const multilib_raw[] = {" @@ -349,61 +353,94 @@ done optout=`echo ${optout} | sed -e 's/^ //'` echo "\".${defaultosdirname} ${optout};\"," +# This part of code convert an option combination to +# its corresponding directory names. +# The directory names will be deduced from MULTILIB_DIRNAMES, +# MULTILIB_OSDIRNAMES or the option combination itself. +rm -rf tmpmultilib3 +cat >tmpmultilib3 <<\EOF +#!/bin/sh + +dirout= +combo=$1 +todirnames=$2 +toosdirnames=$3 +enable_multilib=$4 + +if [ -n "${todirnames}" ]; then + dirout=`echo ${combo} | sed ${todirnames}` +else + dirout=`echo ${combo} | sed -e 's/=/-/g'` +fi +# Remove the leading and trailing slashes. +dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/*:/*|:|' -e 's|/$||g'` + +# Use the OS directory names rather than the option names. +if [ -n "${toosdirnames}" ]; then + osdirout=`echo ${combo} | sed ${toosdirnames}` + # Remove the leading and trailing slashes. + osdirout=`echo ${osdirout} | sed -e 's|^/||' -e 's|/*:/*|:|' -e 's|/$||g'` + if [ "x${enable_multilib}" != xyes ]; then + dirout=".:${osdirout}" + disable_multilib=yes + else + case "${osdirout}" in + !*) + dirout=`echo ${osdirout} | sed 's/^!//'` + ;; + *) + dirout="${dirout}:${osdirout}" + ;; + esac + fi +else + if [ "x${enable_multilib}" != xyes ]; then + # genmultilib with --disable-multilib should be + # called with '' '' '' '' '' '' '' no + # if MULTILIB_OSDIRNAMES is empty. + exit 1 + fi +fi +echo "${dirout}" +EOF +chmod +x tmpmultilib3 + +# Script to look through the options and output each option that is present, +# and negate each option that is not present. +rm -rf tmpmultilib4 +cat > tmpmultilib4 <<\EOF +#!/bin/sh + +optout= +combo=$1 +options=$2 + +for set in ${options}; do + setopts=`echo ${set} | sed -e 's_[/|]_ _g'` + for opt in ${setopts}; do + if expr "${combo} " : ".*/${opt}/.*" > /dev/null; then + optout="${optout} ${opt}" + else + optout="${optout} !${opt}" + fi + done +done +optout=`echo ${optout} | sed -e 's/^ //'` +echo "${optout}" +EOF +chmod +x tmpmultilib4 + # Work over the list of combinations. We have to translate each one # to use the directory names rather than the option names, we have to # include the information in matches, and we have to generate the # correct list of options and negations. for combo in ${combinations}; do # Use the directory names rather than the option names. - if [ -n "${todirnames}" ]; then - dirout=`echo ${combo} | sed ${todirnames}` - else - dirout=`echo ${combo} | sed -e 's/=/-/g'` - fi - # Remove the leading and trailing slashes. - dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/*:/*|:|' -e 's|/$||g'` - - # Use the OS directory names rather than the option names. - if [ -n "${toosdirnames}" ]; then - osdirout=`echo ${combo} | sed ${toosdirnames}` - # Remove the leading and trailing slashes. - osdirout=`echo ${osdirout} | sed -e 's|^/||' -e 's|/*:/*|:|' -e 's|/$||g'` - if [ "x${enable_multilib}" != xyes ]; then - dirout=".:${osdirout}" - disable_multilib=yes - else - case "${osdirout}" in - !*) - dirout=`echo ${osdirout} | sed 's/^!//'` - ;; - *) - dirout="${dirout}:${osdirout}" - ;; - esac - fi - else - if [ "x${enable_multilib}" != xyes ]; then - # genmultilib with --disable-multilib should be - # called with '' '' '' '' '' '' '' no - # if MULTILIB_OSDIRNAMES is empty. - exit 1 - fi - fi + dirout=`./tmpmultilib3 "${combo}" "${todirnames}" "${toosdirnames}" "${enable_multilib}"` # Look through the options. We must output each option that is # present, and negate each option that is not present. - optout= - for set in ${options}; do - setopts=`echo ${set} | sed -e 's_[/|]_ _g'` - for opt in ${setopts}; do - if expr "${combo} " : ".*/${opt}/.*" > /dev/null; then - optout="${optout} ${opt}" - else - optout="${optout} !${opt}" - fi - done - done - optout=`echo ${optout} | sed -e 's/^ //'` + optout=`./tmpmultilib4 "${combo}" "${options}"` # Output the line with all appropriate matches. dirout="${dirout}" optout="${optout}" ./tmpmultilib2 @@ -413,6 +450,35 @@ done echo "NULL" echo "};" +# Output rules used for multilib reuse. +echo "" +echo "static const char *const multilib_reuse_raw[] = {" +for rrule in ${multilib_reuse}; do + # The left part of the rule are the options we used to build multilib. + # The right part of the rule are the options that can reuse this multilib. + combo=`echo ${rrule} | sed -e 's/=.*$//' -e 's/\./=/g'` + copts=`echo ${rrule} | sed -e 's/^.*=//' -e 's/\./=/g'` + # The variable ${combinations} are the option combinations we will build + # multilib from. If the combination in the left part of reuse rule isn't + # in this variable, it means no multilib will be built for current reuse + # rule. Thus the reuse purpose specified by current rule is meaningless. + if expr "${combinations} " : ".*/${combo}/.*" > /dev/null; then + combo="/${combo}/" + dirout=`./tmpmultilib3 "${combo}" "${todirnames}" "${toosdirnames}" "${enable_multilib}"` + copts="/${copts}/" + optout=`./tmpmultilib4 "${copts}" "${options}"` + # Output the line with all appropriate matches. + dirout="${dirout}" optout="${optout}" ./tmpmultilib2 + else + echo "The rule ${rrule} is trying to reuse nonexistent multilib." + exit 1 + fi +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 semicolon trailer. Include all of the normal options as well. # Note, the format of the matches is reversed compared -- 2.7.4