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
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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. */
51extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
52tree 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
57static bool objc_building_struct;
58static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
59
60/* Start building a struct for objc. */
61
62tree
63objc_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
72tree
73objc_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
81tree
82build_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
90static tree
91create_field_decl (tree type, const char *name)
92{
93 return build_decl (input_location,
94 FIELD_DECL, get_identifier (name), type);
95}
96
97tree
98add_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
112tree
113start_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
133void
134finish_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
141tree
142build_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
158void
159build_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
183tree
184build_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
205tree
206build_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
230tree
231build_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
261tree
262build_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
288static GTY(()) int meth_var_names_idx;
289static GTY(()) int meth_var_types_idx;
290static GTY(()) int property_name_attr_idx;
291
292tree
293add_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
343tree
344build_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
368tree
369build_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 (). */
406void
407diagnose_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
428static tree
429init_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
473void
474build_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
524tree
525build_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
564tree
565build_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
590tree
591build_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 */
614void
615build_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
645void
646generate_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). */
675void
676generate_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

source code of gcc/objc/objc-runtime-shared-support.cc