xref: /netbsd-src/external/gpl3/gcc/dist/gcc/common/config/riscv/riscv-common.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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