annotate gcc/objc/objc-encoding.c @ 158:494b0b89df80 default tip

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