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