1 /* Common hooks for RISC-V.
2 Copyright (C) 2016-2019 Free Software Foundation, Inc.
4 This file is part of GCC.
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)
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.
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/>. */
22 #define INCLUDE_STRING
25 #include "coretypes.h"
27 #include "common/common-target.h"
28 #include "common/common-target-def.h"
31 #include "diagnostic-core.h"
32 #include "config/riscv/riscv-protos.h"
34 #define RISCV_DONT_CARE_VERSION -1
44 struct riscv_subset_t
*next
;
48 class riscv_subset_list
51 /* Original arch string. */
54 /* Location of arch string, used for report error. */
57 /* Head of subset info list. */
58 riscv_subset_t
*m_head
;
60 /* Tail of subset info list. */
61 riscv_subset_t
*m_tail
;
63 /* X-len of m_arch. */
66 riscv_subset_list (const char *, location_t
);
68 const char *parsing_subset_version (const char *, unsigned *, unsigned *,
69 unsigned, unsigned, bool);
71 const char *parse_std_ext (const char *);
73 const char *parse_sv_or_non_std_ext (const char *, const char *,
77 ~riscv_subset_list ();
79 void add (const char *, int, int);
81 riscv_subset_t
*lookup (const char *,
82 int major_version
= RISCV_DONT_CARE_VERSION
,
83 int minor_version
= RISCV_DONT_CARE_VERSION
) const;
85 std::string
to_string () const;
87 unsigned xlen() const {return m_xlen
;};
89 static riscv_subset_list
*parse (const char *, location_t
);
93 static const char *riscv_supported_std_ext (void);
95 static riscv_subset_list
*current_subset_list
= NULL
;
97 riscv_subset_t::riscv_subset_t ()
98 : name (), major_version (0), minor_version (0), next (NULL
)
102 riscv_subset_list::riscv_subset_list (const char *arch
, location_t loc
)
103 : m_arch (arch
), m_loc (loc
), m_head (NULL
), m_tail (NULL
), m_xlen (0)
107 riscv_subset_list::~riscv_subset_list ()
112 riscv_subset_t
*item
= this->m_head
;
115 riscv_subset_t
*next
= item
->next
;
121 /* Add new subset to list. */
124 riscv_subset_list::add (const char *subset
, int major_version
,
127 riscv_subset_t
*s
= new riscv_subset_t ();
133 s
->major_version
= major_version
;
134 s
->minor_version
= minor_version
;
143 /* Convert subset info to string with explicit version info. */
146 riscv_subset_list::to_string () const
148 std::ostringstream oss
;
149 oss
<< "rv" << m_xlen
;
152 riscv_subset_t
*subset
= m_head
;
154 while (subset
!= NULL
)
161 << subset
->major_version
163 << subset
->minor_version
;
164 subset
= subset
->next
;
170 /* Find subset in list with version checking, return NULL if not found.
171 major/minor version checking can be ignored if major_version/minor_version
172 is RISCV_DONT_CARE_VERSION. */
175 riscv_subset_list::lookup (const char *subset
, int major_version
,
176 int minor_version
) const
180 for (s
= m_head
; s
!= NULL
; s
= s
->next
)
181 if (strcasecmp (s
->name
.c_str (), subset
) == 0)
183 if ((major_version
!= RISCV_DONT_CARE_VERSION
)
184 && (s
->major_version
!= major_version
))
187 if ((minor_version
!= RISCV_DONT_CARE_VERSION
)
188 && (s
->minor_version
!= minor_version
))
197 /* Return string which contains all supported standard extensions in
201 riscv_supported_std_ext (void)
203 return "mafdqlcbjtpvn";
206 /* Parsing subset version.
209 Points to the end of version
212 `p`: Current parsing position.
213 `major_version`: Parsing result of major version, using
214 default_major_version if version is not present in arch string.
215 `minor_version`: Parsing result of minor version, set to 0 if version is
216 not present in arch string, but set to `default_minor_version` if
217 `major_version` using default_major_version.
218 `default_major_version`: Default major version.
219 `default_minor_version`: Default minor version.
220 `std_ext_p`: True if parsing std extension. */
223 riscv_subset_list::parsing_subset_version (const char *p
,
224 unsigned *major_version
,
225 unsigned *minor_version
,
226 unsigned default_major_version
,
227 unsigned default_minor_version
,
231 unsigned version
= 0;
244 /* Might be beginning of `p` extension. */
247 *major_version
= version
;
253 error_at (m_loc
, "%<-march=%s%>: Expect number after `%dp'.",
263 else if (ISDIGIT (*p
))
264 version
= (version
* 10) + (*p
- '0');
274 if (major
== 0 && minor
== 0)
276 /* We didn't find any version string, use default version. */
277 *major_version
= default_major_version
;
278 *minor_version
= default_minor_version
;
282 *major_version
= major
;
283 *minor_version
= minor
;
288 /* Parsing function for standard extensions.
291 Points to the end of extensions.
294 `p`: Current parsing position. */
297 riscv_subset_list::parse_std_ext (const char *p
)
299 const char *all_std_exts
= riscv_supported_std_ext ();
300 const char *std_exts
= all_std_exts
;
302 unsigned major_version
= 0;
303 unsigned minor_version
= 0;
306 /* First letter must start with i, e or g. */
311 p
= parsing_subset_version (p
, &major_version
, &minor_version
,
312 /* default_major_version= */ 2,
313 /* default_minor_version= */ 0,
314 /* std_ext_p= */ true);
315 add ("i", major_version
, minor_version
);
320 p
= parsing_subset_version (p
, &major_version
, &minor_version
,
321 /* default_major_version= */ 1,
322 /* default_minor_version= */ 9,
323 /* std_ext_p= */ true);
325 add ("e", major_version
, minor_version
);
329 error_at (m_loc
, "%<-march=%s%>: rv%de is not a valid base ISA",
337 p
= parsing_subset_version (p
, &major_version
, &minor_version
,
338 /* default_major_version= */ 2,
339 /* default_minor_version= */ 0,
340 /* std_ext_p= */ true);
341 add ("i", major_version
, minor_version
);
343 for (; *std_exts
!= 'q'; std_exts
++)
345 const char subset
[] = {*std_exts
, '\0'};
346 add (subset
, major_version
, minor_version
);
351 error_at (m_loc
, "%<-march=%s%>: first ISA subset must be `e', "
352 "`i' or `g'", m_arch
);
358 char subset
[2] = {0, 0};
360 if (*p
== 'x' || *p
== 's')
371 /* Checking canonical order. */
372 while (*std_exts
&& std_ext
!= *std_exts
)
375 if (std_ext
!= *std_exts
)
377 if (strchr (all_std_exts
, std_ext
) == NULL
)
378 error_at (m_loc
, "%<-march=%s%>: unsupported ISA subset `%c'",
382 "%<-march=%s%>: ISA string is not in canonical order. "
390 p
= parsing_subset_version (p
, &major_version
, &minor_version
,
391 /* default_major_version= */ 2,
392 /* default_minor_version= */ 0,
393 /* std_ext_p= */ true);
397 add (subset
, major_version
, minor_version
);
402 /* Parsing function for non-standard and supervisor extensions.
405 Points to the end of extensions.
408 `p`: Current parsing position.
409 `ext_type`: What kind of extensions, 'x', 's' or 'sx'.
410 `ext_type_str`: Full name for kind of extension. */
413 riscv_subset_list::parse_sv_or_non_std_ext (const char *p
,
414 const char *ext_type
,
415 const char *ext_type_str
)
417 unsigned major_version
= 0;
418 unsigned minor_version
= 0;
419 size_t ext_type_len
= strlen (ext_type
);
429 if (strncmp (p
, ext_type
, ext_type_len
) != 0)
432 /* It's non-standard supervisor extension if it prefix with sx. */
433 if ((ext_type
[0] == 's') && (ext_type_len
== 1)
434 && (*(p
+ 1) == 'x'))
437 char *subset
= xstrdup (p
);
439 const char *end_of_version
;
441 while (*++q
!= '\0' && *q
!= '_' && !ISDIGIT (*q
))
445 = parsing_subset_version (q
, &major_version
, &minor_version
,
446 /* default_major_version= */ 2,
447 /* default_minor_version= */ 0,
448 /* std_ext_p= */ FALSE
);
452 add (subset
, major_version
, minor_version
);
454 p
+= end_of_version
- subset
;
456 if (*p
!= '\0' && *p
!= '_')
458 error_at (m_loc
, "%<-march=%s%>: %s must separate with _",
459 m_arch
, ext_type_str
);
467 /* Parsing arch string to subset list, return NULL if parsing failed. */
470 riscv_subset_list::parse (const char *arch
, location_t loc
)
472 riscv_subset_list
*subset_list
= new riscv_subset_list (arch
, loc
);
473 const char *p
= arch
;
474 if (strncmp (p
, "rv32", 4) == 0)
476 subset_list
->m_xlen
= 32;
479 else if (strncmp (p
, "rv64", 4) == 0)
481 subset_list
->m_xlen
= 64;
486 error_at (loc
, "%<-march=%s%>: ISA string must begin with rv32 or rv64",
491 /* Parsing standard extension. */
492 p
= subset_list
->parse_std_ext (p
);
497 /* Parsing non-standard extension. */
498 p
= subset_list
->parse_sv_or_non_std_ext (p
, "x", "non-standard extension");
503 /* Parsing supervisor extension. */
504 p
= subset_list
->parse_sv_or_non_std_ext (p
, "s", "supervisor extension");
509 /* Parsing non-standard supervisor extension. */
510 p
= subset_list
->parse_sv_or_non_std_ext
511 (p
, "sx", "non-standard supervisor extension");
523 /* Return the current arch string. */
528 gcc_assert (current_subset_list
);
529 return current_subset_list
->to_string ();
532 /* Parse a RISC-V ISA string into an option mask. Must clear or set all arch
533 dependent mask bits, in case more than one -march string is passed. */
536 riscv_parse_arch_string (const char *isa
, int *flags
, location_t loc
)
538 riscv_subset_list
*subset_list
;
539 subset_list
= riscv_subset_list::parse (isa
, loc
);
543 if (subset_list
->xlen () == 32)
544 *flags
&= ~MASK_64BIT
;
545 else if (subset_list
->xlen () == 64)
546 *flags
|= MASK_64BIT
;
549 if (subset_list
->lookup ("e"))
553 if (subset_list
->lookup ("m"))
556 *flags
&= ~MASK_ATOMIC
;
557 if (subset_list
->lookup ("a"))
558 *flags
|= MASK_ATOMIC
;
560 *flags
&= ~(MASK_HARD_FLOAT
| MASK_DOUBLE_FLOAT
);
561 if (subset_list
->lookup ("f"))
562 *flags
|= MASK_HARD_FLOAT
;
564 if (subset_list
->lookup ("d"))
565 *flags
|= MASK_DOUBLE_FLOAT
;
567 if (current_subset_list
)
568 delete current_subset_list
;
570 current_subset_list
= subset_list
;
573 /* Implement TARGET_HANDLE_OPTION. */
576 riscv_handle_option (struct gcc_options
*opts
,
577 struct gcc_options
*opts_set ATTRIBUTE_UNUSED
,
578 const struct cl_decoded_option
*decoded
,
581 switch (decoded
->opt_index
)
584 riscv_parse_arch_string (decoded
->arg
, &opts
->x_target_flags
, loc
);
592 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
593 static const struct default_options riscv_option_optimization_table
[] =
595 { OPT_LEVELS_1_PLUS
, OPT_fsection_anchors
, NULL
, 1 },
596 { OPT_LEVELS_2_PLUS
, OPT_free
, NULL
, 1 },
597 { OPT_LEVELS_NONE
, 0, NULL
, 0 }
600 #undef TARGET_OPTION_OPTIMIZATION_TABLE
601 #define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table
603 #undef TARGET_HANDLE_OPTION
604 #define TARGET_HANDLE_OPTION riscv_handle_option
606 struct gcc_targetm_common targetm_common
= TARGETM_COMMON_INITIALIZER
;