From b20cd0c743b8823d8ac4437bf893ce691fb820e8 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Wed, 25 Nov 2020 17:30:29 +0800 Subject: [PATCH] RISC-V: Canonicalize --with-arch - 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 | 1 + gcc/config/riscv/arch-canonicalize | 102 ++++++++++++++++++++++++++++ gcc/config/riscv/multilib-generator | 83 +++------------------- 3 files changed, 111 insertions(+), 75 deletions(-) create mode 100755 gcc/config/riscv/arch-canonicalize diff --git a/gcc/config.gcc b/gcc/config.gcc index b8d268651d1..7b138d1bee1 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -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 index 00000000000..2b4289e320d --- /dev/null +++ b/gcc/config/riscv/arch-canonicalize @@ -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 +# . + + +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 [*]" % sys.argv) + sys.exit(1) + +for arg in sys.argv[1:]: + print (arch_canonicalize(arg)) diff --git a/gcc/config/riscv/multilib-generator b/gcc/config/riscv/multilib-generator index 0d9ebcb321f..53c51dfa53f 100755 --- a/gcc/config/riscv/multilib-generator +++ b/gcc/config/riscv/multilib-generator @@ -35,9 +35,11 @@ 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. -- 2.30.2