gdb: remove BLOCK_FUNCTION macro
[binutils-gdb.git] / gdb / reggroups.c
index 407a5b274b024c18e42591fb8fc7cc74c90abfe3..1a13cb2fba0b9fbd39cc1de939d8d089dc9da451 100644 (file)
@@ -1,6 +1,6 @@
 /* Register groupings for GDB, the GNU debugger.
 
-   Copyright 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002-2022 Free Software Foundation, Inc.
 
    Contributed by Red Hat.
 
@@ -8,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "reggroups.h"
 #include "gdbtypes.h"
-#include "gdb_assert.h"
 #include "regcache.h"
 #include "command.h"
 #include "gdbcmd.h"            /* For maintenanceprintlist.  */
+#include "gdbsupport/gdb_obstack.h"
 
-/* Individual register groups.  */
+/* See reggroups.h.  */
 
-struct reggroup
-{
-  const char *name;
-  enum reggroup_type type;
-};
-
-struct reggroup *
+const reggroup *
 reggroup_new (const char *name, enum reggroup_type type)
 {
-  struct reggroup *group = XMALLOC (struct reggroup);
-  group->name = name;
-  group->type = type;
-  return group;
+  return new reggroup (name, type);
 }
 
-/* Register group attributes.  */
+/* See reggroups.h.  */
 
-const char *
-reggroup_name (struct reggroup *group)
+const reggroup *
+reggroup_gdbarch_new (struct gdbarch *gdbarch, const char *name,
+                     enum reggroup_type type)
 {
-  return group->name;
+  name = gdbarch_obstack_strdup (gdbarch, name);
+  return obstack_new<struct reggroup> (gdbarch_obstack (gdbarch),
+                                      name, type);
 }
 
-enum reggroup_type
-reggroup_type (struct reggroup *group)
+/* A container holding all the register groups for a particular
+   architecture.  */
+
+struct reggroups
 {
-  return group->type;
-}
+  /* Add GROUP to the list of register groups.  */
 
-/* A linked list of groups for the given architecture.  */
+  void add (const reggroup *group)
+  {
+    gdb_assert (group != nullptr);
+    gdb_assert (std::find (m_groups.begin(), m_groups.end(), group)
+               == m_groups.end());
 
-struct reggroup_el
-{
-  struct reggroup *group;
-  struct reggroup_el *next;
-};
+    m_groups.push_back (group);
+  }
 
-struct reggroups
-{
-  struct reggroup_el *first;
-  struct reggroup_el **last;
-};
+  /* The number of register groups.  */
 
-static struct gdbarch_data *reggroups_data;
+  std::vector<struct reggroup *>::size_type
+  size () const
+  {
+    return m_groups.size ();
+  }
 
-static void *
-reggroups_init (struct gdbarch *gdbarch)
-{
-  struct reggroups *groups = GDBARCH_OBSTACK_ZALLOC (gdbarch,
-                                                    struct reggroups);
-  groups->last = &groups->first;
-  return groups;
-}
+  /* Return a reference to the list of all groups.  */
 
-/* Add a register group (with attribute values) to the pre-defined
-   list.  */
+  const std::vector<const struct reggroup *> &
+  groups () const
+  {
+    return m_groups;
+  }
 
-static void
-add_group (struct reggroups *groups, struct reggroup *group,
-          struct reggroup_el *el)
-{
-  gdb_assert (group != NULL);
-  el->group = group;
-  el->next = NULL;
-  (*groups->last) = el;
-  groups->last = &el->next;
-}
+private:
+  /* The register groups.  */
+  std::vector<const struct reggroup *> m_groups;
+};
+
+/* Key used to lookup register group data from a gdbarch.  */
+
+static struct gdbarch_data *reggroups_data;
+
+/* See reggroups.h.  */
 
 void
-reggroup_add (struct gdbarch *gdbarch, struct reggroup *group)
+reggroup_add (struct gdbarch *gdbarch, const reggroup *group)
 {
-  struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
+  struct reggroups *groups
+    = (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
 
-  if (groups == NULL)
-    {
-      /* ULGH, called during architecture initialization.  Patch
-         things up.  */
-      groups = reggroups_init (gdbarch);
-      deprecated_set_gdbarch_data (gdbarch, reggroups_data, groups);
-    }
-  add_group (groups, group,
-            GDBARCH_OBSTACK_ZALLOC (gdbarch, struct reggroup_el));
+  gdb_assert (groups != nullptr);
+  gdb_assert (group != nullptr);
+
+  groups->add (group);
 }
 
-/* The default register groups for an architecture.  */
+/* Called to initialize the per-gdbarch register group information.  */
 
-static struct reggroups default_groups = { NULL, &default_groups.first };
+static void *
+reggroups_init (struct obstack *obstack)
+{
+  struct reggroups *groups = obstack_new<struct reggroups> (obstack);
 
-/* A register group iterator.  */
+  /* Add the default groups.  */
+  groups->add (general_reggroup);
+  groups->add (float_reggroup);
+  groups->add (system_reggroup);
+  groups->add (vector_reggroup);
+  groups->add (all_reggroup);
+  groups->add (save_reggroup);
+  groups->add (restore_reggroup);
 
-struct reggroup *
-reggroup_next (struct gdbarch *gdbarch, struct reggroup *last)
+  return groups;
+}
+
+/* See reggroups.h.  */
+const std::vector<const reggroup *> &
+gdbarch_reggroups (struct gdbarch *gdbarch)
 {
-  struct reggroups *groups;
-  struct reggroup_el *el;
-
-  /* Don't allow this function to be called during architecture
-     creation.  If there are no groups, use the default groups list.  */
-  groups = gdbarch_data (gdbarch, reggroups_data);
-  gdb_assert (groups != NULL);
-  if (groups->first == NULL)
-    groups = &default_groups;
-
-  /* Return the first/next reggroup.  */
-  if (last == NULL)
-    return groups->first->group;
-  for (el = groups->first; el != NULL; el = el->next)
-    {
-      if (el->group == last)
-       {
-         if (el->next != NULL)
-           return el->next->group;
-         else
-           return NULL;
-       }
-    }
-  return NULL;
+  struct reggroups *groups
+    = (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
+  gdb_assert (groups != nullptr);
+  gdb_assert (groups->size () > 0);
+  return groups->groups ();
 }
 
-/* Is REGNUM a member of REGGROUP?  */
+/* See reggroups.h.  */
+
 int
 default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
-                            struct reggroup *group)
+                            const struct reggroup *group)
 {
   int vector_p;
   int float_p;
   int raw_p;
 
-  if (REGISTER_NAME (regnum) == NULL
-      || *REGISTER_NAME (regnum) == '\0')
+  if (gdbarch_register_name (gdbarch, regnum) == NULL
+      || *gdbarch_register_name (gdbarch, regnum) == '\0')
     return 0;
   if (group == all_reggroup)
     return 1;
-  vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
-  float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
-  /* FIXME: cagney/2003-04-13: Can't yet use gdbarch_num_regs
-     (gdbarch), as not all architectures are multi-arch.  */
-  raw_p = regnum < NUM_REGS;
+  vector_p = register_type (gdbarch, regnum)->is_vector ();
+  float_p = (register_type (gdbarch, regnum)->code () == TYPE_CODE_FLT
+            || (register_type (gdbarch, regnum)->code ()
+                == TYPE_CODE_DECFLOAT));
+  raw_p = regnum < gdbarch_num_regs (gdbarch);
   if (group == float_reggroup)
     return float_p;
   if (group == vector_reggroup)
@@ -177,7 +160,20 @@ default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return (!vector_p && !float_p);
   if (group == save_reggroup || group == restore_reggroup)
     return raw_p;
-  return 0;   
+  return 0;
+}
+
+/* See reggroups.h.  */
+
+const reggroup *
+reggroup_find (struct gdbarch *gdbarch, const char *name)
+{
+  for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
+    {
+      if (strcmp (name, group->name ()) == 0)
+       return group;
+    }
+  return NULL;
 }
 
 /* Dump out a table of register groups for the current architecture.  */
@@ -185,99 +181,78 @@ default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 static void
 reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  struct reggroup *group = NULL;
+  static constexpr const char *fmt = " %-10s %-10s\n";
 
-  do
+  gdb_printf (file, fmt, "Group", "Type");
+
+  for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
     {
       /* Group name.  */
-      {
-       const char *name;
-       if (group == NULL)
-         name = "Group";
-       else
-         name = reggroup_name (group);
-       fprintf_unfiltered (file, " %-10s", name);
-      }
-      
+      const char *name = group->name ();
+
       /* Group type.  */
-      {
-       const char *type;
-       if (group == NULL)
-         type = "Type";
-       else
-         {
-           switch (reggroup_type (group))
-             {
-             case USER_REGGROUP:
-               type = "user";
-               break;
-             case INTERNAL_REGGROUP:
-               type = "internal";
-               break;
-             default:
-               internal_error (__FILE__, __LINE__, _("bad switch"));
-             }
-         }
-       fprintf_unfiltered (file, " %-10s", type);
-      }
+      const char *type;
+
+      switch (group->type ())
+       {
+       case USER_REGGROUP:
+         type = "user";
+         break;
+       case INTERNAL_REGGROUP:
+         type = "internal";
+         break;
+       default:
+         internal_error (__FILE__, __LINE__, _("bad switch"));
+       }
 
       /* Note: If you change this, be sure to also update the
-         documentation.  */
-      
-      fprintf_unfiltered (file, "\n");
+        documentation.  */
 
-      group = reggroup_next (gdbarch, group);
+      gdb_printf (file, fmt, name, type);
     }
-  while (group != NULL);
 }
 
+/* Implement 'maintenance print reggroups' command.  */
+
 static void
-maintenance_print_reggroups (char *args, int from_tty)
+maintenance_print_reggroups (const char *args, int from_tty)
 {
+  struct gdbarch *gdbarch = get_current_arch ();
+
   if (args == NULL)
-    reggroups_dump (current_gdbarch, gdb_stdout);
+    reggroups_dump (gdbarch, gdb_stdout);
   else
     {
-      struct ui_file *file = gdb_fopen (args, "w");
-      if (file == NULL)
+      stdio_file file;
+
+      if (!file.open (args, "w"))
        perror_with_name (_("maintenance print reggroups"));
-      reggroups_dump (current_gdbarch, file);    
-      ui_file_delete (file);
+      reggroups_dump (gdbarch, &file);
     }
 }
 
 /* Pre-defined register groups.  */
-static struct reggroup general_group = { "general", USER_REGGROUP };
-static struct reggroup float_group = { "float", USER_REGGROUP };
-static struct reggroup system_group = { "system", USER_REGGROUP };
-static struct reggroup vector_group = { "vector", USER_REGGROUP };
-static struct reggroup all_group = { "all", USER_REGGROUP };
-static struct reggroup save_group = { "save", INTERNAL_REGGROUP };
-static struct reggroup restore_group = { "restore", INTERNAL_REGGROUP };
-
-struct reggroup *const general_reggroup = &general_group;
-struct reggroup *const float_reggroup = &float_group;
-struct reggroup *const system_reggroup = &system_group;
-struct reggroup *const vector_reggroup = &vector_group;
-struct reggroup *const all_reggroup = &all_group;
-struct reggroup *const save_reggroup = &save_group;
-struct reggroup *const restore_reggroup = &restore_group;
-
-extern initialize_file_ftype _initialize_reggroup; /* -Wmissing-prototypes */
-
+static const reggroup general_group = { "general", USER_REGGROUP };
+static const reggroup float_group = { "float", USER_REGGROUP };
+static const reggroup system_group = { "system", USER_REGGROUP };
+static const reggroup vector_group = { "vector", USER_REGGROUP };
+static const reggroup all_group = { "all", USER_REGGROUP };
+static const reggroup save_group = { "save", INTERNAL_REGGROUP };
+static const reggroup restore_group = { "restore", INTERNAL_REGGROUP };
+
+const reggroup *const general_reggroup = &general_group;
+const reggroup *const float_reggroup = &float_group;
+const reggroup *const system_reggroup = &system_group;
+const reggroup *const vector_reggroup = &vector_group;
+const reggroup *const all_reggroup = &all_group;
+const reggroup *const save_reggroup = &save_group;
+const reggroup *const restore_reggroup = &restore_group;
+
+void _initialize_reggroup ();
 void
-_initialize_reggroup (void)
+_initialize_reggroup ()
 {
-  reggroups_data = gdbarch_data_register_post_init (reggroups_init);
-
-  /* The pre-defined list of groups.  */
-  add_group (&default_groups, general_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, float_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, system_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, vector_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, all_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, save_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, restore_reggroup, XMALLOC (struct reggroup_el));
+  reggroups_data = gdbarch_data_register_pre_init (reggroups_init);
 
   add_cmd ("reggroups", class_maintenance,
           maintenance_print_reggroups, _("\