Home | History | Annotate | Line # | Download | only in objc
      1 /* Routines dealing with ObjC encoding of types
      2    Copyright (C) 1992-2022 Free Software Foundation, Inc.
      3 
      4 This file is part of GCC.
      5 
      6 GCC is free software; you can redistribute it and/or modify
      7 it under the terms of the GNU General Public License as published by
      8 the Free Software Foundation; either version 3, or (at your option)
      9 any later version.
     10 
     11 GCC is distributed in the hope that it will be useful,
     12 but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 GNU General Public License for more details.
     15 
     16 You should have received a copy of the GNU General Public License
     17 along with GCC; see the file COPYING3.  If not see
     18 <http://www.gnu.org/licenses/>.  */
     19 
     20 #include "config.h"
     21 #include "system.h"
     22 #include "coretypes.h"
     23 #include "tree.h"
     24 #include "options.h"
     25 #include "stringpool.h"
     26 #include "stor-layout.h"
     27 
     28 #ifdef OBJCPLUS
     29 #include "cp/cp-tree.h"
     30 #else
     31 #include "c/c-tree.h"
     32 #include "c/c-lang.h"
     33 #endif
     34 
     35 #include "c-family/c-objc.h"
     36 
     37 #include "objc-encoding.h"
     38 #include "objc-act.h"
     39 
     40 /* For my_build_string().  */
     41 #include "objc-runtime-shared-support.h"
     42 
     43 /* For BITS_PER_UNIT.  */
     44 
     45 /* When building Objective-C++, we are not linking against the C front-end
     46    and so need to replicate the C tree-construction functions in some way.  */
     47 #ifdef OBJCPLUS
     48 #define OBJCP_REMAP_FUNCTIONS
     49 #include "objcp-decl.h"
     50 #endif  /* OBJCPLUS */
     51 
     52 /* Set up for use of obstacks.  */
     53 
     54 /* This obstack is used to accumulate the encoding of a data type.  */
     55 static struct obstack util_obstack;
     56 
     57 /* This points to the beginning of obstack contents, so we can free
     58    the whole contents.  */
     59 static char *util_firstobj;
     60 
     61 void objc_encoding_init (void)
     62 {
     63   gcc_obstack_init (&util_obstack);
     64   util_firstobj = (char *) obstack_finish (&util_obstack);
     65 }
     66 
     67 int generating_instance_variables = 0;
     68 
     69 static void encode_type_qualifiers (tree);
     70 static void encode_type (tree, int, int);
     71 static void encode_field (tree field_decl, int curtype, int format);
     72 
     73 static tree
     74 objc_method_parm_type (tree type)
     75 {
     76   type = TREE_VALUE (TREE_TYPE (type));
     77   if (TREE_CODE (type) == TYPE_DECL)
     78     type = TREE_TYPE (type);
     79   return type;
     80 }
     81 
     82 static int
     83 objc_encoded_type_size (tree type)
     84 {
     85   int sz = int_size_in_bytes (type);
     86 
     87   /* Make all integer and enum types at least as large
     88      as an int.  */
     89   if (sz > 0 && INTEGRAL_TYPE_P (type))
     90     sz = MAX (sz, int_size_in_bytes (integer_type_node));
     91   /* Treat arrays as pointers, since that's how they're
     92      passed in.  */
     93   else if (TREE_CODE (type) == ARRAY_TYPE)
     94     sz = int_size_in_bytes (ptr_type_node);
     95   return sz;
     96 }
     97 
     98 /* Encode a method prototype.  */
     99 tree
    100 encode_method_prototype (tree method_decl)
    101 {
    102   tree parms;
    103   int parm_offset, i;
    104   char buf[40];
    105   tree result;
    106 
    107   /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
    108   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
    109 
    110   /* Encode return type.  */
    111   encode_type (objc_method_parm_type (method_decl),
    112 	       obstack_object_size (&util_obstack),
    113 	       OBJC_ENCODE_INLINE_DEFS);
    114 
    115   /* Stack size.  */
    116   /* The first two arguments (self and _cmd) are pointers; account for
    117      their size.  */
    118   i = int_size_in_bytes (ptr_type_node);
    119   parm_offset = 2 * i;
    120   for (parms = METHOD_SEL_ARGS (method_decl); parms;
    121        parms = DECL_CHAIN (parms))
    122     {
    123       tree type = objc_method_parm_type (parms);
    124       int sz = objc_encoded_type_size (type);
    125 
    126       /* If a type size is not known, bail out.  */
    127       if (sz < 0)
    128 	{
    129 	  error_at (DECL_SOURCE_LOCATION (method_decl),
    130 		    "type %qT does not have a known size",
    131 		    type);
    132 	  /* Pretend that the encoding succeeded; the compilation will
    133 	     fail nevertheless.  */
    134 	  goto finish_encoding;
    135 	}
    136       parm_offset += sz;
    137     }
    138 
    139   sprintf (buf, "%d@0:%d", parm_offset, i);
    140   obstack_grow (&util_obstack, buf, strlen (buf));
    141 
    142   /* Argument types.  */
    143   parm_offset = 2 * i;
    144   for (parms = METHOD_SEL_ARGS (method_decl); parms;
    145        parms = DECL_CHAIN (parms))
    146     {
    147       tree type = objc_method_parm_type (parms);
    148 
    149       /* Process argument qualifiers for user supplied arguments.  */
    150       encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
    151 
    152       /* Type.  */
    153       encode_type (type, obstack_object_size (&util_obstack),
    154 		   OBJC_ENCODE_INLINE_DEFS);
    155 
    156       /* Compute offset.  */
    157       sprintf (buf, "%d", parm_offset);
    158       parm_offset += objc_encoded_type_size (type);
    159 
    160       obstack_grow (&util_obstack, buf, strlen (buf));
    161     }
    162 
    163   finish_encoding:
    164   obstack_1grow (&util_obstack, '\0');
    165   result = get_identifier (XOBFINISH (&util_obstack, char *));
    166   obstack_free (&util_obstack, util_firstobj);
    167   return result;
    168 }
    169 
    170 /* This is used to implement @encode().  */
    171 tree
    172 objc_build_encode_expr (tree type)
    173 {
    174   tree result;
    175   const char *string;
    176 
    177   encode_type (type, obstack_object_size (&util_obstack),
    178 	       OBJC_ENCODE_INLINE_DEFS);
    179   obstack_1grow (&util_obstack, 0);    /* null terminate string */
    180   string = XOBFINISH (&util_obstack, const char *);
    181 
    182   /* Synthesize a string that represents the encoded struct/union.  */
    183   result = my_build_string (strlen (string) + 1, string);
    184   obstack_free (&util_obstack, util_firstobj);
    185   return result;
    186 }
    187 
    188 /* "Encode" a data type into a string, which grows in util_obstack.
    189 
    190    The format is described in gcc/doc/objc.texi, section 'Type
    191    encoding'.
    192 
    193    Most of the encode_xxx functions have a 'type' argument, which is
    194    the type to encode, and an integer 'curtype' argument, which is the
    195    index in the encoding string of the beginning of the encoding of
    196    the current type, and allows you to find what characters have
    197    already been written for the current type (they are the ones in the
    198    current encoding string starting from 'curtype').
    199 
    200    For example, if we are encoding a method which returns 'int' and
    201    takes a 'char **' argument, then when we get to the point of
    202    encoding the 'char **' argument, the encoded string already
    203    contains 'i12@0:4' (assuming a pointer size of 4 bytes).  So,
    204    'curtype' will be set to 7 when starting to encode 'char **'.
    205    During the whole of the encoding of 'char **', 'curtype' will be
    206    fixed at 7, so the routine encoding the second pointer can find out
    207    that it's actually encoding a pointer to a pointer by looking
    208    backwards at what has already been encoded for the current type,
    209    and seeing there is a "^" (meaning a pointer) in there.  */
    210 
    211 
    212 /* Encode type qualifiers encodes one of the "PQ" Objective-C
    213    keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
    214    'const', instead, is encoded directly as part of the type.  */
    215 static void
    216 encode_type_qualifiers (tree declspecs)
    217 {
    218   tree spec;
    219 
    220   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
    221     {
    222       /* FIXME: Shouldn't we use token->keyword here ? */
    223       if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
    224 	obstack_1grow (&util_obstack, 'n');
    225       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
    226 	obstack_1grow (&util_obstack, 'N');
    227       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
    228 	obstack_1grow (&util_obstack, 'o');
    229       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
    230 	obstack_1grow (&util_obstack, 'O');
    231       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
    232         obstack_1grow (&util_obstack, 'R');
    233       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
    234 	obstack_1grow (&util_obstack, 'V');
    235       else
    236 	gcc_unreachable ();
    237     }
    238 }
    239 
    240 /* Determine if a pointee is marked read-only.  Only used by the NeXT
    241    runtime to be compatible with gcc-3.3.  */
    242 static bool
    243 pointee_is_readonly (tree pointee)
    244 {
    245   while (POINTER_TYPE_P (pointee))
    246     pointee = TREE_TYPE (pointee);
    247 
    248   return TYPE_READONLY (pointee);
    249 }
    250 
    251 /* Encode a pointer type.  */
    252 static void
    253 encode_pointer (tree type, int curtype, int format)
    254 {
    255   tree pointer_to = TREE_TYPE (type);
    256 
    257   if (flag_next_runtime)
    258     {
    259       /* This code is used to be compatible with gcc-3.3.  */
    260       /* For historical/compatibility reasons, the read-only qualifier
    261 	 of the pointee gets emitted _before_ the '^'.  The read-only
    262 	 qualifier of the pointer itself gets ignored, _unless_ we are
    263 	 looking at a typedef!  Also, do not emit the 'r' for anything
    264 	 but the outermost type!  */
    265       if (!generating_instance_variables
    266 	  && (obstack_object_size (&util_obstack) - curtype <= 1)
    267 	  && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
    268 	      ? TYPE_READONLY (type)
    269 	      : pointee_is_readonly (pointer_to)))
    270 	obstack_1grow (&util_obstack, 'r');
    271     }
    272 
    273   if (TREE_CODE (pointer_to) == RECORD_TYPE)
    274     {
    275       if (OBJC_TYPE_NAME (pointer_to)
    276 	  && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
    277 	{
    278 	  const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
    279 
    280 	  if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
    281 	    {
    282 	      obstack_1grow (&util_obstack, '@');
    283 	      return;
    284 	    }
    285 	  else if (TYPE_HAS_OBJC_INFO (pointer_to)
    286 		   && TYPE_OBJC_INTERFACE (pointer_to))
    287 	    {
    288               if (generating_instance_variables)
    289 	        {
    290 	          obstack_1grow (&util_obstack, '@');
    291 	          obstack_1grow (&util_obstack, '"');
    292 	          obstack_grow (&util_obstack, name, strlen (name));
    293 	          obstack_1grow (&util_obstack, '"');
    294 	          return;
    295 		}
    296               else
    297 	        {
    298 	          obstack_1grow (&util_obstack, '@');
    299 	          return;
    300 		}
    301 	    }
    302 	  else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
    303 	    {
    304 	      obstack_1grow (&util_obstack, '#');
    305 	      return;
    306 	    }
    307 	  else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
    308 	    {
    309 	      obstack_1grow (&util_obstack, ':');
    310 	      return;
    311 	    }
    312 	}
    313     }
    314   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
    315 	   && TYPE_MODE (pointer_to) == QImode)
    316     {
    317       tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
    318 	          ? OBJC_TYPE_NAME (pointer_to)
    319 	          : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
    320 
    321       /* (BOOL *) are an exception and are encoded as ^c, while all
    322 	 other pointers to char are encoded as *.   */
    323       if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
    324 	{
    325 	  if (!flag_next_runtime)
    326 	    {
    327 	      /* The NeXT runtime adds the 'r' before getting here.  */
    328 
    329 	      /* It appears that "r*" means "const char *" rather than
    330 		 "char *const".  "char *const" is encoded as "*",
    331 		 which is identical to "char *", so the "const" is
    332 		 unfortunately lost.  */
    333 	      if (TYPE_READONLY (pointer_to))
    334 		obstack_1grow (&util_obstack, 'r');
    335 	    }
    336 
    337 	  obstack_1grow (&util_obstack, '*');
    338 	  return;
    339 	}
    340     }
    341 
    342   /* We have a normal pointer type that does not get special treatment.  */
    343   obstack_1grow (&util_obstack, '^');
    344   encode_type (pointer_to, curtype, format);
    345 }
    346 
    347 static void
    348 encode_array (tree type, int curtype, int format)
    349 {
    350   tree an_int_cst = TYPE_SIZE (type);
    351   tree array_of = TREE_TYPE (type);
    352   char buffer[40];
    353 
    354   if (an_int_cst == NULL)
    355     {
    356       /* We are trying to encode an incomplete array.  An incomplete
    357 	 array is forbidden as part of an instance variable; but it
    358 	 may occur if the instance variable is a pointer to such an
    359 	 array.  */
    360 
    361       /* So the only case in which an incomplete array could occur
    362 	 (without being pointed to) is if we are encoding the
    363 	 arguments or return value of a method.  In that case, an
    364 	 incomplete array argument or return value (eg,
    365 	 -(void)display: (char[])string) is treated like a pointer
    366 	 because that is how the compiler does the function call.  A
    367 	 special, more complicated case, is when the incomplete array
    368 	 is the last member of a struct (eg, if we are encoding
    369 	 "struct { unsigned long int a;double b[];}"), which is again
    370 	 part of a method argument/return value.  In that case, we
    371 	 really need to communicate to the runtime that there is an
    372 	 incomplete array (not a pointer!) there.  So, we detect that
    373 	 special case and encode it as a zero-length array.
    374 
    375 	 Try to detect that we are part of a struct.  We do this by
    376 	 searching for '=' in the type encoding for the current type.
    377 	 NB: This hack assumes that you can't use '=' as part of a C
    378 	 identifier.
    379       */
    380       {
    381 	char *enc = (char *) obstack_base (&util_obstack) + curtype;
    382 	if (memchr (enc, '=',
    383 		    obstack_object_size (&util_obstack) - curtype) == NULL)
    384 	  {
    385 	    /* We are not inside a struct.  Encode the array as a
    386 	       pointer.  */
    387 	    encode_pointer (type, curtype, format);
    388 	    return;
    389 	  }
    390       }
    391 
    392       /* Else, we are in a struct, and we encode it as a zero-length
    393 	 array.  */
    394       sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
    395     }
    396   else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
    397    sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
    398   else
    399     sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
    400 	     TREE_INT_CST_LOW (an_int_cst)
    401 	      / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
    402 
    403   obstack_grow (&util_obstack, buffer, strlen (buffer));
    404   encode_type (array_of, curtype, format);
    405   obstack_1grow (&util_obstack, ']');
    406   return;
    407 }
    408 
    409 /* Encode a vector.  The vector type is a GCC extension to C.  */
    410 static void
    411 encode_vector (tree type, int curtype, int format)
    412 {
    413   tree vector_of = TREE_TYPE (type);
    414   char buffer[40];
    415 
    416   /* Vectors are like simple fixed-size arrays.  */
    417 
    418   /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
    419      alignment of the vector, and <code> is the base type.  Eg, int
    420      __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
    421      assuming that the alignment is 32 bytes.  We include size and
    422      alignment in bytes so that the runtime does not have to have any
    423      knowledge of the actual types.
    424   */
    425   sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
    426 	   /* We want to compute the equivalent of sizeof (<vector>).
    427 	      Code inspired by c_sizeof_or_alignof_type.  */
    428 	   ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
    429 	     / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
    430 	   /* We want to compute the equivalent of __alignof__
    431 	      (<vector>).  Code inspired by
    432 	      c_sizeof_or_alignof_type.  */
    433 	   TYPE_ALIGN_UNIT (type));
    434   obstack_grow (&util_obstack, buffer, strlen (buffer));
    435   encode_type (vector_of, curtype, format);
    436   obstack_1grow (&util_obstack, ']');
    437   return;
    438 }
    439 
    440 static void
    441 encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
    442 {
    443   tree field = TYPE_FIELDS (type);
    444 
    445   for (; field; field = DECL_CHAIN (field))
    446     {
    447 #ifdef OBJCPLUS
    448       /* C++ static members, and things that are not field at all,
    449 	 should not appear in the encoding.  */
    450       if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
    451 	continue;
    452 #endif
    453 
    454       /* Recursively encode fields of embedded base classes.  */
    455       if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
    456 	  && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
    457 	{
    458 	  encode_aggregate_fields (TREE_TYPE (field),
    459 				   pointed_to, curtype, format);
    460 	  continue;
    461 	}
    462 
    463       if (generating_instance_variables && !pointed_to)
    464 	{
    465 	  tree fname = DECL_NAME (field);
    466 
    467 	  obstack_1grow (&util_obstack, '"');
    468 
    469 	  if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
    470 	    obstack_grow (&util_obstack,
    471 			  IDENTIFIER_POINTER (fname),
    472 			  strlen (IDENTIFIER_POINTER (fname)));
    473 
    474 	  obstack_1grow (&util_obstack, '"');
    475         }
    476 
    477       encode_field (field, curtype, format);
    478     }
    479 }
    480 
    481 static void
    482 encode_aggregate_within (tree type, int curtype, int format, int left,
    483 			 int right)
    484 {
    485   tree name;
    486   /* NB: aggregates that are pointed to have slightly different encoding
    487      rules in that you never encode the names of instance variables.  */
    488   int ob_size = obstack_object_size (&util_obstack);
    489   bool inline_contents = false;
    490   bool pointed_to = false;
    491 
    492   if (flag_next_runtime)
    493     {
    494       if (ob_size > 0
    495 	  && *((char *) obstack_next_free (&util_obstack) - 1) == '^')
    496 	pointed_to = true;
    497 
    498       if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
    499 	  && (!pointed_to || ob_size - curtype == 1
    500 	      || (ob_size - curtype == 2
    501 		  && *((char *) obstack_next_free (&util_obstack) - 2) == 'r')))
    502 	inline_contents = true;
    503     }
    504   else
    505     {
    506       /* c0 and c1 are the last two characters in the encoding of the
    507 	 current type; if the last two characters were '^' or '^r',
    508 	 then we are encoding an aggregate that is "pointed to".  The
    509 	 comment above applies: in that case we should avoid encoding
    510 	 the names of instance variables.
    511       */
    512       char c0, c1;
    513 
    514       c1 = ob_size > 1 ? *((char *) obstack_next_free (&util_obstack) - 2) : 0;
    515       c0 = ob_size > 0 ? *((char *) obstack_next_free (&util_obstack) - 1) : 0;
    516       if (c0 == '^' || (c1 == '^' && c0 == 'r'))
    517 	pointed_to = true;
    518 
    519       if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
    520 	{
    521 	  if (!pointed_to)
    522 	    inline_contents = true;
    523 	  else
    524 	    {
    525 	      /* Note that the check (ob_size - curtype < 2) prevents
    526 		 infinite recursion when encoding a structure which is
    527 		 a linked list (eg, struct node { struct node *next;
    528 		 }).  Each time we follow a pointer, we add one
    529 		 character to ob_size, and curtype is fixed, so after
    530 		 at most two pointers we stop inlining contents and
    531 		 break the loop.
    532 
    533 		 The other case where we don't inline is "^r", which
    534 		 is a pointer to a constant struct.
    535 	      */
    536 	      if ((ob_size - curtype <= 2) && !(c0 == 'r'))
    537 		inline_contents = true;
    538 	    }
    539 	}
    540     }
    541 
    542   /* Traverse struct aliases; it is important to get the
    543      original struct and its tag name (if any).  */
    544   type = TYPE_MAIN_VARIANT (type);
    545   name = OBJC_TYPE_NAME (type);
    546   /* Open parenth/bracket.  */
    547   obstack_1grow (&util_obstack, left);
    548 
    549   /* Encode the struct/union tag name, or '?' if a tag was
    550      not provided.  Typedef aliases do not qualify.  */
    551 #ifdef OBJCPLUS
    552   /* For compatibility with the NeXT runtime, ObjC++ encodes template
    553      args as a composite struct tag name. */
    554   if (name && TREE_CODE (name) == IDENTIFIER_NODE
    555       /* Did this struct have a tag?  */
    556       && !TYPE_WAS_UNNAMED (type))
    557     obstack_grow (&util_obstack,
    558 		  decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
    559 		  strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
    560 #else
    561   if (name && TREE_CODE (name) == IDENTIFIER_NODE)
    562     obstack_grow (&util_obstack,
    563 		  IDENTIFIER_POINTER (name),
    564 		  strlen (IDENTIFIER_POINTER (name)));
    565 #endif
    566   else
    567     obstack_1grow (&util_obstack, '?');
    568 
    569   /* Encode the types (and possibly names) of the inner fields,
    570      if required.  */
    571   if (inline_contents)
    572     {
    573       obstack_1grow (&util_obstack, '=');
    574       encode_aggregate_fields (type, pointed_to, curtype, format);
    575     }
    576   /* Close parenth/bracket.  */
    577   obstack_1grow (&util_obstack, right);
    578 }
    579 
    580 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
    581    field type.  */
    582 static void
    583 encode_next_bitfield (int width)
    584 {
    585   char buffer[40];
    586   sprintf (buffer, "b%d", width);
    587   obstack_grow (&util_obstack, buffer, strlen (buffer));
    588 }
    589 
    590 /* Encodes 'type', ignoring type qualifiers (which you should encode
    591    beforehand if needed) with the exception of 'const', which is
    592    encoded by encode_type.  See above for the explanation of
    593    'curtype'.  'format' can be OBJC_ENCODE_INLINE_DEFS or
    594    OBJC_ENCODE_DONT_INLINE_DEFS.  */
    595 static void
    596 encode_type (tree type, int curtype, int format)
    597 {
    598   enum tree_code code = TREE_CODE (type);
    599 
    600   /* Ignore type qualifiers other than 'const' when encoding a
    601      type.  */
    602 
    603   if (type == error_mark_node)
    604     return;
    605 
    606   if (!flag_next_runtime)
    607     {
    608       if (TYPE_READONLY (type))
    609 	obstack_1grow (&util_obstack, 'r');
    610     }
    611 
    612   switch (code)
    613     {
    614     case ENUMERAL_TYPE:
    615       if (flag_next_runtime)
    616 	{
    617 	  /* Kludge for backwards-compatibility with gcc-3.3: enums
    618 	     are always encoded as 'i' no matter what type they
    619 	     actually are (!).  */
    620 	  obstack_1grow (&util_obstack, 'i');
    621 	  break;
    622 	}
    623       /* Else, they are encoded exactly like the integer type that is
    624 	 used by the compiler to store them.  */
    625       /* FALLTHRU */
    626     case INTEGER_TYPE:
    627       {
    628 	char c;
    629 	switch (GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type)))
    630 	  {
    631 	  case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
    632 	  case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
    633 	  case 32:
    634 	    {
    635 	      tree int_type = type;
    636 	      if (flag_next_runtime)
    637 		{
    638 		  /* Another legacy kludge for compatibility with
    639 		     gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
    640 		     but not always.  For typedefs, we need to use 'i'
    641 		     or 'I' instead if encoding a struct field, or a
    642 		     pointer!  */
    643 		  int_type =  ((!generating_instance_variables
    644 				&& (obstack_object_size (&util_obstack)
    645 				    == (unsigned) curtype))
    646 			       ? TYPE_MAIN_VARIANT (type)
    647 			       : type);
    648 		}
    649 	      if (int_type == long_unsigned_type_node
    650 		  || int_type == long_integer_type_node)
    651 		c = TYPE_UNSIGNED (type) ? 'L' : 'l';
    652 	      else
    653 		c = TYPE_UNSIGNED (type) ? 'I' : 'i';
    654 	    }
    655 	    break;
    656 	  case 64:  c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
    657 	  case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
    658 	  default: gcc_unreachable ();
    659 	  }
    660 	obstack_1grow (&util_obstack, c);
    661 	break;
    662       }
    663     case REAL_TYPE:
    664       {
    665 	char c;
    666 	/* Floating point types.  */
    667 	switch (GET_MODE_BITSIZE (SCALAR_FLOAT_TYPE_MODE (type)))
    668 	  {
    669 	  case 32:  c = 'f'; break;
    670 	  case 64:  c = 'd'; break;
    671 	  case 96:
    672 	  case 128: c = 'D'; break;
    673 	  default: gcc_unreachable ();
    674 	  }
    675 	obstack_1grow (&util_obstack, c);
    676 	break;
    677       }
    678     case VOID_TYPE:
    679       obstack_1grow (&util_obstack, 'v');
    680       break;
    681 
    682     case BOOLEAN_TYPE:
    683       obstack_1grow (&util_obstack, 'B');
    684       break;
    685 
    686     case ARRAY_TYPE:
    687       encode_array (type, curtype, format);
    688       break;
    689 
    690     case POINTER_TYPE:
    691 #ifdef OBJCPLUS
    692     case REFERENCE_TYPE:
    693 #endif
    694       encode_pointer (type, curtype, format);
    695       break;
    696 
    697     case RECORD_TYPE:
    698       encode_aggregate_within (type, curtype, format, '{', '}');
    699       break;
    700 
    701     case UNION_TYPE:
    702       encode_aggregate_within (type, curtype, format, '(', ')');
    703       break;
    704 
    705     case FUNCTION_TYPE: /* '?' means an unknown type.  */
    706       obstack_1grow (&util_obstack, '?');
    707       break;
    708 
    709     case COMPLEX_TYPE:
    710       /* A complex is encoded as 'j' followed by the inner type (eg,
    711 	 "_Complex int" is encoded as 'ji').  */
    712       obstack_1grow (&util_obstack, 'j');
    713       encode_type (TREE_TYPE (type), curtype, format);
    714       break;
    715 
    716     case VECTOR_TYPE:
    717       encode_vector (type, curtype, format);
    718       break;
    719 
    720     default:
    721       warning (0, "unknown type %<%T%> found during Objective-C encoding",
    722 	       TREE_TYPE (type));
    723       obstack_1grow (&util_obstack, '?');
    724       break;
    725     }
    726 
    727   if (flag_next_runtime)
    728     {
    729       /* Super-kludge.  Some ObjC qualifier and type combinations need
    730 	 to be rearranged for compatibility with gcc-3.3.  */
    731       if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
    732 	{
    733 	  char *enc = (char *) obstack_base (&util_obstack) + curtype;
    734 
    735 	  /* Rewrite "in const" from "nr" to "rn".  */
    736 	  if (curtype >= 1 && startswith (enc - 1, "nr"))
    737 	    memcpy (enc - 1, "rn", 2);
    738 	}
    739     }
    740 }
    741 
    742 static void
    743 encode_gnu_bitfield (int position, tree type, int size)
    744 {
    745   enum tree_code code = TREE_CODE (type);
    746   char buffer[40];
    747   char charType = '?';
    748 
    749   /* This code is only executed for the GNU runtime, so we can ignore
    750      the NeXT runtime kludge of always encoding enums as 'i' no matter
    751      what integers they actually are.  */
    752   if (code == INTEGER_TYPE  ||  code == ENUMERAL_TYPE)
    753     {
    754       if (integer_zerop (TYPE_MIN_VALUE (type)))
    755 	/* Unsigned integer types.  */
    756 	{
    757 	  switch (TYPE_MODE (type))
    758 	    {
    759 	    case E_QImode:
    760 	      charType = 'C'; break;
    761 	    case E_HImode:
    762 	      charType = 'S'; break;
    763 	    case E_SImode:
    764 	      {
    765 		if (type == long_unsigned_type_node)
    766 		  charType = 'L';
    767 		else
    768 		  charType = 'I';
    769 		break;
    770 	      }
    771 	    case E_DImode:
    772 	      charType = 'Q'; break;
    773 	    default:
    774 	      gcc_unreachable ();
    775 	    }
    776 	}
    777       else
    778 	/* Signed integer types.  */
    779 	{
    780 	  switch (TYPE_MODE (type))
    781 	    {
    782 	    case E_QImode:
    783 	      charType = 'c'; break;
    784 	    case E_HImode:
    785 	      charType = 's'; break;
    786 	    case E_SImode:
    787 	      {
    788 		if (type == long_integer_type_node)
    789 		  charType = 'l';
    790 		else
    791 		  charType = 'i';
    792 		break;
    793 	      }
    794 	    case E_DImode:
    795 	      charType = 'q'; break;
    796 	    default:
    797 	      gcc_unreachable ();
    798 	    }
    799 	}
    800     }
    801   else
    802     {
    803       /* Do not do any encoding, produce an error and keep going.  */
    804       error ("trying to encode non-integer type as a bit-field");
    805       return;
    806     }
    807 
    808   sprintf (buffer, "b%d%c%d", position, charType, size);
    809   obstack_grow (&util_obstack, buffer, strlen (buffer));
    810 }
    811 
    812 static void
    813 encode_field (tree field_decl, int curtype, int format)
    814 {
    815 #ifdef OBJCPLUS
    816   /* C++ static members, and things that are not fields at all,
    817      should not appear in the encoding.  */
    818   if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
    819     return;
    820 #endif
    821 
    822   /* Generate the bitfield typing information, if needed.  Note the difference
    823      between GNU and NeXT runtimes.  */
    824   if (DECL_BIT_FIELD_TYPE (field_decl))
    825     {
    826       int size = tree_to_uhwi (DECL_SIZE (field_decl));
    827 
    828       if (flag_next_runtime)
    829 	encode_next_bitfield (size);
    830       else
    831 	encode_gnu_bitfield (int_bit_position (field_decl),
    832 			     DECL_BIT_FIELD_TYPE (field_decl), size);
    833     }
    834   else
    835     encode_type (TREE_TYPE (field_decl), curtype, format);
    836 }
    837 
    838 tree
    839 encode_field_decl (tree field_decl)
    840 {
    841   tree result;
    842 
    843   encode_field (field_decl,
    844 		obstack_object_size (&util_obstack),
    845 		OBJC_ENCODE_DONT_INLINE_DEFS);
    846 
    847   /* Null terminate string.  */
    848   obstack_1grow (&util_obstack, 0);
    849 
    850   /* Get identifier for the string.  */
    851   result = get_identifier (XOBFINISH (&util_obstack, char *));
    852   obstack_free (&util_obstack, util_firstobj);
    853 
    854   return result;
    855 }
    856 
    857 /* This routine encodes the attribute of the input PROPERTY according
    858    to following formula:
    859 
    860    Property attributes are stored as a comma-delimited C string.
    861    Simple attributes such as readonly are encoded as single
    862    character. The parametrized attributes, getter=name and
    863    setter=name, are encoded as a single character followed by an
    864    identifier.  Property types are also encoded as a parametrized
    865    attribute.  The characters used to encode these attributes are
    866    defined by the following enumeration:
    867 
    868    enum PropertyAttributes {
    869      kPropertyReadOnly = 'R',
    870      kPropertyBycopy = 'C',
    871      kPropertyByref = '&',
    872      kPropertyDynamic = 'D',
    873      kPropertyGetter = 'G',
    874      kPropertySetter = 'S',
    875      kPropertyInstanceVariable = 'V',
    876      kPropertyType = 'T',
    877      kPropertyWeak = 'W',
    878      kPropertyStrong = 'P',
    879      kPropertyNonAtomic = 'N'
    880    };  */
    881 tree
    882 objc_v2_encode_prop_attr (tree property)
    883 {
    884   const char *string;
    885   tree type = TREE_TYPE (property);
    886 
    887   obstack_1grow (&util_obstack, 'T');
    888   encode_type (type, obstack_object_size (&util_obstack),
    889 	       OBJC_ENCODE_INLINE_DEFS);
    890 
    891   if (PROPERTY_READONLY (property))
    892     obstack_grow (&util_obstack, ",R", 2);
    893 
    894   switch (PROPERTY_ASSIGN_SEMANTICS (property))
    895     {
    896     case OBJC_PROPERTY_COPY:
    897       obstack_grow (&util_obstack, ",C", 2);
    898       break;
    899     case OBJC_PROPERTY_RETAIN:
    900       obstack_grow (&util_obstack, ",&", 2);
    901       break;
    902     case OBJC_PROPERTY_ASSIGN:
    903     default:
    904       break;
    905     }
    906 
    907   if (PROPERTY_DYNAMIC (property))
    908     obstack_grow (&util_obstack, ",D", 2);
    909 
    910   if (PROPERTY_NONATOMIC (property))
    911     obstack_grow (&util_obstack, ",N", 2);
    912 
    913   /* Here we want to encode the getter name, but only if it's not the
    914      standard one.  */
    915   if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
    916     {
    917       obstack_grow (&util_obstack, ",G", 2);
    918       string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
    919       obstack_grow (&util_obstack, string, strlen (string));
    920     }
    921 
    922   if (!PROPERTY_READONLY (property))
    923     {
    924       /* Here we want to encode the setter name, but only if it's not
    925 	 the standard one.  */
    926       tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
    927       if (PROPERTY_SETTER_NAME (property) != standard_setter)
    928 	{
    929 	  obstack_grow (&util_obstack, ",S", 2);
    930 	  string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
    931 	  obstack_grow (&util_obstack, string, strlen (string));
    932 	}
    933     }
    934 
    935   /* TODO: Encode strong ('P'), weak ('W') for garbage collection.  */
    936 
    937   if (!PROPERTY_DYNAMIC (property))
    938     {
    939       obstack_grow (&util_obstack, ",V", 2);
    940       if (PROPERTY_IVAR_NAME (property))
    941 	string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
    942       else
    943 	string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
    944       obstack_grow (&util_obstack, string, strlen (string));
    945     }
    946 
    947   /* NULL-terminate string.  */
    948   obstack_1grow (&util_obstack, 0);
    949   string = XOBFINISH (&util_obstack, char *);
    950   obstack_free (&util_obstack, util_firstobj);
    951   return get_identifier (string);
    952 }
    953