3 # RISC-V multilib list generator.
4 # Copyright (C) 2011-2021 Free Software Foundation, Inc.
5 # Contributed by Andrew Waterman (andrew@sifive.com).
7 # This file is part of GCC.
9 # GCC is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3, or (at your option)
14 # GCC is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with GCC; see the file COPYING3. If not see
21 # <http://www.gnu.org/licenses/>.
23 # Each argument to this script is of the form
24 # <primary arch>-<abi>-<additional arches>-<extensions>
26 # rv32imafd-ilp32d-rv32g-c,v
27 # means that, in addition to rv32imafd, these configurations can also use the
28 # rv32imafd-ilp32d libraries: rv32imafdc, rv32imafdv, rv32g, rv32gc, rv32gv
31 # rv32imafd-ilp32d--c*b
32 # means that, in addition to rv32imafd, these configurations can also use the
33 # rv32imafd-ilp32d libraries: rv32imafdc-ilp32d, rv32imafdb-ilp32d,
36 from __future__
import print_function
41 from functools
import reduce
46 # TODO: Add test for this script.
49 arches
= collections
.OrderedDict()
50 abis
= collections
.OrderedDict()
54 def arch_canonicalize(arch
):
55 this_file
= os
.path
.abspath(os
.path
.join( __file__
))
57 os
.path
.join(os
.path
.dirname(this_file
), "arch-canonicalize")
58 proc
= subprocess
.Popen([sys
.executable
, arch_can_script
, arch
],
59 stdout
=subprocess
.PIPE
)
60 out
, err
= proc
.communicate()
61 return out
.decode().strip()
64 # Handle expansion operation.
66 # e.g. "a*b" -> [("a",), ("b",), ("a", "b")]
69 def _expand_combination(ext
):
70 exts
= list(ext
.split("*"))
72 # Add underline to every extension.
74 # _b * zvamo => _b * _zvamo
75 exts
= list(map(lambda x
: '_' + x
, exts
))
77 # No need to expand if there is no `*`.
81 # Generate combination!
83 for comb_len
in range(1, len(exts
)+1):
84 for ext_comb
in itertools
.combinations(exts
, comb_len
):
85 ext_combs
.append(ext_comb
)
90 # Input a list and drop duplicated entry.
92 # ["a", "b", "ab", "a"] -> ["a", "b", "ab"]
96 # Drop duplicated entry.
97 # Convert list to set and then convert back to list.
99 # Add sorted to prevent non-deterministic results in different env.
101 return list(sorted(list(set(x
))))
104 # Expand EXT string if there is any expansion operator (*).
106 # "a*b,c" -> ["a", "b", "ab", "c"]
108 def expand_combination(ext
):
109 ext
= list(filter(None, ext
.split(',')))
111 # Expand combination for EXT, got lots of list.
113 # a * b => [[("a",), ("b",)], [("a", "b")]]
114 ext_combs
= list(map(_expand_combination
, ext
))
116 # Then fold to single list.
118 # [[("a",), ("b",)], [("a", "b")]] => [("a",), ("b",), ("a", "b")]
119 ext
= list(reduce(lambda x
, y
: x
+ y
, ext_combs
, []))
121 # Fold the tuple to string.
123 # [("a",), ("b",), ("a", "b")] => ["a", "b", "ab"]
124 ext
= map(lambda e
: reduce(lambda x
, y
: x
+ y
, e
), ext
)
126 # Drop duplicated entry.
131 multilib_cfgs
= filter(lambda x
:not x
.startswith("--"), sys
.argv
[1:])
132 options
= filter(lambda x
:x
.startswith("--"), sys
.argv
[1:])
134 parser
= argparse
.ArgumentParser()
135 parser
.add_argument("--cmodel", type=str)
136 parser
.add_argument("cfgs", type=str, nargs
='*')
137 args
= parser
.parse_args()
140 cmodels
= [None] + args
.cmodel
.split(",")
144 cmodel_options
= '/'.join(['mcmodel=%s' % x
for x
in cmodels
[1:]])
145 cmodel_dirnames
= ' \\\n'.join(cmodels
[1:])
147 for cmodel
in cmodels
:
148 for cfg
in args
.cfgs
:
150 (arch
, abi
, extra
, ext
) = cfg
.split('-')
152 print ("Invalid configure string %s, <arch>-<abi>-<extra>-<extensions>\n"
153 "<extra> and <extensions> can be empty, "
154 "e.g. rv32imafd-ilp32--" % cfg
)
157 # Compact code model only support rv64.
158 if cmodel
== "compact" and arch
.startswith("rv32"):
161 arch
= arch_canonicalize (arch
)
164 extra
= list(filter(None, extra
.split(',')))
165 ext_combs
= expand_combination(ext
)
166 alts
= sum([[x
] + [x
+ y
for y
in ext_combs
] for x
in [arch
] + extra
], [])
167 alts
= list(map(arch_canonicalize
, alts
))
169 # Drop duplicated entry.
176 reuse
.append('march.%s/mabi.%s=march.%s/mabi.%s' % (arch
, abi
, alt
, abi
))
179 required
.append('march=%s/mabi=%s/mcmodel=%s' % (arch
, abi
, cmodel
))
181 required
.append('march=%s/mabi=%s' % (arch
, abi
))
183 arch_options
= '/'.join(['march=%s' % x
for x
in arches
.keys()])
184 arch_dirnames
= ' \\\n'.join(arches
.keys())
186 abi_options
= '/'.join(['mabi=%s' % x
for x
in abis
.keys()])
187 abi_dirnames
= ' \\\n'.join(abis
.keys())
189 prog
= sys
.argv
[0].split('/')[-1]
190 print('# This file was generated by %s with the command:' % prog
)
191 print('# %s' % ' '.join(sys
.argv
))
193 print('MULTILIB_OPTIONS = %s %s %s' % (arch_options
, abi_options
, cmodel_options
))
194 print('MULTILIB_DIRNAMES = %s %s %s' % (arch_dirnames
, abi_dirnames
, cmodel_dirnames
))
195 print('MULTILIB_REQUIRED = %s' % ' \\\n'.join(required
))
196 print('MULTILIB_REUSE = %s' % ' \\\n'.join(reuse
))