The output of -march=help is like below:

```
All available -march extensions for RISC-V:
        Name                Version
        i                       2.0, 2.1
        e                       2.0
        m                       2.0
        a                       2.0, 2.1
        f                       2.0, 2.2
        d                       2.0, 2.2
...
```

Also support -print-supported-extensions and --print-supported-extensions for
clang compatibility.

gcc/ChangeLog:

        PR target/109349

        * common/config/riscv/riscv-common.cc (riscv_arch_help): New.
        * config/riscv/riscv-protos.h (RISCV_MAJOR_VERSION_BASE): New.
        (RISCV_MINOR_VERSION_BASE): Ditto.
        (RISCV_REVISION_VERSION_BASE): Ditto.
        * config/riscv/riscv-c.cc (riscv_ext_version_value): Use enum
        rather than magic number.
        * config/riscv/riscv.h (riscv_arch_help): New.
        (EXTRA_SPEC_FUNCTIONS): Add riscv_arch_help.
        (DRIVER_SELF_SPECS): Handle -march=help, -print-supported-extensions and
        --print-supported-extensions.
        * config/riscv/riscv.opt (march=help): New.
        (print-supported-extensions): New.
        (-print-supported-extensions): New.
        * doc/invoke.texi (RISC-V Options): Document -march=help.
---
 gcc/common/config/riscv/riscv-common.cc | 46 +++++++++++++++++++++++++
 gcc/config/riscv/riscv-c.cc             |  2 +-
 gcc/config/riscv/riscv-protos.h         |  7 ++++
 gcc/config/riscv/riscv.h                |  7 +++-
 gcc/config/riscv/riscv.opt              | 12 +++++++
 gcc/doc/invoke.texi                     |  3 +-
 6 files changed, 74 insertions(+), 3 deletions(-)

diff --git a/gcc/common/config/riscv/riscv-common.cc 
b/gcc/common/config/riscv/riscv-common.cc
index 631ce8309a0..8974fa4a128 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #include <vector>
 
 #define INCLUDE_STRING
+#define INCLUDE_SET
+#define INCLUDE_MAP
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -2225,6 +2227,50 @@ riscv_get_valid_option_values (int option_code,
   return v;
 }
 
+const char *
+riscv_arch_help (int argc, const char **argv)
+{
+  /* Collect all exts, and sort it in canonical order.  */
+  struct extension_comparator {
+    bool operator()(const std::string& a, const std::string& b) const {
+      return subset_cmp(a, b) >= 1;
+    }
+  };
+  std::map<std::string, std::set<unsigned>, extension_comparator> all_exts;
+  for (const riscv_ext_version &ext : riscv_ext_version_table)
+    {
+      if (!ext.name)
+       break;
+      if (ext.name[0] == 'g')
+       continue;
+      unsigned version_value = (ext.major_version * RISCV_MAJOR_VERSION_BASE)
+                               + (ext.minor_version
+                                  * RISCV_MINOR_VERSION_BASE);
+      all_exts[ext.name].insert(version_value);
+    }
+
+  printf("All available -march extensions for RISC-V:\n");
+  printf("\t%-20sVersion\n", "Name");
+  for (auto const &ext_info : all_exts)
+    {
+      printf("\t%-20s\t", ext_info.first.c_str());
+      bool first = true;
+      for (auto version : ext_info.second)
+       {
+         if (first)
+           first = false;
+         else
+           printf(", ");
+         unsigned major = version / RISCV_MAJOR_VERSION_BASE;
+         unsigned minor = (version % RISCV_MAJOR_VERSION_BASE)
+                           / RISCV_MINOR_VERSION_BASE;
+         printf("%u.%u", major, minor);
+       }
+      printf("\n");
+    }
+  exit (0);
+}
+
 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
 static const struct default_options riscv_option_optimization_table[] =
   {
diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index 94c3871c760..3ef06dcfd2d 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -37,7 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 static int
 riscv_ext_version_value (unsigned major, unsigned minor)
 {
-  return (major * 1000000) + (minor * 1000);
+  return (major * RISCV_MAJOR_VERSION_BASE) + (minor * 
RISCV_MINOR_VERSION_BASE);
 }
 
 /* Implement TARGET_CPU_CPP_BUILTINS.  */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index ae1685850ac..80efdf2b7e5 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -780,4 +780,11 @@ const struct riscv_tune_info *
 riscv_parse_tune (const char *, bool);
 const cpu_vector_cost *get_vector_costs ();
 
+enum
+{
+  RISCV_MAJOR_VERSION_BASE = 1000000,
+  RISCV_MINOR_VERSION_BASE = 1000,
+  RISCV_REVISION_VERSION_BASE = 1,
+};
+
 #endif /* ! GCC_RISCV_PROTOS_H */
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 669308cc96d..da089a03e9d 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -50,12 +50,14 @@ extern const char *riscv_expand_arch (int argc, const char 
**argv);
 extern const char *riscv_expand_arch_from_cpu (int argc, const char **argv);
 extern const char *riscv_default_mtune (int argc, const char **argv);
 extern const char *riscv_multi_lib_check (int argc, const char **argv);
+extern const char *riscv_arch_help (int argc, const char **argv);
 
 # define EXTRA_SPEC_FUNCTIONS                                          \
   { "riscv_expand_arch", riscv_expand_arch },                          \
   { "riscv_expand_arch_from_cpu", riscv_expand_arch_from_cpu },                
\
   { "riscv_default_mtune", riscv_default_mtune },                      \
-  { "riscv_multi_lib_check", riscv_multi_lib_check },
+  { "riscv_multi_lib_check", riscv_multi_lib_check },                  \
+  { "riscv_arch_help", riscv_arch_help },
 
 /* Support for a compile-time default CPU, et cetera.  The rules are:
    --with-arch is ignored if -march or -mcpu is specified.
@@ -109,6 +111,9 @@ ASM_MISA_SPEC
 
 #undef DRIVER_SELF_SPECS
 #define DRIVER_SELF_SPECS                                      \
+"%{march=help:%:riscv_arch_help()} "                           \
+"%{print-supported-extensions:%:riscv_arch_help()} "           \
+"%{-print-supported-extensions:%:riscv_arch_help()} "          \
 "%{march=*:%:riscv_expand_arch(%*)} "                          \
 "%{!march=*:%{mcpu=*:%:riscv_expand_arch_from_cpu(%*)}} "
 
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index f6ff70b2b30..20685c42aed 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -86,6 +86,18 @@ Target RejectNegative Joined Negative(march=)
 -march=        Generate code for given RISC-V ISA (e.g. RV64IM).  ISA strings 
must be
 lower-case.
 
+march=help
+Target RejectNegative
+-march=help    Print supported -march extensions.
+
+; -print-supported-extensions and --print-supported-extensions are added for
+; clang compatibility.
+print-supported-extensions
+Target Undocumented RejectNegative Alias(march=help)
+
+-print-supported-extensions
+Target Undocumented RejectNegative Alias(march=help)
+
 mtune=
 Target RejectNegative Joined Var(riscv_tune_string) Save
 -mtune=PROCESSOR       Optimize the output for PROCESSOR.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0de184f6241..1c5423a2a66 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -30204,7 +30204,8 @@ with @option{--with-isa-spec=} specifying a different 
default version.
 @item -march=@var{ISA-string}
 Generate code for given RISC-V ISA (e.g.@: @samp{rv64im}).  ISA strings must be
 lower-case.  Examples include @samp{rv64i}, @samp{rv32g}, @samp{rv32e}, and
-@samp{rv32imaf}.
+@samp{rv32imaf}. Additionally, a special value @option{help}
+(@option{-march=help}) is accepted to list all supported extensions.
 
 The syntax of the ISA string is defined as follows:
 
-- 
2.34.1

Reply via email to