In gcc/objc/: 2011-07-04 Nicola Pero <nicola.pero@meta-innovation.com>
authorNicola Pero <nicola.pero@meta-innovation.com>
Mon, 4 Jul 2011 08:02:50 +0000 (08:02 +0000)
committerNicola Pero <nicola@gcc.gnu.org>
Mon, 4 Jul 2011 08:02:50 +0000 (08:02 +0000)
In gcc/objc/:
2011-07-04  Nicola Pero  <nicola.pero@meta-innovation.com>

Refactored encoding code into objc-encoding.h and objc-encoding.c.
* objc-act.c (util_obstack, util_firstobj, encode_type_qualifiers,
encode_type, generating_instance_variables, objc_method_parm_type,
objc_encoded_type_size, encode_method_prototype,
objc_build_encode_expr, pointee_is_readonly, encode_pointer,
encode_array, encode_vector, encode_aggregate_fields,
encode_aggregate_within, encode_next_bitfield,
encode_gnu_bitfield, encode_field_decl,
objc_v2_encode_property_attr): Moved to objc-encoding.h and
objc-encoding.c.  No change in the actual code.
Include objc-encoding.h.
(objc_init): Added TODO.
(objc_build_property_setter_name): Made non-static so it can be
called from objc-encoding.c.
* objc-act.h (OBJC_ENCODE_INLINE_DEFS,
OBJC_ENCODE_DONT_INLINE_DEFS): Moved to objc-encoding.h.
* objc-runtime-shared-support.h (objc_v2_encode_property_attr,
encode_method_prototype, encode_field_decl,
generating_instance_variables): Moved to objc-encoding.h.
(objc_build_property_setter_name): Declare.
* objc-encoding.c: New.
* objc-encoding.h: New.
* objc-gnu-runtime-abi-01.c: Include objc-encoding.h.
* objc-next-runtime-abi-01.c: Likewise.
* objc-next-runtime-abi-02.c: Likewise.
* objc-runtime-shared-support.c: Likewise.
* Make-lang.in (OBJC_OBJS): Added objc-encoding.o.
(objc/objc-lang.o): Reordered dependencies.
(objc/objc-runtime-shared-support.o): Reordered dependencies.
Added dependencies on objc-encoding.h and on $(GGC_H),
$(DIAGNOSTIC_CORE_H), $(FLAGS_H) and input.h.
(objc/objc-gnu-runtime-abi-01.o): Likewise.
(objc/objc-next-runtime-abi-01.o): Likewise.
(objc/objc-next-runtime-abi-02.o): Likewise.
(objc/objc-act.o): Reordered dependencies.  Added dependency on
objc-encoding.h.
(objc/objc-encoding.o): New rule.

* objc-encoding.c (encode_type): Use "%<%T%>" format when printing
warning "unknown type %<%T%> found during Objective-C encoding"
instead of using gen_type_name.

In gcc/objcp/:
2011-07-04  Nicola Pero  <nicola.pero@meta-innovation.com>

* Make-lang.in (OBJCXX_OBJS): Added objc-encoding.o.
(objcp/objcp-lang.o): Reordered dependencies.  Depend on GGC_H.
(objcp/objcp-decl.o): Reordered dependencies.
(objcp/objc-runtime-shared-support.o): Reordered dependencies.
Updated them to be identical to the corresponding new objc/ ones,
with the addition of objcp-decl.h.
(objcp/objc-runtime-shared-support.o): Likewise.
(objcp/objc-gnu-runtime-abi-01.o): Likewise.
(objcp/objc-next-runtime-abi-01.o): Likewise.
(objcp/objc-next-runtime-abi-02.o): Likewise.
(objcp/objcp-act.o): Reordered dependencies.  Added dependency on
objc-encoding.h.
(objcp/objc-encoding.o): New rule.

From-SVN: r175797

13 files changed:
gcc/objc/ChangeLog
gcc/objc/Make-lang.in
gcc/objc/objc-act.c
gcc/objc/objc-act.h
gcc/objc/objc-encoding.c [new file with mode: 0644]
gcc/objc/objc-encoding.h [new file with mode: 0644]
gcc/objc/objc-gnu-runtime-abi-01.c
gcc/objc/objc-next-runtime-abi-01.c
gcc/objc/objc-next-runtime-abi-02.c
gcc/objc/objc-runtime-shared-support.c
gcc/objc/objc-runtime-shared-support.h
gcc/objcp/ChangeLog
gcc/objcp/Make-lang.in

index 208decc7c86e826df554ca607d92b0585f1b5ab7..e27419775468a9ba3f193e4cf2233fa8637ef448 100644 (file)
@@ -1,3 +1,47 @@
+2011-07-04  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       Refactored encoding code into objc-encoding.h and objc-encoding.c.
+       * objc-act.c (util_obstack, util_firstobj, encode_type_qualifiers,
+       encode_type, generating_instance_variables, objc_method_parm_type,
+       objc_encoded_type_size, encode_method_prototype,
+       objc_build_encode_expr, pointee_is_readonly, encode_pointer,
+       encode_array, encode_vector, encode_aggregate_fields,
+       encode_aggregate_within, encode_next_bitfield,
+       encode_gnu_bitfield, encode_field_decl,
+       objc_v2_encode_property_attr): Moved to objc-encoding.h and
+       objc-encoding.c.  No change in the actual code.
+       Include objc-encoding.h.
+       (objc_init): Added TODO.
+       (objc_build_property_setter_name): Made non-static so it can be
+       called from objc-encoding.c.
+       * objc-act.h (OBJC_ENCODE_INLINE_DEFS,
+       OBJC_ENCODE_DONT_INLINE_DEFS): Moved to objc-encoding.h.
+       * objc-runtime-shared-support.h (objc_v2_encode_property_attr,
+       encode_method_prototype, encode_field_decl,
+       generating_instance_variables): Moved to objc-encoding.h.       
+       (objc_build_property_setter_name): Declare.
+       * objc-encoding.c: New.
+       * objc-encoding.h: New.
+       * objc-gnu-runtime-abi-01.c: Include objc-encoding.h.
+       * objc-next-runtime-abi-01.c: Likewise.
+       * objc-next-runtime-abi-02.c: Likewise. 
+       * objc-runtime-shared-support.c: Likewise.
+       * Make-lang.in (OBJC_OBJS): Added objc-encoding.o.
+       (objc/objc-lang.o): Reordered dependencies.
+       (objc/objc-runtime-shared-support.o): Reordered dependencies.
+       Added dependencies on objc-encoding.h and on $(GGC_H),
+       $(DIAGNOSTIC_CORE_H), $(FLAGS_H) and input.h.
+       (objc/objc-gnu-runtime-abi-01.o): Likewise.
+       (objc/objc-next-runtime-abi-01.o): Likewise.
+       (objc/objc-next-runtime-abi-02.o): Likewise.
+       (objc/objc-act.o): Reordered dependencies.  Added dependency on
+       objc-encoding.h.
+       (objc/objc-encoding.o): New rule.
+
+       * objc-encoding.c (encode_type): Use "%<%T%>" format when printing
+       warning "unknown type %<%T%> found during Objective-C encoding"
+       instead of using gen_type_name.
+       
 2011-06-05  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc-act.c (receiver_is_class_object): Expanded comment.
index 357028f26ea4e48c9c216b05ebe69a26a84f4e2d..1ac74ba4549b9aee7307195ff7289fcad9018d0e 100644 (file)
@@ -55,6 +55,7 @@ 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_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
 
@@ -73,33 +74,75 @@ cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(
 
 # Objective C language specific files.
 
-objc/objc-lang.o : objc/objc-lang.c $(START_HDRS) \
-   $(GGC_H) $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
+# When editing, please keep the objc/ header dependencies in
+# alphabetical order, and try to use a similar logical order for the
+# other files between the different targets.
+
+objc/objc-lang.o : objc/objc-lang.c \
+   $(START_HDRS) \
+   $(GGC_H) \
+   $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
    c-objc-common.h
 
 objc/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
-   $(START_HDRS) objc/objc-runtime-shared-support.h $(OBSTACK_H) \
-   objc/objc-next-metadata-tags.h gt-objc-objc-runtime-shared-support.h
-
-objc/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c $(START_HDRS) \
-   objc/objc-runtime-hooks.h $(GGC_H) \
-   objc/objc-runtime-shared-support.h gt-objc-objc-gnu-runtime-abi-01.h toplev.h
-
-objc/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c $(START_HDRS) \
-   $(GGC_H) objc/objc-runtime-hooks.h \
-   objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-01.h output.h \
-   objc/objc-runtime-shared-support.h $(TARGET_H)
-
-objc/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c $(START_HDRS) \
-   $(GGC_H) objc/objc-runtime-hooks.h \
-   objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-02.h $(TARGET_H) \
-   objc/objc-runtime-shared-support.h $(OBSTACK_H)
-
-objc/objc-act.o : objc/objc-act.c $(START_HDRS) $(GGC_H) \
-   $(DIAGNOSTIC_CORE_H) toplev.h $(FLAGS_H) input.h $(FUNCTION_H) output.h debug.h \
-   $(LANGHOOKS_DEF_H) $(HASHTAB_H) $(C_PRAGMA_H) gt-objc-objc-act.h $(OBSTACK_H) \
-   $(GIMPLE_H) objc/objc-runtime-shared-support.h objc/objc-runtime-hooks.h \
-   $(C_TARGET_H)
+   gt-objc-objc-runtime-shared-support.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   objc/objc-encoding.h \
+   objc/objc-next-metadata-tags.h \
+   objc/objc-runtime-shared-support.h
+
+objc/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c \
+   gt-objc-objc-gnu-runtime-abi-01.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   toplev.h \
+   objc/objc-encoding.h \
+   objc/objc-runtime-hooks.h \
+   objc/objc-runtime-shared-support.h
+
+objc/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c \
+   gt-objc-objc-next-runtime-abi-01.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   $(TARGET_H) output.h \
+   objc/objc-encoding.h \
+   objc/objc-next-metadata-tags.h \
+   objc/objc-runtime-hooks.h \
+   objc/objc-runtime-shared-support.h
+
+objc/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c \
+   gt-objc-objc-next-runtime-abi-02.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   $(TARGET_H) \
+   objc/objc-encoding.h \
+   objc/objc-next-metadata-tags.h \
+   objc/objc-runtime-hooks.h \
+   objc/objc-runtime-shared-support.h
+
+objc/objc-act.o : objc/objc-act.c \
+   gt-objc-objc-act.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   toplev.h $(FUNCTION_H) output.h debug.h $(LANGHOOKS_DEF_H) \
+   $(HASHTAB_H) $(GIMPLE_H) \
+   $(C_PRAGMA_H) $(C_TARGET_H) \
+   objc/objc-encoding.h \
+   objc/objc-runtime-hooks.h \
+   objc/objc-runtime-shared-support.h
+
+objc/objc-encoding.o : objc/objc-encoding.c \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   objc/objc-encoding.h \
+   objc/objc-runtime-shared-support.h
 
 objc.srcextra:
 
index 321d52aaf28f80457f26e4d086ca0f9db1db9b23..14db224df75388364299234f7a4b28493a7d36f5 100644 (file)
@@ -64,6 +64,9 @@ along with GCC; see the file COPYING3.  If not see
 /* For enum gimplify_status */
 #include "gimple.h"
 
+/* For encode_method_prototype().  */
+#include "objc-encoding.h"
+
 static unsigned int should_call_super_dealloc = 0;
 
 /* When building Objective-C++, we are not linking against the C front-end
@@ -105,17 +108,6 @@ static unsigned int should_call_super_dealloc = 0;
 #define OBJC_FORWARDING_MIN_OFFSET 0
 #endif
 
-/* Set up for use of obstacks.  */
-
-#include "obstack.h"
-
-/* This obstack is used to accumulate the encoding of a data type.  */
-struct obstack util_obstack;
-
-/* This points to the beginning of obstack contents, so we can free
-   the whole contents.  */
-char *util_firstobj;
-
 /*** Private Interface (procedures) ***/
 
 /* Init stuff.  */
@@ -146,7 +138,6 @@ static bool objc_derived_from_p (tree, tree);
 static void objc_gen_property_data (tree, tree);
 static void objc_synthesize_getter (tree, tree, tree);
 static void objc_synthesize_setter (tree, tree, tree);
-static char *objc_build_property_setter_name (tree);
 static tree lookup_property (tree, tree);
 static tree lookup_property_in_list (tree, tree);
 static tree lookup_property_in_protocol_list (tree, tree);
@@ -195,11 +186,6 @@ static inline tree lookup_category (tree, tree);
 static tree lookup_protocol (tree, bool, bool);
 static tree lookup_and_install_protocols (tree, bool);
 
-/* Type encoding.  */
-
-static void encode_type_qualifiers (tree);
-static void encode_type (tree, int, int);
-
 #ifdef OBJCPLUS
 static void really_start_method (tree, tree);
 #else
@@ -279,13 +265,6 @@ static GTY((param_is (struct string_descriptor))) htab_t string_htab;
 
 FILE *gen_declaration_file;
 
-/* Tells "encode_pointer/encode_aggregate" whether we are generating
-   type descriptors for instance variables (as opposed to methods).
-   Type descriptors for instance variables contain more information
-   than methods (for static typing and embedded structures).  */
-
-int generating_instance_variables = 0;
-
 /* Hooks for stuff that differs between runtimes.  */
 objc_runtime_hooks runtime;
 
@@ -402,9 +381,9 @@ objc_init (void)
   /* Set up stuff used by FE parser and all runtimes.  */
   errbuf = XNEWVEC (char, 1024 * 10);
   hash_init ();
+  /* TODO: Use objc_encoding_init().  */
   gcc_obstack_init (&util_obstack);
   util_firstobj = (char *) obstack_finish (&util_obstack);
-
   /* ... and then check flags and set-up for the selected runtime ... */
   if (flag_next_runtime && flag_objc_abi >= 2)
     ok = objc_next_runtime_abi_02_init (&runtime);
@@ -4451,110 +4430,6 @@ build_private_template (tree klass)
     }
 }
 
-/* Begin code generation for protocols...  */
-
-static tree
-objc_method_parm_type (tree type)
-{
-  type = TREE_VALUE (TREE_TYPE (type));
-  if (TREE_CODE (type) == TYPE_DECL)
-    type = TREE_TYPE (type);
-  return type;
-}
-
-static int
-objc_encoded_type_size (tree type)
-{
-  int sz = int_size_in_bytes (type);
-
-  /* Make all integer and enum types at least as large
-     as an int.  */
-  if (sz > 0 && INTEGRAL_TYPE_P (type))
-    sz = MAX (sz, int_size_in_bytes (integer_type_node));
-  /* Treat arrays as pointers, since that's how they're
-     passed in.  */
-  else if (TREE_CODE (type) == ARRAY_TYPE)
-    sz = int_size_in_bytes (ptr_type_node);
-  return sz;
-}
-
-/* Encode a method prototype.
-
-   The format is described in gcc/doc/objc.texi, section 'Method
-   signatures'.
- */
-
-tree
-encode_method_prototype (tree method_decl)
-{
-  tree parms;
-  int parm_offset, i;
-  char buf[40];
-  tree result;
-
-  /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
-  encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
-
-  /* Encode return type.  */
-  encode_type (objc_method_parm_type (method_decl),
-              obstack_object_size (&util_obstack),
-              OBJC_ENCODE_INLINE_DEFS);
-
-  /* Stack size.  */
-  /* The first two arguments (self and _cmd) are pointers; account for
-     their size.  */
-  i = int_size_in_bytes (ptr_type_node);
-  parm_offset = 2 * i;
-  for (parms = METHOD_SEL_ARGS (method_decl); parms;
-       parms = DECL_CHAIN (parms))
-    {
-      tree type = objc_method_parm_type (parms);
-      int sz = objc_encoded_type_size (type);
-
-      /* If a type size is not known, bail out.  */
-      if (sz < 0)
-       {
-         error_at (DECL_SOURCE_LOCATION (method_decl),
-                   "type %qT does not have a known size",
-                   type);
-         /* Pretend that the encoding succeeded; the compilation will
-            fail nevertheless.  */
-         goto finish_encoding;
-       }
-      parm_offset += sz;
-    }
-
-  sprintf (buf, "%d@0:%d", parm_offset, i);
-  obstack_grow (&util_obstack, buf, strlen (buf));
-
-  /* Argument types.  */
-  parm_offset = 2 * i;
-  for (parms = METHOD_SEL_ARGS (method_decl); parms;
-       parms = DECL_CHAIN (parms))
-    {
-      tree type = objc_method_parm_type (parms);
-
-      /* Process argument qualifiers for user supplied arguments.  */
-      encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
-
-      /* Type.  */
-      encode_type (type, obstack_object_size (&util_obstack),
-                  OBJC_ENCODE_INLINE_DEFS);
-
-      /* Compute offset.  */
-      sprintf (buf, "%d", parm_offset);
-      parm_offset += objc_encoded_type_size (type);
-
-      obstack_grow (&util_obstack, buf, strlen (buf));
-    }
-
-  finish_encoding:
-  obstack_1grow (&util_obstack, '\0');
-  result = get_identifier (XOBFINISH (&util_obstack, char *));
-  obstack_free (&util_obstack, util_firstobj);
-  return result;
-}
-
 /* Generate either '- .cxx_construct' or '- .cxx_destruct' for the
    current class.  */
 #ifdef OBJCPLUS
@@ -5864,25 +5739,6 @@ objc_build_selector_expr (location_t loc, tree selnamelist)
   return (*runtime.build_selector_reference) (loc, selname, NULL_TREE);
 }
 
-/* This is used to implement @encode().  See gcc/doc/objc.texi,
-   section '@encode'.  */
-tree
-objc_build_encode_expr (tree type)
-{
-  tree result;
-  const char *string;
-
-  encode_type (type, obstack_object_size (&util_obstack),
-              OBJC_ENCODE_INLINE_DEFS);
-  obstack_1grow (&util_obstack, 0);    /* null terminate string */
-  string = XOBFINISH (&util_obstack, const char *);
-
-  /* Synthesize a string that represents the encoded struct/union.  */
-  result = my_build_string (strlen (string) + 1, string);
-  obstack_free (&util_obstack, util_firstobj);
-  return result;
-}
-
 static tree
 build_ivar_reference (tree id)
 {
@@ -7308,7 +7164,7 @@ continue_class (tree klass)
 }
 
 /* This routine builds name of the setter synthesized function. */
-static char *
+char *
 objc_build_property_setter_name (tree ident)
 {
   /* TODO: Use alloca to allocate buffer of appropriate size.  */
@@ -10306,758 +10162,6 @@ objc_check_format_arg (tree ARG_UNUSED (format_arg),
 {
 }
 
-/* --- Encode --- */
-/* "Encode" a data type into a string, which grows in util_obstack.
-
-   The format is described in gcc/doc/objc.texi, section 'Type
-   encoding'.
-
-   Most of the encode_xxx functions have a 'type' argument, which is
-   the type to encode, and an integer 'curtype' argument, which is the
-   index in the encoding string of the beginning of the encoding of
-   the current type, and allows you to find what characters have
-   already been written for the current type (they are the ones in the
-   current encoding string starting from 'curtype').
-
-   For example, if we are encoding a method which returns 'int' and
-   takes a 'char **' argument, then when we get to the point of
-   encoding the 'char **' argument, the encoded string already
-   contains 'i12@0:4' (assuming a pointer size of 4 bytes).  So,
-   'curtype' will be set to 7 when starting to encode 'char **'.
-   During the whole of the encoding of 'char **', 'curtype' will be
-   fixed at 7, so the routine encoding the second pointer can find out
-   that it's actually encoding a pointer to a pointer by looking
-   backwards at what has already been encoded for the current type,
-   and seeing there is a "^" (meaning a pointer) in there.
-*/
-
-
-/* Encode type qualifiers encodes one of the "PQ" Objective-C
-   keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
-   'const', instead, is encoded directly as part of the type.
- */
-
-static void
-encode_type_qualifiers (tree declspecs)
-{
-  tree spec;
-
-  for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
-    {
-      /* FIXME: Shouldn't we use token->keyword here ? */
-      if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
-       obstack_1grow (&util_obstack, 'n');
-      else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
-       obstack_1grow (&util_obstack, 'N');
-      else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
-       obstack_1grow (&util_obstack, 'o');
-      else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
-       obstack_1grow (&util_obstack, 'O');
-      else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
-        obstack_1grow (&util_obstack, 'R');
-      else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
-       obstack_1grow (&util_obstack, 'V');
-      else
-       gcc_unreachable ();
-    }
-}
-
-/* Determine if a pointee is marked read-only.  Only used by the NeXT
-   runtime to be compatible with gcc-3.3.  */
-
-static bool
-pointee_is_readonly (tree pointee)
-{
-  while (POINTER_TYPE_P (pointee))
-    pointee = TREE_TYPE (pointee);
-
-  return TYPE_READONLY (pointee);
-}
-
-/* Encode a pointer type.  */
-
-static void
-encode_pointer (tree type, int curtype, int format)
-{
-  tree pointer_to = TREE_TYPE (type);
-
-  if (flag_next_runtime)
-    {
-      /* This code is used to be compatible with gcc-3.3.  */
-      /* For historical/compatibility reasons, the read-only qualifier
-        of the pointee gets emitted _before_ the '^'.  The read-only
-        qualifier of the pointer itself gets ignored, _unless_ we are
-        looking at a typedef!  Also, do not emit the 'r' for anything
-        but the outermost type!  */
-      if (!generating_instance_variables
-         && (obstack_object_size (&util_obstack) - curtype <= 1)
-         && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-             ? TYPE_READONLY (type)
-             : pointee_is_readonly (pointer_to)))
-       obstack_1grow (&util_obstack, 'r');
-    }
-
-  if (TREE_CODE (pointer_to) == RECORD_TYPE)
-    {
-      if (OBJC_TYPE_NAME (pointer_to)
-         && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
-       {
-         const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
-
-         if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
-           {
-             obstack_1grow (&util_obstack, '@');
-             return;
-           }
-         else if (TYPE_HAS_OBJC_INFO (pointer_to)
-                  && TYPE_OBJC_INTERFACE (pointer_to))
-           {
-              if (generating_instance_variables)
-               {
-                 obstack_1grow (&util_obstack, '@');
-                 obstack_1grow (&util_obstack, '"');
-                 obstack_grow (&util_obstack, name, strlen (name));
-                 obstack_1grow (&util_obstack, '"');
-                 return;
-               }
-              else
-               {
-                 obstack_1grow (&util_obstack, '@');
-                 return;
-               }
-           }
-         else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
-           {
-             obstack_1grow (&util_obstack, '#');
-             return;
-           }
-         else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
-           {
-             obstack_1grow (&util_obstack, ':');
-             return;
-           }
-       }
-    }
-  else if (TREE_CODE (pointer_to) == INTEGER_TYPE
-          && TYPE_MODE (pointer_to) == QImode)
-    {
-      tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
-                 ? OBJC_TYPE_NAME (pointer_to)
-                 : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
-
-      /* (BOOL *) are an exception and are encoded as ^c, while all
-        other pointers to char are encoded as *.   */
-      if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
-       {
-         if (!flag_next_runtime)
-           {
-             /* The NeXT runtime adds the 'r' before getting here.  */
-
-             /* It appears that "r*" means "const char *" rather than
-                "char *const".  "char *const" is encoded as "*",
-                which is identical to "char *", so the "const" is
-                unfortunately lost.  */
-             if (TYPE_READONLY (pointer_to))
-               obstack_1grow (&util_obstack, 'r');
-           }
-
-         obstack_1grow (&util_obstack, '*');
-         return;
-       }
-    }
-
-  /* We have a normal pointer type that does not get special treatment.  */
-  obstack_1grow (&util_obstack, '^');
-  encode_type (pointer_to, curtype, format);
-}
-
-static void
-encode_array (tree type, int curtype, int format)
-{
-  tree an_int_cst = TYPE_SIZE (type);
-  tree array_of = TREE_TYPE (type);
-  char buffer[40];
-
-  if (an_int_cst == NULL)
-    {
-      /* We are trying to encode an incomplete array.  An incomplete
-        array is forbidden as part of an instance variable; but it
-        may occur if the instance variable is a pointer to such an
-        array.  */
-
-      /* So the only case in which an incomplete array could occur
-        (without being pointed to) is if we are encoding the
-        arguments or return value of a method.  In that case, an
-        incomplete array argument or return value (eg,
-        -(void)display: (char[])string) is treated like a pointer
-        because that is how the compiler does the function call.  A
-        special, more complicated case, is when the incomplete array
-        is the last member of a struct (eg, if we are encoding
-        "struct { unsigned long int a;double b[];}"), which is again
-        part of a method argument/return value.  In that case, we
-        really need to communicate to the runtime that there is an
-        incomplete array (not a pointer!) there.  So, we detect that
-        special case and encode it as a zero-length array.
-
-        Try to detect that we are part of a struct.  We do this by
-        searching for '=' in the type encoding for the current type.
-        NB: This hack assumes that you can't use '=' as part of a C
-        identifier.
-      */
-      {
-       char *enc = obstack_base (&util_obstack) + curtype;
-       if (memchr (enc, '=',
-                   obstack_object_size (&util_obstack) - curtype) == NULL)
-         {
-           /* We are not inside a struct.  Encode the array as a
-              pointer.  */
-           encode_pointer (type, curtype, format);
-           return;
-         }
-      }
-
-      /* Else, we are in a struct, and we encode it as a zero-length
-        array.  */
-      sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
-    }
-  else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
-   sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
-  else
-    sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
-            TREE_INT_CST_LOW (an_int_cst)
-             / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
-
-  obstack_grow (&util_obstack, buffer, strlen (buffer));
-  encode_type (array_of, curtype, format);
-  obstack_1grow (&util_obstack, ']');
-  return;
-}
-
-/* Encode a vector.  The vector type is a GCC extension to C.  */
-static void
-encode_vector (tree type, int curtype, int format)
-{
-  tree vector_of = TREE_TYPE (type);
-  char buffer[40];
-
-  /* Vectors are like simple fixed-size arrays.  */
-
-  /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
-     alignment of the vector, and <code> is the base type.  Eg, int
-     __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
-     assuming that the alignment is 32 bytes.  We include size and
-     alignment in bytes so that the runtime does not have to have any
-     knowledge of the actual types.
-  */
-  sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
-          /* We want to compute the equivalent of sizeof (<vector>).
-             Code inspired by c_sizeof_or_alignof_type.  */
-          ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
-            / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
-          /* We want to compute the equivalent of __alignof__
-             (<vector>).  Code inspired by
-             c_sizeof_or_alignof_type.  */
-          TYPE_ALIGN_UNIT (type));
-  obstack_grow (&util_obstack, buffer, strlen (buffer));
-  encode_type (vector_of, curtype, format);
-  obstack_1grow (&util_obstack, ']');
-  return;
-}
-\f
-static void
-encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
-{
-  tree field = TYPE_FIELDS (type);
-
-  for (; field; field = DECL_CHAIN (field))
-    {
-#ifdef OBJCPLUS
-      /* C++ static members, and things that are not field at all,
-        should not appear in the encoding.  */
-      if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
-       continue;
-#endif
-
-      /* Recursively encode fields of embedded base classes.  */
-      if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
-         && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
-       {
-         encode_aggregate_fields (TREE_TYPE (field),
-                                  pointed_to, curtype, format);
-         continue;
-       }
-
-      if (generating_instance_variables && !pointed_to)
-       {
-         tree fname = DECL_NAME (field);
-
-         obstack_1grow (&util_obstack, '"');
-
-         if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
-           obstack_grow (&util_obstack,
-                         IDENTIFIER_POINTER (fname),
-                         strlen (IDENTIFIER_POINTER (fname)));
-
-         obstack_1grow (&util_obstack, '"');
-        }
-
-      encode_field_decl (field, curtype, format);
-    }
-}
-
-static void
-encode_aggregate_within (tree type, int curtype, int format, int left,
-                        int right)
-{
-  tree name;
-  /* NB: aggregates that are pointed to have slightly different encoding
-     rules in that you never encode the names of instance variables.  */
-  int ob_size = obstack_object_size (&util_obstack);
-  bool inline_contents = false;
-  bool pointed_to = false;
-
-  if (flag_next_runtime)
-    {
-      if (ob_size > 0  &&  *(obstack_next_free (&util_obstack) - 1) == '^')
-       pointed_to = true;
-
-      if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
-         && (!pointed_to || ob_size - curtype == 1
-             || (ob_size - curtype == 2
-                 && *(obstack_next_free (&util_obstack) - 2) == 'r')))
-       inline_contents = true;
-    }
-  else
-    {
-      /* c0 and c1 are the last two characters in the encoding of the
-        current type; if the last two characters were '^' or '^r',
-        then we are encoding an aggregate that is "pointed to".  The
-        comment above applies: in that case we should avoid encoding
-        the names of instance variables.
-      */
-      char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
-      char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
-
-      if (c0 == '^' || (c1 == '^' && c0 == 'r'))
-       pointed_to = true;
-
-      if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
-       {
-         if (!pointed_to)
-           inline_contents = true;
-         else
-           {
-             /* Note that the check (ob_size - curtype < 2) prevents
-                infinite recursion when encoding a structure which is
-                a linked list (eg, struct node { struct node *next;
-                }).  Each time we follow a pointer, we add one
-                character to ob_size, and curtype is fixed, so after
-                at most two pointers we stop inlining contents and
-                break the loop.
-
-                The other case where we don't inline is "^r", which
-                is a pointer to a constant struct.
-             */
-             if ((ob_size - curtype <= 2) && !(c0 == 'r'))
-               inline_contents = true;
-           }
-       }
-    }
-
-  /* Traverse struct aliases; it is important to get the
-     original struct and its tag name (if any).  */
-  type = TYPE_MAIN_VARIANT (type);
-  name = OBJC_TYPE_NAME (type);
-  /* Open parenth/bracket.  */
-  obstack_1grow (&util_obstack, left);
-
-  /* Encode the struct/union tag name, or '?' if a tag was
-     not provided.  Typedef aliases do not qualify.  */
-#ifdef OBJCPLUS
-  /* For compatibility with the NeXT runtime, ObjC++ encodes template
-     args as a composite struct tag name. */
-  if (name && TREE_CODE (name) == IDENTIFIER_NODE
-      /* Did this struct have a tag?  */
-      && !TYPE_WAS_ANONYMOUS (type))
-    obstack_grow (&util_obstack,
-                 decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
-                 strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
-#else
-  if (name && TREE_CODE (name) == IDENTIFIER_NODE)
-    obstack_grow (&util_obstack,
-                 IDENTIFIER_POINTER (name),
-                 strlen (IDENTIFIER_POINTER (name)));
-#endif
-  else
-    obstack_1grow (&util_obstack, '?');
-
-  /* Encode the types (and possibly names) of the inner fields,
-     if required.  */
-  if (inline_contents)
-    {
-      obstack_1grow (&util_obstack, '=');
-      encode_aggregate_fields (type, pointed_to, curtype, format);
-    }
-  /* Close parenth/bracket.  */
-  obstack_1grow (&util_obstack, right);
-}
-
-/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
-   field type.  */
-
-static void
-encode_next_bitfield (int width)
-{
-  char buffer[40];
-  sprintf (buffer, "b%d", width);
-  obstack_grow (&util_obstack, buffer, strlen (buffer));
-}
-
-/* Encodes 'type', ignoring type qualifiers (which you should encode
-   beforehand if needed) with the exception of 'const', which is
-   encoded by encode_type.  See above for the explanation of
-   'curtype'.  'format' can be OBJC_ENCODE_INLINE_DEFS or
-   OBJC_ENCODE_DONT_INLINE_DEFS.
-*/
-static void
-encode_type (tree type, int curtype, int format)
-{
-  enum tree_code code = TREE_CODE (type);
-
-  /* Ignore type qualifiers other than 'const' when encoding a
-     type.  */
-
-  if (type == error_mark_node)
-    return;
-
-  if (!flag_next_runtime)
-    {
-      if (TYPE_READONLY (type))
-       obstack_1grow (&util_obstack, 'r');
-    }
-
-  switch (code)
-    {
-    case ENUMERAL_TYPE:
-      if (flag_next_runtime)
-       {
-         /* Kludge for backwards-compatibility with gcc-3.3: enums
-            are always encoded as 'i' no matter what type they
-            actually are (!).  */
-         obstack_1grow (&util_obstack, 'i');
-         break;
-       }
-      /* Else, they are encoded exactly like the integer type that is
-        used by the compiler to store them.  */
-    case INTEGER_TYPE:
-      {
-       char c;
-       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
-         {
-         case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
-         case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
-         case 32:
-           {
-             tree int_type = type;
-             if (flag_next_runtime)
-               {
-                 /* Another legacy kludge for compatiblity with
-                    gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
-                    but not always.  For typedefs, we need to use 'i'
-                    or 'I' instead if encoding a struct field, or a
-                    pointer!  */
-                 int_type =  ((!generating_instance_variables
-                               && (obstack_object_size (&util_obstack)
-                                   == (unsigned) curtype))
-                              ? TYPE_MAIN_VARIANT (type)
-                              : type);
-               }
-             if (int_type == long_unsigned_type_node
-                 || int_type == long_integer_type_node)
-               c = TYPE_UNSIGNED (type) ? 'L' : 'l';
-             else
-               c = TYPE_UNSIGNED (type) ? 'I' : 'i';
-           }
-           break;
-         case 64:  c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
-         case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
-         default: gcc_unreachable ();
-         }
-       obstack_1grow (&util_obstack, c);
-       break;
-      }
-    case REAL_TYPE:
-      {
-       char c;
-       /* Floating point types.  */
-       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
-         {
-         case 32:  c = 'f'; break;
-         case 64:  c = 'd'; break;
-         case 96:
-         case 128: c = 'D'; break;
-         default: gcc_unreachable ();
-         }
-       obstack_1grow (&util_obstack, c);
-       break;
-      }
-    case VOID_TYPE:
-      obstack_1grow (&util_obstack, 'v');
-      break;
-
-    case BOOLEAN_TYPE:
-      obstack_1grow (&util_obstack, 'B');
-      break;
-
-    case ARRAY_TYPE:
-      encode_array (type, curtype, format);
-      break;
-
-    case POINTER_TYPE:
-#ifdef OBJCPLUS
-    case REFERENCE_TYPE:
-#endif
-      encode_pointer (type, curtype, format);
-      break;
-
-    case RECORD_TYPE:
-      encode_aggregate_within (type, curtype, format, '{', '}');
-      break;
-
-    case UNION_TYPE:
-      encode_aggregate_within (type, curtype, format, '(', ')');
-      break;
-
-    case FUNCTION_TYPE: /* '?' means an unknown type.  */
-      obstack_1grow (&util_obstack, '?');
-      break;
-
-    case COMPLEX_TYPE:
-      /* A complex is encoded as 'j' followed by the inner type (eg,
-        "_Complex int" is encoded as 'ji').  */
-      obstack_1grow (&util_obstack, 'j');
-      encode_type (TREE_TYPE (type), curtype, format);
-      break;
-
-    case VECTOR_TYPE:
-      encode_vector (type, curtype, format);
-      break;
-
-    default:
-      warning (0, "unknown type %s found during Objective-C encoding",
-              gen_type_name (type));
-      obstack_1grow (&util_obstack, '?');
-      break;
-    }
-
-  if (flag_next_runtime)
-    {
-      /* Super-kludge.  Some ObjC qualifier and type combinations need
-        to be rearranged for compatibility with gcc-3.3.  */
-      if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
-       {
-         char *enc = obstack_base (&util_obstack) + curtype;
-
-         /* Rewrite "in const" from "nr" to "rn".  */
-         if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
-           strncpy (enc - 1, "rn", 2);
-       }
-    }
-}
-
-static void
-encode_gnu_bitfield (int position, tree type, int size)
-{
-  enum tree_code code = TREE_CODE (type);
-  char buffer[40];
-  char charType = '?';
-
-  /* This code is only executed for the GNU runtime, so we can ignore
-     the NeXT runtime kludge of always encoding enums as 'i' no matter
-     what integers they actually are.  */
-  if (code == INTEGER_TYPE  ||  code == ENUMERAL_TYPE)
-    {
-      if (integer_zerop (TYPE_MIN_VALUE (type)))
-       /* Unsigned integer types.  */
-       {
-         switch (TYPE_MODE (type))
-           {
-           case QImode:
-             charType = 'C'; break;
-           case HImode:
-             charType = 'S'; break;
-           case SImode:
-             {
-               if (type == long_unsigned_type_node)
-                 charType = 'L';
-               else
-                 charType = 'I';
-               break;
-             }
-           case DImode:
-             charType = 'Q'; break;
-           default:
-             gcc_unreachable ();
-           }
-       }
-      else
-       /* Signed integer types.  */
-       {
-         switch (TYPE_MODE (type))
-           {
-           case QImode:
-             charType = 'c'; break;
-           case HImode:
-             charType = 's'; break;
-           case SImode:
-             {
-               if (type == long_integer_type_node)
-                 charType = 'l';
-               else
-                 charType = 'i';
-               break;
-             }
-           case DImode:
-             charType = 'q'; break;
-           default:
-             gcc_unreachable ();
-           }
-       }
-    }
-  else
-    {
-      /* Do not do any encoding, produce an error and keep going.  */
-      error ("trying to encode non-integer type as a bitfield");
-      return;
-    }
-
-  sprintf (buffer, "b%d%c%d", position, charType, size);
-  obstack_grow (&util_obstack, buffer, strlen (buffer));
-}
-
-void
-encode_field_decl (tree field_decl, int curtype, int format)
-{
-#ifdef OBJCPLUS
-  /* C++ static members, and things that are not fields at all,
-     should not appear in the encoding.  */
-  if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
-    return;
-#endif
-
-  /* Generate the bitfield typing information, if needed.  Note the difference
-     between GNU and NeXT runtimes.  */
-  if (DECL_BIT_FIELD_TYPE (field_decl))
-    {
-      int size = tree_low_cst (DECL_SIZE (field_decl), 1);
-
-      if (flag_next_runtime)
-       encode_next_bitfield (size);
-      else
-       encode_gnu_bitfield (int_bit_position (field_decl),
-                            DECL_BIT_FIELD_TYPE (field_decl), size);
-    }
-  else
-    encode_type (TREE_TYPE (field_decl), curtype, format);
-}
-
-/* This routine encodes the attribute of the input PROPERTY according
-   to following formula:
-
-   Property attributes are stored as a comma-delimited C string.
-   Simple attributes such as readonly are encoded as single
-   character. The parametrized attributes, getter=name and
-   setter=name, are encoded as a single character followed by an
-   identifier.  Property types are also encoded as a parametrized
-   attribute.  The characters used to encode these attributes are
-   defined by the following enumeration:
-
-   enum PropertyAttributes {
-     kPropertyReadOnly = 'R',
-     kPropertyBycopy = 'C',
-     kPropertyByref = '&',
-     kPropertyDynamic = 'D',
-     kPropertyGetter = 'G',
-     kPropertySetter = 'S',
-     kPropertyInstanceVariable = 'V',
-     kPropertyType = 'T',
-     kPropertyWeak = 'W',
-     kPropertyStrong = 'P',
-     kPropertyNonAtomic = 'N'
-   };  */
-tree
-objc_v2_encode_prop_attr (tree property)
-{
-  const char *string;
-  tree type = TREE_TYPE (property);
-
-  obstack_1grow (&util_obstack, 'T');
-  encode_type (type, obstack_object_size (&util_obstack),
-              OBJC_ENCODE_INLINE_DEFS);
-
-  if (PROPERTY_READONLY (property))
-    obstack_grow (&util_obstack, ",R", 2);
-
-  switch (PROPERTY_ASSIGN_SEMANTICS (property))
-    {
-    case OBJC_PROPERTY_COPY:
-      obstack_grow (&util_obstack, ",C", 2);
-      break;
-    case OBJC_PROPERTY_RETAIN:
-      obstack_grow (&util_obstack, ",&", 2);
-      break;
-    case OBJC_PROPERTY_ASSIGN:
-    default:
-      break;
-    }
-
-  if (PROPERTY_DYNAMIC (property))
-    obstack_grow (&util_obstack, ",D", 2);
-
-  if (PROPERTY_NONATOMIC (property))
-    obstack_grow (&util_obstack, ",N", 2);
-
-  /* Here we want to encode the getter name, but only if it's not the
-     standard one.  */
-  if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
-    {
-      obstack_grow (&util_obstack, ",G", 2);
-      string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
-      obstack_grow (&util_obstack, string, strlen (string));
-    }
-
-  if (!PROPERTY_READONLY (property))
-    {
-      /* Here we want to encode the setter name, but only if it's not
-        the standard one.  */
-      tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
-      if (PROPERTY_SETTER_NAME (property) != standard_setter)
-       {
-         obstack_grow (&util_obstack, ",S", 2);
-         string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
-         obstack_grow (&util_obstack, string, strlen (string));
-       }
-    }
-
-  /* TODO: Encode strong ('P'), weak ('W') for garbage collection.  */
-
-  if (!PROPERTY_DYNAMIC (property))
-    {
-      obstack_grow (&util_obstack, ",V", 2);
-      if (PROPERTY_IVAR_NAME (property))
-       string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
-      else
-       string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
-      obstack_grow (&util_obstack, string, strlen (string));
-    }
-
-  /* NULL-terminate string.  */
-  obstack_1grow (&util_obstack, 0);
-  string = XOBFINISH (&util_obstack, char *);
-  obstack_free (&util_obstack, util_firstobj);
-  return get_identifier (string);
-}
-
 void
 objc_common_init_ts (void)
 {
index 99551a80256311a43484f2d125bbb15d42323fc5..33f90fdb7850f3e8e838999b97f67f9a524bf634 100644 (file)
@@ -642,10 +642,6 @@ typedef enum string_section
 #define METHOD_DEF                     0
 #define METHOD_REF                     1
 
-/* (Decide if these can ever be validly changed.) */
-#define OBJC_ENCODE_INLINE_DEFS                0
-#define OBJC_ENCODE_DONT_INLINE_DEFS   1
-
 #define BUFSIZE                                1024
 
 #define CLS_FACTORY                    0x0001L
diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c
new file mode 100644 (file)
index 0000000..cb1d0c4
--- /dev/null
@@ -0,0 +1,926 @@
+/* Routines dealing with ObjC encoding of types
+   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
+   2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   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 3, 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 COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+
+#ifdef OBJCPLUS
+#include "cp-tree.h"
+#else
+#include "c-tree.h"
+#include "c-lang.h"
+#endif
+
+#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
+
+#include "objc-encoding.h"
+#include "objc-act.h"
+
+/* For my_build_string().  */
+#include "objc-runtime-shared-support.h"
+
+/* For BITS_PER_UNIT.  */
+#include "tm.h"
+
+/* When building Objective-C++, we are not linking against the C front-end
+   and so need to replicate the C tree-construction functions in some way.  */
+#ifdef OBJCPLUS
+#define OBJCP_REMAP_FUNCTIONS
+#include "objcp-decl.h"
+#endif  /* OBJCPLUS */
+
+/* Set up for use of obstacks.  */
+#include "obstack.h"
+
+/* This obstack is used to accumulate the encoding of a data type.
+   TODO: Make this static.  */
+struct obstack util_obstack;
+
+/* This points to the beginning of obstack contents, so we can free
+   the whole contents.  TODO: Make this static.  */
+char *util_firstobj;
+
+int generating_instance_variables = 0;
+
+static void encode_type_qualifiers (tree);
+static void encode_type (tree, int, int);
+
+static tree
+objc_method_parm_type (tree type)
+{
+  type = TREE_VALUE (TREE_TYPE (type));
+  if (TREE_CODE (type) == TYPE_DECL)
+    type = TREE_TYPE (type);
+  return type;
+}
+
+static int
+objc_encoded_type_size (tree type)
+{
+  int sz = int_size_in_bytes (type);
+
+  /* Make all integer and enum types at least as large
+     as an int.  */
+  if (sz > 0 && INTEGRAL_TYPE_P (type))
+    sz = MAX (sz, int_size_in_bytes (integer_type_node));
+  /* Treat arrays as pointers, since that's how they're
+     passed in.  */
+  else if (TREE_CODE (type) == ARRAY_TYPE)
+    sz = int_size_in_bytes (ptr_type_node);
+  return sz;
+}
+
+/* Encode a method prototype.  */
+tree
+encode_method_prototype (tree method_decl)
+{
+  tree parms;
+  int parm_offset, i;
+  char buf[40];
+  tree result;
+
+  /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
+  encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
+
+  /* Encode return type.  */
+  encode_type (objc_method_parm_type (method_decl),
+              obstack_object_size (&util_obstack),
+              OBJC_ENCODE_INLINE_DEFS);
+
+  /* Stack size.  */
+  /* The first two arguments (self and _cmd) are pointers; account for
+     their size.  */
+  i = int_size_in_bytes (ptr_type_node);
+  parm_offset = 2 * i;
+  for (parms = METHOD_SEL_ARGS (method_decl); parms;
+       parms = DECL_CHAIN (parms))
+    {
+      tree type = objc_method_parm_type (parms);
+      int sz = objc_encoded_type_size (type);
+
+      /* If a type size is not known, bail out.  */
+      if (sz < 0)
+       {
+         error_at (DECL_SOURCE_LOCATION (method_decl),
+                   "type %qT does not have a known size",
+                   type);
+         /* Pretend that the encoding succeeded; the compilation will
+            fail nevertheless.  */
+         goto finish_encoding;
+       }
+      parm_offset += sz;
+    }
+
+  sprintf (buf, "%d@0:%d", parm_offset, i);
+  obstack_grow (&util_obstack, buf, strlen (buf));
+
+  /* Argument types.  */
+  parm_offset = 2 * i;
+  for (parms = METHOD_SEL_ARGS (method_decl); parms;
+       parms = DECL_CHAIN (parms))
+    {
+      tree type = objc_method_parm_type (parms);
+
+      /* Process argument qualifiers for user supplied arguments.  */
+      encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
+
+      /* Type.  */
+      encode_type (type, obstack_object_size (&util_obstack),
+                  OBJC_ENCODE_INLINE_DEFS);
+
+      /* Compute offset.  */
+      sprintf (buf, "%d", parm_offset);
+      parm_offset += objc_encoded_type_size (type);
+
+      obstack_grow (&util_obstack, buf, strlen (buf));
+    }
+
+  finish_encoding:
+  obstack_1grow (&util_obstack, '\0');
+  result = get_identifier (XOBFINISH (&util_obstack, char *));
+  obstack_free (&util_obstack, util_firstobj);
+  return result;
+}
+
+/* This is used to implement @encode().  */
+tree
+objc_build_encode_expr (tree type)
+{
+  tree result;
+  const char *string;
+
+  encode_type (type, obstack_object_size (&util_obstack),
+              OBJC_ENCODE_INLINE_DEFS);
+  obstack_1grow (&util_obstack, 0);    /* null terminate string */
+  string = XOBFINISH (&util_obstack, const char *);
+
+  /* Synthesize a string that represents the encoded struct/union.  */
+  result = my_build_string (strlen (string) + 1, string);
+  obstack_free (&util_obstack, util_firstobj);
+  return result;
+}
+
+/* "Encode" a data type into a string, which grows in util_obstack.
+
+   The format is described in gcc/doc/objc.texi, section 'Type
+   encoding'.
+
+   Most of the encode_xxx functions have a 'type' argument, which is
+   the type to encode, and an integer 'curtype' argument, which is the
+   index in the encoding string of the beginning of the encoding of
+   the current type, and allows you to find what characters have
+   already been written for the current type (they are the ones in the
+   current encoding string starting from 'curtype').
+
+   For example, if we are encoding a method which returns 'int' and
+   takes a 'char **' argument, then when we get to the point of
+   encoding the 'char **' argument, the encoded string already
+   contains 'i12@0:4' (assuming a pointer size of 4 bytes).  So,
+   'curtype' will be set to 7 when starting to encode 'char **'.
+   During the whole of the encoding of 'char **', 'curtype' will be
+   fixed at 7, so the routine encoding the second pointer can find out
+   that it's actually encoding a pointer to a pointer by looking
+   backwards at what has already been encoded for the current type,
+   and seeing there is a "^" (meaning a pointer) in there.  */
+
+
+/* Encode type qualifiers encodes one of the "PQ" Objective-C
+   keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
+   'const', instead, is encoded directly as part of the type.  */
+static void
+encode_type_qualifiers (tree declspecs)
+{
+  tree spec;
+
+  for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
+    {
+      /* FIXME: Shouldn't we use token->keyword here ? */
+      if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
+       obstack_1grow (&util_obstack, 'n');
+      else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
+       obstack_1grow (&util_obstack, 'N');
+      else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
+       obstack_1grow (&util_obstack, 'o');
+      else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
+       obstack_1grow (&util_obstack, 'O');
+      else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
+        obstack_1grow (&util_obstack, 'R');
+      else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
+       obstack_1grow (&util_obstack, 'V');
+      else
+       gcc_unreachable ();
+    }
+}
+
+/* Determine if a pointee is marked read-only.  Only used by the NeXT
+   runtime to be compatible with gcc-3.3.  */
+static bool
+pointee_is_readonly (tree pointee)
+{
+  while (POINTER_TYPE_P (pointee))
+    pointee = TREE_TYPE (pointee);
+
+  return TYPE_READONLY (pointee);
+}
+
+/* Encode a pointer type.  */
+static void
+encode_pointer (tree type, int curtype, int format)
+{
+  tree pointer_to = TREE_TYPE (type);
+
+  if (flag_next_runtime)
+    {
+      /* This code is used to be compatible with gcc-3.3.  */
+      /* For historical/compatibility reasons, the read-only qualifier
+        of the pointee gets emitted _before_ the '^'.  The read-only
+        qualifier of the pointer itself gets ignored, _unless_ we are
+        looking at a typedef!  Also, do not emit the 'r' for anything
+        but the outermost type!  */
+      if (!generating_instance_variables
+         && (obstack_object_size (&util_obstack) - curtype <= 1)
+         && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+             ? TYPE_READONLY (type)
+             : pointee_is_readonly (pointer_to)))
+       obstack_1grow (&util_obstack, 'r');
+    }
+
+  if (TREE_CODE (pointer_to) == RECORD_TYPE)
+    {
+      if (OBJC_TYPE_NAME (pointer_to)
+         && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
+       {
+         const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
+
+         if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
+           {
+             obstack_1grow (&util_obstack, '@');
+             return;
+           }
+         else if (TYPE_HAS_OBJC_INFO (pointer_to)
+                  && TYPE_OBJC_INTERFACE (pointer_to))
+           {
+              if (generating_instance_variables)
+               {
+                 obstack_1grow (&util_obstack, '@');
+                 obstack_1grow (&util_obstack, '"');
+                 obstack_grow (&util_obstack, name, strlen (name));
+                 obstack_1grow (&util_obstack, '"');
+                 return;
+               }
+              else
+               {
+                 obstack_1grow (&util_obstack, '@');
+                 return;
+               }
+           }
+         else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
+           {
+             obstack_1grow (&util_obstack, '#');
+             return;
+           }
+         else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
+           {
+             obstack_1grow (&util_obstack, ':');
+             return;
+           }
+       }
+    }
+  else if (TREE_CODE (pointer_to) == INTEGER_TYPE
+          && TYPE_MODE (pointer_to) == QImode)
+    {
+      tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
+                 ? OBJC_TYPE_NAME (pointer_to)
+                 : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
+
+      /* (BOOL *) are an exception and are encoded as ^c, while all
+        other pointers to char are encoded as *.   */
+      if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
+       {
+         if (!flag_next_runtime)
+           {
+             /* The NeXT runtime adds the 'r' before getting here.  */
+
+             /* It appears that "r*" means "const char *" rather than
+                "char *const".  "char *const" is encoded as "*",
+                which is identical to "char *", so the "const" is
+                unfortunately lost.  */
+             if (TYPE_READONLY (pointer_to))
+               obstack_1grow (&util_obstack, 'r');
+           }
+
+         obstack_1grow (&util_obstack, '*');
+         return;
+       }
+    }
+
+  /* We have a normal pointer type that does not get special treatment.  */
+  obstack_1grow (&util_obstack, '^');
+  encode_type (pointer_to, curtype, format);
+}
+
+static void
+encode_array (tree type, int curtype, int format)
+{
+  tree an_int_cst = TYPE_SIZE (type);
+  tree array_of = TREE_TYPE (type);
+  char buffer[40];
+
+  if (an_int_cst == NULL)
+    {
+      /* We are trying to encode an incomplete array.  An incomplete
+        array is forbidden as part of an instance variable; but it
+        may occur if the instance variable is a pointer to such an
+        array.  */
+
+      /* So the only case in which an incomplete array could occur
+        (without being pointed to) is if we are encoding the
+        arguments or return value of a method.  In that case, an
+        incomplete array argument or return value (eg,
+        -(void)display: (char[])string) is treated like a pointer
+        because that is how the compiler does the function call.  A
+        special, more complicated case, is when the incomplete array
+        is the last member of a struct (eg, if we are encoding
+        "struct { unsigned long int a;double b[];}"), which is again
+        part of a method argument/return value.  In that case, we
+        really need to communicate to the runtime that there is an
+        incomplete array (not a pointer!) there.  So, we detect that
+        special case and encode it as a zero-length array.
+
+        Try to detect that we are part of a struct.  We do this by
+        searching for '=' in the type encoding for the current type.
+        NB: This hack assumes that you can't use '=' as part of a C
+        identifier.
+      */
+      {
+       char *enc = obstack_base (&util_obstack) + curtype;
+       if (memchr (enc, '=',
+                   obstack_object_size (&util_obstack) - curtype) == NULL)
+         {
+           /* We are not inside a struct.  Encode the array as a
+              pointer.  */
+           encode_pointer (type, curtype, format);
+           return;
+         }
+      }
+
+      /* Else, we are in a struct, and we encode it as a zero-length
+        array.  */
+      sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
+    }
+  else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
+   sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
+  else
+    sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
+            TREE_INT_CST_LOW (an_int_cst)
+             / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
+
+  obstack_grow (&util_obstack, buffer, strlen (buffer));
+  encode_type (array_of, curtype, format);
+  obstack_1grow (&util_obstack, ']');
+  return;
+}
+
+/* Encode a vector.  The vector type is a GCC extension to C.  */
+static void
+encode_vector (tree type, int curtype, int format)
+{
+  tree vector_of = TREE_TYPE (type);
+  char buffer[40];
+
+  /* Vectors are like simple fixed-size arrays.  */
+
+  /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
+     alignment of the vector, and <code> is the base type.  Eg, int
+     __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
+     assuming that the alignment is 32 bytes.  We include size and
+     alignment in bytes so that the runtime does not have to have any
+     knowledge of the actual types.
+  */
+  sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
+          /* We want to compute the equivalent of sizeof (<vector>).
+             Code inspired by c_sizeof_or_alignof_type.  */
+          ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
+            / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
+          /* We want to compute the equivalent of __alignof__
+             (<vector>).  Code inspired by
+             c_sizeof_or_alignof_type.  */
+          TYPE_ALIGN_UNIT (type));
+  obstack_grow (&util_obstack, buffer, strlen (buffer));
+  encode_type (vector_of, curtype, format);
+  obstack_1grow (&util_obstack, ']');
+  return;
+}
+
+static void
+encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
+{
+  tree field = TYPE_FIELDS (type);
+
+  for (; field; field = DECL_CHAIN (field))
+    {
+#ifdef OBJCPLUS
+      /* C++ static members, and things that are not field at all,
+        should not appear in the encoding.  */
+      if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
+       continue;
+#endif
+
+      /* Recursively encode fields of embedded base classes.  */
+      if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
+         && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
+       {
+         encode_aggregate_fields (TREE_TYPE (field),
+                                  pointed_to, curtype, format);
+         continue;
+       }
+
+      if (generating_instance_variables && !pointed_to)
+       {
+         tree fname = DECL_NAME (field);
+
+         obstack_1grow (&util_obstack, '"');
+
+         if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
+           obstack_grow (&util_obstack,
+                         IDENTIFIER_POINTER (fname),
+                         strlen (IDENTIFIER_POINTER (fname)));
+
+         obstack_1grow (&util_obstack, '"');
+        }
+
+      encode_field_decl (field, curtype, format);
+    }
+}
+
+static void
+encode_aggregate_within (tree type, int curtype, int format, int left,
+                        int right)
+{
+  tree name;
+  /* NB: aggregates that are pointed to have slightly different encoding
+     rules in that you never encode the names of instance variables.  */
+  int ob_size = obstack_object_size (&util_obstack);
+  bool inline_contents = false;
+  bool pointed_to = false;
+
+  if (flag_next_runtime)
+    {
+      if (ob_size > 0  &&  *(obstack_next_free (&util_obstack) - 1) == '^')
+       pointed_to = true;
+
+      if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
+         && (!pointed_to || ob_size - curtype == 1
+             || (ob_size - curtype == 2
+                 && *(obstack_next_free (&util_obstack) - 2) == 'r')))
+       inline_contents = true;
+    }
+  else
+    {
+      /* c0 and c1 are the last two characters in the encoding of the
+        current type; if the last two characters were '^' or '^r',
+        then we are encoding an aggregate that is "pointed to".  The
+        comment above applies: in that case we should avoid encoding
+        the names of instance variables.
+      */
+      char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
+      char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
+
+      if (c0 == '^' || (c1 == '^' && c0 == 'r'))
+       pointed_to = true;
+
+      if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
+       {
+         if (!pointed_to)
+           inline_contents = true;
+         else
+           {
+             /* Note that the check (ob_size - curtype < 2) prevents
+                infinite recursion when encoding a structure which is
+                a linked list (eg, struct node { struct node *next;
+                }).  Each time we follow a pointer, we add one
+                character to ob_size, and curtype is fixed, so after
+                at most two pointers we stop inlining contents and
+                break the loop.
+
+                The other case where we don't inline is "^r", which
+                is a pointer to a constant struct.
+             */
+             if ((ob_size - curtype <= 2) && !(c0 == 'r'))
+               inline_contents = true;
+           }
+       }
+    }
+
+  /* Traverse struct aliases; it is important to get the
+     original struct and its tag name (if any).  */
+  type = TYPE_MAIN_VARIANT (type);
+  name = OBJC_TYPE_NAME (type);
+  /* Open parenth/bracket.  */
+  obstack_1grow (&util_obstack, left);
+
+  /* Encode the struct/union tag name, or '?' if a tag was
+     not provided.  Typedef aliases do not qualify.  */
+#ifdef OBJCPLUS
+  /* For compatibility with the NeXT runtime, ObjC++ encodes template
+     args as a composite struct tag name. */
+  if (name && TREE_CODE (name) == IDENTIFIER_NODE
+      /* Did this struct have a tag?  */
+      && !TYPE_WAS_ANONYMOUS (type))
+    obstack_grow (&util_obstack,
+                 decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
+                 strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
+#else
+  if (name && TREE_CODE (name) == IDENTIFIER_NODE)
+    obstack_grow (&util_obstack,
+                 IDENTIFIER_POINTER (name),
+                 strlen (IDENTIFIER_POINTER (name)));
+#endif
+  else
+    obstack_1grow (&util_obstack, '?');
+
+  /* Encode the types (and possibly names) of the inner fields,
+     if required.  */
+  if (inline_contents)
+    {
+      obstack_1grow (&util_obstack, '=');
+      encode_aggregate_fields (type, pointed_to, curtype, format);
+    }
+  /* Close parenth/bracket.  */
+  obstack_1grow (&util_obstack, right);
+}
+
+/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
+   field type.  */
+static void
+encode_next_bitfield (int width)
+{
+  char buffer[40];
+  sprintf (buffer, "b%d", width);
+  obstack_grow (&util_obstack, buffer, strlen (buffer));
+}
+
+/* Encodes 'type', ignoring type qualifiers (which you should encode
+   beforehand if needed) with the exception of 'const', which is
+   encoded by encode_type.  See above for the explanation of
+   'curtype'.  'format' can be OBJC_ENCODE_INLINE_DEFS or
+   OBJC_ENCODE_DONT_INLINE_DEFS.  */
+static void
+encode_type (tree type, int curtype, int format)
+{
+  enum tree_code code = TREE_CODE (type);
+
+  /* Ignore type qualifiers other than 'const' when encoding a
+     type.  */
+
+  if (type == error_mark_node)
+    return;
+
+  if (!flag_next_runtime)
+    {
+      if (TYPE_READONLY (type))
+       obstack_1grow (&util_obstack, 'r');
+    }
+
+  switch (code)
+    {
+    case ENUMERAL_TYPE:
+      if (flag_next_runtime)
+       {
+         /* Kludge for backwards-compatibility with gcc-3.3: enums
+            are always encoded as 'i' no matter what type they
+            actually are (!).  */
+         obstack_1grow (&util_obstack, 'i');
+         break;
+       }
+      /* Else, they are encoded exactly like the integer type that is
+        used by the compiler to store them.  */
+    case INTEGER_TYPE:
+      {
+       char c;
+       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+         {
+         case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
+         case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
+         case 32:
+           {
+             tree int_type = type;
+             if (flag_next_runtime)
+               {
+                 /* Another legacy kludge for compatiblity with
+                    gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
+                    but not always.  For typedefs, we need to use 'i'
+                    or 'I' instead if encoding a struct field, or a
+                    pointer!  */
+                 int_type =  ((!generating_instance_variables
+                               && (obstack_object_size (&util_obstack)
+                                   == (unsigned) curtype))
+                              ? TYPE_MAIN_VARIANT (type)
+                              : type);
+               }
+             if (int_type == long_unsigned_type_node
+                 || int_type == long_integer_type_node)
+               c = TYPE_UNSIGNED (type) ? 'L' : 'l';
+             else
+               c = TYPE_UNSIGNED (type) ? 'I' : 'i';
+           }
+           break;
+         case 64:  c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
+         case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
+         default: gcc_unreachable ();
+         }
+       obstack_1grow (&util_obstack, c);
+       break;
+      }
+    case REAL_TYPE:
+      {
+       char c;
+       /* Floating point types.  */
+       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+         {
+         case 32:  c = 'f'; break;
+         case 64:  c = 'd'; break;
+         case 96:
+         case 128: c = 'D'; break;
+         default: gcc_unreachable ();
+         }
+       obstack_1grow (&util_obstack, c);
+       break;
+      }
+    case VOID_TYPE:
+      obstack_1grow (&util_obstack, 'v');
+      break;
+
+    case BOOLEAN_TYPE:
+      obstack_1grow (&util_obstack, 'B');
+      break;
+
+    case ARRAY_TYPE:
+      encode_array (type, curtype, format);
+      break;
+
+    case POINTER_TYPE:
+#ifdef OBJCPLUS
+    case REFERENCE_TYPE:
+#endif
+      encode_pointer (type, curtype, format);
+      break;
+
+    case RECORD_TYPE:
+      encode_aggregate_within (type, curtype, format, '{', '}');
+      break;
+
+    case UNION_TYPE:
+      encode_aggregate_within (type, curtype, format, '(', ')');
+      break;
+
+    case FUNCTION_TYPE: /* '?' means an unknown type.  */
+      obstack_1grow (&util_obstack, '?');
+      break;
+
+    case COMPLEX_TYPE:
+      /* A complex is encoded as 'j' followed by the inner type (eg,
+        "_Complex int" is encoded as 'ji').  */
+      obstack_1grow (&util_obstack, 'j');
+      encode_type (TREE_TYPE (type), curtype, format);
+      break;
+
+    case VECTOR_TYPE:
+      encode_vector (type, curtype, format);
+      break;
+
+    default:
+      warning (0, "unknown type %<%T%> found during Objective-C encoding",
+              TREE_TYPE (type));
+      obstack_1grow (&util_obstack, '?');
+      break;
+    }
+
+  if (flag_next_runtime)
+    {
+      /* Super-kludge.  Some ObjC qualifier and type combinations need
+        to be rearranged for compatibility with gcc-3.3.  */
+      if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
+       {
+         char *enc = obstack_base (&util_obstack) + curtype;
+
+         /* Rewrite "in const" from "nr" to "rn".  */
+         if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
+           strncpy (enc - 1, "rn", 2);
+       }
+    }
+}
+
+static void
+encode_gnu_bitfield (int position, tree type, int size)
+{
+  enum tree_code code = TREE_CODE (type);
+  char buffer[40];
+  char charType = '?';
+
+  /* This code is only executed for the GNU runtime, so we can ignore
+     the NeXT runtime kludge of always encoding enums as 'i' no matter
+     what integers they actually are.  */
+  if (code == INTEGER_TYPE  ||  code == ENUMERAL_TYPE)
+    {
+      if (integer_zerop (TYPE_MIN_VALUE (type)))
+       /* Unsigned integer types.  */
+       {
+         switch (TYPE_MODE (type))
+           {
+           case QImode:
+             charType = 'C'; break;
+           case HImode:
+             charType = 'S'; break;
+           case SImode:
+             {
+               if (type == long_unsigned_type_node)
+                 charType = 'L';
+               else
+                 charType = 'I';
+               break;
+             }
+           case DImode:
+             charType = 'Q'; break;
+           default:
+             gcc_unreachable ();
+           }
+       }
+      else
+       /* Signed integer types.  */
+       {
+         switch (TYPE_MODE (type))
+           {
+           case QImode:
+             charType = 'c'; break;
+           case HImode:
+             charType = 's'; break;
+           case SImode:
+             {
+               if (type == long_integer_type_node)
+                 charType = 'l';
+               else
+                 charType = 'i';
+               break;
+             }
+           case DImode:
+             charType = 'q'; break;
+           default:
+             gcc_unreachable ();
+           }
+       }
+    }
+  else
+    {
+      /* Do not do any encoding, produce an error and keep going.  */
+      error ("trying to encode non-integer type as a bitfield");
+      return;
+    }
+
+  sprintf (buffer, "b%d%c%d", position, charType, size);
+  obstack_grow (&util_obstack, buffer, strlen (buffer));
+}
+
+void
+encode_field_decl (tree field_decl, int curtype, int format)
+{
+#ifdef OBJCPLUS
+  /* C++ static members, and things that are not fields at all,
+     should not appear in the encoding.  */
+  if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
+    return;
+#endif
+
+  /* Generate the bitfield typing information, if needed.  Note the difference
+     between GNU and NeXT runtimes.  */
+  if (DECL_BIT_FIELD_TYPE (field_decl))
+    {
+      int size = tree_low_cst (DECL_SIZE (field_decl), 1);
+
+      if (flag_next_runtime)
+       encode_next_bitfield (size);
+      else
+       encode_gnu_bitfield (int_bit_position (field_decl),
+                            DECL_BIT_FIELD_TYPE (field_decl), size);
+    }
+  else
+    encode_type (TREE_TYPE (field_decl), curtype, format);
+}
+
+/* This routine encodes the attribute of the input PROPERTY according
+   to following formula:
+
+   Property attributes are stored as a comma-delimited C string.
+   Simple attributes such as readonly are encoded as single
+   character. The parametrized attributes, getter=name and
+   setter=name, are encoded as a single character followed by an
+   identifier.  Property types are also encoded as a parametrized
+   attribute.  The characters used to encode these attributes are
+   defined by the following enumeration:
+
+   enum PropertyAttributes {
+     kPropertyReadOnly = 'R',
+     kPropertyBycopy = 'C',
+     kPropertyByref = '&',
+     kPropertyDynamic = 'D',
+     kPropertyGetter = 'G',
+     kPropertySetter = 'S',
+     kPropertyInstanceVariable = 'V',
+     kPropertyType = 'T',
+     kPropertyWeak = 'W',
+     kPropertyStrong = 'P',
+     kPropertyNonAtomic = 'N'
+   };  */
+tree
+objc_v2_encode_prop_attr (tree property)
+{
+  const char *string;
+  tree type = TREE_TYPE (property);
+
+  obstack_1grow (&util_obstack, 'T');
+  encode_type (type, obstack_object_size (&util_obstack),
+              OBJC_ENCODE_INLINE_DEFS);
+
+  if (PROPERTY_READONLY (property))
+    obstack_grow (&util_obstack, ",R", 2);
+
+  switch (PROPERTY_ASSIGN_SEMANTICS (property))
+    {
+    case OBJC_PROPERTY_COPY:
+      obstack_grow (&util_obstack, ",C", 2);
+      break;
+    case OBJC_PROPERTY_RETAIN:
+      obstack_grow (&util_obstack, ",&", 2);
+      break;
+    case OBJC_PROPERTY_ASSIGN:
+    default:
+      break;
+    }
+
+  if (PROPERTY_DYNAMIC (property))
+    obstack_grow (&util_obstack, ",D", 2);
+
+  if (PROPERTY_NONATOMIC (property))
+    obstack_grow (&util_obstack, ",N", 2);
+
+  /* Here we want to encode the getter name, but only if it's not the
+     standard one.  */
+  if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
+    {
+      obstack_grow (&util_obstack, ",G", 2);
+      string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
+      obstack_grow (&util_obstack, string, strlen (string));
+    }
+
+  if (!PROPERTY_READONLY (property))
+    {
+      /* Here we want to encode the setter name, but only if it's not
+        the standard one.  */
+      tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
+      if (PROPERTY_SETTER_NAME (property) != standard_setter)
+       {
+         obstack_grow (&util_obstack, ",S", 2);
+         string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
+         obstack_grow (&util_obstack, string, strlen (string));
+       }
+    }
+
+  /* TODO: Encode strong ('P'), weak ('W') for garbage collection.  */
+
+  if (!PROPERTY_DYNAMIC (property))
+    {
+      obstack_grow (&util_obstack, ",V", 2);
+      if (PROPERTY_IVAR_NAME (property))
+       string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
+      else
+       string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
+      obstack_grow (&util_obstack, string, strlen (string));
+    }
+
+  /* NULL-terminate string.  */
+  obstack_1grow (&util_obstack, 0);
+  string = XOBFINISH (&util_obstack, char *);
+  obstack_free (&util_obstack, util_firstobj);
+  return get_identifier (string);
+}
diff --git a/gcc/objc/objc-encoding.h b/gcc/objc/objc-encoding.h
new file mode 100644 (file)
index 0000000..2fad593
--- /dev/null
@@ -0,0 +1,74 @@
+/* Routines dealing with ObjC encoding of types
+   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
+   2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   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 3, 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 COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_OBJC_ENCODING_H
+#define GCC_OBJC_ENCODING_H
+
+/* TODO: Hide the following obstack code in objc-encoding.c, and have
+   a objc_encoding_init() that is called by objc_init() to set them
+   up.  */
+
+/* Set up for use of obstacks.  */
+#include "obstack.h"
+
+/* This obstack is used to accumulate the encoding of a data type.  */
+extern struct obstack util_obstack;
+
+/* This points to the beginning of obstack contents, so we can free
+   the whole contents.  */
+extern char *util_firstobj;
+
+/* This will be used to initialize the obstacks used by encoding.  It
+   should be called before any encoding function is used.  It is
+   usually done in objc_init().  */
+/* extern void objc_encoding_init (void); */
+
+
+/* Encode a method prototype.  The format is described in
+   gcc/doc/objc.texi, section 'Method signatures'.  */
+extern tree encode_method_prototype (tree method_decl);
+
+/* This is used to implement @encode().  See gcc/doc/objc.texi,
+   section '@encode'.  */
+extern tree objc_build_encode_expr (tree type);
+
+/* (Decide if these can ever be validly changed.)  */
+#define OBJC_ENCODE_INLINE_DEFS                0
+#define OBJC_ENCODE_DONT_INLINE_DEFS   1
+
+/* Encode the attributes of a property.  */
+extern tree objc_v2_encode_prop_attr (tree property);
+
+/* Encode the type of a field.  */
+extern void encode_field_decl (tree field_decl, int curtype, int format);
+
+/* Tells "encode_pointer/encode_aggregate" whether we are generating
+   type descriptors for instance variables (as opposed to methods).
+   Type descriptors for instance variables contain more information
+   than methods (for static typing and embedded structures).
+
+   TODO: Replace this global variable with an argument that is passed
+   to the various encode() functions.
+
+   TODO: Change it to a 'bool'.  */
+extern int generating_instance_variables;
+
+#endif /* GCC_OBJC_ENCODING_H */
index d21f2e9a6b598044b89384074a2486c6023e3a2a..fef5355c6a6e20991a8782f7b37417a57023dfdd 100644 (file)
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "objc-runtime-hooks.h"
 #include "objc-runtime-shared-support.h"
+#include "objc-encoding.h"
 
 /* GNU runtime private definitions.  */
 #define DEF_CONSTANT_STRING_CLASS_NAME "NXConstantString"
index d5b795fbb0e78249e2c81585730e7b2d77e070cb..6183a21e5e85c62e9a6d9f68b331a77470d2bef0 100644 (file)
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "objc-runtime-hooks.h"
 #include "objc-runtime-shared-support.h"
+#include "objc-encoding.h"
 
 /* NeXT ABI 0 and 1 private definitions.  */
 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
index fd9bb9923deb2cc57a290ed7b0a1eb7f176e6256..e7570c7e4b25e5b7093cf175bb6a07e1c89c91ab 100644 (file)
@@ -58,8 +58,8 @@ extern struct obstack util_obstack;
 extern char *util_firstobj;
 
 #include "objc-runtime-hooks.h"
-
 #include "objc-runtime-shared-support.h"
+#include "objc-encoding.h"
 
 /* ABI 2 Private definitions. */
 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
index 78505f4d5e80dd65dc1f30f863d6d9a621bdcb46..913b0fd7e2b45ed6b91a9cbb17ebe991efd26b2a 100644 (file)
@@ -51,6 +51,7 @@ extern char *util_firstobj;
 #include "objc-runtime-hooks.h"
 
 #include "objc-runtime-shared-support.h"
+#include "objc-encoding.h"
 
 /* rt_trees identifiers - shared between NeXT implementations.  These allow
    the FE to tag meta-data in a manner that survives LTO and can be used when
index bb0e5711df0924428c7effe5c8cd138ee152f1a5..0db8bed124086bf4204876f6e3b9e99ae34f5b66 100644 (file)
@@ -52,20 +52,17 @@ extern void objc_push_parm (tree);
 
 extern tree build_function_type_for_method (tree, tree, int, bool);
 
+extern char *objc_build_property_setter_name (tree);
+
 /* Stuff that should be migrated to shared support (or some v1-only file).  */
 extern void build_super_template (void);
 
 extern tree objc_build_component_ref (tree, tree);
 
-extern tree objc_v2_encode_prop_attr (tree);
 extern tree build_descriptor_table_initializer (tree, tree);
 extern tree build_method_prototype_list_template (tree, int);
 extern tree build_protocol_initializer (tree, tree, tree, tree, tree);
 
-/* Stuff that should be migrated to shared encode.  */
-extern tree encode_method_prototype (tree);
-extern void encode_field_decl (tree, int, int);
-
 /* Moved or new routines in objc-runtime-shared-support.c  */
 
 extern tree build_selector (tree);
@@ -85,7 +82,6 @@ extern tree build_ivar_template (void);
 extern void generate_strings (void);
 
 extern void dump_interface (FILE *, tree);
-extern int generating_instance_variables;
 extern FILE *gen_declaration_file;
 
 #endif /* _OBJC_RUNTIME_SHARED_SUPPORT_H_ */
index dba3907fa76757626aaa5888d0b158271a28704c..e137c9936e3657fa0bd19df78132b7d47c57ac07 100644 (file)
@@ -1,3 +1,19 @@
+2011-07-04  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * Make-lang.in (OBJCXX_OBJS): Added objc-encoding.o.
+       (objcp/objcp-lang.o): Reordered dependencies.  Depend on GGC_H.
+       (objcp/objcp-decl.o): Reordered dependencies.
+       (objcp/objc-runtime-shared-support.o): Reordered dependencies.
+       Updated them to be identical to the corresponding new objc/ ones,
+       with the addition of objcp-decl.h.
+       (objcp/objc-runtime-shared-support.o): Likewise.
+       (objcp/objc-gnu-runtime-abi-01.o): Likewise.
+       (objcp/objc-next-runtime-abi-01.o): Likewise.
+       (objcp/objc-next-runtime-abi-02.o): Likewise.
+       (objcp/objcp-act.o): Reordered dependencies.  Added dependency on
+       objc-encoding.h.
+       (objcp/objc-encoding.o): New rule.
+       
 2011-04-15  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objcp-decl.c (objcp_finish_struct): Use
index 7e0ef5c42572e24257fed5cd1d5c1fbf8698a984..f454e5fcd221015f43cf33b520b7d330b99500a5 100644 (file)
@@ -57,6 +57,7 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o objcp/objcp-decl.o \
    objcp/objc-gnu-runtime-abi-01.o \
    objcp/objc-next-runtime-abi-01.o \
    objcp/objc-next-runtime-abi-02.o \
+   objcp/objc-encoding.o \
    $(CXX_AND_OBJCXX_OBJS)
 
 obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o
@@ -76,48 +77,96 @@ cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBDEPS)
 
 # Objective C++ language specific files.
 
-objcp/objcp-lang.o : objcp/objcp-lang.c $(START_HDRS) \
+objcp/objcp-lang.o : objcp/objcp-lang.c \
+  $(START_HDRS) \
+  $(GGC_H) \
   $(C_COMMON_H) $(LANGHOOKS_DEF_H) cp/cp-objcp-common.h \
   $(TARGET_H) gtype-objcp.h
 
 objcp/objcp-decl.o : objcp/objcp-decl.c \
    $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \
-   objc/objc-act.h objcp/objcp-decl.h c-family/c-objc.h
+   objc/objc-act.h c-family/c-objc.h \
+   objcp/objcp-decl.h
 
 objcp/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
-   $(START_HDRS) objc/objc-runtime-shared-support.h $(OBSTACK_H) \
-   objc/objc-next-metadata-tags.h gt-objc-objc-runtime-shared-support.h
+   gt-objc-objc-runtime-shared-support.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   objc/objc-encoding.h \
+   objc/objc-next-metadata-tags.h \
+   objc/objc-runtime-shared-support.h \
+   objcp/objcp-decl.h
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
                $(OUTPUT_OPTION)
 
-objcp/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c $(START_HDRS) \
-   objc/objc-runtime-hooks.h $(GGC_H) \
-   gt-objc-objc-gnu-runtime-abi-01.h toplev.h 
+objcp/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c \
+   gt-objc-objc-gnu-runtime-abi-01.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   toplev.h \
+   objc/objc-encoding.h \
+   objc/objc-runtime-hooks.h \
+   objc/objc-runtime-shared-support.h \
+   objcp/objcp-decl.h
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
                $(OUTPUT_OPTION)
 
-objcp/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c $(START_HDRS) \
-   $(GGC_H) objc/objc-runtime-hooks.h \
-   objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-01.h output.h \
-   objc/objc-runtime-shared-support.h $(TARGET_H)
+objcp/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c \
+   gt-objc-objc-next-runtime-abi-01.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   $(TARGET_H) output.h \
+   objc/objc-encoding.h \
+   objc/objc-next-metadata-tags.h \
+   objc/objc-runtime-hooks.h \
+   objc/objc-runtime-shared-support.h \
+   objcp/objcp-decl.h
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
                $(OUTPUT_OPTION)
 
-objcp/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c $(START_HDRS) \
-   $(GGC_H) objc/objc-runtime-hooks.h \
-   objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-02.h $(TARGET_H) \
-   objc/objc-runtime-shared-support.h $(OBSTACK_H)
+objcp/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c \
+   gt-objc-objc-next-runtime-abi-02.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   $(TARGET_H) \
+   objc/objc-encoding.h \
+   objc/objc-next-metadata-tags.h \
+   objc/objc-runtime-hooks.h \
+   objc/objc-runtime-shared-support.h \
+   objcp/objcp-decl.h
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
                $(OUTPUT_OPTION)
 
 
 # The following must be an explicit rule; please keep in sync with the implicit
 # one in Makefile.in.
-objcp/objcp-act.o : objc/objc-act.c $(START_HDRS) $(GGC_H) \
-   $(RTL_H) $(EXPR_H) $(TARGET_H) $(DIAGNOSTIC_H) toplev.h $(FLAGS_H) \
-   input.h $(FUNCTION_H) output.h debug.h $(OBSTACK_H) \
-   objcp/objcp-decl.h $(LANGHOOKS_DEF_H) $(HASHTAB_H) gt-objc-objc-act.h \
-   $(GIMPLE_H) objc/objc-runtime-hooks.h objc/objc-runtime-shared-support.h
+objcp/objcp-act.o : objc/objc-act.c \
+   gt-objc-objc-act.h \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   toplev.h $(FUNCTION_H) output.h debug.h $(LANGHOOKS_DEF_H) \
+   $(HASHTAB_H) $(GIMPLE_H) \
+   $(RTL_H) $(EXPR_H) $(TARGET_H) \
+   objcp/objcp-decl.h \
+   objc/objc-encoding.h \
+   objc/objc-runtime-hooks.h \
+   objc/objc-runtime-shared-support.h \
+   objcp/objcp-decl.h
+       $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+               $(OUTPUT_OPTION)
+
+objcp/objc-encoding.o : objc/objc-encoding.c \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   objc/objc-encoding.h \
+   objc/objc-runtime-shared-support.h \
+   objcp/objcp-decl.h
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
                $(OUTPUT_OPTION)