]>
Commit | Line | Data |
---|---|---|
09cae750 PD |
1 | #!/usr/bin/env python |
2 | ||
3 | # RISC-V multilib list generator. | |
99dee823 | 4 | # Copyright (C) 2011-2021 Free Software Foundation, Inc. |
09cae750 PD |
5 | # Contributed by Andrew Waterman (andrew@sifive.com). |
6 | # | |
7 | # This file is part of GCC. | |
8 | # | |
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) | |
12 | # any later version. | |
13 | # | |
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. | |
18 | # | |
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/>. | |
22 | ||
23 | # Each argument to this script is of the form | |
24 | # <primary arch>-<abi>-<additional arches>-<extensions> | |
df7f0a3a | 25 | # Example 1: |
09cae750 PD |
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 | |
df7f0a3a KC |
29 | # |
30 | # Example 2: | |
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, | |
34 | # rv32imafdcb-ilp32d | |
09cae750 PD |
35 | |
36 | from __future__ import print_function | |
37 | import sys | |
b20cd0c7 | 38 | import os |
09cae750 | 39 | import collections |
df7f0a3a KC |
40 | import itertools |
41 | from functools import reduce | |
b20cd0c7 | 42 | import subprocess |
df7f0a3a KC |
43 | |
44 | # | |
45 | # TODO: Add test for this script. | |
46 | # | |
09cae750 PD |
47 | |
48 | arches = collections.OrderedDict() | |
49 | abis = collections.OrderedDict() | |
50 | required = [] | |
51 | reuse = [] | |
52 | ||
7551a6e4 | 53 | def arch_canonicalize(arch): |
b20cd0c7 KC |
54 | this_file = os.path.abspath(os.path.join( __file__)) |
55 | arch_can_script = \ | |
56 | os.path.join(os.path.dirname(this_file), "arch-canonicalize") | |
8d63e3c2 SC |
57 | proc = subprocess.Popen([sys.executable, arch_can_script, arch], |
58 | stdout=subprocess.PIPE) | |
b20cd0c7 | 59 | out, err = proc.communicate() |
168be2b3 | 60 | return out.decode().strip() |
df7f0a3a KC |
61 | |
62 | # | |
63 | # Handle expansion operation. | |
64 | # | |
65 | # e.g. "a*b" -> [("a",), ("b",), ("a", "b")] | |
66 | # "a" -> [("a",)] | |
67 | # | |
68 | def _expand_combination(ext): | |
69 | exts = list(ext.split("*")) | |
70 | ||
71 | # No need to expand if there is no `*`. | |
72 | if len(exts) == 1: | |
73 | return [(exts[0],)] | |
74 | ||
75 | # Add underline to every extension. | |
76 | # e.g. | |
77 | # _b * zvamo => _b * _zvamo | |
78 | exts = list(map(lambda x: '_' + x, exts)) | |
79 | ||
80 | # Generate combination! | |
81 | ext_combs = [] | |
82 | for comb_len in range(1, len(exts)+1): | |
83 | for ext_comb in itertools.combinations(exts, comb_len): | |
84 | ext_combs.append(ext_comb) | |
85 | ||
86 | return ext_combs | |
87 | ||
88 | # | |
89 | # Input a list and drop duplicated entry. | |
90 | # e.g. | |
91 | # ["a", "b", "ab", "a"] -> ["a", "b", "ab"] | |
92 | # | |
93 | def unique(x): | |
94 | # | |
95 | # Drop duplicated entry. | |
96 | # Convert list to set and then convert back to list. | |
97 | # | |
98 | # Add sorted to prevent non-deterministic results in different env. | |
99 | # | |
100 | return list(sorted(list(set(x)))) | |
101 | ||
102 | # | |
103 | # Expand EXT string if there is any expansion operator (*). | |
104 | # e.g. | |
105 | # "a*b,c" -> ["a", "b", "ab", "c"] | |
106 | # | |
107 | def expand_combination(ext): | |
108 | ext = list(filter(None, ext.split(','))) | |
109 | ||
110 | # Expand combination for EXT, got lots of list. | |
111 | # e.g. | |
112 | # a * b => [[("a",), ("b",)], [("a", "b")]] | |
113 | ext_combs = list(map(_expand_combination, ext)) | |
114 | ||
115 | # Then fold to single list. | |
116 | # e.g. | |
117 | # [[("a",), ("b",)], [("a", "b")]] => [("a",), ("b",), ("a", "b")] | |
118 | ext = list(reduce(lambda x, y: x + y, ext_combs, [])) | |
119 | ||
120 | # Fold the tuple to string. | |
121 | # e.g. | |
122 | # [("a",), ("b",), ("a", "b")] => ["a", "b", "ab"] | |
123 | ext = map(lambda e : reduce(lambda x, y: x + y, e), ext) | |
124 | ||
125 | # Drop duplicated entry. | |
126 | ext = unique(ext) | |
127 | ||
128 | return ext | |
129 | ||
09cae750 | 130 | for cfg in sys.argv[1:]: |
c1e66912 KC |
131 | try: |
132 | (arch, abi, extra, ext) = cfg.split('-') | |
133 | except: | |
134 | print ("Invalid configure string %s, <arch>-<abi>-<extra>-<extensions>\n" | |
135 | "<extra> and <extensions> can be empty, " | |
136 | "e.g. rv32imafd-ilp32--" % cfg) | |
137 | sys.exit(1) | |
138 | ||
a4b531b2 | 139 | arch = arch_canonicalize (arch) |
09cae750 PD |
140 | arches[arch] = 1 |
141 | abis[abi] = 1 | |
142 | extra = list(filter(None, extra.split(','))) | |
df7f0a3a KC |
143 | ext_combs = expand_combination(ext) |
144 | alts = sum([[x] + [x + y for y in ext_combs] for x in [arch] + extra], []) | |
7551a6e4 | 145 | alts = list(map(arch_canonicalize, alts)) |
df7f0a3a KC |
146 | |
147 | # Drop duplicated entry. | |
148 | alts = unique(alts) | |
149 | ||
09cae750 PD |
150 | for alt in alts[1:]: |
151 | arches[alt] = 1 | |
152 | reuse.append('march.%s/mabi.%s=march.%s/mabi.%s' % (arch, abi, alt, abi)) | |
153 | required.append('march=%s/mabi=%s' % (arch, abi)) | |
154 | ||
155 | arch_options = '/'.join(['march=%s' % x for x in arches.keys()]) | |
156 | arch_dirnames = ' \\\n'.join(arches.keys()) | |
157 | ||
158 | abi_options = '/'.join(['mabi=%s' % x for x in abis.keys()]) | |
159 | abi_dirnames = ' \\\n'.join(abis.keys()) | |
160 | ||
161 | prog = sys.argv[0].split('/')[-1] | |
162 | print('# This file was generated by %s with the command:' % prog) | |
163 | print('# %s' % ' '.join(sys.argv)) | |
164 | ||
165 | print('MULTILIB_OPTIONS = %s %s' % (arch_options, abi_options)) | |
166 | print('MULTILIB_DIRNAMES = %s %s' % (arch_dirnames, abi_dirnames)) | |
167 | print('MULTILIB_REQUIRED = %s' % ' \\\n'.join(required)) | |
168 | print('MULTILIB_REUSE = %s' % ' \\\n'.join(reuse)) |