]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/objc/objc-runtime-shared-support.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / objc / objc-runtime-shared-support.cc
1 /* Support routines shared by all runtimes.
2 Copyright (C) 2011-2024 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, "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];
297
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);
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 (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 (""), 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, "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". */
501 UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_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 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 (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));
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, "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;
625 if (decl)
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.
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 (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"