diff options
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/gengtype.c | 5 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 51 | ||||
-rw-r--r-- | gcc/objc/Make-lang.in | 10 | ||||
-rw-r--r-- | gcc/objc/config-lang.in | 2 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 507 | ||||
-rw-r--r-- | gcc/objc/objc-act.h | 6 | ||||
-rw-r--r-- | gcc/objc/objc-map.c | 161 | ||||
-rw-r--r-- | gcc/objc/objc-map.h | 309 | ||||
-rw-r--r-- | gcc/objc/objc-next-runtime-abi-02.c | 1 | ||||
-rw-r--r-- | gcc/objcp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/objcp/Make-lang.in | 10 | ||||
-rw-r--r-- | gcc/objcp/config-lang.in | 2 |
13 files changed, 770 insertions, 306 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c6f47f9ffc5..5c82e9b837d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com> + + * gengtype.c (files_rules): Added rules for objc/objc-map.h and + objc/objc-map.c. + 2011-10-14 Paolo Carlini <paolo.carlini@oracle.com> PR c++/17212 diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 0820741a051..6063d81daa5 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1817,6 +1817,11 @@ struct file_rule_st files_rules[] = { REG_EXTENDED, NULL_REGEX, "gt-objc-objc-act.h", "objc/objc-act.c", NULL_FRULACT }, + /* objc/objc-map.h gives gt-objc-objc-map.h for objc/objc-map.c ! */ + { DIR_PREFIX_REGEX "objc/objc-map\\.h$", + REG_EXTENDED, NULL_REGEX, + "gt-objc-objc-map.h", "objc/objc-map.c", NULL_FRULACT }, + /* General cases. For header *.h and source *.c files, we need * special actions to handle the language. */ diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index e195ed5dd1b..e5fa097c485 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,54 @@ +2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-map.h: New file. + * objc-map.c: New file. + * config-lang.in (gtfiles): Added objc-map.h. + * Make-lang.in (OBJC_OBJS): Added objc-map.o. + (objc/objc-map.o): New rule. + (objc/objc-act.o): Depend on objc/objc-map.h. + * objc-next-runtime-abi-02.c: Added a TODO comment. + * objc-act.c: Include objc-map.h. + (nst_method_hash_list, cls_method_hash_list): Removed. + (instance_method_map, class_method_map): New. + (cls_name_hash_list, als_name_hash_list): Removed. + (class_name_map, alias_name_map): Removed. + (ivar_offset_hash_list): Removed. + (hash_class_name_enter, hash_class_name_lookup, hash_enter, + hash_lookup, hash_add_attr, add_method_to_hash_list): Removed. + (interface_hash_init): New. + (objc_init): Call interface_hash_init. + (objc_write_global_declarations): Iterate over class_method_map + and instance_method_map instead of cls_method_hash_list and + nst_method_hash_list. + (objc_declare_alias): Use alias_name_map instead of + cls_name_hash_list. + (objc_is_class_name): Use class_name_map and alias_name_map + instead of cls_name_hash_list and als_name_hash_list. + (interface_tuple, interface_htab, hash_interface, eq_interface): + Removed. + (interface_map): New. + (add_class): Renamed to add_interface. Use interface_map instead + of interface_htab. + (lookup_interface): Use interface_map instead of interface_htab. + (check_duplicates): Changed first argument to be a tree, + potentially a TREE_VEC, instead of a hash. Changed implementation + to match. + (lookup_method_in_hash_lists): Use class_method_map and + instance_method_map instead of cls_method_hash_list and + nst_method_hash_list. + (objc_build_selector_expr): Likewise. + (hash_func): Removed. + (hash_init): Create instance_method_map, class_method_map, + class_name_map, and alias_name_map. Do not create + nst_method_hash_list, cls_method_hash_list, cls_name_hash_list, + als_name_hash_list, and ivar_offset_hash_list. + (insert_method_into_method_map): New. + (objc_add_method): Use insert_method_into_method_map instead of + add_method_to_hash_list. + (start_class): Call add_interface instead of add_class. + * objc-act.h (cls_name_hash_list, als_name_hash_list, + nst_method_hash_list, cls_method_hash_list): Removed. + 2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com> * objc-next-runtime-abi-01.c (objc_build_exc_ptr): Delete old diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in index f9b3907fe1c..5cca11a6b4d 100644 --- a/gcc/objc/Make-lang.in +++ b/gcc/objc/Make-lang.in @@ -55,7 +55,8 @@ OBJC_OBJS = objc/objc-lang.o objc/objc-act.o \ objc/objc-gnu-runtime-abi-01.o \ objc/objc-next-runtime-abi-01.o \ objc/objc-next-runtime-abi-02.o \ - objc/objc-encoding.o + objc/objc-encoding.o \ + objc/objc-map.o objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o @@ -129,6 +130,7 @@ objc/objc-act.o : objc/objc-act.c \ $(HASHTAB_H) $(GIMPLE_H) \ $(C_PRAGMA_H) $(C_TARGET_H) \ objc/objc-encoding.h \ + objc/objc-map.h \ objc/objc-runtime-hooks.h \ objc/objc-runtime-shared-support.h @@ -139,6 +141,12 @@ objc/objc-encoding.o : objc/objc-encoding.c \ objc/objc-encoding.h \ objc/objc-runtime-shared-support.h +objc/objc-map.o : objc/objc-map.c \ + $(START_HDRS) \ + $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \ + $(OBSTACK_H) \ + objc/objc-map.h + objc.srcextra: # diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in index 0de0650c0de..48f8582d74c 100644 --- a/gcc/objc/config-lang.in +++ b/gcc/objc/config-lang.in @@ -36,4 +36,4 @@ lang_requires="c" # Order is important. If you change this list, make sure you test # building without C++ as well; that is, remove the gcc/cp directory, # and build with --enable-languages=c,objc. -gtfiles="\$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c" +gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c" diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 72a486d9c83..396d748849f 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "langhooks.h" #include "objc-act.h" +#include "objc-map.h" #include "input.h" #include "function.h" #include "output.h" @@ -157,27 +158,25 @@ static void objc_generate_cxx_cdtors (void); static void objc_decl_method_attributes (tree*, tree, int); static tree build_keyword_selector (tree); -/* Hash tables to manage the global pool of method prototypes. */ static void hash_init (void); -hash *nst_method_hash_list = 0; -hash *cls_method_hash_list = 0; +/* Hash tables to manage the global pool of method prototypes. Each + of these maps map a method name (selector) identifier to either a + single tree (for methods with a single method prototype) or a + TREE_VEC (for methods with multiple method prototypes). */ +static GTY(()) objc_map_t instance_method_map = 0; +static GTY(()) objc_map_t class_method_map = 0; /* Hash tables to manage the global pool of class names. */ -hash *cls_name_hash_list = 0; -hash *als_name_hash_list = 0; +static GTY(()) objc_map_t class_name_map = 0; +static GTY(()) objc_map_t alias_name_map = 0; -hash *ivar_offset_hash_list = 0; - -static void hash_class_name_enter (hash *, tree, tree); -static hash hash_class_name_lookup (hash *, tree); - -static hash hash_lookup (hash *, tree); static tree lookup_method (tree, tree); static tree lookup_method_static (tree, tree, int); -static tree add_class (tree, tree); +static void interface_hash_init (void); +static tree add_interface (tree, tree); static void add_category (tree, tree); static inline tree lookup_category (tree, tree); @@ -207,7 +206,7 @@ static void generate_struct_by_value_array (void) ATTRIBUTE_NORETURN; static void mark_referenced_methods (void); static bool objc_type_valid_for_messaging (tree type, bool allow_classes); -static tree check_duplicates (hash, int, int); +static tree check_duplicates (tree, int, int); /*** Private Interface (data) ***/ /* Flags for lookup_method_static(). */ @@ -380,6 +379,7 @@ objc_init (void) /* Set up stuff used by FE parser and all runtimes. */ errbuf = XNEWVEC (char, 1024 * 10); + interface_hash_init (); hash_init (); objc_encoding_init (); /* ... and then check flags and set-up for the selected runtime ... */ @@ -418,19 +418,15 @@ objc_write_global_declarations (void) if (warn_selector) { - int slot; - hash hsh; + objc_map_iterator_t i; - /* Run through the selector hash tables and print a warning for any - selector which has multiple methods. */ + objc_map_iterator_initialize (class_method_map, &i); + while (objc_map_iterator_move_to_next (class_method_map, &i)) + check_duplicates (objc_map_iterator_current_value (class_method_map, i), 0, 1); - for (slot = 0; slot < SIZEHASHTABLE; slot++) - { - for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next) - check_duplicates (hsh, 0, 1); - for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next) - check_duplicates (hsh, 0, 0); - } + objc_map_iterator_initialize (instance_method_map, &i); + while (objc_map_iterator_move_to_next (instance_method_map, &i)) + check_duplicates (objc_map_iterator_current_value (instance_method_map, i), 0, 0); } /* TODO: consider an early exit here if either errorcount or sorrycount @@ -3351,8 +3347,7 @@ objc_declare_alias (tree alias_ident, tree class_ident) #ifdef OBJCPLUS pop_lang_context (); #endif - hash_class_name_enter (als_name_hash_list, alias_ident, - underlying_class); + objc_map_put (alias_name_map, alias_ident, underlying_class); } } @@ -3392,15 +3387,13 @@ objc_declare_class (tree identifier) the TYPE_OBJC_INTERFACE. If later an @interface is found, we'll replace the ident with the interface. */ TYPE_OBJC_INTERFACE (record) = identifier; - hash_class_name_enter (cls_name_hash_list, identifier, NULL_TREE); + objc_map_put (class_name_map, identifier, NULL_TREE); } } tree objc_is_class_name (tree ident) { - hash target; - if (ident && TREE_CODE (ident) == IDENTIFIER_NODE) { tree t = identifier_global_value (ident); @@ -3428,16 +3421,17 @@ objc_is_class_name (tree ident) if (lookup_interface (ident)) return ident; - target = hash_class_name_lookup (cls_name_hash_list, ident); - if (target) - return target->key; + { + tree target; - target = hash_class_name_lookup (als_name_hash_list, ident); - if (target) - { - gcc_assert (target->list && target->list->value); - return target->list->value; - } + target = objc_map_get (class_name_map, ident); + if (target != OBJC_MAP_NOT_FOUND) + return ident; + + target = objc_map_get (alias_name_map, ident); + if (target != OBJC_MAP_NOT_FOUND) + return target; + } return 0; } @@ -3761,25 +3755,30 @@ objc_generate_write_barrier (tree lhs, enum tree_code modifycode, tree rhs) return result; } -struct GTY(()) interface_tuple { - tree id; - tree class_name; -}; +/* Implementation of the table mapping a class name (as an identifier) + to a class node. The two public functions for it are + lookup_interface() and add_interface(). add_interface() is only + used in this file, so we can make it static. */ -static GTY ((param_is (struct interface_tuple))) htab_t interface_htab; +static GTY(()) objc_map_t interface_map; -static hashval_t -hash_interface (const void *p) +static void +interface_hash_init (void) { - const struct interface_tuple *d = (const struct interface_tuple *) p; - return IDENTIFIER_HASH_VALUE (d->id); + interface_map = objc_map_alloc_ggc (200); } -static int -eq_interface (const void *p1, const void *p2) +static tree +add_interface (tree class_name, tree name) { - const struct interface_tuple *d = (const struct interface_tuple *) p1; - return d->id == p2; + /* Put interfaces on list in reverse order. */ + TREE_CHAIN (class_name) = interface_chain; + interface_chain = class_name; + + /* Add it to the map. */ + objc_map_put (interface_map, name, class_name); + + return interface_chain; } tree @@ -3794,19 +3793,12 @@ lookup_interface (tree ident) return NULL_TREE; { - struct interface_tuple **slot; - tree i = NULL_TREE; + tree interface = objc_map_get (interface_map, ident); - if (interface_htab) - { - slot = (struct interface_tuple **) - htab_find_slot_with_hash (interface_htab, ident, - IDENTIFIER_HASH_VALUE (ident), - NO_INSERT); - if (slot && *slot) - i = (*slot)->class_name; - } - return i; + if (interface == OBJC_MAP_NOT_FOUND) + return NULL_TREE; + else + return interface; } } @@ -5052,71 +5044,75 @@ build_function_type_for_method (tree return_type, tree method, return ftype; } +/* The 'method' argument is a tree; this tree could either be a single + method, which is returned, or could be a TREE_VEC containing a list + of methods. In that case, the first one is returned, and warnings + are issued as appropriate. */ static tree -check_duplicates (hash hsh, int methods, int is_class) +check_duplicates (tree method, int methods, int is_class) { - tree meth = NULL_TREE; - - if (hsh) - { - meth = hsh->key; - - if (hsh->list) - { - /* We have two or more methods with the same name but - different types. */ - attr loop; - - /* But just how different are those types? If - -Wno-strict-selector-match is specified, we shall not - complain if the differences are solely among types with - identical size and alignment. */ - if (!warn_strict_selector_match) - { - for (loop = hsh->list; loop; loop = loop->next) - if (!comp_proto_with_proto (meth, loop->value, 0)) - goto issue_warning; - - return meth; - } - - issue_warning: - if (methods) - { - bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL; - - warning_at (input_location, 0, - "multiple methods named %<%c%E%> found", - (is_class ? '+' : '-'), - METHOD_SEL_NAME (meth)); - inform (DECL_SOURCE_LOCATION (meth), "using %<%c%s%>", - (type ? '-' : '+'), - identifier_to_locale (gen_method_decl (meth))); - } - else - { - bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL; + tree first_method; + size_t i; - warning_at (input_location, 0, - "multiple selectors named %<%c%E%> found", - (is_class ? '+' : '-'), - METHOD_SEL_NAME (meth)); - inform (DECL_SOURCE_LOCATION (meth), "found %<%c%s%>", - (type ? '-' : '+'), - identifier_to_locale (gen_method_decl (meth))); - } - - for (loop = hsh->list; loop; loop = loop->next) - { - bool type = TREE_CODE (loop->value) == INSTANCE_METHOD_DECL; + if (method == NULL_TREE) + return NULL_TREE; - inform (DECL_SOURCE_LOCATION (loop->value), "also found %<%c%s%>", - (type ? '-' : '+'), - identifier_to_locale (gen_method_decl (loop->value))); - } - } + if (TREE_CODE (method) != TREE_VEC) + return method; + + /* We have two or more methods with the same name but different + types. */ + first_method = TREE_VEC_ELT (method, 0); + + /* But just how different are those types? If + -Wno-strict-selector-match is specified, we shall not complain if + the differences are solely among types with identical size and + alignment. */ + if (!warn_strict_selector_match) + { + for (i = 0; i < TREE_VEC_LENGTH (method); i++) + if (!comp_proto_with_proto (first_method, TREE_VEC_ELT (method, i), 0)) + goto issue_warning; + + return first_method; + } + + issue_warning: + if (methods) + { + bool type = TREE_CODE (first_method) == INSTANCE_METHOD_DECL; + + warning_at (input_location, 0, + "multiple methods named %<%c%E%> found", + (is_class ? '+' : '-'), + METHOD_SEL_NAME (first_method)); + inform (DECL_SOURCE_LOCATION (first_method), "using %<%c%s%>", + (type ? '-' : '+'), + identifier_to_locale (gen_method_decl (first_method))); } - return meth; + else + { + bool type = TREE_CODE (first_method) == INSTANCE_METHOD_DECL; + + warning_at (input_location, 0, + "multiple selectors named %<%c%E%> found", + (is_class ? '+' : '-'), + METHOD_SEL_NAME (first_method)); + inform (DECL_SOURCE_LOCATION (first_method), "found %<%c%s%>", + (type ? '-' : '+'), + identifier_to_locale (gen_method_decl (first_method))); + } + + for (i = 0; i < TREE_VEC_LENGTH (method); i++) + { + bool type = TREE_CODE (TREE_VEC_ELT (method, i)) == INSTANCE_METHOD_DECL; + + inform (DECL_SOURCE_LOCATION (TREE_VEC_ELT (method, i)), "also found %<%c%s%>", + (type ? '-' : '+'), + identifier_to_locale (gen_method_decl (TREE_VEC_ELT (method, i)))); + } + + return first_method; } /* If RECEIVER is a class reference, return the identifier node for @@ -5294,17 +5290,18 @@ objc_build_message_expr (tree receiver, tree message_args) static tree lookup_method_in_hash_lists (tree sel_name, int is_class) { - hash method_prototype = NULL; + tree method_prototype = OBJC_MAP_NOT_FOUND; if (!is_class) - method_prototype = hash_lookup (nst_method_hash_list, - sel_name); - - if (!method_prototype) + method_prototype = objc_map_get (instance_method_map, sel_name); + + if (method_prototype == OBJC_MAP_NOT_FOUND) { - method_prototype = hash_lookup (cls_method_hash_list, - sel_name); + method_prototype = objc_map_get (class_method_map, sel_name); is_class = 1; + + if (method_prototype == OBJC_MAP_NOT_FOUND) + return NULL_TREE; } return check_duplicates (method_prototype, 1, is_class); @@ -5714,21 +5711,19 @@ objc_build_selector_expr (location_t loc, tree selnamelist) /* Look the selector up in the list of all known class and instance methods (up to this line) to check that the selector exists. */ - hash hsh; + tree method; /* First try with instance methods. */ - hsh = hash_lookup (nst_method_hash_list, selname); + method = objc_map_get (instance_method_map, selname); /* If not found, try with class methods. */ - if (!hsh) + if (method == OBJC_MAP_NOT_FOUND) { - hsh = hash_lookup (cls_method_hash_list, selname); - } + method = objc_map_get (class_method_map, selname); - /* If still not found, print out a warning. */ - if (!hsh) - { - warning (0, "undeclared selector %qE", selname); + /* If still not found, print out a warning. */ + if (method == OBJC_MAP_NOT_FOUND) + warning (0, "undeclared selector %qE", selname); } } @@ -5761,131 +5756,99 @@ build_ivar_reference (tree id) return (*runtime.build_ivar_reference) (input_location, base, id); } -/* Compute a hash value for a given method SEL_NAME. */ - -static size_t -hash_func (tree sel_name) -{ - const unsigned char *s - = (const unsigned char *)IDENTIFIER_POINTER (sel_name); - size_t h = 0; - - while (*s) - h = h * 67 + *s++ - 113; - return h; -} - static void hash_init (void) { - nst_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE); - cls_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE); - - cls_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE); - als_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE); + instance_method_map = objc_map_alloc_ggc (1000); + class_method_map = objc_map_alloc_ggc (1000); - ivar_offset_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE); + class_name_map = objc_map_alloc_ggc (200); + alias_name_map = objc_map_alloc_ggc (200); /* Initialize the hash table used to hold the constant string objects. */ string_htab = htab_create_ggc (31, string_hash, string_eq, NULL); } -/* This routine adds sel_name to the hash list. sel_name is a class or alias - name for the class. If alias name, then value is its underlying class. - If class, the value is NULL_TREE. */ - +/* Use the following to add a method to class_method_map or + instance_method_map. It will add the method, keyed by the + METHOD_SEL_NAME. If the method already exists, but with one or + more different prototypes, it will store a TREE_VEC in the map, + with the method prototypes in the vector. */ static void -hash_class_name_enter (hash *hashlist, tree sel_name, tree value) +insert_method_into_method_map (bool class_method, tree method) { - hash obj; - int slot = hash_func (sel_name) % SIZEHASHTABLE; + tree method_name = METHOD_SEL_NAME (method); + tree existing_entry; + objc_map_t map; - obj = ggc_alloc_hashed_entry (); - if (value != NULL_TREE) - { - /* Save the underlying class for the 'alias' in the hash table */ - attr obj_attr = ggc_alloc_hashed_attribute (); - obj_attr->value = value; - obj->list = obj_attr; - } + if (class_method) + map = class_method_map; else - obj->list = 0; - obj->next = hashlist[slot]; - obj->key = sel_name; - - hashlist[slot] = obj; /* append to front */ + map = instance_method_map; -} + /* Check if the method already exists in the map. */ + existing_entry = objc_map_get (map, method_name); -/* - Searches in the hash table looking for a match for class or alias name. -*/ - -static hash -hash_class_name_lookup (hash *hashlist, tree sel_name) -{ - hash target; - - target = hashlist[hash_func (sel_name) % SIZEHASHTABLE]; - - while (target) + /* If not, we simply add it to the map. */ + if (existing_entry == OBJC_MAP_NOT_FOUND) + objc_map_put (map, method_name, method); + else { - if (sel_name == target->key) - return target; - - target = target->next; - } - return 0; -} - -/* WARNING!!!! hash_enter is called with a method, and will peek - inside to find its selector! But hash_lookup is given a selector - directly, and looks for the selector that's inside the found - entry's key (method) for comparison. */ - -static void -hash_enter (hash *hashlist, tree method) -{ - hash obj; - int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE; - - obj = ggc_alloc_hashed_entry (); - obj->list = 0; - obj->next = hashlist[slot]; - obj->key = method; - - hashlist[slot] = obj; /* append to front */ -} - -static hash -hash_lookup (hash *hashlist, tree sel_name) -{ - hash target; + tree new_entry; + + /* If an entry already exists, it's more complicated. We'll + have to check whether the method prototype is the same or + not. */ + if (TREE_CODE (existing_entry) != TREE_VEC) + { + /* If the method prototypes are the same, there is nothing + to do. */ + if (comp_proto_with_proto (method, existing_entry, 1)) + return; - target = hashlist[hash_func (sel_name) % SIZEHASHTABLE]; + /* If not, create a vector to store both the method already + in the map, and the new one that we are adding. */ + new_entry = make_tree_vec (2); + + TREE_VEC_ELT (new_entry, 0) = existing_entry; + TREE_VEC_ELT (new_entry, 1) = method; + } + else + { + /* An entry already exists, and it's already a vector. This + means that at least 2 different method prototypes were + already found, and we're considering registering yet + another one. */ + size_t i; + + /* Check all the existing prototypes. If any matches the + one we need to add, there is nothing to do because it's + already there. */ + for (i = 0; i < TREE_VEC_LENGTH (existing_entry); i++) + if (comp_proto_with_proto (method, TREE_VEC_ELT (existing_entry, i), 1)) + return; - while (target) - { - if (sel_name == METHOD_SEL_NAME (target->key)) - return target; + /* Else, create a new, bigger vector and add the new method + at the end of it. This is inefficient but extremely + rare; in any sane program most methods have a single + prototype, and very few, if any, will have more than + 2! */ + new_entry = make_tree_vec (TREE_VEC_LENGTH (existing_entry) + 1); + + /* Copy the methods from the existing vector. */ + for (i = 0; i < TREE_VEC_LENGTH (existing_entry); i++) + TREE_VEC_ELT (new_entry, i) = TREE_VEC_ELT (existing_entry, i); + + /* Add the new method at the end. */ + TREE_VEC_ELT (new_entry, i) = method; + } - target = target->next; + /* Store the new vector in the map. */ + objc_map_put (map, method_name, new_entry); } - return 0; } -static void -hash_add_attr (hash entry, tree value) -{ - attr obj; - - obj = ggc_alloc_hashed_attribute (); - obj->next = entry->list; - obj->value = value; - - entry->list = obj; /* append to front */ -} static tree lookup_method (tree mchain, tree method) @@ -5988,31 +5951,6 @@ lookup_method_static (tree interface, tree ident, int flags) } } -/* Add the method to the hash list if it doesn't contain an identical - method already. */ - -static void -add_method_to_hash_list (hash *hash_list, tree method) -{ - hash hsh; - - if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method)))) - { - /* Install on a global chain. */ - hash_enter (hash_list, method); - } - else - { - /* Check types against those; if different, add to a list. */ - attr loop; - int already_there = comp_proto_with_proto (method, hsh->key, 1); - for (loop = hsh->list; !already_there && loop; loop = loop->next) - already_there |= comp_proto_with_proto (method, loop->value, 1); - if (!already_there) - hash_add_attr (hsh, method); - } -} - static tree objc_add_method (tree klass, tree method, int is_class, bool is_optional) { @@ -6135,10 +6073,10 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional) } if (is_class) - add_method_to_hash_list (cls_method_hash_list, method); + insert_method_into_method_map (true, method); else { - add_method_to_hash_list (nst_method_hash_list, method); + insert_method_into_method_map (false, method); /* Instance methods in root classes (and categories thereof) may act as class methods as a last resort. We also add @@ -6151,37 +6089,12 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional) if (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE || !CLASS_SUPER_NAME (klass)) - add_method_to_hash_list (cls_method_hash_list, method); + insert_method_into_method_map (true, method); } return method; } -static tree -add_class (tree class_name, tree name) -{ - struct interface_tuple **slot; - - /* Put interfaces on list in reverse order. */ - TREE_CHAIN (class_name) = interface_chain; - interface_chain = class_name; - - if (interface_htab == NULL) - interface_htab = htab_create_ggc (31, hash_interface, eq_interface, NULL); - slot = (struct interface_tuple **) - htab_find_slot_with_hash (interface_htab, name, - IDENTIFIER_HASH_VALUE (name), - INSERT); - if (!*slot) - { - *slot = ggc_alloc_cleared_interface_tuple (); - (*slot)->id = name; - } - (*slot)->class_name = class_name; - - return interface_chain; -} - static void add_category (tree klass, tree category) { @@ -6951,8 +6864,8 @@ start_class (enum tree_code code, tree class_name, tree super_name, { warning (0, "cannot find interface declaration for %qE", class_name); - add_class (implementation_template = objc_implementation_context, - class_name); + add_interface (implementation_template = objc_implementation_context, + class_name); } /* If a super class has been specified in the implementation, @@ -6985,7 +6898,7 @@ start_class (enum tree_code code, tree class_name, tree super_name, warning (0, "duplicate interface declaration for class %qE", class_name); #endif else - add_class (klass, class_name); + add_interface (klass, class_name); if (protocol_list) CLASS_PROTOCOL_LIST (klass) diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index 33f90fdb785..e958e669af0 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -252,12 +252,6 @@ struct GTY(()) hashed_entry { #define SIZEHASHTABLE 257 -extern GTY ((length ("SIZEHASHTABLE"))) hash *nst_method_hash_list; -extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_method_hash_list; - -extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_name_hash_list; -extern GTY ((length ("SIZEHASHTABLE"))) hash *als_name_hash_list; - /* An array of all the local variables in the current function that need to be marked as volatile. */ extern GTY(()) VEC(tree,gc) *local_variables_to_volatilize; diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c new file mode 100644 index 00000000000..77a98c1d825 --- /dev/null +++ b/gcc/objc/objc-map.c @@ -0,0 +1,161 @@ +/* objc-map.c -- Implementation of map data structures for ObjC compiler + Copyright 2011 Free Software Foundation, Inc. + Written by Nicola Pero <nicola.pero@meta-innovation.com> + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser Public License as published by the +Free Software Foundation; either version 3, or (at your option) any +later version. + +This program 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 Lesser Public License for more details. + +You should have received a copy of the GNU Lesser Public License +along with this program; if not, write to the Free Software +Foundation, 51 Franklin Street - Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "ggc.h" +#include "objc-map.h" + +#define OUT_OF_MEMORY { fprintf (stderr, "Out of memory\n"); abort (); } + +static +size_t +ATTRIBUTE_PURE +next_power_of_two (size_t x) +{ + size_t result = 1; + + if (x < 2) + return 2; + + /* Avoid the long calculation if x is already a power of two. Since + we internally always increase/shrink tables by powers of 2, the + calculation should only be done once, when the table is first + set up. */ + if ((x & (x - 1)) == 0) + return x; + + /* Calculate log_2 by counting how many times we can divide by 2 + before reaching 0. */ + while (x > 0) + { + x = x >> 1; + result = result << 1; + } + return result; +} + +objc_map_t +objc_map_alloc_ggc (size_t initial_capacity) +{ + objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc_stat (1, sizeof (struct objc_map_private)); + if (map == NULL) + OUT_OF_MEMORY; + + initial_capacity = next_power_of_two (initial_capacity); + + map->number_of_slots = initial_capacity; + map->mask = initial_capacity - 1; + map->maximum_load_factor = 70; + map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100; + + map->slots = (tree *)ggc_internal_cleared_vec_alloc_stat (initial_capacity, sizeof (tree)); + map->values = (tree *)ggc_internal_cleared_vec_alloc_stat (initial_capacity, sizeof (tree)); + + if (map->slots == NULL) + OUT_OF_MEMORY; + + if (map->values == NULL) + OUT_OF_MEMORY; + + return map; +} + +void +objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred) +{ + if (map->number_of_non_empty_slots != 0) + return; + + map->maximum_load_factor = number_between_zero_and_one_hundred; + map->max_number_of_non_empty_slots = (map->number_of_slots * number_between_zero_and_one_hundred) / 100; +} + +int +objc_map_maximum_load_factor (objc_map_t map) +{ + return map->maximum_load_factor; +} + +static void +objc_map_private_resize (objc_map_t map, size_t new_number_of_slots) +{ + tree *old_slots = map->slots; + tree *old_values = map->values; + size_t i, old_number_of_slots = map->number_of_slots; + + if (new_number_of_slots < (map->number_of_non_empty_slots)) + new_number_of_slots = 2 * map->number_of_non_empty_slots; + + new_number_of_slots = next_power_of_two (new_number_of_slots); + + map->number_of_slots = new_number_of_slots; + map->mask = map->number_of_slots - 1; + map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100; + + + map->slots = (tree *)ggc_internal_cleared_vec_alloc_stat (map->number_of_slots, sizeof (tree)); + map->values = (tree *)ggc_internal_cleared_vec_alloc_stat (map->number_of_slots, sizeof (tree)); + + if (map->slots == NULL) + OUT_OF_MEMORY; + + if (map->values == NULL) + OUT_OF_MEMORY; + + for (i = 0; i < old_number_of_slots; i++) + if (old_slots[i] != OBJC_MAP_PRIVATE_EMPTY_SLOT) + { + size_t k = IDENTIFIER_HASH_VALUE (old_slots[i]) & map->mask; + + if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT) + { + map->slots[k] = old_slots[i]; + map->values[k] = old_values[i]; + } + else + { + size_t j = 1; + while (1) + { + k = (k + j) & map->mask; + if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT) + { + map->slots[k] = old_slots[i]; + map->values[k] = old_values[i]; + break; + } + j++; + } + } + } + + ggc_free (old_slots); + ggc_free (old_values); +} + +void +objc_map_private_grow (struct objc_map_private *map) +{ + objc_map_private_resize (map, map->number_of_slots * 2); +} + +#include "gt-objc-objc-map.h" diff --git a/gcc/objc/objc-map.h b/gcc/objc/objc-map.h new file mode 100644 index 00000000000..c4565de186e --- /dev/null +++ b/gcc/objc/objc-map.h @@ -0,0 +1,309 @@ +/* objc-map.h -- Implementation of map data structures for ObjC compiler + Copyright 2011 Free Software Foundation, Inc. + Written by Nicola Pero <nicola.pero@meta-innovation.com> + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser Public License as published by the +Free Software Foundation; either version 3, or (at your option) any +later version. + +This program 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 Lesser Public License for more details. + +You should have received a copy of the GNU Lesser Public License +along with this program; if not, write to the Free Software +Foundation, 51 Franklin Street - Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#ifndef OBJC_MAP_H +#define OBJC_MAP_H + +/* A map is a data structure that maps a key to a value. In this file + we currently have maps that can map a GCC identifier (a tree) to + some other GCC tree. This is what the ObjC frontend mostly needs: + being able to look up an identifier into an ObjC data structure. A + typical usage is mapping ObjC class names (as identifiers) to a + tree representing the class. + + This implementation is fast. :-) */ + +/** + ** Private definitions. + **/ + +/* We include private declaration and definitions that are required to + provide the implementation of inline functions. You should ignore + these definitions (and the implementation of the inline functions) + as they are not part of the public API and may change. */ +typedef unsigned int objc_map_private_hash_t; + +/* This is used as sentinel. */ +#define OBJC_MAP_PRIVATE_EMPTY_SLOT (tree)0 + +struct GTY(()) objc_map_private { + /* Total number of slots. This is the maximum number of elements + that can be currently stored in the map before resizing. This is + the number of slots in the C array. Important: this is + guaranteed to be a power of 2. When we create (or resize) the + map, we round up the size to the next power of 2. This allows us + to convert a hash to a position in the hashtable by simply doing + "position = hash & mask", where mask is number_of_slots - 1 + instead of using a modulo (which requires a division). */ + size_t number_of_slots; + + /* This is number_of_slots - 1, precomputed. */ + size_t mask; + + /* Number of slots that are not empty (ie, that are active). We + keep counts using this variable which can easily be checked + against max_number_of_non_empty_slots. */ + size_t number_of_non_empty_slots; + + /* This is the load factor limit. When the number of non empty + slots equals this number, we need to resize the array. This is + calculated once, when the slots are resized, and then kept cached + so it can be compared quickly when elements are added. */ + size_t max_number_of_non_empty_slots; + + /* The maximum load factor. */ + int maximum_load_factor; + + /* These are the keys. */ + tree * GTY ((length ("%h.number_of_slots"))) slots; + + /* These are the values. values[i] is the the value corresponding + to slots[i]. */ + tree * GTY ((length ("%h.number_of_slots"))) values; +}; + +/* Private functions used to resize the map. They may be called by + the inline functions when adding elements. */ +extern void +objc_map_private_grow (struct objc_map_private *map); + + +/** + ** The definition of a map. + **/ +typedef struct objc_map_private *objc_map_t; + + +/** + ** Creating a map. + **/ + +/* objc_map_alloc_ggc() creates a new map which is under GGC. The initial + capacity must be specified as an argument; this is used to size the map + when it is created. */ +objc_map_t objc_map_alloc_ggc (size_t initial_capacity); + +/** + ** Performance tuning. + **/ + +/* Set a maximum load factor for the data structure. This is the main + tuning parameter to improve performance (at the expense of + memory). */ +void objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred); + +/* Read the maximum load factor. */ +int objc_map_maximum_load_factor (objc_map_t map); + + +/** + ** Getting the value corresponding to a key. + **/ + +/* This is the value returned by objc_map_get() when the value + corresponding to a key is not found. */ +#define OBJC_MAP_NOT_FOUND (tree)1 + +/* objc_map_get() returns the value associated with a certain key, + or OBJC_MAP_NOT_FOUND if there is no value associated with that key. + Note that you can also use it to simply check if the map contains a + pair with a certain key; just compare the result of calling + objc_map_get() to OBJC_MAP_NOT_FOUND. + + It is essential to always check the results of the call to make + sure it is not OBJC_MAP_NOT_FOUND. + + NULL is a valid value, so a key can be inserted into a map with + value NULL, and objc_map_get() will return NULL in that case. + So a result of NULL means that they key *was* found, and the value + associated with it was NULL. */ +static inline tree +objc_map_get (objc_map_t map, /* struct tree_identifier * */tree key) +{ + /* The inline implementation is private and may change without notice. */ + objc_map_private_hash_t hash = IDENTIFIER_HASH_VALUE (key); + size_t i = hash & map->mask; + size_t j = 1; + + if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT) + return OBJC_MAP_NOT_FOUND; + + if (map->slots[i] == key) + return map->values[i]; + + while (1) + { + i = (i + j) & map->mask; + + if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT) + return OBJC_MAP_NOT_FOUND; + + if (map->slots[i] == key) + return map->values[i]; + + j++; + } +} + +/* objc_map_put() puts a key/value pair into the map. If the map does + not contain the key, it is added to it with the specified value. + If the map already contains the key, the previous value is replaced + with the new one. + + You can use any identifier as key, with the exception of NULL. + + You can use any tree as value, including NULL. */ +static inline +void objc_map_put (objc_map_t map, /*struct tree_identifier * */tree key, tree value) +{ + /* The inline implementation is private and may change without notice. */ + objc_map_private_hash_t hash = IDENTIFIER_HASH_VALUE (key); + size_t i, j = 0; + + if (map->number_of_non_empty_slots == map->max_number_of_non_empty_slots) + objc_map_private_grow (map); + + i = hash & map->mask; + + while (1) + { + if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT) + { + map->number_of_non_empty_slots++; + map->slots[i] = key; + map->values[i] = value; + return; + } + if (map->slots[i] == key) + { + map->values[i] = value; + return; + } + + j++; + i = (i + j) & map->mask; + } +} + +/** + ** Iterating over a map using an iterator. + **/ + +/* When using iterators you can iterate directly on the elements in + the map, and take an action over each one. + + Here is how you iterate over a hmap_pointer using iterators: + + objc_map_iterator_t i; + + objc_map_iterator_initialize (map, &i); + + while (objc_map_iterator_move_to_next (map, &i)) + { + tree p = objc_map_iterator_current_key (map, i); + tree q = objc_map_iterator_current_value (map, i); + + ... do something with p and q ... + } + + You'll notice that the functions that modify the iterator (to + initialize it, or move it to the next element) take a pointer to it + as argument (as in "&i"), while the functions that only read its + state (to read the current key/value, or remove the current + key/value from the map) take it as a direct argument (as in "i"). + + Note that all the objc_map_iterator_*() functions are inline and if + you follow the pattern above, the compiler should be able to inline + everything into a very efficient loop, roughly equivalent to + hand-writing a C loop that iterates directly onto the hmap_pointer + internal data structures. */ + +/* A objc_map_iterator_t variable encapsulates the state of an + iteration. The fact that this is actually a size_t (pointing to + the index of the slot that we return next) is an internal, private + detail of the implementation and may change without notice. */ +typedef size_t objc_map_iterator_t; + +/* Initialize an iterator to iterate over the specified objc_map. You + must use this before starting the iteration, to get a working + iterator. */ +static inline +void +objc_map_iterator_initialize (objc_map_t map ATTRIBUTE_UNUSED, objc_map_iterator_t *i) +{ + /* The inline implementation is private and may change without notice. */ + /* This is trivial, but the same API would work to initialize more + complicated iterators. */ + *i = 0; +} + +#define OBJC_MAP_FAILURE 0 +#define OBJC_MAP_SUCCESS 1 + +/* Move the iterator to the next key/value pair, and return + OBJC_MAP_SUCCESS if there is such a key/value pair, and + OBJC_MAP_FAILURE if there are no more ones. The iterator must have + been initialized using objc_map_iterator_initialize(). Note that + because this function is modifying the iterator, you need to pass a + pointer to it. */ +static inline +int +objc_map_iterator_move_to_next (objc_map_t map, objc_map_iterator_t *i) +{ + /* The inline implementation is private and may change without notice. */ + while (1) + { + void *slot; + if (*i == map->number_of_slots) + return OBJC_MAP_FAILURE; + + slot = map->slots[*i]; + *i = *i + 1; + if (slot != OBJC_MAP_PRIVATE_EMPTY_SLOT) + return OBJC_MAP_SUCCESS; + } +} + +/* Return the current key. You can only call it after you have called + objc_map_iterator_move_to_next() at least once (to move to the + first element), and only if the last call returned + OBJC_MAP_SUCCESS. The behaviour is otherwise undefined, probably a + segmentation fault. */ +static inline +tree +objc_map_iterator_current_key (objc_map_t map, objc_map_iterator_t i) +{ + /* The inline implementation is private and may change without notice. */ + return map->slots[i - 1]; +} + +/* Return the current value. You can only call it after you have + called objc_map_iterator_move_to_next() at least once (to move to + the first element), and only if the last call returned + OBJC_MAP_SUCCESS. The behaviour is otherwise undefined, probably a + segmentation fault. */ +static inline +tree +objc_map_iterator_current_value (objc_map_t map, objc_map_iterator_t i) +{ + /* The inline implementation is private and may change without notice. */ + return map->values[i - 1]; +} + +#endif /* OBJC_MAP_H */ diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c index 56df2afaf0c..4512c846cc0 100644 --- a/gcc/objc/objc-next-runtime-abi-02.c +++ b/gcc/objc/objc-next-runtime-abi-02.c @@ -231,6 +231,7 @@ static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool); static void finish_catch (struct objc_try_context **, tree); static tree finish_try_stmt (struct objc_try_context **); +/* TODO: Use an objc-map. */ static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names; bool diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog index 51ab2a5016a..bed3b9dcd25 100644 --- a/gcc/objcp/ChangeLog +++ b/gcc/objcp/ChangeLog @@ -1,3 +1,10 @@ +2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com> + + * Make-lang.in (OBJCXX_OBJS): Added objc-map.o. + (objcp/objc-map.o): New rule. + (objcp/objcp-act.o): Depend on objc/objc-map.h. + * config-lang.in (gtfiles): Added objc-map.h. + 2011-07-11 Nicola Pero <nicola.pero@meta-innovation.com> * Make-lang.in (objcp/objc-runtime-shared-support.o): Do not diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in index 3dac1735e15..4255bd63909 100644 --- a/gcc/objcp/Make-lang.in +++ b/gcc/objcp/Make-lang.in @@ -58,6 +58,7 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o objcp/objcp-decl.o \ objcp/objc-next-runtime-abi-01.o \ objcp/objc-next-runtime-abi-02.o \ objcp/objc-encoding.o \ + objcp/objc-map.o \ $(CXX_AND_OBJCXX_OBJS) obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o @@ -149,6 +150,7 @@ objcp/objcp-act.o : objc/objc-act.c \ $(RTL_H) $(EXPR_H) $(TARGET_H) \ objcp/objcp-decl.h \ objc/objc-encoding.h \ + objc/objc-map.h \ objc/objc-runtime-hooks.h \ objc/objc-runtime-shared-support.h \ objcp/objcp-decl.h @@ -165,6 +167,14 @@ objcp/objc-encoding.o : objc/objc-encoding.c \ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \ $(OUTPUT_OPTION) +objcp/objc-map.o : objc/objc-map.c \ + $(START_HDRS) \ + $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \ + $(OBSTACK_H) \ + objc/objc-map.h + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \ + $(OUTPUT_OPTION) + po-generated: # diff --git a/gcc/objcp/config-lang.in b/gcc/objcp/config-lang.in index e80666da5b5..5fd0f06b33b 100644 --- a/gcc/objcp/config-lang.in +++ b/gcc/objcp/config-lang.in @@ -46,5 +46,5 @@ subdir_requires="objc cp" # This list is separated in two parts: the first one is identical to # the C++ one, the second one contains our ObjC++ additions. gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \ -\$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c" +\$(srcdir)/objc/objc-map.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c" |