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