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