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