Hi.

This one is more interesting as it implements hierarchical option parsing
and as a first step I implemented that for optgroup suboptions.

Next candidates are dump_option_value_info and obviously my primary motivation:
dump_option_value_info.

I'm expecting feedback for implementation I've decided to come up with.
Patch has been tested.

Thanks,
Martin
>From fcb78a3d07f3043766f27f73038f313f914b3976 Mon Sep 17 00:00:00 2001
From: marxin <mli...@suse.cz>
Date: Fri, 5 May 2017 11:31:18 +0200
Subject: [PATCH 2/2] Add dump_flags_type<E> for handling of suboptions.

gcc/ChangeLog:

2017-05-05  Martin Liska  <mli...@suse.cz>

	* dumpfile.c (dump_option_node::initialize): New function.
	(dump_option_node::initialize_masks): Likewise.
	(dump_option_node::parse): Likewise.
	(gcc::dump_manager::dump_manager): Initialize options.
	(dump_switch_p_1): Use the new parser.
	(initialize_options): New function.
	(opt_info_switch_p_1): Use the new parser.
	(opt_info_switch_p): Use new dump_flags_type<E> type.
	* dumpfile.h (struct dump_option_node): New struct.
	(struct dump_flags_type): Likewise.
	(enum optgroup_types): New enum type.
	(struct dump_file_info): Change type of optgroup_flags.
---
 gcc/dumpfile.c | 141 ++++++++++++++++++++++++++++++++++++++++----------
 gcc/dumpfile.h | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 255 insertions(+), 46 deletions(-)

diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 907ded3695f..82c4fc9d4ff 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -135,17 +135,78 @@ static const struct dump_option_value_info optinfo_verbosity_options[] =
   {NULL, 0}
 };
 
-/* Flags used for -fopt-info groups.  */
-static const struct dump_option_value_info optgroup_options[] =
-{
-  {"ipa", OPTGROUP_IPA},
-  {"loop", OPTGROUP_LOOP},
-  {"inline", OPTGROUP_INLINE},
-  {"omp", OPTGROUP_OMP},
-  {"vec", OPTGROUP_VEC},
-  {"optall", OPTGROUP_ALL},
-  {NULL, 0}
-};
+template <typename E>
+dump_option_node<E>::dump_option_node (const char *name, E enum_value):
+  m_name (name), m_enum_value (enum_value), m_children (), m_mask (0)
+{
+}
+
+template <typename E>
+void
+dump_option_node<E>::initialize (uint64_t *mask_translation)
+{
+  memset (mask_translation, 0, sizeof (uint64_t) * OPT_MASK_SIZE);
+  unsigned current = 0;
+  initialize_masks (&current, mask_translation);
+}
+
+template <typename E>
+uint64_t
+dump_option_node<E>::initialize_masks (unsigned *current,
+				       uint64_t *mask_translation)
+{
+  if (m_children.is_empty ())
+    {
+      gcc_assert (*current < OPT_MASK_SIZE);
+      m_mask = 1 << *current;
+      *current += 1;
+    }
+  else
+    {
+      uint64_t combined = 0;
+      for (unsigned i = 0; i < m_children.length (); i++)
+	combined |= m_children[i]->initialize_masks (current, mask_translation);
+
+      m_mask = combined;
+    }
+
+  mask_translation[m_enum_value] = m_mask;
+  return m_mask;
+}
+
+template <typename E>
+uint64_t
+dump_option_node<E>::parse (const char *token)
+{
+  char *s = xstrdup (token);
+  uint64_t r = parse (s);
+  free (s);
+
+  return r;
+}
+
+template <typename E>
+uint64_t
+dump_option_node<E>::parse (char *token)
+{
+  if (token == NULL)
+    return m_mask;
+
+  if (strcmp (token, "all") == 0)
+  {
+    token = strtok (NULL, "-");
+    return token == NULL ? m_mask : 0;
+  }
+
+  for (unsigned i = 0; i < m_children.length (); i++)
+    if (strcmp (m_children[i]->m_name, token) == 0)
+    {
+      token = strtok (NULL, "-");
+      return m_children[i]->parse (token);
+    }
+
+  return 0;
+}
 
 gcc::dump_manager::dump_manager ():
   m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
@@ -153,6 +214,7 @@ gcc::dump_manager::dump_manager ():
   m_extra_dump_files_in_use (0),
   m_extra_dump_files_alloced (0)
 {
+  initialize_options ();
 }
 
 gcc::dump_manager::~dump_manager ()
@@ -174,12 +236,14 @@ gcc::dump_manager::~dump_manager ()
       XDELETEVEC (const_cast <char *> (dfi->alt_filename));
     }
   XDELETEVEC (m_extra_dump_files);
+
+  delete (optgroup_options);
 }
 
 unsigned int
 gcc::dump_manager::
 dump_register (const char *suffix, const char *swtch, const char *glob,
-	       dump_flags_t flags, int optgroup_flags,
+	       dump_flags_t flags, optgroup_dump_flags_t  optgroup_flags,
 	       bool take_ownership)
 {
   int num = m_next_dump++;
@@ -716,8 +780,8 @@ dump_enable_all (dump_flags_t flags, const char *filename)
 
 int
 gcc::dump_manager::
-opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
-			const char *filename)
+opt_info_enable_passes (optgroup_dump_flags_t optgroup_flags,
+			dump_flags_t flags, const char *filename)
 {
   int n = 0;
   size_t i;
@@ -808,7 +872,7 @@ dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
 	if (strlen (option_ptr->name) == length
 	    && !memcmp (option_ptr->name, ptr, length))
           {
-            flags |= option_ptr->value;
+	    flags |= option_ptr->value;
 	    goto found;
           }
 
@@ -865,15 +929,36 @@ dump_switch_p (const char *arg)
   return any;
 }
 
+void
+gcc::dump_manager::
+initialize_options ()
+{
+  /* Initialize optgroup options.  */
+  typedef dump_option_node<optgroup_types> node;
+
+  optgroup_options = new node (NULL, OPTGROUP_NONE);
+  optgroup_options->register_suboption (new node ("ipa", OPTGROUP_IPA));
+  optgroup_options->register_suboption (new node ("loop", OPTGROUP_LOOP));
+  optgroup_options->register_suboption (new node ("inline", OPTGROUP_INLINE));
+  optgroup_options->register_suboption (new node ("omp", OPTGROUP_OMP));
+  optgroup_options->register_suboption (new node ("vec", OPTGROUP_VEC));
+  optgroup_options->register_suboption (new node ("other", OPTGROUP_OTHER));
+
+  optgroup_options->initialize (optgroup_dump_flags_t::m_mask_translation);
+}
+
 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
    and filename.  Return non-zero if it is a recognized switch.  */
 
 static int
-opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
-                     char **filename)
+opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
+		     optgroup_dump_flags_t *optgroup_flags,
+		     char **filename)
 {
   const char *option_value;
   const char *ptr;
+  optgroup_dump_flags_t f;
+  gcc::dump_manager *dumps = g->get_dumps ();
 
   option_value = arg;
   ptr = option_value;
@@ -885,6 +970,7 @@ opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
   if (!ptr)
     return 1;       /* Handle '-fopt-info' without any additional options.  */
 
+
   while (*ptr)
     {
       const struct dump_option_value_info *option_ptr;
@@ -909,17 +995,16 @@ opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
 	if (strlen (option_ptr->name) == length
 	    && !memcmp (option_ptr->name, ptr, length))
           {
-            *flags |= option_ptr->value;
+	    *flags |= option_ptr->value;
 	    goto found;
-          }
+	  }
 
-      for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
-	if (strlen (option_ptr->name) == length
-	    && !memcmp (option_ptr->name, ptr, length))
-          {
-            *optgroup_flags |= option_ptr->value;
-	    goto found;
-          }
+      f = dumps->get_optgroup_options ()->parse (ptr);
+      if (f)
+	{
+	  *optgroup_flags |= f;
+	  goto found;
+	}
 
       if (*ptr == '=')
         {
@@ -948,7 +1033,7 @@ int
 opt_info_switch_p (const char *arg)
 {
   dump_flags_t flags;
-  int optgroup_flags;
+  optgroup_dump_flags_t optgroup_flags;
   char *filename;
   static char *file_seen = NULL;
   gcc::dump_manager *dumps = g->get_dumps ();
@@ -971,7 +1056,7 @@ opt_info_switch_p (const char *arg)
   if (!flags)
     flags = MSG_OPTIMIZED_LOCATIONS;
   if (!optgroup_flags)
-    optgroup_flags = OPTGROUP_ALL;
+    optgroup_flags = optgroup_dump_flags_t::get_all ();
 
   return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
 }
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index 76183e3eede..67da7003331 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -90,20 +90,134 @@ enum tree_dump_index
 #define MSG_ALL         (MSG_OPTIMIZED_LOCATIONS | MSG_MISSED_OPTIMIZATION \
                          | MSG_NOTE)
 
+/* Dump option node is a tree structure that implements
+   parsing of suboptions and provides mapping between a given enum type E
+   and unsigned integer masks that are encapsulated in dump_flags_type type.  */
 
-/* Flags to control high-level -fopt-info dumps.  Usually these flags
-   define a group of passes.  An optimization pass can be part of
-   multiple groups.  */
-#define OPTGROUP_NONE        (0)
-#define OPTGROUP_IPA         (1 << 1)   /* IPA optimization passes */
-#define OPTGROUP_LOOP        (1 << 2)   /* Loop optimization passes */
-#define OPTGROUP_INLINE      (1 << 3)   /* Inlining passes */
-#define OPTGROUP_OMP         (1 << 4)   /* OMP (Offloading and Multi
-					   Processing) transformations */
-#define OPTGROUP_VEC         (1 << 5)   /* Vectorization passes */
-#define OPTGROUP_OTHER       (1 << 6)   /* All other passes */
-#define OPTGROUP_ALL	     (OPTGROUP_IPA | OPTGROUP_LOOP | OPTGROUP_INLINE \
-                              | OPTGROUP_OMP | OPTGROUP_VEC | OPTGROUP_OTHER)
+template <typename E>
+struct dump_option_node
+{
+  /* Constructor.  */
+  dump_option_node (const char *name, E enum_value);
+
+  /* Initialize hierarchy and fill up a MASK_TRANLATION table.  */
+  void initialize (uint64_t *mask_translation);
+
+  /* Parse a given option string and return mask.  */
+  uint64_t parse (const char *token);
+
+  /* Register a SUBOPTION for a dump option node.  */
+  void register_suboption (dump_option_node<E> *suboption)
+  {
+    m_children.safe_push (suboption);
+  }
+
+private:
+  /* Initialize masks for internal nodes.  CURRENT is a counter with first
+     free mask.  MASK_TRANSLATION is table that is filled up.  */
+  uint64_t initialize_masks (unsigned *current, uint64_t *mask_translation);
+
+  /* Parse a given option string and return mask.  */
+  uint64_t parse (char *token);
+
+  /* Name of the option.  */
+  const char *m_name;
+
+  /* Enum value of the option.  */
+  E m_enum_value;
+
+  /* Children options.  */
+  vec<dump_option_node *> m_children;
+
+  /* Mask that represents the option.  */
+  uint64_t m_mask;
+};
+
+/* Size of possible valid leaf options.  */
+#define OPT_MASK_SIZE (CHAR_BIT * sizeof (uint64_t))
+
+/* Dump flags type represents a set of selected options for
+   a given enum type E.  */
+
+template <typename E>
+struct dump_flags_type
+{
+  /* Constructor.  */
+  dump_flags_type<E> (): m_mask (0)
+  {}
+
+  /* Constructor for a MASK.  */
+  dump_flags_type<E> (uint64_t mask): m_mask (mask)
+  {}
+
+  /* Constructor for a enum value E.  */
+  dump_flags_type<E> (E enum_value)
+  {
+    gcc_checking_assert ((unsigned)enum_value <= OPT_MASK_SIZE);
+    m_mask = m_mask_translation[enum_value];
+  }
+
+  /* OR operator for OTHER dump_flags_type.  */
+  inline void operator|= (dump_flags_type other)
+  {
+    m_mask |= other.m_mask;
+  }
+
+  /* AND operator for OTHER dump_flags_type.  */
+  inline void operator&= (dump_flags_type other)
+  {
+    m_mask &= other.m_mask;
+  }
+
+  /* AND operator for OTHER dump_flags_type.  */
+  inline bool operator& (dump_flags_type other)
+  {
+    return m_mask & other.m_mask;
+  }
+
+  /* Bool operator that is typically used to test whether an option is set.  */
+  inline operator bool () const
+  {
+    return m_mask;
+  }
+
+  /* Return mask that represents all selected options.  */
+  static inline dump_flags_type get_all ()
+  {
+    return m_mask_translation[0];
+  }
+
+  /* Initialize.  */
+  static dump_flags_type parse (char *option);
+
+  /* Selected mask of options.  */
+  uint64_t m_mask;
+
+  /* Translation table between enum values and masks.  */
+  static uint64_t m_mask_translation[OPT_MASK_SIZE];
+};
+
+/* Flags used for -fopt-info groups.  */
+
+enum optgroup_types
+{
+  OPTGROUP_NONE,
+  OPTGROUP_IPA,
+  OPTGROUP_LOOP,
+  OPTGROUP_INLINE,
+  OPTGROUP_OMP,
+  OPTGROUP_VEC,
+  OPTGROUP_OTHER,
+  OPTGROUP_COUNT
+};
+
+template<typename E>
+uint64_t
+dump_flags_type<E>::m_mask_translation[OPT_MASK_SIZE];
+
+/* Dump flags type for optgroup_types enum type.  */
+
+typedef dump_flags_type<optgroup_types> optgroup_dump_flags_t;
 
 /* Dump flags type.  */
 
@@ -120,7 +234,7 @@ struct dump_file_info
   FILE *pstream;                /* pass-specific dump stream  */
   FILE *alt_stream;             /* -fopt-info stream */
   dump_flags_t pflags;		/* dump flags */
-  int optgroup_flags;           /* optgroup flags for -fopt-info */
+  optgroup_dump_flags_t optgroup_flags; /* optgroup flags for -fopt-info */
   int alt_flags;                /* flags for opt-info */
   int pstate;                   /* state of pass-specific stream */
   int alt_state;                /* state of the -fopt-info stream */
@@ -187,7 +301,7 @@ public:
      SUFFIX, SWTCH, and GLOB. */
   unsigned int
   dump_register (const char *suffix, const char *swtch, const char *glob,
-		 dump_flags_t flags, int optgroup_flags,
+		 dump_flags_t flags, optgroup_dump_flags_t  optgroup_flags,
 		 bool take_ownership);
 
   /* Return the dump_file_info for the given phase.  */
@@ -232,6 +346,12 @@ public:
   const char *
   dump_flag_name (int phase) const;
 
+  /* Return optgroup_types dump options.  */
+  dump_option_node<optgroup_types> *get_optgroup_options ()
+  {
+    return optgroup_options;
+  }
+
 private:
 
   int
@@ -244,8 +364,10 @@ private:
   dump_enable_all (dump_flags_t flags, const char *filename);
 
   int
-  opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
-			  const char *filename);
+  opt_info_enable_passes (optgroup_dump_flags_t optgroup_flags,
+			  dump_flags_t flags, const char *filename);
+
+  void initialize_options ();
 
 private:
 
@@ -255,12 +377,14 @@ private:
   size_t m_extra_dump_files_in_use;
   size_t m_extra_dump_files_alloced;
 
+  /* Dump option node for optgroup_types enum.  */
+  dump_option_node<optgroup_types> *optgroup_options;
+
   /* Grant access to dump_enable_all.  */
   friend bool ::enable_rtl_dump_file (void);
 
   /* Grant access to opt_info_enable_passes.  */
   friend int ::opt_info_switch_p (const char *arg);
-
 }; // class dump_manager
 
 } // namespace gcc
-- 
2.12.2

Reply via email to