RISC-V: Canonicalize --with-arch
authorKito Cheng <kito.cheng@sifive.com>
Wed, 25 Nov 2020 09:30:29 +0000 (17:30 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Thu, 3 Dec 2020 09:39:27 +0000 (17:39 +0800)
 - We would like to canonicalize the arch string for --with-arch for
   easier handling multilib, so split canonicalization part to a stand
   along script to shared the logic.

gcc/ChangeLog:

* config/riscv/multilib-generator (arch_canonicalize): Move
code to arch-canonicalize, and call that script to canonicalize arch
string.
(canonical_order): Move code to arch-canonicalize.
(LONG_EXT_PREFIXES): Ditto.
(IMPLIED_EXT): Ditto.
* config/riscv/arch-canonicalize: New.
* config.gcc (riscv*-*-*): Canonicalize --with-arch.

gcc/config.gcc
gcc/config/riscv/arch-canonicalize [new file with mode: 0755]
gcc/config/riscv/multilib-generator

index b8d268651d16c56d356bd4b4130bb8bab0b46d62..7b138d1bee166857bb9487cf1918a11880730a98 100644 (file)
@@ -4615,6 +4615,7 @@ case "${target}" in
                        exit 1
                        ;;
                esac
+               with_arch=`${srcdir}/config/riscv/arch-canonicalize ${with_arch}`
                tm_defines="${tm_defines} TARGET_RISCV_DEFAULT_ARCH=${with_arch}"
 
                # Make sure --with-abi is valid.  If it was not specified,
diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize
new file mode 100755 (executable)
index 0000000..2b4289e
--- /dev/null
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+
+# Tool for canonical RISC-V architecture string.
+# Copyright (C) 2011-2020 Free Software Foundation, Inc.
+# Contributed by Andrew Waterman (andrew@sifive.com).
+#
+# 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/>.
+
+
+from __future__ import print_function
+import sys
+import collections
+import itertools
+from functools import reduce
+
+
+CANONICAL_ORDER = "mafdgqlcbjtpvn"
+LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
+
+#
+# IMPLIED_EXT(ext) -> implied extension list.
+#
+IMPLIED_EXT = {
+  "d" : ["f"],
+}
+
+def arch_canonicalize(arch):
+  # TODO: Support extension version.
+  new_arch = ""
+  if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64i', 'rv64g']:
+    # TODO: We should expand g to imad_zifencei once we support newer spec.
+    new_arch = arch[:5].replace("g", "imafd")
+  else:
+    raise Exception("Unexpected arch: `%s`" % arch[:5])
+
+  # Find any Z, S, H or X
+  long_ext_prefixes_idx = map(lambda x: arch.find(x), LONG_EXT_PREFIXES)
+
+  # Filter out any non-existent index.
+  long_ext_prefixes_idx = list(filter(lambda x: x != -1, long_ext_prefixes_idx))
+  if long_ext_prefixes_idx:
+    first_long_ext_idx = min(long_ext_prefixes_idx)
+    long_exts = arch[first_long_ext_idx:].split("_")
+    std_exts = list(arch[5:first_long_ext_idx])
+  else:
+    long_exts = []
+    std_exts = list(arch[5:])
+
+  #
+  # Handle implied extensions.
+  #
+  for ext in std_exts + long_exts:
+    if ext in IMPLIED_EXT:
+      implied_exts = IMPLIED_EXT[ext]
+      for implied_ext in implied_exts:
+        if implied_ext not in std_exts + long_exts:
+          long_exts.append(implied_ext)
+
+  # Single letter extension might appear in the long_exts list,
+  # becasue we just append extensions list to the arch string.
+  std_exts += list(filter(lambda x:len(x) == 1, long_exts))
+
+  # Multi-letter extension must be in lexicographic order.
+  long_exts = list(sorted(filter(lambda x:len(x) != 1, long_exts)))
+
+  # Put extensions in canonical order.
+  for ext in CANONICAL_ORDER:
+    if ext in std_exts:
+      new_arch += ext
+
+  # Check every extension is processed.
+  for ext in std_exts:
+    if ext == '_':
+      continue
+    if ext not in CANONICAL_ORDER:
+      raise Exception("Unsupported extension `%s`" % ext)
+
+  # Concat rest of the multi-char extensions.
+  if long_exts:
+    new_arch += "_" + "_".join(long_exts)
+  return new_arch
+
+if len(sys.argv) < 2:
+  print ("Usage: %s <arch_str> [<arch_str>*]" % sys.argv)
+  sys.exit(1)
+
+for arg in sys.argv[1:]:
+  print (arch_canonicalize(arg))
index 0d9ebcb321f59f75cb3957e9496c414fee5ea958..53c51dfa53f1df0b9a94fd681dbaa48a23cf0d37 100755 (executable)
 
 from __future__ import print_function
 import sys
+import os
 import collections
 import itertools
 from functools import reduce
+import subprocess
 
 #
 # TODO: Add test for this script.
@@ -48,82 +50,13 @@ abis = collections.OrderedDict()
 required = []
 reuse = []
 
-canonical_order = "mafdgqlcbjtpvn"
-LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
-
-#
-# IMPLIED_EXT(ext) -> implied extension list.
-#
-IMPLIED_EXT = {
-  "d" : ["f"],
-}
-
 def arch_canonicalize(arch):
-  # TODO: Support extension version.
-  new_arch = ""
-  if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64i', 'rv64g']:
-    # TODO: We should expand g to imad_zifencei once we support newer spec.
-    new_arch = arch[:5].replace("g", "imafd")
-  else:
-    raise Exception("Unexpected arch: `%s`" % arch[:5])
-
-  # Find any Z, S, H or X
-  long_ext_prefixes_idx = map(lambda x: arch.find(x), LONG_EXT_PREFIXES)
-
-  # Filter out any non-existent index.
-  long_ext_prefixes_idx = list(filter(lambda x: x != -1, long_ext_prefixes_idx))
-  if long_ext_prefixes_idx:
-    first_long_ext_idx = min(long_ext_prefixes_idx)
-    long_exts = arch[first_long_ext_idx:].split("_")
-    std_exts = list(arch[5:first_long_ext_idx])
-  else:
-    long_exts = []
-    std_exts = list(arch[5:])
-
-  #
-  # Handle implied extensions.
-  #
-  for ext in std_exts + long_exts:
-    if ext in IMPLIED_EXT:
-      implied_exts = IMPLIED_EXT[ext]
-      for implied_ext in implied_exts:
-        if implied_ext not in std_exts + long_exts:
-          long_exts.append(implied_ext)
-
-  # Single letter extension might appear in the long_exts list,
-  # becasue we just append extensions list to the arch string.
-  std_exts += list(filter(lambda x:len(x) == 1, long_exts))
-
-  # Multi-letter extension must be in lexicographic order.
-  long_exts = list(sorted(filter(lambda x:len(x) != 1, long_exts)))
-
-  # Put extensions in canonical order.
-  for ext in canonical_order:
-    if ext in std_exts:
-      new_arch += ext
-
-  # Check every extension is processed.
-  for ext in std_exts:
-    if ext == '_':
-      continue
-    if ext not in canonical_order:
-      raise Exception("Unsupported extension `%s`" % ext)
-
-  # Concat rest of the multi-char extensions.
-  if long_exts:
-    new_arch += "_" + "_".join(long_exts)
-  return new_arch
-
-#
-# add underline for each multi-char extensions.
-# e.g. ["a", "zfh"] -> ["a", "_zfh"]
-#
-def add_underline_prefix(ext):
-  for long_ext_prefix in LONG_EXT_PREFIXES:
-    if ext.startswith(long_ext_prefix):
-      return "_" + ext
-
-  return ext
+  this_file = os.path.abspath(os.path.join( __file__))
+  arch_can_script = \
+    os.path.join(os.path.dirname(this_file), "arch-canonicalize")
+  proc = subprocess.Popen([arch_can_script, arch], stdout=subprocess.PIPE)
+  out, err = proc.communicate()
+  return out.strip()
 
 #
 # Handle expansion operation.