annotate gcc/objc/objc-runtime-shared-support.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 /* Support routines shared by all runtimes.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Iain Sandoe (partially split from objc-act.c)
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
8 it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
10 any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful,
kono
parents:
diff changeset
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
15 GNU General Public License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include "config.h"
kono
parents:
diff changeset
22 #include "system.h"
kono
parents:
diff changeset
23 #include "coretypes.h"
kono
parents:
diff changeset
24 #include "tm.h"
kono
parents:
diff changeset
25 #include "stringpool.h"
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 #ifdef OBJCPLUS
kono
parents:
diff changeset
28 #include "cp/cp-tree.h"
kono
parents:
diff changeset
29 #else
kono
parents:
diff changeset
30 #include "c/c-tree.h"
kono
parents:
diff changeset
31 #include "c/c-lang.h"
kono
parents:
diff changeset
32 #endif
kono
parents:
diff changeset
33 #include "c-family/c-objc.h"
kono
parents:
diff changeset
34 #include "objc-act.h"
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 /* When building Objective-C++, we are not linking against the C front-end
kono
parents:
diff changeset
37 and so need to replicate the C tree-construction functions in some way. */
kono
parents:
diff changeset
38 #ifdef OBJCPLUS
kono
parents:
diff changeset
39 #define OBJCP_REMAP_FUNCTIONS
kono
parents:
diff changeset
40 #include "objcp-decl.h"
kono
parents:
diff changeset
41 #endif /* OBJCPLUS */
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 /* Hooks for string decls etc. */
kono
parents:
diff changeset
44 #include "objc-runtime-hooks.h"
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 #include "objc-runtime-shared-support.h"
kono
parents:
diff changeset
47 #include "objc-encoding.h"
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 /* rt_trees identifiers - shared between NeXT implementations. These allow
kono
parents:
diff changeset
50 the FE to tag meta-data in a manner that survives LTO and can be used when
kono
parents:
diff changeset
51 the runtime requires that certain meta-data items appear in particular
kono
parents:
diff changeset
52 named sections. */
kono
parents:
diff changeset
53 #include "objc-next-metadata-tags.h"
kono
parents:
diff changeset
54 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 /* Rather than repeatedly looking up the identifiers, we save them here. */
kono
parents:
diff changeset
57 tree objc_rt_trees[OCTI_RT_META_MAX];
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 /* For building an objc struct. These might not be used when this file
kono
parents:
diff changeset
60 is compiled as part of obj-c++. */
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 static bool objc_building_struct;
kono
parents:
diff changeset
63 static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 /* Start building a struct for objc. */
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 tree
kono
parents:
diff changeset
68 objc_start_struct (tree name)
kono
parents:
diff changeset
69 {
kono
parents:
diff changeset
70 gcc_assert (!objc_building_struct);
kono
parents:
diff changeset
71 objc_building_struct = true;
kono
parents:
diff changeset
72 return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info);
kono
parents:
diff changeset
73 }
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 /* Finish building a struct for objc. */
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 tree
kono
parents:
diff changeset
78 objc_finish_struct (tree type, tree fieldlist)
kono
parents:
diff changeset
79 {
kono
parents:
diff changeset
80 gcc_assert (objc_building_struct);
kono
parents:
diff changeset
81 objc_building_struct = false;
kono
parents:
diff changeset
82 return finish_struct (input_location, type, fieldlist, NULL_TREE,
kono
parents:
diff changeset
83 objc_struct_info);
kono
parents:
diff changeset
84 }
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 tree
kono
parents:
diff changeset
87 build_sized_array_type (tree base_type, int size)
kono
parents:
diff changeset
88 {
kono
parents:
diff changeset
89 tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1));
kono
parents:
diff changeset
90 return build_array_type (base_type, index_type);
kono
parents:
diff changeset
91 }
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 /* Create a declaration for field NAME of a given TYPE. */
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 static tree
kono
parents:
diff changeset
96 create_field_decl (tree type, const char *name)
kono
parents:
diff changeset
97 {
kono
parents:
diff changeset
98 return build_decl (input_location,
kono
parents:
diff changeset
99 FIELD_DECL, get_identifier (name), type);
kono
parents:
diff changeset
100 }
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 tree
kono
parents:
diff changeset
103 add_field_decl (tree type, const char *name, tree **chain)
kono
parents:
diff changeset
104 {
kono
parents:
diff changeset
105 tree field = create_field_decl (type, name);
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 if (*chain != NULL)
kono
parents:
diff changeset
108 **chain = field;
kono
parents:
diff changeset
109 *chain = &DECL_CHAIN (field);
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 return field;
kono
parents:
diff changeset
112 }
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 /* Create a global, static declaration for variable NAME of a given TYPE. The
kono
parents:
diff changeset
115 finish_var_decl() routine will need to be called on it afterwards. */
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 tree
kono
parents:
diff changeset
118 start_var_decl (tree type, const char *name)
kono
parents:
diff changeset
119 {
kono
parents:
diff changeset
120 tree var = build_decl (input_location,
kono
parents:
diff changeset
121 VAR_DECL, get_identifier (name), type);
kono
parents:
diff changeset
122 TREE_STATIC (var) = 1;
kono
parents:
diff changeset
123 DECL_INITIAL (var) = error_mark_node; /* A real initializer is coming... */
kono
parents:
diff changeset
124 DECL_IGNORED_P (var) = 1;
kono
parents:
diff changeset
125 DECL_ARTIFICIAL (var) = 1;
kono
parents:
diff changeset
126 DECL_CONTEXT (var) = NULL_TREE;
kono
parents:
diff changeset
127 #ifdef OBJCPLUS
kono
parents:
diff changeset
128 DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
kono
parents:
diff changeset
129 #endif
kono
parents:
diff changeset
130 return var;
kono
parents:
diff changeset
131 }
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 /* Finish off the variable declaration created by start_var_decl(). */
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 void
kono
parents:
diff changeset
136 finish_var_decl (tree var, tree initializer)
kono
parents:
diff changeset
137 {
kono
parents:
diff changeset
138 finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE);
kono
parents:
diff changeset
139 }
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 /* Just a handy wrapper for add_objc_string. */
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 tree
kono
parents:
diff changeset
144 build_selector (tree ident)
kono
parents:
diff changeset
145 {
kono
parents:
diff changeset
146 return convert (objc_selector_type, add_objc_string (ident, meth_var_names));
kono
parents:
diff changeset
147 }
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 /* --- templates --- */
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
kono
parents:
diff changeset
152 This needs to be done just once per compilation. */
kono
parents:
diff changeset
153
kono
parents:
diff changeset
154 /* struct _objc_super {
kono
parents:
diff changeset
155 struct _objc_object *self;
kono
parents:
diff changeset
156 struct _objc_class *super_class;
kono
parents:
diff changeset
157 [or Class cls; for the abi v2]
kono
parents:
diff changeset
158 }; */
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 void
kono
parents:
diff changeset
161 build_super_template (void)
kono
parents:
diff changeset
162 {
kono
parents:
diff changeset
163 tree decls, *chain = NULL;
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165 objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 /* struct _objc_object *self; */
kono
parents:
diff changeset
168 decls = add_field_decl (objc_object_type, "self", &chain);
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 /* struct _objc_class *super_class; */
kono
parents:
diff changeset
171 add_field_decl (build_pointer_type (objc_class_template),
kono
parents:
diff changeset
172 "super_class", &chain);
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 objc_finish_struct (objc_super_template, decls);
kono
parents:
diff changeset
175 }
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 /* To accomplish method prototyping without generating all kinds of
kono
parents:
diff changeset
178 inane warnings, the definition of the dispatch table entries were
kono
parents:
diff changeset
179 changed from:
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
kono
parents:
diff changeset
182 to:
kono
parents:
diff changeset
183 struct objc_method { SEL _cmd; ...; void *_imp; }; */
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 tree
kono
parents:
diff changeset
186 build_method_template (void)
kono
parents:
diff changeset
187 {
kono
parents:
diff changeset
188 tree _SLT_record;
kono
parents:
diff changeset
189 tree decls, *chain = NULL;
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191 _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 /* SEL _cmd; */
kono
parents:
diff changeset
194 decls = add_field_decl (objc_selector_type, "_cmd", &chain);
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 /* char *method_types; */
kono
parents:
diff changeset
197 add_field_decl (string_type_node, "method_types", &chain);
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 /* void *_imp; */
kono
parents:
diff changeset
200 add_field_decl (build_pointer_type (void_type_node), "_imp", &chain);
kono
parents:
diff changeset
201
kono
parents:
diff changeset
202 objc_finish_struct (_SLT_record, decls);
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 return _SLT_record;
kono
parents:
diff changeset
205 }
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 tree
kono
parents:
diff changeset
208 build_method_prototype_template (void)
kono
parents:
diff changeset
209 {
kono
parents:
diff changeset
210 tree proto_record;
kono
parents:
diff changeset
211 tree decls, *chain = NULL;
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 /* SEL _cmd; */
kono
parents:
diff changeset
216 decls = add_field_decl (objc_selector_type, "_cmd", &chain);
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 /* char *method_types; */
kono
parents:
diff changeset
219 add_field_decl (string_type_node, "method_types", &chain);
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 objc_finish_struct (proto_record, decls);
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 return proto_record;
kono
parents:
diff changeset
224 }
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 /* struct {
kono
parents:
diff changeset
227 struct _objc__method_prototype_list *method_next;
kono
parents:
diff changeset
228 int method_count;
kono
parents:
diff changeset
229 struct objc_method method_list[method_count];
kono
parents:
diff changeset
230 }; */
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 tree
kono
parents:
diff changeset
233 build_method_list_template (tree list_type, int size)
kono
parents:
diff changeset
234 {
kono
parents:
diff changeset
235 tree objc_ivar_list_record;
kono
parents:
diff changeset
236 tree array_type, decls, *chain = NULL;
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 objc_ivar_list_record = objc_start_struct (NULL_TREE);
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 /* struct _objc__method_prototype_list *method_next; */
kono
parents:
diff changeset
241 decls = add_field_decl (objc_method_proto_list_ptr, "method_next", &chain);
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 /* int method_count; */
kono
parents:
diff changeset
244 add_field_decl (integer_type_node, "method_count", &chain);
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 /* struct objc_method method_list[]; */
kono
parents:
diff changeset
247 array_type = build_sized_array_type (list_type, size);
kono
parents:
diff changeset
248 add_field_decl (array_type, "method_list", &chain);
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 objc_finish_struct (objc_ivar_list_record, decls);
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 return objc_ivar_list_record;
kono
parents:
diff changeset
253 }
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 /* struct objc_method_prototype_list {
kono
parents:
diff changeset
256 int count;
kono
parents:
diff changeset
257 struct objc_method_prototype {
kono
parents:
diff changeset
258 SEL name;
kono
parents:
diff changeset
259 char *types;
kono
parents:
diff changeset
260 } list[1];
kono
parents:
diff changeset
261 }; */
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 tree
kono
parents:
diff changeset
264 build_method_prototype_list_template (tree list_type, int size)
kono
parents:
diff changeset
265 {
kono
parents:
diff changeset
266 tree objc_ivar_list_record;
kono
parents:
diff changeset
267 tree array_type, decls, *chain = NULL;
kono
parents:
diff changeset
268
kono
parents:
diff changeset
269 /* Generate an unnamed struct definition. */
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 objc_ivar_list_record = objc_start_struct (NULL_TREE);
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 /* int method_count; */
kono
parents:
diff changeset
274 decls = add_field_decl (integer_type_node, "method_count", &chain);
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 /* struct objc_method method_list[]; */
kono
parents:
diff changeset
277 array_type = build_sized_array_type (list_type, size);
kono
parents:
diff changeset
278 add_field_decl (array_type, "method_list", &chain);
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 objc_finish_struct (objc_ivar_list_record, decls);
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 return objc_ivar_list_record;
kono
parents:
diff changeset
283 }
kono
parents:
diff changeset
284
kono
parents:
diff changeset
285 /* --- names, decls entry --- */
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 /* For each string section we have a chain which maps identifier nodes
kono
parents:
diff changeset
288 to decls for the strings. */
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 static GTY(()) int meth_var_names_idx;
kono
parents:
diff changeset
291 static GTY(()) int meth_var_types_idx;
kono
parents:
diff changeset
292 static GTY(()) int property_name_attr_idx;
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 tree
kono
parents:
diff changeset
295 add_objc_string (tree ident, string_section section)
kono
parents:
diff changeset
296 {
kono
parents:
diff changeset
297 tree *chain, decl, type;
kono
parents:
diff changeset
298 char buf[BUFSIZE];
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 switch (section)
kono
parents:
diff changeset
301 {
kono
parents:
diff changeset
302 case class_names:
kono
parents:
diff changeset
303 chain = &class_names_chain;
kono
parents:
diff changeset
304 snprintf (buf, BUFSIZE, "_OBJC_ClassName_%s", IDENTIFIER_POINTER (ident));
kono
parents:
diff changeset
305 break;
kono
parents:
diff changeset
306 case meth_var_names:
kono
parents:
diff changeset
307 chain = &meth_var_names_chain;
kono
parents:
diff changeset
308 snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
kono
parents:
diff changeset
309 break;
kono
parents:
diff changeset
310 case meth_var_types:
kono
parents:
diff changeset
311 chain = &meth_var_types_chain;
kono
parents:
diff changeset
312 snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
kono
parents:
diff changeset
313 break;
kono
parents:
diff changeset
314 case prop_names_attr:
kono
parents:
diff changeset
315 chain = &prop_names_attr_chain;
kono
parents:
diff changeset
316 snprintf (buf, BUFSIZE, "_OBJC_PropertyAttributeOrName_%d", property_name_attr_idx++);
kono
parents:
diff changeset
317 break;
kono
parents:
diff changeset
318 default:
kono
parents:
diff changeset
319 gcc_unreachable ();
kono
parents:
diff changeset
320 }
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 while (*chain)
kono
parents:
diff changeset
323 {
kono
parents:
diff changeset
324 if (TREE_VALUE (*chain) == ident)
kono
parents:
diff changeset
325 return convert (string_type_node,
kono
parents:
diff changeset
326 build_unary_op (input_location,
kono
parents:
diff changeset
327 ADDR_EXPR, TREE_PURPOSE (*chain), 1));
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 chain = &TREE_CHAIN (*chain);
kono
parents:
diff changeset
330 }
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1);
kono
parents:
diff changeset
333 /* Get a runtime-specific string decl which will be finish_var()'ed in
kono
parents:
diff changeset
334 generate_strings (). */
kono
parents:
diff changeset
335 decl = (*runtime.string_decl) (type, buf, section);
kono
parents:
diff changeset
336 TREE_CONSTANT (decl) = 1;
kono
parents:
diff changeset
337 *chain = tree_cons (decl, ident, NULL_TREE);
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 return convert (string_type_node,
kono
parents:
diff changeset
340 build_unary_op (input_location, ADDR_EXPR, decl, 1));
kono
parents:
diff changeset
341 }
kono
parents:
diff changeset
342
kono
parents:
diff changeset
343 /* --- shared metadata routines --- */
kono
parents:
diff changeset
344
kono
parents:
diff changeset
345 tree
kono
parents:
diff changeset
346 build_descriptor_table_initializer (tree type, tree entries)
kono
parents:
diff changeset
347 {
kono
parents:
diff changeset
348 vec<constructor_elt, va_gc> *inits = NULL;
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 do
kono
parents:
diff changeset
351 {
kono
parents:
diff changeset
352 vec<constructor_elt, va_gc> *elts = NULL;
kono
parents:
diff changeset
353
kono
parents:
diff changeset
354 CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
kono
parents:
diff changeset
355 build_selector (METHOD_SEL_NAME (entries)));
kono
parents:
diff changeset
356 CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
kono
parents:
diff changeset
357 add_objc_string (METHOD_ENCODING (entries),
kono
parents:
diff changeset
358 meth_var_types));
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
kono
parents:
diff changeset
361 objc_build_constructor (type, elts));
kono
parents:
diff changeset
362
kono
parents:
diff changeset
363 entries = DECL_CHAIN (entries);
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365 while (entries);
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 return objc_build_constructor (build_array_type (type, 0), inits);
kono
parents:
diff changeset
368 }
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 tree
kono
parents:
diff changeset
371 build_dispatch_table_initializer (tree type, tree entries)
kono
parents:
diff changeset
372 {
kono
parents:
diff changeset
373 vec<constructor_elt, va_gc> *inits = NULL;
kono
parents:
diff changeset
374
kono
parents:
diff changeset
375 do
kono
parents:
diff changeset
376 {
kono
parents:
diff changeset
377 vec<constructor_elt, va_gc> *elems = NULL;
kono
parents:
diff changeset
378 tree expr;
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
kono
parents:
diff changeset
381 build_selector (METHOD_SEL_NAME (entries)));
kono
parents:
diff changeset
382
kono
parents:
diff changeset
383 /* Generate the method encoding if we don't have one already. */
kono
parents:
diff changeset
384 if (! METHOD_ENCODING (entries))
kono
parents:
diff changeset
385 METHOD_ENCODING (entries) =
kono
parents:
diff changeset
386 encode_method_prototype (entries);
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
kono
parents:
diff changeset
389 add_objc_string (METHOD_ENCODING (entries),
kono
parents:
diff changeset
390 meth_var_types));
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 expr = convert (ptr_type_node,
kono
parents:
diff changeset
393 build_unary_op (input_location, ADDR_EXPR,
kono
parents:
diff changeset
394 METHOD_DEFINITION (entries), 1));
kono
parents:
diff changeset
395 CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, expr);
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
kono
parents:
diff changeset
398 objc_build_constructor (type, elems));
kono
parents:
diff changeset
399
kono
parents:
diff changeset
400 entries = DECL_CHAIN (entries);
kono
parents:
diff changeset
401 }
kono
parents:
diff changeset
402 while (entries);
kono
parents:
diff changeset
403
kono
parents:
diff changeset
404 return objc_build_constructor (build_array_type (type, 0), inits);
kono
parents:
diff changeset
405 }
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 /* Used only by build_*_selector_translation_table (). */
kono
parents:
diff changeset
408 void
kono
parents:
diff changeset
409 diagnose_missing_method (tree meth, location_t here)
kono
parents:
diff changeset
410 {
kono
parents:
diff changeset
411 tree method_chain;
kono
parents:
diff changeset
412 bool found = false;
kono
parents:
diff changeset
413 for (method_chain = meth_var_names_chain;
kono
parents:
diff changeset
414 method_chain;
kono
parents:
diff changeset
415 method_chain = TREE_CHAIN (method_chain))
kono
parents:
diff changeset
416 {
kono
parents:
diff changeset
417 if (TREE_VALUE (method_chain) == meth)
kono
parents:
diff changeset
418 {
kono
parents:
diff changeset
419 found = true;
kono
parents:
diff changeset
420 break;
kono
parents:
diff changeset
421 }
kono
parents:
diff changeset
422 }
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 if (!found)
kono
parents:
diff changeset
425 warning_at (here, 0, "creating selector for nonexistent method %qE",
kono
parents:
diff changeset
426 meth);
kono
parents:
diff changeset
427 }
kono
parents:
diff changeset
428
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 static tree
kono
parents:
diff changeset
431 init_module_descriptor (tree type, long vers)
kono
parents:
diff changeset
432 {
kono
parents:
diff changeset
433 tree expr, ltyp;
kono
parents:
diff changeset
434 location_t loc;
kono
parents:
diff changeset
435 vec<constructor_elt, va_gc> *v = NULL;
kono
parents:
diff changeset
436
kono
parents:
diff changeset
437 /* No really useful place to point to. */
kono
parents:
diff changeset
438 loc = UNKNOWN_LOCATION;
kono
parents:
diff changeset
439
kono
parents:
diff changeset
440 /* version = { 1, ... } */
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 expr = build_int_cst (long_integer_type_node, vers);
kono
parents:
diff changeset
443 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 /* size = { ..., sizeof (struct _objc_module), ... } */
kono
parents:
diff changeset
446
kono
parents:
diff changeset
447 expr = convert (long_integer_type_node,
kono
parents:
diff changeset
448 size_in_bytes (objc_module_template));
kono
parents:
diff changeset
449 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
450
kono
parents:
diff changeset
451 /* Don't provide any file name for security reasons. */
kono
parents:
diff changeset
452 /* name = { ..., "", ... } */
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 expr = add_objc_string (get_identifier (""), class_names);
kono
parents:
diff changeset
455 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
456
kono
parents:
diff changeset
457 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
460 get_identifier (UTAG_SYMTAB)));
kono
parents:
diff changeset
461 if (UOBJC_SYMBOLS_decl)
kono
parents:
diff changeset
462 expr = convert (ltyp, build_unary_op (loc,
kono
parents:
diff changeset
463 ADDR_EXPR, UOBJC_SYMBOLS_decl, 0));
kono
parents:
diff changeset
464 else
kono
parents:
diff changeset
465 expr = convert (ltyp, null_pointer_node);
kono
parents:
diff changeset
466 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 return objc_build_constructor (type, v);
kono
parents:
diff changeset
469 }
kono
parents:
diff changeset
470
kono
parents:
diff changeset
471 /* Write out the data structures to describe Objective C classes defined.
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 struct _objc_module { ... } _OBJC_MODULE = { ... }; */
kono
parents:
diff changeset
474
kono
parents:
diff changeset
475 void
kono
parents:
diff changeset
476 build_module_descriptor (long vers, tree attr)
kono
parents:
diff changeset
477 {
kono
parents:
diff changeset
478 tree decls, *chain = NULL;
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 #ifdef OBJCPLUS
kono
parents:
diff changeset
481 push_lang_context (lang_name_c); /* extern "C" */
kono
parents:
diff changeset
482 #endif
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE));
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 /* long version; */
kono
parents:
diff changeset
487 decls = add_field_decl (long_integer_type_node, "version", &chain);
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 /* long size; */
kono
parents:
diff changeset
490 add_field_decl (long_integer_type_node, "size", &chain);
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 /* char *name; */
kono
parents:
diff changeset
493 add_field_decl (string_type_node, "name", &chain);
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 /* struct _objc_symtab *symtab; */
kono
parents:
diff changeset
496 add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE,
kono
parents:
diff changeset
497 get_identifier (UTAG_SYMTAB))),
kono
parents:
diff changeset
498 "symtab", &chain);
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 objc_finish_struct (objc_module_template, decls);
kono
parents:
diff changeset
501
kono
parents:
diff changeset
502 /* Create an instance of "_objc_module". */
kono
parents:
diff changeset
503 UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_Module");
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 /* This is the root of the metadata for defined classes and categories, it
kono
parents:
diff changeset
506 is referenced by the runtime and, therefore, needed. */
kono
parents:
diff changeset
507 DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1;
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 /* Squash `defined but not used' warning. */
kono
parents:
diff changeset
510 TREE_USED (UOBJC_MODULES_decl) = 1;
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 /* Allow the runtime to mark meta-data such that it can be assigned to target
kono
parents:
diff changeset
513 specific sections by the back-end. */
kono
parents:
diff changeset
514 if (attr)
kono
parents:
diff changeset
515 DECL_ATTRIBUTES (UOBJC_MODULES_decl) = attr;
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 finish_var_decl (UOBJC_MODULES_decl,
kono
parents:
diff changeset
518 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl),
kono
parents:
diff changeset
519 vers));
kono
parents:
diff changeset
520
kono
parents:
diff changeset
521 #ifdef OBJCPLUS
kono
parents:
diff changeset
522 pop_lang_context ();
kono
parents:
diff changeset
523 #endif
kono
parents:
diff changeset
524 }
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 tree
kono
parents:
diff changeset
527 build_ivar_list_initializer (tree type, tree field_decl)
kono
parents:
diff changeset
528 {
kono
parents:
diff changeset
529 vec<constructor_elt, va_gc> *inits = NULL;
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 for (; field_decl; field_decl = DECL_CHAIN (field_decl))
kono
parents:
diff changeset
532 if (TREE_CODE (field_decl) == FIELD_DECL)
kono
parents:
diff changeset
533 {
kono
parents:
diff changeset
534 vec<constructor_elt, va_gc> *ivar = NULL;
kono
parents:
diff changeset
535 tree id;
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 /* Set name. */
kono
parents:
diff changeset
538 if (DECL_NAME (field_decl))
kono
parents:
diff changeset
539 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
kono
parents:
diff changeset
540 add_objc_string (DECL_NAME (field_decl),
kono
parents:
diff changeset
541 meth_var_names));
kono
parents:
diff changeset
542 else
kono
parents:
diff changeset
543 /* Unnamed bit-field ivar (yuck). */
kono
parents:
diff changeset
544 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
kono
parents:
diff changeset
545 build_int_cst (NULL_TREE, 0));
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 /* Set type. */
kono
parents:
diff changeset
548 id = add_objc_string (encode_field_decl (field_decl),
kono
parents:
diff changeset
549 meth_var_types);
kono
parents:
diff changeset
550 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
kono
parents:
diff changeset
551
kono
parents:
diff changeset
552 /* Set offset. */
kono
parents:
diff changeset
553 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
kono
parents:
diff changeset
554 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
kono
parents:
diff changeset
555 objc_build_constructor (type, ivar));
kono
parents:
diff changeset
556 }
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 return objc_build_constructor (build_array_type (type, 0), inits);
kono
parents:
diff changeset
559 }
kono
parents:
diff changeset
560
kono
parents:
diff changeset
561 /* struct {
kono
parents:
diff changeset
562 int ivar_count;
kono
parents:
diff changeset
563 struct objc_ivar ivar_list[ivar_count];
kono
parents:
diff changeset
564 }; */
kono
parents:
diff changeset
565
kono
parents:
diff changeset
566 tree
kono
parents:
diff changeset
567 build_ivar_list_template (tree list_type, int size)
kono
parents:
diff changeset
568 {
kono
parents:
diff changeset
569 tree objc_ivar_list_record;
kono
parents:
diff changeset
570 tree array_type, decls, *chain = NULL;
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 objc_ivar_list_record = objc_start_struct (NULL_TREE);
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 /* int ivar_count; */
kono
parents:
diff changeset
575 decls = add_field_decl (integer_type_node, "ivar_count", &chain);
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 /* struct objc_ivar ivar_list[]; */
kono
parents:
diff changeset
578 array_type = build_sized_array_type (list_type, size);
kono
parents:
diff changeset
579 add_field_decl (array_type, "ivar_list", &chain);
kono
parents:
diff changeset
580
kono
parents:
diff changeset
581 objc_finish_struct (objc_ivar_list_record, decls);
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583 return objc_ivar_list_record;
kono
parents:
diff changeset
584 }
kono
parents:
diff changeset
585
kono
parents:
diff changeset
586 /* struct _objc_ivar {
kono
parents:
diff changeset
587 char *ivar_name;
kono
parents:
diff changeset
588 char *ivar_type;
kono
parents:
diff changeset
589 int ivar_offset;
kono
parents:
diff changeset
590 }; */
kono
parents:
diff changeset
591
kono
parents:
diff changeset
592 tree
kono
parents:
diff changeset
593 build_ivar_template (void)
kono
parents:
diff changeset
594 {
kono
parents:
diff changeset
595 tree objc_ivar_id, objc_ivar_record;
kono
parents:
diff changeset
596 tree decls, *chain = NULL;
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598 objc_ivar_id = get_identifier (UTAG_IVAR);
kono
parents:
diff changeset
599 objc_ivar_record = objc_start_struct (objc_ivar_id);
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 /* char *ivar_name; */
kono
parents:
diff changeset
602 decls = add_field_decl (string_type_node, "ivar_name", &chain);
kono
parents:
diff changeset
603
kono
parents:
diff changeset
604 /* char *ivar_type; */
kono
parents:
diff changeset
605 add_field_decl (string_type_node, "ivar_type", &chain);
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 /* int ivar_offset; */
kono
parents:
diff changeset
608 add_field_decl (integer_type_node, "ivar_offset", &chain);
kono
parents:
diff changeset
609
kono
parents:
diff changeset
610 objc_finish_struct (objc_ivar_record, decls);
kono
parents:
diff changeset
611
kono
parents:
diff changeset
612 return objc_ivar_record;
kono
parents:
diff changeset
613 }
kono
parents:
diff changeset
614
kono
parents:
diff changeset
615 /* Used by NeXT ABI=0..2 */
kono
parents:
diff changeset
616 void
kono
parents:
diff changeset
617 build_next_selector_translation_table (void)
kono
parents:
diff changeset
618 {
kono
parents:
diff changeset
619 tree chain;
kono
parents:
diff changeset
620 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
kono
parents:
diff changeset
621 {
kono
parents:
diff changeset
622 tree expr;
kono
parents:
diff changeset
623 tree decl = TREE_PURPOSE (chain);
kono
parents:
diff changeset
624 if (warn_selector)
kono
parents:
diff changeset
625 {
kono
parents:
diff changeset
626 location_t loc;
kono
parents:
diff changeset
627 if (decl)
kono
parents:
diff changeset
628 loc = DECL_SOURCE_LOCATION (decl);
kono
parents:
diff changeset
629 else
kono
parents:
diff changeset
630 loc = UNKNOWN_LOCATION;
kono
parents:
diff changeset
631 diagnose_missing_method (TREE_VALUE (chain), loc);
kono
parents:
diff changeset
632 }
kono
parents:
diff changeset
633
kono
parents:
diff changeset
634 expr = build_selector (TREE_VALUE (chain));
kono
parents:
diff changeset
635
kono
parents:
diff changeset
636 if (decl)
kono
parents:
diff changeset
637 {
kono
parents:
diff changeset
638 /* Entries of this form are used for references to methods.
kono
parents:
diff changeset
639 The runtime re-writes these on start-up, but the compiler can't see
kono
parents:
diff changeset
640 that and optimizes it away unless we force it. */
kono
parents:
diff changeset
641 DECL_PRESERVE_P (decl) = 1;
kono
parents:
diff changeset
642 finish_var_decl (decl, expr);
kono
parents:
diff changeset
643 }
kono
parents:
diff changeset
644 }
kono
parents:
diff changeset
645 }
kono
parents:
diff changeset
646
kono
parents:
diff changeset
647 void
kono
parents:
diff changeset
648 generate_protocol_references (tree plist)
kono
parents:
diff changeset
649 {
kono
parents:
diff changeset
650 tree lproto;
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652 /* Forward declare protocols referenced. */
kono
parents:
diff changeset
653 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 tree proto = TREE_VALUE (lproto);
kono
parents:
diff changeset
656
kono
parents:
diff changeset
657 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
kono
parents:
diff changeset
658 && PROTOCOL_NAME (proto))
kono
parents:
diff changeset
659 {
kono
parents:
diff changeset
660 if (! PROTOCOL_FORWARD_DECL (proto))
kono
parents:
diff changeset
661 PROTOCOL_FORWARD_DECL (proto) = (*runtime.protocol_decl) (proto);
kono
parents:
diff changeset
662
kono
parents:
diff changeset
663 if (PROTOCOL_LIST (proto))
kono
parents:
diff changeset
664 generate_protocol_references (PROTOCOL_LIST (proto));
kono
parents:
diff changeset
665 }
kono
parents:
diff changeset
666 }
kono
parents:
diff changeset
667 }
kono
parents:
diff changeset
668
kono
parents:
diff changeset
669 /* --- new routines --- */
kono
parents:
diff changeset
670
kono
parents:
diff changeset
671 /* Output all strings. */
kono
parents:
diff changeset
672
kono
parents:
diff changeset
673 /* FIXME: don't use global vars for all this... */
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 /* This emits all the meta-data string tables (and finalizes each var
kono
parents:
diff changeset
676 as it goes). */
kono
parents:
diff changeset
677 void
kono
parents:
diff changeset
678 generate_strings (void)
kono
parents:
diff changeset
679 {
kono
parents:
diff changeset
680 tree chain, string_expr;
kono
parents:
diff changeset
681 tree string, decl; /* , type;*/
kono
parents:
diff changeset
682
kono
parents:
diff changeset
683 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
kono
parents:
diff changeset
684 {
kono
parents:
diff changeset
685 string = TREE_VALUE (chain);
kono
parents:
diff changeset
686 decl = TREE_PURPOSE (chain);
kono
parents:
diff changeset
687 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
kono
parents:
diff changeset
688 IDENTIFIER_POINTER (string));
kono
parents:
diff changeset
689 finish_var_decl (decl, string_expr);
kono
parents:
diff changeset
690 }
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
kono
parents:
diff changeset
693 {
kono
parents:
diff changeset
694 string = TREE_VALUE (chain);
kono
parents:
diff changeset
695 decl = TREE_PURPOSE (chain);
kono
parents:
diff changeset
696 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
kono
parents:
diff changeset
697 IDENTIFIER_POINTER (string));
kono
parents:
diff changeset
698 finish_var_decl (decl, string_expr);
kono
parents:
diff changeset
699 }
kono
parents:
diff changeset
700
kono
parents:
diff changeset
701 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
kono
parents:
diff changeset
702 {
kono
parents:
diff changeset
703 string = TREE_VALUE (chain);
kono
parents:
diff changeset
704 decl = TREE_PURPOSE (chain);
kono
parents:
diff changeset
705 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
kono
parents:
diff changeset
706 IDENTIFIER_POINTER (string));
kono
parents:
diff changeset
707 finish_var_decl (decl, string_expr);
kono
parents:
diff changeset
708 }
kono
parents:
diff changeset
709
kono
parents:
diff changeset
710 for (chain = prop_names_attr_chain; chain; chain = TREE_CHAIN (chain))
kono
parents:
diff changeset
711 {
kono
parents:
diff changeset
712 string = TREE_VALUE (chain);
kono
parents:
diff changeset
713 decl = TREE_PURPOSE (chain);
kono
parents:
diff changeset
714 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
kono
parents:
diff changeset
715 IDENTIFIER_POINTER (string));
kono
parents:
diff changeset
716 finish_var_decl (decl, string_expr);
kono
parents:
diff changeset
717 }
kono
parents:
diff changeset
718 }
kono
parents:
diff changeset
719
kono
parents:
diff changeset
720 #include "gt-objc-objc-runtime-shared-support.h"