1 /* Common hooks for RISC-V.
2 Copyright (C) 2016-2022 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include <sstream>
21
22 #define INCLUDE_STRING
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "common/common-target.h"
28 #include "common/common-target-def.h"
29 #include "opts.h"
30 #include "flags.h"
31 #include "diagnostic-core.h"
32 #include "config/riscv/riscv-protos.h"
33 #include "config/riscv/riscv-subset.h"
34
35 #ifdef TARGET_BIG_ENDIAN_DEFAULT
36 #undef TARGET_DEFAULT_TARGET_FLAGS
37 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_ENDIAN)
38 #endif
39
40 /* Type for implied ISA info. */
41 struct riscv_implied_info_t
42 {
43 const char *ext;
44 const char *implied_ext;
45 };
46
47 /* Implied ISA info, must end with NULL sentinel. */
48 static const riscv_implied_info_t riscv_implied_info[] =
49 {
50 {"d", "f"},
51 {"f", "zicsr"},
52 {"d", "zicsr"},
53 {"zk", "zkn"},
54 {"zk", "zkr"},
55 {"zk", "zkt"},
56 {"zkn", "zbkb"},
57 {"zkn", "zbkc"},
58 {"zkn", "zbkx"},
59 {"zkn", "zkne"},
60 {"zkn", "zknd"},
61 {"zkn", "zknh"},
62 {"zks", "zbkb"},
63 {"zks", "zbkc"},
64 {"zks", "zbkx"},
65 {"zks", "zksed"},
66 {"zks", "zksh"},
67
68 {"v", "zvl128b"},
69 {"v", "zve64d"},
70
71 {"zve32f", "f"},
72 {"zve64f", "f"},
73 {"zve64d", "d"},
74
75 {"zve32x", "zvl32b"},
76 {"zve32f", "zve32x"},
77 {"zve32f", "zvl32b"},
78
79 {"zve64x", "zve32x"},
80 {"zve64x", "zvl64b"},
81 {"zve64f", "zve32f"},
82 {"zve64f", "zve64x"},
83 {"zve64f", "zvl64b"},
84 {"zve64d", "zve64f"},
85 {"zve64d", "zvl64b"},
86
87 {"zvl64b", "zvl32b"},
88 {"zvl128b", "zvl64b"},
89 {"zvl256b", "zvl128b"},
90 {"zvl512b", "zvl256b"},
91 {"zvl1024b", "zvl512b"},
92 {"zvl2048b", "zvl1024b"},
93 {"zvl4096b", "zvl2048b"},
94 {"zvl8192b", "zvl4096b"},
95 {"zvl16384b", "zvl8192b"},
96 {"zvl32768b", "zvl16384b"},
97 {"zvl65536b", "zvl32768b"},
98
99 {NULL, NULL}
100 };
101
102 /* This structure holds version information for specific ISA version. */
103
104 struct riscv_ext_version
105 {
106 const char *name;
107 enum riscv_isa_spec_class isa_spec_class;
108 int major_version;
109 int minor_version;
110 };
111
112 /* All standard extensions defined in all supported ISA spec. */
113 static const struct riscv_ext_version riscv_ext_version_table[] =
114 {
115 /* name, ISA spec, major version, minor_version. */
116 {"e", ISA_SPEC_CLASS_20191213, 1, 9},
117 {"e", ISA_SPEC_CLASS_20190608, 1, 9},
118 {"e", ISA_SPEC_CLASS_2P2, 1, 9},
119
120 {"i", ISA_SPEC_CLASS_20191213, 2, 1},
121 {"i", ISA_SPEC_CLASS_20190608, 2, 1},
122 {"i", ISA_SPEC_CLASS_2P2, 2, 0},
123
124 {"m", ISA_SPEC_CLASS_20191213, 2, 0},
125 {"m", ISA_SPEC_CLASS_20190608, 2, 0},
126 {"m", ISA_SPEC_CLASS_2P2, 2, 0},
127
128 {"a", ISA_SPEC_CLASS_20191213, 2, 1},
129 {"a", ISA_SPEC_CLASS_20190608, 2, 0},
130 {"a", ISA_SPEC_CLASS_2P2, 2, 0},
131
132 {"f", ISA_SPEC_CLASS_20191213, 2, 2},
133 {"f", ISA_SPEC_CLASS_20190608, 2, 2},
134 {"f", ISA_SPEC_CLASS_2P2, 2, 0},
135
136 {"d", ISA_SPEC_CLASS_20191213, 2, 2},
137 {"d", ISA_SPEC_CLASS_20190608, 2, 2},
138 {"d", ISA_SPEC_CLASS_2P2, 2, 0},
139
140 {"c", ISA_SPEC_CLASS_20191213, 2, 0},
141 {"c", ISA_SPEC_CLASS_20190608, 2, 0},
142 {"c", ISA_SPEC_CLASS_2P2, 2, 0},
143
144 {"v", ISA_SPEC_CLASS_NONE, 1, 0},
145
146 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0},
147 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0},
148
149 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0},
150 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0},
151
152 {"zba", ISA_SPEC_CLASS_NONE, 1, 0},
153 {"zbb", ISA_SPEC_CLASS_NONE, 1, 0},
154 {"zbc", ISA_SPEC_CLASS_NONE, 1, 0},
155 {"zbs", ISA_SPEC_CLASS_NONE, 1, 0},
156
157 {"zbkb", ISA_SPEC_CLASS_NONE, 1, 0},
158 {"zbkc", ISA_SPEC_CLASS_NONE, 1, 0},
159 {"zbkx", ISA_SPEC_CLASS_NONE, 1, 0},
160 {"zkne", ISA_SPEC_CLASS_NONE, 1, 0},
161 {"zknd", ISA_SPEC_CLASS_NONE, 1, 0},
162 {"zknh", ISA_SPEC_CLASS_NONE, 1, 0},
163 {"zkr", ISA_SPEC_CLASS_NONE, 1, 0},
164 {"zksed", ISA_SPEC_CLASS_NONE, 1, 0},
165 {"zksh", ISA_SPEC_CLASS_NONE, 1, 0},
166 {"zkt", ISA_SPEC_CLASS_NONE, 1, 0},
167
168 {"zk", ISA_SPEC_CLASS_NONE, 1, 0},
169 {"zkn", ISA_SPEC_CLASS_NONE, 1, 0},
170 {"zks", ISA_SPEC_CLASS_NONE, 1, 0},
171
172 {"zve32x", ISA_SPEC_CLASS_NONE, 1, 0},
173 {"zve32f", ISA_SPEC_CLASS_NONE, 1, 0},
174 {"zve32d", ISA_SPEC_CLASS_NONE, 1, 0},
175 {"zve64x", ISA_SPEC_CLASS_NONE, 1, 0},
176 {"zve64f", ISA_SPEC_CLASS_NONE, 1, 0},
177 {"zve64d", ISA_SPEC_CLASS_NONE, 1, 0},
178
179 {"zvl32b", ISA_SPEC_CLASS_NONE, 1, 0},
180 {"zvl64b", ISA_SPEC_CLASS_NONE, 1, 0},
181 {"zvl128b", ISA_SPEC_CLASS_NONE, 1, 0},
182 {"zvl256b", ISA_SPEC_CLASS_NONE, 1, 0},
183 {"zvl512b", ISA_SPEC_CLASS_NONE, 1, 0},
184 {"zvl1024b", ISA_SPEC_CLASS_NONE, 1, 0},
185 {"zvl2048b", ISA_SPEC_CLASS_NONE, 1, 0},
186 {"zvl4096b", ISA_SPEC_CLASS_NONE, 1, 0},
187 {"zvl8192b", ISA_SPEC_CLASS_NONE, 1, 0},
188 {"zvl16384b", ISA_SPEC_CLASS_NONE, 1, 0},
189 {"zvl32768b", ISA_SPEC_CLASS_NONE, 1, 0},
190 {"zvl65536b", ISA_SPEC_CLASS_NONE, 1, 0},
191
192 /* Terminate the list. */
193 {NULL, ISA_SPEC_CLASS_NONE, 0, 0}
194 };
195
196 /* Combine extensions defined in this table */
197 static const struct riscv_ext_version riscv_combine_info[] =
198 {
199 {"zk", ISA_SPEC_CLASS_NONE, 1, 0},
200 {"zkn", ISA_SPEC_CLASS_NONE, 1, 0},
201 {"zks", ISA_SPEC_CLASS_NONE, 1, 0},
202 /* Terminate the list. */
203 {NULL, ISA_SPEC_CLASS_NONE, 0, 0}
204 };
205
206 static const riscv_cpu_info riscv_cpu_tables[] =
207 {
208 #define RISCV_CORE(CORE_NAME, ARCH, TUNE) \
209 {CORE_NAME, ARCH, TUNE},
210 #include "../../../config/riscv/riscv-cores.def"
211 {NULL, NULL, NULL}
212 };
213
214 static const char *riscv_supported_std_ext (void);
215
216 static riscv_subset_list *current_subset_list = NULL;
217
riscv_current_subset_list()218 const riscv_subset_list *riscv_current_subset_list ()
219 {
220 return current_subset_list;
221 }
222
riscv_subset_t()223 riscv_subset_t::riscv_subset_t ()
224 : name (), major_version (0), minor_version (0), next (NULL),
225 explicit_version_p (false), implied_p (false)
226 {
227 }
228
riscv_subset_list(const char * arch,location_t loc)229 riscv_subset_list::riscv_subset_list (const char *arch, location_t loc)
230 : m_arch (arch), m_loc (loc), m_head (NULL), m_tail (NULL), m_xlen (0)
231 {
232 }
233
~riscv_subset_list()234 riscv_subset_list::~riscv_subset_list ()
235 {
236 if (!m_head)
237 return;
238
239 riscv_subset_t *item = this->m_head;
240 while (item != NULL)
241 {
242 riscv_subset_t *next = item->next;
243 delete item;
244 item = next;
245 }
246 }
247
248 /* Get the rank for single-letter subsets, lower value meaning higher
249 priority. */
250
251 static int
single_letter_subset_rank(char ext)252 single_letter_subset_rank (char ext)
253 {
254 int rank;
255
256 switch (ext)
257 {
258 case 'i':
259 return 0;
260 case 'e':
261 return 1;
262 default:
263 break;
264 }
265
266 const char *all_ext = riscv_supported_std_ext ();
267 const char *ext_pos = strchr (all_ext, ext);
268 if (ext_pos == NULL)
269 /* If got an unknown extension letter, then give it an alphabetical
270 order, but after all known standard extension. */
271 rank = strlen (all_ext) + ext - 'a';
272 else
273 rank = (int)(ext_pos - all_ext) + 2 /* e and i has higher rank. */;
274
275 return rank;
276 }
277
278 /* Get the rank for multi-letter subsets, lower value meaning higher
279 priority. */
280
281 static int
multi_letter_subset_rank(const std::string & subset)282 multi_letter_subset_rank (const std::string &subset)
283 {
284 gcc_assert (subset.length () >= 2);
285 int high_order = -1;
286 int low_order = 0;
287 /* The order between multi-char extensions: s -> h -> z -> x. */
288 char multiletter_class = subset[0];
289 switch (multiletter_class)
290 {
291 case 's':
292 high_order = 0;
293 break;
294 case 'h':
295 high_order = 1;
296 break;
297 case 'z':
298 high_order = 2;
299 break;
300 case 'x':
301 high_order = 3;
302 break;
303 default:
304 gcc_unreachable ();
305 return -1;
306 }
307
308 if (multiletter_class == 'z')
309 /* Order for z extension on spec: If multiple "Z" extensions are named, they
310 should be ordered first by category, then alphabetically within a
311 category - for example, "Zicsr_Zifencei_Zam". */
312 low_order = single_letter_subset_rank (subset[1]);
313 else
314 low_order = 0;
315
316 return (high_order << 8) + low_order;
317 }
318
319 /* subset compare
320
321 Returns an integral value indicating the relationship between the subsets:
322 Return value indicates
323 -1 B has higher order than A.
324 0 A and B are same subset.
325 1 A has higher order than B.
326
327 */
328
329 static int
subset_cmp(const std::string & a,const std::string & b)330 subset_cmp (const std::string &a, const std::string &b)
331 {
332 if (a == b)
333 return 0;
334
335 size_t a_len = a.length ();
336 size_t b_len = b.length ();
337
338 /* Single-letter extension always get higher order than
339 multi-letter extension. */
340 if (a_len == 1 && b_len != 1)
341 return 1;
342
343 if (a_len != 1 && b_len == 1)
344 return -1;
345
346 if (a_len == 1 && b_len == 1)
347 {
348 int rank_a = single_letter_subset_rank (a[0]);
349 int rank_b = single_letter_subset_rank (b[0]);
350
351 if (rank_a < rank_b)
352 return 1;
353 else
354 return -1;
355 }
356 else
357 {
358 int rank_a = multi_letter_subset_rank(a);
359 int rank_b = multi_letter_subset_rank(b);
360
361 /* Using alphabetical/lexicographical order if they have same rank. */
362 if (rank_a == rank_b)
363 /* The return value of strcmp has opposite meaning. */
364 return -strcmp (a.c_str (), b.c_str ());
365 else
366 return (rank_a < rank_b) ? 1 : -1;
367 }
368 }
369
370 /* Add new subset to list. */
371
372 void
add(const char * subset,int major_version,int minor_version,bool explicit_version_p,bool implied_p)373 riscv_subset_list::add (const char *subset, int major_version,
374 int minor_version, bool explicit_version_p,
375 bool implied_p)
376 {
377 riscv_subset_t *ext = lookup (subset);
378
379 if (ext)
380 {
381 if (ext->implied_p)
382 {
383 /* We won't add impiled `ext` if it already in list. */
384 gcc_assert (!implied_p);
385 ext->implied_p = implied_p;
386 ext->major_version = major_version;
387 ext->minor_version = minor_version;
388 }
389 else
390 error_at (
391 m_loc,
392 "%<-march=%s%>: extension %qs appear more than one time",
393 m_arch,
394 subset);
395
396 return;
397 }
398
399 riscv_subset_t *s = new riscv_subset_t ();
400 riscv_subset_t *itr;
401
402 if (m_head == NULL)
403 m_head = s;
404
405 s->name = subset;
406 s->major_version = major_version;
407 s->minor_version = minor_version;
408 s->explicit_version_p = explicit_version_p;
409 s->implied_p = implied_p;
410 s->next = NULL;
411
412 if (m_tail == NULL)
413 {
414 m_tail = s;
415 return;
416 }
417
418 /* e, i or g should be first subext, never come here. */
419 gcc_assert (subset[0] != 'e'
420 && subset[0] != 'i'
421 && subset[0] != 'g');
422
423 if (m_tail == m_head)
424 {
425 gcc_assert (m_head->next == NULL);
426 m_head->next = s;
427 m_tail = s;
428 return;
429 }
430
431 gcc_assert (m_head->next != NULL);
432
433 /* Subset list must in canonical order, but implied subset won't
434 add in canonical order. */
435 for (itr = m_head; itr->next != NULL; itr = itr->next)
436 {
437 riscv_subset_t *next = itr->next;
438 int cmp = subset_cmp (s->name, next->name);
439 gcc_assert (cmp != 0);
440
441 if (cmp > 0)
442 {
443 s->next = next;
444 itr->next = s;
445 return;
446 }
447 }
448
449 /* Insert at tail of the list. */
450 itr->next = s;
451 m_tail = s;
452 }
453
454 static void
get_default_version(const char * ext,unsigned int * major_version,unsigned int * minor_version)455 get_default_version (const char *ext,
456 unsigned int *major_version,
457 unsigned int *minor_version)
458 {
459 const riscv_ext_version *ext_ver;
460 for (ext_ver = &riscv_ext_version_table[0];
461 ext_ver->name != NULL;
462 ++ext_ver)
463 if (strcmp (ext, ext_ver->name) == 0)
464 {
465 if ((ext_ver->isa_spec_class == riscv_isa_spec) ||
466 (ext_ver->isa_spec_class == ISA_SPEC_CLASS_NONE))
467 {
468 *major_version = ext_ver->major_version;
469 *minor_version = ext_ver->minor_version;
470 return;
471 }
472 }
473
474 /* Not found version info. */
475 *major_version = 0;
476 *minor_version = 0;
477 }
478
479 /* Add new subset to list, but using default version from ISA spec version. */
480
481 void
add(const char * subset,bool implied_p)482 riscv_subset_list::add (const char *subset, bool implied_p)
483 {
484 unsigned int major_version = 0, minor_version = 0;
485
486 get_default_version (subset, &major_version, &minor_version);
487
488 add (subset, major_version, minor_version, false, implied_p);
489 }
490
491 /* Convert subset info to string with explicit version info,
492 VERSION_P to determine append version info or not. */
493
494 std::string
to_string(bool version_p) const495 riscv_subset_list::to_string (bool version_p) const
496 {
497 std::ostringstream oss;
498 oss << "rv" << m_xlen;
499
500 bool first = true;
501 riscv_subset_t *subset;
502
503 bool skip_zifencei = false;
504 bool skip_zicsr = false;
505 bool i2p0 = false;
506
507 /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifencei is
508 included in the base ISA. */
509 if (riscv_isa_spec == ISA_SPEC_CLASS_2P2)
510 {
511 skip_zifencei = true;
512 skip_zicsr = true;
513 }
514
515 for (subset = m_head; subset != NULL; subset = subset->next)
516 if (subset->name == "i")
517 {
518 i2p0 = subset->major_version == 2 && subset->minor_version == 0;
519 break;
520 }
521
522 #ifndef HAVE_AS_MISA_SPEC
523 /* Skip since older binutils doesn't recognize zicsr. */
524 skip_zicsr = true;
525 #endif
526 #ifndef HAVE_AS_MARCH_ZIFENCEI
527 /* Skip since older binutils doesn't recognize zifencei, we made
528 a mistake in that binutils 2.35 supports zicsr but not zifencei. */
529 skip_zifencei = true;
530 #endif
531
532 for (subset = m_head; subset != NULL; subset = subset->next)
533 {
534 if (((subset->implied_p && skip_zifencei) || i2p0) &&
535 subset->name == "zifencei")
536 continue;
537
538 if (((subset->implied_p && skip_zicsr) || i2p0) &&
539 subset->name == "zicsr")
540 continue;
541
542 /* For !version_p, we only separate extension with underline for
543 multi-letter extension. */
544 if (!first &&
545 (version_p
546 || subset->explicit_version_p
547 || subset->name.length() > 1))
548 oss << '_';
549 first = false;
550
551 oss << subset->name;
552
553 /* Let binutils decide the extension version if we don't know. */
554 if ((version_p || subset->explicit_version_p) &&
555 (subset->major_version != 0 || subset->minor_version != 0))
556 oss << subset->major_version
557 << 'p'
558 << subset->minor_version;
559 }
560
561 return oss.str ();
562 }
563
564 /* Find subset in list with version checking, return NULL if not found.
565 major/minor version checking can be ignored if major_version/minor_version
566 is RISCV_DONT_CARE_VERSION. */
567
568 riscv_subset_t *
lookup(const char * subset,int major_version,int minor_version) const569 riscv_subset_list::lookup (const char *subset, int major_version,
570 int minor_version) const
571 {
572 riscv_subset_t *s;
573
574 for (s = m_head; s != NULL; s = s->next)
575 if (strcasecmp (s->name.c_str (), subset) == 0)
576 {
577 if ((major_version != RISCV_DONT_CARE_VERSION)
578 && (s->major_version != major_version))
579 return NULL;
580
581 if ((minor_version != RISCV_DONT_CARE_VERSION)
582 && (s->minor_version != minor_version))
583 return NULL;
584
585 return s;
586 }
587
588 return s;
589 }
590
591 /* Return string which contains all supported standard extensions in
592 canonical order. */
593
594 static const char *
riscv_supported_std_ext(void)595 riscv_supported_std_ext (void)
596 {
597 return "mafdqlcbjktpvn";
598 }
599
600 /* Parsing subset version.
601
602 Return Value:
603 Points to the end of version
604
605 Arguments:
606 `ext`: This extension.
607 `p`: Current parsing position.
608 `major_version`: Parsing result of major version, using
609 default_major_version if version is not present in arch string.
610 `minor_version`: Parsing result of minor version, set to 0 if version is
611 not present in arch string, but set to `default_minor_version` if
612 `major_version` using default_major_version.
613 `std_ext_p`: True if parsing std extension.
614 `explicit_version_p`: True if this subset is not using default version. */
615
616 const char *
parsing_subset_version(const char * ext,const char * p,unsigned * major_version,unsigned * minor_version,bool std_ext_p,bool * explicit_version_p)617 riscv_subset_list::parsing_subset_version (const char *ext,
618 const char *p,
619 unsigned *major_version,
620 unsigned *minor_version,
621 bool std_ext_p,
622 bool *explicit_version_p)
623 {
624 bool major_p = true;
625 unsigned version = 0;
626 unsigned major = 0;
627 unsigned minor = 0;
628 *explicit_version_p = false;
629
630 /* If we got `p`, that means we are still parsing standard extension. */
631 gcc_assert (std_ext_p || *p != 'p');
632
633 if (*p != 'p') {
634 for (; *p; ++p)
635 {
636 if (*p == 'p')
637 {
638 if (!ISDIGIT (*(p+1)))
639 {
640 error_at (m_loc, "%<-march=%s%>: expect number "
641 "after %<%dp%>", m_arch, version);
642 return NULL;
643 }
644 if (!major_p)
645 {
646 error_at (m_loc, "%<-march=%s%>: for %<%s%dp%dp?%>, version "
647 "number with more than 2 level is not supported",
648 m_arch, ext, major, version);
649 return NULL;
650 }
651 major = version;
652 major_p = false;
653 version = 0;
654 }
655 else if (ISDIGIT (*p))
656 version = (version * 10) + (*p - '0');
657 else
658 break;
659 }
660 }
661
662 if (major_p)
663 major = version;
664 else
665 minor = version;
666
667 if (major == 0 && minor == 0)
668 get_default_version (ext, major_version, minor_version);
669 else
670 {
671 *explicit_version_p = true;
672 *major_version = major;
673 *minor_version = minor;
674 }
675 return p;
676 }
677
678 /* Parsing function for standard extensions.
679
680 Return Value:
681 Points to the end of extensions.
682
683 Arguments:
684 `p`: Current parsing position. */
685
686 const char *
parse_std_ext(const char * p)687 riscv_subset_list::parse_std_ext (const char *p)
688 {
689 const char *all_std_exts = riscv_supported_std_ext ();
690 const char *std_exts = all_std_exts;
691
692 unsigned major_version = 0;
693 unsigned minor_version = 0;
694 char std_ext = '\0';
695 bool explicit_version_p = false;
696
697 /* First letter must start with i, e or g. */
698 switch (*p)
699 {
700 case 'i':
701 p++;
702 p = parsing_subset_version ("i", p, &major_version, &minor_version,
703 /* std_ext_p= */ true, &explicit_version_p);
704 add ("i", major_version, minor_version, explicit_version_p, false);
705 break;
706
707 case 'e':
708 p++;
709 p = parsing_subset_version ("e", p, &major_version, &minor_version,
710 /* std_ext_p= */ true, &explicit_version_p);
711
712 add ("e", major_version, minor_version, explicit_version_p, false);
713
714 if (m_xlen > 32)
715 {
716 error_at (m_loc, "%<-march=%s%>: rv%de is not a valid base ISA",
717 m_arch, m_xlen);
718 return NULL;
719 }
720 break;
721
722 case 'g':
723 p++;
724 p = parsing_subset_version ("g", p, &major_version, &minor_version,
725 /* std_ext_p= */ true, &explicit_version_p);
726 if (major_version != 0 || minor_version != 0)
727 {
728 warning_at (m_loc, 0, "version of %<g%> will be omitted, please "
729 "specify version for individual extension");
730 }
731
732 /* We have special rule for G, we disallow rv32gm2p but allow rv32g_zicsr
733 here, basically we treating G expand to imafd and implied zicsr and
734 zifencei. */
735
736 add ("i", false);
737 add ("m", false);
738 add ("a", false);
739 add ("f", false);
740 add ("d", false);
741 add ("zicsr", true);
742 add ("zifencei", true);
743
744 break;
745
746 default:
747 error_at (m_loc, "%<-march=%s%>: first ISA subset must be %<e%>, "
748 "%<i%> or %<g%>", m_arch);
749 return NULL;
750 }
751
752 while (p != NULL && *p)
753 {
754 char subset[2] = {0, 0};
755
756 if (*p == 'x' || *p == 's' || *p == 'h' || *p == 'z')
757 break;
758
759 if (*p == '_')
760 {
761 p++;
762 continue;
763 }
764
765 std_ext = *p;
766
767 /* Checking canonical order. */
768 while (*std_exts && std_ext != *std_exts)
769 std_exts++;
770
771 if (std_ext != *std_exts)
772 {
773 if (strchr (all_std_exts, std_ext) == NULL)
774 error_at (m_loc, "%<-march=%s%>: unsupported ISA subset %<%c%>",
775 m_arch, *p);
776 else
777 error_at (m_loc,
778 "%<-march=%s%>: ISA string is not in canonical order. "
779 "%<%c%>", m_arch, *p);
780 return NULL;
781 }
782
783 std_exts++;
784
785 p++;
786 subset[0] = std_ext;
787
788 p = parsing_subset_version (subset, p, &major_version, &minor_version,
789 /* std_ext_p= */ true, &explicit_version_p);
790
791 add (subset, major_version, minor_version, explicit_version_p, false);
792 }
793 return p;
794 }
795
796
797 /* Check any implied extensions for EXT. */
798 void
handle_implied_ext(riscv_subset_t * ext)799 riscv_subset_list::handle_implied_ext (riscv_subset_t *ext)
800 {
801 const riscv_implied_info_t *implied_info;
802 for (implied_info = &riscv_implied_info[0];
803 implied_info->ext;
804 ++implied_info)
805 {
806 if (strcmp (ext->name.c_str (), implied_info->ext) != 0)
807 continue;
808
809 /* Skip if implied extension already present. */
810 if (lookup (implied_info->implied_ext))
811 continue;
812
813 /* Version of implied extension will get from current ISA spec
814 version. */
815 add (implied_info->implied_ext, true);
816 }
817
818 /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifence is
819 included in the base ISA. */
820 if (riscv_isa_spec == ISA_SPEC_CLASS_2P2)
821 {
822 if (lookup ("zicsr") == NULL)
823 add ("zicsr", true);
824
825 if (lookup ("zifencei") == NULL)
826 add ("zifencei", true);
827 }
828 }
829
830 /* Check any combine extensions for EXT. */
831 void
handle_combine_ext()832 riscv_subset_list::handle_combine_ext ()
833 {
834 const riscv_ext_version *combine_info;
835 const riscv_implied_info_t *implied_info;
836 bool is_combined = false;
837
838 for (combine_info = &riscv_combine_info[0]; combine_info->name;
839 ++combine_info)
840 {
841 /* Skip if combine extensions are present */
842 if (lookup (combine_info->name))
843 continue;
844
845 /* Find all extensions of the combine extension */
846 for (implied_info = &riscv_implied_info[0]; implied_info->ext;
847 ++implied_info)
848 {
849 /* Skip if implied extension don't match combine extension */
850 if (strcmp (combine_info->name, implied_info->ext) != 0)
851 continue;
852
853 if (lookup (implied_info->implied_ext))
854 is_combined = true;
855 else
856 {
857 is_combined = false;
858 break;
859 }
860 }
861
862 /* Add combine extensions */
863 if (is_combined)
864 {
865 if (lookup (combine_info->name) == NULL)
866 {
867 add (combine_info->name, combine_info->major_version,
868 combine_info->minor_version, false, true);
869 }
870 }
871 }
872 }
873
874 /* Parsing function for multi-letter extensions.
875
876 Return Value:
877 Points to the end of extensions.
878
879 Arguments:
880 `p`: Current parsing position.
881 `ext_type`: What kind of extensions, 's', 'h', 'z' or 'x'.
882 `ext_type_str`: Full name for kind of extension. */
883
884 const char *
parse_multiletter_ext(const char * p,const char * ext_type,const char * ext_type_str)885 riscv_subset_list::parse_multiletter_ext (const char *p,
886 const char *ext_type,
887 const char *ext_type_str)
888 {
889 unsigned major_version = 0;
890 unsigned minor_version = 0;
891 size_t ext_type_len = strlen (ext_type);
892
893 while (*p)
894 {
895 if (*p == '_')
896 {
897 p++;
898 continue;
899 }
900
901 if (strncmp (p, ext_type, ext_type_len) != 0)
902 break;
903
904 char *subset = xstrdup (p);
905 char *q = subset;
906 const char *end_of_version;
907 bool explicit_version_p = false;
908 char *ext;
909 char backup;
910 size_t len;
911 size_t end_of_version_pos, i;
912 bool found_any_number = false;
913 bool found_minor_version = false;
914
915 /* Parse until end of this extension including version number. */
916 while (*++q != '\0' && *q != '_')
917 ;
918
919 backup = *q;
920 *q = '\0';
921 len = q - subset;
922 *q = backup;
923
924 end_of_version_pos = len;
925 /* Find the begin of version string. */
926 for (i = len -1; i > 0; --i)
927 {
928 if (ISDIGIT (subset[i]))
929 {
930 found_any_number = true;
931 continue;
932 }
933 /* Might be version seperator, but need to check one more char,
934 we only allow <major>p<minor>, so we could stop parsing if found
935 any more `p`. */
936 if (subset[i] == 'p' &&
937 !found_minor_version &&
938 found_any_number && ISDIGIT (subset[i-1]))
939 {
940 found_minor_version = true;
941 continue;
942 }
943
944 end_of_version_pos = i + 1;
945 break;
946 }
947
948 backup = subset[end_of_version_pos];
949 subset[end_of_version_pos] = '\0';
950 ext = xstrdup (subset);
951 subset[end_of_version_pos] = backup;
952
953 end_of_version
954 = parsing_subset_version (ext, subset + end_of_version_pos, &major_version, &minor_version,
955 /* std_ext_p= */ false, &explicit_version_p);
956 free (ext);
957
958 if (end_of_version == NULL)
959 return NULL;
960
961 subset[end_of_version_pos] = '\0';
962
963 if (strlen (subset) == 1)
964 {
965 error_at (m_loc, "%<-march=%s%>: name of %s must be more than 1 letter",
966 m_arch, ext_type_str);
967 free (subset);
968 return NULL;
969 }
970
971 add (subset, major_version, minor_version, explicit_version_p, false);
972 p += end_of_version - subset;
973 free (subset);
974
975 if (*p != '\0' && *p != '_')
976 {
977 error_at (m_loc, "%<-march=%s%>: %s must separate with %<_%>",
978 m_arch, ext_type_str);
979 return NULL;
980 }
981 }
982
983 return p;
984 }
985
986 /* Parsing arch string to subset list, return NULL if parsing failed. */
987
988 riscv_subset_list *
parse(const char * arch,location_t loc)989 riscv_subset_list::parse (const char *arch, location_t loc)
990 {
991 riscv_subset_list *subset_list = new riscv_subset_list (arch, loc);
992 riscv_subset_t *itr;
993 const char *p = arch;
994 if (startswith (p, "rv32"))
995 {
996 subset_list->m_xlen = 32;
997 p += 4;
998 }
999 else if (startswith (p, "rv64"))
1000 {
1001 subset_list->m_xlen = 64;
1002 p += 4;
1003 }
1004 else
1005 {
1006 error_at (loc, "%<-march=%s%>: ISA string must begin with rv32 or rv64",
1007 arch);
1008 goto fail;
1009 }
1010
1011 /* Parsing standard extension. */
1012 p = subset_list->parse_std_ext (p);
1013
1014 if (p == NULL)
1015 goto fail;
1016
1017 /* Parsing supervisor extension. */
1018 p = subset_list->parse_multiletter_ext (p, "s", "supervisor extension");
1019
1020 if (p == NULL)
1021 goto fail;
1022
1023 /* Parsing hypervisor extension. */
1024 p = subset_list->parse_multiletter_ext (p, "h", "hypervisor extension");
1025
1026 if (p == NULL)
1027 goto fail;
1028
1029 /* Parsing sub-extensions. */
1030 p = subset_list->parse_multiletter_ext (p, "z", "sub-extension");
1031
1032 if (p == NULL)
1033 goto fail;
1034
1035 /* Parsing non-standard extension. */
1036 p = subset_list->parse_multiletter_ext (p, "x", "non-standard extension");
1037
1038 if (p == NULL)
1039 goto fail;
1040
1041 if (*p != '\0')
1042 {
1043 error_at (loc, "%<-march=%s%>: unexpected ISA string at end: %qs",
1044 arch, p);
1045 goto fail;
1046 }
1047
1048 for (itr = subset_list->m_head; itr != NULL; itr = itr->next)
1049 {
1050 subset_list->handle_implied_ext (itr);
1051 }
1052
1053 subset_list->handle_combine_ext ();
1054
1055 return subset_list;
1056
1057 fail:
1058 delete subset_list;
1059 return NULL;
1060 }
1061
1062 /* Return the current arch string. */
1063
1064 std::string
riscv_arch_str(bool version_p)1065 riscv_arch_str (bool version_p)
1066 {
1067 if (current_subset_list)
1068 return current_subset_list->to_string (version_p);
1069 else
1070 return std::string();
1071 }
1072
1073 /* Type for pointer to member of gcc_options. */
1074 typedef int (gcc_options::*opt_var_ref_t);
1075
1076 /* Types for recording extension to internal flag. */
1077 struct riscv_ext_flag_table_t {
1078 const char *ext;
1079 opt_var_ref_t var_ref;
1080 int mask;
1081 };
1082
1083 /* Mapping table between extension to internal flag. */
1084 static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
1085 {
1086 {"e", &gcc_options::x_target_flags, MASK_RVE},
1087 {"m", &gcc_options::x_target_flags, MASK_MUL},
1088 {"a", &gcc_options::x_target_flags, MASK_ATOMIC},
1089 {"f", &gcc_options::x_target_flags, MASK_HARD_FLOAT},
1090 {"d", &gcc_options::x_target_flags, MASK_DOUBLE_FLOAT},
1091 {"c", &gcc_options::x_target_flags, MASK_RVC},
1092 {"v", &gcc_options::x_target_flags, MASK_VECTOR},
1093
1094 {"zicsr", &gcc_options::x_riscv_zi_subext, MASK_ZICSR},
1095 {"zifencei", &gcc_options::x_riscv_zi_subext, MASK_ZIFENCEI},
1096
1097 {"zba", &gcc_options::x_riscv_zb_subext, MASK_ZBA},
1098 {"zbb", &gcc_options::x_riscv_zb_subext, MASK_ZBB},
1099 {"zbc", &gcc_options::x_riscv_zb_subext, MASK_ZBC},
1100 {"zbs", &gcc_options::x_riscv_zb_subext, MASK_ZBS},
1101
1102 {"zbkb", &gcc_options::x_riscv_zk_subext, MASK_ZBKB},
1103 {"zbkc", &gcc_options::x_riscv_zk_subext, MASK_ZBKC},
1104 {"zbkx", &gcc_options::x_riscv_zk_subext, MASK_ZBKX},
1105 {"zknd", &gcc_options::x_riscv_zk_subext, MASK_ZKND},
1106 {"zkne", &gcc_options::x_riscv_zk_subext, MASK_ZKNE},
1107 {"zknh", &gcc_options::x_riscv_zk_subext, MASK_ZKNH},
1108 {"zkr", &gcc_options::x_riscv_zk_subext, MASK_ZKR},
1109 {"zksed", &gcc_options::x_riscv_zk_subext, MASK_ZKSED},
1110 {"zksh", &gcc_options::x_riscv_zk_subext, MASK_ZKSH},
1111 {"zkt", &gcc_options::x_riscv_zk_subext, MASK_ZKT},
1112
1113 {"zve32x", &gcc_options::x_target_flags, MASK_VECTOR},
1114 {"zve32f", &gcc_options::x_target_flags, MASK_VECTOR},
1115 {"zve64x", &gcc_options::x_target_flags, MASK_VECTOR},
1116 {"zve64f", &gcc_options::x_target_flags, MASK_VECTOR},
1117 {"zve64d", &gcc_options::x_target_flags, MASK_VECTOR},
1118
1119 /* We don't need to put complete ELEN/ELEN_FP info here, due to the
1120 implication relation of vector extension.
1121 e.g. v -> zve64d ... zve32x, so v has set MASK_VECTOR_ELEN_FP_64,
1122 MASK_VECTOR_ELEN_FP_32, MASK_VECTOR_ELEN_64 and MASK_VECTOR_ELEN_32
1123 due to the extension implication. */
1124 {"zve32x", &gcc_options::x_riscv_vector_elen_flags, MASK_VECTOR_ELEN_32},
1125 {"zve32f", &gcc_options::x_riscv_vector_elen_flags, MASK_VECTOR_ELEN_FP_32},
1126 {"zve64x", &gcc_options::x_riscv_vector_elen_flags, MASK_VECTOR_ELEN_64},
1127 {"zve64f", &gcc_options::x_riscv_vector_elen_flags, MASK_VECTOR_ELEN_FP_32},
1128 {"zve64d", &gcc_options::x_riscv_vector_elen_flags, MASK_VECTOR_ELEN_FP_64},
1129
1130 {"zvl32b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL32B},
1131 {"zvl64b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL64B},
1132 {"zvl128b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL128B},
1133 {"zvl256b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL256B},
1134 {"zvl512b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL512B},
1135 {"zvl1024b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL1024B},
1136 {"zvl2048b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL2048B},
1137 {"zvl4096b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL4096B},
1138 {"zvl8192b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL8192B},
1139 {"zvl16384b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL16384B},
1140 {"zvl32768b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL32768B},
1141 {"zvl65536b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL65536B},
1142
1143
1144 {NULL, NULL, 0}
1145 };
1146
1147 /* Parse a RISC-V ISA string into an option mask. Must clear or set all arch
1148 dependent mask bits, in case more than one -march string is passed. */
1149
1150 static void
riscv_parse_arch_string(const char * isa,struct gcc_options * opts,location_t loc)1151 riscv_parse_arch_string (const char *isa,
1152 struct gcc_options *opts,
1153 location_t loc)
1154 {
1155 riscv_subset_list *subset_list;
1156 subset_list = riscv_subset_list::parse (isa, loc);
1157 if (!subset_list)
1158 return;
1159
1160 if (opts)
1161 {
1162 const riscv_ext_flag_table_t *arch_ext_flag_tab;
1163 /* Clean up target flags before we set. */
1164 for (arch_ext_flag_tab = &riscv_ext_flag_table[0];
1165 arch_ext_flag_tab->ext;
1166 ++arch_ext_flag_tab)
1167 opts->*arch_ext_flag_tab->var_ref &= ~arch_ext_flag_tab->mask;
1168
1169 if (subset_list->xlen () == 32)
1170 opts->x_target_flags &= ~MASK_64BIT;
1171 else if (subset_list->xlen () == 64)
1172 opts->x_target_flags |= MASK_64BIT;
1173
1174
1175 for (arch_ext_flag_tab = &riscv_ext_flag_table[0];
1176 arch_ext_flag_tab->ext;
1177 ++arch_ext_flag_tab)
1178 {
1179 if (subset_list->lookup (arch_ext_flag_tab->ext))
1180 opts->*arch_ext_flag_tab->var_ref |= arch_ext_flag_tab->mask;
1181 }
1182 }
1183
1184 if (current_subset_list)
1185 delete current_subset_list;
1186
1187 current_subset_list = subset_list;
1188 }
1189
1190 /* Return the riscv_cpu_info entry for CPU, NULL if not found. */
1191
1192 const riscv_cpu_info *
riscv_find_cpu(const char * cpu)1193 riscv_find_cpu (const char *cpu)
1194 {
1195 const riscv_cpu_info *cpu_info = &riscv_cpu_tables[0];
1196 for (;cpu_info->name != NULL; ++cpu_info)
1197 {
1198 const char *name = cpu_info->name;
1199 if (strcmp (cpu, name) == 0)
1200 return cpu_info;
1201 }
1202 return NULL;
1203 }
1204
1205 /* Implement TARGET_HANDLE_OPTION. */
1206
1207 static bool
riscv_handle_option(struct gcc_options * opts,struct gcc_options * opts_set ATTRIBUTE_UNUSED,const struct cl_decoded_option * decoded,location_t loc)1208 riscv_handle_option (struct gcc_options *opts,
1209 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
1210 const struct cl_decoded_option *decoded,
1211 location_t loc)
1212 {
1213 switch (decoded->opt_index)
1214 {
1215 case OPT_march_:
1216 riscv_parse_arch_string (decoded->arg, opts, loc);
1217 return true;
1218
1219 case OPT_mcpu_:
1220 if (riscv_find_cpu (decoded->arg) == NULL)
1221 error_at (loc, "%<-mcpu=%s%>: unknown CPU",
1222 decoded->arg);
1223 return true;
1224
1225 default:
1226 return true;
1227 }
1228 }
1229
1230 /* Expand arch string with implied extensions. */
1231
1232 const char *
riscv_expand_arch(int argc ATTRIBUTE_UNUSED,const char ** argv)1233 riscv_expand_arch (int argc ATTRIBUTE_UNUSED,
1234 const char **argv)
1235 {
1236 gcc_assert (argc == 1);
1237 location_t loc = UNKNOWN_LOCATION;
1238 riscv_parse_arch_string (argv[0], NULL, loc);
1239 const std::string arch = riscv_arch_str (false);
1240 if (arch.length())
1241 return xasprintf ("-march=%s", arch.c_str());
1242 else
1243 return "";
1244 }
1245
1246 /* Expand default -mtune option from -mcpu option, use default --with-tune value
1247 if -mcpu don't have valid value. */
1248
1249 const char *
riscv_default_mtune(int argc,const char ** argv)1250 riscv_default_mtune (int argc, const char **argv)
1251 {
1252 gcc_assert (argc == 2);
1253 const riscv_cpu_info *cpu = riscv_find_cpu (argv[0]);
1254 const char *default_mtune = argv[1];
1255 if (cpu)
1256 return cpu->tune;
1257 else
1258 return default_mtune;
1259 }
1260
1261 /* Expand arch string with implied extensions from -mcpu option. */
1262
1263 const char *
riscv_expand_arch_from_cpu(int argc ATTRIBUTE_UNUSED,const char ** argv)1264 riscv_expand_arch_from_cpu (int argc ATTRIBUTE_UNUSED,
1265 const char **argv)
1266 {
1267 gcc_assert (argc > 0 && argc <= 2);
1268 const char *default_arch_str = NULL;
1269 const char *arch_str = NULL;
1270 if (argc >= 2)
1271 default_arch_str = argv[1];
1272
1273 const riscv_cpu_info *cpu = riscv_find_cpu (argv[0]);
1274
1275 if (cpu == NULL)
1276 {
1277 if (default_arch_str == NULL)
1278 return "";
1279 else
1280 arch_str = default_arch_str;
1281 }
1282 else
1283 arch_str = cpu->arch;
1284
1285 location_t loc = UNKNOWN_LOCATION;
1286
1287 riscv_parse_arch_string (arch_str, NULL, loc);
1288 const std::string arch = riscv_arch_str (false);
1289 return xasprintf ("-march=%s", arch.c_str());
1290 }
1291
1292
1293 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
1294 static const struct default_options riscv_option_optimization_table[] =
1295 {
1296 { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 },
1297 { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 },
1298 { OPT_LEVELS_NONE, 0, NULL, 0 }
1299 };
1300
1301 #undef TARGET_OPTION_OPTIMIZATION_TABLE
1302 #define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table
1303
1304 #undef TARGET_HANDLE_OPTION
1305 #define TARGET_HANDLE_OPTION riscv_handle_option
1306
1307 struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
1308