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