[PATCH 14/19] RISC-V: error handling for subset parsing

Jiawei jiawei@iscas.ac.cn
Wed Apr 29 12:27:33 GMT 2026


> The parsing of both the argument of -march= and the operand(s) of
> ".option arch, ..." can fail. In such a case for .option (and equally
> for .attribute) prior state should continue to be used, while for -march=
> defaults should be put in place. In particular, extensions conflicting
> with previously enabled extensions should not suddenly become available.
>
The temporary-subset approach in riscv_update_subset() looks right to me.
For .option arch and .attribute parsing failures, keeping the previous ISA
state is safer than leaving the current subset list partially updated.

>
> While re-indenting riscv_set_rvc() invocations, leverage that C implies
> Zca (and hence a check for the latter suffices). Mirror that change to
> riscv_set_arch() for consistency.
>
Since C always implies Zca, checking for Zca is better, and it also 
naturally

covers explicit Zca use without requiring the C extension

(May other Zc* extensions).

> --- a/bfd/elfxx-riscv.c
> +++ b/bfd/elfxx-riscv.c
> @@ -2768,7 +2768,28 @@ bool
>  riscv_update_subset (riscv_parse_subset_t *rps,
>               const char *str)
>  {
> -  return riscv_update_subset1 (rps, NULL, str);
> +  unsigned int newxlen = *rps->xlen;
> +  riscv_parse_subset_t newrps = {
> +    .subset_list = riscv_copy_subset_list (rps->subset_list),
> +    .error_handler = rps->error_handler,
> +    .xlen = &newxlen,
> +    .isa_spec = rps->isa_spec,
> +    .check_unknown_prefixed_ext = rps->check_unknown_prefixed_ext,
> +  };
> +
> +  if (!riscv_update_subset1 (&newrps, NULL, str))
> +    {
> +      riscv_release_subset_list (newrps.subset_list);
> +      free (newrps.subset_list);
> +      return false;
> +    }
> +
> +  *rps->xlen = newxlen;
> +  riscv_release_subset_list (rps->subset_list);
> +  *rps->subset_list = *newrps.subset_list;
> +  free (newrps.subset_list);
> +
> +  return true;
>  }
>
>  /* Called from .option norvc directives.  */
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -350,20 +350,38 @@ riscv_set_arch (const char *s)
>        s = DEFAULT_RISCV_ARCH_WITH_EXT;
>      }
>
> -  if (riscv_rps_as.subset_list == NULL)
> +  unsigned int newxlen = xlen;
> +  riscv_parse_subset_t newrps = {
> +    .subset_list = XCNEW (riscv_subset_list_t),
> +    .error_handler = as_bad,
> +    .xlen = &newxlen,
> +    .isa_spec = &default_isa_spec,
> +    .check_unknown_prefixed_ext = true,
> +  };
> +
> +  if (!riscv_parse_subset (&newrps, s))
>      {
> -      riscv_rps_as.subset_list = XNEW (riscv_subset_list_t);
> -      riscv_rps_as.subset_list->head = NULL;
> -      riscv_rps_as.subset_list->tail = NULL;
> -      riscv_rps_as.subset_list->arch_str = NULL;
> +      riscv_release_subset_list (newrps.subset_list);
> +      if (file_arch_str != NULL)
> +    {
> +      free (newrps.subset_list);
> +      return;
> +    }
> +      if (!riscv_parse_subset (&newrps, DEFAULT_RISCV_ARCH_WITH_EXT))
> +    abort ();
>      }
> -  riscv_release_subset_list (riscv_rps_as.subset_list);
> -  riscv_parse_subset (&riscv_rps_as, s);
> +  xlen = newxlen;
> +  if (riscv_rps_as.subset_list != NULL)
> +    {
> +      riscv_release_subset_list (riscv_rps_as.subset_list);
> +      free (riscv_rps_as.subset_list);
> +    }
> +  riscv_rps_as.subset_list = newrps.subset_list;
> +
>    riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */);
>    file_arch_str = xstrdup (riscv_rps_as.subset_list->arch_str);
>
> -  riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "c")
> -         || riscv_subset_supports (&riscv_rps_as, "zca"));
> +  riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "zca"));
>
>    if (riscv_subset_supports (&riscv_rps_as, "ztso"))
>      riscv_set_tso ();
> @@ -5077,13 +5095,16 @@ s_riscv_option (int x ATTRIBUTE_UNUSED)
>
>    if (strcmp (name, "rvc") == 0)
>      {
> -      riscv_update_subset (&riscv_rps_as, "+c");
> -      riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */);
> -      riscv_set_rvc (true);
> +      if (riscv_update_subset (&riscv_rps_as, "+c"))
> +    {
> +      riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */);
> +      riscv_set_rvc (true);
> +    }
>      }
>    else if (strcmp (name, "norvc") == 0)
>      {
> -      riscv_update_subset_norvc (&riscv_rps_as);
> +      if (!riscv_update_subset_norvc (&riscv_rps_as))
> +    abort ();
>        riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */);
>        riscv_set_rvc (false);
>      }
> @@ -5104,14 +5125,15 @@ s_riscv_option (int x ATTRIBUTE_UNUSED)
>        name += 5;
>        if (is_whitespace (*name) && *name != '\0')
>      name++;
> -      riscv_update_subset (&riscv_rps_as, name);
> -      riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */);
> +      if (riscv_update_subset (&riscv_rps_as, name))
> +    {
> +      riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */);
>
> -      riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "c")
> -             || riscv_subset_supports (&riscv_rps_as, "zca"));
> +      riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "zca"));
>
> -      if (riscv_subset_supports (&riscv_rps_as, "ztso"))
> -    riscv_set_tso ();
> +      if (riscv_subset_supports (&riscv_rps_as, "ztso"))
> +        riscv_set_tso ();
> +    }
>      }
>    else if (strcmp (name, "push") == 0)
>      {
> --- a/gas/testsuite/gas/riscv/x-thead-vector-fail.d
> +++ b/gas/testsuite/gas/riscv/x-thead-vector-fail.d
> @@ -1,3 +1,3 @@
>  #as: -march=rv64gc_zve32x_xtheadvector
> -#source: x-thead-vector.s
> +#source: empty.s
>  #error_output: x-thead-vector-fail.l
>
Reviewed-by: Jiawei <jiawei@iscas.ac.cn>



More information about the Binutils mailing list