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