remove unused files
[platform/upstream/gcc48.git] / gcc / objc / objc-encoding.c
1 /* Routines dealing with ObjC encoding of types
2    Copyright (C) 1992-2013 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
25 #ifdef OBJCPLUS
26 #include "cp/cp-tree.h"
27 #else
28 #include "c/c-tree.h"
29 #include "c/c-lang.h"
30 #endif
31
32 #include "c-family/c-common.h"
33 #include "c-family/c-objc.h"
34
35 #include "objc-encoding.h"
36 #include "objc-act.h"
37
38 /* For my_build_string().  */
39 #include "objc-runtime-shared-support.h"
40
41 /* For BITS_PER_UNIT.  */
42 #include "tm.h"
43
44 /* When building Objective-C++, we are not linking against the C front-end
45    and so need to replicate the C tree-construction functions in some way.  */
46 #ifdef OBJCPLUS
47 #define OBJCP_REMAP_FUNCTIONS
48 #include "objcp-decl.h"
49 #endif  /* OBJCPLUS */
50
51 /* Set up for use of obstacks.  */
52 #include "obstack.h"
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 = 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  &&  *(obstack_next_free (&util_obstack) - 1) == '^')
495         pointed_to = true;
496
497       if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
498           && (!pointed_to || ob_size - curtype == 1
499               || (ob_size - curtype == 2
500                   && *(obstack_next_free (&util_obstack) - 2) == 'r')))
501         inline_contents = true;
502     }
503   else
504     {
505       /* c0 and c1 are the last two characters in the encoding of the
506          current type; if the last two characters were '^' or '^r',
507          then we are encoding an aggregate that is "pointed to".  The
508          comment above applies: in that case we should avoid encoding
509          the names of instance variables.
510       */
511       char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
512       char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
513
514       if (c0 == '^' || (c1 == '^' && c0 == 'r'))
515         pointed_to = true;
516
517       if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
518         {
519           if (!pointed_to)
520             inline_contents = true;
521           else
522             {
523               /* Note that the check (ob_size - curtype < 2) prevents
524                  infinite recursion when encoding a structure which is
525                  a linked list (eg, struct node { struct node *next;
526                  }).  Each time we follow a pointer, we add one
527                  character to ob_size, and curtype is fixed, so after
528                  at most two pointers we stop inlining contents and
529                  break the loop.
530
531                  The other case where we don't inline is "^r", which
532                  is a pointer to a constant struct.
533               */
534               if ((ob_size - curtype <= 2) && !(c0 == 'r'))
535                 inline_contents = true;
536             }
537         }
538     }
539
540   /* Traverse struct aliases; it is important to get the
541      original struct and its tag name (if any).  */
542   type = TYPE_MAIN_VARIANT (type);
543   name = OBJC_TYPE_NAME (type);
544   /* Open parenth/bracket.  */
545   obstack_1grow (&util_obstack, left);
546
547   /* Encode the struct/union tag name, or '?' if a tag was
548      not provided.  Typedef aliases do not qualify.  */
549 #ifdef OBJCPLUS
550   /* For compatibility with the NeXT runtime, ObjC++ encodes template
551      args as a composite struct tag name. */
552   if (name && TREE_CODE (name) == IDENTIFIER_NODE
553       /* Did this struct have a tag?  */
554       && !TYPE_WAS_ANONYMOUS (type))
555     obstack_grow (&util_obstack,
556                   decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
557                   strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
558 #else
559   if (name && TREE_CODE (name) == IDENTIFIER_NODE)
560     obstack_grow (&util_obstack,
561                   IDENTIFIER_POINTER (name),
562                   strlen (IDENTIFIER_POINTER (name)));
563 #endif
564   else
565     obstack_1grow (&util_obstack, '?');
566
567   /* Encode the types (and possibly names) of the inner fields,
568      if required.  */
569   if (inline_contents)
570     {
571       obstack_1grow (&util_obstack, '=');
572       encode_aggregate_fields (type, pointed_to, curtype, format);
573     }
574   /* Close parenth/bracket.  */
575   obstack_1grow (&util_obstack, right);
576 }
577
578 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
579    field type.  */
580 static void
581 encode_next_bitfield (int width)
582 {
583   char buffer[40];
584   sprintf (buffer, "b%d", width);
585   obstack_grow (&util_obstack, buffer, strlen (buffer));
586 }
587
588 /* Encodes 'type', ignoring type qualifiers (which you should encode
589    beforehand if needed) with the exception of 'const', which is
590    encoded by encode_type.  See above for the explanation of
591    'curtype'.  'format' can be OBJC_ENCODE_INLINE_DEFS or
592    OBJC_ENCODE_DONT_INLINE_DEFS.  */
593 static void
594 encode_type (tree type, int curtype, int format)
595 {
596   enum tree_code code = TREE_CODE (type);
597
598   /* Ignore type qualifiers other than 'const' when encoding a
599      type.  */
600
601   if (type == error_mark_node)
602     return;
603
604   if (!flag_next_runtime)
605     {
606       if (TYPE_READONLY (type))
607         obstack_1grow (&util_obstack, 'r');
608     }
609
610   switch (code)
611     {
612     case ENUMERAL_TYPE:
613       if (flag_next_runtime)
614         {
615           /* Kludge for backwards-compatibility with gcc-3.3: enums
616              are always encoded as 'i' no matter what type they
617              actually are (!).  */
618           obstack_1grow (&util_obstack, 'i');
619           break;
620         }
621       /* Else, they are encoded exactly like the integer type that is
622          used by the compiler to store them.  */
623     case INTEGER_TYPE:
624       {
625         char c;
626         switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
627           {
628           case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
629           case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
630           case 32:
631             {
632               tree int_type = type;
633               if (flag_next_runtime)
634                 {
635                   /* Another legacy kludge for compatiblity with
636                      gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
637                      but not always.  For typedefs, we need to use 'i'
638                      or 'I' instead if encoding a struct field, or a
639                      pointer!  */
640                   int_type =  ((!generating_instance_variables
641                                 && (obstack_object_size (&util_obstack)
642                                     == (unsigned) curtype))
643                                ? TYPE_MAIN_VARIANT (type)
644                                : type);
645                 }
646               if (int_type == long_unsigned_type_node
647                   || int_type == long_integer_type_node)
648                 c = TYPE_UNSIGNED (type) ? 'L' : 'l';
649               else
650                 c = TYPE_UNSIGNED (type) ? 'I' : 'i';
651             }
652             break;
653           case 64:  c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
654           case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
655           default: gcc_unreachable ();
656           }
657         obstack_1grow (&util_obstack, c);
658         break;
659       }
660     case REAL_TYPE:
661       {
662         char c;
663         /* Floating point types.  */
664         switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
665           {
666           case 32:  c = 'f'; break;
667           case 64:  c = 'd'; break;
668           case 96:
669           case 128: c = 'D'; break;
670           default: gcc_unreachable ();
671           }
672         obstack_1grow (&util_obstack, c);
673         break;
674       }
675     case VOID_TYPE:
676       obstack_1grow (&util_obstack, 'v');
677       break;
678
679     case BOOLEAN_TYPE:
680       obstack_1grow (&util_obstack, 'B');
681       break;
682
683     case ARRAY_TYPE:
684       encode_array (type, curtype, format);
685       break;
686
687     case POINTER_TYPE:
688 #ifdef OBJCPLUS
689     case REFERENCE_TYPE:
690 #endif
691       encode_pointer (type, curtype, format);
692       break;
693
694     case RECORD_TYPE:
695       encode_aggregate_within (type, curtype, format, '{', '}');
696       break;
697
698     case UNION_TYPE:
699       encode_aggregate_within (type, curtype, format, '(', ')');
700       break;
701
702     case FUNCTION_TYPE: /* '?' means an unknown type.  */
703       obstack_1grow (&util_obstack, '?');
704       break;
705
706     case COMPLEX_TYPE:
707       /* A complex is encoded as 'j' followed by the inner type (eg,
708          "_Complex int" is encoded as 'ji').  */
709       obstack_1grow (&util_obstack, 'j');
710       encode_type (TREE_TYPE (type), curtype, format);
711       break;
712
713     case VECTOR_TYPE:
714       encode_vector (type, curtype, format);
715       break;
716
717     default:
718       warning (0, "unknown type %<%T%> found during Objective-C encoding",
719                TREE_TYPE (type));
720       obstack_1grow (&util_obstack, '?');
721       break;
722     }
723
724   if (flag_next_runtime)
725     {
726       /* Super-kludge.  Some ObjC qualifier and type combinations need
727          to be rearranged for compatibility with gcc-3.3.  */
728       if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
729         {
730           char *enc = obstack_base (&util_obstack) + curtype;
731
732           /* Rewrite "in const" from "nr" to "rn".  */
733           if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
734             strncpy (enc - 1, "rn", 2);
735         }
736     }
737 }
738
739 static void
740 encode_gnu_bitfield (int position, tree type, int size)
741 {
742   enum tree_code code = TREE_CODE (type);
743   char buffer[40];
744   char charType = '?';
745
746   /* This code is only executed for the GNU runtime, so we can ignore
747      the NeXT runtime kludge of always encoding enums as 'i' no matter
748      what integers they actually are.  */
749   if (code == INTEGER_TYPE  ||  code == ENUMERAL_TYPE)
750     {
751       if (integer_zerop (TYPE_MIN_VALUE (type)))
752         /* Unsigned integer types.  */
753         {
754           switch (TYPE_MODE (type))
755             {
756             case QImode:
757               charType = 'C'; break;
758             case HImode:
759               charType = 'S'; break;
760             case SImode:
761               {
762                 if (type == long_unsigned_type_node)
763                   charType = 'L';
764                 else
765                   charType = 'I';
766                 break;
767               }
768             case DImode:
769               charType = 'Q'; break;
770             default:
771               gcc_unreachable ();
772             }
773         }
774       else
775         /* Signed integer types.  */
776         {
777           switch (TYPE_MODE (type))
778             {
779             case QImode:
780               charType = 'c'; break;
781             case HImode:
782               charType = 's'; break;
783             case SImode:
784               {
785                 if (type == long_integer_type_node)
786                   charType = 'l';
787                 else
788                   charType = 'i';
789                 break;
790               }
791             case DImode:
792               charType = 'q'; break;
793             default:
794               gcc_unreachable ();
795             }
796         }
797     }
798   else
799     {
800       /* Do not do any encoding, produce an error and keep going.  */
801       error ("trying to encode non-integer type as a bitfield");
802       return;
803     }
804
805   sprintf (buffer, "b%d%c%d", position, charType, size);
806   obstack_grow (&util_obstack, buffer, strlen (buffer));
807 }
808
809 static void
810 encode_field (tree field_decl, int curtype, int format)
811 {
812 #ifdef OBJCPLUS
813   /* C++ static members, and things that are not fields at all,
814      should not appear in the encoding.  */
815   if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
816     return;
817 #endif
818
819   /* Generate the bitfield typing information, if needed.  Note the difference
820      between GNU and NeXT runtimes.  */
821   if (DECL_BIT_FIELD_TYPE (field_decl))
822     {
823       int size = tree_low_cst (DECL_SIZE (field_decl), 1);
824
825       if (flag_next_runtime)
826         encode_next_bitfield (size);
827       else
828         encode_gnu_bitfield (int_bit_position (field_decl),
829                              DECL_BIT_FIELD_TYPE (field_decl), size);
830     }
831   else
832     encode_type (TREE_TYPE (field_decl), curtype, format);
833 }
834
835 tree
836 encode_field_decl (tree field_decl)
837 {
838   tree result;
839
840   encode_field (field_decl,
841                 obstack_object_size (&util_obstack),
842                 OBJC_ENCODE_DONT_INLINE_DEFS);
843   
844   /* Null terminate string.  */
845   obstack_1grow (&util_obstack, 0);
846
847   /* Get identifier for the string.  */
848   result = get_identifier (XOBFINISH (&util_obstack, char *));
849   obstack_free (&util_obstack, util_firstobj);
850
851   return result;
852 }
853
854 /* This routine encodes the attribute of the input PROPERTY according
855    to following formula:
856
857    Property attributes are stored as a comma-delimited C string.
858    Simple attributes such as readonly are encoded as single
859    character. The parametrized attributes, getter=name and
860    setter=name, are encoded as a single character followed by an
861    identifier.  Property types are also encoded as a parametrized
862    attribute.  The characters used to encode these attributes are
863    defined by the following enumeration:
864
865    enum PropertyAttributes {
866      kPropertyReadOnly = 'R',
867      kPropertyBycopy = 'C',
868      kPropertyByref = '&',
869      kPropertyDynamic = 'D',
870      kPropertyGetter = 'G',
871      kPropertySetter = 'S',
872      kPropertyInstanceVariable = 'V',
873      kPropertyType = 'T',
874      kPropertyWeak = 'W',
875      kPropertyStrong = 'P',
876      kPropertyNonAtomic = 'N'
877    };  */
878 tree
879 objc_v2_encode_prop_attr (tree property)
880 {
881   const char *string;
882   tree type = TREE_TYPE (property);
883
884   obstack_1grow (&util_obstack, 'T');
885   encode_type (type, obstack_object_size (&util_obstack),
886                OBJC_ENCODE_INLINE_DEFS);
887
888   if (PROPERTY_READONLY (property))
889     obstack_grow (&util_obstack, ",R", 2);
890
891   switch (PROPERTY_ASSIGN_SEMANTICS (property))
892     {
893     case OBJC_PROPERTY_COPY:
894       obstack_grow (&util_obstack, ",C", 2);
895       break;
896     case OBJC_PROPERTY_RETAIN:
897       obstack_grow (&util_obstack, ",&", 2);
898       break;
899     case OBJC_PROPERTY_ASSIGN:
900     default:
901       break;
902     }
903
904   if (PROPERTY_DYNAMIC (property))
905     obstack_grow (&util_obstack, ",D", 2);
906
907   if (PROPERTY_NONATOMIC (property))
908     obstack_grow (&util_obstack, ",N", 2);
909
910   /* Here we want to encode the getter name, but only if it's not the
911      standard one.  */
912   if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
913     {
914       obstack_grow (&util_obstack, ",G", 2);
915       string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
916       obstack_grow (&util_obstack, string, strlen (string));
917     }
918
919   if (!PROPERTY_READONLY (property))
920     {
921       /* Here we want to encode the setter name, but only if it's not
922          the standard one.  */
923       tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
924       if (PROPERTY_SETTER_NAME (property) != standard_setter)
925         {
926           obstack_grow (&util_obstack, ",S", 2);
927           string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
928           obstack_grow (&util_obstack, string, strlen (string));
929         }
930     }
931
932   /* TODO: Encode strong ('P'), weak ('W') for garbage collection.  */
933
934   if (!PROPERTY_DYNAMIC (property))
935     {
936       obstack_grow (&util_obstack, ",V", 2);
937       if (PROPERTY_IVAR_NAME (property))
938         string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
939       else
940         string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
941       obstack_grow (&util_obstack, string, strlen (string));
942     }
943
944   /* NULL-terminate string.  */
945   obstack_1grow (&util_obstack, 0);
946   string = XOBFINISH (&util_obstack, char *);
947   obstack_free (&util_obstack, util_firstobj);
948   return get_identifier (string);
949 }