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