Index: gcc/ChangeLog

2012-11-30  Lawrence Crowl  <crowl@google.com>

	* alloc-pool.c (static hash_table <alloc_pool_hasher> alloc_pool_hash):
	Move declaration to after the type's method definitons.

	* attribs.c (htab_t scoped_attributes::attribute_hash):
	Change type to hash_table.  Update dependent calls and types.

	* bitmap.c (htab_t bitmap_desc_hash):
	Change type to hash_table.  Update dependent calls and types.

	* dwarf2cfi.c (htab_t trace_index):
	Change type to hash_table.  Update dependent calls and types.

	* dwarf2out.c (htab_t break_out_includes::cu_hash_table):
	Change type to hash_table.  Update dependent calls and types.
	(htab_t copy_decls_for_unworthy_types::decl_table): Likewise.
	(htab_t optimize_external_refs::map): Likewise.
	(htab_t output_comp_unit::extern_map): Likewise.
	(htab_t output_comdat_type_unit::extern_map): Likewise.
	(htab_t output_macinfo::macinfo_htab): Likewise.
	(htab_t optimize_location_lists::htab): Likewise.
	(htab_t dwarf2out_finish::comdat_type_table): Likewise.

	* except.c (htab_t ehspec_hash_type):
	Change type to hash_table.  Update dependent calls and types.
	(assign_filter_values::ttypes): Likewise.
	(assign_filter_values::ehspec): Likewise.
	(sjlj_assign_call_site_values::ar_hash): Likewise.
	(convert_to_eh_region_ranges::ar_hash): Likewise.

	* trans-mem.c (htab_t tm_new_mem_hash):
	Change type to hash_table.  Update dependent calls and types.

	* tree-browser.c (htab_t TB_up_ht):
	Change type to hash_table.  Update dependent calls and types.

	* tree-eh.c (htab_t finally_tree):
	Change type to hash_table.  Update dependent calls and types.

	* Makefile.in: Update to changes above.

Index: gcc/attribs.c
===================================================================
--- gcc/attribs.c	(revision 193902)
+++ gcc/attribs.c	(working copy)
@@ -31,7 +31,7 @@ along with GCC; see the file COPYING3.
 #include "cpplib.h"
 #include "target.h"
 #include "langhooks.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "plugin.h"

 /* Table of the tables of attributes (common, language, format, machine)
@@ -46,13 +46,45 @@ struct substring
   int length;
 };

+/* Simple hash function to avoid need to scan whole string.  */
+
+static inline hashval_t
+substring_hash (const char *str, int l)
+{
+  return str[0] + str[l - 1] * 256 + l * 65536;
+}
+
+/* Used for attribute_hash.  */
+
+struct attribute_hasher : typed_noop_remove <attribute_spec>
+{
+  typedef attribute_spec value_type;
+  typedef substring compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+attribute_hasher::hash (const value_type *spec)
+{
+  const int l = strlen (spec->name);
+  return substring_hash (spec->name, l);
+}
+
+inline bool
+attribute_hasher::equal (const value_type *spec, const compare_type *str)
+{
+  return (!strncmp (spec->name, str->str, str->length)
+	  && !spec->name[str->length]);
+}
+
 /* Scoped attribute name representation.  */

 struct scoped_attributes
 {
   const char *ns;
   vec<attribute_spec> attributes;
-  htab_t attribute_hash;
+  hash_table <attribute_hasher> attribute_hash;
 };

 /* The table of scope attributes.  */
@@ -85,36 +117,6 @@ extract_attribute_substring (struct subs
     }
 }

-/* Simple hash function to avoid need to scan whole string.  */
-
-static inline hashval_t
-substring_hash (const char *str, int l)
-{
-  return str[0] + str[l - 1] * 256 + l * 65536;
-}
-
-/* Used for attribute_hash.  */
-
-static hashval_t
-hash_attr (const void *p)
-{
-  const struct attribute_spec *const spec = (const struct attribute_spec *) p;
-  const int l = strlen (spec->name);
-
-  return substring_hash (spec->name, l);
-}
-
-/* Used for attribute_hash.  */
-
-static int
-eq_attr (const void *p, const void *q)
-{
-  const struct attribute_spec *const spec = (const struct attribute_spec *) p;
-  const struct substring *const str = (const struct substring *) q;
-
-  return (!strncmp (spec->name, str->str, str->length) &&
!spec->name[str->length]);
-}
-
 /* Insert an array of attributes ATTRIBUTES into a namespace.  This
    array must be NULL terminated.  NS is the name of attribute
    namespace.  The function returns the namespace into which the
@@ -141,7 +143,7 @@ register_scoped_attributes (const struct
       sa.ns = ns;
       sa.attributes.create (64);
       result = attributes_table.safe_push (sa);
-      result->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
+      result->attribute_hash.create (200);
     }

   /* Really add the attributes to their namespace now.  */
@@ -274,11 +276,11 @@ register_scoped_attribute (const struct
 			   scoped_attributes *name_space)
 {
   struct substring str;
-  void **slot;
+  attribute_spec **slot;

   gcc_assert (attr != NULL && name_space != NULL);

-  gcc_assert (name_space->attribute_hash != NULL);
+  gcc_assert (name_space->attribute_hash.is_created ());

   str.str = attr->name;
   str.length = strlen (str.str);
@@ -287,11 +289,11 @@ register_scoped_attribute (const struct
      in the form '__text__'.  */
   gcc_assert (str.length > 0 && str.str[0] != '_');

-  slot = htab_find_slot_with_hash (name_space->attribute_hash, &str,
-				   substring_hash (str.str, str.length),
-				   INSERT);
+  slot = name_space->attribute_hash
+	 .find_slot_with_hash (&str, substring_hash (str.str, str.length),
+			       INSERT);
   gcc_assert (!*slot || attr->name[0] == '*');
-  *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
+  *slot = CONST_CAST (struct attribute_spec *, attr);
 }

 /* Return the spec for the scoped attribute with namespace NS and
@@ -313,8 +315,7 @@ lookup_scoped_attribute_spec (const_tree
   attr.str = IDENTIFIER_POINTER (name);
   attr.length = IDENTIFIER_LENGTH (name);
   extract_attribute_substring (&attr);
-  return (const struct attribute_spec *)
-    htab_find_with_hash (attrs->attribute_hash, &attr,
+  return attrs->attribute_hash.find_with_hash (&attr,
 			 substring_hash (attr.str, attr.length));
 }

Index: gcc/bitmap.c
===================================================================
--- gcc/bitmap.c	(revision 193902)
+++ gcc/bitmap.c	(working copy)
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.
 #include "obstack.h"
 #include "ggc.h"
 #include "bitmap.h"
-#include "hashtab.h"
+#include "hash-table.h"

 /* Store information about each particular bitmap.  */
 struct bitmap_descriptor
@@ -39,35 +39,41 @@ struct bitmap_descriptor
   int search_iter;
 };

-/* Hashtable mapping bitmap names to descriptors.  */
-static htab_t bitmap_desc_hash;
-
 /* Hashtable helpers.  */
-static hashval_t
-hash_descriptor (const void *p)
-{
-  const struct bitmap_descriptor *const d =
-    (const struct bitmap_descriptor *) p;
-  return htab_hash_pointer (d->file) + d->line;
-}
+
 struct loc
 {
   const char *file;
   const char *function;
   int line;
 };
-static int
-eq_descriptor (const void *p1, const void *p2)
+
+struct bitmap_desc_hasher : typed_noop_remove <bitmap_descriptor>
+{
+  typedef bitmap_descriptor value_type;
+  typedef loc compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+bitmap_desc_hasher::hash (const value_type *d)
+{
+  return htab_hash_pointer (d->file) + d->line;
+}
+
+inline bool
+bitmap_desc_hasher::equal (const value_type *d, const compare_type *l)
 {
-  const struct bitmap_descriptor *const d =
-    (const struct bitmap_descriptor *) p1;
-  const struct loc *const l = (const struct loc *) p2;
   return d->file == l->file && d->function == l->function && d->line
== l->line;
 }

+/* Hashtable mapping bitmap names to descriptors.  */
+static hash_table <bitmap_desc_hasher> bitmap_desc_hash;
+
 /* For given file and line, return descriptor, create new if needed.  */
 static struct bitmap_descriptor *
-bitmap_descriptor (const char *file, int line, const char *function)
+make_bitmap_descriptor (const char *file, int line, const char *function)
 {
   struct bitmap_descriptor **slot;
   struct loc loc;
@@ -76,13 +82,11 @@ bitmap_descriptor (const char *file, int
   loc.function = function;
   loc.line = line;

-  if (!bitmap_desc_hash)
-    bitmap_desc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
+  if (!bitmap_desc_hash.is_created ())
+    bitmap_desc_hash.create (10);

-  slot = (struct bitmap_descriptor **)
-    htab_find_slot_with_hash (bitmap_desc_hash, &loc,
-			      htab_hash_pointer (file) + line,
-			      INSERT);
+  slot = bitmap_desc_hash
+	 .find_slot_with_hash (&loc, htab_hash_pointer (file) + line, INSERT);
   if (*slot)
     return *slot;
   *slot = XCNEW (struct bitmap_descriptor);
@@ -96,7 +100,7 @@ bitmap_descriptor (const char *file, int
 void
 bitmap_register (bitmap b MEM_STAT_DECL)
 {
-  b->desc = bitmap_descriptor (ALONE_FINAL_PASS_MEM_STAT);
+  b->desc = make_bitmap_descriptor (ALONE_FINAL_PASS_MEM_STAT);
   b->desc->created++;
 }

@@ -2122,13 +2126,12 @@ struct output_info
   int count;
 };

-/* Called via htab_traverse.  Output bitmap descriptor pointed out by SLOT
-   and update statistics.  */
-static int
-print_statistics (void **slot, void *b)
+/* Called via hash_table::traverse.  Output bitmap descriptor pointed out by
+   SLOT and update statistics.  */
+int
+print_statistics (bitmap_descriptor **slot, output_info *i)
 {
-  struct bitmap_descriptor *d = (struct bitmap_descriptor *) *slot;
-  struct output_info *i = (struct output_info *) b;
+  struct bitmap_descriptor *d = *slot;
   char s[4096];

   if (d->allocated)
@@ -2158,7 +2161,7 @@ dump_bitmap_statistics (void)
   if (! GATHER_STATISTICS)
     return;

-  if (!bitmap_desc_hash)
+  if (!bitmap_desc_hash.is_created ())
     return;

   fprintf (stderr, "\nBitmap                                     Overall "
@@ -2167,7 +2170,7 @@ dump_bitmap_statistics (void)
   fprintf (stderr,
"---------------------------------------------------------------------------------\n");
   info.count = 0;
   info.size = 0;
-  htab_traverse (bitmap_desc_hash, print_statistics, &info);
+  bitmap_desc_hash.traverse <output_info *, print_statistics> (&info);
   fprintf (stderr,
"---------------------------------------------------------------------------------\n");
   fprintf (stderr, "%-40s %9d %15"HOST_WIDEST_INT_PRINT"d\n",
 	   "Total", info.count, info.size);
Index: gcc/alloc-pool.c
===================================================================
--- gcc/alloc-pool.c	(revision 193902)
+++ gcc/alloc-pool.c	(working copy)
@@ -83,6 +83,7 @@ struct alloc_pool_descriptor
   int elt_size;
 };

+/* Hashtable helpers.  */
 struct alloc_pool_hasher : typed_noop_remove <alloc_pool_descriptor>
 {
   typedef alloc_pool_descriptor value_type;
@@ -91,10 +92,6 @@ struct alloc_pool_hasher : typed_noop_re
   static inline bool equal (const value_type *, const compare_type *);
 };

-/* Hashtable mapping alloc_pool names to descriptors.  */
-static hash_table <alloc_pool_hasher>  alloc_pool_hash;
-
-/* Hashtable helpers.  */
 inline hashval_t
 alloc_pool_hasher::hash (const value_type *d)
 {
@@ -108,6 +105,9 @@ alloc_pool_hasher::equal (const value_ty
   return d->name == p2;
 }

+/* Hashtable mapping alloc_pool names to descriptors.  */
+static hash_table <alloc_pool_hasher>  alloc_pool_hash;
+
 /* For given name, return descriptor, create new if needed.  */
 static struct alloc_pool_descriptor *
 allocate_pool_descriptor (const char *name)
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 193902)
+++ gcc/dwarf2out.c	(working copy)
@@ -86,7 +86,7 @@ along with GCC; see the file COPYING3.
 #include "target.h"
 #include "common/common-target.h"
 #include "langhooks.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "cgraph.h"
 #include "input.h"
 #include "gimple.h"
@@ -3016,17 +3016,9 @@ static dw_die_ref remove_child_or_replac
                                                          dw_die_ref,
                                                          dw_die_ref);
 static void break_out_comdat_types (dw_die_ref);
-static dw_die_ref copy_ancestor_tree (dw_die_ref, dw_die_ref, htab_t);
-static void copy_decls_walk (dw_die_ref, dw_die_ref, htab_t);
 static void copy_decls_for_unworthy_types (dw_die_ref);

-static hashval_t htab_cu_hash (const void *);
-static int htab_cu_eq (const void *, const void *);
-static void htab_cu_del (void *);
-static int check_duplicate_cu (dw_die_ref, htab_t, unsigned *);
-static void record_comdat_symbol_number (dw_die_ref, htab_t, unsigned);
 static void add_sibling_attributes (dw_die_ref);
-static void build_abbrev_table (dw_die_ref, htab_t);
 static void output_location_lists (dw_die_ref);
 static int constant_size (unsigned HOST_WIDE_INT);
 static unsigned long size_of_die (dw_die_ref);
@@ -6490,31 +6482,34 @@ struct cu_hash_table_entry
   struct cu_hash_table_entry *next;
 };

-/* Routines to manipulate hash table of CUs.  */
-static hashval_t
-htab_cu_hash (const void *of)
+/* Helpers to manipulate hash table of CUs.  */
+
+struct cu_hash_table_entry_hasher
 {
-  const struct cu_hash_table_entry *const entry =
-    (const struct cu_hash_table_entry *) of;
+  typedef cu_hash_table_entry value_type;
+  typedef die_struct compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+  static inline void remove (value_type *);
+};

+inline hashval_t
+cu_hash_table_entry_hasher::hash (const value_type *entry)
+{
   return htab_hash_string (entry->cu->die_id.die_symbol);
 }

-static int
-htab_cu_eq (const void *of1, const void *of2)
+inline bool
+cu_hash_table_entry_hasher::equal (const value_type *entry1,
+				   const compare_type *entry2)
 {
-  const struct cu_hash_table_entry *const entry1 =
-    (const struct cu_hash_table_entry *) of1;
-  const struct die_struct *const entry2 = (const struct die_struct *) of2;
-
   return !strcmp (entry1->cu->die_id.die_symbol, entry2->die_id.die_symbol);
 }

-static void
-htab_cu_del (void *what)
+inline void
+cu_hash_table_entry_hasher::remove (value_type *entry)
 {
-  struct cu_hash_table_entry *next,
-    *entry = (struct cu_hash_table_entry *) what;
+  struct cu_hash_table_entry *next;

   while (entry)
     {
@@ -6524,19 +6519,21 @@ htab_cu_del (void *what)
     }
 }

+typedef hash_table <cu_hash_table_entry_hasher> cu_hash_type;
+
 /* Check whether we have already seen this CU and set up SYM_NUM
    accordingly.  */
 static int
-check_duplicate_cu (dw_die_ref cu, htab_t htable, unsigned int *sym_num)
+check_duplicate_cu (dw_die_ref cu, cu_hash_type htable, unsigned int *sym_num)
 {
   struct cu_hash_table_entry dummy;
   struct cu_hash_table_entry **slot, *entry, *last = &dummy;

   dummy.max_comdat_num = 0;

-  slot = (struct cu_hash_table_entry **)
-    htab_find_slot_with_hash (htable, cu, htab_hash_string
(cu->die_id.die_symbol),
-	INSERT);
+  slot = htable.find_slot_with_hash (cu,
+				     htab_hash_string (cu->die_id.die_symbol),
+				     INSERT);
   entry = *slot;

   for (; entry; last = entry, entry = entry->next)
@@ -6562,13 +6559,14 @@ check_duplicate_cu (dw_die_ref cu, htab_

 /* Record SYM_NUM to record of CU in HTABLE.  */
 static void
-record_comdat_symbol_number (dw_die_ref cu, htab_t htable, unsigned
int sym_num)
+record_comdat_symbol_number (dw_die_ref cu, cu_hash_type htable,
+			     unsigned int sym_num)
 {
   struct cu_hash_table_entry **slot, *entry;

-  slot = (struct cu_hash_table_entry **)
-    htab_find_slot_with_hash (htable, cu, htab_hash_string
(cu->die_id.die_symbol),
-	NO_INSERT);
+  slot = htable.find_slot_with_hash (cu,
+				     htab_hash_string (cu->die_id.die_symbol),
+				     NO_INSERT);
   entry = *slot;

   entry->max_comdat_num = sym_num;
@@ -6584,7 +6582,7 @@ break_out_includes (dw_die_ref die)
   dw_die_ref c;
   dw_die_ref unit = NULL;
   limbo_die_node *node, **pnode;
-  htab_t cu_hash_table;
+  cu_hash_type cu_hash_table;

   c = die->die_child;
   if (c) do {
@@ -6617,7 +6615,7 @@ break_out_includes (dw_die_ref die)
 #endif

   assign_symbol_names (die);
-  cu_hash_table = htab_create (10, htab_cu_hash, htab_cu_eq, htab_cu_del);
+  cu_hash_table.create (10);
   for (node = limbo_die_list, pnode = &limbo_die_list;
        node;
        node = node->next)
@@ -6637,7 +6635,7 @@ break_out_includes (dw_die_ref die)
 		comdat_symbol_number);
 	}
     }
-  htab_delete (cu_hash_table);
+  cu_hash_table.dispose ();
 }

 /* Return non-zero if this DIE is a declaration.  */
@@ -6812,6 +6810,94 @@ clone_as_declaration (dw_die_ref die)
   return clone;
 }

+
+/* Structure to map a DIE in one CU to its copy in a comdat type unit.  */
+
+struct decl_table_entry
+{
+  dw_die_ref orig;
+  dw_die_ref copy;
+};
+
+/* Helpers to manipulate hash table of copied declarations.  */
+
+/* Hashtable helpers.  */
+
+struct decl_table_entry_hasher : typed_free_remove <decl_table_entry>
+{
+  typedef decl_table_entry value_type;
+  typedef die_struct compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+decl_table_entry_hasher::hash (const value_type *entry)
+{
+  return htab_hash_pointer (entry->orig);
+}
+
+inline bool
+decl_table_entry_hasher::equal (const value_type *entry1,
+				const compare_type *entry2)
+{
+  return entry1->orig == entry2;
+}
+
+typedef hash_table <decl_table_entry_hasher> decl_hash_type;
+
+/* Copy DIE and its ancestors, up to, but not including, the compile unit
+   or type unit entry, to a new tree.  Adds the new tree to UNIT and returns
+   a pointer to the copy of DIE.  If DECL_TABLE is provided, it is used
+   to check if the ancestor has already been copied into UNIT.  */
+
+static dw_die_ref
+copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
+{
+  dw_die_ref parent = die->die_parent;
+  dw_die_ref new_parent = unit;
+  dw_die_ref copy;
+  decl_table_entry **slot = NULL;
+  struct decl_table_entry *entry = NULL;
+
+  if (decl_table.is_created ())
+    {
+      /* Check if the entry has already been copied to UNIT.  */
+      slot = decl_table.find_slot_with_hash (die, htab_hash_pointer (die),
+					     INSERT);
+      if (*slot != HTAB_EMPTY_ENTRY)
+        {
+          entry = *slot;
+          return entry->copy;
+        }
+
+      /* Record in DECL_TABLE that DIE has been copied to UNIT.  */
+      entry = XCNEW (struct decl_table_entry);
+      entry->orig = die;
+      entry->copy = NULL;
+      *slot = entry;
+    }
+
+  if (parent != NULL)
+    {
+      dw_die_ref spec = get_AT_ref (parent, DW_AT_specification);
+      if (spec != NULL)
+        parent = spec;
+      if (!is_unit_die (parent))
+        new_parent = copy_ancestor_tree (unit, parent, decl_table);
+    }
+
+  copy = clone_as_declaration (die);
+  add_child_die (new_parent, copy);
+
+  if (decl_table.is_created ())
+    {
+      /* Record the pointer to the copy.  */
+      entry->copy = copy;
+    }
+
+  return copy;
+}
 /* Copy the declaration context to the new type unit DIE.  This includes
    any surrounding namespace or type declarations.  If the DIE has an
    AT_specification attribute, it also includes attributes and children
@@ -6859,7 +6945,7 @@ copy_declaration_context (dw_die_ref uni
   if (decl->die_parent != NULL
       && !is_unit_die (decl->die_parent))
     {
-      new_decl = copy_ancestor_tree (unit, decl, NULL);
+      new_decl = copy_ancestor_tree (unit, decl, decl_hash_type ());
       if (new_decl != NULL)
         {
           remove_AT (new_decl, DW_AT_signature);
@@ -7058,106 +7144,16 @@ break_out_comdat_types (dw_die_ref die)
   } while (next != NULL);
 }

-/* Structure to map a DIE in one CU to its copy in a comdat type unit.  */
-
-struct decl_table_entry
-{
-  dw_die_ref orig;
-  dw_die_ref copy;
-};
-
-/* Routines to manipulate hash table of copied declarations.  */
-
-static hashval_t
-htab_decl_hash (const void *of)
-{
-  const struct decl_table_entry *const entry =
-    (const struct decl_table_entry *) of;
-
-  return htab_hash_pointer (entry->orig);
-}
-
-static int
-htab_decl_eq (const void *of1, const void *of2)
-{
-  const struct decl_table_entry *const entry1 =
-    (const struct decl_table_entry *) of1;
-  const struct die_struct *const entry2 = (const struct die_struct *) of2;
-
-  return entry1->orig == entry2;
-}
-
-static void
-htab_decl_del (void *what)
-{
-  struct decl_table_entry *entry = (struct decl_table_entry *) what;
-
-  free (entry);
-}
-
-/* Copy DIE and its ancestors, up to, but not including, the compile unit
-   or type unit entry, to a new tree.  Adds the new tree to UNIT and returns
-   a pointer to the copy of DIE.  If DECL_TABLE is provided, it is used
-   to check if the ancestor has already been copied into UNIT.  */
-
-static dw_die_ref
-copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
-{
-  dw_die_ref parent = die->die_parent;
-  dw_die_ref new_parent = unit;
-  dw_die_ref copy;
-  void **slot = NULL;
-  struct decl_table_entry *entry = NULL;
-
-  if (decl_table)
-    {
-      /* Check if the entry has already been copied to UNIT.  */
-      slot = htab_find_slot_with_hash (decl_table, die,
-                                       htab_hash_pointer (die), INSERT);
-      if (*slot != HTAB_EMPTY_ENTRY)
-        {
-          entry = (struct decl_table_entry *) *slot;
-          return entry->copy;
-        }
-
-      /* Record in DECL_TABLE that DIE has been copied to UNIT.  */
-      entry = XCNEW (struct decl_table_entry);
-      entry->orig = die;
-      entry->copy = NULL;
-      *slot = entry;
-    }
-
-  if (parent != NULL)
-    {
-      dw_die_ref spec = get_AT_ref (parent, DW_AT_specification);
-      if (spec != NULL)
-        parent = spec;
-      if (!is_unit_die (parent))
-        new_parent = copy_ancestor_tree (unit, parent, decl_table);
-    }
-
-  copy = clone_as_declaration (die);
-  add_child_die (new_parent, copy);
-
-  if (decl_table != NULL)
-    {
-      /* Record the pointer to the copy.  */
-      entry->copy = copy;
-    }
-
-  return copy;
-}
-
 /* Like clone_tree, but additionally enter all the children into
    the hash table decl_table.  */

 static dw_die_ref
-clone_tree_hash (dw_die_ref die, htab_t decl_table)
+clone_tree_hash (dw_die_ref die, decl_hash_type decl_table)
 {
   dw_die_ref c;
   dw_die_ref clone = clone_die (die);
   struct decl_table_entry *entry;
-  void **slot = htab_find_slot_with_hash (decl_table, die,
+  decl_table_entry **slot = decl_table.find_slot_with_hash (die,
 					  htab_hash_pointer (die), INSERT);
   /* Assert that DIE isn't in the hash table yet.  If it would be there
      before, the ancestors would be necessarily there as well, therefore
@@ -7179,7 +7175,7 @@ clone_tree_hash (dw_die_ref die, htab_t
    type_unit).  */

 static void
-copy_decls_walk (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
+copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
 {
   dw_die_ref c;
   dw_attr_ref a;
@@ -7190,20 +7186,20 @@ copy_decls_walk (dw_die_ref unit, dw_die
       if (AT_class (a) == dw_val_class_die_ref)
         {
           dw_die_ref targ = AT_ref (a);
-          void **slot;
+          decl_table_entry **slot;
           struct decl_table_entry *entry;

           if (targ->die_mark != 0 || targ->comdat_type_p)
             continue;

-          slot = htab_find_slot_with_hash (decl_table, targ,
-                                           htab_hash_pointer (targ), INSERT);
+          slot = decl_table.find_slot_with_hash (targ,
htab_hash_pointer (targ),
+						 INSERT);

           if (*slot != HTAB_EMPTY_ENTRY)
             {
               /* TARG has already been copied, so we just need to
                  modify the reference to point to the copy.  */
-              entry = (struct decl_table_entry *) *slot;
+              entry = *slot;
               a->dw_attr_val.v.val_die_ref.die = entry->copy;
             }
           else
@@ -7270,12 +7266,12 @@ copy_decls_walk (dw_die_ref unit, dw_die
 static void
 copy_decls_for_unworthy_types (dw_die_ref unit)
 {
-  htab_t decl_table;
+  decl_hash_type decl_table;

   mark_dies (unit);
-  decl_table = htab_create (10, htab_decl_hash, htab_decl_eq, htab_decl_del);
+  decl_table.create (10);
   copy_decls_walk (unit, unit, decl_table);
-  htab_delete (decl_table);
+  decl_table.dispose ();
   unmark_dies (unit);
 }

@@ -7330,37 +7326,42 @@ struct external_ref
   unsigned n_refs;
 };

-/* Hash an external_ref.  */
+/* Hashtable helpers.  */

-static hashval_t
-hash_external_ref (const void *p)
+struct external_ref_hasher : typed_free_remove <external_ref>
+{
+  typedef external_ref value_type;
+  typedef external_ref compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+external_ref_hasher::hash (const value_type *r)
 {
-  const struct external_ref *r = (const struct external_ref *)p;
   return htab_hash_pointer (r->type);
 }

-/* Compare external_refs.  */
-
-static int
-external_ref_eq (const void *p1, const void *p2)
+inline bool
+external_ref_hasher::equal (const value_type *r1, const compare_type *r2)
 {
-  const struct external_ref *r1 = (const struct external_ref *)p1;
-  const struct external_ref *r2 = (const struct external_ref *)p2;
   return r1->type == r2->type;
 }

+typedef hash_table <external_ref_hasher> external_ref_hash_type;
+
 /* Return a pointer to the external_ref for references to DIE.  */

 static struct external_ref *
-lookup_external_ref (htab_t map, dw_die_ref die)
+lookup_external_ref (external_ref_hash_type map, dw_die_ref die)
 {
   struct external_ref ref, *ref_p;
-  void ** slot;
+  external_ref **slot;

   ref.type = die;
-  slot = htab_find_slot (map, &ref, INSERT);
+  slot = map.find_slot (&ref, INSERT);
   if (*slot != HTAB_EMPTY_ENTRY)
-    return (struct external_ref *) *slot;
+    return *slot;

   ref_p = XCNEW (struct external_ref);
   ref_p->type = die;
@@ -7374,7 +7375,7 @@ lookup_external_ref (htab_t map, dw_die_
    references, remember how many we've seen.  */

 static void
-optimize_external_refs_1 (dw_die_ref die, htab_t map)
+optimize_external_refs_1 (dw_die_ref die, external_ref_hash_type map)
 {
   dw_die_ref c;
   dw_attr_ref a;
@@ -7407,17 +7408,17 @@ optimize_external_refs_1 (dw_die_ref die
    points to an external_ref, DATA is the CU we're processing.  If we don't
    already have a local stub, and we have multiple refs, build a stub.  */

-static int
-build_local_stub (void **slot, void *data)
+int
+dwarf2_build_local_stub (external_ref **slot, dw_die_ref data)
 {
-  struct external_ref *ref_p = (struct external_ref *)*slot;
+  struct external_ref *ref_p = *slot;

   if (ref_p->stub == NULL && ref_p->n_refs > 1 && !dwarf_strict)
     {
       /* We have multiple references to this type, so build a small stub.
 	 Both of these forms are a bit dodgy from the perspective of the
 	 DWARF standard, since technically they should have names.  */
-      dw_die_ref cu = (dw_die_ref) data;
+      dw_die_ref cu = data;
       dw_die_ref type = ref_p->type;
       dw_die_ref stub = NULL;

@@ -7445,12 +7446,13 @@ build_local_stub (void **slot, void *dat
    them which will be applied in build_abbrev_table.  This is useful because
    references to local DIEs are smaller.  */

-static htab_t
+static external_ref_hash_type
 optimize_external_refs (dw_die_ref die)
 {
-  htab_t map = htab_create (10, hash_external_ref, external_ref_eq, free);
+  external_ref_hash_type map;
+  map.create (10);
   optimize_external_refs_1 (die, map);
-  htab_traverse (map, build_local_stub, die);
+  map.traverse <dw_die_ref, dwarf2_build_local_stub> (die);
   return map;
 }

@@ -7460,7 +7462,7 @@ optimize_external_refs (dw_die_ref die)
    die are visited recursively.  */

 static void
-build_abbrev_table (dw_die_ref die, htab_t extern_map)
+build_abbrev_table (dw_die_ref die, external_ref_hash_type extern_map)
 {
   unsigned long abbrev_id;
   unsigned int n_alloc;
@@ -8589,7 +8591,7 @@ output_comp_unit (dw_die_ref die, int ou
 {
   const char *secname, *oldsym;
   char *tmp;
-  htab_t extern_map;
+  external_ref_hash_type extern_map;

   /* Unless we are outputting main CU, we may throw away empty ones.  */
   if (!output_if_empty && die->die_child == NULL)
@@ -8606,7 +8608,7 @@ output_comp_unit (dw_die_ref die, int ou

   build_abbrev_table (die, extern_map);

-  htab_delete (extern_map);
+  extern_map.dispose ();

   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
@@ -8764,7 +8766,7 @@ output_comdat_type_unit (comdat_type_nod
 #if defined (OBJECT_FORMAT_ELF)
   tree comdat_key;
 #endif
-  htab_t extern_map;
+  external_ref_hash_type extern_map;

   /* First mark all the DIEs in this CU so we know which get local refs.  */
   mark_dies (node->root_die);
@@ -8773,7 +8775,7 @@ output_comdat_type_unit (comdat_type_nod

   build_abbrev_table (node->root_die, extern_map);

-  htab_delete (extern_map);
+  extern_map.dispose ();

   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE;
@@ -21092,26 +21094,31 @@ dwarf2out_undef (unsigned int lineno ATT
     }
 }

-/* Routines to manipulate hash table of CUs.  */
+/* Helpers to manipulate hash table of CUs.  */

-static hashval_t
-htab_macinfo_hash (const void *of)
+struct macinfo_entry_hasher : typed_noop_remove <macinfo_entry>
 {
-  const macinfo_entry *const entry =
-    (const macinfo_entry *) of;
+  typedef macinfo_entry value_type;
+  typedef macinfo_entry compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

+inline hashval_t
+macinfo_entry_hasher::hash (const value_type *entry)
+{
   return htab_hash_string (entry->info);
 }

-static int
-htab_macinfo_eq (const void *of1, const void *of2)
+inline bool
+macinfo_entry_hasher::equal (const value_type *entry1,
+			     const compare_type *entry2)
 {
-  const macinfo_entry *const entry1 = (const macinfo_entry *) of1;
-  const macinfo_entry *const entry2 = (const macinfo_entry *) of2;
-
   return !strcmp (entry1->info, entry2->info);
 }

+typedef hash_table <macinfo_entry_hasher> macinfo_hash_type;
+
 /* Output a single .debug_macinfo entry.  */

 static void
@@ -21200,7 +21207,7 @@ output_macinfo_op (macinfo_entry *ref)

 static unsigned
 optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
-			htab_t *macinfo_htab)
+			macinfo_hash_type *macinfo_htab)
 {
   macinfo_entry *first, *second, *cur, *inc;
   char linebuf[sizeof (HOST_WIDE_INT) * 3 + 1];
@@ -21209,7 +21216,7 @@ optimize_macinfo_range (unsigned int idx
   char *grp_name, *tail;
   const char *base;
   unsigned int i, count, encoded_filename_len, linebuf_len;
-  void **slot;
+  macinfo_entry **slot;

   first = &(*macinfo_table)[idx];
   second = &(*macinfo_table)[idx + 1];
@@ -21287,17 +21294,17 @@ optimize_macinfo_range (unsigned int idx
   inc->code = DW_MACRO_GNU_transparent_include;
   inc->lineno = 0;
   inc->info = ggc_strdup (grp_name);
-  if (*macinfo_htab == NULL)
-    *macinfo_htab = htab_create (10, htab_macinfo_hash, htab_macinfo_eq, NULL);
+  if (!macinfo_htab->is_created ())
+    macinfo_htab->create (10);
   /* Avoid emitting duplicates.  */
-  slot = htab_find_slot (*macinfo_htab, inc, INSERT);
+  slot = macinfo_htab->find_slot (inc, INSERT);
   if (*slot != NULL)
     {
       inc->code = 0;
       inc->info = NULL;
       /* If such an entry has been used before, just emit
 	 a DW_MACRO_GNU_transparent_include op.  */
-      inc = (macinfo_entry *) *slot;
+      inc = *slot;
       output_macinfo_op (inc);
       /* And clear all macinfo_entry in the range to avoid emitting them
 	 in the second pass.  */
@@ -21310,7 +21317,7 @@ optimize_macinfo_range (unsigned int idx
   else
     {
       *slot = inc;
-      inc->lineno = htab_elements (*macinfo_htab);
+      inc->lineno = macinfo_htab->elements ();
       output_macinfo_op (inc);
     }
   return count;
@@ -21361,7 +21368,7 @@ output_macinfo (void)
   unsigned long length = vec_safe_length (macinfo_table);
   macinfo_entry *ref;
   vec<macinfo_entry, va_gc> *files = NULL;
-  htab_t macinfo_htab = NULL;
+  macinfo_hash_type macinfo_htab;

   if (! length)
     return;
@@ -21434,10 +21441,10 @@ output_macinfo (void)
       ref->code = 0;
     }

-  if (macinfo_htab == NULL)
+  if (!macinfo_htab.is_created ())
     return;

-  htab_delete (macinfo_htab);
+  macinfo_htab.dispose ();

   /* If any DW_MACRO_GNU_transparent_include were used, on those
      DW_MACRO_GNU_transparent_include entries terminate the
@@ -22183,24 +22190,28 @@ file_table_relative_p (void ** slot, voi
   return 1;
 }

-/* Routines to manipulate hash table of comdat type units.  */
+/* Helpers to manipulate hash table of comdat type units.  */

-static hashval_t
-htab_ct_hash (const void *of)
+struct comdat_type_hasher : typed_noop_remove <comdat_type_node>
 {
-  hashval_t h;
-  const comdat_type_node *const type_node = (const comdat_type_node *) of;
+  typedef comdat_type_node value_type;
+  typedef comdat_type_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

+inline hashval_t
+comdat_type_hasher::hash (const value_type *type_node)
+{
+  hashval_t h;
   memcpy (&h, type_node->signature, sizeof (h));
   return h;
 }

-static int
-htab_ct_eq (const void *of1, const void *of2)
+inline bool
+comdat_type_hasher::equal (const value_type *type_node_1,
+			   const compare_type *type_node_2)
 {
-  const comdat_type_node *const type_node_1 = (const comdat_type_node *) of1;
-  const comdat_type_node *const type_node_2 = (const comdat_type_node *) of2;
-
   return (! memcmp (type_node_1->signature, type_node_2->signature,
                     DWARF_TYPE_SIGNATURE_SIZE));
 }
@@ -23070,21 +23081,29 @@ compare_locs (dw_loc_descr_ref x, dw_loc
   return x == NULL && y == NULL;
 }

+/* Hashtable helpers.  */
+
+struct loc_list_hasher : typed_noop_remove <dw_loc_list_struct>
+{
+  typedef dw_loc_list_struct value_type;
+  typedef dw_loc_list_struct compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
 /* Return precomputed hash of location list X.  */

-static hashval_t
-loc_list_hash (const void *x)
+inline hashval_t
+loc_list_hasher::hash (const value_type *x)
 {
-  return ((const struct dw_loc_list_struct *) x)->hash;
+  return x->hash;
 }

-/* Return 1 if location lists X and Y are the same.  */
+/* Return true if location lists A and B are the same.  */

-static int
-loc_list_eq (const void *x, const void *y)
+inline bool
+loc_list_hasher::equal (const value_type *a, const compare_type *b)
 {
-  const struct dw_loc_list_struct *a = (const struct dw_loc_list_struct *) x;
-  const struct dw_loc_list_struct *b = (const struct dw_loc_list_struct *) y;
   if (a == b)
     return 1;
   if (a->hash != b->hash)
@@ -23099,16 +23118,19 @@ loc_list_eq (const void *x, const void *
   return a == NULL && b == NULL;
 }

+typedef hash_table <loc_list_hasher> loc_list_hash_type;
+
+
 /* Recursively optimize location lists referenced from DIE
    children and share them whenever possible.  */

 static void
-optimize_location_lists_1 (dw_die_ref die, htab_t htab)
+optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type htab)
 {
   dw_die_ref c;
   dw_attr_ref a;
   unsigned ix;
-  void **slot;
+  dw_loc_list_struct **slot;

   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (AT_class (a) == dw_val_class_loc_list)
@@ -23117,12 +23139,11 @@ optimize_location_lists_1 (dw_die_ref di
 	/* TODO: perform some optimizations here, before hashing
 	   it and storing into the hash table.  */
 	hash_loc_list (list);
-	slot = htab_find_slot_with_hash (htab, list, list->hash,
-					 INSERT);
+	slot = htab.find_slot_with_hash (list, list->hash, INSERT);
 	if (*slot == NULL)
-	  *slot = (void *) list;
+	  *slot = list;
 	else
-          a->dw_attr_val.v.val_loc_list = (dw_loc_list_ref) *slot;
+          a->dw_attr_val.v.val_loc_list = *slot;
       }

   FOR_EACH_CHILD (die, c, optimize_location_lists_1 (c, htab));
@@ -23167,9 +23188,10 @@ index_location_lists (dw_die_ref die)
 static void
 optimize_location_lists (dw_die_ref die)
 {
-  htab_t htab = htab_create (500, loc_list_hash, loc_list_eq, NULL);
+  loc_list_hash_type htab;
+  htab.create (500);
   optimize_location_lists_1 (die, htab);
-  htab_delete (htab);
+  htab.dispose ();
 }
 
 /* Output stuff that dwarf requires at the end of every file,
@@ -23180,7 +23202,7 @@ dwarf2out_finish (const char *filename)
 {
   limbo_die_node *node, *next_node;
   comdat_type_node *ctnode;
-  htab_t comdat_type_table;
+  hash_table <comdat_type_hasher> comdat_type_table;
   unsigned int i;
   dw_die_ref main_comp_unit_die;

@@ -23440,10 +23462,10 @@ dwarf2out_finish (const char *filename)
   for (node = limbo_die_list; node; node = node->next)
     output_comp_unit (node->die, 0);

-  comdat_type_table = htab_create (100, htab_ct_hash, htab_ct_eq, NULL);
+  comdat_type_table.create (100);
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
     {
-      void **slot = htab_find_slot (comdat_type_table, ctnode, INSERT);
+      comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);

       /* Don't output duplicate types.  */
       if (*slot != HTAB_EMPTY_ENTRY)
@@ -23461,7 +23483,7 @@ dwarf2out_finish (const char *filename)
       output_comdat_type_unit (ctnode);
       *slot = ctnode;
     }
-  htab_delete (comdat_type_table);
+  comdat_type_table.dispose ();

   /* The AT_pubnames attribute needs to go in all skeleton dies, including
      both the main_cu and all skeleton TUs.  Making this call unconditional
Index: gcc/tree-browser.c
===================================================================
--- gcc/tree-browser.c	(revision 193902)
+++ gcc/tree-browser.c	(working copy)
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tree.h"
 #include "tree-pretty-print.h"

@@ -101,8 +102,40 @@ static tree TB_history_prev (void);
 /* FIXME: To be declared in a .h file.  */
 void browse_tree (tree);

+/* Hashtable helpers.  */
+struct tree_upper_hasher : typed_noop_remove <VALUE>
+{
+  typedef tree_node value_type;
+  typedef tree_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+tree_upper_hasher::hash (const value_type *v)
+{
+  return pointer_hash <value_type>::hash (v);
+}
+
+inline bool
+tree_upper_hasher::equal (const value_type *parent, const compare_type *node)
+{
+  if (parent == NULL || node == NULL)
+    return 0;
+
+  if (EXPR_P (parent))
+    {
+      int n = TREE_OPERAND_LENGTH (parent);
+      int i;
+      for (i = 0; i < n; i++)
+	if (node == TREE_OPERAND (parent, i))
+	  return true;
+    }
+  return false;
+}
+
 /* Static variables.  */
-static htab_t TB_up_ht;
+static hash_table <tree_upper_hasher> TB_up_ht;
 static vec<tree, va_gc> *TB_history_stack;
 static int TB_verbose = 1;

@@ -135,7 +168,7 @@ browse_tree (tree begin)

   /* Store in a hashtable information about previous and upper statements.  */
   {
-    TB_up_ht = htab_create (1023, htab_hash_pointer, &TB_parent_eq, NULL);
+    TB_up_ht.create (1023);
     TB_update_up (head);
   }

@@ -613,7 +646,7 @@ browse_tree (tree begin)
     }

  ret:;
-  htab_delete (TB_up_ht);
+  TB_up_ht.dispose ();
   return;
 }

@@ -659,7 +692,7 @@ TB_up_expr (tree node)
   if (node == NULL_TREE)
     return NULL_TREE;

-  res = (tree) htab_find (TB_up_ht, node);
+  res = TB_up_ht.find (node);
   return res;
 }

@@ -725,7 +758,7 @@ store_child_info (tree *tp, int *walk_su
 		  void *data ATTRIBUTE_UNUSED)
 {
   tree node;
-  void **slot;
+  tree_node **slot;

   node = *tp;

@@ -737,8 +770,8 @@ store_child_info (tree *tp, int *walk_su
       for (i = 0; i < n; i++)
 	{
 	  tree op = TREE_OPERAND (node, i);
-	  slot = htab_find_slot (TB_up_ht, op, INSERT);
-	  *slot = (void *) node;
+	  slot = TB_up_ht.find_slot (op, INSERT);
+	  *slot = node;
 	}
     }

@@ -746,28 +779,6 @@ store_child_info (tree *tp, int *walk_su
   return NULL_TREE;
 }

-/* Function used in TB_up_ht.  */
-
-static int
-TB_parent_eq (const void *p1, const void *p2)
-{
-  const_tree const node = (const_tree)p2;
-  const_tree const parent = (const_tree) p1;
-
-  if (p1 == NULL || p2 == NULL)
-    return 0;
-
-  if (EXPR_P (parent))
-    {
-      int n = TREE_OPERAND_LENGTH (parent);
-      int i;
-      for (i = 0; i < n; i++)
-	if (node == TREE_OPERAND (parent, i))
-	  return 1;
-    }
-  return 0;
-}
-
 /* Update information about upper expressions in the hash table.  */

 static void
Index: gcc/tree-eh.c
===================================================================
--- gcc/tree-eh.c	(revision 193902)
+++ gcc/tree-eh.c	(working copy)
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tm.h"
 #include "tree.h"
 #include "flags.h"
@@ -194,20 +195,42 @@ struct finally_tree_node
   gimple parent;
 };

+/* Hashtable helpers.  */
+
+struct finally_tree_hasher : typed_free_remove <finally_tree_node>
+{
+  typedef finally_tree_node value_type;
+  typedef finally_tree_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+finally_tree_hasher::hash (const value_type *v)
+{
+  return (intptr_t)v->child.t >> 4;
+}
+
+inline bool
+finally_tree_hasher::equal (const value_type *v, const compare_type *c)
+{
+  return v->child.t == c->child.t;
+}
+
 /* Note that this table is *not* marked GTY.  It is short-lived.  */
-static htab_t finally_tree;
+static hash_table <finally_tree_hasher> finally_tree;

 static void
 record_in_finally_tree (treemple child, gimple parent)
 {
   struct finally_tree_node *n;
-  void **slot;
+  finally_tree_node **slot;

   n = XNEW (struct finally_tree_node);
   n->child = child;
   n->parent = parent;

-  slot = htab_find_slot (finally_tree, n, INSERT);
+  slot = finally_tree.find_slot (n, INSERT);
   gcc_assert (!*slot);
   *slot = n;
 }
@@ -286,7 +309,7 @@ outside_finally_tree (treemple start, gi
   do
     {
       n.child = start;
-      p = (struct finally_tree_node *) htab_find (finally_tree, &n);
+      p = finally_tree.find (&n);
       if (!p)
 	return true;
       start.g = p->parent;
@@ -2102,7 +2125,7 @@ lower_eh_constructs (void)
   if (bodyp == NULL)
     return 0;

-  finally_tree = htab_create (31, struct_ptr_hash, struct_ptr_eq, free);
+  finally_tree.create (31);
   eh_region_may_contain_throw_map = BITMAP_ALLOC (NULL);
   memset (&null_state, 0, sizeof (null_state));

@@ -2120,7 +2143,7 @@ lower_eh_constructs (void)
      didn't change its value, and we don't have to re-set the function.  */
   gcc_assert (bodyp == gimple_body (current_function_decl));

-  htab_delete (finally_tree);
+  finally_tree.dispose ();
   BITMAP_FREE (eh_region_may_contain_throw_map);
   eh_seq = NULL;

Index: gcc/trans-mem.c
===================================================================
--- gcc/trans-mem.c	(revision 193902)
+++ gcc/trans-mem.c	(working copy)
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tree.h"
 #include "gimple.h"
 #include "tree-flow.h"
@@ -886,10 +887,6 @@ static htab_t tm_log;
    dominator order.  */
 static vec<tree> tm_log_save_addresses;

-/* Map for an SSA_NAME originally pointing to a non aliased new piece
-   of memory (malloc, alloc, etc).  */
-static htab_t tm_new_mem_hash;
-
 enum thread_memory_type
   {
     mem_non_local = 0,
@@ -905,6 +902,32 @@ typedef struct tm_new_mem_map
   enum thread_memory_type local_new_memory;
 } tm_new_mem_map_t;

+/* Hashtable helpers.  */
+
+struct tm_mem_map_hasher : typed_free_remove <tm_new_mem_map_t>
+{
+  typedef tm_new_mem_map_t value_type;
+  typedef tm_new_mem_map_t compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+tm_mem_map_hasher::hash (const value_type *v)
+{
+  return (intptr_t)v->val >> 4;
+}
+
+inline bool
+tm_mem_map_hasher::equal (const value_type *v, const compare_type *c)
+{
+  return v->val == c->val;
+}
+
+/* Map for an SSA_NAME originally pointing to a non aliased new piece
+   of memory (malloc, alloc, etc).  */
+static hash_table <tm_mem_map_hasher> tm_new_mem_hash;
+
 /* Htab support.  Return hash value for a `tm_log_entry'.  */
 static hashval_t
 tm_log_hash (const void *p)
@@ -956,7 +979,7 @@ static void
 tm_log_init (void)
 {
   tm_log = htab_create (10, tm_log_hash, tm_log_eq, tm_log_free);
-  tm_new_mem_hash = htab_create (5, struct_ptr_hash, struct_ptr_eq, free);
+  tm_new_mem_hash.create (5);
   tm_log_save_addresses.create (5);
 }

@@ -965,7 +988,7 @@ static void
 tm_log_delete (void)
 {
   htab_delete (tm_log);
-  htab_delete (tm_new_mem_hash);
+  tm_new_mem_hash.dispose ();
   tm_log_save_addresses.release ();
 }

@@ -1271,7 +1294,7 @@ thread_private_new_memory (basic_block e
 {
   gimple stmt = NULL;
   enum tree_code code;
-  void **slot;
+  tm_new_mem_map_t **slot;
   tm_new_mem_map_t elt, *elt_p;
   tree val = x;
   enum thread_memory_type retval = mem_transaction_local;
@@ -1285,8 +1308,8 @@ thread_private_new_memory (basic_block e

   /* Look in cache first.  */
   elt.val = x;
-  slot = htab_find_slot (tm_new_mem_hash, &elt, INSERT);
-  elt_p = (tm_new_mem_map_t *) *slot;
+  slot = tm_new_mem_hash.find_slot (&elt, INSERT);
+  elt_p = *slot;
   if (elt_p)
     return elt_p->local_new_memory;

Index: gcc/except.c
===================================================================
--- gcc/except.c	(revision 193902)
+++ gcc/except.c	(working copy)
@@ -130,7 +130,7 @@ along with GCC; see the file COPYING3.
 #include "dwarf2out.h"
 #include "dwarf2.h"
 #include "toplev.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "intl.h"
 #include "ggc.h"
 #include "tm_p.h"
@@ -168,6 +168,49 @@ struct GTY(()) call_site_record_d
   rtx landing_pad;
   int action;
 };
+
+/* In the following structure and associated functions,
+   we represent entries in the action table as 1-based indices.
+   Special cases are:
+
+	 0:	null action record, non-null landing pad; implies cleanups
+	-1:	null action record, null landing pad; implies no action
+	-2:	no call-site entry; implies must_not_throw
+	-3:	we have yet to process outer regions
+
+   Further, no special cases apply to the "next" field of the record.
+   For next, 0 means end of list.  */
+
+struct action_record
+{
+  int offset;
+  int filter;
+  int next;
+};
+
+/* Hashtable helpers.  */
+
+struct action_record_hasher : typed_free_remove <action_record>
+{
+  typedef action_record value_type;
+  typedef action_record compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+action_record_hasher::hash (const value_type *entry)
+{
+  return entry->next * 1009 + entry->filter;
+}
+
+inline bool
+action_record_hasher::equal (const value_type *entry, const compare_type *data)
+{
+  return entry->filter == data->filter && entry->next == data->next;
+}
+
+typedef hash_table <action_record_hasher> action_hash_type;
 
 static bool get_eh_region_and_lp_from_rtx (const_rtx, eh_region *,
 					   eh_landing_pad *);
@@ -175,18 +218,9 @@ static bool get_eh_region_and_lp_from_rt
 static int t2r_eq (const void *, const void *);
 static hashval_t t2r_hash (const void *);

-static int ttypes_filter_eq (const void *, const void *);
-static hashval_t ttypes_filter_hash (const void *);
-static int ehspec_filter_eq (const void *, const void *);
-static hashval_t ehspec_filter_hash (const void *);
-static int add_ttypes_entry (htab_t, tree);
-static int add_ehspec_entry (htab_t, htab_t, tree);
 static void dw2_build_landing_pads (void);

-static int action_record_eq (const void *, const void *);
-static hashval_t action_record_hash (const void *);
-static int add_action_record (htab_t, int, int);
-static int collect_one_action_chain (htab_t, eh_region);
+static int collect_one_action_chain (action_hash_type, eh_region);
 static int add_call_site (rtx, int, int);

 static void push_uleb128 (vec<uchar, va_gc> **, unsigned int);
@@ -689,46 +723,60 @@ struct ttypes_filter {
   int filter;
 };

+/* Helper for ttypes_filter hashing.  */
+
+struct ttypes_filter_hasher : typed_free_remove <ttypes_filter>
+{
+  typedef ttypes_filter value_type;
+  typedef tree_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
 /* Compare ENTRY (a ttypes_filter entry in the hash table) with DATA
    (a tree) for a @TTypes type node we are thinking about adding.  */

-static int
-ttypes_filter_eq (const void *pentry, const void *pdata)
+inline bool
+ttypes_filter_hasher::equal (const value_type *entry, const compare_type *data)
 {
-  const struct ttypes_filter *const entry
-    = (const struct ttypes_filter *) pentry;
-  const_tree const data = (const_tree) pdata;
-
   return entry->t == data;
 }

-static hashval_t
-ttypes_filter_hash (const void *pentry)
+inline hashval_t
+ttypes_filter_hasher::hash (const value_type *entry)
 {
-  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
   return TREE_HASH (entry->t);
 }

+typedef hash_table <ttypes_filter_hasher> ttypes_hash_type;
+
+
+/* Helper for ehspec hashing.  */
+
+struct ehspec_hasher : typed_free_remove <ttypes_filter>
+{
+  typedef ttypes_filter value_type;
+  typedef ttypes_filter compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
 /* Compare ENTRY with DATA (both struct ttypes_filter) for a @TTypes
    exception specification list we are thinking about adding.  */
 /* ??? Currently we use the type lists in the order given.  Someone
    should put these in some canonical order.  */

-static int
-ehspec_filter_eq (const void *pentry, const void *pdata)
+inline bool
+ehspec_hasher::equal (const value_type *entry, const compare_type *data)
 {
-  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
-  const struct ttypes_filter *data = (const struct ttypes_filter *) pdata;
-
   return type_list_equal (entry->t, data->t);
 }

 /* Hash function for exception specification lists.  */

-static hashval_t
-ehspec_filter_hash (const void *pentry)
+inline hashval_t
+ehspec_hasher::hash (const value_type *entry)
 {
-  const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry;
   hashval_t h = 0;
   tree list;

@@ -737,16 +785,19 @@ ehspec_filter_hash (const void *pentry)
   return h;
 }

+typedef hash_table <ehspec_hasher> ehspec_hash_type;
+
+
 /* Add TYPE (which may be NULL) to cfun->eh->ttype_data, using TYPES_HASH
    to speed up the search.  Return the filter value to be used.  */

 static int
-add_ttypes_entry (htab_t ttypes_hash, tree type)
+add_ttypes_entry (ttypes_hash_type ttypes_hash, tree type)
 {
   struct ttypes_filter **slot, *n;

-  slot = (struct ttypes_filter **)
-    htab_find_slot_with_hash (ttypes_hash, type, TREE_HASH (type), INSERT);
+  slot = ttypes_hash.find_slot_with_hash (type, (hashval_t) TREE_HASH (type),
+					  INSERT);

   if ((n = *slot) == NULL)
     {
@@ -767,14 +818,14 @@ add_ttypes_entry (htab_t ttypes_hash, tr
    to speed up the search.  Return the filter value to be used.  */

 static int
-add_ehspec_entry (htab_t ehspec_hash, htab_t ttypes_hash, tree list)
+add_ehspec_entry (ehspec_hash_type ehspec_hash, ttypes_hash_type ttypes_hash,
+		  tree list)
 {
   struct ttypes_filter **slot, *n;
   struct ttypes_filter dummy;

   dummy.t = list;
-  slot = (struct ttypes_filter **)
-    htab_find_slot (ehspec_hash, &dummy, INSERT);
+  slot = ehspec_hash.find_slot (&dummy, INSERT);

   if ((n = *slot) == NULL)
     {
@@ -823,7 +874,8 @@ void
 assign_filter_values (void)
 {
   int i;
-  htab_t ttypes, ehspec;
+  ttypes_hash_type ttypes;
+  ehspec_hash_type ehspec;
   eh_region r;
   eh_catch c;

@@ -833,8 +885,8 @@ assign_filter_values (void)
   else
     vec_alloc (cfun->eh->ehspec_data.other, 64);

-  ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free);
-  ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free);
+  ttypes.create (31);
+  ehspec.create (31);

   for (i = 1; vec_safe_iterate (cfun->eh->region_array, i, &r); ++i)
     {
@@ -888,8 +940,8 @@ assign_filter_values (void)
 	}
     }

-  htab_delete (ttypes);
-  htab_delete (ehspec);
+  ttypes.dispose ();
+  ehspec.dispose ();
 }

 /* Emit SEQ into basic block just before INSN (that is assumed to be
@@ -1011,12 +1063,12 @@ static vec<int> sjlj_lp_call_site_index;
 static int
 sjlj_assign_call_site_values (void)
 {
-  htab_t ar_hash;
+  action_hash_type ar_hash;
   int i, disp_index;
   eh_landing_pad lp;

   vec_alloc (crtl->eh.action_record_data, 64);
-  ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
+  ar_hash.create (31);

   disp_index = 0;
   call_site_base = 1;
@@ -1045,7 +1097,7 @@ sjlj_assign_call_site_values (void)
 	disp_index++;
       }

-  htab_delete (ar_hash);
+  ar_hash.dispose ();

   return disp_index;
 }
@@ -2201,47 +2253,14 @@ expand_builtin_extend_pointer (tree addr
   return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend);
 }
 
-/* In the following functions, we represent entries in the action table
-   as 1-based indices.  Special cases are:
-
-	 0:	null action record, non-null landing pad; implies cleanups
-	-1:	null action record, null landing pad; implies no action
-	-2:	no call-site entry; implies must_not_throw
-	-3:	we have yet to process outer regions
-
-   Further, no special cases apply to the "next" field of the record.
-   For next, 0 means end of list.  */
-
-struct action_record
-{
-  int offset;
-  int filter;
-  int next;
-};
-
 static int
-action_record_eq (const void *pentry, const void *pdata)
-{
-  const struct action_record *entry = (const struct action_record *) pentry;
-  const struct action_record *data = (const struct action_record *) pdata;
-  return entry->filter == data->filter && entry->next == data->next;
-}
-
-static hashval_t
-action_record_hash (const void *pentry)
-{
-  const struct action_record *entry = (const struct action_record *) pentry;
-  return entry->next * 1009 + entry->filter;
-}
-
-static int
-add_action_record (htab_t ar_hash, int filter, int next)
+add_action_record (action_hash_type ar_hash, int filter, int next)
 {
   struct action_record **slot, *new_ar, tmp;

   tmp.filter = filter;
   tmp.next = next;
-  slot = (struct action_record **) htab_find_slot (ar_hash, &tmp, INSERT);
+  slot = ar_hash.find_slot (&tmp, INSERT);

   if ((new_ar = *slot) == NULL)
     {
@@ -2266,7 +2285,7 @@ add_action_record (htab_t ar_hash, int f
 }

 static int
-collect_one_action_chain (htab_t ar_hash, eh_region region)
+collect_one_action_chain (action_hash_type ar_hash, eh_region region)
 {
   int next;

@@ -2395,7 +2414,7 @@ static unsigned int
 convert_to_eh_region_ranges (void)
 {
   rtx insn, iter, note;
-  htab_t ar_hash;
+  action_hash_type ar_hash;
   int last_action = -3;
   rtx last_action_insn = NULL_RTX;
   rtx last_landing_pad = NULL_RTX;
@@ -2409,7 +2428,7 @@ convert_to_eh_region_ranges (void)

   vec_alloc (crtl->eh.action_record_data, 64);

-  ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
+  ar_hash.create (31);

   for (iter = get_insns (); iter ; iter = NEXT_INSN (iter))
     if (INSN_P (iter))
@@ -2546,7 +2565,7 @@ convert_to_eh_region_ranges (void)

   call_site_base = saved_call_site_base;

-  htab_delete (ar_hash);
+  ar_hash.dispose ();
   return 0;
 }

Index: gcc/dwarf2cfi.c
===================================================================
--- gcc/dwarf2cfi.c	(revision 193902)
+++ gcc/dwarf2cfi.c	(working copy)
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.
 #include "dwarf2out.h"
 #include "dwarf2asm.h"
 #include "ggc.h"
+#include "hash-table.h"
 #include "tm_p.h"
 #include "target.h"
 #include "common/common-target.h"
@@ -155,10 +156,33 @@ typedef struct
 typedef dw_trace_info *dw_trace_info_ref;


+/* Hashtable helpers.  */
+
+struct trace_info_hasher : typed_noop_remove <dw_trace_info>
+{
+  typedef dw_trace_info value_type;
+  typedef dw_trace_info compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+trace_info_hasher::hash (const value_type *ti)
+{
+  return INSN_UID (ti->head);
+}
+
+inline bool
+trace_info_hasher::equal (const value_type *a, const compare_type *b)
+{
+  return a->head == b->head;
+}
+
+
 /* The variables making up the pseudo-cfg, as described above.  */
 static vec<dw_trace_info> trace_info;
 static vec<dw_trace_info_ref> trace_work_list;
-static htab_t trace_index;
+static hash_table <trace_info_hasher> trace_index;

 /* A vector of call frame insns for the CIE.  */
 cfi_vec cie_cfi_vec;
@@ -277,28 +301,12 @@ expand_builtin_init_dwarf_reg_sizes (tre
 }

 
-static hashval_t
-dw_trace_info_hash (const void *ptr)
-{
-  const dw_trace_info *ti = (const dw_trace_info *) ptr;
-  return INSN_UID (ti->head);
-}
-
-static int
-dw_trace_info_eq (const void *ptr_a, const void *ptr_b)
-{
-  const dw_trace_info *a = (const dw_trace_info *) ptr_a;
-  const dw_trace_info *b = (const dw_trace_info *) ptr_b;
-  return a->head == b->head;
-}
-
 static dw_trace_info *
 get_trace_info (rtx insn)
 {
   dw_trace_info dummy;
   dummy.head = insn;
-  return (dw_trace_info *)
-    htab_find_with_hash (trace_index, &dummy, INSN_UID (insn));
+  return trace_index.find_with_hash (&dummy, INSN_UID (insn));
 }

 static bool
@@ -2746,22 +2754,20 @@ create_pseudo_cfg (void)

   /* Create the trace index after we've finished building trace_info,
      avoiding stale pointer problems due to reallocation.  */
-  trace_index = htab_create (trace_info.length (),
-			     dw_trace_info_hash, dw_trace_info_eq, NULL);
+  trace_index.create (trace_info.length ());
   dw_trace_info *tp;
   FOR_EACH_VEC_ELT (trace_info, i, tp)
     {
-      void **slot;
+      dw_trace_info **slot;

       if (dump_file)
 	fprintf (dump_file, "Creating trace %u : start at %s %d%s\n", i,
 		 rtx_name[(int) GET_CODE (tp->head)], INSN_UID (tp->head),
 		 tp->switch_sections ? " (section switch)" : "");

-      slot = htab_find_slot_with_hash (trace_index, tp,
-				       INSN_UID (tp->head), INSERT);
+      slot = trace_index.find_slot_with_hash (tp, INSN_UID (tp->head), INSERT);
       gcc_assert (*slot == NULL);
-      *slot = (void *) tp;
+      *slot = tp;
     }
 }

@@ -2910,8 +2916,7 @@ execute_dwarf2_frame (void)
   }
   trace_info.release ();

-  htab_delete (trace_index);
-  trace_index = NULL;
+  trace_index.dispose ();

   return 0;
 }
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 193902)
+++ gcc/Makefile.in	(working copy)
@@ -2008,7 +2008,7 @@ default-c.o: config/default-c.c $(CONFIG
 # Files used by all variants of C and some other languages.

 attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
-	$(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) \
+	$(HASH_TABLE_H) $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) \
 	$(TARGET_H) langhooks.h $(CPPLIB_H) $(PLUGIN_H)

 incpath.o: incpath.c incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \
@@ -2100,7 +2100,7 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $
 	$(CFGLOOP_H) $(TARGET_H) $(IPA_PROP_H) $(LTO_STREAMER_H) \
 	target-globals.h

-trans-mem.o : trans-mem.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+trans-mem.o : trans-mem.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(HASH_TABLE_H) \
 	$(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_INLINE_H) \
 	$(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \
 	$(PARAMS_H) $(TARGET_H) langhooks.h \
@@ -2421,7 +2421,7 @@ tree-ssa-operands.o : tree-ssa-operands.
    coretypes.h dumpfile.h langhooks.h $(IPA_REFERENCE_H)
$(GIMPLE_PRETTY_PRINT_H)
 tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) langhooks.h \
-   $(GGC_H) $(TREE_PASS_H) coretypes.h pointer-set.h \
+   $(HASH_TABLE_H) $(GGC_H) $(TREE_PASS_H) coretypes.h pointer-set.h \
    $(TREE_INLINE_H) tree-iterator.h toplev.h \
    $(DIAGNOSTIC_CORE_H) $(TARGET_H) $(CFGLOOP_H)
