Index: objc/objc-encoding.c
===================================================================
--- objc/objc-encoding.c	(revision 0)
+++ objc/objc-encoding.c	(revision 0)
@@ -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);
+}
Index: objc/objc-encoding.h
===================================================================
--- objc/objc-encoding.h	(revision 0)
+++ objc/objc-encoding.h	(revision 0)
@@ -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: objc/ChangeLog
===================================================================
--- objc/ChangeLog	(revision 175590)
+++ objc/ChangeLog	(working copy)
@@ -1,3 +1,47 @@
+2011-07-02  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: objc/objc-runtime-shared-support.c
===================================================================
--- objc/objc-runtime-shared-support.c	(revision 175590)
+++ objc/objc-runtime-shared-support.c	(working copy)
@@ -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: objc/Make-lang.in
===================================================================
--- objc/Make-lang.in	(revision 175590)
+++ objc/Make-lang.in	(working copy)
@@ -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,34 +74,76 @@ cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) c
 
 # 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
+   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 $(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-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 $(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-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 $(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-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 $(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)
+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: objc/objc-runtime-shared-support.h
===================================================================
--- objc/objc-runtime-shared-support.h	(revision 175590)
+++ objc/objc-runtime-shared-support.h	(working copy)
@@ -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: objc/objc-next-runtime-abi-01.c
===================================================================
--- objc/objc-next-runtime-abi-01.c	(revision 175590)
+++ objc/objc-next-runtime-abi-01.c	(working copy)
@@ -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: objc/objc-next-runtime-abi-02.c
===================================================================
--- objc/objc-next-runtime-abi-02.c	(revision 175590)
+++ objc/objc-next-runtime-abi-02.c	(working copy)
@@ -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: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 175590)
+++ objc/objc-act.c	(working copy)
@@ -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)))
 
 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 sel
   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,759 +10162,7 @@ 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;
-}
-
-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)
 {
   c_common_init_ts ();
Index: objc/objc-act.h
===================================================================
--- objc/objc-act.h	(revision 175590)
+++ objc/objc-act.h	(working copy)
@@ -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
Index: objc/objc-gnu-runtime-abi-01.c
===================================================================
--- objc/objc-gnu-runtime-abi-01.c	(revision 175590)
+++ objc/objc-gnu-runtime-abi-01.c	(working copy)
@@ -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: objcp/Make-lang.in
===================================================================
--- objcp/Make-lang.in	(revision 175590)
+++ objcp/Make-lang.in	(working copy)
@@ -57,6 +57,7 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.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,51 +77,99 @@ cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-che
 
 # 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)
+
 po-generated:
 
 #
Index: objcp/ChangeLog
===================================================================
--- objcp/ChangeLog	(revision 175590)
+++ objcp/ChangeLog	(working copy)
@@ -1,3 +1,19 @@
+2011-07-02  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
