[llvm-commits] [dragonegg] r137119 - in /dragonegg/trunk: Makefile include/dragonegg/Cache.h include/dragonegg/cache.h include/dragonegg/gt-cache-4.5.h include/dragonegg/gt-cache-4.6.h src/Backend.cpp src/Cache.cpp src/Constants.cpp src/Types.cpp src/cache.c

Duncan Sands baldrick at free.fr
Tue Aug 9 08:11:51 PDT 2011


Author: baldrick
Date: Tue Aug  9 10:11:51 2011
New Revision: 137119

URL: http://llvm.org/viewvc/llvm-project?rev=137119&view=rev
Log:
Fix an obscure use-after-free coming from the tree to constant map: if a
constant used a global variable, and the global variable was replaced with
another because the initializer changed, then the constant is freed if it
is the last user of the initializer.  The map was updated for the global
variable change, but wasn't expecting the knock-on effect on constant
users of the global.  Solve by having a tree to weak value handle map
instead.  Since the map also has to be GCC garbage collector aware, some
hoops need to be jumped through to ensure that weakvh destructors are run
when map entries are garbage collected and so on.

Added:
    dragonegg/trunk/include/dragonegg/Cache.h
      - copied, changed from r137045, dragonegg/trunk/include/dragonegg/cache.h
    dragonegg/trunk/src/Cache.cpp
      - copied, changed from r137045, dragonegg/trunk/src/cache.c
Removed:
    dragonegg/trunk/include/dragonegg/cache.h
    dragonegg/trunk/src/cache.c
Modified:
    dragonegg/trunk/Makefile
    dragonegg/trunk/include/dragonegg/gt-cache-4.5.h
    dragonegg/trunk/include/dragonegg/gt-cache-4.6.h
    dragonegg/trunk/src/Backend.cpp
    dragonegg/trunk/src/Constants.cpp
    dragonegg/trunk/src/Types.cpp

Modified: dragonegg/trunk/Makefile
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Makefile?rev=137119&r1=137118&r2=137119&view=diff
==============================================================================
--- dragonegg/trunk/Makefile (original)
+++ dragonegg/trunk/Makefile Tue Aug  9 10:11:51 2011
@@ -40,7 +40,7 @@
 REVISION:=$(shell svnversion -n $(TOP_DIR))
 
 PLUGIN=dragonegg.so
-PLUGIN_OBJECTS=cache.o Backend.o Constants.o Convert.o Debug.o DefaultABI.o \
+PLUGIN_OBJECTS=Backend.o Cache.o Constants.o Convert.o Debug.o DefaultABI.o \
 	       Trees.o Types.o bits_and_bobs.o
 
 TARGET_OBJECT=Target.o
@@ -77,10 +77,6 @@
 	$(QUIET)$(CXX) -o $@ $^ $(shell $(LLVM_CONFIG) --libs support) \
 	$(LD_OPTIONS)
 
-%.o : $(SRC_DIR)/%.c $(TARGET_UTIL)
-	@echo Compiling $*.c
-	$(QUIET)$(CC) -c $(TARGET_HEADERS) $(CPP_OPTIONS) $(CFLAGS) $<
-
 %.o : $(SRC_DIR)/%.cpp $(TARGET_UTIL)
 	@echo Compiling $*.cpp
 	$(QUIET)$(CXX) -c $(TARGET_HEADERS) $(CPP_OPTIONS) $(CXXFLAGS) $<
@@ -106,7 +102,7 @@
 # The following target exists for the benefit of the dragonegg maintainers, and
 # is not used in a normal build.  You need to specify the path to the GCC build
 # directory in GCC_BUILD_DIR.
-GENGTYPE_INPUT=$(SRC_DIR)/cache.c
+GENGTYPE_INPUT=$(SRC_DIR)/Cache.cpp
 GENGTYPE_OUTPUT=$(INCLUDE_DIR)/dragonegg/gt-cache-$(GCC_MAJOR).$(GCC_MINOR).h
 gt-cache.h::
 	$(QUIET)$(GCC_BUILD_DIR)/gcc/build/gengtype \

Copied: dragonegg/trunk/include/dragonegg/Cache.h (from r137045, dragonegg/trunk/include/dragonegg/cache.h)
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Cache.h?p2=dragonegg/trunk/include/dragonegg/Cache.h&p1=dragonegg/trunk/include/dragonegg/cache.h&r1=137045&r2=137119&rev=137119&view=diff
==============================================================================
--- dragonegg/trunk/include/dragonegg/cache.h (original)
+++ dragonegg/trunk/include/dragonegg/Cache.h Tue Aug  9 10:11:51 2011
@@ -1,41 +1,61 @@
-/*===----------- cache.h - Caching values "in" GCC trees ----------*- C -*-===*\
-|*                                                                            *|
-|* Copyright (C) 2009, 2010, 2011  Duncan Sands.                              *|
-|*                                                                            *|
-|* This file is part of DragonEgg.                                            *|
-|*                                                                            *|
-|* DragonEgg 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, or (at your option) any later       *|
-|* version.                                                                   *|
-|*                                                                            *|
-|* DragonEgg is distributed in the hope that it will be useful, but WITHOUT   *|
-|* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      *|
-|* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  *|
-|* more details.                                                              *|
-|* You should have received a copy of the GNU General Public License along    *|
-|* with DragonEgg; see the file COPYING.  If not, write to the Free Software  *|
-|* Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.     *|
-|*                                                                            *|
-|*===----------------------------------------------------------------------===*|
-|* This code lets you to associate a void* with a tree, as if it were cached  *|
-|* inside the tree: if the tree is garbage collected and reallocated, then    *|
-|* the cached value will have been cleared.                                   *|
-\*===----------------------------------------------------------------------===*/
+//==----------- Cache.h - Caching values "in" GCC trees ----------*- C++ -*-==//
+//
+// Copyright (C) 2009, 2010, 2011  Duncan Sands.
+//
+// This file is part of DragonEgg.
+//
+// DragonEgg 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, or (at your option) any later
+// version.
+//
+// DragonEgg is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+// You should have received a copy of the GNU General Public License along
+// with DragonEgg; see the file COPYING.  If not, write to the Free Software
+// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+//
+//===----------------------------------------------------------------------===//
+// This code lets you associate a value with a tree, as if it were cached inside
+// the tree: if the tree is garbage collected and reallocated, then the cached
+// value will have been cleared.
+//===----------------------------------------------------------------------===//
 
 #ifndef DRAGONEGG_CACHE_H
 #define DRAGONEGG_CACHE_H
 
+// Forward declarations.
+namespace llvm {
+  class Type;
+  class Value;
+}
 union tree_node;
 
-/* llvm_get_cached - Returns the value associated with the tree, or NULL.  */
-extern const void *llvm_get_cached(union tree_node *tree);
-
-/* llvm_set_cached - Associates the given value with the tree (and returns it).
-   To delete an association, pass NULL for the value.  */
-extern const void *llvm_set_cached(union tree_node *tree, const void *val);
-
-/* llvm_replace_cached - Replaces all occurrences of old_val with new_val.  */
-extern void llvm_replace_cached(const void *old_val, const void *new_val);
+/// getCachedInteger - Returns true if there is an integer associated with the
+/// given GCC tree and puts the integer in 'val'.  Otherwise returns false.
+extern bool getCachedInteger(union tree_node *t, int &Val);
+
+/// setCachedInteger - Associates the given integer with the given GCC tree, and
+/// returns the integer.
+extern void setCachedInteger(union tree_node *t, int Val);
+
+/// getCachedType - Returns the type associated with the given GCC tree, or null
+/// if none.
+extern llvm::Type *getCachedType(union tree_node *t);
+
+/// setCachedType - Associates the given type (which may be null) with the given
+/// GCC tree, and returns the type.
+extern void setCachedType(union tree_node *t, llvm::Type *Ty);
+
+/// getCachedValue - Returns the value associated with the given GCC tree, or
+/// null if none.
+extern llvm::Value *getCachedValue(union tree_node *t);
+
+/// setCachedValue - Associates the given value (which may be null) with the
+/// given GCC tree.  The association is removed if tree is garbage collected
+/// or the value deleted.
+extern void setCachedValue(union tree_node *t, llvm::Value *V);
 
 #endif /* DRAGONEGG_CACHE_H */

Removed: dragonegg/trunk/include/dragonegg/cache.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/cache.h?rev=137118&view=auto
==============================================================================
--- dragonegg/trunk/include/dragonegg/cache.h (original)
+++ dragonegg/trunk/include/dragonegg/cache.h (removed)
@@ -1,41 +0,0 @@
-/*===----------- cache.h - Caching values "in" GCC trees ----------*- C -*-===*\
-|*                                                                            *|
-|* Copyright (C) 2009, 2010, 2011  Duncan Sands.                              *|
-|*                                                                            *|
-|* This file is part of DragonEgg.                                            *|
-|*                                                                            *|
-|* DragonEgg 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, or (at your option) any later       *|
-|* version.                                                                   *|
-|*                                                                            *|
-|* DragonEgg is distributed in the hope that it will be useful, but WITHOUT   *|
-|* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      *|
-|* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  *|
-|* more details.                                                              *|
-|* You should have received a copy of the GNU General Public License along    *|
-|* with DragonEgg; see the file COPYING.  If not, write to the Free Software  *|
-|* Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.     *|
-|*                                                                            *|
-|*===----------------------------------------------------------------------===*|
-|* This code lets you to associate a void* with a tree, as if it were cached  *|
-|* inside the tree: if the tree is garbage collected and reallocated, then    *|
-|* the cached value will have been cleared.                                   *|
-\*===----------------------------------------------------------------------===*/
-
-#ifndef DRAGONEGG_CACHE_H
-#define DRAGONEGG_CACHE_H
-
-union tree_node;
-
-/* llvm_get_cached - Returns the value associated with the tree, or NULL.  */
-extern const void *llvm_get_cached(union tree_node *tree);
-
-/* llvm_set_cached - Associates the given value with the tree (and returns it).
-   To delete an association, pass NULL for the value.  */
-extern const void *llvm_set_cached(union tree_node *tree, const void *val);
-
-/* llvm_replace_cached - Replaces all occurrences of old_val with new_val.  */
-extern void llvm_replace_cached(const void *old_val, const void *new_val);
-
-#endif /* DRAGONEGG_CACHE_H */

Modified: dragonegg/trunk/include/dragonegg/gt-cache-4.5.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/gt-cache-4.5.h?rev=137119&r1=137118&r2=137119&view=diff
==============================================================================
--- dragonegg/trunk/include/dragonegg/gt-cache-4.5.h (original)
+++ dragonegg/trunk/include/dragonegg/gt-cache-4.5.h Tue Aug  9 10:11:51 2011
@@ -21,10 +21,18 @@
 
 /* GC marker procedures.  */
 /* macros and declarations */
-#define gt_ggc_m_13tree_llvm_map(X) do { \
-  if (X != NULL) gt_ggc_mx_tree_llvm_map (X);\
+#define gt_ggc_m_11tree2WeakVH(X) do { \
+  if (X != NULL) gt_ggc_mx_tree2WeakVH (X);\
   } while (0)
-extern void gt_ggc_mx_tree_llvm_map (void *);
+extern void gt_ggc_mx_tree2WeakVH (void *);
+#define gt_ggc_m_9tree2Type(X) do { \
+  if (X != NULL) gt_ggc_mx_tree2Type (X);\
+  } while (0)
+extern void gt_ggc_mx_tree2Type (void *);
+#define gt_ggc_m_8tree2int(X) do { \
+  if (X != NULL) gt_ggc_mx_tree2int (X);\
+  } while (0)
+extern void gt_ggc_mx_tree2int (void *);
 #define gt_ggc_m_15interface_tuple(X) do { \
   if (X != NULL) gt_ggc_mx_interface_tuple (X);\
   } while (0)
@@ -105,14 +113,6 @@
   if (X != NULL) gt_ggc_mx_opt_stack (X);\
   } while (0)
 extern void gt_ggc_mx_opt_stack (void *);
-#define gt_ggc_m_16def_pragma_macro(X) do { \
-  if (X != NULL) gt_ggc_mx_def_pragma_macro (X);\
-  } while (0)
-extern void gt_ggc_mx_def_pragma_macro (void *);
-#define gt_ggc_m_22def_pragma_macro_value(X) do { \
-  if (X != NULL) gt_ggc_mx_def_pragma_macro_value (X);\
-  } while (0)
-extern void gt_ggc_mx_def_pragma_macro_value (void *);
 #define gt_ggc_m_11align_stack(X) do { \
   if (X != NULL) gt_ggc_mx_align_stack (X);\
   } while (0)
@@ -169,10 +169,6 @@
   if (X != NULL) gt_ggc_mx_VEC_deferred_access_check_gc (X);\
   } while (0)
 extern void gt_ggc_mx_VEC_deferred_access_check_gc (void *);
-#define gt_ggc_m_11tinst_level(X) do { \
-  if (X != NULL) gt_ggc_mx_tinst_level (X);\
-  } while (0)
-extern void gt_ggc_mx_tinst_level (void *);
 #define gt_ggc_m_18sorted_fields_type(X) do { \
   if (X != NULL) gt_ggc_mx_sorted_fields_type (X);\
   } while (0)
@@ -185,6 +181,10 @@
   if (X != NULL) gt_ggc_mx_named_label_entry (X);\
   } while (0)
 extern void gt_ggc_mx_named_label_entry (void *);
+#define gt_ggc_m_32VEC_qualified_typedef_usage_t_gc(X) do { \
+  if (X != NULL) gt_ggc_mx_VEC_qualified_typedef_usage_t_gc (X);\
+  } while (0)
+extern void gt_ggc_mx_VEC_qualified_typedef_usage_t_gc (void *);
 #define gt_ggc_m_14cp_token_cache(X) do { \
   if (X != NULL) gt_ggc_mx_cp_token_cache (X);\
   } while (0)
@@ -221,6 +221,10 @@
   if (X != NULL) gt_ggc_mx_binding_table_s (X);\
   } while (0)
 extern void gt_ggc_mx_binding_table_s (void *);
+#define gt_ggc_m_11tinst_level(X) do { \
+  if (X != NULL) gt_ggc_mx_tinst_level (X);\
+  } while (0)
+extern void gt_ggc_mx_tinst_level (void *);
 #define gt_ggc_m_14VEC_tinfo_s_gc(X) do { \
   if (X != NULL) gt_ggc_mx_VEC_tinfo_s_gc (X);\
   } while (0)
@@ -261,6 +265,10 @@
   if (X != NULL) gt_ggc_mx_scev_info_str (X);\
   } while (0)
 extern void gt_ggc_mx_scev_info_str (void *);
+#define gt_ggc_m_24VEC_mem_addr_template_gc(X) do { \
+  if (X != NULL) gt_ggc_mx_VEC_mem_addr_template_gc (X);\
+  } while (0)
+extern void gt_ggc_mx_VEC_mem_addr_template_gc (void *);
 #define gt_ggc_m_13VEC_gimple_gc(X) do { \
   if (X != NULL) gt_ggc_mx_VEC_gimple_gc (X);\
   } while (0)
@@ -565,6 +573,10 @@
   if (X != NULL) gt_ggc_mx_tree_statement_list_node (X);\
   } while (0)
 extern void gt_ggc_mx_tree_statement_list_node (void *);
+#define gt_ggc_m_9var_ann_d(X) do { \
+  if (X != NULL) gt_ggc_mx_var_ann_d (X);\
+  } while (0)
+extern void gt_ggc_mx_var_ann_d (void *);
 #define gt_ggc_m_9lang_decl(X) do { \
   if (X != NULL) gt_ggc_mx_lang_decl (X);\
   } while (0)
@@ -589,10 +601,6 @@
   if (X != NULL) gt_ggc_mx_VEC_constructor_elt_gc (X);\
   } while (0)
 extern void gt_ggc_mx_VEC_constructor_elt_gc (void *);
-#define gt_ggc_m_10tree_ann_d(X) do { \
-  if (X != NULL) gt_ggc_mx_tree_ann_d (X);\
-  } while (0)
-extern void gt_ggc_mx_tree_ann_d (void *);
 #define gt_ggc_m_17VEC_alias_pair_gc(X) do { \
   if (X != NULL) gt_ggc_mx_VEC_alias_pair_gc (X);\
   } while (0)
@@ -713,14 +721,15 @@
 extern void gt_ggc_m_SP9tree_node17splay_tree_node_s (void *);
 extern void gt_ggc_m_P9tree_nodeP9tree_node17splay_tree_node_s (void *);
 extern void gt_ggc_m_IP9tree_node17splay_tree_node_s (void *);
-extern void gt_ggc_m_P13tree_llvm_map4htab (void *);
+extern void gt_ggc_m_P11tree2WeakVH4htab (void *);
+extern void gt_ggc_m_P9tree2Type4htab (void *);
+extern void gt_ggc_m_P8tree2int4htab (void *);
 extern void gt_ggc_m_P15interface_tuple4htab (void *);
 extern void gt_ggc_m_P16volatilized_type4htab (void *);
 extern void gt_ggc_m_P17string_descriptor4htab (void *);
 extern void gt_ggc_m_P14type_assertion4htab (void *);
 extern void gt_ggc_m_P18treetreehash_entry4htab (void *);
 extern void gt_ggc_m_P17module_htab_entry4htab (void *);
-extern void gt_ggc_m_P16def_pragma_macro4htab (void *);
 extern void gt_ggc_m_P21pending_abstract_type4htab (void *);
 extern void gt_ggc_m_P10spec_entry4htab (void *);
 extern void gt_ggc_m_P16cxx_int_tree_map4htab (void *);
@@ -761,9 +770,19 @@
 /* functions code */
 
 void
-gt_ggc_mx_tree_llvm_map (void *x_p)
+gt_ggc_mx_tree2WeakVH (void *x_p)
+{
+  struct tree2WeakVH * const x = (struct tree2WeakVH *)x_p;
+  if (ggc_test_and_set_mark (x))
+    {
+      gt_ggc_m_9tree_node ((*x).base.from);
+    }
+}
+
+void
+gt_ggc_mx_tree2Type (void *x_p)
 {
-  struct tree_llvm_map * const x = (struct tree_llvm_map *)x_p;
+  struct tree2Type * const x = (struct tree2Type *)x_p;
   if (ggc_test_and_set_mark (x))
     {
       gt_ggc_m_9tree_node ((*x).base.from);
@@ -771,7 +790,17 @@
 }
 
 void
-gt_ggc_m_P13tree_llvm_map4htab (void *x_p)
+gt_ggc_mx_tree2int (void *x_p)
+{
+  struct tree2int * const x = (struct tree2int *)x_p;
+  if (ggc_test_and_set_mark (x))
+    {
+      gt_ggc_m_9tree_node ((*x).base.from);
+    }
+}
+
+void
+gt_ggc_m_P11tree2WeakVH4htab (void *x_p)
 {
   struct htab * const x = (struct htab *)x_p;
   if (ggc_test_and_set_mark (x))
@@ -779,7 +808,39 @@
       if ((*x).entries != NULL) {
         size_t i0;
         for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) {
-          gt_ggc_m_13tree_llvm_map ((*x).entries[i0]);
+          gt_ggc_m_11tree2WeakVH ((*x).entries[i0]);
+        }
+        ggc_mark ((*x).entries);
+      }
+    }
+}
+
+void
+gt_ggc_m_P9tree2Type4htab (void *x_p)
+{
+  struct htab * const x = (struct htab *)x_p;
+  if (ggc_test_and_set_mark (x))
+    {
+      if ((*x).entries != NULL) {
+        size_t i0;
+        for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) {
+          gt_ggc_m_9tree2Type ((*x).entries[i0]);
+        }
+        ggc_mark ((*x).entries);
+      }
+    }
+}
+
+void
+gt_ggc_m_P8tree2int4htab (void *x_p)
+{
+  struct htab * const x = (struct htab *)x_p;
+  if (ggc_test_and_set_mark (x))
+    {
+      if ((*x).entries != NULL) {
+        size_t i0;
+        for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) {
+          gt_ggc_m_8tree2int ((*x).entries[i0]);
         }
         ggc_mark ((*x).entries);
       }
@@ -790,12 +851,28 @@
 
 EXPORTED_CONST struct ggc_cache_tab gt_ggc_rc__gt_cache_h[] = {
   {
-    &llvm_cache,
+    &WeakVHCache,
+    1,
+    sizeof (WeakVHCache),
+    &gt_ggc_mx_tree2WeakVH,
+    NULL,
+    &tree2WeakVH_marked_p
+  },
+  {
+    &TypeCache,
+    1,
+    sizeof (TypeCache),
+    &gt_ggc_mx_tree2Type,
+    NULL,
+    &tree2Type_marked_p
+  },
+  {
+    &intCache,
     1,
-    sizeof (llvm_cache),
-    &gt_ggc_mx_tree_llvm_map,
+    sizeof (intCache),
+    &gt_ggc_mx_tree2int,
     NULL,
-    &tree_llvm_map_marked_p
+    &tree2int_marked_p
   },
   LAST_GGC_CACHE_TAB
 };

Modified: dragonegg/trunk/include/dragonegg/gt-cache-4.6.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/gt-cache-4.6.h?rev=137119&r1=137118&r2=137119&view=diff
==============================================================================
--- dragonegg/trunk/include/dragonegg/gt-cache-4.6.h (original)
+++ dragonegg/trunk/include/dragonegg/gt-cache-4.6.h Tue Aug  9 10:11:51 2011
@@ -21,23 +21,47 @@
 
 /* Allocators for known structs and unions.  */
 
-#define ggc_alloc_tree_llvm_map() ((struct tree_llvm_map *)(ggc_internal_alloc_stat (sizeof (struct tree_llvm_map) MEM_STAT_INFO)))
-#define ggc_alloc_cleared_tree_llvm_map() ((struct tree_llvm_map *)(ggc_internal_cleared_alloc_stat (sizeof (struct tree_llvm_map) MEM_STAT_INFO)))
-#define ggc_alloc_vec_tree_llvm_map(n) ((struct tree_llvm_map *)(ggc_internal_vec_alloc_stat (sizeof (struct tree_llvm_map), n MEM_STAT_INFO)))
-#define ggc_alloc_cleared_vec_tree_llvm_map(n) ((struct tree_llvm_map *)(ggc_internal_cleared_vec_alloc_stat (sizeof (struct tree_llvm_map), n MEM_STAT_INFO)))
-#define ggc_alloc_zone_tree_llvm_map(z) ((struct tree_llvm_map *)(ggc_internal_zone_alloc_stat (z, sizeof (struct tree_llvm_map) MEM_STAT_INFO)))
-#define ggc_alloc_zone_cleared_tree_llvm_map(z) ((struct tree_llvm_map *)(ggc_internal_zone_cleared_alloc_stat (z, sizeof (struct tree_llvm_map) MEM_STAT_INFO)))
-#define ggc_alloc_zone_vec_tree_llvm_map(n, z) ((struct tree_llvm_map *)(ggc_internal_zone_vec_alloc_stat (z, sizeof (struct tree_llvm_map), n MEM_STAT_INFO)))
-#define ggc_alloc_zone_cleared_vec_tree_llvm_map(n, z) ((struct tree_llvm_map *)(ggc_internal_zone_cleared_vec_alloc_stat (z, sizeof (struct tree_llvm_map), n MEM_STAT_INFO)))
+#define ggc_alloc_tree2WeakVH() ((struct tree2WeakVH *)(ggc_internal_alloc_stat (sizeof (struct tree2WeakVH) MEM_STAT_INFO)))
+#define ggc_alloc_cleared_tree2WeakVH() ((struct tree2WeakVH *)(ggc_internal_cleared_alloc_stat (sizeof (struct tree2WeakVH) MEM_STAT_INFO)))
+#define ggc_alloc_vec_tree2WeakVH(n) ((struct tree2WeakVH *)(ggc_internal_vec_alloc_stat (sizeof (struct tree2WeakVH), n MEM_STAT_INFO)))
+#define ggc_alloc_cleared_vec_tree2WeakVH(n) ((struct tree2WeakVH *)(ggc_internal_cleared_vec_alloc_stat (sizeof (struct tree2WeakVH), n MEM_STAT_INFO)))
+#define ggc_alloc_zone_tree2WeakVH(z) ((struct tree2WeakVH *)(ggc_internal_zone_alloc_stat (z, sizeof (struct tree2WeakVH) MEM_STAT_INFO)))
+#define ggc_alloc_zone_cleared_tree2WeakVH(z) ((struct tree2WeakVH *)(ggc_internal_zone_cleared_alloc_stat (z, sizeof (struct tree2WeakVH) MEM_STAT_INFO)))
+#define ggc_alloc_zone_vec_tree2WeakVH(n, z) ((struct tree2WeakVH *)(ggc_internal_zone_vec_alloc_stat (z, sizeof (struct tree2WeakVH), n MEM_STAT_INFO)))
+#define ggc_alloc_zone_cleared_vec_tree2WeakVH(n, z) ((struct tree2WeakVH *)(ggc_internal_zone_cleared_vec_alloc_stat (z, sizeof (struct tree2WeakVH), n MEM_STAT_INFO)))
+#define ggc_alloc_tree2Type() ((struct tree2Type *)(ggc_internal_alloc_stat (sizeof (struct tree2Type) MEM_STAT_INFO)))
+#define ggc_alloc_cleared_tree2Type() ((struct tree2Type *)(ggc_internal_cleared_alloc_stat (sizeof (struct tree2Type) MEM_STAT_INFO)))
+#define ggc_alloc_vec_tree2Type(n) ((struct tree2Type *)(ggc_internal_vec_alloc_stat (sizeof (struct tree2Type), n MEM_STAT_INFO)))
+#define ggc_alloc_cleared_vec_tree2Type(n) ((struct tree2Type *)(ggc_internal_cleared_vec_alloc_stat (sizeof (struct tree2Type), n MEM_STAT_INFO)))
+#define ggc_alloc_zone_tree2Type(z) ((struct tree2Type *)(ggc_internal_zone_alloc_stat (z, sizeof (struct tree2Type) MEM_STAT_INFO)))
+#define ggc_alloc_zone_cleared_tree2Type(z) ((struct tree2Type *)(ggc_internal_zone_cleared_alloc_stat (z, sizeof (struct tree2Type) MEM_STAT_INFO)))
+#define ggc_alloc_zone_vec_tree2Type(n, z) ((struct tree2Type *)(ggc_internal_zone_vec_alloc_stat (z, sizeof (struct tree2Type), n MEM_STAT_INFO)))
+#define ggc_alloc_zone_cleared_vec_tree2Type(n, z) ((struct tree2Type *)(ggc_internal_zone_cleared_vec_alloc_stat (z, sizeof (struct tree2Type), n MEM_STAT_INFO)))
+#define ggc_alloc_tree2int() ((struct tree2int *)(ggc_internal_alloc_stat (sizeof (struct tree2int) MEM_STAT_INFO)))
+#define ggc_alloc_cleared_tree2int() ((struct tree2int *)(ggc_internal_cleared_alloc_stat (sizeof (struct tree2int) MEM_STAT_INFO)))
+#define ggc_alloc_vec_tree2int(n) ((struct tree2int *)(ggc_internal_vec_alloc_stat (sizeof (struct tree2int), n MEM_STAT_INFO)))
+#define ggc_alloc_cleared_vec_tree2int(n) ((struct tree2int *)(ggc_internal_cleared_vec_alloc_stat (sizeof (struct tree2int), n MEM_STAT_INFO)))
+#define ggc_alloc_zone_tree2int(z) ((struct tree2int *)(ggc_internal_zone_alloc_stat (z, sizeof (struct tree2int) MEM_STAT_INFO)))
+#define ggc_alloc_zone_cleared_tree2int(z) ((struct tree2int *)(ggc_internal_zone_cleared_alloc_stat (z, sizeof (struct tree2int) MEM_STAT_INFO)))
+#define ggc_alloc_zone_vec_tree2int(n, z) ((struct tree2int *)(ggc_internal_zone_vec_alloc_stat (z, sizeof (struct tree2int), n MEM_STAT_INFO)))
+#define ggc_alloc_zone_cleared_vec_tree2int(n, z) ((struct tree2int *)(ggc_internal_zone_cleared_vec_alloc_stat (z, sizeof (struct tree2int), n MEM_STAT_INFO)))
 
 /* Allocators for known typedefs.  */
 
 /* GC marker procedures.  */
 /* macros and declarations */
-#define gt_ggc_m_13tree_llvm_map(X) do { \
-  if (X != NULL) gt_ggc_mx_tree_llvm_map (X);\
+#define gt_ggc_m_11tree2WeakVH(X) do { \
+  if (X != NULL) gt_ggc_mx_tree2WeakVH (X);\
   } while (0)
-extern void gt_ggc_mx_tree_llvm_map (void *);
+extern void gt_ggc_mx_tree2WeakVH (void *);
+#define gt_ggc_m_9tree2Type(X) do { \
+  if (X != NULL) gt_ggc_mx_tree2Type (X);\
+  } while (0)
+extern void gt_ggc_mx_tree2Type (void *);
+#define gt_ggc_m_8tree2int(X) do { \
+  if (X != NULL) gt_ggc_mx_tree2int (X);\
+  } while (0)
+extern void gt_ggc_mx_tree2int (void *);
 #define gt_ggc_m_15c_inline_static(X) do { \
   if (X != NULL) gt_ggc_mx_c_inline_static (X);\
   } while (0)
@@ -130,6 +154,10 @@
   if (X != NULL) gt_ggc_mx_binding_level (X);\
   } while (0)
 extern void gt_ggc_mx_binding_level (void *);
+#define gt_ggc_m_23VEC_pending_noexcept_gc(X) do { \
+  if (X != NULL) gt_ggc_mx_VEC_pending_noexcept_gc (X);\
+  } while (0)
+extern void gt_ggc_mx_VEC_pending_noexcept_gc (void *);
 #define gt_ggc_m_9opt_stack(X) do { \
   if (X != NULL) gt_ggc_mx_opt_stack (X);\
   } while (0)
@@ -202,10 +230,6 @@
   if (X != NULL) gt_ggc_mx_VEC_deferred_access_gc (X);\
   } while (0)
 extern void gt_ggc_mx_VEC_deferred_access_gc (void *);
-#define gt_ggc_m_17VEC_spec_entry_gc(X) do { \
-  if (X != NULL) gt_ggc_mx_VEC_spec_entry_gc (X);\
-  } while (0)
-extern void gt_ggc_mx_VEC_spec_entry_gc (void *);
 #define gt_ggc_m_10spec_entry(X) do { \
   if (X != NULL) gt_ggc_mx_spec_entry (X);\
   } while (0)
@@ -454,18 +478,22 @@
   if (X != NULL) gt_ggc_mx_VEC_deferred_locations_gc (X);\
   } while (0)
 extern void gt_ggc_mx_VEC_deferred_locations_gc (void *);
-#define gt_ggc_m_18dw_loc_list_struct(X) do { \
-  if (X != NULL) gt_ggc_mx_dw_loc_list_struct (X);\
+#define gt_ggc_m_17VEC_dw_fde_ref_gc(X) do { \
+  if (X != NULL) gt_ggc_mx_VEC_dw_fde_ref_gc (X);\
   } while (0)
-extern void gt_ggc_mx_dw_loc_list_struct (void *);
+extern void gt_ggc_mx_VEC_dw_fde_ref_gc (void *);
+#define gt_ggc_m_24reg_saved_in_data_struct(X) do { \
+  if (X != NULL) gt_ggc_mx_reg_saved_in_data_struct (X);\
+  } while (0)
+extern void gt_ggc_mx_reg_saved_in_data_struct (void *);
+#define gt_ggc_m_17dw_cfi_row_struct(X) do { \
+  if (X != NULL) gt_ggc_mx_dw_cfi_row_struct (X);\
+  } while (0)
+extern void gt_ggc_mx_dw_cfi_row_struct (void *);
 #define gt_ggc_m_15dwarf_file_data(X) do { \
   if (X != NULL) gt_ggc_mx_dwarf_file_data (X);\
   } while (0)
 extern void gt_ggc_mx_dwarf_file_data (void *);
-#define gt_ggc_m_15queued_reg_save(X) do { \
-  if (X != NULL) gt_ggc_mx_queued_reg_save (X);\
-  } while (0)
-extern void gt_ggc_mx_queued_reg_save (void *);
 #define gt_ggc_m_20indirect_string_node(X) do { \
   if (X != NULL) gt_ggc_mx_indirect_string_node (X);\
   } while (0)
@@ -474,14 +502,14 @@
   if (X != NULL) gt_ggc_mx_VEC_dw_cfi_ref_gc (X);\
   } while (0)
 extern void gt_ggc_mx_VEC_dw_cfi_ref_gc (void *);
+#define gt_ggc_m_18dw_loc_list_struct(X) do { \
+  if (X != NULL) gt_ggc_mx_dw_loc_list_struct (X);\
+  } while (0)
+extern void gt_ggc_mx_dw_loc_list_struct (void *);
 #define gt_ggc_m_19dw_loc_descr_struct(X) do { \
   if (X != NULL) gt_ggc_mx_dw_loc_descr_struct (X);\
   } while (0)
 extern void gt_ggc_mx_dw_loc_descr_struct (void *);
-#define gt_ggc_m_13dw_fde_struct(X) do { \
-  if (X != NULL) gt_ggc_mx_dw_fde_struct (X);\
-  } while (0)
-extern void gt_ggc_mx_dw_fde_struct (void *);
 #define gt_ggc_m_13dw_cfi_struct(X) do { \
   if (X != NULL) gt_ggc_mx_dw_cfi_struct (X);\
   } while (0)
@@ -610,6 +638,10 @@
   if (X != NULL) gt_ggc_mx_VEC_temp_slot_p_gc (X);\
   } while (0)
 extern void gt_ggc_mx_VEC_temp_slot_p_gc (void *);
+#define gt_ggc_m_13dw_fde_struct(X) do { \
+  if (X != NULL) gt_ggc_mx_dw_fde_struct (X);\
+  } while (0)
+extern void gt_ggc_mx_dw_fde_struct (void *);
 #define gt_ggc_m_9temp_slot(X) do { \
   if (X != NULL) gt_ggc_mx_temp_slot (X);\
   } while (0)
@@ -634,6 +666,10 @@
   if (X != NULL) gt_ggc_mx_libfunc_entry (X);\
   } while (0)
 extern void gt_ggc_mx_libfunc_entry (void *);
+#define gt_ggc_m_12tree_vec_map(X) do { \
+  if (X != NULL) gt_ggc_mx_tree_vec_map (X);\
+  } while (0)
+extern void gt_ggc_mx_tree_vec_map (void *);
 #define gt_ggc_m_17tree_priority_map(X) do { \
   if (X != NULL) gt_ggc_mx_tree_priority_map (X);\
   } while (0)
@@ -798,7 +834,9 @@
   if (X != NULL) gt_ggc_mx_line_maps (X);\
   } while (0)
 extern void gt_ggc_mx_line_maps (void *);
-extern void gt_ggc_m_P13tree_llvm_map4htab (void *);
+extern void gt_ggc_m_P11tree2WeakVH4htab (void *);
+extern void gt_ggc_m_P9tree2Type4htab (void *);
+extern void gt_ggc_m_P8tree2int4htab (void *);
 extern void gt_ggc_m_II17splay_tree_node_s (void *);
 extern void gt_ggc_m_SP9tree_node17splay_tree_node_s (void *);
 extern void gt_ggc_m_P9tree_nodeP9tree_node17splay_tree_node_s (void *);
@@ -825,6 +863,7 @@
 extern void gt_ggc_m_P12object_block4htab (void *);
 extern void gt_ggc_m_P7section4htab (void *);
 extern void gt_ggc_m_P17tree_priority_map4htab (void *);
+extern void gt_ggc_m_P12tree_vec_map4htab (void *);
 extern void gt_ggc_m_P13tree_decl_map4htab (void *);
 extern void gt_ggc_m_P9type_hash4htab (void *);
 extern void gt_ggc_m_P23temp_slot_address_entry4htab (void *);
@@ -832,12 +871,12 @@
 extern void gt_ggc_m_P9reg_attrs4htab (void *);
 extern void gt_ggc_m_P9mem_attrs4htab (void *);
 extern void gt_ggc_m_P7rtx_def4htab (void *);
-extern void gt_ggc_m_SP9tree_node12splay_tree_s (void *);
 extern void gt_ggc_m_P22cached_dw_loc_list_def4htab (void *);
 extern void gt_ggc_m_P16var_loc_list_def4htab (void *);
 extern void gt_ggc_m_P10die_struct4htab (void *);
 extern void gt_ggc_m_P15dwarf_file_data4htab (void *);
 extern void gt_ggc_m_P20indirect_string_node4htab (void *);
+extern void gt_ggc_m_SP9tree_node12splay_tree_s (void *);
 extern void gt_ggc_m_P11cgraph_node4htab (void *);
 extern void gt_ggc_m_II12splay_tree_s (void *);
 extern void gt_ggc_m_P11cgraph_edge4htab (void *);
@@ -849,9 +888,9 @@
 /* functions code */
 
 void
-gt_ggc_mx_tree_llvm_map (void *x_p)
+gt_ggc_mx_tree2WeakVH (void *x_p)
 {
-  struct tree_llvm_map * const x = (struct tree_llvm_map *)x_p;
+  struct tree2WeakVH * const x = (struct tree2WeakVH *)x_p;
   if (ggc_test_and_set_mark (x))
     {
       gt_ggc_m_9tree_node ((*x).base.from);
@@ -859,7 +898,27 @@
 }
 
 void
-gt_ggc_m_P13tree_llvm_map4htab (void *x_p)
+gt_ggc_mx_tree2Type (void *x_p)
+{
+  struct tree2Type * const x = (struct tree2Type *)x_p;
+  if (ggc_test_and_set_mark (x))
+    {
+      gt_ggc_m_9tree_node ((*x).base.from);
+    }
+}
+
+void
+gt_ggc_mx_tree2int (void *x_p)
+{
+  struct tree2int * const x = (struct tree2int *)x_p;
+  if (ggc_test_and_set_mark (x))
+    {
+      gt_ggc_m_9tree_node ((*x).base.from);
+    }
+}
+
+void
+gt_ggc_m_P11tree2WeakVH4htab (void *x_p)
 {
   struct htab * const x = (struct htab *)x_p;
   if (ggc_test_and_set_mark (x))
@@ -867,7 +926,39 @@
       if ((*x).entries != NULL) {
         size_t i0;
         for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) {
-          gt_ggc_m_13tree_llvm_map ((*x).entries[i0]);
+          gt_ggc_m_11tree2WeakVH ((*x).entries[i0]);
+        }
+        ggc_mark ((*x).entries);
+      }
+    }
+}
+
+void
+gt_ggc_m_P9tree2Type4htab (void *x_p)
+{
+  struct htab * const x = (struct htab *)x_p;
+  if (ggc_test_and_set_mark (x))
+    {
+      if ((*x).entries != NULL) {
+        size_t i0;
+        for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) {
+          gt_ggc_m_9tree2Type ((*x).entries[i0]);
+        }
+        ggc_mark ((*x).entries);
+      }
+    }
+}
+
+void
+gt_ggc_m_P8tree2int4htab (void *x_p)
+{
+  struct htab * const x = (struct htab *)x_p;
+  if (ggc_test_and_set_mark (x))
+    {
+      if ((*x).entries != NULL) {
+        size_t i0;
+        for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) {
+          gt_ggc_m_8tree2int ((*x).entries[i0]);
         }
         ggc_mark ((*x).entries);
       }
@@ -878,12 +969,28 @@
 
 EXPORTED_CONST struct ggc_cache_tab gt_ggc_rc__gt_cache_h[] = {
   {
-    &llvm_cache,
+    &WeakVHCache,
+    1,
+    sizeof (WeakVHCache),
+    &gt_ggc_mx_tree2WeakVH,
+    NULL,
+    &tree2WeakVH_marked_p
+  },
+  {
+    &TypeCache,
+    1,
+    sizeof (TypeCache),
+    &gt_ggc_mx_tree2Type,
+    NULL,
+    &tree2Type_marked_p
+  },
+  {
+    &intCache,
     1,
-    sizeof (llvm_cache),
-    &gt_ggc_mx_tree_llvm_map,
+    sizeof (intCache),
+    &gt_ggc_mx_tree2int,
     NULL,
-    &tree_llvm_map_marked_p
+    &tree2int_marked_p
   },
   LAST_GGC_CACHE_TAB
 };

Modified: dragonegg/trunk/src/Backend.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Backend.cpp?rev=137119&r1=137118&r2=137119&view=diff
==============================================================================
--- dragonegg/trunk/src/Backend.cpp (original)
+++ dragonegg/trunk/src/Backend.cpp Tue Aug  9 10:11:51 2011
@@ -22,9 +22,7 @@
 //===----------------------------------------------------------------------===//
 
 // Plugin headers
-extern "C" {
-#include "dragonegg/cache.h"
-}
+#include "dragonegg/Cache.h"
 #include "dragonegg/Constants.h"
 #include "dragonegg/Debug.h"
 #include "dragonegg/OS.h"
@@ -134,13 +132,14 @@
 /// set_decl_llvm - Remember the LLVM value for a GCC declaration.
 Value *set_decl_llvm (tree t, Value *V) {
   assert(HAS_RTL_P(t) && "Expected a declaration with RTL!");
-  return (Value *)llvm_set_cached(t, V);
+  setCachedValue(t, V);
+  return V;
 }
 
 /// get_decl_llvm - Retrieve the LLVM value for a GCC declaration, or NULL.
 Value *get_decl_llvm(tree t) {
   assert(HAS_RTL_P(t) && "Expected a declaration with RTL!");
-  return (Value *)llvm_get_cached(t);
+  return getCachedValue(t);
 }
 
 /// set_decl_index - Associate a non-negative number with the given GCC
@@ -148,9 +147,7 @@
 int set_decl_index(tree t, int i) {
   assert(!HAS_RTL_P(t) && "Expected a declaration without RTL!");
   assert(i >= 0 && "Negative indices not allowed!");
-  // In order to use zero as a special value (see get_decl_index) map the range
-  // 0 .. INT_MAX to -1 .. INT_MIN.
-  llvm_set_cached(t, (void *)(intptr_t)(-i - 1));
+  setCachedInteger(t, i);
   return i;
 }
 
@@ -158,9 +155,10 @@
 /// declaration.  Returns a negative value if no such association has been made.
 int get_decl_index(tree t) {
   assert(!HAS_RTL_P(t) && "Expected a declaration without RTL!");
-  // Map the range -1 .. INT_MIN back to 0 .. INT_MAX (see set_decl_index) and
-  // send 0 (aka void) to -1.
-  return -(1 + (int)(intptr_t)llvm_get_cached(t));
+  int Idx;
+  if (getCachedInteger(t, Idx))
+    return Idx;
+  return -1;
 }
 
 /// changeLLVMConstant - Replace Old with New everywhere, updating all maps
@@ -189,7 +187,7 @@
       StaticDtors[i].first = New;
   }
 
-  llvm_replace_cached(Old, New);
+  // No need to update the value cache - it autoupdates on RAUW.
 }
 
 /// handleVisibility - Forward decl visibility style to global.

Copied: dragonegg/trunk/src/Cache.cpp (from r137045, dragonegg/trunk/src/cache.c)
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Cache.cpp?p2=dragonegg/trunk/src/Cache.cpp&p1=dragonegg/trunk/src/cache.c&r1=137045&r2=137119&rev=137119&view=diff
==============================================================================
--- dragonegg/trunk/src/cache.c (original)
+++ dragonegg/trunk/src/Cache.cpp Tue Aug  9 10:11:51 2011
@@ -1,139 +1,239 @@
-/* Caching values "in" trees
-Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+//==----------- Cache.h - Caching values "in" GCC trees ----------*- C++ -*-==//
+//
+// Copyright (C) 2009, 2010, 2011  Duncan Sands.
+//
+// This file is part of DragonEgg.
+//
+// DragonEgg 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, or (at your option) any later
+// version.
+//
+// DragonEgg is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+// You should have received a copy of the GNU General Public License along
+// with DragonEgg; see the file COPYING.  If not, write to the Free Software
+// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+//
+//===----------------------------------------------------------------------===//
+// This code lets you associate values with a tree, as if it were cached inside
+// the tree: if the tree is garbage collected and reallocated, then the cached
+// value will have been cleared.
+//===----------------------------------------------------------------------===//
+
+// Plugin headers.
+#include "dragonegg/Cache.h"
+
+// LLVM headers
+#include "llvm/Support/ValueHandle.h"
+
+// System headers
+#include <cassert>
+#include <gmp.h>
 
-This file is part of GCC.
-
-GCC 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, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
-
-/*===----------------------------------------------------------------------===
-   This code lets you to associate a void* with a tree, as if it were cached
-   inside the tree: if the tree is garbage collected and reallocated, then the
-   cached value will have been cleared.
-  ===----------------------------------------------------------------------===*/
-
-/* Plugin headers.  */
-#include "dragonegg/cache.h"
-
-/* GCC headers.  */
+// GCC headers
+extern "C" {
 #include "config.h"
+// Stop GCC declaring 'getopt' as it can clash with the system's declaration.
+#undef HAVE_DECL_GETOPT
 #include "system.h"
 #include "coretypes.h"
 #include "target.h"
 #include "tree.h"
+
 #include "ggc.h"
+}
+
+using namespace llvm;
+
+// Hash table mapping trees to integers.
 
-struct GTY(()) tree_llvm_map {
+struct GTY(()) tree2int {
   struct tree_map_base base;
-  const void * GTY((skip)) val;
+  int GTY((skip)) val;
 };
 
-#define tree_llvm_map_eq tree_map_base_eq
-#define tree_llvm_map_hash tree_map_base_hash
-#define tree_llvm_map_marked_p tree_map_base_marked_p
-
-static GTY ((if_marked ("tree_llvm_map_marked_p"),
-             param_is(struct tree_llvm_map)))
-  htab_t llvm_cache;
+#define tree2int_eq tree_map_base_eq
+#define tree2int_hash tree_map_base_hash
+#define tree2int_marked_p tree_map_base_marked_p
+
+static GTY((if_marked("tree2int_marked_p"),
+            param_is(struct tree2int)))
+  htab_t intCache;
+
+
+// Hash table mapping trees to Type*.
+
+// Forward declare Type for the benefit of gengtype.
+#ifndef IN_GCC
+struct Type;
+#endif
+struct GTY(()) tree2Type {
+  struct tree_map_base base;
+#ifndef IN_GCC
+  struct
+#endif
+  Type *GTY((skip)) Ty;
+};
+
+#define tree2Type_eq tree_map_base_eq
+#define tree2Type_hash tree_map_base_hash
+#define tree2Type_marked_p tree_map_base_marked_p
+
+static GTY((if_marked("tree2Type_marked_p"),
+            param_is(struct tree2Type)))
+  htab_t TypeCache;
+
+
+// Hash table mapping trees to WeakVH.
+
+// Forward declare WeakVH for the benefit of gengtype.
+#ifndef IN_GCC
+struct WeakVH;
+#endif
+struct GTY(()) tree2WeakVH {
+  struct tree_map_base base;
+#ifndef IN_GCC
+  struct
+#endif
+  WeakVH GTY((skip)) V;
+};
+
+#define tree2WeakVH_eq tree_map_base_eq
+#define tree2WeakVH_hash tree_map_base_hash
+#define tree2WeakVH_marked_p tree_map_base_marked_p
+
+static GTY((if_marked("tree2WeakVH_marked_p"),
+            param_is(struct tree2WeakVH)))
+  htab_t WeakVHCache;
+
 
-/* Garbage collector header.  */
+// Include the garbage collector header.
+extern "C" {
 #if (GCC_MINOR > 5)
 #include "dragonegg/gt-cache-4.6.h"
 #else
 #include "dragonegg/gt-cache-4.5.h"
 #endif
+}
+
+bool getCachedInteger(tree t, int &Val) {
+  if (!intCache)
+    return false;
+  tree_map_base in = { t };
+  tree2int *h = (tree2int *)htab_find(intCache, &in);
+  if (!h)
+    return false;
+  Val = h->val;
+  return true;
+}
+
+void setCachedInteger(tree t, int Val) {
+  if (!intCache)
+    intCache = htab_create_ggc(1024, tree2int_hash, tree2int_eq, 0);
+
+  tree_map_base in = { t };
+  tree2int **slot = (tree2int **)htab_find_slot(intCache, &in, INSERT);
+  assert(slot && "Failed to create hash table slot!");
+
+  if (!*slot) {
+    *slot =
+#if (GCC_MINOR > 5)
+      ggc_alloc_tree2int();
+#else
+      GGC_NEW(struct tree2int);
+#endif
+    (*slot)->base.from = t;
+  }
+
+  (*slot)->val = Val;
+}
 
-/* llvm_get_cached - Returns the value associated with the tree, or NULL.  */
-const void *llvm_get_cached(union tree_node *tree) {
-  struct tree_llvm_map *h;
-  struct tree_map_base in;
-
-  if (!llvm_cache)
-    return NULL;
-
-  in.from = tree;
-  h = (struct tree_llvm_map *) htab_find(llvm_cache, &in);
-  return h ? h->val : NULL;
-}
-
-/* llvm_set_cached - Associates the given value with the tree (and returns it).
-   To delete an association, pass a NULL value here.  */
-const void *llvm_set_cached(union tree_node *tree, const void *val) {
-  struct tree_llvm_map **slot;
-  struct tree_map_base in;
+Type *getCachedType(tree t) {
+  if (!TypeCache)
+    return 0;
+  tree_map_base in = { t };
+  tree2Type *h = (tree2Type *)htab_find(TypeCache, &in);
+  return h ? h->Ty : 0;
+}
 
-  in.from = tree;
+void setCachedType(tree t, Type *Ty) {
+  tree_map_base in = { t };
 
   /* If deleting, remove the slot.  */
-  if (val == NULL) {
-    if (llvm_cache)
-      htab_remove_elt(llvm_cache, &in);
-    return NULL;
+  if (!Ty) {
+    if (TypeCache)
+      htab_remove_elt(TypeCache, &in);
+    return;
   }
 
-  if (!llvm_cache)
-    llvm_cache = htab_create_ggc(1024, tree_llvm_map_hash, tree_llvm_map_eq, NULL);
+  if (!TypeCache)
+    TypeCache = htab_create_ggc(1024, tree2Type_hash, tree2Type_eq, 0);
 
-  slot = (struct tree_llvm_map **) htab_find_slot(llvm_cache, &in, INSERT);
-  gcc_assert(slot);
+  tree2Type **slot = (tree2Type **)htab_find_slot(TypeCache, &in, INSERT);
+  assert(slot && "Failed to create hash table slot!");
 
   if (!*slot) {
     *slot =
 #if (GCC_MINOR > 5)
-      ggc_alloc_tree_llvm_map();
+      ggc_alloc_tree2Type();
 #else
-      GGC_NEW(struct tree_llvm_map);
+      GGC_NEW(struct tree2Type);
 #endif
-    (*slot)->base.from = tree;
+    (*slot)->base.from = t;
   }
 
-  (*slot)->val = val;
+  (*slot)->Ty = Ty;
+}
 
-  return val;
+/// getCachedValue - Returns the value associated with the given GCC tree, or
+/// null if none.
+Value *getCachedValue(tree t) {
+  if (!WeakVHCache)
+    return 0;
+  tree_map_base in = { t };
+  tree2WeakVH *h = (tree2WeakVH *)htab_find(WeakVHCache, &in);
+  return h ? h->V : 0;
 }
 
-struct update {
-  const void *old_val;
-  const void *new_val;
-};
+static void DestructWeakVH(void *p) {
+  ((WeakVH*)&((tree2WeakVH*)p)->V)->~WeakVH();
+}
 
-/* replace - If the current value for the slot matches old_val, then replace
-   it with new_val, or delete it if new_val is NULL.  */
-static int replace(void **slot, void *data) {
-  struct tree_llvm_map *entry = *(struct tree_llvm_map **)slot;
-  struct update *u = (struct update *)data;
-
-  if (entry->val != u->old_val)
-    return 1;
-
-  if (u->new_val != NULL)
-    entry->val = u->new_val;
-  else
-    htab_clear_slot(llvm_cache, slot);
-
-  return 1;
-}
-
-/* llvm_replace_cached - Replaces all occurrences of old_val with new_val.  */
-void llvm_replace_cached(const void *old_val, const void *new_val) {
-  struct update u;
-  u.old_val = old_val;
-  u.new_val = new_val;
+/// setCachedValue - Associates the given value (which may be null) with the
+/// given GCC tree.  The association is removed if tree is garbage collected
+/// or the value deleted.
+void setCachedValue(tree t, Value *V) {
+  tree_map_base in = { t };
+
+  // If deleting, remove the slot.
+  if (!V) {
+    if (WeakVHCache)
+      htab_remove_elt(WeakVHCache, &in);
+    return;
+  }
 
-  if (!llvm_cache || old_val == NULL)
+  if (!WeakVHCache)
+    WeakVHCache = htab_create_ggc(1024, tree2WeakVH_hash, tree2WeakVH_eq,
+                                  DestructWeakVH);
+
+  tree2WeakVH **slot = (tree2WeakVH **)htab_find_slot(WeakVHCache, &in, INSERT);
+  assert(slot && "Failed to create hash table slot!");
+
+  if (*slot) {
+    (*slot)->V = V;
     return;
+  }
 
-  htab_traverse(llvm_cache, replace, &u);
+  *slot =
+#if (GCC_MINOR > 5)
+    ggc_alloc_tree2WeakVH();
+#else
+    GGC_NEW(struct tree2WeakVH);
+#endif
+  (*slot)->base.from = t;
+  WeakVH *W = new(&(*slot)->V) WeakVH(V);
+  assert(W == &(*slot)->V && "Pointer was displaced!");
 }

Modified: dragonegg/trunk/src/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Constants.cpp?rev=137119&r1=137118&r2=137119&view=diff
==============================================================================
--- dragonegg/trunk/src/Constants.cpp (original)
+++ dragonegg/trunk/src/Constants.cpp Tue Aug  9 10:11:51 2011
@@ -21,15 +21,13 @@
 //===----------------------------------------------------------------------===//
 
 // Plugin headers
+#include "dragonegg/Cache.h"
 #include "dragonegg/Constants.h"
 #include "dragonegg/Internals.h"
 #include "dragonegg/Trees.h"
 #include "dragonegg/Types.h"
 #include "dragonegg/ADT/IntervalList.h"
 #include "dragonegg/ADT/Range.h"
-extern "C" {
-#include "dragonegg/cache.h"
-}
 
 // LLVM headers
 #include "llvm/GlobalVariable.h"
@@ -1277,7 +1275,7 @@
 /// ConvertInitializerImpl - Implementation of ConvertInitializer.
 static Constant *ConvertInitializerImpl(tree exp, TargetFolder &Folder) {
   // If we already converted the initializer then return the cached copy.
-  if (Constant *C = (Constant *)llvm_get_cached(exp))
+  if (Constant *C = cast_or_null<Constant>(getCachedValue(exp)))
     return C;
 
   Constant *Init;
@@ -1344,7 +1342,7 @@
 
   // Cache the result of converting the initializer since the same tree is often
   // converted multiple times.
-  llvm_set_cached(exp, Init);
+  setCachedValue(exp, Init);
 
   return Init;
 }

Modified: dragonegg/trunk/src/Types.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Types.cpp?rev=137119&r1=137118&r2=137119&view=diff
==============================================================================
--- dragonegg/trunk/src/Types.cpp (original)
+++ dragonegg/trunk/src/Types.cpp Tue Aug  9 10:11:51 2011
@@ -23,11 +23,9 @@
 
 // Plugin headers
 #include "dragonegg/ABI.h"
+#include "dragonegg/Cache.h"
 #include "dragonegg/Trees.h"
 #include "dragonegg/Types.h"
-extern "C" {
-#include "dragonegg/cache.h"
-}
 
 // LLVM headers
 #include "llvm/Module.h"
@@ -306,7 +304,7 @@
 //                   Matching LLVM types with GCC trees
 //===----------------------------------------------------------------------===//
 
-// llvm_get_type/llvm_set_type - Associate an LLVM type with each TREE type.
+// llvm_set_type - Associate an LLVM type with each TREE type.
 // These are lazily computed by ConvertType.
 
 static Type *llvm_set_type(tree Tr, Type *Ty) {
@@ -329,16 +327,8 @@
   }
 #endif
 
-  return (Type *)llvm_set_cached(Tr, Ty);
-}
-
-static Type *llvm_get_type(tree Tr) {
-  assert(TYPE_P(Tr) && "Expected a gcc type!");
-  return (Type *)llvm_get_cached(Tr);
-}
-
-static bool llvm_has_type(tree Tr) {
-  return llvm_get_type(Tr) != 0;
+  setCachedType(Tr, Ty);
+  return Ty;
 }
 
 
@@ -1460,8 +1450,8 @@
 static Type *ConvertRECORD(tree type) {
   assert(TYPE_SIZE(type) && "Incomplete types should be handled elsewhere!");
 
-  assert(llvm_get_type(type) && isa<StructType>(llvm_get_type(type)) &&
-         cast<StructType>(llvm_get_type(type))->isOpaque() &&
+  assert(getCachedType(type) && isa<StructType>(getCachedType(type)) &&
+         cast<StructType>(getCachedType(type))->isOpaque() &&
          "Incorrect placeholder for struct type!");
 
   // Record those fields which will be converted to LLVM fields.
@@ -1552,7 +1542,7 @@
   } else
     Info->RemoveExtraBytes();
 
-  StructType *ResultTy = cast<StructType>(llvm_get_type(type));
+  StructType *ResultTy = cast<StructType>(getCachedType(type));
   Info->fillInLLVMType(ResultTy);
 
   return ResultTy;
@@ -1605,7 +1595,7 @@
   case POINTER_TYPE:
   case REFERENCE_TYPE:
     // Converting these types may recurse unless the type was already converted.
-    return !llvm_has_type(type);
+    return getCachedType(type) == 0;
 
   case QUAL_UNION_TYPE:
   case RECORD_TYPE:
@@ -1620,7 +1610,7 @@
       return false;
 
     // If the type was not previously converted then converting it may recurse.
-    Type *Ty = llvm_get_type(type);
+    Type *Ty = getCachedType(type);
     if (!Ty)
       return true;
 
@@ -1740,7 +1730,7 @@
   case REFERENCE_TYPE: {
     // If these types are not recursive it can only be because they were already
     // converted and we can safely return the result of the previous conversion.
-    Type *Ty = llvm_get_type(type);
+    Type *Ty = getCachedType(type);
     assert(Ty && "Type not already converted!");
     return Ty;
   }
@@ -1757,7 +1747,7 @@
   }
 
   case COMPLEX_TYPE: {
-    if (Type *Ty = llvm_get_type(type)) return Ty;
+    if (Type *Ty = getCachedType(type)) return Ty;
     Type *Ty = ConvertNonRecursiveType(TYPE_MAIN_VARIANT(TREE_TYPE(type)));
     Ty = StructType::get(Ty, Ty, NULL);
     return llvm_set_type(type, Ty);
@@ -1790,7 +1780,7 @@
   case QUAL_UNION_TYPE:
   case UNION_TYPE:
     // If the type was already converted then return the already computed type.
-    if (Type *Ty = llvm_get_type(type)) return Ty;
+    if (Type *Ty = getCachedType(type)) return Ty;
 
     // Otherwise this must be an incomplete type - return an opaque struct.
     assert(!TYPE_SIZE(type) && "Expected an incomplete type!");
@@ -1798,7 +1788,7 @@
                                                      getDescriptiveName(type)));
 
   case VECTOR_TYPE: {
-    if (Type *Ty = llvm_get_type(type)) return Ty;
+    if (Type *Ty = getCachedType(type)) return Ty;
     Type *Ty;
     // LLVM does not support vectors of pointers, so turn any pointers into
     // integers.
@@ -1894,7 +1884,7 @@
       if (TREE_CODE(pointee) == QUAL_UNION_TYPE ||
           TREE_CODE(pointee) == RECORD_TYPE ||
           TREE_CODE(pointee) == UNION_TYPE)
-        PointeeTy = llvm_get_type(pointee);
+        PointeeTy = getCachedType(pointee);
       else
         PointeeTy = StructType::get(Context);
     }
@@ -1979,12 +1969,12 @@
       if (TREE_CODE(some_type) != QUAL_UNION_TYPE &&
           TREE_CODE(some_type) != RECORD_TYPE &&
           TREE_CODE(some_type) != UNION_TYPE) {
-        assert(!llvm_has_type(some_type) && "Type already converted!");
+        assert(!getCachedType(some_type) && "Type already converted!");
         continue;
       }
       // If the type used to be incomplete then a opaque struct placeholder may
       // have been created for it already.
-      Type *Ty = llvm_get_type(some_type);
+      Type *Ty = getCachedType(some_type);
       if (Ty) {
         assert(isa<StructType>(Ty) && cast<StructType>(Ty)->isOpaque() &&
                "Recursive struct already fully converted!");
@@ -2012,7 +2002,7 @@
 
   // At this point every type reachable from this one has been converted, and
   // the conversion results cached.  Return the value computed for the type.
-  Type *Ty = llvm_get_type(type);
+  Type *Ty = getCachedType(type);
   assert(Ty && "Type not converted!");
   return Ty;
 }

Removed: dragonegg/trunk/src/cache.c
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/cache.c?rev=137118&view=auto
==============================================================================
--- dragonegg/trunk/src/cache.c (original)
+++ dragonegg/trunk/src/cache.c (removed)
@@ -1,139 +0,0 @@
-/* Caching values "in" trees
-Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC 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, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
-
-/*===----------------------------------------------------------------------===
-   This code lets you to associate a void* with a tree, as if it were cached
-   inside the tree: if the tree is garbage collected and reallocated, then the
-   cached value will have been cleared.
-  ===----------------------------------------------------------------------===*/
-
-/* Plugin headers.  */
-#include "dragonegg/cache.h"
-
-/* GCC headers.  */
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "target.h"
-#include "tree.h"
-#include "ggc.h"
-
-struct GTY(()) tree_llvm_map {
-  struct tree_map_base base;
-  const void * GTY((skip)) val;
-};
-
-#define tree_llvm_map_eq tree_map_base_eq
-#define tree_llvm_map_hash tree_map_base_hash
-#define tree_llvm_map_marked_p tree_map_base_marked_p
-
-static GTY ((if_marked ("tree_llvm_map_marked_p"),
-             param_is(struct tree_llvm_map)))
-  htab_t llvm_cache;
-
-/* Garbage collector header.  */
-#if (GCC_MINOR > 5)
-#include "dragonegg/gt-cache-4.6.h"
-#else
-#include "dragonegg/gt-cache-4.5.h"
-#endif
-
-/* llvm_get_cached - Returns the value associated with the tree, or NULL.  */
-const void *llvm_get_cached(union tree_node *tree) {
-  struct tree_llvm_map *h;
-  struct tree_map_base in;
-
-  if (!llvm_cache)
-    return NULL;
-
-  in.from = tree;
-  h = (struct tree_llvm_map *) htab_find(llvm_cache, &in);
-  return h ? h->val : NULL;
-}
-
-/* llvm_set_cached - Associates the given value with the tree (and returns it).
-   To delete an association, pass a NULL value here.  */
-const void *llvm_set_cached(union tree_node *tree, const void *val) {
-  struct tree_llvm_map **slot;
-  struct tree_map_base in;
-
-  in.from = tree;
-
-  /* If deleting, remove the slot.  */
-  if (val == NULL) {
-    if (llvm_cache)
-      htab_remove_elt(llvm_cache, &in);
-    return NULL;
-  }
-
-  if (!llvm_cache)
-    llvm_cache = htab_create_ggc(1024, tree_llvm_map_hash, tree_llvm_map_eq, NULL);
-
-  slot = (struct tree_llvm_map **) htab_find_slot(llvm_cache, &in, INSERT);
-  gcc_assert(slot);
-
-  if (!*slot) {
-    *slot =
-#if (GCC_MINOR > 5)
-      ggc_alloc_tree_llvm_map();
-#else
-      GGC_NEW(struct tree_llvm_map);
-#endif
-    (*slot)->base.from = tree;
-  }
-
-  (*slot)->val = val;
-
-  return val;
-}
-
-struct update {
-  const void *old_val;
-  const void *new_val;
-};
-
-/* replace - If the current value for the slot matches old_val, then replace
-   it with new_val, or delete it if new_val is NULL.  */
-static int replace(void **slot, void *data) {
-  struct tree_llvm_map *entry = *(struct tree_llvm_map **)slot;
-  struct update *u = (struct update *)data;
-
-  if (entry->val != u->old_val)
-    return 1;
-
-  if (u->new_val != NULL)
-    entry->val = u->new_val;
-  else
-    htab_clear_slot(llvm_cache, slot);
-
-  return 1;
-}
-
-/* llvm_replace_cached - Replaces all occurrences of old_val with new_val.  */
-void llvm_replace_cached(const void *old_val, const void *new_val) {
-  struct update u;
-  u.old_val = old_val;
-  u.new_val = new_val;
-
-  if (!llvm_cache || old_val == NULL)
-    return;
-
-  htab_traverse(llvm_cache, replace, &u);
-}





More information about the llvm-commits mailing list