1/* Implement classes and message passing for Objective C. 2 Copyright (C) 1992, 93-95, 97, 1998 Free Software Foundation, Inc. 3 Contributed by Steve Naroff. 4 5This file is part of GNU CC. 6 7GNU CC 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 2, or (at your option) 10any later version. 11 12GNU CC 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 GNU CC; see the file COPYING. If not, write to 19the Free Software Foundation, 59 Temple Place - Suite 330, 20Boston, MA 02111-1307, USA. */ 21 22/* Purpose: This module implements the Objective-C 4.0 language. 23 24 compatibility issues (with the Stepstone translator): 25 26 - does not recognize the following 3.3 constructs. 27 @requires, @classes, @messages, = (...) 28 - methods with variable arguments must conform to ANSI standard. 29 - tagged structure definitions that appear in BOTH the interface 30 and implementation are not allowed. 31 - public/private: all instance variables are public within the 32 context of the implementation...I consider this to be a bug in 33 the translator. 34 - statically allocated objects are not supported. the user will 35 receive an error if this service is requested. 36 37 code generation `options': 38 39 - OBJC_INT_SELECTORS */ 40 41#include "config.h" 42#include "system.h" 43#include "tree.h" 44#include "c-tree.h" 45#include "c-lex.h" 46#include "flags.h" 47#include "objc-act.h" 48#include "input.h" 49#include "except.h" 50#include "function.h" 51#include "output.h" 52#include "toplev.h" 53 54#if USE_CPPLIB 55#include "cpplib.h" 56extern cpp_reader parse_in; 57extern cpp_options parse_options; 58#endif 59 60/* This is the default way of generating a method name. */ 61/* I am not sure it is really correct. 62 Perhaps there's a danger that it will make name conflicts 63 if method names contain underscores. -- rms. */ 64#ifndef OBJC_GEN_METHOD_LABEL 65#define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \ 66 do { \ 67 char *temp; \ 68 sprintf ((BUF), "_%s_%s_%s_%s", \ 69 ((IS_INST) ? "i" : "c"), \ 70 (CLASS_NAME), \ 71 ((CAT_NAME)? (CAT_NAME) : ""), \ 72 (SEL_NAME)); \ 73 for (temp = (BUF); *temp; temp++) \ 74 if (*temp == ':') *temp = '_'; \ 75 } while (0) 76#endif 77 78/* These need specifying. */ 79#ifndef OBJC_FORWARDING_STACK_OFFSET 80#define OBJC_FORWARDING_STACK_OFFSET 0 81#endif 82 83#ifndef OBJC_FORWARDING_MIN_OFFSET 84#define OBJC_FORWARDING_MIN_OFFSET 0 85#endif 86 87/* Define the special tree codes that we use. */ 88 89/* Table indexed by tree code giving a string containing a character 90 classifying the tree code. Possibilities are 91 t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */ 92 93#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, 94 95char objc_tree_code_type[] = { 96 'x', 97#include "objc-tree.def" 98}; 99#undef DEFTREECODE 100 101/* Table indexed by tree code giving number of expression 102 operands beyond the fixed part of the node structure. 103 Not used for types or decls. */ 104 105#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, 106 107int objc_tree_code_length[] = { 108 0, 109#include "objc-tree.def" 110}; 111#undef DEFTREECODE 112 113/* Names of tree components. 114 Used for printing out the tree and error messages. */ 115#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, 116 117char *objc_tree_code_name[] = { 118 "@@dummy", 119#include "objc-tree.def" 120}; 121#undef DEFTREECODE 122 123/* Set up for use of obstacks. */ 124 125#include "obstack.h" 126 127#define obstack_chunk_alloc xmalloc 128#define obstack_chunk_free free 129 130/* This obstack is used to accumulate the encoding of a data type. */ 131static struct obstack util_obstack; 132/* This points to the beginning of obstack contents, 133 so we can free the whole contents. */ 134char *util_firstobj; 135 136/* List of classes with list of their static instances. */ 137static tree objc_static_instances = NULL_TREE; 138 139/* The declaration of the array administrating the static instances. */ 140static tree static_instances_decl = NULL_TREE; 141 142/* for encode_method_def */ 143#include "rtl.h" 144#include "c-parse.h" 145 146#define OBJC_VERSION (flag_next_runtime ? 5 : 8) 147#define PROTOCOL_VERSION 2 148 149#define OBJC_ENCODE_INLINE_DEFS 0 150#define OBJC_ENCODE_DONT_INLINE_DEFS 1 151 152/*** Private Interface (procedures) ***/ 153 154/* Used by compile_file. */ 155 156static void init_objc PROTO((void)); 157static void finish_objc PROTO((void)); 158 159/* Code generation. */ 160 161static void synth_module_prologue PROTO((void)); 162static tree build_constructor PROTO((tree, tree)); 163static char *build_module_descriptor PROTO((void)); 164static tree init_module_descriptor PROTO((tree)); 165static tree build_objc_method_call PROTO((int, tree, tree, 166 tree, tree, tree)); 167static void generate_strings PROTO((void)); 168static tree get_proto_encoding PROTO((tree)); 169static void build_selector_translation_table PROTO((void)); 170static tree build_ivar_chain PROTO((tree, int)); 171 172static tree objc_add_static_instance PROTO((tree, tree)); 173 174static tree build_ivar_template PROTO((void)); 175static tree build_method_template PROTO((void)); 176static tree build_private_template PROTO((tree)); 177static void build_class_template PROTO((void)); 178static void build_selector_template PROTO((void)); 179static void build_category_template PROTO((void)); 180static tree build_super_template PROTO((void)); 181static tree build_category_initializer PROTO((tree, tree, tree, 182 tree, tree, tree)); 183static tree build_protocol_initializer PROTO((tree, tree, tree, 184 tree, tree)); 185 186static void synth_forward_declarations PROTO((void)); 187static void generate_ivar_lists PROTO((void)); 188static void generate_dispatch_tables PROTO((void)); 189static void generate_shared_structures PROTO((void)); 190static tree generate_protocol_list PROTO((tree)); 191static void generate_forward_declaration_to_string_table PROTO((void)); 192static void build_protocol_reference PROTO((tree)); 193 194#if 0 195static tree init_selector PROTO((int)); 196#endif 197static tree build_keyword_selector PROTO((tree)); 198static tree synth_id_with_class_suffix PROTO((char *, tree)); 199 200static void generate_static_references PROTO((void)); 201static int check_methods_accessible PROTO((tree, tree, 202 int)); 203static void encode_aggregate_within PROTO((tree, int, int, 204 int, int)); 205 206/* We handle printing method names ourselves for ObjC */ 207extern char *(*decl_printable_name) (); 208 209/* Misc. bookkeeping */ 210 211typedef struct hashed_entry *hash; 212typedef struct hashed_attribute *attr; 213 214struct hashed_attribute 215{ 216 attr next; 217 tree value; 218}; 219struct hashed_entry 220{ 221 attr list; 222 hash next; 223 tree key; 224}; 225 226static void hash_init PROTO((void)); 227static void hash_enter PROTO((hash *, tree)); 228static hash hash_lookup PROTO((hash *, tree)); 229static void hash_add_attr PROTO((hash, tree)); 230static tree lookup_method PROTO((tree, tree)); 231static tree lookup_instance_method_static PROTO((tree, tree)); 232static tree lookup_class_method_static PROTO((tree, tree)); 233static tree add_class PROTO((tree)); 234static void add_category PROTO((tree, tree)); 235 236enum string_section 237{ 238 class_names, /* class, category, protocol, module names */ 239 meth_var_names, /* method and variable names */ 240 meth_var_types /* method and variable type descriptors */ 241}; 242 243static tree add_objc_string PROTO((tree, 244 enum string_section)); 245static tree get_objc_string_decl PROTO((tree, 246 enum string_section)); 247static tree build_objc_string_decl PROTO((tree, 248 enum string_section)); 249static tree build_selector_reference_decl PROTO((tree)); 250 251/* Protocol additions. */ 252 253static tree add_protocol PROTO((tree)); 254static tree lookup_protocol PROTO((tree)); 255static tree lookup_and_install_protocols PROTO((tree)); 256 257/* Type encoding. */ 258 259static void encode_type_qualifiers PROTO((tree)); 260static void encode_pointer PROTO((tree, int, int)); 261static void encode_array PROTO((tree, int, int)); 262static void encode_aggregate PROTO((tree, int, int)); 263static void encode_bitfield PROTO((int, int)); 264static void encode_type PROTO((tree, int, int)); 265static void encode_field_decl PROTO((tree, int, int)); 266 267static void really_start_method PROTO((tree, tree)); 268static int comp_method_with_proto PROTO((tree, tree)); 269static int comp_proto_with_proto PROTO((tree, tree)); 270static tree get_arg_type_list PROTO((tree, int, int)); 271static tree expr_last PROTO((tree)); 272 273/* Utilities for debugging and error diagnostics. */ 274 275static void warn_with_method PROTO((char *, int, tree)); 276static void error_with_ivar PROTO((char *, tree, tree)); 277static char *gen_method_decl PROTO((tree, char *)); 278static char *gen_declaration PROTO((tree, char *)); 279static char *gen_declarator PROTO((tree, char *, char *)); 280static int is_complex_decl PROTO((tree)); 281static void adorn_decl PROTO((tree, char *)); 282static void dump_interface PROTO((FILE *, tree)); 283 284/* Everything else. */ 285 286static void objc_fatal PROTO((void)) 287 ATTRIBUTE_NORETURN; 288static tree define_decl PROTO((tree, tree)); 289static tree lookup_method_in_protocol_list PROTO((tree, tree, int)); 290static tree lookup_protocol_in_reflist PROTO((tree, tree)); 291static tree create_builtin_decl PROTO((enum tree_code, 292 tree, char *)); 293static tree my_build_string PROTO((int, char *)); 294static void build_objc_symtab_template PROTO((void)); 295static tree init_def_list PROTO((tree)); 296static tree init_objc_symtab PROTO((tree)); 297static void forward_declare_categories PROTO((void)); 298static void generate_objc_symtab_decl PROTO((void)); 299static tree build_selector PROTO((tree)); 300#if 0 301static tree build_msg_pool_reference PROTO((int)); 302#endif 303static tree build_typed_selector_reference PROTO((tree, tree)); 304static tree build_selector_reference PROTO((tree)); 305static tree build_class_reference_decl PROTO((tree)); 306static void add_class_reference PROTO((tree)); 307static tree objc_copy_list PROTO((tree, tree *)); 308static tree build_protocol_template PROTO((void)); 309static tree build_descriptor_table_initializer PROTO((tree, tree)); 310static tree build_method_prototype_list_template PROTO((tree, int)); 311static tree build_method_prototype_template PROTO((void)); 312static int forwarding_offset PROTO((tree)); 313static tree encode_method_prototype PROTO((tree, tree)); 314static tree generate_descriptor_table PROTO((tree, char *, int, tree, tree)); 315static void generate_method_descriptors PROTO((tree)); 316static tree build_tmp_function_decl PROTO((void)); 317static void hack_method_prototype PROTO((tree, tree)); 318static void generate_protocol_references PROTO((tree)); 319static void generate_protocols PROTO((void)); 320static void check_ivars PROTO((tree, tree)); 321static tree build_ivar_list_template PROTO((tree, int)); 322static tree build_method_list_template PROTO((tree, int)); 323static tree build_ivar_list_initializer PROTO((tree, tree)); 324static tree generate_ivars_list PROTO((tree, char *, 325 int, tree)); 326static tree build_dispatch_table_initializer PROTO((tree, tree)); 327static tree generate_dispatch_table PROTO((tree, char *, 328 int, tree)); 329static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree, 330 tree, int, tree, tree, 331 tree)); 332static void generate_category PROTO((tree)); 333static int is_objc_type_qualifier PROTO((tree)); 334static tree adjust_type_for_id_default PROTO((tree)); 335static tree check_duplicates PROTO((hash)); 336static tree receiver_is_class_object PROTO((tree)); 337static int check_methods PROTO((tree, tree, int)); 338static int conforms_to_protocol PROTO((tree, tree)); 339static void check_protocols PROTO((tree, char *, char *)); 340static tree encode_method_def PROTO((tree)); 341static void gen_declspecs PROTO((tree, char *, int)); 342static void generate_classref_translation_entry PROTO((tree)); 343static void handle_class_ref PROTO((tree)); 344 345/*** Private Interface (data) ***/ 346 347/* Reserved tag definitions. */ 348 349#define TYPE_ID "id" 350#define TAG_OBJECT "objc_object" 351#define TAG_CLASS "objc_class" 352#define TAG_SUPER "objc_super" 353#define TAG_SELECTOR "objc_selector" 354 355#define UTAG_CLASS "_objc_class" 356#define UTAG_IVAR "_objc_ivar" 357#define UTAG_IVAR_LIST "_objc_ivar_list" 358#define UTAG_METHOD "_objc_method" 359#define UTAG_METHOD_LIST "_objc_method_list" 360#define UTAG_CATEGORY "_objc_category" 361#define UTAG_MODULE "_objc_module" 362#define UTAG_STATICS "_objc_statics" 363#define UTAG_SYMTAB "_objc_symtab" 364#define UTAG_SUPER "_objc_super" 365#define UTAG_SELECTOR "_objc_selector" 366 367#define UTAG_PROTOCOL "_objc_protocol" 368#define UTAG_PROTOCOL_LIST "_objc_protocol_list" 369#define UTAG_METHOD_PROTOTYPE "_objc_method_prototype" 370#define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list" 371 372#define STRING_OBJECT_CLASS_NAME "NXConstantString" 373#define PROTOCOL_OBJECT_CLASS_NAME "Protocol" 374 375static char *TAG_GETCLASS; 376static char *TAG_GETMETACLASS; 377static char *TAG_MSGSEND; 378static char *TAG_MSGSENDSUPER; 379static char *TAG_EXECCLASS; 380 381/* Set by `continue_class' and checked by `is_public'. */ 382 383#define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type)) 384#define TYPED_OBJECT(type) \ 385 (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type)) 386 387/* Some commonly used instances of "identifier_node". */ 388 389static tree self_id, ucmd_id; 390static tree unused_list; 391 392static tree self_decl, umsg_decl, umsg_super_decl; 393static tree objc_get_class_decl, objc_get_meta_class_decl; 394 395static tree super_type, selector_type, id_type, objc_class_type; 396static tree instance_type, protocol_type; 397 398/* Type checking macros. */ 399 400#define IS_ID(TYPE) \ 401 (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type)) 402#define IS_PROTOCOL_QUALIFIED_ID(TYPE) \ 403 (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE)) 404#define IS_SUPER(TYPE) \ 405 (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type)) 406 407static tree class_chain = NULL_TREE; 408static tree alias_chain = NULL_TREE; 409static tree interface_chain = NULL_TREE; 410static tree protocol_chain = NULL_TREE; 411 412/* Chains to manage selectors that are referenced and defined in the 413 module. */ 414 415static tree cls_ref_chain = NULL_TREE; /* Classes referenced. */ 416static tree sel_ref_chain = NULL_TREE; /* Selectors referenced. */ 417 418/* Chains to manage uniquing of strings. */ 419 420static tree class_names_chain = NULL_TREE; 421static tree meth_var_names_chain = NULL_TREE; 422static tree meth_var_types_chain = NULL_TREE; 423 424/* Hash tables to manage the global pool of method prototypes. */ 425 426static hash *nst_method_hash_list = 0; 427static hash *cls_method_hash_list = 0; 428 429/* Backend data declarations. */ 430 431static tree UOBJC_SYMBOLS_decl; 432static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl; 433static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl; 434static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl; 435static tree UOBJC_SELECTOR_TABLE_decl; 436static tree UOBJC_MODULES_decl; 437static tree UOBJC_STRINGS_decl; 438 439/* The following are used when compiling a class implementation. 440 implementation_template will normally be an interface, however if 441 none exists this will be equal to implementation_context...it is 442 set in start_class. */ 443 444static tree implementation_context = NULL_TREE; 445static tree implementation_template = NULL_TREE; 446 447struct imp_entry 448{ 449 struct imp_entry *next; 450 tree imp_context; 451 tree imp_template; 452 tree class_decl; /* _OBJC_CLASS_<my_name>; */ 453 tree meta_decl; /* _OBJC_METACLASS_<my_name>; */ 454}; 455 456static void handle_impent PROTO((struct imp_entry *)); 457 458static struct imp_entry *imp_list = 0; 459static int imp_count = 0; /* `@implementation' */ 460static int cat_count = 0; /* `@category' */ 461 462static tree objc_class_template, objc_category_template, uprivate_record; 463static tree objc_protocol_template, objc_selector_template; 464static tree ucls_super_ref, uucls_super_ref; 465 466static tree objc_method_template, objc_ivar_template; 467static tree objc_symtab_template, objc_module_template; 468static tree objc_super_template, objc_object_reference; 469 470static tree objc_object_id, objc_class_id, objc_id_id; 471static tree constant_string_id; 472static tree constant_string_type; 473static tree UOBJC_SUPER_decl; 474 475static tree method_context = NULL_TREE; 476static int method_slot = 0; /* Used by start_method_def, */ 477 478#define BUFSIZE 1024 479 480static char *errbuf; /* Buffer for error diagnostics */ 481 482/* Data imported from tree.c. */ 483 484extern enum debug_info_type write_symbols; 485 486/* Data imported from toplev.c. */ 487 488extern char *dump_base_name; 489 490/* Generate code for GNU or NeXT runtime environment. */ 491 492#ifdef NEXT_OBJC_RUNTIME 493int flag_next_runtime = 1; 494#else 495int flag_next_runtime = 0; 496#endif 497 498int flag_typed_selectors; 499 500/* Open and close the file for outputting class declarations, if requested. */ 501 502int flag_gen_declaration = 0; 503 504FILE *gen_declaration_file; 505 506/* Warn if multiple methods are seen for the same selector, but with 507 different argument types. */ 508 509int warn_selector = 0; 510 511/* Warn if methods required by a protocol are not implemented in the 512 class adopting it. When turned off, methods inherited to that 513 class are also considered implemented */ 514 515int flag_warn_protocol = 1; 516 517/* Tells "encode_pointer/encode_aggregate" whether we are generating 518 type descriptors for instance variables (as opposed to methods). 519 Type descriptors for instance variables contain more information 520 than methods (for static typing and embedded structures). This 521 was added to support features being planned for dbkit2. */ 522 523static int generating_instance_variables = 0; 524 525/* Tells the compiler that this is a special run. Do not perform 526 any compiling, instead we are to test some platform dependent 527 features and output a C header file with appropriate definitions. */ 528 529static int print_struct_values = 0; 530 531/* Some platforms pass small structures through registers versus through 532 an invisible pointer. Determine at what size structure is the 533 transition point between the two possibilities. */ 534 535void 536generate_struct_by_value_array () 537{ 538 tree type; 539 tree field_decl, field_decl_chain; 540 int i, j; 541 int aggregate_in_mem[32]; 542 int found = 0; 543 544 /* Presumbaly no platform passes 32 byte structures in a register. */ 545 for (i = 1; i < 32; i++) 546 { 547 char buffer[5]; 548 549 /* Create an unnamed struct that has `i' character components */ 550 type = start_struct (RECORD_TYPE, NULL_TREE); 551 552 strcpy (buffer, "c1"); 553 field_decl = create_builtin_decl (FIELD_DECL, 554 char_type_node, 555 buffer); 556 field_decl_chain = field_decl; 557 558 for (j = 1; j < i; j++) 559 { 560 sprintf (buffer, "c%d", j + 1); 561 field_decl = create_builtin_decl (FIELD_DECL, 562 char_type_node, 563 buffer); 564 chainon (field_decl_chain, field_decl); 565 } 566 finish_struct (type, field_decl_chain, NULL_TREE); 567 568 aggregate_in_mem[i] = aggregate_value_p (type); 569 if (!aggregate_in_mem[i]) 570 found = 1; 571 } 572 573 /* We found some structures that are returned in registers instead of memory 574 so output the necessary data. */ 575 if (found) 576 { 577 for (i = 31; i >= 0; i--) 578 if (!aggregate_in_mem[i]) 579 break; 580 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i); 581 582 /* The first member of the structure is always 0 because we don't handle 583 structures with 0 members */ 584 printf ("static int struct_forward_array[] = {\n 0"); 585 586 for (j = 1; j <= i; j++) 587 printf (", %d", aggregate_in_mem[j]); 588 printf ("\n};\n"); 589 } 590 591 exit (0); 592} 593 594#if USE_CPPLIB 595extern char *yy_cur; 596#endif 597 598void 599lang_init_options () 600{ 601#if USE_CPPLIB 602 cpp_reader_init (&parse_in); 603 parse_in.opts = &parse_options; 604 cpp_options_init (&parse_options); 605#endif 606} 607 608void 609lang_init () 610{ 611#if !USE_CPPLIB 612 /* The beginning of the file is a new line; check for #. 613 With luck, we discover the real source file's name from that 614 and put it in input_filename. */ 615 ungetc (check_newline (), finput); 616#else 617 check_newline (); 618 yy_cur--; 619#endif 620 621 /* The line number can be -1 if we had -g3 and the input file 622 had a directive specifying line 0. But we want predefined 623 functions to have a line number of 0, not -1. */ 624 if (lineno == -1) 625 lineno = 0; 626 627 /* If gen_declaration desired, open the output file. */ 628 if (flag_gen_declaration) 629 { 630 int dump_base_name_length = strlen (dump_base_name); 631 register char *dumpname = (char *) xmalloc (dump_base_name_length + 7); 632 strcpy (dumpname, dump_base_name); 633 strcat (dumpname, ".decl"); 634 gen_declaration_file = fopen (dumpname, "w"); 635 if (gen_declaration_file == 0) 636 pfatal_with_name (dumpname); 637 } 638 639 if (flag_next_runtime) 640 { 641 TAG_GETCLASS = "objc_getClass"; 642 TAG_GETMETACLASS = "objc_getMetaClass"; 643 TAG_MSGSEND = "objc_msgSend"; 644 TAG_MSGSENDSUPER = "objc_msgSendSuper"; 645 TAG_EXECCLASS = "__objc_execClass"; 646 } 647 else 648 { 649 TAG_GETCLASS = "objc_get_class"; 650 TAG_GETMETACLASS = "objc_get_meta_class"; 651 TAG_MSGSEND = "objc_msg_lookup"; 652 TAG_MSGSENDSUPER = "objc_msg_lookup_super"; 653 TAG_EXECCLASS = "__objc_exec_class"; 654 flag_typed_selectors = 1; 655 } 656 657 if (doing_objc_thang) 658 init_objc (); 659 660 if (print_struct_values) 661 generate_struct_by_value_array (); 662} 663 664static void 665objc_fatal () 666{ 667 fatal ("Objective-C text in C source file"); 668} 669 670void 671finish_file () 672{ 673 if (doing_objc_thang) 674 finish_objc (); /* Objective-C finalization */ 675 676 if (gen_declaration_file) 677 fclose (gen_declaration_file); 678} 679 680void 681lang_finish () 682{ 683} 684 685char * 686lang_identify () 687{ 688 return "objc"; 689} 690 691int 692lang_decode_option (argc, argv) 693 int argc; 694 char **argv; 695{ 696 char *p = argv[0]; 697 if (!strcmp (p, "-lang-objc")) 698 doing_objc_thang = 1; 699 else if (!strcmp (p, "-gen-decls")) 700 flag_gen_declaration = 1; 701 else if (!strcmp (p, "-Wselector")) 702 warn_selector = 1; 703 else if (!strcmp (p, "-Wno-selector")) 704 warn_selector = 0; 705 else if (!strcmp (p, "-Wprotocol")) 706 flag_warn_protocol = 1; 707 else if (!strcmp (p, "-Wno-protocol")) 708 flag_warn_protocol = 0; 709 else if (!strcmp (p, "-fgnu-runtime")) 710 flag_next_runtime = 0; 711 else if (!strcmp (p, "-fno-next-runtime")) 712 flag_next_runtime = 0; 713 else if (!strcmp (p, "-fno-gnu-runtime")) 714 flag_next_runtime = 1; 715 else if (!strcmp (p, "-fnext-runtime")) 716 flag_next_runtime = 1; 717 else if (!strcmp (p, "-print-objc-runtime-info")) 718 print_struct_values = 1; 719 else 720 return c_decode_option (argc, argv); 721 722 return 1; 723} 724 725/* used by print-tree.c */ 726 727void 728lang_print_xnode (file, node, indent) 729 FILE *file ATTRIBUTE_UNUSED; 730 tree node ATTRIBUTE_UNUSED; 731 int indent ATTRIBUTE_UNUSED; 732{ 733} 734 735 736static tree 737define_decl (declarator, declspecs) 738 tree declarator; 739 tree declspecs; 740{ 741 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE); 742 finish_decl (decl, NULL_TREE, NULL_TREE); 743 return decl; 744} 745 746/* Return 1 if LHS and RHS are compatible types for assignment or 747 various other operations. Return 0 if they are incompatible, and 748 return -1 if we choose to not decide. When the operation is 749 REFLEXIVE, check for compatibility in either direction. 750 751 For statically typed objects, an assignment of the form `a' = `b' 752 is permitted if: 753 754 `a' is of type "id", 755 `a' and `b' are the same class type, or 756 `a' and `b' are of class types A and B such that B is a descendant of A. */ 757 758int 759maybe_objc_comptypes (lhs, rhs, reflexive) 760 tree lhs, rhs; 761 int reflexive; 762{ 763 if (doing_objc_thang) 764 return objc_comptypes (lhs, rhs, reflexive); 765 return -1; 766} 767 768static tree 769lookup_method_in_protocol_list (rproto_list, sel_name, class_meth) 770 tree rproto_list; 771 tree sel_name; 772 int class_meth; 773{ 774 tree rproto, p; 775 tree fnd = 0; 776 777 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) 778 { 779 p = TREE_VALUE (rproto); 780 781 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) 782 { 783 if ((fnd = lookup_method (class_meth 784 ? PROTOCOL_CLS_METHODS (p) 785 : PROTOCOL_NST_METHODS (p), sel_name))) 786 ; 787 else if (PROTOCOL_LIST (p)) 788 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p), 789 sel_name, class_meth); 790 } 791 else 792 { 793 ; /* An identifier...if we could not find a protocol. */ 794 } 795 796 if (fnd) 797 return fnd; 798 } 799 800 return 0; 801} 802 803static tree 804lookup_protocol_in_reflist (rproto_list, lproto) 805 tree rproto_list; 806 tree lproto; 807{ 808 tree rproto, p; 809 810 /* Make sure the protocol is support by the object on the rhs. */ 811 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE) 812 { 813 tree fnd = 0; 814 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) 815 { 816 p = TREE_VALUE (rproto); 817 818 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) 819 { 820 if (lproto == p) 821 fnd = lproto; 822 823 else if (PROTOCOL_LIST (p)) 824 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto); 825 } 826 827 if (fnd) 828 return fnd; 829 } 830 } 831 else 832 { 833 ; /* An identifier...if we could not find a protocol. */ 834 } 835 836 return 0; 837} 838 839/* Return 1 if LHS and RHS are compatible types for assignment 840 or various other operations. Return 0 if they are incompatible, 841 and return -1 if we choose to not decide. When the operation 842 is REFLEXIVE, check for compatibility in either direction. */ 843 844int 845objc_comptypes (lhs, rhs, reflexive) 846 tree lhs; 847 tree rhs; 848 int reflexive; 849{ 850 /* New clause for protocols. */ 851 852 if (TREE_CODE (lhs) == POINTER_TYPE 853 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE 854 && TREE_CODE (rhs) == POINTER_TYPE 855 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE) 856 { 857 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs); 858 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs); 859 860 if (lhs_is_proto) 861 { 862 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs); 863 tree rproto, rproto_list; 864 tree p; 865 866 if (rhs_is_proto) 867 { 868 rproto_list = TYPE_PROTOCOL_LIST (rhs); 869 870 /* Make sure the protocol is supported by the object 871 on the rhs. */ 872 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto)) 873 { 874 p = TREE_VALUE (lproto); 875 rproto = lookup_protocol_in_reflist (rproto_list, p); 876 877 if (!rproto) 878 warning ("object does not conform to the `%s' protocol", 879 IDENTIFIER_POINTER (PROTOCOL_NAME (p))); 880 } 881 } 882 else if (TYPED_OBJECT (TREE_TYPE (rhs))) 883 { 884 tree rname = TYPE_NAME (TREE_TYPE (rhs)); 885 tree rinter; 886 887 /* Make sure the protocol is supported by the object 888 on the rhs. */ 889 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto)) 890 { 891 p = TREE_VALUE (lproto); 892 rproto = 0; 893 rinter = lookup_interface (rname); 894 895 while (rinter && !rproto) 896 { 897 tree cat; 898 899 rproto_list = CLASS_PROTOCOL_LIST (rinter); 900 rproto = lookup_protocol_in_reflist (rproto_list, p); 901 902 /* Check for protocols adopted by categories. */ 903 cat = CLASS_CATEGORY_LIST (rinter); 904 while (cat && !rproto) 905 { 906 rproto_list = CLASS_PROTOCOL_LIST (cat); 907 rproto = lookup_protocol_in_reflist (rproto_list, p); 908 909 cat = CLASS_CATEGORY_LIST (cat); 910 } 911 912 rinter = lookup_interface (CLASS_SUPER_NAME (rinter)); 913 } 914 915 if (!rproto) 916 warning ("class `%s' does not implement the `%s' protocol", 917 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))), 918 IDENTIFIER_POINTER (PROTOCOL_NAME (p))); 919 } 920 } 921 922 /* May change...based on whether there was any mismatch */ 923 return 1; 924 } 925 else if (rhs_is_proto) 926 /* Lhs is not a protocol...warn if it is statically typed */ 927 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0); 928 929 else 930 /* Defer to comptypes .*/ 931 return -1; 932 } 933 934 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE) 935 ; /* Fall thru. This is the case we have been handling all along */ 936 else 937 /* Defer to comptypes. */ 938 return -1; 939 940 /* `id' = `<class> *', `<class> *' = `id' */ 941 942 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs)) 943 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs))) 944 return 1; 945 946 /* `id' = `Class', `Class' = `id' */ 947 948 else if ((TYPE_NAME (lhs) == objc_object_id 949 && TYPE_NAME (rhs) == objc_class_id) 950 || (TYPE_NAME (lhs) == objc_class_id 951 && TYPE_NAME (rhs) == objc_object_id)) 952 return 1; 953 954 /* `<class> *' = `<class> *' */ 955 956 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs)) 957 { 958 tree lname = TYPE_NAME (lhs); 959 tree rname = TYPE_NAME (rhs); 960 tree inter; 961 962 if (lname == rname) 963 return 1; 964 965 /* If the left hand side is a super class of the right hand side, 966 allow it. */ 967 for (inter = lookup_interface (rname); inter; 968 inter = lookup_interface (CLASS_SUPER_NAME (inter))) 969 if (lname == CLASS_SUPER_NAME (inter)) 970 return 1; 971 972 /* Allow the reverse when reflexive. */ 973 if (reflexive) 974 for (inter = lookup_interface (lname); inter; 975 inter = lookup_interface (CLASS_SUPER_NAME (inter))) 976 if (rname == CLASS_SUPER_NAME (inter)) 977 return 1; 978 979 return 0; 980 } 981 else 982 /* Defer to comptypes. */ 983 return -1; 984} 985 986/* Called from c-decl.c before all calls to rest_of_decl_compilation. */ 987 988void 989objc_check_decl (decl) 990 tree decl; 991{ 992 tree type = TREE_TYPE (decl); 993 994 if (TREE_CODE (type) == RECORD_TYPE 995 && TREE_STATIC_TEMPLATE (type) 996 && type != constant_string_type) 997 { 998 error_with_decl (decl, "`%s' cannot be statically allocated"); 999 fatal ("statically allocated objects not supported"); 1000 } 1001} 1002 1003void 1004maybe_objc_check_decl (decl) 1005 tree decl; 1006{ 1007 if (doing_objc_thang) 1008 objc_check_decl (decl); 1009} 1010 1011/* Implement static typing. At this point, we know we have an interface. */ 1012 1013tree 1014get_static_reference (interface, protocols) 1015 tree interface; 1016 tree protocols; 1017{ 1018 tree type = xref_tag (RECORD_TYPE, interface); 1019 1020 if (protocols) 1021 { 1022 tree t, m = TYPE_MAIN_VARIANT (type); 1023 1024 push_obstacks_nochange (); 1025 end_temporary_allocation (); 1026 t = copy_node (type); 1027 TYPE_BINFO (t) = make_tree_vec (2); 1028 pop_obstacks (); 1029 1030 /* Add this type to the chain of variants of TYPE. */ 1031 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); 1032 TYPE_NEXT_VARIANT (m) = t; 1033 1034 /* Look up protocols and install in lang specific list. */ 1035 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols); 1036 1037 /* This forces a new pointer type to be created later 1038 (in build_pointer_type)...so that the new template 1039 we just created will actually be used...what a hack! */ 1040 if (TYPE_POINTER_TO (t)) 1041 TYPE_POINTER_TO (t) = 0; 1042 1043 type = t; 1044 } 1045 1046 return type; 1047} 1048 1049tree 1050get_object_reference (protocols) 1051 tree protocols; 1052{ 1053 tree type_decl = lookup_name (objc_id_id); 1054 tree type; 1055 1056 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL) 1057 { 1058 type = TREE_TYPE (type_decl); 1059 if (TYPE_MAIN_VARIANT (type) != id_type) 1060 warning ("Unexpected type for `id' (%s)", 1061 gen_declaration (type, errbuf)); 1062 } 1063 else 1064 fatal ("Undefined type `id', please import <objc/objc.h>"); 1065 1066 /* This clause creates a new pointer type that is qualified with 1067 the protocol specification...this info is used later to do more 1068 elaborate type checking. */ 1069 1070 if (protocols) 1071 { 1072 tree t, m = TYPE_MAIN_VARIANT (type); 1073 1074 push_obstacks_nochange (); 1075 end_temporary_allocation (); 1076 t = copy_node (type); 1077 TYPE_BINFO (t) = make_tree_vec (2); 1078 pop_obstacks (); 1079 1080 /* Add this type to the chain of variants of TYPE. */ 1081 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); 1082 TYPE_NEXT_VARIANT (m) = t; 1083 1084 /* Look up protocols...and install in lang specific list */ 1085 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols); 1086 1087 /* This forces a new pointer type to be created later 1088 (in build_pointer_type)...so that the new template 1089 we just created will actually be used...what a hack! */ 1090 if (TYPE_POINTER_TO (t)) 1091 TYPE_POINTER_TO (t) = NULL; 1092 1093 type = t; 1094 } 1095 return type; 1096} 1097 1098static tree 1099lookup_and_install_protocols (protocols) 1100 tree protocols; 1101{ 1102 tree proto; 1103 tree prev = NULL; 1104 tree return_value = protocols; 1105 1106 for (proto = protocols; proto; proto = TREE_CHAIN (proto)) 1107 { 1108 tree ident = TREE_VALUE (proto); 1109 tree p = lookup_protocol (ident); 1110 1111 if (!p) 1112 { 1113 error ("Cannot find protocol declaration for `%s'", 1114 IDENTIFIER_POINTER (ident)); 1115 if (prev) 1116 TREE_CHAIN (prev) = TREE_CHAIN (proto); 1117 else 1118 return_value = TREE_CHAIN (proto); 1119 } 1120 else 1121 { 1122 /* Replace identifier with actual protocol node. */ 1123 TREE_VALUE (proto) = p; 1124 prev = proto; 1125 } 1126 } 1127 1128 return return_value; 1129} 1130 1131/* Create and push a decl for a built-in external variable or field NAME. 1132 CODE says which. 1133 TYPE is its data type. */ 1134 1135static tree 1136create_builtin_decl (code, type, name) 1137 enum tree_code code; 1138 tree type; 1139 char *name; 1140{ 1141 tree decl = build_decl (code, get_identifier (name), type); 1142 1143 if (code == VAR_DECL) 1144 { 1145 TREE_STATIC (decl) = 1; 1146 make_decl_rtl (decl, 0, 1); 1147 pushdecl (decl); 1148 } 1149 1150 DECL_ARTIFICIAL (decl) = 1; 1151 return decl; 1152} 1153 1154/* Purpose: "play" parser, creating/installing representations 1155 of the declarations that are required by Objective-C. 1156 1157 Model: 1158 1159 type_spec--------->sc_spec 1160 (tree_list) (tree_list) 1161 | | 1162 | | 1163 identifier_node identifier_node */ 1164 1165static void 1166synth_module_prologue () 1167{ 1168 tree temp_type; 1169 tree super_p; 1170 1171 /* Defined in `objc.h' */ 1172 objc_object_id = get_identifier (TAG_OBJECT); 1173 1174 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id); 1175 1176 id_type = build_pointer_type (objc_object_reference); 1177 1178 objc_id_id = get_identifier (TYPE_ID); 1179 objc_class_id = get_identifier (TAG_CLASS); 1180 1181 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id)); 1182 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE, 1183 get_identifier (PROTOCOL_OBJECT_CLASS_NAME))); 1184 1185 /* Declare type of selector-objects that represent an operation name. */ 1186 1187#ifdef OBJC_INT_SELECTORS 1188 /* `unsigned int' */ 1189 selector_type = unsigned_type_node; 1190#else 1191 /* `struct objc_selector *' */ 1192 selector_type 1193 = build_pointer_type (xref_tag (RECORD_TYPE, 1194 get_identifier (TAG_SELECTOR))); 1195#endif /* not OBJC_INT_SELECTORS */ 1196 1197 /* Forward declare type, or else the prototype for msgSendSuper will 1198 complain. */ 1199 1200 super_p = build_pointer_type (xref_tag (RECORD_TYPE, 1201 get_identifier (TAG_SUPER))); 1202 1203 1204 /* id objc_msgSend (id, SEL, ...); */ 1205 1206 temp_type 1207 = build_function_type (id_type, 1208 tree_cons (NULL_TREE, id_type, 1209 tree_cons (NULL_TREE, selector_type, 1210 NULL_TREE))); 1211 1212 if (! flag_next_runtime) 1213 { 1214 umsg_decl = build_decl (FUNCTION_DECL, 1215 get_identifier (TAG_MSGSEND), temp_type); 1216 DECL_EXTERNAL (umsg_decl) = 1; 1217 TREE_PUBLIC (umsg_decl) = 1; 1218 DECL_INLINE (umsg_decl) = 1; 1219 DECL_ARTIFICIAL (umsg_decl) = 1; 1220 1221 if (flag_traditional && TAG_MSGSEND[0] != '_') 1222 DECL_BUILT_IN_NONANSI (umsg_decl) = 1; 1223 1224 make_decl_rtl (umsg_decl, NULL_PTR, 1); 1225 pushdecl (umsg_decl); 1226 } 1227 else 1228 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0); 1229 1230 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */ 1231 1232 temp_type 1233 = build_function_type (id_type, 1234 tree_cons (NULL_TREE, super_p, 1235 tree_cons (NULL_TREE, selector_type, 1236 NULL_TREE))); 1237 1238 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER, 1239 temp_type, NOT_BUILT_IN, 0); 1240 1241 /* id objc_getClass (const char *); */ 1242 1243 temp_type = build_function_type (id_type, 1244 tree_cons (NULL_TREE, 1245 const_string_type_node, 1246 tree_cons (NULL_TREE, void_type_node, 1247 NULL_TREE))); 1248 1249 objc_get_class_decl 1250 = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0); 1251 1252 /* id objc_getMetaClass (const char *); */ 1253 1254 objc_get_meta_class_decl 1255 = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0); 1256 1257 /* static SEL _OBJC_SELECTOR_TABLE[]; */ 1258 1259 if (! flag_next_runtime) 1260 { 1261 if (flag_typed_selectors) 1262 { 1263 /* Suppress outputting debug symbols, because 1264 dbxout_init hasn'r been called yet. */ 1265 enum debug_info_type save_write_symbols = write_symbols; 1266 write_symbols = NO_DEBUG; 1267 1268 build_selector_template (); 1269 temp_type = build_array_type (objc_selector_template, NULL_TREE); 1270 1271 write_symbols = save_write_symbols; 1272 } 1273 else 1274 temp_type = build_array_type (selector_type, NULL_TREE); 1275 1276 layout_type (temp_type); 1277 UOBJC_SELECTOR_TABLE_decl 1278 = create_builtin_decl (VAR_DECL, temp_type, 1279 "_OBJC_SELECTOR_TABLE"); 1280 1281 /* Avoid warning when not sending messages. */ 1282 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1; 1283 } 1284 1285 generate_forward_declaration_to_string_table (); 1286 1287 /* Forward declare constant_string_id and constant_string_type. */ 1288 constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME); 1289 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id); 1290} 1291 1292/* Custom build_string which sets TREE_TYPE! */ 1293 1294static tree 1295my_build_string (len, str) 1296 int len; 1297 char *str; 1298{ 1299 int wide_flag = 0; 1300 tree a_string = build_string (len, str); 1301 1302 /* Some code from combine_strings, which is local to c-parse.y. */ 1303 if (TREE_TYPE (a_string) == int_array_type_node) 1304 wide_flag = 1; 1305 1306 TREE_TYPE (a_string) 1307 = build_array_type (wide_flag ? integer_type_node : char_type_node, 1308 build_index_type (build_int_2 (len - 1, 0))); 1309 1310 TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */ 1311 TREE_STATIC (a_string) = 1; 1312 1313 return a_string; 1314} 1315 1316/* Return a newly constructed OBJC_STRING_CST node whose value is 1317 the LEN characters at STR. 1318 The TREE_TYPE is not initialized. */ 1319 1320tree 1321build_objc_string (len, str) 1322 int len; 1323 const char *str; 1324{ 1325 tree s = build_string (len, str); 1326 1327 TREE_SET_CODE (s, OBJC_STRING_CST); 1328 return s; 1329} 1330 1331/* Given a chain of OBJC_STRING_CST's, build a static instance of 1332 NXConstanString which points at the concatenation of those strings. 1333 We place the string object in the __string_objects section of the 1334 __OBJC segment. The Objective-C runtime will initialize the isa 1335 pointers of the string objects to point at the NXConstandString class 1336 object. */ 1337 1338tree 1339build_objc_string_object (strings) 1340 tree strings; 1341{ 1342 tree string, initlist, constructor; 1343 int length; 1344 1345 if (!doing_objc_thang) 1346 objc_fatal (); 1347 1348 if (lookup_interface (constant_string_id) == NULL_TREE) 1349 { 1350 error ("Cannot find interface declaration for `%s'", 1351 IDENTIFIER_POINTER (constant_string_id)); 1352 return error_mark_node; 1353 } 1354 1355 add_class_reference (constant_string_id); 1356 1357 /* Combine_strings will work for OBJC_STRING_CST's too. */ 1358 string = combine_strings (strings); 1359 TREE_SET_CODE (string, STRING_CST); 1360 length = TREE_STRING_LENGTH (string) - 1; 1361 1362 if (! flag_next_runtime) 1363 { 1364 push_obstacks_nochange (); 1365 end_temporary_allocation (); 1366 if (! TREE_PERMANENT (strings)) 1367 string = my_build_string (length + 1, 1368 TREE_STRING_POINTER (string)); 1369 } 1370 1371 /* & ((NXConstantString) {0, string, length}) */ 1372 1373 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); 1374 initlist 1375 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)), 1376 initlist); 1377 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist); 1378 constructor = build_constructor (constant_string_type, nreverse (initlist)); 1379 1380 if (!flag_next_runtime) 1381 { 1382 constructor 1383 = objc_add_static_instance (constructor, constant_string_type); 1384 pop_obstacks (); 1385 } 1386 1387 return (build_unary_op (ADDR_EXPR, constructor, 1)); 1388} 1389 1390/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */ 1391 1392static tree 1393objc_add_static_instance (constructor, class_decl) 1394 tree constructor, class_decl; 1395{ 1396 static int num_static_inst; 1397 tree *chain, decl; 1398 char buf[256]; 1399 1400 push_obstacks_nochange (); 1401 end_temporary_allocation (); 1402 1403 /* Find the list of static instances for the CLASS_DECL. Create one if 1404 not found. */ 1405 for (chain = &objc_static_instances; 1406 *chain && TREE_VALUE (*chain) != class_decl; 1407 chain = &TREE_CHAIN (*chain)); 1408 if (!*chain) 1409 { 1410 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE); 1411 add_objc_string (TYPE_NAME (class_decl), class_names); 1412 } 1413 1414 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++); 1415 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl); 1416 DECL_COMMON (decl) = 1; 1417 TREE_STATIC (decl) = 1; 1418 DECL_ARTIFICIAL (decl) = 1; 1419 pushdecl_top_level (decl); 1420 rest_of_decl_compilation (decl, 0, 1, 0); 1421 1422 /* Do this here so it gets output later instead of possibly 1423 inside something else we are writing. */ 1424 DECL_INITIAL (decl) = constructor; 1425 1426 /* Add the DECL to the head of this CLASS' list. */ 1427 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain)); 1428 1429 pop_obstacks (); 1430 return decl; 1431} 1432 1433/* Build a static constant CONSTRUCTOR 1434 with type TYPE and elements ELTS. */ 1435 1436static tree 1437build_constructor (type, elts) 1438 tree type, elts; 1439{ 1440 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts); 1441 1442 TREE_CONSTANT (constructor) = 1; 1443 TREE_STATIC (constructor) = 1; 1444 TREE_READONLY (constructor) = 1; 1445 1446 return constructor; 1447} 1448 1449/* Take care of defining and initializing _OBJC_SYMBOLS. */ 1450 1451/* Predefine the following data type: 1452 1453 struct _objc_symtab 1454 { 1455 long sel_ref_cnt; 1456 SEL *refs; 1457 short cls_def_cnt; 1458 short cat_def_cnt; 1459 void *defs[cls_def_cnt + cat_def_cnt]; 1460 }; */ 1461 1462static void 1463build_objc_symtab_template () 1464{ 1465 tree field_decl, field_decl_chain, index; 1466 1467 objc_symtab_template 1468 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB)); 1469 1470 /* long sel_ref_cnt; */ 1471 1472 field_decl = create_builtin_decl (FIELD_DECL, 1473 long_integer_type_node, 1474 "sel_ref_cnt"); 1475 field_decl_chain = field_decl; 1476 1477 /* SEL *refs; */ 1478 1479 field_decl = create_builtin_decl (FIELD_DECL, 1480 build_pointer_type (selector_type), 1481 "refs"); 1482 chainon (field_decl_chain, field_decl); 1483 1484 /* short cls_def_cnt; */ 1485 1486 field_decl = create_builtin_decl (FIELD_DECL, 1487 short_integer_type_node, 1488 "cls_def_cnt"); 1489 chainon (field_decl_chain, field_decl); 1490 1491 /* short cat_def_cnt; */ 1492 1493 field_decl = create_builtin_decl (FIELD_DECL, 1494 short_integer_type_node, 1495 "cat_def_cnt"); 1496 chainon (field_decl_chain, field_decl); 1497 1498 /* void *defs[cls_def_cnt + cat_def_cnt]; */ 1499 1500 if (!flag_next_runtime) 1501 index = build_index_type (build_int_2 (imp_count + cat_count, 0)); 1502 else 1503 index = build_index_type (build_int_2 (imp_count + cat_count - 1, 1504 imp_count == 0 && cat_count == 0 1505 ? -1 : 0)); 1506 field_decl = create_builtin_decl (FIELD_DECL, 1507 build_array_type (ptr_type_node, index), 1508 "defs"); 1509 chainon (field_decl_chain, field_decl); 1510 1511 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE); 1512} 1513 1514/* Create the initial value for the `defs' field of _objc_symtab. 1515 This is a CONSTRUCTOR. */ 1516 1517static tree 1518init_def_list (type) 1519 tree type; 1520{ 1521 tree expr, initlist = NULL_TREE; 1522 struct imp_entry *impent; 1523 1524 if (imp_count) 1525 for (impent = imp_list; impent; impent = impent->next) 1526 { 1527 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) 1528 { 1529 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0); 1530 initlist = tree_cons (NULL_TREE, expr, initlist); 1531 } 1532 } 1533 1534 if (cat_count) 1535 for (impent = imp_list; impent; impent = impent->next) 1536 { 1537 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) 1538 { 1539 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0); 1540 initlist = tree_cons (NULL_TREE, expr, initlist); 1541 } 1542 } 1543 1544 if (!flag_next_runtime) 1545 { 1546 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */ 1547 tree expr; 1548 1549 if (static_instances_decl) 1550 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0); 1551 else 1552 expr = build_int_2 (0, 0); 1553 1554 initlist = tree_cons (NULL_TREE, expr, initlist); 1555 } 1556 1557 return build_constructor (type, nreverse (initlist)); 1558} 1559 1560/* Construct the initial value for all of _objc_symtab. */ 1561 1562static tree 1563init_objc_symtab (type) 1564 tree type; 1565{ 1566 tree initlist; 1567 1568 /* sel_ref_cnt = { ..., 5, ... } */ 1569 1570 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); 1571 1572 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */ 1573 1574 if (flag_next_runtime || ! sel_ref_chain) 1575 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 1576 else 1577 initlist = tree_cons (NULL_TREE, 1578 build_unary_op (ADDR_EXPR, 1579 UOBJC_SELECTOR_TABLE_decl, 1), 1580 initlist); 1581 1582 /* cls_def_cnt = { ..., 5, ... } */ 1583 1584 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist); 1585 1586 /* cat_def_cnt = { ..., 5, ... } */ 1587 1588 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist); 1589 1590 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */ 1591 1592 if (imp_count || cat_count || static_instances_decl) 1593 { 1594 1595 tree field = TYPE_FIELDS (type); 1596 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field)))); 1597 1598 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)), 1599 initlist); 1600 } 1601 1602 return build_constructor (type, nreverse (initlist)); 1603} 1604 1605/* Push forward-declarations of all the categories 1606 so that init_def_list can use them in a CONSTRUCTOR. */ 1607 1608static void 1609forward_declare_categories () 1610{ 1611 struct imp_entry *impent; 1612 tree sav = implementation_context; 1613 1614 for (impent = imp_list; impent; impent = impent->next) 1615 { 1616 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) 1617 { 1618 /* Set an invisible arg to synth_id_with_class_suffix. */ 1619 implementation_context = impent->imp_context; 1620 impent->class_decl 1621 = create_builtin_decl (VAR_DECL, objc_category_template, 1622 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context))); 1623 } 1624 } 1625 implementation_context = sav; 1626} 1627 1628/* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab' 1629 and initialized appropriately. */ 1630 1631static void 1632generate_objc_symtab_decl () 1633{ 1634 tree sc_spec; 1635 1636 if (!objc_category_template) 1637 build_category_template (); 1638 1639 /* forward declare categories */ 1640 if (cat_count) 1641 forward_declare_categories (); 1642 1643 if (!objc_symtab_template) 1644 build_objc_symtab_template (); 1645 1646 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]); 1647 1648 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"), 1649 tree_cons (NULL_TREE, 1650 objc_symtab_template, sc_spec), 1651 1, 1652 NULL_TREE, NULL_TREE); 1653 1654 TREE_USED (UOBJC_SYMBOLS_decl) = 1; 1655 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1; 1656 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1; 1657 finish_decl (UOBJC_SYMBOLS_decl, 1658 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)), 1659 NULL_TREE); 1660} 1661 1662static tree 1663init_module_descriptor (type) 1664 tree type; 1665{ 1666 tree initlist, expr; 1667 1668 /* version = { 1, ... } */ 1669 1670 expr = build_int_2 (OBJC_VERSION, 0); 1671 initlist = build_tree_list (NULL_TREE, expr); 1672 1673 /* size = { ..., sizeof (struct objc_module), ... } */ 1674 1675 expr = size_in_bytes (objc_module_template); 1676 initlist = tree_cons (NULL_TREE, expr, initlist); 1677 1678 /* name = { ..., "foo.m", ... } */ 1679 1680 expr = add_objc_string (get_identifier (input_filename), class_names); 1681 initlist = tree_cons (NULL_TREE, expr, initlist); 1682 1683 /* symtab = { ..., _OBJC_SYMBOLS, ... } */ 1684 1685 if (UOBJC_SYMBOLS_decl) 1686 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0); 1687 else 1688 expr = build_int_2 (0, 0); 1689 initlist = tree_cons (NULL_TREE, expr, initlist); 1690 1691 return build_constructor (type, nreverse (initlist)); 1692} 1693 1694/* Write out the data structures to describe Objective C classes defined. 1695 If appropriate, compile and output a setup function to initialize them. 1696 Return a string which is the name of a function to call to initialize 1697 the Objective C data structures for this file (and perhaps for other files 1698 also). 1699 1700 struct objc_module { ... } _OBJC_MODULE = { ... }; */ 1701 1702static char * 1703build_module_descriptor () 1704{ 1705 tree decl_specs, field_decl, field_decl_chain; 1706 1707 objc_module_template 1708 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE)); 1709 1710 /* Long version; */ 1711 1712 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); 1713 field_decl = get_identifier ("version"); 1714 field_decl 1715 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 1716 field_decl_chain = field_decl; 1717 1718 /* long size; */ 1719 1720 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); 1721 field_decl = get_identifier ("size"); 1722 field_decl 1723 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 1724 chainon (field_decl_chain, field_decl); 1725 1726 /* char *name; */ 1727 1728 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); 1729 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name")); 1730 field_decl 1731 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 1732 chainon (field_decl_chain, field_decl); 1733 1734 /* struct objc_symtab *symtab; */ 1735 1736 decl_specs = get_identifier (UTAG_SYMTAB); 1737 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs)); 1738 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab")); 1739 field_decl 1740 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 1741 chainon (field_decl_chain, field_decl); 1742 1743 finish_struct (objc_module_template, field_decl_chain, NULL_TREE); 1744 1745 /* Create an instance of "objc_module". */ 1746 1747 decl_specs = tree_cons (NULL_TREE, objc_module_template, 1748 build_tree_list (NULL_TREE, 1749 ridpointers[(int) RID_STATIC])); 1750 1751 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"), 1752 decl_specs, 1, NULL_TREE, NULL_TREE); 1753 1754 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1; 1755 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1; 1756 finish_decl (UOBJC_MODULES_decl, 1757 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)), 1758 NULL_TREE); 1759 1760 /* Mark the decl to avoid "defined but not used" warning. */ 1761 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1; 1762 1763 /* Generate a constructor call for the module descriptor. 1764 This code was generated by reading the grammar rules 1765 of c-parse.in; Therefore, it may not be the most efficient 1766 way of generating the requisite code. */ 1767 1768 if (flag_next_runtime) 1769 return 0; 1770 1771 { 1772 tree parms, function_decl, decelerator, void_list_node; 1773 tree function_type; 1774 tree init_function_name = get_file_function_name ('I'); 1775 1776 /* Declare void __objc_execClass (void *); */ 1777 1778 void_list_node = build_tree_list (NULL_TREE, void_type_node); 1779 function_type 1780 = build_function_type (void_type_node, 1781 tree_cons (NULL_TREE, ptr_type_node, 1782 void_list_node)); 1783 function_decl = build_decl (FUNCTION_DECL, 1784 get_identifier (TAG_EXECCLASS), 1785 function_type); 1786 DECL_EXTERNAL (function_decl) = 1; 1787 DECL_ARTIFICIAL (function_decl) = 1; 1788 TREE_PUBLIC (function_decl) = 1; 1789 1790 pushdecl (function_decl); 1791 rest_of_decl_compilation (function_decl, 0, 0, 0); 1792 1793 parms 1794 = build_tree_list (NULL_TREE, 1795 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0)); 1796 decelerator = build_function_call (function_decl, parms); 1797 1798 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */ 1799 1800 start_function (void_list_node, 1801 build_parse_node (CALL_EXPR, init_function_name, 1802 /* This has the format of the output 1803 of get_parm_info. */ 1804 tree_cons (NULL_TREE, NULL_TREE, 1805 void_list_node), 1806 NULL_TREE), 1807 NULL_TREE, NULL_TREE, 0); 1808#if 0 /* This should be turned back on later 1809 for the systems where collect is not needed. */ 1810 /* Make these functions nonglobal 1811 so each file can use the same name. */ 1812 TREE_PUBLIC (current_function_decl) = 0; 1813#endif 1814 TREE_USED (current_function_decl) = 1; 1815 store_parm_decls (); 1816 1817 assemble_external (function_decl); 1818 c_expand_expr_stmt (decelerator); 1819 1820 TREE_PUBLIC (current_function_decl) = 1; 1821 1822 function_decl = current_function_decl; 1823 finish_function (0); 1824 1825 /* Return the name of the constructor function. */ 1826 return XSTR (XEXP (DECL_RTL (function_decl), 0), 0); 1827 } 1828} 1829 1830/* extern const char _OBJC_STRINGS[]; */ 1831 1832static void 1833generate_forward_declaration_to_string_table () 1834{ 1835 tree sc_spec, decl_specs, expr_decl; 1836 1837 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE); 1838 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); 1839 1840 expr_decl 1841 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE); 1842 1843 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs); 1844} 1845 1846/* Return the DECL of the string IDENT in the SECTION. */ 1847 1848static tree 1849get_objc_string_decl (ident, section) 1850 tree ident; 1851 enum string_section section; 1852{ 1853 tree chain; 1854 1855 if (section == class_names) 1856 chain = class_names_chain; 1857 else if (section == meth_var_names) 1858 chain = meth_var_names_chain; 1859 else if (section == meth_var_types) 1860 chain = meth_var_types_chain; 1861 else 1862 abort (); 1863 1864 for (; chain != 0; chain = TREE_VALUE (chain)) 1865 if (TREE_VALUE (chain) == ident) 1866 return (TREE_PURPOSE (chain)); 1867 1868 abort (); 1869 return NULL_TREE; 1870} 1871 1872/* Output references to all statically allocated objects. Return the DECL 1873 for the array built. */ 1874 1875static void 1876generate_static_references () 1877{ 1878 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE; 1879 tree class_name, class, decl, initlist; 1880 tree cl_chain, in_chain, type; 1881 int num_inst, num_class; 1882 char buf[256]; 1883 1884 if (flag_next_runtime) 1885 abort (); 1886 1887 for (cl_chain = objc_static_instances, num_class = 0; 1888 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++) 1889 { 1890 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain); 1891 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain)); 1892 1893 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class); 1894 ident = get_identifier (buf); 1895 1896 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE); 1897 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node), 1898 build_tree_list (NULL_TREE, 1899 ridpointers[(int) RID_STATIC])); 1900 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE); 1901 DECL_CONTEXT (decl) = 0; 1902 DECL_ARTIFICIAL (decl) = 1; 1903 1904 /* Output {class_name, ...}. */ 1905 class = TREE_VALUE (cl_chain); 1906 class_name = get_objc_string_decl (TYPE_NAME (class), class_names); 1907 initlist = build_tree_list (NULL_TREE, 1908 build_unary_op (ADDR_EXPR, class_name, 1)); 1909 1910 /* Output {..., instance, ...}. */ 1911 for (in_chain = TREE_PURPOSE (cl_chain); 1912 in_chain; in_chain = TREE_CHAIN (in_chain)) 1913 { 1914 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1); 1915 initlist = tree_cons (NULL_TREE, expr, initlist); 1916 } 1917 1918 /* Output {..., NULL}. */ 1919 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 1920 1921 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist)); 1922 finish_decl (decl, expr, NULL_TREE); 1923 TREE_USED (decl) = 1; 1924 1925 type = build_array_type (build_pointer_type (void_type_node), 0); 1926 decl = build_decl (VAR_DECL, ident, type); 1927 make_decl_rtl (decl, 0, 1); 1928 TREE_USED (decl) = 1; 1929 decls 1930 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls); 1931 } 1932 1933 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls); 1934 ident = get_identifier ("_OBJC_STATIC_INSTANCES"); 1935 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE); 1936 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node), 1937 build_tree_list (NULL_TREE, 1938 ridpointers[(int) RID_STATIC])); 1939 static_instances_decl 1940 = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE); 1941 TREE_USED (static_instances_decl) = 1; 1942 DECL_CONTEXT (static_instances_decl) = 0; 1943 DECL_ARTIFICIAL (static_instances_decl) = 1; 1944 end_temporary_allocation (); 1945 expr = build_constructor (TREE_TYPE (static_instances_decl), 1946 nreverse (decls)); 1947 finish_decl (static_instances_decl, expr, NULL_TREE); 1948} 1949 1950/* Output all strings. */ 1951 1952static void 1953generate_strings () 1954{ 1955 tree sc_spec, decl_specs, expr_decl; 1956 tree chain, string_expr; 1957 tree string, decl; 1958 1959 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain)) 1960 { 1961 string = TREE_VALUE (chain); 1962 decl = TREE_PURPOSE (chain); 1963 sc_spec 1964 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 1965 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); 1966 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); 1967 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); 1968 end_temporary_allocation (); 1969 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, 1970 IDENTIFIER_POINTER (string)); 1971 finish_decl (decl, string_expr, NULL_TREE); 1972 } 1973 1974 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain)) 1975 { 1976 string = TREE_VALUE (chain); 1977 decl = TREE_PURPOSE (chain); 1978 sc_spec 1979 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 1980 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); 1981 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); 1982 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); 1983 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, 1984 IDENTIFIER_POINTER (string)); 1985 finish_decl (decl, string_expr, NULL_TREE); 1986 } 1987 1988 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain)) 1989 { 1990 string = TREE_VALUE (chain); 1991 decl = TREE_PURPOSE (chain); 1992 sc_spec 1993 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 1994 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); 1995 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); 1996 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); 1997 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, 1998 IDENTIFIER_POINTER (string)); 1999 finish_decl (decl, string_expr, NULL_TREE); 2000 } 2001} 2002 2003static tree 2004build_selector_reference_decl (name) 2005 tree name; 2006{ 2007 tree decl, ident; 2008 char buf[256]; 2009 static int idx = 0; 2010 2011 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++); 2012 2013 push_obstacks_nochange (); 2014 end_temporary_allocation (); 2015 2016 ident = get_identifier (buf); 2017 2018 decl = build_decl (VAR_DECL, ident, selector_type); 2019 DECL_EXTERNAL (decl) = 1; 2020 TREE_PUBLIC (decl) = 1; 2021 TREE_USED (decl) = 1; 2022 TREE_READONLY (decl) = 1; 2023 DECL_ARTIFICIAL (decl) = 1; 2024 DECL_CONTEXT (decl) = 0; 2025 2026 make_decl_rtl (decl, 0, 1); 2027 pushdecl_top_level (decl); 2028 2029 pop_obstacks (); 2030 2031 return decl; 2032} 2033 2034/* Just a handy wrapper for add_objc_string. */ 2035 2036static tree 2037build_selector (ident) 2038 tree ident; 2039{ 2040 tree expr = add_objc_string (ident, meth_var_names); 2041 if (flag_typed_selectors) 2042 return expr; 2043 else 2044 return build_c_cast (selector_type, expr); /* cast! */ 2045} 2046 2047/* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>] 2048 The cast stops the compiler from issuing the following message: 2049 grok.m: warning: initialization of non-const * pointer from const * 2050 grok.m: warning: initialization between incompatible pointer types. */ 2051 2052#if 0 2053static tree 2054build_msg_pool_reference (offset) 2055 int offset; 2056{ 2057 tree expr = build_int_2 (offset, 0); 2058 tree cast; 2059 2060 expr = build_array_ref (UOBJC_STRINGS_decl, expr); 2061 expr = build_unary_op (ADDR_EXPR, expr, 0); 2062 2063 cast = build_tree_list (build_tree_list (NULL_TREE, 2064 ridpointers[(int) RID_CHAR]), 2065 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)); 2066 TREE_TYPE (expr) = groktypename (cast); 2067 return expr; 2068} 2069 2070static tree 2071init_selector (offset) 2072 int offset; 2073{ 2074 tree expr = build_msg_pool_reference (offset); 2075 TREE_TYPE (expr) = selector_type; 2076 return expr; 2077} 2078#endif 2079 2080static void 2081build_selector_translation_table () 2082{ 2083 tree sc_spec, decl_specs; 2084 tree chain, initlist = NULL_TREE; 2085 int offset = 0; 2086 tree decl = NULL_TREE, var_decl, name; 2087 2088 /* The corresponding pop_obstacks is in finish_decl, 2089 called at the end of this function. */ 2090 if (! flag_next_runtime) 2091 push_obstacks_nochange (); 2092 2093 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) 2094 { 2095 tree expr; 2096 2097 expr = build_selector (TREE_VALUE (chain)); 2098 2099 if (flag_next_runtime) 2100 { 2101 name = DECL_NAME (TREE_PURPOSE (chain)); 2102 2103 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]); 2104 2105 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */ 2106 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec); 2107 2108 var_decl = name; 2109 2110 /* The `decl' that is returned from start_decl is the one that we 2111 forward declared in `build_selector_reference' */ 2112 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE); 2113 } 2114 2115 /* add one for the '\0' character */ 2116 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1; 2117 2118 if (flag_next_runtime) 2119 finish_decl (decl, expr, NULL_TREE); 2120 else 2121 { 2122 if (flag_typed_selectors) 2123 { 2124 tree eltlist = NULL_TREE; 2125 tree encoding = get_proto_encoding (TREE_PURPOSE (chain)); 2126 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE); 2127 eltlist = tree_cons (NULL_TREE, encoding, eltlist); 2128 expr = build_constructor (objc_selector_template, 2129 nreverse (eltlist)); 2130 } 2131 initlist = tree_cons (NULL_TREE, expr, initlist); 2132 2133 } 2134 } 2135 2136 if (! flag_next_runtime) 2137 { 2138 /* Cause the variable and its initial value to be actually output. */ 2139 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0; 2140 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1; 2141 /* NULL terminate the list and fix the decl for output. */ 2142 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 2143 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1; 2144 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl), 2145 nreverse (initlist)); 2146 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE); 2147 current_function_decl = NULL_TREE; 2148 } 2149} 2150 2151static tree 2152get_proto_encoding (proto) 2153 tree proto; 2154{ 2155 tree encoding; 2156 if (proto) 2157 { 2158 tree tmp_decl; 2159 2160 if (! METHOD_ENCODING (proto)) 2161 { 2162 tmp_decl = build_tmp_function_decl (); 2163 hack_method_prototype (proto, tmp_decl); 2164 encoding = encode_method_prototype (proto, tmp_decl); 2165 METHOD_ENCODING (proto) = encoding; 2166 } 2167 else 2168 encoding = METHOD_ENCODING (proto); 2169 2170 return add_objc_string (encoding, meth_var_types); 2171 } 2172 else 2173 return build_int_2 (0, 0); 2174} 2175 2176/* sel_ref_chain is a list whose "value" fields will be instances of 2177 identifier_node that represent the selector. */ 2178 2179static tree 2180build_typed_selector_reference (ident, proto) 2181 tree ident, proto; 2182{ 2183 tree *chain = &sel_ref_chain; 2184 tree expr; 2185 int index = 0; 2186 2187 while (*chain) 2188 { 2189 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto) 2190 goto return_at_index; 2191 2192 index++; 2193 chain = &TREE_CHAIN (*chain); 2194 } 2195 2196 *chain = perm_tree_cons (proto, ident, NULL_TREE); 2197 2198 return_at_index: 2199 expr = build_unary_op (ADDR_EXPR, 2200 build_array_ref (UOBJC_SELECTOR_TABLE_decl, 2201 build_int_2 (index, 0)), 2202 1); 2203 return build_c_cast (selector_type, expr); 2204} 2205 2206static tree 2207build_selector_reference (ident) 2208 tree ident; 2209{ 2210 tree *chain = &sel_ref_chain; 2211 tree expr; 2212 int index = 0; 2213 2214 while (*chain) 2215 { 2216 if (TREE_VALUE (*chain) == ident) 2217 return (flag_next_runtime 2218 ? TREE_PURPOSE (*chain) 2219 : build_array_ref (UOBJC_SELECTOR_TABLE_decl, 2220 build_int_2 (index, 0))); 2221 2222 index++; 2223 chain = &TREE_CHAIN (*chain); 2224 } 2225 2226 expr = build_selector_reference_decl (ident); 2227 2228 *chain = perm_tree_cons (expr, ident, NULL_TREE); 2229 2230 return (flag_next_runtime 2231 ? expr 2232 : build_array_ref (UOBJC_SELECTOR_TABLE_decl, 2233 build_int_2 (index, 0))); 2234} 2235 2236static tree 2237build_class_reference_decl (name) 2238 tree name; 2239{ 2240 tree decl, ident; 2241 char buf[256]; 2242 static int idx = 0; 2243 2244 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++); 2245 2246 push_obstacks_nochange (); 2247 end_temporary_allocation (); 2248 2249 ident = get_identifier (buf); 2250 2251 decl = build_decl (VAR_DECL, ident, objc_class_type); 2252 DECL_EXTERNAL (decl) = 1; 2253 TREE_PUBLIC (decl) = 1; 2254 TREE_USED (decl) = 1; 2255 TREE_READONLY (decl) = 1; 2256 DECL_CONTEXT (decl) = 0; 2257 DECL_ARTIFICIAL (decl) = 1; 2258 2259 make_decl_rtl (decl, 0, 1); 2260 pushdecl_top_level (decl); 2261 2262 pop_obstacks (); 2263 2264 return decl; 2265} 2266 2267/* Create a class reference, but don't create a variable to reference 2268 it. */ 2269 2270static void 2271add_class_reference (ident) 2272 tree ident; 2273{ 2274 tree chain; 2275 2276 if ((chain = cls_ref_chain)) 2277 { 2278 tree tail; 2279 do 2280 { 2281 if (ident == TREE_VALUE (chain)) 2282 return; 2283 2284 tail = chain; 2285 chain = TREE_CHAIN (chain); 2286 } 2287 while (chain); 2288 2289 /* Append to the end of the list */ 2290 TREE_CHAIN (tail) = perm_tree_cons (NULL_TREE, ident, NULL_TREE); 2291 } 2292 else 2293 cls_ref_chain = perm_tree_cons (NULL_TREE, ident, NULL_TREE); 2294} 2295 2296/* Get a class reference, creating it if necessary. Also create the 2297 reference variable. */ 2298 2299tree 2300get_class_reference (ident) 2301 tree ident; 2302{ 2303 if (flag_next_runtime) 2304 { 2305 tree *chain; 2306 tree decl; 2307 2308 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain)) 2309 if (TREE_VALUE (*chain) == ident) 2310 { 2311 if (! TREE_PURPOSE (*chain)) 2312 TREE_PURPOSE (*chain) = build_class_reference_decl (ident); 2313 2314 return TREE_PURPOSE (*chain); 2315 } 2316 2317 decl = build_class_reference_decl (ident); 2318 *chain = perm_tree_cons (decl, ident, NULL_TREE); 2319 return decl; 2320 } 2321 else 2322 { 2323 tree params; 2324 2325 add_class_reference (ident); 2326 2327 params = build_tree_list (NULL_TREE, 2328 my_build_string (IDENTIFIER_LENGTH (ident) + 1, 2329 IDENTIFIER_POINTER (ident))); 2330 2331 assemble_external (objc_get_class_decl); 2332 return build_function_call (objc_get_class_decl, params); 2333 } 2334} 2335 2336/* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances 2337 of identifier_node that represent the selector. It returns the 2338 offset of the selector from the beginning of the _OBJC_STRINGS 2339 pool. This offset is typically used by init_selector during code 2340 generation. 2341 2342 For each string section we have a chain which maps identifier nodes 2343 to decls for the strings. */ 2344 2345static tree 2346add_objc_string (ident, section) 2347 tree ident; 2348 enum string_section section; 2349{ 2350 tree *chain, decl; 2351 2352 if (section == class_names) 2353 chain = &class_names_chain; 2354 else if (section == meth_var_names) 2355 chain = &meth_var_names_chain; 2356 else if (section == meth_var_types) 2357 chain = &meth_var_types_chain; 2358 else 2359 abort (); 2360 2361 while (*chain) 2362 { 2363 if (TREE_VALUE (*chain) == ident) 2364 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1); 2365 2366 chain = &TREE_CHAIN (*chain); 2367 } 2368 2369 decl = build_objc_string_decl (ident, section); 2370 2371 *chain = perm_tree_cons (decl, ident, NULL_TREE); 2372 2373 return build_unary_op (ADDR_EXPR, decl, 1); 2374} 2375 2376static tree 2377build_objc_string_decl (name, section) 2378 tree name; 2379 enum string_section section; 2380{ 2381 tree decl, ident; 2382 char buf[256]; 2383 static int class_names_idx = 0; 2384 static int meth_var_names_idx = 0; 2385 static int meth_var_types_idx = 0; 2386 2387 if (section == class_names) 2388 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++); 2389 else if (section == meth_var_names) 2390 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++); 2391 else if (section == meth_var_types) 2392 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++); 2393 2394 push_obstacks_nochange (); 2395 end_temporary_allocation (); 2396 ident = get_identifier (buf); 2397 2398 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0)); 2399 DECL_EXTERNAL (decl) = 1; 2400 TREE_PUBLIC (decl) = 1; 2401 TREE_USED (decl) = 1; 2402 TREE_READONLY (decl) = 1; 2403 TREE_CONSTANT (decl) = 1; 2404 DECL_CONTEXT (decl) = 0; 2405 DECL_ARTIFICIAL (decl) = 1; 2406 2407 make_decl_rtl (decl, 0, 1); 2408 pushdecl_top_level (decl); 2409 2410 pop_obstacks (); 2411 2412 return decl; 2413} 2414 2415 2416void 2417objc_declare_alias (alias_ident, class_ident) 2418 tree alias_ident; 2419 tree class_ident; 2420{ 2421 if (!doing_objc_thang) 2422 objc_fatal (); 2423 2424 if (is_class_name (class_ident) != class_ident) 2425 warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident)); 2426 else if (is_class_name (alias_ident)) 2427 warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident)); 2428 else 2429 alias_chain = tree_cons (class_ident, alias_ident, alias_chain); 2430} 2431 2432void 2433objc_declare_class (ident_list) 2434 tree ident_list; 2435{ 2436 tree list; 2437 2438 if (!doing_objc_thang) 2439 objc_fatal (); 2440 2441 for (list = ident_list; list; list = TREE_CHAIN (list)) 2442 { 2443 tree ident = TREE_VALUE (list); 2444 tree decl; 2445 2446 if ((decl = lookup_name (ident))) 2447 { 2448 error ("`%s' redeclared as different kind of symbol", 2449 IDENTIFIER_POINTER (ident)); 2450 error_with_decl (decl, "previous declaration of `%s'"); 2451 } 2452 2453 if (! is_class_name (ident)) 2454 { 2455 tree record = xref_tag (RECORD_TYPE, ident); 2456 TREE_STATIC_TEMPLATE (record) = 1; 2457 class_chain = tree_cons (NULL_TREE, ident, class_chain); 2458 } 2459 } 2460} 2461 2462tree 2463is_class_name (ident) 2464 tree ident; 2465{ 2466 tree chain; 2467 2468 if (lookup_interface (ident)) 2469 return ident; 2470 2471 for (chain = class_chain; chain; chain = TREE_CHAIN (chain)) 2472 { 2473 if (ident == TREE_VALUE (chain)) 2474 return ident; 2475 } 2476 2477 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain)) 2478 { 2479 if (ident == TREE_VALUE (chain)) 2480 return TREE_PURPOSE (chain); 2481 } 2482 2483 return 0; 2484} 2485 2486tree 2487lookup_interface (ident) 2488 tree ident; 2489{ 2490 tree chain; 2491 2492 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain)) 2493 { 2494 if (ident == CLASS_NAME (chain)) 2495 return chain; 2496 } 2497 return NULL_TREE; 2498} 2499 2500static tree 2501objc_copy_list (list, head) 2502 tree list; 2503 tree *head; 2504{ 2505 tree newlist = NULL_TREE, tail = NULL_TREE; 2506 2507 while (list) 2508 { 2509 tail = copy_node (list); 2510 2511 /* The following statement fixes a bug when inheriting instance 2512 variables that are declared to be bitfields. finish_struct 2513 expects to find the width of the bitfield in DECL_INITIAL, 2514 which it nulls out after processing the decl of the super 2515 class...rather than change the way finish_struct works (which 2516 is risky), I create the situation it expects...s.naroff 2517 (7/23/89). */ 2518 2519 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0) 2520 DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0); 2521 2522 newlist = chainon (newlist, tail); 2523 list = TREE_CHAIN (list); 2524 } 2525 2526 *head = newlist; 2527 return tail; 2528} 2529 2530/* Used by: build_private_template, get_class_ivars, and 2531 continue_class. COPY is 1 when called from @defs. In this case 2532 copy all fields. Otherwise don't copy leaf ivars since we rely on 2533 them being side-effected exactly once by finish_struct. */ 2534 2535static tree 2536build_ivar_chain (interface, copy) 2537 tree interface; 2538 int copy; 2539{ 2540 tree my_name, super_name, ivar_chain; 2541 2542 my_name = CLASS_NAME (interface); 2543 super_name = CLASS_SUPER_NAME (interface); 2544 2545 /* Possibly copy leaf ivars. */ 2546 if (copy) 2547 objc_copy_list (CLASS_IVARS (interface), &ivar_chain); 2548 else 2549 ivar_chain = CLASS_IVARS (interface); 2550 2551 while (super_name) 2552 { 2553 tree op1; 2554 tree super_interface = lookup_interface (super_name); 2555 2556 if (!super_interface) 2557 { 2558 /* fatal did not work with 2 args...should fix */ 2559 error ("Cannot find interface declaration for `%s', superclass of `%s'", 2560 IDENTIFIER_POINTER (super_name), 2561 IDENTIFIER_POINTER (my_name)); 2562 exit (FATAL_EXIT_CODE); 2563 } 2564 2565 if (super_interface == interface) 2566 { 2567 fatal ("Circular inheritance in interface declaration for `%s'", 2568 IDENTIFIER_POINTER (super_name)); 2569 } 2570 2571 interface = super_interface; 2572 my_name = CLASS_NAME (interface); 2573 super_name = CLASS_SUPER_NAME (interface); 2574 2575 op1 = CLASS_IVARS (interface); 2576 if (op1) 2577 { 2578 tree head, tail = objc_copy_list (op1, &head); 2579 2580 /* Prepend super class ivars...make a copy of the list, we 2581 do not want to alter the original. */ 2582 TREE_CHAIN (tail) = ivar_chain; 2583 ivar_chain = head; 2584 } 2585 } 2586 return ivar_chain; 2587} 2588 2589/* struct <classname> { 2590 struct objc_class *isa; 2591 ... 2592 }; */ 2593 2594static tree 2595build_private_template (class) 2596 tree class; 2597{ 2598 tree ivar_context; 2599 2600 if (CLASS_STATIC_TEMPLATE (class)) 2601 { 2602 uprivate_record = CLASS_STATIC_TEMPLATE (class); 2603 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class)); 2604 } 2605 else 2606 { 2607 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class)); 2608 2609 ivar_context = build_ivar_chain (class, 0); 2610 2611 finish_struct (uprivate_record, ivar_context, NULL_TREE); 2612 2613 CLASS_STATIC_TEMPLATE (class) = uprivate_record; 2614 2615 /* mark this record as class template - for class type checking */ 2616 TREE_STATIC_TEMPLATE (uprivate_record) = 1; 2617 } 2618 2619 instance_type 2620 = groktypename (build_tree_list (build_tree_list (NULL_TREE, 2621 uprivate_record), 2622 build1 (INDIRECT_REF, NULL_TREE, 2623 NULL_TREE))); 2624 2625 return ivar_context; 2626} 2627 2628/* Begin code generation for protocols... */ 2629 2630/* struct objc_protocol { 2631 char *protocol_name; 2632 struct objc_protocol **protocol_list; 2633 struct objc_method_desc *instance_methods; 2634 struct objc_method_desc *class_methods; 2635 }; */ 2636 2637static tree 2638build_protocol_template () 2639{ 2640 tree decl_specs, field_decl, field_decl_chain; 2641 tree template; 2642 2643 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL)); 2644 2645 /* struct objc_class *isa; */ 2646 2647 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, 2648 get_identifier (UTAG_CLASS))); 2649 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa")); 2650 field_decl 2651 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2652 field_decl_chain = field_decl; 2653 2654 /* char *protocol_name; */ 2655 2656 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); 2657 field_decl 2658 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name")); 2659 field_decl 2660 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2661 chainon (field_decl_chain, field_decl); 2662 2663 /* struct objc_protocol **protocol_list; */ 2664 2665 decl_specs = build_tree_list (NULL_TREE, template); 2666 field_decl 2667 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list")); 2668 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl); 2669 field_decl 2670 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2671 chainon (field_decl_chain, field_decl); 2672 2673 /* struct objc_method_list *instance_methods; */ 2674 2675 decl_specs 2676 = build_tree_list (NULL_TREE, 2677 xref_tag (RECORD_TYPE, 2678 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))); 2679 field_decl 2680 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods")); 2681 field_decl 2682 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2683 chainon (field_decl_chain, field_decl); 2684 2685 /* struct objc_method_list *class_methods; */ 2686 2687 decl_specs 2688 = build_tree_list (NULL_TREE, 2689 xref_tag (RECORD_TYPE, 2690 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))); 2691 field_decl 2692 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods")); 2693 field_decl 2694 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2695 chainon (field_decl_chain, field_decl); 2696 2697 return finish_struct (template, field_decl_chain, NULL_TREE); 2698} 2699 2700static tree 2701build_descriptor_table_initializer (type, entries) 2702 tree type; 2703 tree entries; 2704{ 2705 tree initlist = NULL_TREE; 2706 2707 do 2708 { 2709 tree eltlist = NULL_TREE; 2710 2711 eltlist 2712 = tree_cons (NULL_TREE, 2713 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE); 2714 eltlist 2715 = tree_cons (NULL_TREE, 2716 add_objc_string (METHOD_ENCODING (entries), 2717 meth_var_types), 2718 eltlist); 2719 2720 initlist 2721 = tree_cons (NULL_TREE, 2722 build_constructor (type, nreverse (eltlist)), initlist); 2723 2724 entries = TREE_CHAIN (entries); 2725 } 2726 while (entries); 2727 2728 return build_constructor (build_array_type (type, 0), nreverse (initlist)); 2729} 2730 2731/* struct objc_method_prototype_list { 2732 int count; 2733 struct objc_method_prototype { 2734 SEL name; 2735 char *types; 2736 } list[1]; 2737 }; */ 2738 2739static tree 2740build_method_prototype_list_template (list_type, size) 2741 tree list_type; 2742 int size; 2743{ 2744 tree objc_ivar_list_record; 2745 tree decl_specs, field_decl, field_decl_chain; 2746 2747 /* Generate an unnamed struct definition. */ 2748 2749 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE); 2750 2751 /* int method_count; */ 2752 2753 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]); 2754 field_decl = get_identifier ("method_count"); 2755 2756 field_decl 2757 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2758 field_decl_chain = field_decl; 2759 2760 /* struct objc_method method_list[]; */ 2761 2762 decl_specs = build_tree_list (NULL_TREE, list_type); 2763 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"), 2764 build_int_2 (size, 0)); 2765 2766 field_decl 2767 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2768 chainon (field_decl_chain, field_decl); 2769 2770 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE); 2771 2772 return objc_ivar_list_record; 2773} 2774 2775static tree 2776build_method_prototype_template () 2777{ 2778 tree proto_record; 2779 tree decl_specs, field_decl, field_decl_chain; 2780 2781 proto_record 2782 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE)); 2783 2784#ifdef OBJC_INT_SELECTORS 2785 /* unsigned int _cmd; */ 2786 decl_specs 2787 = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE); 2788 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); 2789 field_decl = get_identifier ("_cmd"); 2790#else /* OBJC_INT_SELECTORS */ 2791 /* struct objc_selector *_cmd; */ 2792 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE, 2793 get_identifier (TAG_SELECTOR)), NULL_TREE); 2794 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd")); 2795#endif /* OBJC_INT_SELECTORS */ 2796 2797 field_decl 2798 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2799 field_decl_chain = field_decl; 2800 2801 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE); 2802 field_decl 2803 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types")); 2804 field_decl 2805 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 2806 chainon (field_decl_chain, field_decl); 2807 2808 finish_struct (proto_record, field_decl_chain, NULL_TREE); 2809 2810 return proto_record; 2811} 2812 2813/* True if last call to forwarding_offset yielded a register offset. */ 2814static int offset_is_register; 2815 2816static int 2817forwarding_offset (parm) 2818 tree parm; 2819{ 2820 int offset_in_bytes; 2821 2822 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM) 2823 { 2824 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0); 2825 2826 /* ??? Here we assume that the parm address is indexed 2827 off the frame pointer or arg pointer. 2828 If that is not true, we produce meaningless results, 2829 but do not crash. */ 2830 if (GET_CODE (addr) == PLUS 2831 && GET_CODE (XEXP (addr, 1)) == CONST_INT) 2832 offset_in_bytes = INTVAL (XEXP (addr, 1)); 2833 else 2834 offset_in_bytes = 0; 2835 2836 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET; 2837 offset_is_register = 0; 2838 } 2839 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG) 2840 { 2841 int regno = REGNO (DECL_INCOMING_RTL (parm)); 2842 offset_in_bytes = apply_args_register_offset (regno); 2843 offset_is_register = 1; 2844 } 2845 else 2846 return 0; 2847 2848 /* This is the case where the parm is passed as an int or double 2849 and it is converted to a char, short or float and stored back 2850 in the parmlist. In this case, describe the parm 2851 with the variable's declared type, and adjust the address 2852 if the least significant bytes (which we are using) are not 2853 the first ones. */ 2854 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm)) 2855 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm))) 2856 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm)))); 2857 2858 return offset_in_bytes; 2859} 2860 2861static tree 2862encode_method_prototype (method_decl, func_decl) 2863 tree method_decl; 2864 tree func_decl; 2865{ 2866 tree parms; 2867 int stack_size, i; 2868 tree user_args; 2869 int max_parm_end = 0; 2870 char buf[40]; 2871 tree result; 2872 2873 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */ 2874 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl))); 2875 2876 /* C type. */ 2877 encode_type (TREE_TYPE (TREE_TYPE (func_decl)), 2878 obstack_object_size (&util_obstack), 2879 OBJC_ENCODE_INLINE_DEFS); 2880 2881 /* Stack size. */ 2882 for (parms = DECL_ARGUMENTS (func_decl); parms; 2883 parms = TREE_CHAIN (parms)) 2884 { 2885 int parm_end = (forwarding_offset (parms) 2886 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms))) 2887 / BITS_PER_UNIT)); 2888 2889 if (!offset_is_register && max_parm_end < parm_end) 2890 max_parm_end = parm_end; 2891 } 2892 2893 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET; 2894 2895 sprintf (buf, "%d", stack_size); 2896 obstack_grow (&util_obstack, buf, strlen (buf)); 2897 2898 user_args = METHOD_SEL_ARGS (method_decl); 2899 2900 /* Argument types. */ 2901 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms; 2902 parms = TREE_CHAIN (parms), i++) 2903 { 2904 /* Process argument qualifiers for user supplied arguments. */ 2905 if (i > 1) 2906 { 2907 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args))); 2908 user_args = TREE_CHAIN (user_args); 2909 } 2910 2911 /* Type. */ 2912 encode_type (TREE_TYPE (parms), 2913 obstack_object_size (&util_obstack), 2914 OBJC_ENCODE_INLINE_DEFS); 2915 2916 /* Compute offset. */ 2917 sprintf (buf, "%d", forwarding_offset (parms)); 2918 2919 /* Indicate register. */ 2920 if (offset_is_register) 2921 obstack_1grow (&util_obstack, '+'); 2922 2923 obstack_grow (&util_obstack, buf, strlen (buf)); 2924 } 2925 2926 obstack_1grow (&util_obstack, '\0'); 2927 result = get_identifier (obstack_finish (&util_obstack)); 2928 obstack_free (&util_obstack, util_firstobj); 2929 return result; 2930} 2931 2932static tree 2933generate_descriptor_table (type, name, size, list, proto) 2934 tree type; 2935 char *name; 2936 int size; 2937 tree list; 2938 tree proto; 2939{ 2940 tree sc_spec, decl_specs, decl, initlist; 2941 2942 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 2943 decl_specs = tree_cons (NULL_TREE, type, sc_spec); 2944 2945 decl = start_decl (synth_id_with_class_suffix (name, proto), 2946 decl_specs, 1, NULL_TREE, NULL_TREE); 2947 2948 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0)); 2949 initlist = tree_cons (NULL_TREE, list, initlist); 2950 2951 finish_decl (decl, build_constructor (type, nreverse (initlist)), 2952 NULL_TREE); 2953 2954 return decl; 2955} 2956 2957static void 2958generate_method_descriptors (protocol) /* generate_dispatch_tables */ 2959 tree protocol; 2960{ 2961 static tree objc_method_prototype_template; 2962 tree initlist, chain, method_list_template; 2963 tree cast, variable_length_type; 2964 int size; 2965 2966 if (!objc_method_prototype_template) 2967 objc_method_prototype_template = build_method_prototype_template (); 2968 2969 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, 2970 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))), 2971 NULL_TREE); 2972 variable_length_type = groktypename (cast); 2973 2974 chain = PROTOCOL_CLS_METHODS (protocol); 2975 if (chain) 2976 { 2977 size = list_length (chain); 2978 2979 method_list_template 2980 = build_method_prototype_list_template (objc_method_prototype_template, 2981 size); 2982 2983 initlist 2984 = build_descriptor_table_initializer (objc_method_prototype_template, 2985 chain); 2986 2987 UOBJC_CLASS_METHODS_decl 2988 = generate_descriptor_table (method_list_template, 2989 "_OBJC_PROTOCOL_CLASS_METHODS", 2990 size, initlist, protocol); 2991 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type; 2992 } 2993 else 2994 UOBJC_CLASS_METHODS_decl = 0; 2995 2996 chain = PROTOCOL_NST_METHODS (protocol); 2997 if (chain) 2998 { 2999 size = list_length (chain); 3000 3001 method_list_template 3002 = build_method_prototype_list_template (objc_method_prototype_template, 3003 size); 3004 initlist 3005 = build_descriptor_table_initializer (objc_method_prototype_template, 3006 chain); 3007 3008 UOBJC_INSTANCE_METHODS_decl 3009 = generate_descriptor_table (method_list_template, 3010 "_OBJC_PROTOCOL_INSTANCE_METHODS", 3011 size, initlist, protocol); 3012 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type; 3013 } 3014 else 3015 UOBJC_INSTANCE_METHODS_decl = 0; 3016} 3017 3018static tree 3019build_tmp_function_decl () 3020{ 3021 tree decl_specs, expr_decl, parms; 3022 static int xxx = 0; 3023 char buffer[80]; 3024 3025 /* struct objc_object *objc_xxx (id, SEL, ...); */ 3026 pushlevel (0); 3027 decl_specs = build_tree_list (NULL_TREE, objc_object_reference); 3028 push_parm_decl (build_tree_list 3029 (build_tree_list (decl_specs, 3030 build1 (INDIRECT_REF, NULL_TREE, 3031 NULL_TREE)), 3032 build_tree_list (NULL_TREE, NULL_TREE))); 3033 3034 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, 3035 get_identifier (TAG_SELECTOR))); 3036 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE); 3037 3038 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl), 3039 build_tree_list (NULL_TREE, NULL_TREE))); 3040 parms = get_parm_info (0); 3041 poplevel (0, 0, 0); 3042 3043 decl_specs = build_tree_list (NULL_TREE, objc_object_reference); 3044 sprintf (buffer, "__objc_tmp_%x", xxx++); 3045 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE); 3046 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl); 3047 3048 return define_decl (expr_decl, decl_specs); 3049} 3050 3051static void 3052hack_method_prototype (nst_methods, tmp_decl) 3053 tree nst_methods; 3054 tree tmp_decl; 3055{ 3056 tree parms; 3057 tree parm; 3058 3059 /* Hack to avoid problem with static typing of self arg. */ 3060 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL); 3061 start_method_def (nst_methods); 3062 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL); 3063 3064 if (METHOD_ADD_ARGS (nst_methods) == (tree) 1) 3065 parms = get_parm_info (0); /* we have a `, ...' */ 3066 else 3067 parms = get_parm_info (1); /* place a `void_at_end' */ 3068 3069 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */ 3070 3071 /* Usually called from store_parm_decls -> init_function_start. */ 3072 3073 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms); 3074 current_function_decl = tmp_decl; 3075 3076 { 3077 /* Code taken from start_function. */ 3078 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl)); 3079 /* Promote the value to int before returning it. */ 3080 if (TREE_CODE (restype) == INTEGER_TYPE 3081 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node)) 3082 restype = integer_type_node; 3083 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype); 3084 } 3085 3086 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm)) 3087 DECL_CONTEXT (parm) = tmp_decl; 3088 3089 init_function_start (tmp_decl, "objc-act", 0); 3090 3091 /* Typically called from expand_function_start for function definitions. */ 3092 assign_parms (tmp_decl, 0); 3093 3094 /* install return type */ 3095 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods)); 3096 3097} 3098 3099static void 3100generate_protocol_references (plist) 3101 tree plist; 3102{ 3103 tree lproto; 3104 3105 /* Forward declare protocols referenced. */ 3106 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) 3107 { 3108 tree proto = TREE_VALUE (lproto); 3109 3110 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE 3111 && PROTOCOL_NAME (proto)) 3112 { 3113 if (! PROTOCOL_FORWARD_DECL (proto)) 3114 build_protocol_reference (proto); 3115 3116 if (PROTOCOL_LIST (proto)) 3117 generate_protocol_references (PROTOCOL_LIST (proto)); 3118 } 3119 } 3120} 3121 3122static void 3123generate_protocols () 3124{ 3125 tree p, tmp_decl, encoding; 3126 tree sc_spec, decl_specs, decl; 3127 tree initlist, protocol_name_expr, refs_decl, refs_expr; 3128 tree cast_type2 = 0; 3129 3130 tmp_decl = build_tmp_function_decl (); 3131 3132 if (! objc_protocol_template) 3133 objc_protocol_template = build_protocol_template (); 3134 3135 /* If a protocol was directly referenced, pull in indirect references. */ 3136 for (p = protocol_chain; p; p = TREE_CHAIN (p)) 3137 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p)) 3138 generate_protocol_references (PROTOCOL_LIST (p)); 3139 3140 for (p = protocol_chain; p; p = TREE_CHAIN (p)) 3141 { 3142 tree nst_methods = PROTOCOL_NST_METHODS (p); 3143 tree cls_methods = PROTOCOL_CLS_METHODS (p); 3144 3145 /* If protocol wasn't referenced, don't generate any code. */ 3146 if (! PROTOCOL_FORWARD_DECL (p)) 3147 continue; 3148 3149 /* Make sure we link in the Protocol class. */ 3150 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME)); 3151 3152 while (nst_methods) 3153 { 3154 if (! METHOD_ENCODING (nst_methods)) 3155 { 3156 hack_method_prototype (nst_methods, tmp_decl); 3157 encoding = encode_method_prototype (nst_methods, tmp_decl); 3158 METHOD_ENCODING (nst_methods) = encoding; 3159 } 3160 nst_methods = TREE_CHAIN (nst_methods); 3161 } 3162 3163 while (cls_methods) 3164 { 3165 if (! METHOD_ENCODING (cls_methods)) 3166 { 3167 hack_method_prototype (cls_methods, tmp_decl); 3168 encoding = encode_method_prototype (cls_methods, tmp_decl); 3169 METHOD_ENCODING (cls_methods) = encoding; 3170 } 3171 3172 cls_methods = TREE_CHAIN (cls_methods); 3173 } 3174 generate_method_descriptors (p); 3175 3176 if (PROTOCOL_LIST (p)) 3177 refs_decl = generate_protocol_list (p); 3178 else 3179 refs_decl = 0; 3180 3181 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */ 3182 3183 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], 3184 NULL_TREE); 3185 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec); 3186 3187 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p), 3188 decl_specs, 1, NULL_TREE, NULL_TREE); 3189 3190 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names); 3191 3192 if (refs_decl) 3193 { 3194 if (!cast_type2) 3195 cast_type2 3196 = groktypename 3197 (build_tree_list (build_tree_list (NULL_TREE, 3198 objc_protocol_template), 3199 build1 (INDIRECT_REF, NULL_TREE, 3200 build1 (INDIRECT_REF, NULL_TREE, 3201 NULL_TREE)))); 3202 3203 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0); 3204 TREE_TYPE (refs_expr) = cast_type2; 3205 } 3206 else 3207 refs_expr = build_int_2 (0, 0); 3208 3209 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set 3210 by generate_method_descriptors, which is called above. */ 3211 initlist = build_protocol_initializer (TREE_TYPE (decl), 3212 protocol_name_expr, refs_expr, 3213 UOBJC_INSTANCE_METHODS_decl, 3214 UOBJC_CLASS_METHODS_decl); 3215 finish_decl (decl, initlist, NULL_TREE); 3216 3217 /* Mark the decl as used to avoid "defined but not used" warning. */ 3218 TREE_USED (decl) = 1; 3219 } 3220} 3221 3222static tree 3223build_protocol_initializer (type, protocol_name, protocol_list, 3224 instance_methods, class_methods) 3225 tree type; 3226 tree protocol_name; 3227 tree protocol_list; 3228 tree instance_methods; 3229 tree class_methods; 3230{ 3231 tree initlist = NULL_TREE, expr; 3232 static tree cast_type = 0; 3233 3234 if (!cast_type) 3235 cast_type 3236 = groktypename 3237 (build_tree_list 3238 (build_tree_list (NULL_TREE, 3239 xref_tag (RECORD_TYPE, 3240 get_identifier (UTAG_CLASS))), 3241 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))); 3242 3243 /* Filling the "isa" in with one allows the runtime system to 3244 detect that the version change...should remove before final release. */ 3245 3246 expr = build_int_2 (PROTOCOL_VERSION, 0); 3247 TREE_TYPE (expr) = cast_type; 3248 initlist = tree_cons (NULL_TREE, expr, initlist); 3249 initlist = tree_cons (NULL_TREE, protocol_name, initlist); 3250 initlist = tree_cons (NULL_TREE, protocol_list, initlist); 3251 3252 if (!instance_methods) 3253 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 3254 else 3255 { 3256 expr = build_unary_op (ADDR_EXPR, instance_methods, 0); 3257 initlist = tree_cons (NULL_TREE, expr, initlist); 3258 } 3259 3260 if (!class_methods) 3261 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 3262 else 3263 { 3264 expr = build_unary_op (ADDR_EXPR, class_methods, 0); 3265 initlist = tree_cons (NULL_TREE, expr, initlist); 3266 } 3267 3268 return build_constructor (type, nreverse (initlist)); 3269} 3270 3271/* struct objc_category { 3272 char *category_name; 3273 char *class_name; 3274 struct objc_method_list *instance_methods; 3275 struct objc_method_list *class_methods; 3276 struct objc_protocol_list *protocols; 3277 }; */ 3278 3279static void 3280build_category_template () 3281{ 3282 tree decl_specs, field_decl, field_decl_chain; 3283 3284 objc_category_template = start_struct (RECORD_TYPE, 3285 get_identifier (UTAG_CATEGORY)); 3286 /* char *category_name; */ 3287 3288 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); 3289 field_decl 3290 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name")); 3291 field_decl 3292 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3293 field_decl_chain = field_decl; 3294 3295 /* char *class_name; */ 3296 3297 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); 3298 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name")); 3299 field_decl 3300 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3301 chainon (field_decl_chain, field_decl); 3302 3303 /* struct objc_method_list *instance_methods; */ 3304 3305 decl_specs = build_tree_list (NULL_TREE, 3306 xref_tag (RECORD_TYPE, 3307 get_identifier (UTAG_METHOD_LIST))); 3308 field_decl 3309 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods")); 3310 field_decl 3311 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3312 chainon (field_decl_chain, field_decl); 3313 3314 /* struct objc_method_list *class_methods; */ 3315 3316 decl_specs = build_tree_list (NULL_TREE, 3317 xref_tag (RECORD_TYPE, 3318 get_identifier (UTAG_METHOD_LIST))); 3319 field_decl 3320 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods")); 3321 field_decl 3322 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3323 chainon (field_decl_chain, field_decl); 3324 3325 /* struct objc_protocol **protocol_list; */ 3326 3327 decl_specs = build_tree_list (NULL_TREE, 3328 xref_tag (RECORD_TYPE, 3329 get_identifier (UTAG_PROTOCOL))); 3330 field_decl 3331 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list")); 3332 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl); 3333 field_decl 3334 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3335 chainon (field_decl_chain, field_decl); 3336 3337 finish_struct (objc_category_template, field_decl_chain, NULL_TREE); 3338} 3339 3340/* struct objc_selector { 3341 void *sel_id; 3342 char *sel_type; 3343 }; */ 3344 3345static void 3346build_selector_template () 3347{ 3348 3349 tree decl_specs, field_decl, field_decl_chain; 3350 3351 objc_selector_template 3352 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR)); 3353 3354 /* void *sel_id; */ 3355 3356 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]); 3357 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id")); 3358 field_decl 3359 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3360 field_decl_chain = field_decl; 3361 3362 /* char *sel_type; */ 3363 3364 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); 3365 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type")); 3366 field_decl 3367 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3368 chainon (field_decl_chain, field_decl); 3369 3370 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE); 3371} 3372 3373/* struct objc_class { 3374 struct objc_class *isa; 3375 struct objc_class *super_class; 3376 char *name; 3377 long version; 3378 long info; 3379 long instance_size; 3380 struct objc_ivar_list *ivars; 3381 struct objc_method_list *methods; 3382 if (flag_next_runtime) 3383 struct objc_cache *cache; 3384 else { 3385 struct sarray *dtable; 3386 struct objc_class *subclass_list; 3387 struct objc_class *sibling_class; 3388 } 3389 struct objc_protocol_list *protocols; 3390 void *gc_object_type; 3391 }; */ 3392 3393static void 3394build_class_template () 3395{ 3396 tree decl_specs, field_decl, field_decl_chain; 3397 3398 objc_class_template 3399 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS)); 3400 3401 /* struct objc_class *isa; */ 3402 3403 decl_specs = build_tree_list (NULL_TREE, objc_class_template); 3404 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa")); 3405 field_decl 3406 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3407 field_decl_chain = field_decl; 3408 3409 /* struct objc_class *super_class; */ 3410 3411 decl_specs = build_tree_list (NULL_TREE, objc_class_template); 3412 field_decl 3413 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class")); 3414 field_decl 3415 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3416 chainon (field_decl_chain, field_decl); 3417 3418 /* char *name; */ 3419 3420 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); 3421 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name")); 3422 field_decl 3423 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3424 chainon (field_decl_chain, field_decl); 3425 3426 /* long version; */ 3427 3428 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); 3429 field_decl = get_identifier ("version"); 3430 field_decl 3431 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3432 chainon (field_decl_chain, field_decl); 3433 3434 /* long info; */ 3435 3436 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); 3437 field_decl = get_identifier ("info"); 3438 field_decl 3439 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3440 chainon (field_decl_chain, field_decl); 3441 3442 /* long instance_size; */ 3443 3444 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); 3445 field_decl = get_identifier ("instance_size"); 3446 field_decl 3447 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3448 chainon (field_decl_chain, field_decl); 3449 3450 /* struct objc_ivar_list *ivars; */ 3451 3452 decl_specs = build_tree_list (NULL_TREE, 3453 xref_tag (RECORD_TYPE, 3454 get_identifier (UTAG_IVAR_LIST))); 3455 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars")); 3456 field_decl 3457 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3458 chainon (field_decl_chain, field_decl); 3459 3460 /* struct objc_method_list *methods; */ 3461 3462 decl_specs = build_tree_list (NULL_TREE, 3463 xref_tag (RECORD_TYPE, 3464 get_identifier (UTAG_METHOD_LIST))); 3465 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods")); 3466 field_decl 3467 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3468 chainon (field_decl_chain, field_decl); 3469 3470 if (flag_next_runtime) 3471 { 3472 /* struct objc_cache *cache; */ 3473 3474 decl_specs = build_tree_list (NULL_TREE, 3475 xref_tag (RECORD_TYPE, 3476 get_identifier ("objc_cache"))); 3477 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache")); 3478 field_decl = grokfield (input_filename, lineno, field_decl, 3479 decl_specs, NULL_TREE); 3480 chainon (field_decl_chain, field_decl); 3481 } 3482 else 3483 { 3484 /* struct sarray *dtable; */ 3485 3486 decl_specs = build_tree_list (NULL_TREE, 3487 xref_tag (RECORD_TYPE, 3488 get_identifier ("sarray"))); 3489 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable")); 3490 field_decl = grokfield (input_filename, lineno, field_decl, 3491 decl_specs, NULL_TREE); 3492 chainon (field_decl_chain, field_decl); 3493 3494 /* struct objc_class *subclass_list; */ 3495 3496 decl_specs = build_tree_list (NULL_TREE, objc_class_template); 3497 field_decl 3498 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list")); 3499 field_decl = grokfield (input_filename, lineno, field_decl, 3500 decl_specs, NULL_TREE); 3501 chainon (field_decl_chain, field_decl); 3502 3503 /* struct objc_class *sibling_class; */ 3504 3505 decl_specs = build_tree_list (NULL_TREE, objc_class_template); 3506 field_decl 3507 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class")); 3508 field_decl = grokfield (input_filename, lineno, field_decl, 3509 decl_specs, NULL_TREE); 3510 chainon (field_decl_chain, field_decl); 3511 } 3512 3513 /* struct objc_protocol **protocol_list; */ 3514 3515 decl_specs = build_tree_list (NULL_TREE, 3516 xref_tag (RECORD_TYPE, 3517 get_identifier (UTAG_PROTOCOL))); 3518 field_decl 3519 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list")); 3520 field_decl 3521 = build1 (INDIRECT_REF, NULL_TREE, field_decl); 3522 field_decl = grokfield (input_filename, lineno, field_decl, 3523 decl_specs, NULL_TREE); 3524 chainon (field_decl_chain, field_decl); 3525 3526 /* void *sel_id; */ 3527 3528 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]); 3529 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id")); 3530 field_decl 3531 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3532 chainon (field_decl_chain, field_decl); 3533 3534 /* void *gc_object_type; */ 3535 3536 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]); 3537 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type")); 3538 field_decl 3539 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); 3540 chainon (field_decl_chain, field_decl); 3541 3542 finish_struct (objc_class_template, field_decl_chain, NULL_TREE); 3543} 3544 3545/* Generate appropriate forward declarations for an implementation. */ 3546 3547static void 3548synth_forward_declarations () 3549{ 3550 tree sc_spec, decl_specs, an_id; 3551 3552 /* extern struct objc_class _OBJC_CLASS_<my_name>; */ 3553 3554 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context); 3555 3556 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]); 3557 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec); 3558 UOBJC_CLASS_decl = define_decl (an_id, decl_specs); 3559 TREE_USED (UOBJC_CLASS_decl) = 1; 3560 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1; 3561 3562 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */ 3563 3564 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS", 3565 implementation_context); 3566 3567 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs); 3568 TREE_USED (UOBJC_METACLASS_decl) = 1; 3569 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1; 3570 3571 /* Pre-build the following entities - for speed/convenience. */ 3572 3573 an_id = get_identifier ("super_class"); 3574 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id); 3575 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id); 3576} 3577 3578static void 3579error_with_ivar (message, decl, rawdecl) 3580 char *message; 3581 tree decl; 3582 tree rawdecl; 3583{ 3584 count_error (0); 3585 3586 report_error_function (DECL_SOURCE_FILE (decl)); 3587 3588 fprintf (stderr, "%s:%d: ", 3589 DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); 3590 bzero (errbuf, BUFSIZE); 3591 fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf)); 3592} 3593 3594#define USERTYPE(t) \ 3595 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \ 3596 || TREE_CODE (t) == ENUMERAL_TYPE) 3597 3598static void 3599check_ivars (inter, imp) 3600 tree inter; 3601 tree imp; 3602{ 3603 tree intdecls = CLASS_IVARS (inter); 3604 tree impdecls = CLASS_IVARS (imp); 3605 tree rawintdecls = CLASS_RAW_IVARS (inter); 3606 tree rawimpdecls = CLASS_RAW_IVARS (imp); 3607 3608 while (1) 3609 { 3610 tree t1, t2; 3611 3612 if (intdecls == 0 && impdecls == 0) 3613 break; 3614 if (intdecls == 0 || impdecls == 0) 3615 { 3616 error ("inconsistent instance variable specification"); 3617 break; 3618 } 3619 3620 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls); 3621 3622 if (!comptypes (t1, t2)) 3623 { 3624 if (DECL_NAME (intdecls) == DECL_NAME (impdecls)) 3625 { 3626 error_with_ivar ("conflicting instance variable type", 3627 impdecls, rawimpdecls); 3628 error_with_ivar ("previous declaration of", 3629 intdecls, rawintdecls); 3630 } 3631 else /* both the type and the name don't match */ 3632 { 3633 error ("inconsistent instance variable specification"); 3634 break; 3635 } 3636 } 3637 3638 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls)) 3639 { 3640 error_with_ivar ("conflicting instance variable name", 3641 impdecls, rawimpdecls); 3642 error_with_ivar ("previous declaration of", 3643 intdecls, rawintdecls); 3644 } 3645 3646 intdecls = TREE_CHAIN (intdecls); 3647 impdecls = TREE_CHAIN (impdecls); 3648 rawintdecls = TREE_CHAIN (rawintdecls); 3649 rawimpdecls = TREE_CHAIN (rawimpdecls); 3650 } 3651} 3652 3653/* Set super_type to the data type node for struct objc_super *, 3654 first defining struct objc_super itself. 3655 This needs to be done just once per compilation. */ 3656 3657static tree 3658build_super_template () 3659{ 3660 tree record, decl_specs, field_decl, field_decl_chain; 3661 3662 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER)); 3663 3664 /* struct objc_object *self; */ 3665 3666 decl_specs = build_tree_list (NULL_TREE, objc_object_reference); 3667 field_decl = get_identifier ("self"); 3668 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl); 3669 field_decl = grokfield (input_filename, lineno, 3670 field_decl, decl_specs, NULL_TREE); 3671 field_decl_chain = field_decl; 3672 3673 /* struct objc_class *class; */ 3674 3675 decl_specs = get_identifier (UTAG_CLASS); 3676 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs)); 3677 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class")); 3678 3679 field_decl = grokfield (input_filename, lineno, 3680 field_decl, decl_specs, NULL_TREE); 3681 chainon (field_decl_chain, field_decl); 3682 3683 finish_struct (record, field_decl_chain, NULL_TREE); 3684 3685 /* `struct objc_super *' */ 3686 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE, 3687 record), 3688 build1 (INDIRECT_REF, 3689 NULL_TREE, NULL_TREE))); 3690 return record; 3691} 3692 3693/* struct objc_ivar { 3694 char *ivar_name; 3695 char *ivar_type; 3696 int ivar_offset; 3697 }; */ 3698 3699static tree 3700build_ivar_template () 3701{ 3702 tree objc_ivar_id, objc_ivar_record; 3703 tree decl_specs, field_decl, field_decl_chain; 3704 3705 objc_ivar_id = get_identifier (UTAG_IVAR); 3706 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id); 3707 3708 /* char *ivar_name; */ 3709 3710 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); 3711 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name")); 3712 3713 field_decl = grokfield (input_filename, lineno, field_decl, 3714 decl_specs, NULL_TREE); 3715 field_decl_chain = field_decl; 3716 3717 /* char *ivar_type; */ 3718 3719 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); 3720 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type")); 3721 3722 field_decl = grokfield (input_filename, lineno, field_decl, 3723 decl_specs, NULL_TREE); 3724 chainon (field_decl_chain, field_decl); 3725 3726 /* int ivar_offset; */ 3727 3728 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]); 3729 field_decl = get_identifier ("ivar_offset"); 3730 3731 field_decl = grokfield (input_filename, lineno, field_decl, 3732 decl_specs, NULL_TREE); 3733 chainon (field_decl_chain, field_decl); 3734 3735 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE); 3736 3737 return objc_ivar_record; 3738} 3739 3740/* struct { 3741 int ivar_count; 3742 struct objc_ivar ivar_list[ivar_count]; 3743 }; */ 3744 3745static tree 3746build_ivar_list_template (list_type, size) 3747 tree list_type; 3748 int size; 3749{ 3750 tree objc_ivar_list_record; 3751 tree decl_specs, field_decl, field_decl_chain; 3752 3753 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE); 3754 3755 /* int ivar_count; */ 3756 3757 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]); 3758 field_decl = get_identifier ("ivar_count"); 3759 3760 field_decl = grokfield (input_filename, lineno, field_decl, 3761 decl_specs, NULL_TREE); 3762 field_decl_chain = field_decl; 3763 3764 /* struct objc_ivar ivar_list[]; */ 3765 3766 decl_specs = build_tree_list (NULL_TREE, list_type); 3767 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"), 3768 build_int_2 (size, 0)); 3769 3770 field_decl = grokfield (input_filename, lineno, 3771 field_decl, decl_specs, NULL_TREE); 3772 chainon (field_decl_chain, field_decl); 3773 3774 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE); 3775 3776 return objc_ivar_list_record; 3777} 3778 3779/* struct { 3780 int method_next; 3781 int method_count; 3782 struct objc_method method_list[method_count]; 3783 }; */ 3784 3785static tree 3786build_method_list_template (list_type, size) 3787 tree list_type; 3788 int size; 3789{ 3790 tree objc_ivar_list_record; 3791 tree decl_specs, field_decl, field_decl_chain; 3792 3793 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE); 3794 3795 /* int method_next; */ 3796 3797 decl_specs 3798 = build_tree_list 3799 (NULL_TREE, 3800 xref_tag (RECORD_TYPE, 3801 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))); 3802 field_decl 3803 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next")); 3804 field_decl = grokfield (input_filename, lineno, field_decl, 3805 decl_specs, NULL_TREE); 3806 field_decl_chain = field_decl; 3807 3808 /* int method_count; */ 3809 3810 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]); 3811 field_decl = get_identifier ("method_count"); 3812 3813 field_decl = grokfield (input_filename, lineno, 3814 field_decl, decl_specs, NULL_TREE); 3815 chainon (field_decl_chain, field_decl); 3816 3817 /* struct objc_method method_list[]; */ 3818 3819 decl_specs = build_tree_list (NULL_TREE, list_type); 3820 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"), 3821 build_int_2 (size, 0)); 3822 3823 field_decl = grokfield (input_filename, lineno, 3824 field_decl, decl_specs, NULL_TREE); 3825 chainon (field_decl_chain, field_decl); 3826 3827 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE); 3828 3829 return objc_ivar_list_record; 3830} 3831 3832static tree 3833build_ivar_list_initializer (type, field_decl) 3834 tree type; 3835 tree field_decl; 3836{ 3837 tree initlist = NULL_TREE; 3838 3839 do 3840 { 3841 tree ivar = NULL_TREE; 3842 3843 /* Set name. */ 3844 if (DECL_NAME (field_decl)) 3845 ivar = tree_cons (NULL_TREE, 3846 add_objc_string (DECL_NAME (field_decl), 3847 meth_var_names), 3848 ivar); 3849 else 3850 /* Unnamed bit-field ivar (yuck). */ 3851 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar); 3852 3853 /* Set type. */ 3854 encode_field_decl (field_decl, 3855 obstack_object_size (&util_obstack), 3856 OBJC_ENCODE_DONT_INLINE_DEFS); 3857 3858 /* Null terminate string. */ 3859 obstack_1grow (&util_obstack, 0); 3860 ivar 3861 = tree_cons 3862 (NULL_TREE, 3863 add_objc_string (get_identifier (obstack_finish (&util_obstack)), 3864 meth_var_types), 3865 ivar); 3866 obstack_free (&util_obstack, util_firstobj); 3867 3868 /* set offset */ 3869 ivar 3870 = tree_cons 3871 (NULL_TREE, 3872 build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)) 3873 / BITS_PER_UNIT), 3874 0), 3875 ivar); 3876 3877 initlist = tree_cons (NULL_TREE, 3878 build_constructor (type, nreverse (ivar)), 3879 initlist); 3880 3881 field_decl = TREE_CHAIN (field_decl); 3882 } 3883 while (field_decl); 3884 3885 return build_constructor (build_array_type (type, 0), nreverse (initlist)); 3886} 3887 3888static tree 3889generate_ivars_list (type, name, size, list) 3890 tree type; 3891 char *name; 3892 int size; 3893 tree list; 3894{ 3895 tree sc_spec, decl_specs, decl, initlist; 3896 3897 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 3898 decl_specs = tree_cons (NULL_TREE, type, sc_spec); 3899 3900 decl = start_decl (synth_id_with_class_suffix (name, implementation_context), 3901 decl_specs, 1, NULL_TREE, NULL_TREE); 3902 3903 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0)); 3904 initlist = tree_cons (NULL_TREE, list, initlist); 3905 3906 finish_decl (decl, 3907 build_constructor (TREE_TYPE (decl), nreverse (initlist)), 3908 NULL_TREE); 3909 3910 return decl; 3911} 3912 3913static void 3914generate_ivar_lists () 3915{ 3916 tree initlist, ivar_list_template, chain; 3917 tree cast, variable_length_type; 3918 int size; 3919 3920 generating_instance_variables = 1; 3921 3922 if (!objc_ivar_template) 3923 objc_ivar_template = build_ivar_template (); 3924 3925 cast 3926 = build_tree_list 3927 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, 3928 get_identifier (UTAG_IVAR_LIST))), 3929 NULL_TREE); 3930 variable_length_type = groktypename (cast); 3931 3932 /* Only generate class variables for the root of the inheritance 3933 hierarchy since these will be the same for every class. */ 3934 3935 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE 3936 && (chain = TYPE_FIELDS (objc_class_template))) 3937 { 3938 size = list_length (chain); 3939 3940 ivar_list_template = build_ivar_list_template (objc_ivar_template, size); 3941 initlist = build_ivar_list_initializer (objc_ivar_template, chain); 3942 3943 UOBJC_CLASS_VARIABLES_decl 3944 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES", 3945 size, initlist); 3946 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type; 3947 } 3948 else 3949 UOBJC_CLASS_VARIABLES_decl = 0; 3950 3951 chain = CLASS_IVARS (implementation_template); 3952 if (chain) 3953 { 3954 size = list_length (chain); 3955 ivar_list_template = build_ivar_list_template (objc_ivar_template, size); 3956 initlist = build_ivar_list_initializer (objc_ivar_template, chain); 3957 3958 UOBJC_INSTANCE_VARIABLES_decl 3959 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES", 3960 size, initlist); 3961 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type; 3962 } 3963 else 3964 UOBJC_INSTANCE_VARIABLES_decl = 0; 3965 3966 generating_instance_variables = 0; 3967} 3968 3969static tree 3970build_dispatch_table_initializer (type, entries) 3971 tree type; 3972 tree entries; 3973{ 3974 tree initlist = NULL_TREE; 3975 3976 do 3977 { 3978 tree elemlist = NULL_TREE; 3979 3980 elemlist = tree_cons (NULL_TREE, 3981 build_selector (METHOD_SEL_NAME (entries)), 3982 NULL_TREE); 3983 3984 elemlist = tree_cons (NULL_TREE, 3985 add_objc_string (METHOD_ENCODING (entries), 3986 meth_var_types), 3987 elemlist); 3988 3989 elemlist = tree_cons (NULL_TREE, 3990 build_unary_op (ADDR_EXPR, 3991 METHOD_DEFINITION (entries), 1), 3992 elemlist); 3993 3994 initlist = tree_cons (NULL_TREE, 3995 build_constructor (type, nreverse (elemlist)), 3996 initlist); 3997 3998 entries = TREE_CHAIN (entries); 3999 } 4000 while (entries); 4001 4002 return build_constructor (build_array_type (type, 0), nreverse (initlist)); 4003} 4004 4005/* To accomplish method prototyping without generating all kinds of 4006 inane warnings, the definition of the dispatch table entries were 4007 changed from: 4008 4009 struct objc_method { SEL _cmd; ...; id (*_imp)(); }; 4010 to: 4011 struct objc_method { SEL _cmd; ...; void *_imp; }; */ 4012 4013static tree 4014build_method_template () 4015{ 4016 tree _SLT_record; 4017 tree decl_specs, field_decl, field_decl_chain; 4018 4019 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD)); 4020 4021#ifdef OBJC_INT_SELECTORS 4022 /* unsigned int _cmd; */ 4023 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], 4024 NULL_TREE); 4025 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); 4026 field_decl = get_identifier ("_cmd"); 4027#else /* not OBJC_INT_SELECTORS */ 4028 /* struct objc_selector *_cmd; */ 4029 decl_specs = tree_cons (NULL_TREE, 4030 xref_tag (RECORD_TYPE, 4031 get_identifier (TAG_SELECTOR)), 4032 NULL_TREE); 4033 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd")); 4034#endif /* not OBJC_INT_SELECTORS */ 4035 4036 field_decl = grokfield (input_filename, lineno, field_decl, 4037 decl_specs, NULL_TREE); 4038 field_decl_chain = field_decl; 4039 4040 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE); 4041 field_decl = build1 (INDIRECT_REF, NULL_TREE, 4042 get_identifier ("method_types")); 4043 field_decl = grokfield (input_filename, lineno, field_decl, 4044 decl_specs, NULL_TREE); 4045 chainon (field_decl_chain, field_decl); 4046 4047 /* void *_imp; */ 4048 4049 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE); 4050 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp")); 4051 field_decl = grokfield (input_filename, lineno, field_decl, 4052 decl_specs, NULL_TREE); 4053 chainon (field_decl_chain, field_decl); 4054 4055 finish_struct (_SLT_record, field_decl_chain, NULL_TREE); 4056 4057 return _SLT_record; 4058} 4059 4060 4061static tree 4062generate_dispatch_table (type, name, size, list) 4063 tree type; 4064 char *name; 4065 int size; 4066 tree list; 4067{ 4068 tree sc_spec, decl_specs, decl, initlist; 4069 4070 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 4071 decl_specs = tree_cons (NULL_TREE, type, sc_spec); 4072 4073 decl = start_decl (synth_id_with_class_suffix (name, implementation_context), 4074 decl_specs, 1, NULL_TREE, NULL_TREE); 4075 4076 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); 4077 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist); 4078 initlist = tree_cons (NULL_TREE, list, initlist); 4079 4080 finish_decl (decl, 4081 build_constructor (TREE_TYPE (decl), nreverse (initlist)), 4082 NULL_TREE); 4083 4084 return decl; 4085} 4086 4087static void 4088generate_dispatch_tables () 4089{ 4090 tree initlist, chain, method_list_template; 4091 tree cast, variable_length_type; 4092 int size; 4093 4094 if (!objc_method_template) 4095 objc_method_template = build_method_template (); 4096 4097 cast 4098 = build_tree_list 4099 (build_tree_list (NULL_TREE, 4100 xref_tag (RECORD_TYPE, 4101 get_identifier (UTAG_METHOD_LIST))), 4102 NULL_TREE); 4103 4104 variable_length_type = groktypename (cast); 4105 4106 chain = CLASS_CLS_METHODS (implementation_context); 4107 if (chain) 4108 { 4109 size = list_length (chain); 4110 4111 method_list_template 4112 = build_method_list_template (objc_method_template, size); 4113 initlist 4114 = build_dispatch_table_initializer (objc_method_template, chain); 4115 4116 UOBJC_CLASS_METHODS_decl 4117 = generate_dispatch_table (method_list_template, 4118 ((TREE_CODE (implementation_context) 4119 == CLASS_IMPLEMENTATION_TYPE) 4120 ? "_OBJC_CLASS_METHODS" 4121 : "_OBJC_CATEGORY_CLASS_METHODS"), 4122 size, initlist); 4123 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type; 4124 } 4125 else 4126 UOBJC_CLASS_METHODS_decl = 0; 4127 4128 chain = CLASS_NST_METHODS (implementation_context); 4129 if (chain) 4130 { 4131 size = list_length (chain); 4132 4133 method_list_template 4134 = build_method_list_template (objc_method_template, size); 4135 initlist 4136 = build_dispatch_table_initializer (objc_method_template, chain); 4137 4138 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) 4139 UOBJC_INSTANCE_METHODS_decl 4140 = generate_dispatch_table (method_list_template, 4141 "_OBJC_INSTANCE_METHODS", 4142 size, initlist); 4143 else 4144 /* We have a category. */ 4145 UOBJC_INSTANCE_METHODS_decl 4146 = generate_dispatch_table (method_list_template, 4147 "_OBJC_CATEGORY_INSTANCE_METHODS", 4148 size, initlist); 4149 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type; 4150 } 4151 else 4152 UOBJC_INSTANCE_METHODS_decl = 0; 4153} 4154 4155static tree 4156generate_protocol_list (i_or_p) 4157 tree i_or_p; 4158{ 4159 static tree cast_type = 0; 4160 tree initlist, decl_specs, sc_spec; 4161 tree refs_decl, expr_decl, lproto, e, plist; 4162 int size = 0; 4163 4164 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE 4165 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE) 4166 plist = CLASS_PROTOCOL_LIST (i_or_p); 4167 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE) 4168 plist = PROTOCOL_LIST (i_or_p); 4169 else 4170 abort (); 4171 4172 if (!cast_type) 4173 cast_type 4174 = groktypename 4175 (build_tree_list 4176 (build_tree_list (NULL_TREE, 4177 xref_tag (RECORD_TYPE, 4178 get_identifier (UTAG_PROTOCOL))), 4179 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))); 4180 4181 /* Compute size. */ 4182 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) 4183 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE 4184 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto))) 4185 size++; 4186 4187 /* Build initializer. */ 4188 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE); 4189 4190 e = build_int_2 (size, 0); 4191 TREE_TYPE (e) = cast_type; 4192 initlist = tree_cons (NULL_TREE, e, initlist); 4193 4194 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) 4195 { 4196 tree pval = TREE_VALUE (lproto); 4197 4198 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE 4199 && PROTOCOL_FORWARD_DECL (pval)) 4200 { 4201 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0); 4202 initlist = tree_cons (NULL_TREE, e, initlist); 4203 } 4204 } 4205 4206 /* static struct objc_protocol *refs[n]; */ 4207 4208 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 4209 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE, 4210 get_identifier (UTAG_PROTOCOL)), 4211 sc_spec); 4212 4213 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE) 4214 expr_decl = build_nt (ARRAY_REF, 4215 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS", 4216 i_or_p), 4217 build_int_2 (size + 2, 0)); 4218 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE) 4219 expr_decl = build_nt (ARRAY_REF, 4220 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS", 4221 i_or_p), 4222 build_int_2 (size + 2, 0)); 4223 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE) 4224 expr_decl 4225 = build_nt (ARRAY_REF, 4226 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS", 4227 i_or_p), 4228 build_int_2 (size + 2, 0)); 4229 else 4230 abort (); 4231 4232 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl); 4233 4234 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); 4235 4236 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl), 4237 nreverse (initlist)), 4238 NULL_TREE); 4239 4240 return refs_decl; 4241} 4242 4243static tree 4244build_category_initializer (type, cat_name, class_name, 4245 instance_methods, class_methods, protocol_list) 4246 tree type; 4247 tree cat_name; 4248 tree class_name; 4249 tree instance_methods; 4250 tree class_methods; 4251 tree protocol_list; 4252{ 4253 tree initlist = NULL_TREE, expr; 4254 4255 initlist = tree_cons (NULL_TREE, cat_name, initlist); 4256 initlist = tree_cons (NULL_TREE, class_name, initlist); 4257 4258 if (!instance_methods) 4259 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4260 else 4261 { 4262 expr = build_unary_op (ADDR_EXPR, instance_methods, 0); 4263 initlist = tree_cons (NULL_TREE, expr, initlist); 4264 } 4265 if (!class_methods) 4266 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4267 else 4268 { 4269 expr = build_unary_op (ADDR_EXPR, class_methods, 0); 4270 initlist = tree_cons (NULL_TREE, expr, initlist); 4271 } 4272 4273 /* protocol_list = */ 4274 if (!protocol_list) 4275 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4276 else 4277 { 4278 static tree cast_type2; 4279 4280 if (!cast_type2) 4281 cast_type2 4282 = groktypename 4283 (build_tree_list 4284 (build_tree_list (NULL_TREE, 4285 xref_tag (RECORD_TYPE, 4286 get_identifier (UTAG_PROTOCOL))), 4287 build1 (INDIRECT_REF, NULL_TREE, 4288 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)))); 4289 4290 expr = build_unary_op (ADDR_EXPR, protocol_list, 0); 4291 TREE_TYPE (expr) = cast_type2; 4292 initlist = tree_cons (NULL_TREE, expr, initlist); 4293 } 4294 4295 return build_constructor (type, nreverse (initlist)); 4296} 4297 4298/* struct objc_class { 4299 struct objc_class *isa; 4300 struct objc_class *super_class; 4301 char *name; 4302 long version; 4303 long info; 4304 long instance_size; 4305 struct objc_ivar_list *ivars; 4306 struct objc_method_list *methods; 4307 if (flag_next_runtime) 4308 struct objc_cache *cache; 4309 else { 4310 struct sarray *dtable; 4311 struct objc_class *subclass_list; 4312 struct objc_class *sibling_class; 4313 } 4314 struct objc_protocol_list *protocols; 4315 void *gc_object_type; 4316 }; */ 4317 4318static tree 4319build_shared_structure_initializer (type, isa, super, name, size, status, 4320 dispatch_table, ivar_list, protocol_list) 4321 tree type; 4322 tree isa; 4323 tree super; 4324 tree name; 4325 tree size; 4326 int status; 4327 tree dispatch_table; 4328 tree ivar_list; 4329 tree protocol_list; 4330{ 4331 tree initlist = NULL_TREE, expr; 4332 4333 /* isa = */ 4334 initlist = tree_cons (NULL_TREE, isa, initlist); 4335 4336 /* super_class = */ 4337 initlist = tree_cons (NULL_TREE, super, initlist); 4338 4339 /* name = */ 4340 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist); 4341 4342 /* version = */ 4343 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4344 4345 /* info = */ 4346 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist); 4347 4348 /* instance_size = */ 4349 initlist = tree_cons (NULL_TREE, size, initlist); 4350 4351 /* objc_ivar_list = */ 4352 if (!ivar_list) 4353 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4354 else 4355 { 4356 expr = build_unary_op (ADDR_EXPR, ivar_list, 0); 4357 initlist = tree_cons (NULL_TREE, expr, initlist); 4358 } 4359 4360 /* objc_method_list = */ 4361 if (!dispatch_table) 4362 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4363 else 4364 { 4365 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0); 4366 initlist = tree_cons (NULL_TREE, expr, initlist); 4367 } 4368 4369 if (flag_next_runtime) 4370 /* method_cache = */ 4371 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4372 else 4373 { 4374 /* dtable = */ 4375 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4376 4377 /* subclass_list = */ 4378 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4379 4380 /* sibling_class = */ 4381 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4382 } 4383 4384 /* protocol_list = */ 4385 if (! protocol_list) 4386 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4387 else 4388 { 4389 static tree cast_type2; 4390 4391 if (!cast_type2) 4392 cast_type2 4393 = groktypename 4394 (build_tree_list 4395 (build_tree_list (NULL_TREE, 4396 xref_tag (RECORD_TYPE, 4397 get_identifier (UTAG_PROTOCOL))), 4398 build1 (INDIRECT_REF, NULL_TREE, 4399 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)))); 4400 4401 expr = build_unary_op (ADDR_EXPR, protocol_list, 0); 4402 TREE_TYPE (expr) = cast_type2; 4403 initlist = tree_cons (NULL_TREE, expr, initlist); 4404 } 4405 4406 /* gc_object_type = NULL */ 4407 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); 4408 4409 return build_constructor (type, nreverse (initlist)); 4410} 4411 4412/* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */ 4413 4414static void 4415generate_category (cat) 4416 tree cat; 4417{ 4418 tree sc_spec, decl_specs, decl; 4419 tree initlist, cat_name_expr, class_name_expr; 4420 tree protocol_decl, category; 4421 4422 add_class_reference (CLASS_NAME (cat)); 4423 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names); 4424 4425 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names); 4426 4427 category = CLASS_CATEGORY_LIST (implementation_template); 4428 4429 /* find the category interface from the class it is associated with */ 4430 while (category) 4431 { 4432 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category)) 4433 break; 4434 category = CLASS_CATEGORY_LIST (category); 4435 } 4436 4437 if (category && CLASS_PROTOCOL_LIST (category)) 4438 { 4439 generate_protocol_references (CLASS_PROTOCOL_LIST (category)); 4440 protocol_decl = generate_protocol_list (category); 4441 } 4442 else 4443 protocol_decl = 0; 4444 4445 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 4446 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec); 4447 4448 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY", 4449 implementation_context), 4450 decl_specs, 1, NULL_TREE, NULL_TREE); 4451 4452 initlist = build_category_initializer (TREE_TYPE (decl), 4453 cat_name_expr, class_name_expr, 4454 UOBJC_INSTANCE_METHODS_decl, 4455 UOBJC_CLASS_METHODS_decl, 4456 protocol_decl); 4457 4458 TREE_USED (decl) = 1; 4459 finish_decl (decl, initlist, NULL_TREE); 4460} 4461 4462/* static struct objc_class _OBJC_METACLASS_Foo={ ... }; 4463 static struct objc_class _OBJC_CLASS_Foo={ ... }; */ 4464 4465static void 4466generate_shared_structures () 4467{ 4468 tree sc_spec, decl_specs, decl; 4469 tree name_expr, super_expr, root_expr; 4470 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE; 4471 tree cast_type, initlist, protocol_decl; 4472 4473 my_super_id = CLASS_SUPER_NAME (implementation_template); 4474 if (my_super_id) 4475 { 4476 add_class_reference (my_super_id); 4477 4478 /* Compute "my_root_id" - this is required for code generation. 4479 the "isa" for all meta class structures points to the root of 4480 the inheritance hierarchy (e.g. "__Object")... */ 4481 my_root_id = my_super_id; 4482 do 4483 { 4484 tree my_root_int = lookup_interface (my_root_id); 4485 4486 if (my_root_int && CLASS_SUPER_NAME (my_root_int)) 4487 my_root_id = CLASS_SUPER_NAME (my_root_int); 4488 else 4489 break; 4490 } 4491 while (1); 4492 } 4493 else 4494 /* No super class. */ 4495 my_root_id = CLASS_NAME (implementation_template); 4496 4497 cast_type 4498 = groktypename (build_tree_list (build_tree_list (NULL_TREE, 4499 objc_class_template), 4500 build1 (INDIRECT_REF, 4501 NULL_TREE, NULL_TREE))); 4502 4503 name_expr = add_objc_string (CLASS_NAME (implementation_template), 4504 class_names); 4505 4506 /* Install class `isa' and `super' pointers at runtime. */ 4507 if (my_super_id) 4508 { 4509 super_expr = add_objc_string (my_super_id, class_names); 4510 super_expr = build_c_cast (cast_type, super_expr); /* cast! */ 4511 } 4512 else 4513 super_expr = build_int_2 (0, 0); 4514 4515 root_expr = add_objc_string (my_root_id, class_names); 4516 root_expr = build_c_cast (cast_type, root_expr); /* cast! */ 4517 4518 if (CLASS_PROTOCOL_LIST (implementation_template)) 4519 { 4520 generate_protocol_references 4521 (CLASS_PROTOCOL_LIST (implementation_template)); 4522 protocol_decl = generate_protocol_list (implementation_template); 4523 } 4524 else 4525 protocol_decl = 0; 4526 4527 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */ 4528 4529 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]); 4530 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec); 4531 4532 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1, 4533 NULL_TREE, NULL_TREE); 4534 4535 initlist 4536 = build_shared_structure_initializer 4537 (TREE_TYPE (decl), 4538 root_expr, super_expr, name_expr, 4539 build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) 4540 / BITS_PER_UNIT), 4541 0), 4542 2 /*CLS_META*/, 4543 UOBJC_CLASS_METHODS_decl, 4544 UOBJC_CLASS_VARIABLES_decl, 4545 protocol_decl); 4546 4547 finish_decl (decl, initlist, NULL_TREE); 4548 4549 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */ 4550 4551 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1, 4552 NULL_TREE, NULL_TREE); 4553 4554 initlist 4555 = build_shared_structure_initializer 4556 (TREE_TYPE (decl), 4557 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0), 4558 super_expr, name_expr, 4559 build_int_2 4560 ((TREE_INT_CST_LOW 4561 (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) 4562 / BITS_PER_UNIT), 4563 0), 4564 1 /*CLS_FACTORY*/, 4565 UOBJC_INSTANCE_METHODS_decl, 4566 UOBJC_INSTANCE_VARIABLES_decl, 4567 protocol_decl); 4568 4569 finish_decl (decl, initlist, NULL_TREE); 4570} 4571 4572static tree 4573synth_id_with_class_suffix (preamble, ctxt) 4574 char *preamble; 4575 tree ctxt; 4576{ 4577 char *string; 4578 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE 4579 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE) 4580 { 4581 char *class_name 4582 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); 4583 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3); 4584 sprintf (string, "%s_%s", preamble, 4585 IDENTIFIER_POINTER (CLASS_NAME (ctxt))); 4586 } 4587 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE 4588 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE) 4589 { 4590 /* We have a category. */ 4591 char *class_name 4592 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); 4593 char *class_super_name 4594 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)); 4595 string = (char *) alloca (strlen (preamble) 4596 + strlen (class_name) 4597 + strlen (class_super_name) 4598 + 3); 4599 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name); 4600 } 4601 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE) 4602 { 4603 char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt)); 4604 string 4605 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3); 4606 sprintf (string, "%s_%s", preamble, protocol_name); 4607 } 4608 else 4609 abort (); 4610 4611 return get_identifier (string); 4612} 4613 4614static int 4615is_objc_type_qualifier (node) 4616 tree node; 4617{ 4618 return (TREE_CODE (node) == IDENTIFIER_NODE 4619 && (node == ridpointers [(int) RID_CONST] 4620 || node == ridpointers [(int) RID_VOLATILE] 4621 || node == ridpointers [(int) RID_IN] 4622 || node == ridpointers [(int) RID_OUT] 4623 || node == ridpointers [(int) RID_INOUT] 4624 || node == ridpointers [(int) RID_BYCOPY] 4625 || node == ridpointers [(int) RID_BYREF] 4626 || node == ridpointers [(int) RID_ONEWAY])); 4627} 4628 4629/* If type is empty or only type qualifiers are present, add default 4630 type of id (otherwise grokdeclarator will default to int). */ 4631 4632static tree 4633adjust_type_for_id_default (type) 4634 tree type; 4635{ 4636 tree declspecs, chain; 4637 4638 if (!type) 4639 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference), 4640 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)); 4641 4642 declspecs = TREE_PURPOSE (type); 4643 4644 /* Determine if a typespec is present. */ 4645 for (chain = declspecs; 4646 chain; 4647 chain = TREE_CHAIN (chain)) 4648 { 4649 if (!is_objc_type_qualifier (TREE_VALUE (chain))) 4650 return type; 4651 } 4652 4653 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference, 4654 declspecs), 4655 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)); 4656} 4657 4658/* Usage: 4659 keyworddecl: 4660 selector ':' '(' typename ')' identifier 4661 4662 Purpose: 4663 Transform an Objective-C keyword argument into 4664 the C equivalent parameter declarator. 4665 4666 In: key_name, an "identifier_node" (optional). 4667 arg_type, a "tree_list" (optional). 4668 arg_name, an "identifier_node". 4669 4670 Note: It would be really nice to strongly type the preceding 4671 arguments in the function prototype; however, then I 4672 could not use the "accessor" macros defined in "tree.h". 4673 4674 Out: an instance of "keyword_decl". */ 4675 4676tree 4677build_keyword_decl (key_name, arg_type, arg_name) 4678 tree key_name; 4679 tree arg_type; 4680 tree arg_name; 4681{ 4682 tree keyword_decl; 4683 4684 /* If no type is specified, default to "id". */ 4685 arg_type = adjust_type_for_id_default (arg_type); 4686 4687 keyword_decl = make_node (KEYWORD_DECL); 4688 4689 TREE_TYPE (keyword_decl) = arg_type; 4690 KEYWORD_ARG_NAME (keyword_decl) = arg_name; 4691 KEYWORD_KEY_NAME (keyword_decl) = key_name; 4692 4693 return keyword_decl; 4694} 4695 4696/* Given a chain of keyword_decl's, synthesize the full keyword selector. */ 4697 4698static tree 4699build_keyword_selector (selector) 4700 tree selector; 4701{ 4702 int len = 0; 4703 tree key_chain, key_name; 4704 char *buf; 4705 4706 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain)) 4707 { 4708 if (TREE_CODE (selector) == KEYWORD_DECL) 4709 key_name = KEYWORD_KEY_NAME (key_chain); 4710 else if (TREE_CODE (selector) == TREE_LIST) 4711 key_name = TREE_PURPOSE (key_chain); 4712 else 4713 abort (); 4714 4715 if (key_name) 4716 len += IDENTIFIER_LENGTH (key_name) + 1; 4717 else 4718 /* Just a ':' arg. */ 4719 len++; 4720 } 4721 4722 buf = (char *)alloca (len + 1); 4723 bzero (buf, len + 1); 4724 4725 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain)) 4726 { 4727 if (TREE_CODE (selector) == KEYWORD_DECL) 4728 key_name = KEYWORD_KEY_NAME (key_chain); 4729 else if (TREE_CODE (selector) == TREE_LIST) 4730 key_name = TREE_PURPOSE (key_chain); 4731 else 4732 abort (); 4733 4734 if (key_name) 4735 strcat (buf, IDENTIFIER_POINTER (key_name)); 4736 strcat (buf, ":"); 4737 } 4738 4739 return get_identifier (buf); 4740} 4741 4742/* Used for declarations and definitions. */ 4743 4744tree 4745build_method_decl (code, ret_type, selector, add_args) 4746 enum tree_code code; 4747 tree ret_type; 4748 tree selector; 4749 tree add_args; 4750{ 4751 tree method_decl; 4752 4753 /* If no type is specified, default to "id". */ 4754 ret_type = adjust_type_for_id_default (ret_type); 4755 4756 method_decl = make_node (code); 4757 TREE_TYPE (method_decl) = ret_type; 4758 4759 /* If we have a keyword selector, create an identifier_node that 4760 represents the full selector name (`:' included)... */ 4761 if (TREE_CODE (selector) == KEYWORD_DECL) 4762 { 4763 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector); 4764 METHOD_SEL_ARGS (method_decl) = selector; 4765 METHOD_ADD_ARGS (method_decl) = add_args; 4766 } 4767 else 4768 { 4769 METHOD_SEL_NAME (method_decl) = selector; 4770 METHOD_SEL_ARGS (method_decl) = NULL_TREE; 4771 METHOD_ADD_ARGS (method_decl) = NULL_TREE; 4772 } 4773 4774 return method_decl; 4775} 4776 4777#define METHOD_DEF 0 4778#define METHOD_REF 1 4779 4780/* Used by `build_message_expr' and `comp_method_types'. Return an 4781 argument list for method METH. CONTEXT is either METHOD_DEF or 4782 METHOD_REF, saying whether we are trying to define a method or call 4783 one. SUPERFLAG says this is for a send to super; this makes a 4784 difference for the NeXT calling sequence in which the lookup and 4785 the method call are done together. */ 4786 4787static tree 4788get_arg_type_list (meth, context, superflag) 4789 tree meth; 4790 int context; 4791 int superflag; 4792{ 4793 tree arglist, akey; 4794 4795 /* Receiver type. */ 4796 if (flag_next_runtime && superflag) 4797 arglist = build_tree_list (NULL_TREE, super_type); 4798 else if (context == METHOD_DEF) 4799 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl)); 4800 else 4801 arglist = build_tree_list (NULL_TREE, id_type); 4802 4803 /* Selector type - will eventually change to `int'. */ 4804 chainon (arglist, build_tree_list (NULL_TREE, selector_type)); 4805 4806 /* Build a list of argument types. */ 4807 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey)) 4808 { 4809 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey)); 4810 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl))); 4811 } 4812 4813 if (METHOD_ADD_ARGS (meth) == (tree)1) 4814 /* We have a `, ...' immediately following the selector, 4815 finalize the arglist...simulate get_parm_info (0). */ 4816 ; 4817 else if (METHOD_ADD_ARGS (meth)) 4818 { 4819 /* we have a variable length selector */ 4820 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth)); 4821 chainon (arglist, add_arg_list); 4822 } 4823 else 4824 /* finalize the arglist...simulate get_parm_info (1) */ 4825 chainon (arglist, build_tree_list (NULL_TREE, void_type_node)); 4826 4827 return arglist; 4828} 4829 4830static tree 4831check_duplicates (hsh) 4832 hash hsh; 4833{ 4834 tree meth = NULL_TREE; 4835 4836 if (hsh) 4837 { 4838 meth = hsh->key; 4839 4840 if (hsh->list) 4841 { 4842 /* We have two methods with the same name and different types. */ 4843 attr loop; 4844 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+'; 4845 4846 warning ("multiple declarations for method `%s'", 4847 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth))); 4848 4849 warn_with_method ("using", type, meth); 4850 for (loop = hsh->list; loop; loop = loop->next) 4851 warn_with_method ("also found", type, loop->value); 4852 } 4853 } 4854 return meth; 4855} 4856 4857/* If RECEIVER is a class reference, return the identifier node for the 4858 referenced class. RECEIVER is created by get_class_reference, so we 4859 check the exact form created depending on which runtimes are used. */ 4860 4861static tree 4862receiver_is_class_object (receiver) 4863 tree receiver; 4864{ 4865 tree chain, exp, arg; 4866 if (flag_next_runtime) 4867 { 4868 /* The receiver is a variable created by build_class_reference_decl. */ 4869 if (TREE_CODE (receiver) == VAR_DECL 4870 && TREE_TYPE (receiver) == objc_class_type) 4871 /* Look up the identifier. */ 4872 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain)) 4873 if (TREE_PURPOSE (chain) == receiver) 4874 return TREE_VALUE (chain); 4875 } 4876 else 4877 { 4878 /* The receiver is a function call that returns an id. Check if 4879 it is a call to objc_getClass, if so, pick up the class name. */ 4880 if ((exp = TREE_OPERAND (receiver, 0)) 4881 && TREE_CODE (exp) == ADDR_EXPR 4882 && (exp = TREE_OPERAND (exp, 0)) 4883 && TREE_CODE (exp) == FUNCTION_DECL 4884 && exp == objc_get_class_decl 4885 /* we have a call to objc_getClass! */ 4886 && (arg = TREE_OPERAND (receiver, 1)) 4887 && TREE_CODE (arg) == TREE_LIST 4888 && (arg = TREE_VALUE (arg))) 4889 { 4890 STRIP_NOPS (arg); 4891 if (TREE_CODE (arg) == ADDR_EXPR 4892 && (arg = TREE_OPERAND (arg, 0)) 4893 && TREE_CODE (arg) == STRING_CST) 4894 /* Finally, we have the class name. */ 4895 return get_identifier (TREE_STRING_POINTER (arg)); 4896 } 4897 } 4898 return 0; 4899} 4900 4901/* If we are currently building a message expr, this holds 4902 the identifier of the selector of the message. This is 4903 used when printing warnings about argument mismatches. */ 4904 4905static tree building_objc_message_expr = 0; 4906 4907tree 4908maybe_building_objc_message_expr () 4909{ 4910 return building_objc_message_expr; 4911} 4912 4913/* Construct an expression for sending a message. 4914 MESS has the object to send to in TREE_PURPOSE 4915 and the argument list (including selector) in TREE_VALUE. 4916 4917 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...); 4918 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */ 4919 4920tree 4921build_message_expr (mess) 4922 tree mess; 4923{ 4924 tree receiver = TREE_PURPOSE (mess); 4925 tree selector, self_object; 4926 tree rtype, sel_name; 4927 tree args = TREE_VALUE (mess); 4928 tree method_params = NULL_TREE; 4929 tree method_prototype = NULL_TREE; 4930 tree retval; 4931 int statically_typed = 0, statically_allocated = 0; 4932 tree class_ident = 0; 4933 4934 /* 1 if this is sending to the superclass. */ 4935 int super; 4936 4937 if (!doing_objc_thang) 4938 objc_fatal (); 4939 4940 if (TREE_CODE (receiver) == ERROR_MARK) 4941 return error_mark_node; 4942 4943 /* Determine receiver type. */ 4944 rtype = TREE_TYPE (receiver); 4945 super = IS_SUPER (rtype); 4946 4947 if (! super) 4948 { 4949 if (TREE_STATIC_TEMPLATE (rtype)) 4950 statically_allocated = 1; 4951 else if (TREE_CODE (rtype) == POINTER_TYPE 4952 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype))) 4953 statically_typed = 1; 4954 else if ((flag_next_runtime 4955 || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype))) 4956 && (class_ident = receiver_is_class_object (receiver))) 4957 ; 4958 else if (! IS_ID (rtype) 4959 /* Allow any type that matches objc_class_type. */ 4960 && ! comptypes (rtype, objc_class_type)) 4961 { 4962 bzero (errbuf, BUFSIZE); 4963 warning ("invalid receiver type `%s'", 4964 gen_declaration (rtype, errbuf)); 4965 } 4966 4967 if (statically_allocated) 4968 receiver = build_unary_op (ADDR_EXPR, receiver, 0); 4969 4970 /* Don't evaluate the receiver twice. */ 4971 receiver = save_expr (receiver); 4972 self_object = receiver; 4973 } 4974 else 4975 /* If sending to `super', use current self as the object. */ 4976 self_object = self_decl; 4977 4978 /* Obtain the full selector name. */ 4979 4980 if (TREE_CODE (args) == IDENTIFIER_NODE) 4981 /* A unary selector. */ 4982 sel_name = args; 4983 else if (TREE_CODE (args) == TREE_LIST) 4984 sel_name = build_keyword_selector (args); 4985 else 4986 abort (); 4987 4988 /* Build the parameter list to give to the method. */ 4989 4990 method_params = NULL_TREE; 4991 if (TREE_CODE (args) == TREE_LIST) 4992 { 4993 tree chain = args, prev = NULL_TREE; 4994 4995 /* We have a keyword selector--check for comma expressions. */ 4996 while (chain) 4997 { 4998 tree element = TREE_VALUE (chain); 4999 5000 /* We have a comma expression, must collapse... */ 5001 if (TREE_CODE (element) == TREE_LIST) 5002 { 5003 if (prev) 5004 TREE_CHAIN (prev) = element; 5005 else 5006 args = element; 5007 } 5008 prev = chain; 5009 chain = TREE_CHAIN (chain); 5010 } 5011 method_params = args; 5012 } 5013 5014 /* Determine operation return type. */ 5015 5016 if (IS_SUPER (rtype)) 5017 { 5018 tree iface; 5019 5020 if (CLASS_SUPER_NAME (implementation_template)) 5021 { 5022 iface 5023 = lookup_interface (CLASS_SUPER_NAME (implementation_template)); 5024 5025 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL) 5026 method_prototype = lookup_instance_method_static (iface, sel_name); 5027 else 5028 method_prototype = lookup_class_method_static (iface, sel_name); 5029 5030 if (iface && !method_prototype) 5031 warning ("`%s' does not respond to `%s'", 5032 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)), 5033 IDENTIFIER_POINTER (sel_name)); 5034 } 5035 else 5036 { 5037 error ("no super class declared in interface for `%s'", 5038 IDENTIFIER_POINTER (CLASS_NAME (implementation_template))); 5039 return error_mark_node; 5040 } 5041 5042 } 5043 else if (statically_allocated) 5044 { 5045 tree ctype = TREE_TYPE (rtype); 5046 tree iface = lookup_interface (TYPE_NAME (rtype)); 5047 5048 if (iface) 5049 method_prototype = lookup_instance_method_static (iface, sel_name); 5050 5051 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype)) 5052 method_prototype 5053 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype), 5054 sel_name, 0); 5055 5056 if (!method_prototype) 5057 warning ("`%s' does not respond to `%s'", 5058 IDENTIFIER_POINTER (TYPE_NAME (rtype)), 5059 IDENTIFIER_POINTER (sel_name)); 5060 } 5061 else if (statically_typed) 5062 { 5063 tree ctype = TREE_TYPE (rtype); 5064 5065 /* `self' is now statically_typed. All methods should be visible 5066 within the context of the implementation. */ 5067 if (implementation_context 5068 && CLASS_NAME (implementation_context) == TYPE_NAME (ctype)) 5069 { 5070 method_prototype 5071 = lookup_instance_method_static (implementation_template, 5072 sel_name); 5073 5074 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype)) 5075 method_prototype 5076 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype), 5077 sel_name, 0); 5078 5079 if (! method_prototype 5080 && implementation_template != implementation_context) 5081 /* The method is not published in the interface. Check 5082 locally. */ 5083 method_prototype 5084 = lookup_method (CLASS_NST_METHODS (implementation_context), 5085 sel_name); 5086 } 5087 else 5088 { 5089 tree iface; 5090 5091 if ((iface = lookup_interface (TYPE_NAME (ctype)))) 5092 method_prototype = lookup_instance_method_static (iface, sel_name); 5093 5094 if (! method_prototype) 5095 { 5096 tree protocol_list = TYPE_PROTOCOL_LIST (ctype); 5097 if (protocol_list) 5098 method_prototype 5099 = lookup_method_in_protocol_list (protocol_list, 5100 sel_name, 0); 5101 } 5102 } 5103 5104 if (!method_prototype) 5105 warning ("`%s' does not respond to `%s'", 5106 IDENTIFIER_POINTER (TYPE_NAME (ctype)), 5107 IDENTIFIER_POINTER (sel_name)); 5108 } 5109 else if (class_ident) 5110 { 5111 if (implementation_context 5112 && CLASS_NAME (implementation_context) == class_ident) 5113 { 5114 method_prototype 5115 = lookup_class_method_static (implementation_template, sel_name); 5116 5117 if (!method_prototype 5118 && implementation_template != implementation_context) 5119 /* The method is not published in the interface. Check 5120 locally. */ 5121 method_prototype 5122 = lookup_method (CLASS_CLS_METHODS (implementation_context), 5123 sel_name); 5124 } 5125 else 5126 { 5127 tree iface; 5128 5129 if ((iface = lookup_interface (class_ident))) 5130 method_prototype = lookup_class_method_static (iface, sel_name); 5131 } 5132 5133 if (!method_prototype) 5134 { 5135 warning ("cannot find class (factory) method."); 5136 warning ("return type for `%s' defaults to id", 5137 IDENTIFIER_POINTER (sel_name)); 5138 } 5139 } 5140 else if (IS_PROTOCOL_QUALIFIED_ID (rtype)) 5141 { 5142 /* An anonymous object that has been qualified with a protocol. */ 5143 5144 tree protocol_list = TYPE_PROTOCOL_LIST (rtype); 5145 5146 method_prototype = lookup_method_in_protocol_list (protocol_list, 5147 sel_name, 0); 5148 5149 if (!method_prototype) 5150 { 5151 hash hsh; 5152 5153 warning ("method `%s' not implemented by protocol.", 5154 IDENTIFIER_POINTER (sel_name)); 5155 5156 /* Try and find the method signature in the global pools. */ 5157 5158 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name))) 5159 hsh = hash_lookup (cls_method_hash_list, sel_name); 5160 5161 if (!(method_prototype = check_duplicates (hsh))) 5162 warning ("return type defaults to id"); 5163 } 5164 } 5165 else 5166 { 5167 hash hsh; 5168 5169 /* We think we have an instance...loophole: extern id Object; */ 5170 hsh = hash_lookup (nst_method_hash_list, sel_name); 5171 if (!hsh) 5172 /* For various loopholes, like sending messages to self in a 5173 factory context. */ 5174 hsh = hash_lookup (cls_method_hash_list, sel_name); 5175 5176 method_prototype = check_duplicates (hsh); 5177 if (!method_prototype) 5178 { 5179 warning ("cannot find method."); 5180 warning ("return type for `%s' defaults to id", 5181 IDENTIFIER_POINTER (sel_name)); 5182 } 5183 } 5184 5185 /* Save the selector name for printing error messages. */ 5186 building_objc_message_expr = sel_name; 5187 5188 /* Build the parameters list for looking up the method. 5189 These are the object itself and the selector. */ 5190 5191 if (flag_typed_selectors) 5192 selector = build_typed_selector_reference (sel_name, method_prototype); 5193 else 5194 selector = build_selector_reference (sel_name); 5195 5196 retval = build_objc_method_call (super, method_prototype, 5197 receiver, self_object, 5198 selector, method_params); 5199 5200 building_objc_message_expr = 0; 5201 5202 return retval; 5203} 5204 5205/* Build a tree expression to send OBJECT the operation SELECTOR, 5206 looking up the method on object LOOKUP_OBJECT (often same as OBJECT), 5207 assuming the method has prototype METHOD_PROTOTYPE. 5208 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.) 5209 Use METHOD_PARAMS as list of args to pass to the method. 5210 If SUPER_FLAG is nonzero, we look up the superclass's method. */ 5211 5212static tree 5213build_objc_method_call (super_flag, method_prototype, lookup_object, object, 5214 selector, method_params) 5215 int super_flag; 5216 tree method_prototype, lookup_object, object, selector, method_params; 5217{ 5218 tree sender = (super_flag ? umsg_super_decl : umsg_decl); 5219 tree rcv_p = (super_flag 5220 ? build_pointer_type (xref_tag (RECORD_TYPE, 5221 get_identifier (TAG_SUPER))) 5222 : id_type); 5223 5224 if (flag_next_runtime) 5225 { 5226 if (! method_prototype) 5227 { 5228 method_params = tree_cons (NULL_TREE, lookup_object, 5229 tree_cons (NULL_TREE, selector, 5230 method_params)); 5231 assemble_external (sender); 5232 return build_function_call (sender, method_params); 5233 } 5234 else 5235 { 5236 /* This is a real kludge, but it is used only for the Next. 5237 Clobber the data type of SENDER temporarily to accept 5238 all the arguments for this operation, and to return 5239 whatever this operation returns. */ 5240 tree arglist = NULL_TREE; 5241 tree retval; 5242 5243 /* Save the proper contents of SENDER's data type. */ 5244 tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender)); 5245 tree savret = TREE_TYPE (TREE_TYPE (sender)); 5246 5247 /* Install this method's argument types. */ 5248 arglist = get_arg_type_list (method_prototype, METHOD_REF, 5249 super_flag); 5250 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist; 5251 5252 /* Install this method's return type. */ 5253 TREE_TYPE (TREE_TYPE (sender)) 5254 = groktypename (TREE_TYPE (method_prototype)); 5255 5256 /* Call SENDER with all the parameters. This will do type 5257 checking using the arg types for this method. */ 5258 method_params = tree_cons (NULL_TREE, lookup_object, 5259 tree_cons (NULL_TREE, selector, 5260 method_params)); 5261 assemble_external (sender); 5262 retval = build_function_call (sender, method_params); 5263 5264 /* Restore SENDER's return/argument types. */ 5265 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg; 5266 TREE_TYPE (TREE_TYPE (sender)) = savret; 5267 return retval; 5268 } 5269 } 5270 else 5271 { 5272 /* This is the portable way. 5273 First call the lookup function to get a pointer to the method, 5274 then cast the pointer, then call it with the method arguments. */ 5275 tree method; 5276 5277 /* Avoid trouble since we may evaluate each of these twice. */ 5278 object = save_expr (object); 5279 selector = save_expr (selector); 5280 5281 lookup_object = build_c_cast (rcv_p, lookup_object); 5282 5283 assemble_external (sender); 5284 method 5285 = build_function_call (sender, 5286 tree_cons (NULL_TREE, lookup_object, 5287 tree_cons (NULL_TREE, selector, 5288 NULL_TREE))); 5289 5290 /* If we have a method prototype, construct the data type this 5291 method needs, and cast what we got from SENDER into a pointer 5292 to that type. */ 5293 if (method_prototype) 5294 { 5295 tree arglist = get_arg_type_list (method_prototype, METHOD_REF, 5296 super_flag); 5297 tree valtype = groktypename (TREE_TYPE (method_prototype)); 5298 tree fake_function_type = build_function_type (valtype, arglist); 5299 TREE_TYPE (method) = build_pointer_type (fake_function_type); 5300 } 5301 else 5302 TREE_TYPE (method) 5303 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE)); 5304 5305 /* Pass the object to the method. */ 5306 assemble_external (method); 5307 return build_function_call (method, 5308 tree_cons (NULL_TREE, object, 5309 tree_cons (NULL_TREE, selector, 5310 method_params))); 5311 } 5312} 5313 5314static void 5315build_protocol_reference (p) 5316 tree p; 5317{ 5318 tree decl, ident, ptype; 5319 5320 push_obstacks_nochange (); 5321 end_temporary_allocation (); 5322 5323 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */ 5324 5325 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p); 5326 ptype 5327 = groktypename (build_tree_list (build_tree_list (NULL_TREE, 5328 objc_protocol_template), 5329 NULL_TREE)); 5330 5331 if (IDENTIFIER_GLOBAL_VALUE (ident)) 5332 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */ 5333 else 5334 { 5335 decl = build_decl (VAR_DECL, ident, ptype); 5336 DECL_EXTERNAL (decl) = 1; 5337 TREE_PUBLIC (decl) = 1; 5338 TREE_USED (decl) = 1; 5339 DECL_ARTIFICIAL (decl) = 1; 5340 5341 make_decl_rtl (decl, 0, 1); 5342 pushdecl_top_level (decl); 5343 } 5344 5345 PROTOCOL_FORWARD_DECL (p) = decl; 5346 pop_obstacks (); 5347} 5348 5349tree 5350build_protocol_expr (protoname) 5351 tree protoname; 5352{ 5353 tree expr; 5354 tree p; 5355 5356 if (!doing_objc_thang) 5357 objc_fatal (); 5358 5359 p = lookup_protocol (protoname); 5360 5361 if (!p) 5362 { 5363 error ("Cannot find protocol declaration for `%s'", 5364 IDENTIFIER_POINTER (protoname)); 5365 return error_mark_node; 5366 } 5367 5368 if (!PROTOCOL_FORWARD_DECL (p)) 5369 build_protocol_reference (p); 5370 5371 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0); 5372 5373 TREE_TYPE (expr) = protocol_type; 5374 5375 return expr; 5376} 5377 5378tree 5379build_selector_expr (selnamelist) 5380 tree selnamelist; 5381{ 5382 tree selname; 5383 5384 if (!doing_objc_thang) 5385 objc_fatal (); 5386 5387 /* Obtain the full selector name. */ 5388 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE) 5389 /* A unary selector. */ 5390 selname = selnamelist; 5391 else if (TREE_CODE (selnamelist) == TREE_LIST) 5392 selname = build_keyword_selector (selnamelist); 5393 else 5394 abort (); 5395 5396 if (flag_typed_selectors) 5397 return build_typed_selector_reference (selname, 0); 5398 else 5399 return build_selector_reference (selname); 5400} 5401 5402tree 5403build_encode_expr (type) 5404 tree type; 5405{ 5406 tree result; 5407 char *string; 5408 5409 if (!doing_objc_thang) 5410 objc_fatal (); 5411 5412 encode_type (type, obstack_object_size (&util_obstack), 5413 OBJC_ENCODE_INLINE_DEFS); 5414 obstack_1grow (&util_obstack, 0); /* null terminate string */ 5415 string = obstack_finish (&util_obstack); 5416 5417 /* Synthesize a string that represents the encoded struct/union. */ 5418 result = my_build_string (strlen (string) + 1, string); 5419 obstack_free (&util_obstack, util_firstobj); 5420 return result; 5421} 5422 5423tree 5424build_ivar_reference (id) 5425 tree id; 5426{ 5427 if (TREE_CODE (method_context) == CLASS_METHOD_DECL) 5428 { 5429 /* Historically, a class method that produced objects (factory 5430 method) would assign `self' to the instance that it 5431 allocated. This would effectively turn the class method into 5432 an instance method. Following this assignment, the instance 5433 variables could be accessed. That practice, while safe, 5434 violates the simple rule that a class method should not refer 5435 to an instance variable. It's better to catch the cases 5436 where this is done unknowingly than to support the above 5437 paradigm. */ 5438 warning ("instance variable `%s' accessed in class method", 5439 IDENTIFIER_POINTER (id)); 5440 TREE_TYPE (self_decl) = instance_type; /* cast */ 5441 } 5442 5443 return build_component_ref (build_indirect_ref (self_decl, "->"), id); 5444} 5445 5446#define HASH_ALLOC_LIST_SIZE 170 5447#define ATTR_ALLOC_LIST_SIZE 170 5448#define SIZEHASHTABLE 257 5449 5450/* make positive */ 5451#define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff) 5452 5453static void 5454hash_init () 5455{ 5456 nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash)); 5457 cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash)); 5458 5459 if (!nst_method_hash_list || !cls_method_hash_list) 5460 perror ("unable to allocate space in objc-tree.c"); 5461 else 5462 { 5463 int i; 5464 5465 for (i = 0; i < SIZEHASHTABLE; i++) 5466 { 5467 nst_method_hash_list[i] = 0; 5468 cls_method_hash_list[i] = 0; 5469 } 5470 } 5471} 5472 5473static void 5474hash_enter (hashlist, method) 5475 hash *hashlist; 5476 tree method; 5477{ 5478 static hash hash_alloc_list = 0; 5479 static int hash_alloc_index = 0; 5480 hash obj; 5481 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE; 5482 5483 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE) 5484 { 5485 hash_alloc_index = 0; 5486 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry) 5487 * HASH_ALLOC_LIST_SIZE); 5488 if (! hash_alloc_list) 5489 perror ("unable to allocate in objc-tree.c"); 5490 } 5491 obj = &hash_alloc_list[hash_alloc_index++]; 5492 obj->list = 0; 5493 obj->next = hashlist[slot]; 5494 obj->key = method; 5495 5496 hashlist[slot] = obj; /* append to front */ 5497} 5498 5499static hash 5500hash_lookup (hashlist, sel_name) 5501 hash *hashlist; 5502 tree sel_name; 5503{ 5504 hash target; 5505 5506 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE]; 5507 5508 while (target) 5509 { 5510 if (sel_name == METHOD_SEL_NAME (target->key)) 5511 return target; 5512 5513 target = target->next; 5514 } 5515 return 0; 5516} 5517 5518static void 5519hash_add_attr (entry, value) 5520 hash entry; 5521 tree value; 5522{ 5523 static attr attr_alloc_list = 0; 5524 static int attr_alloc_index = 0; 5525 attr obj; 5526 5527 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE) 5528 { 5529 attr_alloc_index = 0; 5530 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute) 5531 * ATTR_ALLOC_LIST_SIZE); 5532 if (! attr_alloc_list) 5533 perror ("unable to allocate in objc-tree.c"); 5534 } 5535 obj = &attr_alloc_list[attr_alloc_index++]; 5536 obj->next = entry->list; 5537 obj->value = value; 5538 5539 entry->list = obj; /* append to front */ 5540} 5541 5542static tree 5543lookup_method (mchain, method) 5544 tree mchain; 5545 tree method; 5546{ 5547 tree key; 5548 5549 if (TREE_CODE (method) == IDENTIFIER_NODE) 5550 key = method; 5551 else 5552 key = METHOD_SEL_NAME (method); 5553 5554 while (mchain) 5555 { 5556 if (METHOD_SEL_NAME (mchain) == key) 5557 return mchain; 5558 mchain = TREE_CHAIN (mchain); 5559 } 5560 return NULL_TREE; 5561} 5562 5563static tree 5564lookup_instance_method_static (interface, ident) 5565 tree interface; 5566 tree ident; 5567{ 5568 tree inter = interface; 5569 tree chain = CLASS_NST_METHODS (inter); 5570 tree meth = NULL_TREE; 5571 5572 do 5573 { 5574 if ((meth = lookup_method (chain, ident))) 5575 return meth; 5576 5577 if (CLASS_CATEGORY_LIST (inter)) 5578 { 5579 tree category = CLASS_CATEGORY_LIST (inter); 5580 chain = CLASS_NST_METHODS (category); 5581 5582 do 5583 { 5584 if ((meth = lookup_method (chain, ident))) 5585 return meth; 5586 5587 /* Check for instance methods in protocols in categories. */ 5588 if (CLASS_PROTOCOL_LIST (category)) 5589 { 5590 if ((meth = (lookup_method_in_protocol_list 5591 (CLASS_PROTOCOL_LIST (category), ident, 0)))) 5592 return meth; 5593 } 5594 5595 if ((category = CLASS_CATEGORY_LIST (category))) 5596 chain = CLASS_NST_METHODS (category); 5597 } 5598 while (category); 5599 } 5600 5601 if (CLASS_PROTOCOL_LIST (inter)) 5602 { 5603 if ((meth = (lookup_method_in_protocol_list 5604 (CLASS_PROTOCOL_LIST (inter), ident, 0)))) 5605 return meth; 5606 } 5607 5608 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter)))) 5609 chain = CLASS_NST_METHODS (inter); 5610 } 5611 while (inter); 5612 5613 return meth; 5614} 5615 5616static tree 5617lookup_class_method_static (interface, ident) 5618 tree interface; 5619 tree ident; 5620{ 5621 tree inter = interface; 5622 tree chain = CLASS_CLS_METHODS (inter); 5623 tree meth = NULL_TREE; 5624 tree root_inter = NULL_TREE; 5625 5626 do 5627 { 5628 if ((meth = lookup_method (chain, ident))) 5629 return meth; 5630 5631 if (CLASS_CATEGORY_LIST (inter)) 5632 { 5633 tree category = CLASS_CATEGORY_LIST (inter); 5634 chain = CLASS_CLS_METHODS (category); 5635 5636 do 5637 { 5638 if ((meth = lookup_method (chain, ident))) 5639 return meth; 5640 5641 /* Check for class methods in protocols in categories. */ 5642 if (CLASS_PROTOCOL_LIST (category)) 5643 { 5644 if ((meth = (lookup_method_in_protocol_list 5645 (CLASS_PROTOCOL_LIST (category), ident, 1)))) 5646 return meth; 5647 } 5648 5649 if ((category = CLASS_CATEGORY_LIST (category))) 5650 chain = CLASS_CLS_METHODS (category); 5651 } 5652 while (category); 5653 } 5654 5655 /* Check for class methods in protocols. */ 5656 if (CLASS_PROTOCOL_LIST (inter)) 5657 { 5658 if ((meth = (lookup_method_in_protocol_list 5659 (CLASS_PROTOCOL_LIST (inter), ident, 1)))) 5660 return meth; 5661 } 5662 5663 root_inter = inter; 5664 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter)))) 5665 chain = CLASS_CLS_METHODS (inter); 5666 } 5667 while (inter); 5668 5669 /* Simulate wrap around. */ 5670 return lookup_instance_method_static (root_inter, ident); 5671} 5672 5673tree 5674add_class_method (class, method) 5675 tree class; 5676 tree method; 5677{ 5678 tree mth; 5679 hash hsh; 5680 5681 /* We will have allocated the method parameter declarations on the 5682 maybepermanent_obstack. Need to make sure they stick around! */ 5683 preserve_data (); 5684 5685 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method))) 5686 { 5687 /* put method on list in reverse order */ 5688 TREE_CHAIN (method) = CLASS_CLS_METHODS (class); 5689 CLASS_CLS_METHODS (class) = method; 5690 } 5691 else 5692 { 5693 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) 5694 error ("duplicate definition of class method `%s'.", 5695 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); 5696 else 5697 { 5698 /* Check types; if different, complain. */ 5699 if (!comp_proto_with_proto (method, mth)) 5700 error ("duplicate declaration of class method `%s'.", 5701 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); 5702 } 5703 } 5704 5705 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method)))) 5706 { 5707 /* Install on a global chain. */ 5708 hash_enter (cls_method_hash_list, method); 5709 } 5710 else 5711 { 5712 /* Check types; if different, add to a list. */ 5713 if (!comp_proto_with_proto (method, hsh->key)) 5714 hash_add_attr (hsh, method); 5715 } 5716 return method; 5717} 5718 5719tree 5720add_instance_method (class, method) 5721 tree class; 5722 tree method; 5723{ 5724 tree mth; 5725 hash hsh; 5726 5727 /* We will have allocated the method parameter declarations on the 5728 maybepermanent_obstack. Need to make sure they stick around! */ 5729 preserve_data (); 5730 5731 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method))) 5732 { 5733 /* Put method on list in reverse order. */ 5734 TREE_CHAIN (method) = CLASS_NST_METHODS (class); 5735 CLASS_NST_METHODS (class) = method; 5736 } 5737 else 5738 { 5739 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) 5740 error ("duplicate definition of instance method `%s'.", 5741 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); 5742 else 5743 { 5744 /* Check types; if different, complain. */ 5745 if (!comp_proto_with_proto (method, mth)) 5746 error ("duplicate declaration of instance method `%s'.", 5747 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); 5748 } 5749 } 5750 5751 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method)))) 5752 { 5753 /* Install on a global chain. */ 5754 hash_enter (nst_method_hash_list, method); 5755 } 5756 else 5757 { 5758 /* Check types; if different, add to a list. */ 5759 if (!comp_proto_with_proto (method, hsh->key)) 5760 hash_add_attr (hsh, method); 5761 } 5762 return method; 5763} 5764 5765static tree 5766add_class (class) 5767 tree class; 5768{ 5769 /* Put interfaces on list in reverse order. */ 5770 TREE_CHAIN (class) = interface_chain; 5771 interface_chain = class; 5772 return interface_chain; 5773} 5774 5775static void 5776add_category (class, category) 5777 tree class; 5778 tree category; 5779{ 5780 /* Put categories on list in reverse order. */ 5781 tree cat = CLASS_CATEGORY_LIST (class); 5782 5783 while (cat) 5784 { 5785 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category)) 5786 warning ("duplicate interface declaration for category `%s(%s)'", 5787 IDENTIFIER_POINTER (CLASS_NAME (class)), 5788 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category))); 5789 cat = CLASS_CATEGORY_LIST (cat); 5790 } 5791 5792 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class); 5793 CLASS_CATEGORY_LIST (class) = category; 5794} 5795 5796/* Called after parsing each instance variable declaration. Necessary to 5797 preserve typedefs and implement public/private... 5798 5799 PUBLIC is 1 for public, 0 for protected, and 2 for private. */ 5800 5801tree 5802add_instance_variable (class, public, declarator, declspecs, width) 5803 tree class; 5804 int public; 5805 tree declarator; 5806 tree declspecs; 5807 tree width; 5808{ 5809 tree field_decl, raw_decl; 5810 5811 raw_decl = build_tree_list (declspecs, declarator); 5812 5813 if (CLASS_RAW_IVARS (class)) 5814 chainon (CLASS_RAW_IVARS (class), raw_decl); 5815 else 5816 CLASS_RAW_IVARS (class) = raw_decl; 5817 5818 field_decl = grokfield (input_filename, lineno, 5819 declarator, declspecs, width); 5820 5821 /* Overload the public attribute, it is not used for FIELD_DECLs. */ 5822 switch (public) 5823 { 5824 case 0: 5825 TREE_PUBLIC (field_decl) = 0; 5826 TREE_PRIVATE (field_decl) = 0; 5827 TREE_PROTECTED (field_decl) = 1; 5828 break; 5829 5830 case 1: 5831 TREE_PUBLIC (field_decl) = 1; 5832 TREE_PRIVATE (field_decl) = 0; 5833 TREE_PROTECTED (field_decl) = 0; 5834 break; 5835 5836 case 2: 5837 TREE_PUBLIC (field_decl) = 0; 5838 TREE_PRIVATE (field_decl) = 1; 5839 TREE_PROTECTED (field_decl) = 0; 5840 break; 5841 5842 } 5843 5844 if (CLASS_IVARS (class)) 5845 chainon (CLASS_IVARS (class), field_decl); 5846 else 5847 CLASS_IVARS (class) = field_decl; 5848 5849 return class; 5850} 5851 5852tree 5853is_ivar (decl_chain, ident) 5854 tree decl_chain; 5855 tree ident; 5856{ 5857 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain)) 5858 if (DECL_NAME (decl_chain) == ident) 5859 return decl_chain; 5860 return NULL_TREE; 5861} 5862 5863/* True if the ivar is private and we are not in its implementation. */ 5864 5865int 5866is_private (decl) 5867 tree decl; 5868{ 5869 if (TREE_PRIVATE (decl) 5870 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl))) 5871 { 5872 error ("instance variable `%s' is declared private", 5873 IDENTIFIER_POINTER (DECL_NAME (decl))); 5874 return 1; 5875 } 5876 else 5877 return 0; 5878} 5879 5880/* We have an instance variable reference;, check to see if it is public. */ 5881 5882int 5883is_public (expr, identifier) 5884 tree expr; 5885 tree identifier; 5886{ 5887 tree basetype = TREE_TYPE (expr); 5888 enum tree_code code = TREE_CODE (basetype); 5889 tree decl; 5890 5891 if (code == RECORD_TYPE) 5892 { 5893 if (TREE_STATIC_TEMPLATE (basetype)) 5894 { 5895 if (!lookup_interface (TYPE_NAME (basetype))) 5896 { 5897 error ("Cannot find interface declaration for `%s'", 5898 IDENTIFIER_POINTER (TYPE_NAME (basetype))); 5899 return 0; 5900 } 5901 5902 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier))) 5903 { 5904 if (TREE_PUBLIC (decl)) 5905 return 1; 5906 5907 /* Important difference between the Stepstone translator: 5908 all instance variables should be public within the context 5909 of the implementation. */ 5910 if (implementation_context 5911 && (((TREE_CODE (implementation_context) 5912 == CLASS_IMPLEMENTATION_TYPE) 5913 || (TREE_CODE (implementation_context) 5914 == CATEGORY_IMPLEMENTATION_TYPE)) 5915 && (CLASS_NAME (implementation_context) 5916 == TYPE_NAME (basetype)))) 5917 return ! is_private (decl); 5918 5919 error ("instance variable `%s' is declared %s", 5920 IDENTIFIER_POINTER (identifier), 5921 TREE_PRIVATE (decl) ? "private" : "protected"); 5922 return 0; 5923 } 5924 } 5925 5926 else if (implementation_context && (basetype == objc_object_reference)) 5927 { 5928 TREE_TYPE (expr) = uprivate_record; 5929 warning ("static access to object of type `id'"); 5930 } 5931 } 5932 5933 return 1; 5934} 5935 5936/* Implement @defs (<classname>) within struct bodies. */ 5937 5938tree 5939get_class_ivars (interface) 5940 tree interface; 5941{ 5942 if (!doing_objc_thang) 5943 objc_fatal (); 5944 5945 return build_ivar_chain (interface, 1); 5946} 5947 5948/* Make sure all entries in CHAIN are also in LIST. */ 5949 5950static int 5951check_methods (chain, list, mtype) 5952 tree chain; 5953 tree list; 5954 int mtype; 5955{ 5956 int first = 1; 5957 5958 while (chain) 5959 { 5960 if (!lookup_method (list, chain)) 5961 { 5962 if (first) 5963 { 5964 if (TREE_CODE (implementation_context) 5965 == CLASS_IMPLEMENTATION_TYPE) 5966 warning ("incomplete implementation of class `%s'", 5967 IDENTIFIER_POINTER (CLASS_NAME (implementation_context))); 5968 else if (TREE_CODE (implementation_context) 5969 == CATEGORY_IMPLEMENTATION_TYPE) 5970 warning ("incomplete implementation of category `%s'", 5971 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); 5972 first = 0; 5973 } 5974 5975 warning ("method definition for `%c%s' not found", 5976 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain))); 5977 } 5978 5979 chain = TREE_CHAIN (chain); 5980 } 5981 5982 return first; 5983} 5984 5985static int 5986conforms_to_protocol (class, protocol) 5987 tree class; 5988 tree protocol; 5989{ 5990 while (protocol) 5991 { 5992 tree p = CLASS_PROTOCOL_LIST (class); 5993 5994 while (p && TREE_VALUE (p) != TREE_VALUE (protocol)) 5995 p = TREE_CHAIN (p); 5996 5997 if (!p) 5998 { 5999 tree super = (CLASS_SUPER_NAME (class) 6000 ? lookup_interface (CLASS_SUPER_NAME (class)) 6001 : NULL_TREE); 6002 int tmp = super ? conforms_to_protocol (super, protocol) : 0; 6003 if (!tmp) 6004 return 0; 6005 } 6006 6007 protocol = TREE_CHAIN (protocol); 6008 } 6009 6010 return 1; 6011} 6012 6013/* Make sure all methods in CHAIN are accessible as MTYPE methods in 6014 CONTEXT. This is one of two mechanisms to check protocol integrity. */ 6015 6016static int 6017check_methods_accessible (chain, context, mtype) 6018 tree chain; 6019 tree context; 6020 int mtype; 6021{ 6022 int first = 1; 6023 tree list; 6024 tree base_context = context; 6025 6026 while (chain) 6027 { 6028 context = base_context; 6029 while (context) 6030 { 6031 if (mtype == '+') 6032 list = CLASS_CLS_METHODS (context); 6033 else 6034 list = CLASS_NST_METHODS (context); 6035 6036 if (lookup_method (list, chain)) 6037 break; 6038 6039 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE 6040 || TREE_CODE (context) == CLASS_INTERFACE_TYPE) 6041 context = (CLASS_SUPER_NAME (context) 6042 ? lookup_interface (CLASS_SUPER_NAME (context)) 6043 : NULL_TREE); 6044 6045 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE 6046 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE) 6047 context = (CLASS_NAME (context) 6048 ? lookup_interface (CLASS_NAME (context)) 6049 : NULL_TREE); 6050 else 6051 abort (); 6052 } 6053 6054 if (context == NULL_TREE) 6055 { 6056 if (first) 6057 { 6058 if (TREE_CODE (implementation_context) 6059 == CLASS_IMPLEMENTATION_TYPE) 6060 warning ("incomplete implementation of class `%s'", 6061 IDENTIFIER_POINTER 6062 (CLASS_NAME (implementation_context))); 6063 else if (TREE_CODE (implementation_context) 6064 == CATEGORY_IMPLEMENTATION_TYPE) 6065 warning ("incomplete implementation of category `%s'", 6066 IDENTIFIER_POINTER 6067 (CLASS_SUPER_NAME (implementation_context))); 6068 first = 0; 6069 } 6070 warning ("method definition for `%c%s' not found", 6071 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain))); 6072 } 6073 6074 chain = TREE_CHAIN (chain); /* next method... */ 6075 } 6076 return first; 6077} 6078 6079static void 6080check_protocols (proto_list, type, name) 6081 tree proto_list; 6082 char *type; 6083 char *name; 6084{ 6085 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list)) 6086 { 6087 tree p = TREE_VALUE (proto_list); 6088 6089 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) 6090 { 6091 int f1, f2; 6092 6093 /* Ensure that all protocols have bodies. */ 6094 if (flag_warn_protocol) { 6095 f1 = check_methods (PROTOCOL_CLS_METHODS (p), 6096 CLASS_CLS_METHODS (implementation_context), 6097 '+'); 6098 f2 = check_methods (PROTOCOL_NST_METHODS (p), 6099 CLASS_NST_METHODS (implementation_context), 6100 '-'); 6101 } else { 6102 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p), 6103 implementation_context, 6104 '+'); 6105 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p), 6106 implementation_context, 6107 '-'); 6108 } 6109 6110 if (!f1 || !f2) 6111 warning ("%s `%s' does not fully implement the `%s' protocol", 6112 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p))); 6113 6114 } 6115 else 6116 { 6117 ; /* An identifier if we could not find a protocol. */ 6118 } 6119 6120 /* Check protocols recursively. */ 6121 if (PROTOCOL_LIST (p)) 6122 { 6123 tree super_class 6124 = lookup_interface (CLASS_SUPER_NAME (implementation_template)); 6125 if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p))) 6126 check_protocols (PROTOCOL_LIST (p), type, name); 6127 } 6128 } 6129} 6130 6131/* Make sure that the class CLASS_NAME is defined 6132 CODE says which kind of thing CLASS_NAME ought to be. 6133 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, 6134 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. 6135 6136 If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange 6137 whose matching pop is in continue_class. */ 6138 6139tree 6140start_class (code, class_name, super_name, protocol_list) 6141 enum tree_code code; 6142 tree class_name; 6143 tree super_name; 6144 tree protocol_list; 6145{ 6146 tree class, decl; 6147 6148 if (code == CLASS_INTERFACE_TYPE) 6149 { 6150 push_obstacks_nochange (); 6151 end_temporary_allocation (); 6152 } 6153 6154 if (!doing_objc_thang) 6155 objc_fatal (); 6156 6157 class = make_node (code); 6158 TYPE_BINFO (class) = make_tree_vec (5); 6159 6160 CLASS_NAME (class) = class_name; 6161 CLASS_SUPER_NAME (class) = super_name; 6162 CLASS_CLS_METHODS (class) = NULL_TREE; 6163 6164 if (! is_class_name (class_name) && (decl = lookup_name (class_name))) 6165 { 6166 error ("`%s' redeclared as different kind of symbol", 6167 IDENTIFIER_POINTER (class_name)); 6168 error_with_decl (decl, "previous declaration of `%s'"); 6169 } 6170 6171 if (code == CLASS_IMPLEMENTATION_TYPE) 6172 { 6173 { 6174 static tree implemented_classes = 0; 6175 tree chain = implemented_classes; 6176 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain)) 6177 if (TREE_VALUE (chain) == class_name) 6178 { 6179 error ("reimplementation of class `%s'", 6180 IDENTIFIER_POINTER (class_name)); 6181 return error_mark_node; 6182 } 6183 implemented_classes = perm_tree_cons (NULL_TREE, class_name, 6184 implemented_classes); 6185 } 6186 6187 /* Pre-build the following entities - for speed/convenience. */ 6188 if (!self_id) 6189 self_id = get_identifier ("self"); 6190 if (!ucmd_id) 6191 ucmd_id = get_identifier ("_cmd"); 6192 if (!unused_list) 6193 unused_list 6194 = build_tree_list (get_identifier ("__unused__"), NULL_TREE); 6195 if (!objc_super_template) 6196 objc_super_template = build_super_template (); 6197 6198 /* Reset for multiple classes per file. */ 6199 method_slot = 0; 6200 6201 implementation_context = class; 6202 6203 /* Lookup the interface for this implementation. */ 6204 6205 if (!(implementation_template = lookup_interface (class_name))) 6206 { 6207 warning ("Cannot find interface declaration for `%s'", 6208 IDENTIFIER_POINTER (class_name)); 6209 add_class (implementation_template = implementation_context); 6210 } 6211 6212 /* If a super class has been specified in the implementation, 6213 insure it conforms to the one specified in the interface. */ 6214 6215 if (super_name 6216 && (super_name != CLASS_SUPER_NAME (implementation_template))) 6217 { 6218 tree previous_name = CLASS_SUPER_NAME (implementation_template); 6219 char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : ""; 6220 error ("conflicting super class name `%s'", 6221 IDENTIFIER_POINTER (super_name)); 6222 error ("previous declaration of `%s'", name); 6223 } 6224 6225 else if (! super_name) 6226 { 6227 CLASS_SUPER_NAME (implementation_context) 6228 = CLASS_SUPER_NAME (implementation_template); 6229 } 6230 } 6231 6232 else if (code == CLASS_INTERFACE_TYPE) 6233 { 6234 if (lookup_interface (class_name)) 6235 warning ("duplicate interface declaration for class `%s'", 6236 IDENTIFIER_POINTER (class_name)); 6237 else 6238 add_class (class); 6239 6240 if (protocol_list) 6241 CLASS_PROTOCOL_LIST (class) 6242 = lookup_and_install_protocols (protocol_list); 6243 } 6244 6245 else if (code == CATEGORY_INTERFACE_TYPE) 6246 { 6247 tree class_category_is_assoc_with; 6248 6249 /* For a category, class_name is really the name of the class that 6250 the following set of methods will be associated with. We must 6251 find the interface so that can derive the objects template. */ 6252 6253 if (!(class_category_is_assoc_with = lookup_interface (class_name))) 6254 { 6255 error ("Cannot find interface declaration for `%s'", 6256 IDENTIFIER_POINTER (class_name)); 6257 exit (FATAL_EXIT_CODE); 6258 } 6259 else 6260 add_category (class_category_is_assoc_with, class); 6261 6262 if (protocol_list) 6263 CLASS_PROTOCOL_LIST (class) 6264 = lookup_and_install_protocols (protocol_list); 6265 } 6266 6267 else if (code == CATEGORY_IMPLEMENTATION_TYPE) 6268 { 6269 /* Pre-build the following entities for speed/convenience. */ 6270 if (!self_id) 6271 self_id = get_identifier ("self"); 6272 if (!ucmd_id) 6273 ucmd_id = get_identifier ("_cmd"); 6274 if (!unused_list) 6275 unused_list 6276 = build_tree_list (get_identifier ("__unused__"), NULL_TREE); 6277 if (!objc_super_template) 6278 objc_super_template = build_super_template (); 6279 6280 /* Reset for multiple classes per file. */ 6281 method_slot = 0; 6282 6283 implementation_context = class; 6284 6285 /* For a category, class_name is really the name of the class that 6286 the following set of methods will be associated with. We must 6287 find the interface so that can derive the objects template. */ 6288 6289 if (!(implementation_template = lookup_interface (class_name))) 6290 { 6291 error ("Cannot find interface declaration for `%s'", 6292 IDENTIFIER_POINTER (class_name)); 6293 exit (FATAL_EXIT_CODE); 6294 } 6295 } 6296 return class; 6297} 6298 6299tree 6300continue_class (class) 6301 tree class; 6302{ 6303 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE 6304 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE) 6305 { 6306 struct imp_entry *imp_entry; 6307 tree ivar_context; 6308 6309 /* Check consistency of the instance variables. */ 6310 6311 if (CLASS_IVARS (class)) 6312 check_ivars (implementation_template, class); 6313 6314 /* code generation */ 6315 6316 ivar_context = build_private_template (implementation_template); 6317 6318 if (!objc_class_template) 6319 build_class_template (); 6320 6321 if (!(imp_entry 6322 = (struct imp_entry *) xmalloc (sizeof (struct imp_entry)))) 6323 perror ("unable to allocate in objc-tree.c"); 6324 6325 imp_entry->next = imp_list; 6326 imp_entry->imp_context = class; 6327 imp_entry->imp_template = implementation_template; 6328 6329 synth_forward_declarations (); 6330 imp_entry->class_decl = UOBJC_CLASS_decl; 6331 imp_entry->meta_decl = UOBJC_METACLASS_decl; 6332 6333 /* Append to front and increment count. */ 6334 imp_list = imp_entry; 6335 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) 6336 imp_count++; 6337 else 6338 cat_count++; 6339 6340 return ivar_context; 6341 } 6342 6343 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE) 6344 { 6345 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class)); 6346 6347 if (!TYPE_FIELDS (record)) 6348 { 6349 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE); 6350 CLASS_STATIC_TEMPLATE (class) = record; 6351 6352 /* Mark this record as a class template for static typing. */ 6353 TREE_STATIC_TEMPLATE (record) = 1; 6354 } 6355 6356 return NULL_TREE; 6357 } 6358 6359 else 6360 return error_mark_node; 6361} 6362 6363/* This is called once we see the "@end" in an interface/implementation. */ 6364 6365void 6366finish_class (class) 6367 tree class; 6368{ 6369 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) 6370 { 6371 /* All code generation is done in finish_objc. */ 6372 6373 if (implementation_template != implementation_context) 6374 { 6375 /* Ensure that all method listed in the interface contain bodies. */ 6376 check_methods (CLASS_CLS_METHODS (implementation_template), 6377 CLASS_CLS_METHODS (implementation_context), '+'); 6378 check_methods (CLASS_NST_METHODS (implementation_template), 6379 CLASS_NST_METHODS (implementation_context), '-'); 6380 6381 if (CLASS_PROTOCOL_LIST (implementation_template)) 6382 check_protocols (CLASS_PROTOCOL_LIST (implementation_template), 6383 "class", 6384 IDENTIFIER_POINTER (CLASS_NAME (implementation_context))); 6385 } 6386 } 6387 6388 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE) 6389 { 6390 tree category = CLASS_CATEGORY_LIST (implementation_template); 6391 6392 /* Find the category interface from the class it is associated with. */ 6393 while (category) 6394 { 6395 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category)) 6396 break; 6397 category = CLASS_CATEGORY_LIST (category); 6398 } 6399 6400 if (category) 6401 { 6402 /* Ensure all method listed in the interface contain bodies. */ 6403 check_methods (CLASS_CLS_METHODS (category), 6404 CLASS_CLS_METHODS (implementation_context), '+'); 6405 check_methods (CLASS_NST_METHODS (category), 6406 CLASS_NST_METHODS (implementation_context), '-'); 6407 6408 if (CLASS_PROTOCOL_LIST (category)) 6409 check_protocols (CLASS_PROTOCOL_LIST (category), 6410 "category", 6411 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); 6412 } 6413 } 6414 6415 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE) 6416 { 6417 tree decl_specs; 6418 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class)); 6419 char *string = (char *) alloca (strlen (class_name) + 3); 6420 6421 /* extern struct objc_object *_<my_name>; */ 6422 6423 sprintf (string, "_%s", class_name); 6424 6425 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]); 6426 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs); 6427 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)), 6428 decl_specs); 6429 } 6430} 6431 6432static tree 6433add_protocol (protocol) 6434 tree protocol; 6435{ 6436 /* Put protocol on list in reverse order. */ 6437 TREE_CHAIN (protocol) = protocol_chain; 6438 protocol_chain = protocol; 6439 return protocol_chain; 6440} 6441 6442static tree 6443lookup_protocol (ident) 6444 tree ident; 6445{ 6446 tree chain; 6447 6448 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain)) 6449 { 6450 if (ident == PROTOCOL_NAME (chain)) 6451 return chain; 6452 } 6453 6454 return NULL_TREE; 6455} 6456 6457tree 6458start_protocol (code, name, list) 6459 enum tree_code code; 6460 tree name; 6461 tree list; 6462{ 6463 tree protocol; 6464 6465 if (!doing_objc_thang) 6466 objc_fatal (); 6467 6468 /* This is as good a place as any. Need to invoke push_tag_toplevel. */ 6469 if (!objc_protocol_template) 6470 objc_protocol_template = build_protocol_template (); 6471 6472 protocol = make_node (code); 6473 TYPE_BINFO (protocol) = make_tree_vec (2); 6474 6475 PROTOCOL_NAME (protocol) = name; 6476 PROTOCOL_LIST (protocol) = list; 6477 6478 lookup_and_install_protocols (list); 6479 6480 if (lookup_protocol (name)) 6481 warning ("duplicate declaration for protocol `%s'", 6482 IDENTIFIER_POINTER (name)); 6483 else 6484 add_protocol (protocol); 6485 6486 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE; 6487 6488 return protocol; 6489} 6490 6491void 6492finish_protocol (protocol) 6493 tree protocol ATTRIBUTE_UNUSED; 6494{ 6495} 6496 6497 6498/* "Encode" a data type into a string, which grows in util_obstack. 6499 ??? What is the FORMAT? Someone please document this! */ 6500 6501static void 6502encode_type_qualifiers (declspecs) 6503 tree declspecs; 6504{ 6505 tree spec; 6506 6507 for (spec = declspecs; spec; spec = TREE_CHAIN (spec)) 6508 { 6509 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec)) 6510 obstack_1grow (&util_obstack, 'r'); 6511 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec)) 6512 obstack_1grow (&util_obstack, 'n'); 6513 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec)) 6514 obstack_1grow (&util_obstack, 'N'); 6515 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec)) 6516 obstack_1grow (&util_obstack, 'o'); 6517 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec)) 6518 obstack_1grow (&util_obstack, 'O'); 6519 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec)) 6520 obstack_1grow (&util_obstack, 'R'); 6521 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec)) 6522 obstack_1grow (&util_obstack, 'V'); 6523 } 6524} 6525 6526/* Encode a pointer type. */ 6527 6528static void 6529encode_pointer (type, curtype, format) 6530 tree type; 6531 int curtype; 6532 int format; 6533{ 6534 tree pointer_to = TREE_TYPE (type); 6535 6536 if (TREE_CODE (pointer_to) == RECORD_TYPE) 6537 { 6538 if (TYPE_NAME (pointer_to) 6539 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE) 6540 { 6541 char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to)); 6542 6543 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */ 6544 { 6545 obstack_1grow (&util_obstack, '@'); 6546 return; 6547 } 6548 else if (TREE_STATIC_TEMPLATE (pointer_to)) 6549 { 6550 if (generating_instance_variables) 6551 { 6552 obstack_1grow (&util_obstack, '@'); 6553 obstack_1grow (&util_obstack, '"'); 6554 obstack_grow (&util_obstack, name, strlen (name)); 6555 obstack_1grow (&util_obstack, '"'); 6556 return; 6557 } 6558 else 6559 { 6560 obstack_1grow (&util_obstack, '@'); 6561 return; 6562 } 6563 } 6564 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */ 6565 { 6566 obstack_1grow (&util_obstack, '#'); 6567 return; 6568 } 6569#ifndef OBJC_INT_SELECTORS 6570 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */ 6571 { 6572 obstack_1grow (&util_obstack, ':'); 6573 return; 6574 } 6575#endif /* OBJC_INT_SELECTORS */ 6576 } 6577 } 6578 else if (TREE_CODE (pointer_to) == INTEGER_TYPE 6579 && TYPE_MODE (pointer_to) == QImode) 6580 { 6581 obstack_1grow (&util_obstack, '*'); 6582 return; 6583 } 6584 6585 /* We have a type that does not get special treatment. */ 6586 6587 /* NeXT extension */ 6588 obstack_1grow (&util_obstack, '^'); 6589 encode_type (pointer_to, curtype, format); 6590} 6591 6592static void 6593encode_array (type, curtype, format) 6594 tree type; 6595 int curtype; 6596 int format; 6597{ 6598 tree an_int_cst = TYPE_SIZE (type); 6599 tree array_of = TREE_TYPE (type); 6600 char buffer[40]; 6601 6602 /* An incomplete array is treated like a pointer. */ 6603 if (an_int_cst == NULL) 6604 { 6605 encode_pointer (type, curtype, format); 6606 return; 6607 } 6608 6609 sprintf (buffer, "[%ld", 6610 (long) (TREE_INT_CST_LOW (an_int_cst) 6611 / TREE_INT_CST_LOW (TYPE_SIZE (array_of)))); 6612 6613 obstack_grow (&util_obstack, buffer, strlen (buffer)); 6614 encode_type (array_of, curtype, format); 6615 obstack_1grow (&util_obstack, ']'); 6616 return; 6617} 6618 6619static void 6620encode_aggregate_within (type, curtype, format, left, right) 6621 tree type; 6622 int curtype; 6623 int format; 6624 int left; 6625 int right; 6626{ 6627 if (obstack_object_size (&util_obstack) > 0 6628 && *(obstack_next_free (&util_obstack) - 1) == '^') 6629 { 6630 tree name = TYPE_NAME (type); 6631 6632 /* we have a reference; this is a NeXT extension. */ 6633 6634 if (obstack_object_size (&util_obstack) - curtype == 1 6635 && format == OBJC_ENCODE_INLINE_DEFS) 6636 { 6637 /* Output format of struct for first level only. */ 6638 tree fields = TYPE_FIELDS (type); 6639 6640 if (name && TREE_CODE (name) == IDENTIFIER_NODE) 6641 { 6642 obstack_1grow (&util_obstack, left); 6643 obstack_grow (&util_obstack, 6644 IDENTIFIER_POINTER (name), 6645 strlen (IDENTIFIER_POINTER (name))); 6646 obstack_1grow (&util_obstack, '='); 6647 } 6648 else 6649 { 6650 obstack_1grow (&util_obstack, left); 6651 obstack_grow (&util_obstack, "?=", 2); 6652 } 6653 6654 for ( ; fields; fields = TREE_CHAIN (fields)) 6655 encode_field_decl (fields, curtype, format); 6656 6657 obstack_1grow (&util_obstack, right); 6658 } 6659 6660 else if (name && TREE_CODE (name) == IDENTIFIER_NODE) 6661 { 6662 obstack_1grow (&util_obstack, left); 6663 obstack_grow (&util_obstack, 6664 IDENTIFIER_POINTER (name), 6665 strlen (IDENTIFIER_POINTER (name))); 6666 obstack_1grow (&util_obstack, right); 6667 } 6668 6669 else 6670 { 6671 /* We have an untagged structure or a typedef. */ 6672 obstack_1grow (&util_obstack, left); 6673 obstack_1grow (&util_obstack, '?'); 6674 obstack_1grow (&util_obstack, right); 6675 } 6676 } 6677 6678 else 6679 { 6680 tree name = TYPE_NAME (type); 6681 tree fields = TYPE_FIELDS (type); 6682 6683 if (format == OBJC_ENCODE_INLINE_DEFS 6684 || generating_instance_variables) 6685 { 6686 obstack_1grow (&util_obstack, left); 6687 if (name && TREE_CODE (name) == IDENTIFIER_NODE) 6688 obstack_grow (&util_obstack, 6689 IDENTIFIER_POINTER (name), 6690 strlen (IDENTIFIER_POINTER (name))); 6691 else 6692 obstack_1grow (&util_obstack, '?'); 6693 6694 obstack_1grow (&util_obstack, '='); 6695 6696 for (; fields; fields = TREE_CHAIN (fields)) 6697 { 6698 if (generating_instance_variables) 6699 { 6700 tree fname = DECL_NAME (fields); 6701 6702 obstack_1grow (&util_obstack, '"'); 6703 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE) 6704 { 6705 obstack_grow (&util_obstack, 6706 IDENTIFIER_POINTER (fname), 6707 strlen (IDENTIFIER_POINTER (fname))); 6708 } 6709 6710 obstack_1grow (&util_obstack, '"'); 6711 } 6712 6713 encode_field_decl (fields, curtype, format); 6714 } 6715 6716 obstack_1grow (&util_obstack, right); 6717 } 6718 6719 else 6720 { 6721 obstack_1grow (&util_obstack, left); 6722 if (name && TREE_CODE (name) == IDENTIFIER_NODE) 6723 obstack_grow (&util_obstack, 6724 IDENTIFIER_POINTER (name), 6725 strlen (IDENTIFIER_POINTER (name))); 6726 else 6727 /* We have an untagged structure or a typedef. */ 6728 obstack_1grow (&util_obstack, '?'); 6729 6730 obstack_1grow (&util_obstack, right); 6731 } 6732 } 6733} 6734 6735static void 6736encode_aggregate (type, curtype, format) 6737 tree type; 6738 int curtype; 6739 int format; 6740{ 6741 enum tree_code code = TREE_CODE (type); 6742 6743 switch (code) 6744 { 6745 case RECORD_TYPE: 6746 { 6747 encode_aggregate_within(type, curtype, format, '{', '}'); 6748 break; 6749 } 6750 case UNION_TYPE: 6751 { 6752 encode_aggregate_within(type, curtype, format, '(', ')'); 6753 break; 6754 } 6755 6756 case ENUMERAL_TYPE: 6757 obstack_1grow (&util_obstack, 'i'); 6758 break; 6759 6760 default: 6761 break; 6762 } 6763} 6764 6765/* Support bitfields. The current version of Objective-C does not support 6766 them. The string will consist of one or more "b:n"'s where n is an 6767 integer describing the width of the bitfield. Currently, classes in 6768 the kit implement a method "-(char *)describeBitfieldStruct:" that 6769 simulates this. If they do not implement this method, the archiver 6770 assumes the bitfield is 16 bits wide (padded if necessary) and packed 6771 according to the GNU compiler. After looking at the "kit", it appears 6772 that all classes currently rely on this default behavior, rather than 6773 hand generating this string (which is tedious). */ 6774 6775static void 6776encode_bitfield (width, format) 6777 int width; 6778 int format; 6779{ 6780 char buffer[40]; 6781 sprintf (buffer, "b%d", width); 6782 obstack_grow (&util_obstack, buffer, strlen (buffer)); 6783} 6784 6785/* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */ 6786 6787static void 6788encode_type (type, curtype, format) 6789 tree type; 6790 int curtype; 6791 int format; 6792{ 6793 enum tree_code code = TREE_CODE (type); 6794 6795 if (code == INTEGER_TYPE) 6796 { 6797 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0 6798 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0) 6799 { 6800 /* Unsigned integer types. */ 6801 6802 if (TYPE_MODE (type) == QImode) 6803 obstack_1grow (&util_obstack, 'C'); 6804 else if (TYPE_MODE (type) == HImode) 6805 obstack_1grow (&util_obstack, 'S'); 6806 else if (TYPE_MODE (type) == SImode) 6807 { 6808 if (type == long_unsigned_type_node) 6809 obstack_1grow (&util_obstack, 'L'); 6810 else 6811 obstack_1grow (&util_obstack, 'I'); 6812 } 6813 else if (TYPE_MODE (type) == DImode) 6814 obstack_1grow (&util_obstack, 'Q'); 6815 } 6816 6817 else 6818 /* Signed integer types. */ 6819 { 6820 if (TYPE_MODE (type) == QImode) 6821 obstack_1grow (&util_obstack, 'c'); 6822 else if (TYPE_MODE (type) == HImode) 6823 obstack_1grow (&util_obstack, 's'); 6824 else if (TYPE_MODE (type) == SImode) 6825 { 6826 if (type == long_integer_type_node) 6827 obstack_1grow (&util_obstack, 'l'); 6828 else 6829 obstack_1grow (&util_obstack, 'i'); 6830 } 6831 6832 else if (TYPE_MODE (type) == DImode) 6833 obstack_1grow (&util_obstack, 'q'); 6834 } 6835 } 6836 6837 else if (code == REAL_TYPE) 6838 { 6839 /* Floating point types. */ 6840 6841 if (TYPE_MODE (type) == SFmode) 6842 obstack_1grow (&util_obstack, 'f'); 6843 else if (TYPE_MODE (type) == DFmode 6844 || TYPE_MODE (type) == TFmode) 6845 obstack_1grow (&util_obstack, 'd'); 6846 } 6847 6848 else if (code == VOID_TYPE) 6849 obstack_1grow (&util_obstack, 'v'); 6850 6851 else if (code == ARRAY_TYPE) 6852 encode_array (type, curtype, format); 6853 6854 else if (code == POINTER_TYPE) 6855 encode_pointer (type, curtype, format); 6856 6857 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE) 6858 encode_aggregate (type, curtype, format); 6859 6860 else if (code == FUNCTION_TYPE) /* '?' */ 6861 obstack_1grow (&util_obstack, '?'); 6862} 6863 6864static void 6865encode_complete_bitfield (int position, tree type, int size) 6866{ 6867 enum tree_code code = TREE_CODE (type); 6868 char buffer[40]; 6869 char charType = '?'; 6870 6871 if (code == INTEGER_TYPE) 6872 { 6873 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0 6874 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0) 6875 { 6876 /* Unsigned integer types. */ 6877 6878 if (TYPE_MODE (type) == QImode) 6879 charType = 'C'; 6880 else if (TYPE_MODE (type) == HImode) 6881 charType = 'S'; 6882 else if (TYPE_MODE (type) == SImode) 6883 { 6884 if (type == long_unsigned_type_node) 6885 charType = 'L'; 6886 else 6887 charType = 'I'; 6888 } 6889 else if (TYPE_MODE (type) == DImode) 6890 charType = 'Q'; 6891 } 6892 6893 else 6894 /* Signed integer types. */ 6895 { 6896 if (TYPE_MODE (type) == QImode) 6897 charType = 'c'; 6898 else if (TYPE_MODE (type) == HImode) 6899 charType = 's'; 6900 else if (TYPE_MODE (type) == SImode) 6901 { 6902 if (type == long_integer_type_node) 6903 charType = 'l'; 6904 else 6905 charType = 'i'; 6906 } 6907 6908 else if (TYPE_MODE (type) == DImode) 6909 charType = 'q'; 6910 } 6911 } 6912 6913 else 6914 abort (); 6915 6916 sprintf (buffer, "b%d%c%d", position, charType, size); 6917 obstack_grow (&util_obstack, buffer, strlen (buffer)); 6918} 6919 6920static void 6921encode_field_decl (field_decl, curtype, format) 6922 tree field_decl; 6923 int curtype; 6924 int format; 6925{ 6926 tree type; 6927 6928 type = TREE_TYPE (field_decl); 6929 6930 /* If this field is obviously a bitfield, or is a bitfield that has been 6931 clobbered to look like a ordinary integer mode, go ahead and generate 6932 the bitfield typing information. */ 6933 if (flag_next_runtime) 6934 { 6935 if (DECL_BIT_FIELD (field_decl)) 6936 encode_bitfield (DECL_FIELD_SIZE (field_decl), format); 6937 else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST 6938 && DECL_FIELD_SIZE (field_decl) 6939 && TYPE_MODE (type) > DECL_MODE (field_decl)) 6940 encode_bitfield (DECL_FIELD_SIZE (field_decl), format); 6941 else 6942 encode_type (TREE_TYPE (field_decl), curtype, format); 6943 } 6944 else 6945 { 6946 if (DECL_BIT_FIELD (field_decl) 6947 || (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST 6948 && DECL_FIELD_SIZE (field_decl) 6949 && TYPE_MODE (type) > DECL_MODE (field_decl))) 6950 { 6951 encode_complete_bitfield (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)), 6952 DECL_BIT_FIELD_TYPE (field_decl), 6953 DECL_FIELD_SIZE (field_decl)); 6954 } 6955 else 6956 encode_type (TREE_TYPE (field_decl), curtype, format); 6957 } 6958} 6959 6960static tree 6961expr_last (complex_expr) 6962 tree complex_expr; 6963{ 6964 tree next; 6965 6966 if (complex_expr) 6967 while ((next = TREE_OPERAND (complex_expr, 0))) 6968 complex_expr = next; 6969 6970 return complex_expr; 6971} 6972 6973/* The selector of the current method, 6974 or NULL if we aren't compiling a method. */ 6975 6976tree 6977maybe_objc_method_name (decl) 6978 tree decl; 6979{ 6980 if (method_context) 6981 return METHOD_SEL_NAME (method_context); 6982 else 6983 return 0; 6984} 6985 6986/* Transform a method definition into a function definition as follows: 6987 - synthesize the first two arguments, "self" and "_cmd". */ 6988 6989void 6990start_method_def (method) 6991 tree method; 6992{ 6993 tree decl_specs; 6994 6995 /* Required to implement _msgSuper. */ 6996 method_context = method; 6997 UOBJC_SUPER_decl = NULL_TREE; 6998 6999 /* Must be called BEFORE start_function. */ 7000 pushlevel (0); 7001 7002 /* Generate prototype declarations for arguments..."new-style". */ 7003 7004 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL) 7005 decl_specs = build_tree_list (NULL_TREE, uprivate_record); 7006 else 7007 /* Really a `struct objc_class *'. However, we allow people to 7008 assign to self, which changes its type midstream. */ 7009 decl_specs = build_tree_list (NULL_TREE, objc_object_reference); 7010 7011 push_parm_decl (build_tree_list 7012 (build_tree_list (decl_specs, 7013 build1 (INDIRECT_REF, NULL_TREE, self_id)), 7014 build_tree_list (unused_list, NULL_TREE))); 7015 7016#ifdef OBJC_INT_SELECTORS 7017 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]); 7018 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); 7019 push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id), 7020 build_tree_list (unused_list, NULL_TREE))); 7021#else /* not OBJC_INT_SELECTORS */ 7022 decl_specs = build_tree_list (NULL_TREE, 7023 xref_tag (RECORD_TYPE, 7024 get_identifier (TAG_SELECTOR))); 7025 push_parm_decl (build_tree_list 7026 (build_tree_list (decl_specs, 7027 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)), 7028 build_tree_list (unused_list, NULL_TREE))); 7029#endif /* not OBJC_INT_SELECTORS */ 7030 7031 /* Generate argument declarations if a keyword_decl. */ 7032 if (METHOD_SEL_ARGS (method)) 7033 { 7034 tree arglist = METHOD_SEL_ARGS (method); 7035 do 7036 { 7037 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist)); 7038 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist)); 7039 7040 if (arg_decl) 7041 { 7042 tree last_expr = expr_last (arg_decl); 7043 7044 /* Unite the abstract decl with its name. */ 7045 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist); 7046 push_parm_decl (build_tree_list 7047 (build_tree_list (arg_spec, arg_decl), 7048 build_tree_list (NULL_TREE, NULL_TREE))); 7049 7050 /* Unhook: restore the abstract declarator. */ 7051 TREE_OPERAND (last_expr, 0) = NULL_TREE; 7052 } 7053 7054 else 7055 push_parm_decl (build_tree_list 7056 (build_tree_list (arg_spec, 7057 KEYWORD_ARG_NAME (arglist)), 7058 build_tree_list (NULL_TREE, NULL_TREE))); 7059 7060 arglist = TREE_CHAIN (arglist); 7061 } 7062 while (arglist); 7063 } 7064 7065 if (METHOD_ADD_ARGS (method) > (tree)1) 7066 { 7067 /* We have a variable length selector - in "prototype" format. */ 7068 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method)); 7069 while (akey) 7070 { 7071 /* This must be done prior to calling pushdecl. pushdecl is 7072 going to change our chain on us. */ 7073 tree nextkey = TREE_CHAIN (akey); 7074 pushdecl (akey); 7075 akey = nextkey; 7076 } 7077 } 7078} 7079 7080static void 7081warn_with_method (message, mtype, method) 7082 char *message; 7083 int mtype; 7084 tree method; 7085{ 7086 if (count_error (1) == 0) 7087 return; 7088 7089 report_error_function (DECL_SOURCE_FILE (method)); 7090 7091 fprintf (stderr, "%s:%d: warning: ", 7092 DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method)); 7093 bzero (errbuf, BUFSIZE); 7094 fprintf (stderr, "%s `%c%s'\n", 7095 message, mtype, gen_method_decl (method, errbuf)); 7096} 7097 7098/* Return 1 if METHOD is consistent with PROTO. */ 7099 7100static int 7101comp_method_with_proto (method, proto) 7102 tree method, proto; 7103{ 7104 static tree function_type = 0; 7105 7106 /* Create a function_type node once. */ 7107 if (!function_type) 7108 { 7109 push_obstacks_nochange (); 7110 end_temporary_allocation (); 7111 function_type = make_node (FUNCTION_TYPE); 7112 pop_obstacks (); 7113 } 7114 7115 /* Install argument types - normally set by build_function_type. */ 7116 TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0); 7117 7118 /* install return type */ 7119 TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto)); 7120 7121 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type); 7122} 7123 7124/* Return 1 if PROTO1 is consistent with PROTO2. */ 7125 7126static int 7127comp_proto_with_proto (proto1, proto2) 7128 tree proto1, proto2; 7129{ 7130 static tree function_type1 = 0, function_type2 = 0; 7131 7132 /* Create a couple function_type node's once. */ 7133 if (!function_type1) 7134 { 7135 push_obstacks_nochange (); 7136 end_temporary_allocation (); 7137 function_type1 = make_node (FUNCTION_TYPE); 7138 function_type2 = make_node (FUNCTION_TYPE); 7139 pop_obstacks (); 7140 } 7141 7142 /* Install argument types; normally set by build_function_type. */ 7143 TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0); 7144 TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0); 7145 7146 /* Install return type. */ 7147 TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1)); 7148 TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2)); 7149 7150 return comptypes (function_type1, function_type2); 7151} 7152 7153/* - Generate an identifier for the function. the format is "_n_cls", 7154 where 1 <= n <= nMethods, and cls is the name the implementation we 7155 are processing. 7156 - Install the return type from the method declaration. 7157 - If we have a prototype, check for type consistency. */ 7158 7159static void 7160really_start_method (method, parmlist) 7161 tree method, parmlist; 7162{ 7163 tree sc_spec, ret_spec, ret_decl, decl_specs; 7164 tree method_decl, method_id; 7165 char *buf, *sel_name, *class_name, *cat_name; 7166 7167 /* Synth the storage class & assemble the return type. */ 7168 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); 7169 ret_spec = TREE_PURPOSE (TREE_TYPE (method)); 7170 decl_specs = chainon (sc_spec, ret_spec); 7171 7172 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method)); 7173 class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); 7174 cat_name = ((TREE_CODE (implementation_context) 7175 == CLASS_IMPLEMENTATION_TYPE) 7176 ? NULL 7177 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); 7178 method_slot++; 7179 7180 /* Make sure this is big enough for any plausible method label. */ 7181 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name) 7182 + (cat_name ? strlen (cat_name) : 0)); 7183 7184 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL, 7185 class_name, cat_name, sel_name, method_slot); 7186 7187 method_id = get_identifier (buf); 7188 7189 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE); 7190 7191 /* Check the declarator portion of the return type for the method. */ 7192 if ((ret_decl = TREE_VALUE (TREE_TYPE (method)))) 7193 { 7194 /* Unite the complex decl (specified in the abstract decl) with the 7195 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */ 7196 tree save_expr = expr_last (ret_decl); 7197 7198 TREE_OPERAND (save_expr, 0) = method_decl; 7199 method_decl = ret_decl; 7200 7201 /* Fool the parser into thinking it is starting a function. */ 7202 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0); 7203 7204 /* Unhook: this has the effect of restoring the abstract declarator. */ 7205 TREE_OPERAND (save_expr, 0) = NULL_TREE; 7206 } 7207 7208 else 7209 { 7210 TREE_VALUE (TREE_TYPE (method)) = method_decl; 7211 7212 /* Fool the parser into thinking it is starting a function. */ 7213 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0); 7214 7215 /* Unhook: this has the effect of restoring the abstract declarator. */ 7216 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE; 7217 } 7218 7219 METHOD_DEFINITION (method) = current_function_decl; 7220 7221 if (implementation_template != implementation_context) 7222 { 7223 tree proto; 7224 7225 if (TREE_CODE (method) == INSTANCE_METHOD_DECL) 7226 proto = lookup_instance_method_static (implementation_template, 7227 METHOD_SEL_NAME (method)); 7228 else 7229 proto = lookup_class_method_static (implementation_template, 7230 METHOD_SEL_NAME (method)); 7231 7232 if (proto && ! comp_method_with_proto (method, proto)) 7233 { 7234 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+'); 7235 7236 warn_with_method ("conflicting types for", type, method); 7237 warn_with_method ("previous declaration of", type, proto); 7238 } 7239 } 7240} 7241 7242/* The following routine is always called...this "architecture" is to 7243 accommodate "old-style" variable length selectors. 7244 7245 - a:a b:b // prototype ; id c; id d; // old-style. */ 7246 7247void 7248continue_method_def () 7249{ 7250 tree parmlist; 7251 7252 if (METHOD_ADD_ARGS (method_context) == (tree)1) 7253 /* We have a `, ...' immediately following the selector. */ 7254 parmlist = get_parm_info (0); 7255 else 7256 parmlist = get_parm_info (1); /* place a `void_at_end' */ 7257 7258 /* Set self_decl from the first argument...this global is used by 7259 build_ivar_reference calling build_indirect_ref. */ 7260 self_decl = TREE_PURPOSE (parmlist); 7261 7262 poplevel (0, 0, 0); 7263 really_start_method (method_context, parmlist); 7264 store_parm_decls (); 7265} 7266 7267/* Called by the parser, from the `pushlevel' production. */ 7268 7269void 7270add_objc_decls () 7271{ 7272 if (!UOBJC_SUPER_decl) 7273 { 7274 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER), 7275 build_tree_list (NULL_TREE, 7276 objc_super_template), 7277 0, NULL_TREE, NULL_TREE); 7278 7279 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE); 7280 7281 /* This prevents `unused variable' warnings when compiling with -Wall. */ 7282 TREE_USED (UOBJC_SUPER_decl) = 1; 7283 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1; 7284 } 7285} 7286 7287/* _n_Method (id self, SEL sel, ...) 7288 { 7289 struct objc_super _S; 7290 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...); 7291 } */ 7292 7293tree 7294get_super_receiver () 7295{ 7296 if (method_context) 7297 { 7298 tree super_expr, super_expr_list; 7299 7300 /* Set receiver to self. */ 7301 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id); 7302 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl); 7303 super_expr_list = build_tree_list (NULL_TREE, super_expr); 7304 7305 /* Set class to begin searching. */ 7306 super_expr = build_component_ref (UOBJC_SUPER_decl, 7307 get_identifier ("class")); 7308 7309 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) 7310 { 7311 /* [_cls, __cls]Super are "pre-built" in 7312 synth_forward_declarations. */ 7313 7314 super_expr = build_modify_expr (super_expr, NOP_EXPR, 7315 ((TREE_CODE (method_context) 7316 == INSTANCE_METHOD_DECL) 7317 ? ucls_super_ref 7318 : uucls_super_ref)); 7319 } 7320 7321 else 7322 /* We have a category. */ 7323 { 7324 tree super_name = CLASS_SUPER_NAME (implementation_template); 7325 tree super_class; 7326 7327 if (!super_name) 7328 { 7329 error ("no super class declared in interface for `%s'", 7330 IDENTIFIER_POINTER (CLASS_NAME (implementation_template))); 7331 return error_mark_node; 7332 } 7333 7334 if (flag_next_runtime) 7335 { 7336 super_class = get_class_reference (super_name); 7337 if (TREE_CODE (method_context) == CLASS_METHOD_DECL) 7338 super_class 7339 = build_component_ref (build_indirect_ref (super_class, "->"), 7340 get_identifier ("isa")); 7341 } 7342 else 7343 { 7344 add_class_reference (super_name); 7345 super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL 7346 ? objc_get_class_decl : objc_get_meta_class_decl); 7347 assemble_external (super_class); 7348 super_class 7349 = build_function_call 7350 (super_class, 7351 build_tree_list 7352 (NULL_TREE, 7353 my_build_string (IDENTIFIER_LENGTH (super_name) + 1, 7354 IDENTIFIER_POINTER (super_name)))); 7355 } 7356 7357 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref); 7358 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class); 7359 } 7360 7361 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr)); 7362 7363 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0); 7364 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr)); 7365 7366 return build_compound_expr (super_expr_list); 7367 } 7368 else 7369 { 7370 error ("[super ...] must appear in a method context"); 7371 return error_mark_node; 7372 } 7373} 7374 7375static tree 7376encode_method_def (func_decl) 7377 tree func_decl; 7378{ 7379 tree parms; 7380 int stack_size; 7381 int max_parm_end = 0; 7382 char buffer[40]; 7383 tree result; 7384 7385 /* Return type. */ 7386 encode_type (TREE_TYPE (TREE_TYPE (func_decl)), 7387 obstack_object_size (&util_obstack), 7388 OBJC_ENCODE_INLINE_DEFS); 7389 7390 /* Stack size. */ 7391 for (parms = DECL_ARGUMENTS (func_decl); parms; 7392 parms = TREE_CHAIN (parms)) 7393 { 7394 int parm_end = (forwarding_offset (parms) 7395 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms))) 7396 / BITS_PER_UNIT)); 7397 7398 if (!offset_is_register && parm_end > max_parm_end) 7399 max_parm_end = parm_end; 7400 } 7401 7402 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET; 7403 7404 sprintf (buffer, "%d", stack_size); 7405 obstack_grow (&util_obstack, buffer, strlen (buffer)); 7406 7407 /* Argument types. */ 7408 for (parms = DECL_ARGUMENTS (func_decl); parms; 7409 parms = TREE_CHAIN (parms)) 7410 { 7411 /* Type. */ 7412 encode_type (TREE_TYPE (parms), 7413 obstack_object_size (&util_obstack), 7414 OBJC_ENCODE_INLINE_DEFS); 7415 7416 /* Compute offset. */ 7417 sprintf (buffer, "%d", forwarding_offset (parms)); 7418 7419 /* Indicate register. */ 7420 if (offset_is_register) 7421 obstack_1grow (&util_obstack, '+'); 7422 7423 obstack_grow (&util_obstack, buffer, strlen (buffer)); 7424 } 7425 7426 obstack_1grow (&util_obstack, 0); 7427 result = get_identifier (obstack_finish (&util_obstack)); 7428 obstack_free (&util_obstack, util_firstobj); 7429 return result; 7430} 7431 7432void 7433finish_method_def () 7434{ 7435 METHOD_ENCODING (method_context) = encode_method_def (current_function_decl); 7436 7437 finish_function (0); 7438 7439 /* Required to implement _msgSuper. This must be done AFTER finish_function, 7440 since the optimizer may find "may be used before set" errors. */ 7441 method_context = NULL_TREE; 7442} 7443 7444#if 0 7445int 7446lang_report_error_function (decl) 7447 tree decl; 7448{ 7449 if (method_context) 7450 { 7451 fprintf (stderr, "In method `%s'\n", 7452 IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context))); 7453 return 1; 7454 } 7455 7456 else 7457 return 0; 7458} 7459#endif 7460 7461static int 7462is_complex_decl (type) 7463 tree type; 7464{ 7465 return (TREE_CODE (type) == ARRAY_TYPE 7466 || TREE_CODE (type) == FUNCTION_TYPE 7467 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type))); 7468} 7469 7470 7471/* Code to convert a decl node into text for a declaration in C. */ 7472 7473static char tmpbuf[256]; 7474 7475static void 7476adorn_decl (decl, str) 7477 tree decl; 7478 char *str; 7479{ 7480 enum tree_code code = TREE_CODE (decl); 7481 7482 if (code == ARRAY_REF) 7483 { 7484 tree an_int_cst = TREE_OPERAND (decl, 1); 7485 7486 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST) 7487 sprintf (str + strlen (str), "[%ld]", 7488 (long) TREE_INT_CST_LOW (an_int_cst)); 7489 else 7490 strcat (str, "[]"); 7491 } 7492 7493 else if (code == ARRAY_TYPE) 7494 { 7495 tree an_int_cst = TYPE_SIZE (decl); 7496 tree array_of = TREE_TYPE (decl); 7497 7498 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE) 7499 sprintf (str + strlen (str), "[%ld]", 7500 (long) (TREE_INT_CST_LOW (an_int_cst) 7501 / TREE_INT_CST_LOW (TYPE_SIZE (array_of)))); 7502 else 7503 strcat (str, "[]"); 7504 } 7505 7506 else if (code == CALL_EXPR) 7507 { 7508 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1)); 7509 7510 strcat (str, "("); 7511 while (chain) 7512 { 7513 gen_declaration (chain, str); 7514 chain = TREE_CHAIN (chain); 7515 if (chain) 7516 strcat (str, ", "); 7517 } 7518 strcat (str, ")"); 7519 } 7520 7521 else if (code == FUNCTION_TYPE) 7522 { 7523 tree chain = TYPE_ARG_TYPES (decl); 7524 7525 strcat (str, "("); 7526 while (chain && TREE_VALUE (chain) != void_type_node) 7527 { 7528 gen_declaration (TREE_VALUE (chain), str); 7529 chain = TREE_CHAIN (chain); 7530 if (chain && TREE_VALUE (chain) != void_type_node) 7531 strcat (str, ", "); 7532 } 7533 strcat (str, ")"); 7534 } 7535 7536 else if (code == INDIRECT_REF) 7537 { 7538 strcpy (tmpbuf, "*"); 7539 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST) 7540 { 7541 tree chain; 7542 7543 for (chain = nreverse (copy_list (TREE_TYPE (decl))); 7544 chain; 7545 chain = TREE_CHAIN (chain)) 7546 { 7547 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE) 7548 { 7549 strcat (tmpbuf, " "); 7550 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain))); 7551 } 7552 } 7553 if (str[0]) 7554 strcat (tmpbuf, " "); 7555 } 7556 strcat (tmpbuf, str); 7557 strcpy (str, tmpbuf); 7558 } 7559 7560 else if (code == POINTER_TYPE) 7561 { 7562 strcpy (tmpbuf, "*"); 7563 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl)) 7564 { 7565 if (TREE_READONLY (decl)) 7566 strcat (tmpbuf, " const"); 7567 if (TYPE_VOLATILE (decl)) 7568 strcat (tmpbuf, " volatile"); 7569 if (str[0]) 7570 strcat (tmpbuf, " "); 7571 } 7572 strcat (tmpbuf, str); 7573 strcpy (str, tmpbuf); 7574 } 7575} 7576 7577static char * 7578gen_declarator (decl, buf, name) 7579 tree decl; 7580 char *buf; 7581 char *name; 7582{ 7583 if (decl) 7584 { 7585 enum tree_code code = TREE_CODE (decl); 7586 char *str; 7587 tree op; 7588 int wrap = 0; 7589 7590 switch (code) 7591 { 7592 case ARRAY_REF: 7593 case INDIRECT_REF: 7594 case CALL_EXPR: 7595 op = TREE_OPERAND (decl, 0); 7596 7597 /* We have a pointer to a function or array...(*)(), (*)[] */ 7598 if ((code == ARRAY_REF || code == CALL_EXPR) 7599 && op && TREE_CODE (op) == INDIRECT_REF) 7600 wrap = 1; 7601 7602 str = gen_declarator (op, buf, name); 7603 7604 if (wrap) 7605 { 7606 strcpy (tmpbuf, "("); 7607 strcat (tmpbuf, str); 7608 strcat (tmpbuf, ")"); 7609 strcpy (str, tmpbuf); 7610 } 7611 7612 adorn_decl (decl, str); 7613 break; 7614 7615 case ARRAY_TYPE: 7616 case FUNCTION_TYPE: 7617 case POINTER_TYPE: 7618 strcpy (buf, name); 7619 str = buf; 7620 7621 /* This clause is done iteratively rather than recursively. */ 7622 do 7623 { 7624 op = (is_complex_decl (TREE_TYPE (decl)) 7625 ? TREE_TYPE (decl) : NULL_TREE); 7626 7627 adorn_decl (decl, str); 7628 7629 /* We have a pointer to a function or array...(*)(), (*)[] */ 7630 if (code == POINTER_TYPE 7631 && op && (TREE_CODE (op) == FUNCTION_TYPE 7632 || TREE_CODE (op) == ARRAY_TYPE)) 7633 { 7634 strcpy (tmpbuf, "("); 7635 strcat (tmpbuf, str); 7636 strcat (tmpbuf, ")"); 7637 strcpy (str, tmpbuf); 7638 } 7639 7640 decl = (is_complex_decl (TREE_TYPE (decl)) 7641 ? TREE_TYPE (decl) : NULL_TREE); 7642 } 7643 7644 while (decl && (code = TREE_CODE (decl))) 7645 ; 7646 7647 break; 7648 7649 case IDENTIFIER_NODE: 7650 /* Will only happen if we are processing a "raw" expr-decl. */ 7651 strcpy (buf, IDENTIFIER_POINTER (decl)); 7652 return buf; 7653 7654 default: 7655 abort (); 7656 } 7657 7658 return str; 7659 } 7660 7661 else 7662 /* We have an abstract declarator or a _DECL node. */ 7663 { 7664 strcpy (buf, name); 7665 return buf; 7666 } 7667} 7668 7669static void 7670gen_declspecs (declspecs, buf, raw) 7671 tree declspecs; 7672 char *buf; 7673 int raw; 7674{ 7675 if (raw) 7676 { 7677 tree chain; 7678 7679 for (chain = nreverse (copy_list (declspecs)); 7680 chain; chain = TREE_CHAIN (chain)) 7681 { 7682 tree aspec = TREE_VALUE (chain); 7683 7684 if (TREE_CODE (aspec) == IDENTIFIER_NODE) 7685 strcat (buf, IDENTIFIER_POINTER (aspec)); 7686 else if (TREE_CODE (aspec) == RECORD_TYPE) 7687 { 7688 if (TYPE_NAME (aspec)) 7689 { 7690 tree protocol_list = TYPE_PROTOCOL_LIST (aspec); 7691 7692 if (! TREE_STATIC_TEMPLATE (aspec)) 7693 strcat (buf, "struct "); 7694 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec))); 7695 7696 /* NEW!!! */ 7697 if (protocol_list) 7698 { 7699 tree chain = protocol_list; 7700 7701 strcat (buf, " <"); 7702 while (chain) 7703 { 7704 strcat (buf, 7705 IDENTIFIER_POINTER 7706 (PROTOCOL_NAME (TREE_VALUE (chain)))); 7707 chain = TREE_CHAIN (chain); 7708 if (chain) 7709 strcat (buf, ", "); 7710 } 7711 strcat (buf, ">"); 7712 } 7713 } 7714 7715 else 7716 strcat (buf, "untagged struct"); 7717 } 7718 7719 else if (TREE_CODE (aspec) == UNION_TYPE) 7720 { 7721 if (TYPE_NAME (aspec)) 7722 { 7723 if (! TREE_STATIC_TEMPLATE (aspec)) 7724 strcat (buf, "union "); 7725 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec))); 7726 } 7727 else 7728 strcat (buf, "untagged union"); 7729 } 7730 7731 else if (TREE_CODE (aspec) == ENUMERAL_TYPE) 7732 { 7733 if (TYPE_NAME (aspec)) 7734 { 7735 if (! TREE_STATIC_TEMPLATE (aspec)) 7736 strcat (buf, "enum "); 7737 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec))); 7738 } 7739 else 7740 strcat (buf, "untagged enum"); 7741 } 7742 7743 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec)) 7744 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec))); 7745 7746 else if (IS_ID (aspec)) 7747 { 7748 tree protocol_list = TYPE_PROTOCOL_LIST (aspec); 7749 7750 strcat (buf, "id"); 7751 if (protocol_list) 7752 { 7753 tree chain = protocol_list; 7754 7755 strcat (buf, " <"); 7756 while (chain) 7757 { 7758 strcat (buf, 7759 IDENTIFIER_POINTER 7760 (PROTOCOL_NAME (TREE_VALUE (chain)))); 7761 chain = TREE_CHAIN (chain); 7762 if (chain) 7763 strcat (buf, ", "); 7764 } 7765 strcat (buf, ">"); 7766 } 7767 } 7768 if (TREE_CHAIN (chain)) 7769 strcat (buf, " "); 7770 } 7771 } 7772 else 7773 { 7774 /* Type qualifiers. */ 7775 if (TREE_READONLY (declspecs)) 7776 strcat (buf, "const "); 7777 if (TYPE_VOLATILE (declspecs)) 7778 strcat (buf, "volatile "); 7779 7780 switch (TREE_CODE (declspecs)) 7781 { 7782 /* Type specifiers. */ 7783 7784 case INTEGER_TYPE: 7785 declspecs = TYPE_MAIN_VARIANT (declspecs); 7786 7787 /* Signed integer types. */ 7788 7789 if (declspecs == short_integer_type_node) 7790 strcat (buf, "short int "); 7791 else if (declspecs == integer_type_node) 7792 strcat (buf, "int "); 7793 else if (declspecs == long_integer_type_node) 7794 strcat (buf, "long int "); 7795 else if (declspecs == long_long_integer_type_node) 7796 strcat (buf, "long long int "); 7797 else if (declspecs == signed_char_type_node 7798 || declspecs == char_type_node) 7799 strcat (buf, "char "); 7800 7801 /* Unsigned integer types. */ 7802 7803 else if (declspecs == short_unsigned_type_node) 7804 strcat (buf, "unsigned short "); 7805 else if (declspecs == unsigned_type_node) 7806 strcat (buf, "unsigned int "); 7807 else if (declspecs == long_unsigned_type_node) 7808 strcat (buf, "unsigned long "); 7809 else if (declspecs == long_long_unsigned_type_node) 7810 strcat (buf, "unsigned long long "); 7811 else if (declspecs == unsigned_char_type_node) 7812 strcat (buf, "unsigned char "); 7813 break; 7814 7815 case REAL_TYPE: 7816 declspecs = TYPE_MAIN_VARIANT (declspecs); 7817 7818 if (declspecs == float_type_node) 7819 strcat (buf, "float "); 7820 else if (declspecs == double_type_node) 7821 strcat (buf, "double "); 7822 else if (declspecs == long_double_type_node) 7823 strcat (buf, "long double "); 7824 break; 7825 7826 case RECORD_TYPE: 7827 if (TYPE_NAME (declspecs) 7828 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE) 7829 { 7830 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs); 7831 7832 if (! TREE_STATIC_TEMPLATE (declspecs)) 7833 strcat (buf, "struct "); 7834 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs))); 7835 7836 if (protocol_list) 7837 { 7838 tree chain = protocol_list; 7839 7840 strcat (buf, " <"); 7841 while (chain) 7842 { 7843 strcat (buf, 7844 IDENTIFIER_POINTER 7845 (PROTOCOL_NAME (TREE_VALUE (chain)))); 7846 chain = TREE_CHAIN (chain); 7847 if (chain) 7848 strcat (buf, ", "); 7849 } 7850 strcat (buf, ">"); 7851 } 7852 } 7853 7854 else 7855 strcat (buf, "untagged struct"); 7856 7857 strcat (buf, " "); 7858 break; 7859 7860 case UNION_TYPE: 7861 if (TYPE_NAME (declspecs) 7862 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE) 7863 { 7864 strcat (buf, "union "); 7865 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs))); 7866 strcat (buf, " "); 7867 } 7868 7869 else 7870 strcat (buf, "untagged union "); 7871 break; 7872 7873 case ENUMERAL_TYPE: 7874 if (TYPE_NAME (declspecs) 7875 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE) 7876 { 7877 strcat (buf, "enum "); 7878 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs))); 7879 strcat (buf, " "); 7880 } 7881 7882 else 7883 strcat (buf, "untagged enum "); 7884 break; 7885 7886 case VOID_TYPE: 7887 strcat (buf, "void "); 7888 break; 7889 7890 case POINTER_TYPE: 7891 { 7892 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs); 7893 7894 strcat (buf, "id"); 7895 if (protocol_list) 7896 { 7897 tree chain = protocol_list; 7898 7899 strcat (buf, " <"); 7900 while (chain) 7901 { 7902 strcat (buf, 7903 IDENTIFIER_POINTER 7904 (PROTOCOL_NAME (TREE_VALUE (chain)))); 7905 chain = TREE_CHAIN (chain); 7906 if (chain) 7907 strcat (buf, ", "); 7908 } 7909 7910 strcat (buf, ">"); 7911 } 7912 } 7913 break; 7914 7915 default: 7916 break; 7917 } 7918 } 7919} 7920 7921static char * 7922gen_declaration (atype_or_adecl, buf) 7923 tree atype_or_adecl; 7924 char *buf; 7925{ 7926 char declbuf[256]; 7927 7928 if (TREE_CODE (atype_or_adecl) == TREE_LIST) 7929 { 7930 tree declspecs; /* "identifier_node", "record_type" */ 7931 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */ 7932 7933 /* We have a "raw", abstract declarator (typename). */ 7934 declarator = TREE_VALUE (atype_or_adecl); 7935 declspecs = TREE_PURPOSE (atype_or_adecl); 7936 7937 gen_declspecs (declspecs, buf, 1); 7938 if (declarator) 7939 { 7940 strcat (buf, " "); 7941 strcat (buf, gen_declarator (declarator, declbuf, "")); 7942 } 7943 } 7944 7945 else 7946 { 7947 tree atype; 7948 tree declspecs; /* "integer_type", "real_type", "record_type"... */ 7949 tree declarator; /* "array_type", "function_type", "pointer_type". */ 7950 7951 if (TREE_CODE (atype_or_adecl) == FIELD_DECL 7952 || TREE_CODE (atype_or_adecl) == PARM_DECL 7953 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL) 7954 atype = TREE_TYPE (atype_or_adecl); 7955 else 7956 /* Assume we have a *_type node. */ 7957 atype = atype_or_adecl; 7958 7959 if (is_complex_decl (atype)) 7960 { 7961 tree chain; 7962 7963 /* Get the declaration specifier; it is at the end of the list. */ 7964 declarator = chain = atype; 7965 do 7966 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */ 7967 while (is_complex_decl (chain)); 7968 declspecs = chain; 7969 } 7970 7971 else 7972 { 7973 declspecs = atype; 7974 declarator = NULL_TREE; 7975 } 7976 7977 gen_declspecs (declspecs, buf, 0); 7978 7979 if (TREE_CODE (atype_or_adecl) == FIELD_DECL 7980 || TREE_CODE (atype_or_adecl) == PARM_DECL 7981 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL) 7982 { 7983 char *decl_name = (DECL_NAME (atype_or_adecl) 7984 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) 7985 : ""); 7986 7987 if (declarator) 7988 { 7989 strcat (buf, " "); 7990 strcat (buf, gen_declarator (declarator, declbuf, decl_name)); 7991 } 7992 7993 else if (decl_name[0]) 7994 { 7995 strcat (buf, " "); 7996 strcat (buf, decl_name); 7997 } 7998 } 7999 else if (declarator) 8000 { 8001 strcat (buf, " "); 8002 strcat (buf, gen_declarator (declarator, declbuf, "")); 8003 } 8004 } 8005 8006 return buf; 8007} 8008 8009#define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth)))) 8010 8011static char * 8012gen_method_decl (method, buf) 8013 tree method; 8014 char *buf; 8015{ 8016 tree chain; 8017 8018 if (RAW_TYPESPEC (method) != objc_object_reference) 8019 { 8020 strcpy (buf, "("); 8021 gen_declaration (TREE_TYPE (method), buf); 8022 strcat (buf, ")"); 8023 } 8024 8025 chain = METHOD_SEL_ARGS (method); 8026 if (chain) 8027 { 8028 /* We have a chain of keyword_decls. */ 8029 do 8030 { 8031 if (KEYWORD_KEY_NAME (chain)) 8032 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain))); 8033 8034 strcat (buf, ":"); 8035 if (RAW_TYPESPEC (chain) != objc_object_reference) 8036 { 8037 strcat (buf, "("); 8038 gen_declaration (TREE_TYPE (chain), buf); 8039 strcat (buf, ")"); 8040 } 8041 8042 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain))); 8043 if ((chain = TREE_CHAIN (chain))) 8044 strcat (buf, " "); 8045 } 8046 while (chain); 8047 8048 if (METHOD_ADD_ARGS (method) == (tree)1) 8049 strcat (buf, ", ..."); 8050 else if (METHOD_ADD_ARGS (method)) 8051 { 8052 /* We have a tree list node as generate by get_parm_info. */ 8053 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method)); 8054 8055 /* Know we have a chain of parm_decls. */ 8056 while (chain) 8057 { 8058 strcat (buf, ", "); 8059 gen_declaration (chain, buf); 8060 chain = TREE_CHAIN (chain); 8061 } 8062 } 8063 } 8064 8065 else 8066 /* We have a unary selector. */ 8067 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method))); 8068 8069 return buf; 8070} 8071 8072/* Debug info. */ 8073 8074static void 8075dump_interface (fp, chain) 8076 FILE *fp; 8077 tree chain; 8078{ 8079 char *buf = (char *)xmalloc (256); 8080 char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain)); 8081 tree ivar_decls = CLASS_RAW_IVARS (chain); 8082 tree nst_methods = CLASS_NST_METHODS (chain); 8083 tree cls_methods = CLASS_CLS_METHODS (chain); 8084 8085 fprintf (fp, "\n@interface %s", my_name); 8086 8087 if (CLASS_SUPER_NAME (chain)) 8088 { 8089 char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain)); 8090 fprintf (fp, " : %s\n", super_name); 8091 } 8092 else 8093 fprintf (fp, "\n"); 8094 8095 if (ivar_decls) 8096 { 8097 fprintf (fp, "{\n"); 8098 do 8099 { 8100 bzero (buf, 256); 8101 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf)); 8102 ivar_decls = TREE_CHAIN (ivar_decls); 8103 } 8104 while (ivar_decls); 8105 fprintf (fp, "}\n"); 8106 } 8107 8108 while (nst_methods) 8109 { 8110 bzero (buf, 256); 8111 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf)); 8112 nst_methods = TREE_CHAIN (nst_methods); 8113 } 8114 8115 while (cls_methods) 8116 { 8117 bzero (buf, 256); 8118 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf)); 8119 cls_methods = TREE_CHAIN (cls_methods); 8120 } 8121 fprintf (fp, "\n@end"); 8122} 8123 8124/* Demangle function for Objective-C */ 8125static const char * 8126objc_demangle (mangled) 8127 const char *mangled; 8128{ 8129 char *demangled, *cp; 8130 8131 if (mangled[0] == '_' && 8132 (mangled[1] == 'i' || mangled[1] == 'c') && 8133 mangled[2] == '_') 8134 { 8135 cp = demangled = xmalloc(strlen(mangled) + 2); 8136 if (mangled[1] == 'i') 8137 *cp++ = '-'; /* for instance method */ 8138 else 8139 *cp++ = '+'; /* for class method */ 8140 *cp++ = '['; /* opening left brace */ 8141 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */ 8142 while (*cp && *cp == '_') 8143 cp++; /* skip any initial underbars in class name */ 8144 cp = strchr(cp, '_'); /* find first non-initial underbar */ 8145 if (cp == NULL) 8146 { 8147 free(demangled); /* not mangled name */ 8148 return mangled; 8149 } 8150 if (cp[1] == '_') /* easy case: no category name */ 8151 { 8152 *cp++ = ' '; /* replace two '_' with one ' ' */ 8153 strcpy(cp, mangled + (cp - demangled) + 2); 8154 } 8155 else 8156 { 8157 *cp++ = '('; /* less easy case: category name */ 8158 cp = strchr(cp, '_'); 8159 if (cp == 0) 8160 { 8161 free(demangled); /* not mangled name */ 8162 return mangled; 8163 } 8164 *cp++ = ')'; 8165 *cp++ = ' '; /* overwriting 1st char of method name... */ 8166 strcpy(cp, mangled + (cp - demangled)); /* get it back */ 8167 } 8168 while (*cp && *cp == '_') 8169 cp++; /* skip any initial underbars in method name */ 8170 for (; *cp; cp++) 8171 if (*cp == '_') 8172 *cp = ':'; /* replace remaining '_' with ':' */ 8173 *cp++ = ']'; /* closing right brace */ 8174 *cp++ = 0; /* string terminator */ 8175 return demangled; 8176 } 8177 else 8178 return mangled; /* not an objc mangled name */ 8179} 8180 8181static const char * 8182objc_printable_name (decl, kind) 8183 tree decl; 8184 char **kind; 8185{ 8186 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl))); 8187} 8188 8189static void 8190init_objc () 8191{ 8192 /* Add the special tree codes of Objective C to the tables. */ 8193 8194#define LAST_CODE LAST_AND_UNUSED_TREE_CODE 8195 8196 gcc_obstack_init (&util_obstack); 8197 util_firstobj = (char *) obstack_finish (&util_obstack); 8198 8199 bcopy (objc_tree_code_type, 8200 tree_code_type + (int) LAST_CODE, 8201 (int) LAST_OBJC_TREE_CODE - (int) LAST_CODE); 8202 bcopy ((char *) objc_tree_code_length, 8203 (char *) (tree_code_length + (int) LAST_CODE), 8204 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) 8205 * sizeof (int))); 8206 bcopy ((char *) objc_tree_code_name, 8207 (char *) (tree_code_name + (int) LAST_CODE), 8208 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) 8209 * sizeof (char *))); 8210 8211 errbuf = (char *)xmalloc (BUFSIZE); 8212 hash_init (); 8213 synth_module_prologue (); 8214 8215 /* Change the default error function */ 8216 decl_printable_name = (char* (*)()) objc_printable_name; 8217} 8218 8219static void 8220finish_objc () 8221{ 8222 struct imp_entry *impent; 8223 tree chain; 8224 /* The internally generated initializers appear to have missing braces. 8225 Don't warn about this. */ 8226 int save_warn_missing_braces = warn_missing_braces; 8227 warn_missing_braces = 0; 8228 8229 generate_forward_declaration_to_string_table (); 8230 8231#ifdef OBJC_PROLOGUE 8232 OBJC_PROLOGUE; 8233#endif 8234 8235 /* Process the static instances here because initialization of objc_symtab 8236 depends on them. */ 8237 if (objc_static_instances) 8238 generate_static_references (); 8239 8240 if (implementation_context || class_names_chain 8241 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) 8242 generate_objc_symtab_decl (); 8243 8244 for (impent = imp_list; impent; impent = impent->next) 8245 { 8246 implementation_context = impent->imp_context; 8247 implementation_template = impent->imp_template; 8248 8249 UOBJC_CLASS_decl = impent->class_decl; 8250 UOBJC_METACLASS_decl = impent->meta_decl; 8251 8252 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) 8253 { 8254 /* all of the following reference the string pool... */ 8255 generate_ivar_lists (); 8256 generate_dispatch_tables (); 8257 generate_shared_structures (); 8258 } 8259 else 8260 { 8261 generate_dispatch_tables (); 8262 generate_category (implementation_context); 8263 } 8264 } 8265 8266 /* If we are using an array of selectors, we must always 8267 finish up the array decl even if no selectors were used. */ 8268 if (! flag_next_runtime || sel_ref_chain) 8269 build_selector_translation_table (); 8270 8271 if (protocol_chain) 8272 generate_protocols (); 8273 8274 if (implementation_context || class_names_chain || objc_static_instances 8275 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) 8276 { 8277 /* Arrange for Objc data structures to be initialized at run time. */ 8278 char *init_name = build_module_descriptor (); 8279 if (init_name) 8280 assemble_constructor (init_name); 8281 } 8282 8283 /* Dump the class references. This forces the appropriate classes 8284 to be linked into the executable image, preserving unix archive 8285 semantics. This can be removed when we move to a more dynamically 8286 linked environment. */ 8287 8288 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain)) 8289 { 8290 handle_class_ref (chain); 8291 if (TREE_PURPOSE (chain)) 8292 generate_classref_translation_entry (chain); 8293 } 8294 8295 for (impent = imp_list; impent; impent = impent->next) 8296 handle_impent (impent); 8297 8298 /* Dump the string table last. */ 8299 8300 generate_strings (); 8301 8302 if (flag_gen_declaration) 8303 { 8304 add_class (implementation_context); 8305 dump_interface (gen_declaration_file, implementation_context); 8306 } 8307 8308 if (warn_selector) 8309 { 8310 int slot; 8311 hash hsh; 8312 8313 /* Run through the selector hash tables and print a warning for any 8314 selector which has multiple methods. */ 8315 8316 for (slot = 0; slot < SIZEHASHTABLE; slot++) 8317 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next) 8318 if (hsh->list) 8319 { 8320 tree meth = hsh->key; 8321 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL 8322 ? '-' : '+'); 8323 attr loop; 8324 8325 warning ("potential selector conflict for method `%s'", 8326 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth))); 8327 warn_with_method ("found", type, meth); 8328 for (loop = hsh->list; loop; loop = loop->next) 8329 warn_with_method ("found", type, loop->value); 8330 } 8331 8332 for (slot = 0; slot < SIZEHASHTABLE; slot++) 8333 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next) 8334 if (hsh->list) 8335 { 8336 tree meth = hsh->key; 8337 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL 8338 ? '-' : '+'); 8339 attr loop; 8340 8341 warning ("potential selector conflict for method `%s'", 8342 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth))); 8343 warn_with_method ("found", type, meth); 8344 for (loop = hsh->list; loop; loop = loop->next) 8345 warn_with_method ("found", type, loop->value); 8346 } 8347 } 8348 8349 warn_missing_braces = save_warn_missing_braces; 8350} 8351 8352/* Subroutines of finish_objc. */ 8353 8354static void 8355generate_classref_translation_entry (chain) 8356 tree chain; 8357{ 8358 tree expr, name, decl_specs, decl, sc_spec; 8359 tree type; 8360 8361 type = TREE_TYPE (TREE_PURPOSE (chain)); 8362 8363 expr = add_objc_string (TREE_VALUE (chain), class_names); 8364 expr = build_c_cast (type, expr); /* cast! */ 8365 8366 name = DECL_NAME (TREE_PURPOSE (chain)); 8367 8368 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]); 8369 8370 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */ 8371 decl_specs = tree_cons (NULL_TREE, type, sc_spec); 8372 8373 /* The decl that is returned from start_decl is the one that we 8374 forward declared in build_class_reference. */ 8375 decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE); 8376 finish_decl (decl, expr, NULL_TREE); 8377 return; 8378} 8379 8380static void 8381handle_class_ref (chain) 8382 tree chain; 8383{ 8384 char *name = IDENTIFIER_POINTER (TREE_VALUE (chain)); 8385 if (! flag_next_runtime) 8386 { 8387 tree decl; 8388 char *string = (char *) alloca (strlen (name) + 30); 8389 tree exp; 8390 8391 sprintf (string, "%sobjc_class_name_%s", 8392 (flag_next_runtime ? "." : "__"), name); 8393 8394 /* Make a decl for this name, so we can use its address in a tree. */ 8395 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node); 8396 DECL_EXTERNAL (decl) = 1; 8397 TREE_PUBLIC (decl) = 1; 8398 8399 pushdecl (decl); 8400 rest_of_decl_compilation (decl, 0, 0, 0); 8401 8402 /* Make following constant read-only (why not)? */ 8403 readonly_data_section (); 8404 8405 exp = build1 (ADDR_EXPR, string_type_node, decl); 8406 8407 /* Align the section properly. */ 8408 assemble_constant_align (exp); 8409 8410 /* Inform the assembler about this new external thing. */ 8411 assemble_external (decl); 8412 8413 /* Output a constant to reference this address. */ 8414 output_constant (exp, int_size_in_bytes (string_type_node)); 8415 } 8416 else 8417 { 8418 /* This overreliance on our assembler (i.e. lack of portability) 8419 should be dealt with at some point. The GNU strategy (above) 8420 won't work either, but it is a start. */ 8421 char *string = (char *) alloca (strlen (name) + 30); 8422 sprintf (string, ".reference .objc_class_name_%s", name); 8423 assemble_asm (my_build_string (strlen (string) + 1, string)); 8424 } 8425} 8426 8427static void 8428handle_impent (impent) 8429 struct imp_entry *impent; 8430{ 8431 implementation_context = impent->imp_context; 8432 implementation_template = impent->imp_template; 8433 8434 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) 8435 { 8436 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)); 8437 char *string = (char *) alloca (strlen (class_name) + 30); 8438 8439 if (flag_next_runtime) 8440 { 8441 /* Grossly unportable. 8442 People should know better than to assume 8443 such things about assembler syntax! */ 8444 sprintf (string, ".objc_class_name_%s=0", class_name); 8445 assemble_asm (my_build_string (strlen (string) + 1, string)); 8446 8447 sprintf (string, ".globl .objc_class_name_%s", class_name); 8448 assemble_asm (my_build_string (strlen (string) + 1, string)); 8449 } 8450 8451 else 8452 { 8453 sprintf (string, "%sobjc_class_name_%s", 8454 (flag_next_runtime ? "." : "__"), class_name); 8455 assemble_global (string); 8456 assemble_label (string); 8457 } 8458 } 8459 8460 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) 8461 { 8462 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)); 8463 char *class_super_name 8464 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)); 8465 char *string = (char *) alloca (strlen (class_name) 8466 + strlen (class_super_name) + 30); 8467 8468 /* Do the same for categories. Even though no references to these 8469 symbols are generated automatically by the compiler, it gives 8470 you a handle to pull them into an archive by hand. */ 8471 if (flag_next_runtime) 8472 { 8473 /* Grossly unportable. */ 8474 sprintf (string, ".objc_category_name_%s_%s=0", 8475 class_name, class_super_name); 8476 assemble_asm (my_build_string (strlen (string) + 1, string)); 8477 8478 sprintf (string, ".globl .objc_category_name_%s_%s", 8479 class_name, class_super_name); 8480 assemble_asm (my_build_string (strlen (string) + 1, string)); 8481 } 8482 8483 else 8484 { 8485 sprintf (string, "%sobjc_category_name_%s_%s", 8486 (flag_next_runtime ? "." : "__"), 8487 class_name, class_super_name); 8488 assemble_global (string); 8489 assemble_label (string); 8490 } 8491 } 8492} 8493 8494#ifdef DEBUG 8495 8496static void 8497objc_debug (fp) 8498 FILE *fp; 8499{ 8500 char *buf = (char *)xmalloc (256); 8501 8502 { /* dump function prototypes */ 8503 tree loop = UOBJC_MODULES_decl; 8504 8505 fprintf (fp, "\n\nfunction prototypes:\n"); 8506 while (loop) 8507 { 8508 if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop)) 8509 { 8510 /* We have a function definition: generate prototype. */ 8511 bzero (errbuf, BUFSIZE); 8512 gen_declaration (loop, errbuf); 8513 fprintf (fp, "%s;\n", errbuf); 8514 } 8515 loop = TREE_CHAIN (loop); 8516 } 8517 } 8518 { 8519 /* Dump global chains. */ 8520 tree loop; 8521 int i, index = 0, offset = 0; 8522 hash hashlist; 8523 8524 for (i = 0; i < SIZEHASHTABLE; i++) 8525 { 8526 if (hashlist = nst_method_hash_list[i]) 8527 { 8528 fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i); 8529 do 8530 { 8531 bzero (buf, 256); 8532 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf)); 8533 hashlist = hashlist->next; 8534 } 8535 while (hashlist); 8536 } 8537 } 8538 8539 for (i = 0; i < SIZEHASHTABLE; i++) 8540 { 8541 if (hashlist = cls_method_hash_list[i]) 8542 { 8543 fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i); 8544 do 8545 { 8546 bzero (buf, 256); 8547 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf)); 8548 hashlist = hashlist->next; 8549 } 8550 while (hashlist); 8551 } 8552 } 8553 8554 fprintf (fp, "\nsel_refdef_chain:\n"); 8555 for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop)) 8556 { 8557 fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset, 8558 IDENTIFIER_POINTER (TREE_VALUE (loop))); 8559 index++; 8560 /* add one for the '\0' character */ 8561 offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1; 8562 } 8563 8564 fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index); 8565 } 8566} 8567#endif 8568 8569void 8570print_lang_statistics () 8571{ 8572} 8573