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