aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKito Cheng <kito.cheng@sifive.com>2025-03-10 16:26:04 +0800
committerKito Cheng <kito.cheng@sifive.com>2025-05-27 13:41:45 +0800
commit447156e4d143d7f513c488dd0b44037524a01fba (patch)
tree9a808d76d66b5655c2cce8b17353ac0dc92c01a5
parenta91679a3d9f7cbc079880f201fd8292c1d54baa7 (diff)
downloadgcc-447156e4d143d7f513c488dd0b44037524a01fba.zip
gcc-447156e4d143d7f513c488dd0b44037524a01fba.tar.gz
gcc-447156e4d143d7f513c488dd0b44037524a01fba.tar.bz2
driver: Fix multilib_os_dir and multiarch_dir for those target use TARGET_COMPUTE_MULTILIB
This patch fixes the multilib_os_dir and multiarch_dir for those targets that use TARGET_COMPUTE_MULTILIB, since the TARGET_COMPUTE_MULTILIB hook only update/fix the multilib_dir but not the multilib_os_dir and multiarch_dir, so the multilib_os_dir and multiarch_dir are not set correctly for those targets. Use RISC-V linux target (riscv64-unknown-linux-gnu) as an example: ``` $ riscv64-unknown-linux-gnu-gcc -print-multi-lib .; lib32/ilp32;@march=rv32imac@mabi=ilp32 lib32/ilp32d;@march=rv32imafdc@mabi=ilp32d lib64/lp64;@march=rv64imac@mabi=lp64 lib64/lp64d;@march=rv64imafdc@mabi=lp64d ``` If we use the exactly same -march and -mabi options to compile a source file, the multilib_os_dir and multiarch_dir are set correctly: ``` $ riscv64-unknown-linux-gnu-gcc -print-multi-os-directory -march=rv64imafdc -mabi=lp64d ../lib64/lp64d $ riscv64-unknown-linux-gnu-gcc -print-multi-directory -march=rv64imafdc -mabi=lp64d lib64/lp64d ``` However if we use the -march=rv64imafdcv -mabi=lp64d option to compile a source file, the multilib_os_dir and multiarch_dir are not set correctly: ``` $ riscv64-unknown-linux-gnu-gcc -print-multi-os-directory -march=rv64imafdc -mabi=lp64d lib64/lp64d $ riscv64-unknown-linux-gnu-gcc -print-multi-directory -march=rv64imafdc -mabi=lp64d lib64/lp64d ``` That's because the TARGET_COMPUTE_MULTILIB hook only update/fix the multilib_dir but not the multilib_os_dir, so the multilib_os_dir is blank and will use same value as multilib_dir, but that is not correct. So we introduce second chance to fix the multilib_os_dir if it's not set, we do also try to fix the multiarch_dir, because it may also not set correctly if multilib_os_dir is not set. Changes since v1: - Fix non-multilib build. - Fix fix indentation. gcc/ChangeLog: * gcc.cc (find_multilib_os_dir_by_multilib_dir): New. (set_multilib_dir): Fix multilib_os_dir and multiarch_dir if multilib_os_dir is not set.
-rw-r--r--gcc/gcc.cc108
1 files changed, 107 insertions, 1 deletions
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 4fd87f2..4e61de2 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -9747,6 +9747,103 @@ default_arg (const char *p, int len)
return 0;
}
+/* Use multilib_dir as key to find corresponding multilib_os_dir and
+ multiarch_dir. */
+
+static void
+find_multilib_os_dir_by_multilib_dir (const char *multilib_dir,
+ const char **p_multilib_os_dir,
+ const char **p_multiarch_dir)
+{
+ const char *p = multilib_select;
+ unsigned int this_path_len;
+ const char *this_path;
+ int ok = 0;
+
+ while (*p != '\0')
+ {
+ /* Ignore newlines. */
+ if (*p == '\n')
+ {
+ ++p;
+ continue;
+ }
+
+ /* Get the initial path. */
+ this_path = p;
+ while (*p != ' ')
+ {
+ if (*p == '\0')
+ {
+ fatal_error (input_location, "multilib select %qs %qs is invalid",
+ multilib_select, multilib_reuse);
+ }
+ ++p;
+ }
+ this_path_len = p - this_path;
+
+ ok = 0;
+
+ /* Skip any arguments, we don't care at this stage. */
+ while (*++p != ';');
+
+ if (this_path_len != 1
+ || this_path[0] != '.')
+ {
+ char *new_multilib_dir = XNEWVEC (char, this_path_len + 1);
+ char *q;
+
+ strncpy (new_multilib_dir, this_path, this_path_len);
+ new_multilib_dir[this_path_len] = '\0';
+ q = strchr (new_multilib_dir, ':');
+ if (q != NULL)
+ *q = '\0';
+
+ if (strcmp (new_multilib_dir, multilib_dir) == 0)
+ ok = 1;
+ }
+
+ /* Found matched multilib_dir, update multilib_os_dir and
+ multiarch_dir. */
+ if (ok)
+ {
+ const char *q = this_path, *end = this_path + this_path_len;
+
+ while (q < end && *q != ':')
+ q++;
+ if (q < end)
+ {
+ const char *q2 = q + 1, *ml_end = end;
+ char *new_multilib_os_dir;
+
+ while (q2 < end && *q2 != ':')
+ q2++;
+ if (*q2 == ':')
+ ml_end = q2;
+ if (ml_end - q == 1)
+ *p_multilib_os_dir = xstrdup (".");
+ else
+ {
+ new_multilib_os_dir = XNEWVEC (char, ml_end - q);
+ memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
+ new_multilib_os_dir[ml_end - q - 1] = '\0';
+ *p_multilib_os_dir = new_multilib_os_dir;
+ }
+
+ if (q2 < end && *q2 == ':')
+ {
+ char *new_multiarch_dir = XNEWVEC (char, end - q2);
+ memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
+ new_multiarch_dir[end - q2 - 1] = '\0';
+ *p_multiarch_dir = new_multiarch_dir;
+ }
+ break;
+ }
+ }
+ ++p;
+ }
+}
+
/* Work out the subdirectory to use based on the options. The format of
multilib_select is a list of elements. Each element is a subdirectory
name followed by a list of options followed by a semicolon. The format
@@ -10025,7 +10122,16 @@ set_multilib_dir (void)
multilib_os_dir = NULL;
}
else if (multilib_dir != NULL && multilib_os_dir == NULL)
- multilib_os_dir = multilib_dir;
+ {
+ /* Give second chance to search matched multilib_os_dir again by matching
+ the multilib_dir since some target may use TARGET_COMPUTE_MULTILIB
+ hook rather than the builtin way. */
+ find_multilib_os_dir_by_multilib_dir (multilib_dir, &multilib_os_dir,
+ &multiarch_dir);
+
+ if (multilib_os_dir == NULL)
+ multilib_os_dir = multilib_dir;
+ }
}
/* Print out the multiple library subdirectory selection