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