OSDN Git Service

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