hppa: Always enable PIE on 64-bit target
[official-gcc.git] / gcc / objc / objc-runtime-shared-support.cc
blob49dac5ea1dbc79ee1f433bc3e88c1e09e6ba23fb
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)
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "stringpool.h"
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"
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 */
43 /* Hooks for string decls etc. */
44 #include "objc-runtime-hooks.h"
46 #include "objc-runtime-shared-support.h"
47 #include "objc-next-metadata-tags.h"
48 #include "objc-encoding.h"
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];
54 /* For building an objc struct. These might not be used when this file
55 is compiled as part of obj-c++. */
57 static bool objc_building_struct;
58 static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
60 /* Start building a struct for objc. */
62 tree
63 objc_start_struct (tree name)
65 gcc_assert (!objc_building_struct);
66 objc_building_struct = true;
67 return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info);
70 /* Finish building a struct for objc. */
72 tree
73 objc_finish_struct (tree type, tree fieldlist)
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);
81 tree
82 build_sized_array_type (tree base_type, int size)
84 tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1));
85 return build_array_type (base_type, index_type);
88 /* Create a declaration for field NAME of a given TYPE. */
90 static tree
91 create_field_decl (tree type, const char *name)
93 return build_decl (input_location,
94 FIELD_DECL, get_identifier (name), type);
97 tree
98 add_field_decl (tree type, const char *name, tree **chain)
100 tree field = create_field_decl (type, name);
102 if (*chain != NULL)
103 **chain = field;
104 *chain = &DECL_CHAIN (field);
106 return field;
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. */
112 tree
113 start_var_decl (tree type, const char *name)
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;
131 /* Finish off the variable declaration created by start_var_decl(). */
133 void
134 finish_var_decl (tree var, tree initializer)
136 finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE);
139 /* Just a handy wrapper for add_objc_string. */
141 tree
142 build_selector (tree ident)
144 return convert (objc_selector_type, add_objc_string (ident, meth_var_names));
147 /* --- templates --- */
149 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
150 This needs to be done just once per compilation. */
152 /* struct _objc_super {
153 struct _objc_object *self;
154 struct _objc_class *super_class;
155 [or Class cls; for the abi v2]
156 }; */
158 void
159 build_super_template (void)
161 tree decls, *chain = NULL;
163 objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
165 /* struct _objc_object *self; */
166 decls = add_field_decl (objc_object_type, "self", &chain);
168 /* struct _objc_class *super_class; */
169 add_field_decl (build_pointer_type (objc_class_template),
170 "super_class", &chain);
172 objc_finish_struct (objc_super_template, decls);
175 /* To accomplish method prototyping without generating all kinds of
176 inane warnings, the definition of the dispatch table entries were
177 changed from:
179 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
181 struct objc_method { SEL _cmd; ...; void *_imp; }; */
183 tree
184 build_method_template (void)
186 tree _SLT_record;
187 tree decls, *chain = NULL;
189 _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
191 /* SEL _cmd; */
192 decls = add_field_decl (objc_selector_type, "_cmd", &chain);
194 /* char *method_types; */
195 add_field_decl (string_type_node, "method_types", &chain);
197 /* void *_imp; */
198 add_field_decl (build_pointer_type (void_type_node), "_imp", &chain);
200 objc_finish_struct (_SLT_record, decls);
202 return _SLT_record;
205 tree
206 build_method_prototype_template (void)
208 tree proto_record;
209 tree decls, *chain = NULL;
211 proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
213 /* SEL _cmd; */
214 decls = add_field_decl (objc_selector_type, "_cmd", &chain);
216 /* char *method_types; */
217 add_field_decl (string_type_node, "method_types", &chain);
219 objc_finish_struct (proto_record, decls);
221 return proto_record;
224 /* struct {
225 struct _objc__method_prototype_list *method_next;
226 int method_count;
227 struct objc_method method_list[method_count];
228 }; */
230 tree
231 build_method_list_template (tree list_type, int size)
233 tree objc_ivar_list_record;
234 tree array_type, decls, *chain = NULL;
236 objc_ivar_list_record = objc_start_struct (NULL_TREE);
238 /* struct _objc__method_prototype_list *method_next; */
239 decls = add_field_decl (objc_method_proto_list_ptr, "method_next", &chain);
241 /* int method_count; */
242 add_field_decl (integer_type_node, "method_count", &chain);
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);
248 objc_finish_struct (objc_ivar_list_record, decls);
250 return objc_ivar_list_record;
253 /* struct objc_method_prototype_list {
254 int count;
255 struct objc_method_prototype {
256 SEL name;
257 char *types;
258 } list[1];
259 }; */
261 tree
262 build_method_prototype_list_template (tree list_type, int size)
264 tree objc_ivar_list_record;
265 tree array_type, decls, *chain = NULL;
267 /* Generate an unnamed struct definition. */
269 objc_ivar_list_record = objc_start_struct (NULL_TREE);
271 /* int method_count; */
272 decls = add_field_decl (integer_type_node, "method_count", &chain);
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);
278 objc_finish_struct (objc_ivar_list_record, decls);
280 return objc_ivar_list_record;
283 /* --- names, decls entry --- */
285 /* For each string section we have a chain which maps identifier nodes
286 to decls for the strings. */
288 static GTY(()) int meth_var_names_idx;
289 static GTY(()) int meth_var_types_idx;
290 static GTY(()) int property_name_attr_idx;
292 tree
293 add_objc_string (tree ident, string_section section)
295 tree *chain, decl, type;
296 char buf[BUFSIZE];
298 switch (section)
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 ();
320 while (*chain)
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));
327 chain = &TREE_CHAIN (*chain);
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);
337 return convert (string_type_node,
338 build_unary_op (input_location, ADDR_EXPR, decl, 1));
341 /* --- shared metadata routines --- */
343 tree
344 build_descriptor_table_initializer (tree type, tree entries)
346 vec<constructor_elt, va_gc> *inits = NULL;
350 vec<constructor_elt, va_gc> *elts = NULL;
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));
358 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
359 objc_build_constructor (type, elts));
361 entries = DECL_CHAIN (entries);
363 while (entries);
365 return objc_build_constructor (build_array_type (type, 0), inits);
368 tree
369 build_dispatch_table_initializer (tree type, tree entries)
371 vec<constructor_elt, va_gc> *inits = NULL;
375 vec<constructor_elt, va_gc> *elems = NULL;
376 tree expr;
378 CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
379 build_selector (METHOD_SEL_NAME (entries)));
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);
386 CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
387 add_objc_string (METHOD_ENCODING (entries),
388 meth_var_types));
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);
395 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
396 objc_build_constructor (type, elems));
398 entries = DECL_CHAIN (entries);
400 while (entries);
402 return objc_build_constructor (build_array_type (type, 0), inits);
405 /* Used only by build_*_selector_translation_table (). */
406 void
407 diagnose_missing_method (tree meth, location_t here)
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))
415 if (TREE_VALUE (method_chain) == meth)
417 found = true;
418 break;
422 if (!found)
423 warning_at (here, 0, "creating selector for nonexistent method %qE",
424 meth);
428 static tree
429 init_module_descriptor (tree type, long vers)
431 tree expr, ltyp;
432 location_t loc;
433 vec<constructor_elt, va_gc> *v = NULL;
435 /* No really useful place to point to. */
436 loc = UNKNOWN_LOCATION;
438 /* version = { 1, ... } */
440 expr = build_int_cst (long_integer_type_node, vers);
441 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
443 /* size = { ..., sizeof (struct _objc_module), ... } */
445 expr = convert (long_integer_type_node,
446 size_in_bytes (objc_module_template));
447 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
449 /* Don't provide any file name for security reasons. */
450 /* name = { ..., "", ... } */
452 expr = add_objc_string (get_identifier (""), class_names);
453 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
455 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
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);
466 return objc_build_constructor (type, v);
469 /* Write out the data structures to describe Objective C classes defined.
471 struct _objc_module { ... } _OBJC_MODULE = { ... }; */
473 void
474 build_module_descriptor (long vers, tree attr)
476 tree decls, *chain = NULL;
478 #ifdef OBJCPLUS
479 push_lang_context (lang_name_c); /* extern "C" */
480 #endif
482 objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE));
484 /* long version; */
485 decls = add_field_decl (long_integer_type_node, "version", &chain);
487 /* long size; */
488 add_field_decl (long_integer_type_node, "size", &chain);
490 /* char *name; */
491 add_field_decl (string_type_node, "name", &chain);
493 /* struct _objc_symtab *symtab; */
494 add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE,
495 get_identifier (UTAG_SYMTAB))),
496 "symtab", &chain);
498 objc_finish_struct (objc_module_template, decls);
500 /* Create an instance of "_objc_module". */
501 UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_Module");
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;
507 /* Squash `defined but not used' warning. */
508 TREE_USED (UOBJC_MODULES_decl) = 1;
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;
515 finish_var_decl (UOBJC_MODULES_decl,
516 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl),
517 vers));
519 #ifdef OBJCPLUS
520 pop_lang_context ();
521 #endif
524 tree
525 build_ivar_list_initializer (tree type, tree field_decl)
527 vec<constructor_elt, va_gc> *inits = NULL;
529 for (; field_decl; field_decl = DECL_CHAIN (field_decl))
530 if (TREE_CODE (field_decl) == FIELD_DECL)
532 vec<constructor_elt, va_gc> *ivar = NULL;
533 tree id;
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));
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);
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));
556 return objc_build_constructor (build_array_type (type, 0), inits);
559 /* struct {
560 int ivar_count;
561 struct objc_ivar ivar_list[ivar_count];
562 }; */
564 tree
565 build_ivar_list_template (tree list_type, int size)
567 tree objc_ivar_list_record;
568 tree array_type, decls, *chain = NULL;
570 objc_ivar_list_record = objc_start_struct (NULL_TREE);
572 /* int ivar_count; */
573 decls = add_field_decl (integer_type_node, "ivar_count", &chain);
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);
579 objc_finish_struct (objc_ivar_list_record, decls);
581 return objc_ivar_list_record;
584 /* struct _objc_ivar {
585 char *ivar_name;
586 char *ivar_type;
587 int ivar_offset;
588 }; */
590 tree
591 build_ivar_template (void)
593 tree objc_ivar_id, objc_ivar_record;
594 tree decls, *chain = NULL;
596 objc_ivar_id = get_identifier (UTAG_IVAR);
597 objc_ivar_record = objc_start_struct (objc_ivar_id);
599 /* char *ivar_name; */
600 decls = add_field_decl (string_type_node, "ivar_name", &chain);
602 /* char *ivar_type; */
603 add_field_decl (string_type_node, "ivar_type", &chain);
605 /* int ivar_offset; */
606 add_field_decl (integer_type_node, "ivar_offset", &chain);
608 objc_finish_struct (objc_ivar_record, decls);
610 return objc_ivar_record;
613 /* Used by NeXT ABI=0..2 */
614 void
615 build_next_selector_translation_table (void)
617 tree chain;
618 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
620 tree expr;
621 tree decl = TREE_PURPOSE (chain);
622 if (warn_selector)
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);
632 expr = build_selector (TREE_VALUE (chain));
634 if (decl)
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);
645 void
646 generate_protocol_references (tree plist)
648 tree lproto;
650 /* Forward declare protocols referenced. */
651 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
653 tree proto = TREE_VALUE (lproto);
655 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
656 && PROTOCOL_NAME (proto))
658 if (! PROTOCOL_FORWARD_DECL (proto))
659 PROTOCOL_FORWARD_DECL (proto) = (*runtime.protocol_decl) (proto);
661 if (PROTOCOL_LIST (proto))
662 generate_protocol_references (PROTOCOL_LIST (proto));
667 /* --- new routines --- */
669 /* Output all strings. */
671 /* FIXME: don't use global vars for all this... */
673 /* This emits all the meta-data string tables (and finalizes each var
674 as it goes). */
675 void
676 generate_strings (void)
678 tree chain, string_expr;
679 tree string, decl; /* , type;*/
681 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
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);
690 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
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);
699 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
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);
708 for (chain = prop_names_attr_chain; chain; chain = TREE_CHAIN (chain))
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);
718 #include "gt-objc-objc-runtime-shared-support.h"