]>
Commit | Line | Data |
---|---|---|
d764a8e6 | 1 | /* Support routines shared by all runtimes. |
7adcbafe | 2 | Copyright (C) 2011-2022 Free Software Foundation, Inc. |
d764a8e6 IS |
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" | |
d8a2d370 | 25 | #include "stringpool.h" |
d764a8e6 IS |
26 | |
27 | #ifdef OBJCPLUS | |
d4a10d0a | 28 | #include "cp/cp-tree.h" |
d764a8e6 | 29 | #else |
d4a10d0a SB |
30 | #include "c/c-tree.h" |
31 | #include "c/c-lang.h" | |
d764a8e6 | 32 | #endif |
d764a8e6 IS |
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 | ||
d764a8e6 IS |
43 | /* Hooks for string decls etc. */ |
44 | #include "objc-runtime-hooks.h" | |
45 | ||
46 | #include "objc-runtime-shared-support.h" | |
d764a8e6 | 47 | #include "objc-next-metadata-tags.h" |
c9419fae | 48 | #include "objc-encoding.h" |
d764a8e6 IS |
49 | |
50 | /* Rather than repeatedly looking up the identifiers, we save them here. */ | |
c9419fae | 51 | extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX]; |
d764a8e6 IS |
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 | { | |
1cc74766 IS |
115 | tree name_id = get_identifier (name); |
116 | tree var = build_decl (input_location, VAR_DECL, name_id, type); | |
d764a8e6 | 117 | DECL_INITIAL (var) = error_mark_node; /* A real initializer is coming... */ |
1cc74766 | 118 | TREE_STATIC (var) = 1; |
d764a8e6 IS |
119 | DECL_IGNORED_P (var) = 1; |
120 | DECL_ARTIFICIAL (var) = 1; | |
121 | DECL_CONTEXT (var) = NULL_TREE; | |
122 | #ifdef OBJCPLUS | |
1cc74766 IS |
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); | |
d764a8e6 IS |
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; | |
944fb799 MS |
154 | struct _objc_class *super_class; |
155 | [or Class cls; for the abi v2] | |
d764a8e6 IS |
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, "self", &chain); | |
167 | ||
168 | /* struct _objc_class *super_class; */ | |
169 | add_field_decl (build_pointer_type (objc_class_template), | |
170 | "super_class", &chain); | |
171 | ||
172 | objc_finish_struct (objc_super_template, 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, "_cmd", &chain); | |
193 | ||
194 | /* char *method_types; */ | |
195 | add_field_decl (string_type_node, "method_types", &chain); | |
196 | ||
197 | /* void *_imp; */ | |
198 | add_field_decl (build_pointer_type (void_type_node), "_imp", &chain); | |
199 | ||
200 | objc_finish_struct (_SLT_record, 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, "_cmd", &chain); | |
215 | ||
216 | /* char *method_types; */ | |
217 | add_field_decl (string_type_node, "method_types", &chain); | |
218 | ||
219 | objc_finish_struct (proto_record, 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, "method_next", &chain); | |
240 | ||
241 | /* int method_count; */ | |
242 | add_field_decl (integer_type_node, "method_count", &chain); | |
243 | ||
244 | /* struct objc_method method_list[]; */ | |
245 | array_type = build_sized_array_type (list_type, size); | |
246 | add_field_decl (array_type, "method_list", &chain); | |
247 | ||
248 | objc_finish_struct (objc_ivar_list_record, 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, "method_count", &chain); | |
273 | ||
274 | /* struct objc_method method_list[]; */ | |
275 | array_type = build_sized_array_type (list_type, size); | |
276 | add_field_decl (array_type, "method_list", &chain); | |
277 | ||
278 | objc_finish_struct (objc_ivar_list_record, 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]; | |
944fb799 | 297 | |
d764a8e6 IS |
298 | switch (section) |
299 | { | |
300 | case class_names: | |
301 | chain = &class_names_chain; | |
302 | snprintf (buf, BUFSIZE, "_OBJC_ClassName_%s", IDENTIFIER_POINTER (ident)); | |
303 | break; | |
304 | case meth_var_names: | |
305 | chain = &meth_var_names_chain; | |
306 | snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++); | |
307 | break; | |
308 | case meth_var_types: | |
309 | chain = &meth_var_types_chain; | |
310 | snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++); | |
311 | break; | |
312 | case prop_names_attr: | |
313 | chain = &prop_names_attr_chain; | |
314 | snprintf (buf, BUFSIZE, "_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); | |
944fb799 | 331 | /* Get a runtime-specific string decl which will be finish_var()'ed in |
d764a8e6 IS |
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 | ||
944fb799 | 337 | return convert (string_type_node, |
d764a8e6 IS |
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 | { | |
9771b263 | 346 | vec<constructor_elt, va_gc> *inits = NULL; |
d764a8e6 IS |
347 | |
348 | do | |
349 | { | |
9771b263 | 350 | vec<constructor_elt, va_gc> *elts = NULL; |
d764a8e6 IS |
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 | { | |
9771b263 | 371 | vec<constructor_elt, va_gc> *inits = NULL; |
d764a8e6 IS |
372 | |
373 | do | |
374 | { | |
9771b263 | 375 | vec<constructor_elt, va_gc> *elems = NULL; |
d764a8e6 IS |
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 (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; | |
9771b263 | 433 | vec<constructor_elt, va_gc> *v = NULL; |
d764a8e6 IS |
434 | |
435 | /* No really useful place to point to. */ | |
436 | loc = UNKNOWN_LOCATION; | |
944fb799 | 437 | |
d764a8e6 IS |
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 (""), 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, | |
944fb799 | 458 | get_identifier (UTAG_SYMTAB))); |
d764a8e6 IS |
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, "version", &chain); | |
486 | ||
487 | /* long size; */ | |
488 | add_field_decl (long_integer_type_node, "size", &chain); | |
489 | ||
490 | /* char *name; */ | |
491 | add_field_decl (string_type_node, "name", &chain); | |
492 | ||
493 | /* struct _objc_symtab *symtab; */ | |
494 | add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE, | |
495 | get_identifier (UTAG_SYMTAB))), | |
496 | "symtab", &chain); | |
497 | ||
498 | objc_finish_struct (objc_module_template, decls); | |
499 | ||
500 | /* Create an instance of "_objc_module". */ | |
be742f1e | 501 | UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_Module"); |
d764a8e6 IS |
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 | ||
02de9c16 AH |
507 | /* Squash `defined but not used' warning. */ |
508 | TREE_USED (UOBJC_MODULES_decl) = 1; | |
509 | ||
d764a8e6 IS |
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) | |
944fb799 | 513 | DECL_ATTRIBUTES (UOBJC_MODULES_decl) = attr; |
d764a8e6 IS |
514 | |
515 | finish_var_decl (UOBJC_MODULES_decl, | |
516 | 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 | { | |
9771b263 | 527 | vec<constructor_elt, va_gc> *inits = NULL; |
d764a8e6 | 528 | |
5aaa8fb4 NS |
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 (encode_field_decl (field_decl), | |
547 | 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)); | |
d764a8e6 | 554 | } |
d764a8e6 IS |
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, "ivar_count", &chain); | |
574 | ||
575 | /* struct objc_ivar ivar_list[]; */ | |
576 | array_type = build_sized_array_type (list_type, size); | |
577 | add_field_decl (array_type, "ivar_list", &chain); | |
578 | ||
579 | objc_finish_struct (objc_ivar_list_record, 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 (objc_ivar_id); | |
598 | ||
599 | /* char *ivar_name; */ | |
600 | decls = add_field_decl (string_type_node, "ivar_name", &chain); | |
601 | ||
602 | /* char *ivar_type; */ | |
603 | add_field_decl (string_type_node, "ivar_type", &chain); | |
604 | ||
605 | /* int ivar_offset; */ | |
606 | add_field_decl (integer_type_node, "ivar_offset", &chain); | |
607 | ||
608 | objc_finish_struct (objc_ivar_record, 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; | |
944fb799 | 625 | if (decl) |
d764a8e6 IS |
626 | loc = DECL_SOURCE_LOCATION (decl); |
627 | else | |
628 | loc = UNKNOWN_LOCATION; | |
629 | diagnose_missing_method (TREE_VALUE (chain), 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. | |
944fb799 | 637 | The runtime re-writes these on start-up, but the compiler can't see |
d764a8e6 IS |
638 | that and optimizes it away unless we force it. */ |
639 | DECL_PRESERVE_P (decl) = 1; | |
640 | finish_var_decl (decl, 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 (decl, 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 (decl, 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 (decl, 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 (decl, string_expr); | |
715 | } | |
716 | } | |
717 | ||
718 | #include "gt-objc-objc-runtime-shared-support.h" |