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