Define a new riscv_ext_info_t struct to aggregate all ISA extension fields
(name, version, flags, implied extensions, bitmask and extra flags) generated
from riscv-ext.def.

Also adjust riscv_ext_flag_table_t and riscv_implied_info_t to make it
able to not hold extension name, this part will refactor in later
patchs.

gcc/ChangeLog:

        * common/config/riscv/riscv-common.cc (riscv_ext_info_t): New
        struct.
        (opt_var_ref_t): Adjust order.
        (cl_opt_var_ref_t): Ditto.
        (riscv_ext_flag_table_t): Adjust order, and add a new construct
        that not hold the extension name.
        (riscv_version_t): New struct.
        (riscv_implied_info_t): Adjust order, and add a new construct that not
        hold the extension name.
        (apply_extra_extension_flags): New function.
        (riscv_ext_infos): New.
        (riscv_implied_info): Adjust.
        * config/riscv/riscv-opts.h (EXT_FLAG_MACRO): New macro.
        (BITMASK_NOT_YET_ALLOCATED): New macro.
---
 gcc/common/config/riscv/riscv-common.cc | 191 ++++++++++++++++++++++--
 gcc/config/riscv/riscv-opts.h           |   8 +
 2 files changed, 185 insertions(+), 14 deletions(-)

diff --git a/gcc/common/config/riscv/riscv-common.cc 
b/gcc/common/config/riscv/riscv-common.cc
index 5a091e3987b1..72d5d8181d16 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include <sstream>
 #include <vector>
+#include <unordered_map>
 #include <queue>
 
 #define INCLUDE_STRING
@@ -41,11 +42,62 @@ along with GCC; see the file COPYING3.  If not see
 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_ENDIAN)
 #endif
 
+/* Type for pointer to member of gcc_options and cl_target_option.  */
+typedef int (gcc_options::*opt_var_ref_t);
+typedef int (cl_target_option::*cl_opt_var_ref_t);
+
+/* Types for recording extension to internal flag.  */
+struct riscv_ext_flag_table_t
+{
+  riscv_ext_flag_table_t (const char *ext, opt_var_ref_t var_ref,
+                         cl_opt_var_ref_t cl_var_ref, int mask)
+       : ext (ext), var_ref (var_ref), cl_var_ref (cl_var_ref), mask (mask)
+  {}
+  riscv_ext_flag_table_t (opt_var_ref_t var_ref,
+                         cl_opt_var_ref_t cl_var_ref, int mask)
+       : ext (nullptr), var_ref (var_ref), cl_var_ref (cl_var_ref), mask (mask)
+  {}
+
+  const char *ext;
+  opt_var_ref_t var_ref;
+  cl_opt_var_ref_t cl_var_ref;
+  int mask;
+
+  void clean (gcc_options *opts) const { opts->*var_ref &= ~mask; }
+
+  void set (gcc_options *opts) const { opts->*var_ref |= mask; }
+
+  bool check (cl_target_option *opts) const
+  {
+    return (opts->*cl_var_ref & mask);
+  }
+};
+
+/* Type for hold RISC-V extension version.  */
+struct riscv_version_t
+{
+  riscv_version_t (int major_version, int minor_version,
+                  enum riscv_isa_spec_class isa_spec_class
+                  = ISA_SPEC_CLASS_NONE)
+    : major_version (major_version), minor_version (minor_version),
+      isa_spec_class (isa_spec_class)
+  {}
+  int major_version;
+  int minor_version;
+  enum riscv_isa_spec_class isa_spec_class;
+};
+
 typedef bool (*riscv_implied_predicator_t) (const riscv_subset_list *);
 
 /* Type for implied ISA info.  */
 struct riscv_implied_info_t
 {
+  constexpr riscv_implied_info_t (const char *implied_ext,
+                                 riscv_implied_predicator_t predicator
+                                 = nullptr)
+    : ext (nullptr), implied_ext (implied_ext), predicator (predicator)
+  {}
+
   constexpr riscv_implied_info_t (const char *ext, const char *implied_ext,
                                  riscv_implied_predicator_t predicator
                                  = nullptr)
@@ -53,7 +105,7 @@ struct riscv_implied_info_t
 
   bool match (const riscv_subset_list *subset_list, const char *ext_name) const
   {
-    if (strcmp (ext_name, ext) != 0)
+    if (ext_name && strcmp (ext_name, ext) != 0)
       return false;
 
     if (predicator && !predicator (subset_list))
@@ -73,6 +125,111 @@ struct riscv_implied_info_t
   riscv_implied_predicator_t predicator;
 };
 
+static void
+apply_extra_extension_flags (const char *ext,
+                            std::vector<riscv_ext_flag_table_t> &flag_table);
+
+/* Class for hold the extension info.  */
+class riscv_ext_info_t
+{
+public:
+  riscv_ext_info_t (const char *ext,
+                   const std::vector<riscv_implied_info_t> &implied_exts,
+                   const std::vector<riscv_version_t> &supported_versions,
+                   const std::vector<riscv_ext_flag_table_t> &flag_table,
+                   int bitmask_group_id, int bitmask_group_bit_pos,
+                   unsigned extra_extension_flags)
+    : m_ext (ext), m_implied_exts (implied_exts),
+      m_supported_versions (supported_versions), m_flag_table (flag_table),
+      m_bitmask_group_id (bitmask_group_id),
+      m_bitmask_group_bit_pos (bitmask_group_bit_pos),
+      m_extra_extension_flags (extra_extension_flags)
+  {
+    apply_extra_extension_flags (ext, m_flag_table);
+  }
+
+  /* Return true if any change.  */
+  bool apply_implied_ext (riscv_subset_list *subset_list) const;
+
+  const std::vector<riscv_implied_info_t> implied_exts () const
+  {
+    return m_implied_exts;
+  }
+
+  bool need_combine_p () const
+  {
+     return m_extra_extension_flags & EXT_FLAG_MACRO;
+  }
+
+  riscv_version_t default_version () const
+  {
+    if (m_supported_versions.size () == 1)
+      {
+       return *m_supported_versions.begin ();
+      }
+
+    for (const riscv_version_t &ver : m_supported_versions)
+      {
+       if (ver.isa_spec_class == riscv_isa_spec
+           || ver.isa_spec_class == ISA_SPEC_CLASS_NONE)
+         return ver;
+      }
+    gcc_unreachable ();
+  }
+
+  void clean_opts (gcc_options *opts) const
+  {
+    for (auto &flag : m_flag_table)
+      flag.clean (opts);
+  }
+
+  void set_opts (gcc_options *opts) const
+  {
+    for (auto &flag : m_flag_table)
+      flag.set (opts);
+  }
+
+  bool check_opts (cl_target_option *opts) const
+  {
+    bool result = true;
+    for (auto &flag : m_flag_table)
+      result = result && flag.check (opts);
+    return result;
+  }
+
+  const std::vector<riscv_version_t> &supported_versions () const
+  {
+    return m_supported_versions;
+  }
+
+private:
+  const char *m_ext;
+  std::vector<riscv_implied_info_t> m_implied_exts;
+  std::vector<riscv_version_t> m_supported_versions;
+  std::vector<riscv_ext_flag_table_t> m_flag_table;
+  int m_bitmask_group_id;
+  int m_bitmask_group_bit_pos;
+  unsigned m_extra_extension_flags;
+};
+
+static const std::unordered_map<std::string, riscv_ext_info_t> riscv_ext_infos
+  = {
+#define DEFINE_RISCV_EXT(NAME, UPPERCAE_NAME, FULL_NAME, DESC, URL, DEP_EXTS,  
\
+                        SUPPORTED_VERSIONS, FLAG_GROUP, BITMASK_GROUP_ID,     \
+                        BITMASK_BIT_POSITION, EXTRA_EXTENSION_FLAGS)          \
+  {std::string (#NAME),                                                        
\
+   riscv_ext_info_t (#NAME, std::vector<riscv_implied_info_t> DEP_EXTS,        
\
+                    std::vector<riscv_version_t> SUPPORTED_VERSIONS,          \
+                    std::vector<riscv_ext_flag_table_t> (                     \
+                      {{&gcc_options::x_riscv_##FLAG_GROUP##_subext,          \
+                        &cl_target_option::x_riscv_##FLAG_GROUP##_subext,     \
+                        MASK_##UPPERCAE_NAME}}),                              \
+                    BITMASK_GROUP_ID, BITMASK_BIT_POSITION,                   \
+                    EXTRA_EXTENSION_FLAGS)},
+#include "../../../config/riscv/riscv-ext.def"
+#undef DEFINE_RISCV_EXT
+};
+
 /* Implied ISA info, must end with NULL sentinel.  */
 static const riscv_implied_info_t riscv_implied_info[] =
 {
@@ -261,7 +418,7 @@ static const riscv_implied_info_t riscv_implied_info[] =
 
   {"xsfvcp", "zve32x"},
 
-  {NULL, NULL}
+  {NULL, NULL, NULL}
 };
 
 /* This structure holds version information for specific ISA version.  */
@@ -1620,18 +1777,6 @@ riscv_arch_str (bool version_p)
     return std::string();
 }
 
-/* Type for pointer to member of gcc_options and cl_target_option.  */
-typedef int (gcc_options::*opt_var_ref_t);
-typedef int (cl_target_option::*cl_opt_var_ref_t);
-
-/* Types for recording extension to internal flag.  */
-struct riscv_ext_flag_table_t {
-  const char *ext;
-  opt_var_ref_t var_ref;
-  cl_opt_var_ref_t cl_var_ref;
-  int mask;
-};
-
 #define RISCV_EXT_FLAG_ENTRY(NAME, VAR, MASK) \
   {NAME, &gcc_options::VAR, &cl_target_option::VAR, MASK}
 
@@ -1822,6 +1967,24 @@ static const riscv_ext_flag_table_t 
riscv_ext_flag_table[] =
   {NULL, NULL, NULL, 0}
 };
 
+/* Add extra extension flags into FLAG_TABLE for EXT.  */
+static void
+apply_extra_extension_flags (const char *ext,
+                            std::vector<riscv_ext_flag_table_t> &flag_table)
+{
+  const riscv_ext_flag_table_t *arch_ext_flag_tab;
+  for (arch_ext_flag_tab = &riscv_ext_flag_table[0]; arch_ext_flag_tab->ext;
+       ++arch_ext_flag_tab)
+    {
+      if (strcmp (arch_ext_flag_tab->ext, ext) == 0)
+       {
+         flag_table.push_back ({arch_ext_flag_tab->var_ref,
+                                arch_ext_flag_tab->cl_var_ref,
+                                arch_ext_flag_tab->mask});
+       }
+    }
+}
+
 /* Types for recording extension to RISC-V C-API bitmask.  */
 struct riscv_ext_bitmask_table_t {
   const char *ext;
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index fc3963c96bc5..0f3bca5bb7c7 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -164,4 +164,12 @@ enum riscv_tls_type {
 
 #define GPR2VR_COST_UNPROVIDED -1
 
+/* Extra extension flags, used for carry extra info for a RISC-V extension.  */
+enum
+{
+  EXT_FLAG_MACRO = 1 << 0,
+};
+
+#define BITMASK_NOT_YET_ALLOCATED -1
+
 #endif /* ! GCC_RISCV_OPTS_H */
-- 
2.34.1

Reply via email to