Resent with the patch expanded correctly (I guess, it wasn't because of UTF-8 
encoding...). 

Hi everyone,

Since noone answered, I assume that MULTILIB_REUSE was indeed not the solution. 
Thus, I've implemented a solution using a new target macro MULTILIB_FALLBACK. 
It allows any target to return a new multilib suffix based on the current
one being used by the algorithm. This solution is much simpler than
adding a new Makefile option like MULTILIB_REUSE and it allows targets
to fully control the new suffix, which can be an advantage.

However, this solution is not perfect. Especially, MULTILIB_FALLBACK must take
care of freeing "curr_multilib_dir" array, which might not be the best thing to
do. But letting "for_each_path" doing it is created a much more complex code,
which isn't better in my opinion.

Anyway, is a patch like the following one seems possible to be integrated or
should I search for a better solution ?

Thanks,
Clément

-----------------------------------------------------------------
>From 73efb4cc50a221ed45a4d44c06157fcf9124e320 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= <clement.chi...@atos.net>
Date: Mon, 12 Oct 2020 11:37:13 +0200
Subject: [PATCH] gcc: implement multilib fallbacks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Some targets needs to be able to fallback from multilib A to
multilib B if multilib A isn't available at runtime.
Currently, the searched paths generated by gcc only include a single
multilib suffix and the default library.
This patch adds MULTILIB_FALLBACK macro to allow targets to get extra
multlib suffixes in these paths.

gcc/ChangeLog:

2020-10-12  Clément Chigot  <clement.chi...@atos.net>

        * config/rs6000/aix.h (MULTILIB_FALLBACK): New Define
        * gcc.c (for_each_path): Allow several multilib suffixes
        to be tried, based on MULTILIB_FALLBACK macro.
---
 gcc/config/rs6000/aix.h | 21 +++++++++++++++
 gcc/gcc.c               | 60 ++++++++++++++++++++++++++++++-----------
 2 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h
index edd6fdb0ec2..9cff6a67e1c 100644
--- a/gcc/config/rs6000/aix.h
+++ b/gcc/config/rs6000/aix.h
@@ -280,3 +280,24 @@
 /* Use standard DWARF numbering for DWARF debugging information.  */
 #define RS6000_USE_DWARF_NUMBERING
 
+/* Threaded programs must be able to fallback on pthread FAT library
+   if their architecture directory isn't present.  This is happening
+   when a 32bit program built with a 64-bit gcc is running on a 32bit
+   runtime.  */
+#define MULTILIB_FALLBACK(CURR_MULTILIB)                               \
+  do                                                                   \
+    {                                                                  \
+      if (!strcmp (CURR_MULTILIB, "pthread/ppc64")                     \
+         || !(strcmp (CURR_MULTILIB, "pthread/ppc32")))                \
+       {                                                               \
+         free (CONST_CAST (char *, CURR_MULTILIB));                    \
+         CURR_MULTILIB = XNEWVEC (char, strlen ("pthread") + 1);       \
+         strcpy (CURR_MULTILIB, "pthread");                            \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         free (CONST_CAST (char *, CURR_MULTILIB));                    \
+         CURR_MULTILIB = NULL;                                         \
+       }                                                               \
+    }                                                                  \
+  while (0)
diff --git a/gcc/gcc.c b/gcc/gcc.c
index ff7b6c4a320..6bee64dbec9 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -2683,11 +2683,12 @@ clear_failure_queue (void)
 
 /* Call CALLBACK for each path in PATHS, breaking out early if CALLBACK
    returns non-NULL.
-   If DO_MULTI is true iterate over the paths twice, first with multilib
-   suffix then without, otherwise iterate over the paths once without
-   adding a multilib suffix.  When DO_MULTI is true, some attempt is made
-   to avoid visiting the same path twice, but we could do better.  For
-   instance, /usr/lib/../lib is considered different from /usr/lib.
+   If DO_MULTI is true iterate over the paths at least twice, first with
+   multilib suffixes then without any, otherwise iterate over the paths
+   once without adding a multilib suffix.  When DO_MULTI is true, some
+   attempt is made to avoid visiting the same path twice, but we could
+   do better.  For instance, /usr/lib/../lib is considered different
+   from /usr/lib.
    At least EXTRA_SPACE chars past the end of the path passed to
    CALLBACK are available for use by the callback.
    CALLBACK_INFO allows extra parameters to be passed to CALLBACK.
@@ -2712,11 +2713,18 @@ for_each_path (const struct path_prefix *paths,
   bool skip_multi_dir = false;
   bool skip_multi_os_dir = false;
 
+  char *curr_multilib_dir = NULL;
+  if (do_multi && multilib_dir)
+    {
+      curr_multilib_dir = XNEWVEC (char, strlen (multilib_dir));
+      strcpy (curr_multilib_dir, multilib_dir);
+    }
+
   multi_suffix = machine_suffix;
   just_multi_suffix = just_machine_suffix;
-  if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
+  if (do_multi && curr_multilib_dir && strcmp (curr_multilib_dir, ".") != 0)
     {
-      multi_dir = concat (multilib_dir, dir_separator_str, NULL);
+      multi_dir = concat (curr_multilib_dir, dir_separator_str, NULL);
       multi_suffix = concat (multi_suffix, multi_dir, NULL);
       just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
     }
@@ -2819,17 +2827,39 @@ for_each_path (const struct path_prefix *paths,
       if (multi_dir == NULL && multi_os_dir == NULL)
        break;
 
-      /* Run through the paths again, this time without multilibs.
+      /* Run through the paths again, this time with a new
+        multilib suffix or without any.
         Don't repeat any we have already seen.  */
       if (multi_dir)
        {
-         free (CONST_CAST (char *, multi_dir));
-         multi_dir = NULL;
-         free (CONST_CAST (char *, multi_suffix));
-         multi_suffix = machine_suffix;
-         free (CONST_CAST (char *, just_multi_suffix));
-         just_multi_suffix = just_machine_suffix;
-       }
+
+#ifdef MULTILIB_FALLBACK
+         /* Retrieve the next multilib to be tried.  */
+         if (curr_multilib_dir)
+           MULTILIB_FALLBACK (curr_multilib_dir);
+#else
+         free (curr_multilib_dir);
+         curr_multilib_dir = NULL;
+#endif
+         if (curr_multilib_dir)
+           {
+             free (CONST_CAST (char *, multi_dir));
+             multi_dir = concat (curr_multilib_dir, dir_separator_str, NULL);
+             free (CONST_CAST (char *, multi_suffix));
+             multi_suffix = concat (machine_suffix, multi_dir, NULL);
+             free (CONST_CAST (char *, just_multi_suffix));
+             just_multi_suffix = concat (just_machine_suffix, multi_dir, NULL);
+           }
+         else
+           {
+             free (CONST_CAST (char *, multi_dir));
+             multi_dir = NULL;
+             free (CONST_CAST (char *, multi_suffix));
+             multi_suffix = machine_suffix;
+             free (CONST_CAST (char *, just_multi_suffix));
+             just_multi_suffix = just_machine_suffix;
+           }
+  }
       else
        skip_multi_dir = true;
       if (multi_os_dir)
-- 
2.25.1

Reply via email to