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