Initial revision
[official-gcc.git] / gcc / objc / objc-act.c
bloba0b20fea00bfe001c06f78676fba4ce877e32358
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
3 Contributed by Steve Naroff.
5 This file is part of GNU CC.
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.
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.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Purpose: This module implements the Objective-C 4.0 language.
24 compatibility issues (with the Stepstone translator):
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.
37 code generation `options':
39 - OBJC_INT_SELECTORS */
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 "except.h"
50 #include "function.h"
53 /* This is the default way of generating a method name. */
54 /* I am not sure it is really correct.
55 Perhaps there's a danger that it will make name conflicts
56 if method names contain underscores. -- rms. */
57 #ifndef OBJC_GEN_METHOD_LABEL
58 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
59 do { \
60 char *temp; \
61 sprintf ((BUF), "_%s_%s_%s_%s", \
62 ((IS_INST) ? "i" : "c"), \
63 (CLASS_NAME), \
64 ((CAT_NAME)? (CAT_NAME) : ""), \
65 (SEL_NAME)); \
66 for (temp = (BUF); *temp; temp++) \
67 if (*temp == ':') *temp = '_'; \
68 } while (0)
69 #endif
71 /* These need specifying. */
72 #ifndef OBJC_FORWARDING_STACK_OFFSET
73 #define OBJC_FORWARDING_STACK_OFFSET 0
74 #endif
76 #ifndef OBJC_FORWARDING_MIN_OFFSET
77 #define OBJC_FORWARDING_MIN_OFFSET 0
78 #endif
80 /* Define the special tree codes that we use. */
82 /* Table indexed by tree code giving a string containing a character
83 classifying the tree code. Possibilities are
84 t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */
86 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
88 char *objc_tree_code_type[] = {
89 "x",
90 #include "objc-tree.def"
92 #undef DEFTREECODE
94 /* Table indexed by tree code giving number of expression
95 operands beyond the fixed part of the node structure.
96 Not used for types or decls. */
98 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
100 int objc_tree_code_length[] = {
102 #include "objc-tree.def"
104 #undef DEFTREECODE
106 /* Names of tree components.
107 Used for printing out the tree and error messages. */
108 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
110 char *objc_tree_code_name[] = {
111 "@@dummy",
112 #include "objc-tree.def"
114 #undef DEFTREECODE
116 /* Set up for use of obstacks. */
118 #include "obstack.h"
120 #define obstack_chunk_alloc xmalloc
121 #define obstack_chunk_free free
123 /* This obstack is used to accumulate the encoding of a data type. */
124 static struct obstack util_obstack;
125 /* This points to the beginning of obstack contents,
126 so we can free the whole contents. */
127 char *util_firstobj;
129 /* List of classes with list of their static instances. */
130 static tree objc_static_instances = NULL_TREE;
132 /* The declaration of the array administrating the static instances. */
133 static tree static_instances_decl = NULL_TREE;
135 /* for encode_method_def */
136 #include "rtl.h"
137 #include "c-parse.h"
139 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
140 #define PROTOCOL_VERSION 2
142 #define OBJC_ENCODE_INLINE_DEFS 0
143 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
145 /*** Private Interface (procedures) ***/
147 /* Used by compile_file. */
149 static void init_objc PROTO((void));
150 static void finish_objc PROTO((void));
152 /* Code generation. */
154 static void synth_module_prologue PROTO((void));
155 static tree build_constructor PROTO((tree, tree));
156 static char *build_module_descriptor PROTO((void));
157 static tree init_module_descriptor PROTO((tree));
158 static tree build_objc_method_call PROTO((int, tree, tree,
159 tree, tree, tree));
160 static void generate_strings PROTO((void));
161 static tree get_proto_encoding PROTO((tree));
162 static void build_selector_translation_table PROTO((void));
163 static tree build_ivar_chain PROTO((tree, int));
165 static tree objc_add_static_instance PROTO((tree, tree));
167 static tree build_ivar_template PROTO((void));
168 static tree build_method_template PROTO((void));
169 static tree build_private_template PROTO((tree));
170 static void build_class_template PROTO((void));
171 static void build_selector_template PROTO((void));
172 static void build_category_template PROTO((void));
173 static tree build_super_template PROTO((void));
174 static tree build_category_initializer PROTO((tree, tree, tree,
175 tree, tree, tree));
176 static tree build_protocol_initializer PROTO((tree, tree, tree,
177 tree, tree));
179 static void synth_forward_declarations PROTO((void));
180 static void generate_ivar_lists PROTO((void));
181 static void generate_dispatch_tables PROTO((void));
182 static void generate_shared_structures PROTO((void));
183 static tree generate_protocol_list PROTO((tree));
184 static void generate_forward_declaration_to_string_table PROTO((void));
185 static void build_protocol_reference PROTO((tree));
187 static tree init_selector PROTO((int));
188 static tree build_keyword_selector PROTO((tree));
189 static tree synth_id_with_class_suffix PROTO((char *, tree));
191 /* From expr.c */
192 extern int apply_args_register_offset PROTO((int));
194 /* Misc. bookkeeping */
196 typedef struct hashed_entry *hash;
197 typedef struct hashed_attribute *attr;
199 struct hashed_attribute
201 attr next;
202 tree value;
204 struct hashed_entry
206 attr list;
207 hash next;
208 tree key;
211 static void hash_init PROTO((void));
212 static void hash_enter PROTO((hash *, tree));
213 static hash hash_lookup PROTO((hash *, tree));
214 static void hash_add_attr PROTO((hash, tree));
215 static tree lookup_method PROTO((tree, tree));
216 static tree lookup_instance_method_static PROTO((tree, tree));
217 static tree lookup_class_method_static PROTO((tree, tree));
218 static tree add_class PROTO((tree));
219 static void add_category PROTO((tree, tree));
221 enum string_section
223 class_names, /* class, category, protocol, module names */
224 meth_var_names, /* method and variable names */
225 meth_var_types /* method and variable type descriptors */
228 static tree add_objc_string PROTO((tree,
229 enum string_section));
230 static tree build_objc_string_decl PROTO((tree,
231 enum string_section));
232 static tree build_selector_reference_decl PROTO((tree));
234 /* Protocol additions. */
236 static tree add_protocol PROTO((tree));
237 static tree lookup_protocol PROTO((tree));
238 static tree lookup_and_install_protocols PROTO((tree));
240 /* Type encoding. */
242 static void encode_type_qualifiers PROTO((tree));
243 static void encode_pointer PROTO((tree, int, int));
244 static void encode_array PROTO((tree, int, int));
245 static void encode_aggregate PROTO((tree, int, int));
246 static void encode_bitfield PROTO((int, int));
247 static void encode_type PROTO((tree, int, int));
248 static void encode_field_decl PROTO((tree, int, int));
250 static void really_start_method PROTO((tree, tree));
251 static int comp_method_with_proto PROTO((tree, tree));
252 static int comp_proto_with_proto PROTO((tree, tree));
253 static tree get_arg_type_list PROTO((tree, int, int));
254 static tree expr_last PROTO((tree));
256 /* Utilities for debugging and error diagnostics. */
258 static void warn_with_method PROTO((char *, int, tree));
259 static void error_with_ivar PROTO((char *, tree, tree));
260 static char *gen_method_decl PROTO((tree, char *));
261 static char *gen_declaration PROTO((tree, char *));
262 static char *gen_declarator PROTO((tree, char *, char *));
263 static int is_complex_decl PROTO((tree));
264 static void adorn_decl PROTO((tree, char *));
265 static void dump_interface PROTO((FILE *, tree));
267 /* Everything else. */
269 static void objc_fatal PROTO((void));
270 static tree define_decl PROTO((tree, tree));
271 static tree lookup_method_in_protocol_list PROTO((tree, tree, int));
272 static tree lookup_protocol_in_reflist PROTO((tree, tree));
273 static tree create_builtin_decl PROTO((enum tree_code,
274 tree, char *));
275 static tree my_build_string PROTO((int, char *));
276 static void build_objc_symtab_template PROTO((void));
277 static tree init_def_list PROTO((tree));
278 static tree init_objc_symtab PROTO((tree));
279 static void forward_declare_categories PROTO((void));
280 static void generate_objc_symtab_decl PROTO((void));
281 static tree build_selector PROTO((tree));
282 static tree build_msg_pool_reference PROTO((int));
283 static tree build_typed_selector_reference PROTO((tree, tree));
284 static tree build_selector_reference PROTO((tree));
285 static tree build_class_reference_decl PROTO((tree));
286 static void add_class_reference PROTO((tree));
287 static tree objc_copy_list PROTO((tree, tree *));
288 static tree build_protocol_template PROTO((void));
289 static tree build_descriptor_table_initializer PROTO((tree, tree));
290 static tree build_method_prototype_list_template PROTO((tree, int));
291 static tree build_method_prototype_template PROTO((void));
292 static int forwarding_offset PROTO((tree));
293 static tree encode_method_prototype PROTO((tree, tree));
294 static tree generate_descriptor_table PROTO((tree, char *, int, tree, tree));
295 static void generate_method_descriptors PROTO((tree));
296 static tree build_tmp_function_decl PROTO((void));
297 static void hack_method_prototype PROTO((tree, tree));
298 static void generate_protocol_references PROTO((tree));
299 static void generate_protocols PROTO((void));
300 static void check_ivars PROTO((tree, tree));
301 static tree build_ivar_list_template PROTO((tree, int));
302 static tree build_method_list_template PROTO((tree, int));
303 static tree build_ivar_list_initializer PROTO((tree, tree));
304 static tree generate_ivars_list PROTO((tree, char *,
305 int, tree));
306 static tree build_dispatch_table_initializer PROTO((tree, tree));
307 static tree generate_dispatch_table PROTO((tree, char *,
308 int, tree));
309 static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree,
310 tree, int, tree, tree,
311 tree));
312 static void generate_category PROTO((tree));
313 static int is_objc_type_qualifier PROTO((tree));
314 static tree adjust_type_for_id_default PROTO((tree));
315 static tree check_duplicates PROTO((hash));
316 static tree receiver_is_class_object PROTO((tree));
317 static int check_methods PROTO((tree, tree, int));
318 static int conforms_to_protocol PROTO((tree, tree));
319 static void check_protocols PROTO((tree, char *, char *));
320 static tree encode_method_def PROTO((tree));
321 static void gen_declspecs PROTO((tree, char *, int));
322 static void generate_classref_translation_entry PROTO((tree));
323 static void handle_class_ref PROTO((tree));
325 /*** Private Interface (data) ***/
327 /* Reserved tag definitions. */
329 #define TYPE_ID "id"
330 #define TAG_OBJECT "objc_object"
331 #define TAG_CLASS "objc_class"
332 #define TAG_SUPER "objc_super"
333 #define TAG_SELECTOR "objc_selector"
335 #define UTAG_CLASS "_objc_class"
336 #define UTAG_IVAR "_objc_ivar"
337 #define UTAG_IVAR_LIST "_objc_ivar_list"
338 #define UTAG_METHOD "_objc_method"
339 #define UTAG_METHOD_LIST "_objc_method_list"
340 #define UTAG_CATEGORY "_objc_category"
341 #define UTAG_MODULE "_objc_module"
342 #define UTAG_STATICS "_objc_statics"
343 #define UTAG_SYMTAB "_objc_symtab"
344 #define UTAG_SUPER "_objc_super"
345 #define UTAG_SELECTOR "_objc_selector"
347 #define UTAG_PROTOCOL "_objc_protocol"
348 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
349 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
350 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
352 #define STRING_OBJECT_CLASS_NAME "NXConstantString"
353 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
355 static char *TAG_GETCLASS;
356 static char *TAG_GETMETACLASS;
357 static char *TAG_MSGSEND;
358 static char *TAG_MSGSENDSUPER;
359 static char *TAG_EXECCLASS;
361 /* Set by `continue_class' and checked by `is_public'. */
363 #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
364 #define TYPED_OBJECT(type) \
365 (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
367 /* Some commonly used instances of "identifier_node". */
369 static tree self_id, ucmd_id;
370 static tree unused_list;
372 static tree self_decl, umsg_decl, umsg_super_decl;
373 static tree objc_get_class_decl, objc_get_meta_class_decl;
375 static tree super_type, selector_type, id_type, objc_class_type;
376 static tree instance_type, protocol_type;
378 /* Type checking macros. */
380 #define IS_ID(TYPE) \
381 (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
382 #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
383 (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
384 #define IS_SUPER(TYPE) \
385 (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
387 static tree class_chain = NULL_TREE;
388 static tree alias_chain = NULL_TREE;
389 static tree interface_chain = NULL_TREE;
390 static tree protocol_chain = NULL_TREE;
392 /* Chains to manage selectors that are referenced and defined in the
393 module. */
395 static tree cls_ref_chain = NULL_TREE; /* Classes referenced. */
396 static tree sel_ref_chain = NULL_TREE; /* Selectors referenced. */
398 /* Chains to manage uniquing of strings. */
400 static tree class_names_chain = NULL_TREE;
401 static tree meth_var_names_chain = NULL_TREE;
402 static tree meth_var_types_chain = NULL_TREE;
404 /* Hash tables to manage the global pool of method prototypes. */
406 static hash *nst_method_hash_list = 0;
407 static hash *cls_method_hash_list = 0;
409 /* Backend data declarations. */
411 static tree UOBJC_SYMBOLS_decl;
412 static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl;
413 static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl;
414 static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl;
415 static tree UOBJC_SELECTOR_TABLE_decl;
416 static tree UOBJC_MODULES_decl;
417 static tree UOBJC_STRINGS_decl;
419 /* The following are used when compiling a class implementation.
420 implementation_template will normally be an interface, however if
421 none exists this will be equal to implementation_context...it is
422 set in start_class. */
424 static tree implementation_context = NULL_TREE;
425 static tree implementation_template = NULL_TREE;
427 struct imp_entry
429 struct imp_entry *next;
430 tree imp_context;
431 tree imp_template;
432 tree class_decl; /* _OBJC_CLASS_<my_name>; */
433 tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
436 static void handle_impent PROTO((struct imp_entry *));
438 static struct imp_entry *imp_list = 0;
439 static int imp_count = 0; /* `@implementation' */
440 static int cat_count = 0; /* `@category' */
442 static tree objc_class_template, objc_category_template, uprivate_record;
443 static tree objc_protocol_template, objc_selector_template;
444 static tree ucls_super_ref, uucls_super_ref;
446 static tree objc_method_template, objc_ivar_template;
447 static tree objc_symtab_template, objc_module_template;
448 static tree objc_super_template, objc_object_reference;
450 static tree objc_object_id, objc_class_id, objc_id_id;
451 static tree constant_string_id;
452 static tree constant_string_type;
453 static tree UOBJC_SUPER_decl;
455 static tree method_context = NULL_TREE;
456 static int method_slot = 0; /* Used by start_method_def, */
458 #define BUFSIZE 1024
460 static char *errbuf; /* Buffer for error diagnostics */
462 /* Data imported from tree.c. */
464 extern enum debug_info_type write_symbols;
466 /* Data imported from toplev.c. */
468 extern char *dump_base_name;
470 /* Generate code for GNU or NeXT runtime environment. */
472 #ifdef NEXT_OBJC_RUNTIME
473 int flag_next_runtime = 1;
474 #else
475 int flag_next_runtime = 0;
476 #endif
478 int flag_typed_selectors;
480 /* Open and close the file for outputting class declarations, if requested. */
482 int flag_gen_declaration = 0;
484 FILE *gen_declaration_file;
486 /* Warn if multiple methods are seen for the same selector, but with
487 different argument types. */
489 int warn_selector = 0;
491 /* Warn if methods required by a protocol are not implemented in the
492 class adopting it. When turned off, methods inherited to that
493 class are also considered implemented */
495 int flag_warn_protocol = 1;
497 /* Tells "encode_pointer/encode_aggregate" whether we are generating
498 type descriptors for instance variables (as opposed to methods).
499 Type descriptors for instance variables contain more information
500 than methods (for static typing and embedded structures). This
501 was added to support features being planned for dbkit2. */
503 static int generating_instance_variables = 0;
505 void
506 lang_init ()
508 #if !USE_CPPLIB
509 /* The beginning of the file is a new line; check for #.
510 With luck, we discover the real source file's name from that
511 and put it in input_filename. */
512 ungetc (check_newline (), finput);
513 #endif
515 /* The line number can be -1 if we had -g3 and the input file
516 had a directive specifying line 0. But we want predefined
517 functions to have a line number of 0, not -1. */
518 if (lineno == -1)
519 lineno = 0;
521 /* If gen_declaration desired, open the output file. */
522 if (flag_gen_declaration)
524 int dump_base_name_length = strlen (dump_base_name);
525 register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
526 strcpy (dumpname, dump_base_name);
527 strcat (dumpname, ".decl");
528 gen_declaration_file = fopen (dumpname, "w");
529 if (gen_declaration_file == 0)
530 pfatal_with_name (dumpname);
533 if (flag_next_runtime)
535 TAG_GETCLASS = "objc_getClass";
536 TAG_GETMETACLASS = "objc_getMetaClass";
537 TAG_MSGSEND = "objc_msgSend";
538 TAG_MSGSENDSUPER = "objc_msgSendSuper";
539 TAG_EXECCLASS = "__objc_execClass";
541 else
543 TAG_GETCLASS = "objc_get_class";
544 TAG_GETMETACLASS = "objc_get_meta_class";
545 TAG_MSGSEND = "objc_msg_lookup";
546 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
547 TAG_EXECCLASS = "__objc_exec_class";
548 flag_typed_selectors = 1;
551 if (doing_objc_thang)
552 init_objc ();
555 static void
556 objc_fatal ()
558 fatal ("Objective-C text in C source file");
561 void
562 finish_file ()
564 if (doing_objc_thang)
565 finish_objc (); /* Objective-C finalization */
567 if (gen_declaration_file)
568 fclose (gen_declaration_file);
571 void
572 lang_finish ()
576 char *
577 lang_identify ()
579 return "objc";
583 lang_decode_option (p)
584 char *p;
586 if (!strcmp (p, "-lang-objc"))
587 doing_objc_thang = 1;
588 else if (!strcmp (p, "-gen-decls"))
589 flag_gen_declaration = 1;
590 else if (!strcmp (p, "-Wselector"))
591 warn_selector = 1;
592 else if (!strcmp (p, "-Wno-selector"))
593 warn_selector = 0;
594 else if (!strcmp (p, "-Wprotocol"))
595 flag_warn_protocol = 1;
596 else if (!strcmp (p, "-Wno-protocol"))
597 flag_warn_protocol = 0;
598 else if (!strcmp (p, "-fgnu-runtime"))
599 flag_next_runtime = 0;
600 else if (!strcmp (p, "-fno-next-runtime"))
601 flag_next_runtime = 0;
602 else if (!strcmp (p, "-fno-gnu-runtime"))
603 flag_next_runtime = 1;
604 else if (!strcmp (p, "-fnext-runtime"))
605 flag_next_runtime = 1;
606 else
607 return c_decode_option (p);
609 return 1;
612 static tree
613 define_decl (declarator, declspecs)
614 tree declarator;
615 tree declspecs;
617 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE);
618 finish_decl (decl, NULL_TREE, NULL_TREE);
619 return decl;
622 /* Return 1 if LHS and RHS are compatible types for assignment or
623 various other operations. Return 0 if they are incompatible, and
624 return -1 if we choose to not decide. When the operation is
625 REFLEXIVE, check for compatibility in either direction.
627 For statically typed objects, an assignment of the form `a' = `b'
628 is permitted if:
630 `a' is of type "id",
631 `a' and `b' are the same class type, or
632 `a' and `b' are of class types A and B such that B is a descendant of A. */
635 maybe_objc_comptypes (lhs, rhs, reflexive)
636 tree lhs, rhs;
637 int reflexive;
639 if (doing_objc_thang)
640 return objc_comptypes (lhs, rhs, reflexive);
641 return -1;
644 static tree
645 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
646 tree rproto_list;
647 tree sel_name;
648 int class_meth;
650 tree rproto, p;
651 tree fnd = 0;
653 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
655 p = TREE_VALUE (rproto);
657 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
659 if ((fnd = lookup_method (class_meth
660 ? PROTOCOL_CLS_METHODS (p)
661 : PROTOCOL_NST_METHODS (p), sel_name)))
663 else if (PROTOCOL_LIST (p))
664 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
665 sel_name, class_meth);
667 else
668 ; /* An identifier...if we could not find a protocol. */
670 if (fnd)
671 return fnd;
674 return 0;
677 static tree
678 lookup_protocol_in_reflist (rproto_list, lproto)
679 tree rproto_list;
680 tree lproto;
682 tree rproto, p;
684 /* Make sure the protocol is support by the object on the rhs. */
685 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
687 tree fnd = 0;
688 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
690 p = TREE_VALUE (rproto);
692 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
694 if (lproto == p)
695 fnd = lproto;
697 else if (PROTOCOL_LIST (p))
698 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
701 if (fnd)
702 return fnd;
705 else
706 ; /* An identifier...if we could not find a protocol. */
708 return 0;
711 /* Return 1 if LHS and RHS are compatible types for assignment
712 or various other operations. Return 0 if they are incompatible,
713 and return -1 if we choose to not decide. When the operation
714 is REFLEXIVE, check for compatibility in either direction. */
717 objc_comptypes (lhs, rhs, reflexive)
718 tree lhs;
719 tree rhs;
720 int reflexive;
722 /* New clause for protocols. */
724 if (TREE_CODE (lhs) == POINTER_TYPE
725 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
726 && TREE_CODE (rhs) == POINTER_TYPE
727 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
729 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
730 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
732 if (lhs_is_proto)
734 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
735 tree rproto, rproto_list;
736 tree p;
738 if (rhs_is_proto)
740 rproto_list = TYPE_PROTOCOL_LIST (rhs);
742 /* Make sure the protocol is supported by the object
743 on the rhs. */
744 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
746 p = TREE_VALUE (lproto);
747 rproto = lookup_protocol_in_reflist (rproto_list, p);
749 if (!rproto)
750 warning ("object does not conform to the `%s' protocol",
751 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
754 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
756 tree rname = TYPE_NAME (TREE_TYPE (rhs));
757 tree rinter;
759 /* Make sure the protocol is supported by the object
760 on the rhs. */
761 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
763 p = TREE_VALUE (lproto);
764 rproto = 0;
765 rinter = lookup_interface (rname);
767 while (rinter && !rproto)
769 tree cat;
771 rproto_list = CLASS_PROTOCOL_LIST (rinter);
772 rproto = lookup_protocol_in_reflist (rproto_list, p);
774 /* Check for protocols adopted by categories. */
775 cat = CLASS_CATEGORY_LIST (rinter);
776 while (cat && !rproto)
778 rproto_list = CLASS_PROTOCOL_LIST (cat);
779 rproto = lookup_protocol_in_reflist (rproto_list, p);
781 cat = CLASS_CATEGORY_LIST (cat);
784 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
787 if (!rproto)
788 warning ("class `%s' does not implement the `%s' protocol",
789 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
790 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
794 /* May change...based on whether there was any mismatch */
795 return 1;
797 else if (rhs_is_proto)
798 /* Lhs is not a protocol...warn if it is statically typed */
799 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
801 else
802 /* Defer to comptypes .*/
803 return -1;
806 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
807 ; /* Fall thru. This is the case we have been handling all along */
808 else
809 /* Defer to comptypes. */
810 return -1;
812 /* `id' = `<class> *', `<class> *' = `id' */
814 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
815 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
816 return 1;
818 /* `id' = `Class', `Class' = `id' */
820 else if ((TYPE_NAME (lhs) == objc_object_id
821 && TYPE_NAME (rhs) == objc_class_id)
822 || (TYPE_NAME (lhs) == objc_class_id
823 && TYPE_NAME (rhs) == objc_object_id))
824 return 1;
826 /* `<class> *' = `<class> *' */
828 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
830 tree lname = TYPE_NAME (lhs);
831 tree rname = TYPE_NAME (rhs);
832 tree inter;
834 if (lname == rname)
835 return 1;
837 /* If the left hand side is a super class of the right hand side,
838 allow it. */
839 for (inter = lookup_interface (rname); inter;
840 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
841 if (lname == CLASS_SUPER_NAME (inter))
842 return 1;
844 /* Allow the reverse when reflexive. */
845 if (reflexive)
846 for (inter = lookup_interface (lname); inter;
847 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
848 if (rname == CLASS_SUPER_NAME (inter))
849 return 1;
851 return 0;
853 else
854 /* Defer to comptypes. */
855 return -1;
858 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
860 void
861 objc_check_decl (decl)
862 tree decl;
864 tree type = TREE_TYPE (decl);
866 if (TREE_CODE (type) == RECORD_TYPE
867 && TREE_STATIC_TEMPLATE (type)
868 && type != constant_string_type)
870 error_with_decl (decl, "`%s' cannot be statically allocated");
871 fatal ("statically allocated objects not supported");
875 void
876 maybe_objc_check_decl (decl)
877 tree decl;
879 if (doing_objc_thang)
880 objc_check_decl (decl);
883 /* Implement static typing. At this point, we know we have an interface. */
885 tree
886 get_static_reference (interface, protocols)
887 tree interface;
888 tree protocols;
890 tree type = xref_tag (RECORD_TYPE, interface);
892 if (protocols)
894 tree t, m = TYPE_MAIN_VARIANT (type);
896 push_obstacks_nochange ();
897 end_temporary_allocation ();
898 t = copy_node (type);
899 TYPE_BINFO (t) = make_tree_vec (2);
900 pop_obstacks ();
902 /* Add this type to the chain of variants of TYPE. */
903 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
904 TYPE_NEXT_VARIANT (m) = t;
906 /* Look up protocols and install in lang specific list. */
907 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
909 /* This forces a new pointer type to be created later
910 (in build_pointer_type)...so that the new template
911 we just created will actually be used...what a hack! */
912 if (TYPE_POINTER_TO (t))
913 TYPE_POINTER_TO (t) = 0;
915 type = t;
918 return type;
921 tree
922 get_object_reference (protocols)
923 tree protocols;
925 tree type_decl = lookup_name (objc_id_id);
926 tree type;
928 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
930 type = TREE_TYPE (type_decl);
931 if (TYPE_MAIN_VARIANT (type) != id_type)
932 warning ("Unexpected type for `id' (%s)",
933 gen_declaration (type, errbuf));
935 else
936 fatal ("Undefined type `id', please import <objc/objc.h>");
938 /* This clause creates a new pointer type that is qualified with
939 the protocol specification...this info is used later to do more
940 elaborate type checking. */
942 if (protocols)
944 tree t, m = TYPE_MAIN_VARIANT (type);
946 push_obstacks_nochange ();
947 end_temporary_allocation ();
948 t = copy_node (type);
949 TYPE_BINFO (t) = make_tree_vec (2);
950 pop_obstacks ();
952 /* Add this type to the chain of variants of TYPE. */
953 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
954 TYPE_NEXT_VARIANT (m) = t;
956 /* Look up protocols...and install in lang specific list */
957 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
959 /* This forces a new pointer type to be created later
960 (in build_pointer_type)...so that the new template
961 we just created will actually be used...what a hack! */
962 if (TYPE_POINTER_TO (t))
963 TYPE_POINTER_TO (t) = NULL;
965 type = t;
967 return type;
970 static tree
971 lookup_and_install_protocols (protocols)
972 tree protocols;
974 tree proto;
975 tree prev = NULL;
976 tree return_value = protocols;
978 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
980 tree ident = TREE_VALUE (proto);
981 tree p = lookup_protocol (ident);
983 if (!p)
985 error ("Cannot find protocol declaration for `%s'",
986 IDENTIFIER_POINTER (ident));
987 if (prev)
988 TREE_CHAIN (prev) = TREE_CHAIN (proto);
989 else
990 return_value = TREE_CHAIN (proto);
992 else
994 /* Replace identifier with actual protocol node. */
995 TREE_VALUE (proto) = p;
996 prev = proto;
1000 return return_value;
1003 /* Create and push a decl for a built-in external variable or field NAME.
1004 CODE says which.
1005 TYPE is its data type. */
1007 static tree
1008 create_builtin_decl (code, type, name)
1009 enum tree_code code;
1010 tree type;
1011 char *name;
1013 tree decl = build_decl (code, get_identifier (name), type);
1015 if (code == VAR_DECL)
1017 TREE_STATIC (decl) = 1;
1018 make_decl_rtl (decl, 0, 1);
1019 pushdecl (decl);
1022 DECL_ARTIFICIAL (decl) = 1;
1023 return decl;
1026 /* Purpose: "play" parser, creating/installing representations
1027 of the declarations that are required by Objective-C.
1029 Model:
1031 type_spec--------->sc_spec
1032 (tree_list) (tree_list)
1035 identifier_node identifier_node */
1037 static void
1038 synth_module_prologue ()
1040 tree temp_type;
1041 tree super_p;
1043 /* Defined in `objc.h' */
1044 objc_object_id = get_identifier (TAG_OBJECT);
1046 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1048 id_type = build_pointer_type (objc_object_reference);
1050 objc_id_id = get_identifier (TYPE_ID);
1051 objc_class_id = get_identifier (TAG_CLASS);
1053 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1054 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1055 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
1057 /* Declare type of selector-objects that represent an operation name. */
1059 #ifdef OBJC_INT_SELECTORS
1060 /* `unsigned int' */
1061 selector_type = unsigned_type_node;
1062 #else
1063 /* `struct objc_selector *' */
1064 selector_type
1065 = build_pointer_type (xref_tag (RECORD_TYPE,
1066 get_identifier (TAG_SELECTOR)));
1067 #endif /* not OBJC_INT_SELECTORS */
1069 /* Forward declare type, or else the prototype for msgSendSuper will
1070 complain. */
1072 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
1073 get_identifier (TAG_SUPER)));
1076 /* id objc_msgSend (id, SEL, ...); */
1078 temp_type
1079 = build_function_type (id_type,
1080 tree_cons (NULL_TREE, id_type,
1081 tree_cons (NULL_TREE, selector_type,
1082 NULL_TREE)));
1084 if (! flag_next_runtime)
1086 umsg_decl = build_decl (FUNCTION_DECL,
1087 get_identifier (TAG_MSGSEND), temp_type);
1088 DECL_EXTERNAL (umsg_decl) = 1;
1089 TREE_PUBLIC (umsg_decl) = 1;
1090 DECL_INLINE (umsg_decl) = 1;
1091 DECL_ARTIFICIAL (umsg_decl) = 1;
1093 if (flag_traditional && TAG_MSGSEND[0] != '_')
1094 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
1096 make_decl_rtl (umsg_decl, NULL_PTR, 1);
1097 pushdecl (umsg_decl);
1099 else
1100 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0);
1102 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1104 temp_type
1105 = build_function_type (id_type,
1106 tree_cons (NULL_TREE, super_p,
1107 tree_cons (NULL_TREE, selector_type,
1108 NULL_TREE)));
1110 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1111 temp_type, NOT_BUILT_IN, 0);
1113 /* id objc_getClass (const char *); */
1115 temp_type = build_function_type (id_type,
1116 tree_cons (NULL_TREE,
1117 const_string_type_node,
1118 tree_cons (NULL_TREE, void_type_node,
1119 NULL_TREE)));
1121 objc_get_class_decl
1122 = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0);
1124 /* id objc_getMetaClass (const char *); */
1126 objc_get_meta_class_decl
1127 = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0);
1129 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1131 if (! flag_next_runtime)
1133 if (flag_typed_selectors)
1135 /* Suppress outputting debug symbols, because
1136 dbxout_init hasn'r been called yet. */
1137 enum debug_info_type save_write_symbols = write_symbols;
1138 write_symbols = NO_DEBUG;
1140 build_selector_template ();
1141 temp_type = build_array_type (objc_selector_template, NULL_TREE);
1143 write_symbols = save_write_symbols;
1145 else
1146 temp_type = build_array_type (selector_type, NULL_TREE);
1148 layout_type (temp_type);
1149 UOBJC_SELECTOR_TABLE_decl
1150 = create_builtin_decl (VAR_DECL, temp_type,
1151 "_OBJC_SELECTOR_TABLE");
1153 /* Avoid warning when not sending messages. */
1154 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1157 generate_forward_declaration_to_string_table ();
1159 /* Forward declare constant_string_id and constant_string_type. */
1160 constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME);
1161 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
1164 /* Custom build_string which sets TREE_TYPE! */
1166 static tree
1167 my_build_string (len, str)
1168 int len;
1169 char *str;
1171 int wide_flag = 0;
1172 tree a_string = build_string (len, str);
1174 /* Some code from combine_strings, which is local to c-parse.y. */
1175 if (TREE_TYPE (a_string) == int_array_type_node)
1176 wide_flag = 1;
1178 TREE_TYPE (a_string)
1179 = build_array_type (wide_flag ? integer_type_node : char_type_node,
1180 build_index_type (build_int_2 (len - 1, 0)));
1182 TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
1183 TREE_STATIC (a_string) = 1;
1185 return a_string;
1188 /* Return a newly constructed OBJC_STRING_CST node whose value is
1189 the LEN characters at STR.
1190 The TREE_TYPE is not initialized. */
1192 tree
1193 build_objc_string (len, str)
1194 int len;
1195 char *str;
1197 tree s = build_string (len, str);
1199 TREE_SET_CODE (s, OBJC_STRING_CST);
1200 return s;
1203 /* Given a chain of OBJC_STRING_CST's, build a static instance of
1204 NXConstanString which points at the concatenation of those strings.
1205 We place the string object in the __string_objects section of the
1206 __OBJC segment. The Objective-C runtime will initialize the isa
1207 pointers of the string objects to point at the NXConstandString class
1208 object. */
1210 tree
1211 build_objc_string_object (strings)
1212 tree strings;
1214 tree string, initlist, constructor;
1215 int length;
1217 if (!doing_objc_thang)
1218 objc_fatal ();
1220 if (lookup_interface (constant_string_id) == NULL_TREE)
1222 error ("Cannot find interface declaration for `%s'",
1223 IDENTIFIER_POINTER (constant_string_id));
1224 return error_mark_node;
1227 add_class_reference (constant_string_id);
1229 /* Combine_strings will work for OBJC_STRING_CST's too. */
1230 string = combine_strings (strings);
1231 TREE_SET_CODE (string, STRING_CST);
1232 length = TREE_STRING_LENGTH (string) - 1;
1234 if (! flag_next_runtime)
1236 push_obstacks_nochange ();
1237 end_temporary_allocation ();
1238 if (! TREE_PERMANENT (strings))
1239 string = my_build_string (length + 1,
1240 TREE_STRING_POINTER (string));
1243 /* & ((NXConstantString) {0, string, length}) */
1245 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1246 initlist
1247 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1248 initlist);
1249 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1250 constructor = build_constructor (constant_string_type, nreverse (initlist));
1252 if (!flag_next_runtime)
1254 constructor
1255 = objc_add_static_instance (constructor, constant_string_type);
1256 pop_obstacks ();
1259 return (build_unary_op (ADDR_EXPR, constructor, 1));
1262 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1264 static tree
1265 objc_add_static_instance (constructor, class_decl)
1266 tree constructor, class_decl;
1268 static int num_static_inst;
1269 tree *chain, decl, decl_spec, decl_expr;
1270 char buf[256];
1272 push_obstacks_nochange ();
1273 end_temporary_allocation ();
1275 /* Find the list of static instances for the CLASS_DECL. Create one if
1276 not found. */
1277 for (chain = &objc_static_instances;
1278 *chain && TREE_VALUE (*chain) != class_decl;
1279 chain = &TREE_CHAIN (*chain));
1280 if (!*chain)
1282 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1283 add_objc_string (TYPE_NAME (class_decl), class_names);
1286 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1287 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1288 DECL_COMMON (decl) = 1;
1289 TREE_STATIC (decl) = 1;
1290 DECL_ARTIFICIAL (decl) = 1;
1291 pushdecl_top_level (decl);
1292 rest_of_decl_compilation (decl, 0, 1, 0);
1294 /* Do this here so it gets output later instead of possibly
1295 inside something else we are writing. */
1296 DECL_INITIAL (decl) = constructor;
1298 /* Add the DECL to the head of this CLASS' list. */
1299 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1301 pop_obstacks ();
1302 return decl;
1305 /* Build a static constant CONSTRUCTOR
1306 with type TYPE and elements ELTS. */
1308 static tree
1309 build_constructor (type, elts)
1310 tree type, elts;
1312 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
1314 TREE_CONSTANT (constructor) = 1;
1315 TREE_STATIC (constructor) = 1;
1316 TREE_READONLY (constructor) = 1;
1318 return constructor;
1321 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1323 /* Predefine the following data type:
1325 struct _objc_symtab
1327 long sel_ref_cnt;
1328 SEL *refs;
1329 short cls_def_cnt;
1330 short cat_def_cnt;
1331 void *defs[cls_def_cnt + cat_def_cnt];
1332 }; */
1334 static void
1335 build_objc_symtab_template ()
1337 tree field_decl, field_decl_chain, index;
1339 objc_symtab_template
1340 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1342 /* long sel_ref_cnt; */
1344 field_decl = create_builtin_decl (FIELD_DECL,
1345 long_integer_type_node,
1346 "sel_ref_cnt");
1347 field_decl_chain = field_decl;
1349 /* SEL *refs; */
1351 field_decl = create_builtin_decl (FIELD_DECL,
1352 build_pointer_type (selector_type),
1353 "refs");
1354 chainon (field_decl_chain, field_decl);
1356 /* short cls_def_cnt; */
1358 field_decl = create_builtin_decl (FIELD_DECL,
1359 short_integer_type_node,
1360 "cls_def_cnt");
1361 chainon (field_decl_chain, field_decl);
1363 /* short cat_def_cnt; */
1365 field_decl = create_builtin_decl (FIELD_DECL,
1366 short_integer_type_node,
1367 "cat_def_cnt");
1368 chainon (field_decl_chain, field_decl);
1370 /* void *defs[cls_def_cnt + cat_def_cnt]; */
1372 if (!flag_next_runtime)
1373 index = build_index_type (build_int_2 (imp_count + cat_count, 0));
1374 else
1375 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
1376 imp_count == 0 && cat_count == 0
1377 ? -1 : 0));
1378 field_decl = create_builtin_decl (FIELD_DECL,
1379 build_array_type (ptr_type_node, index),
1380 "defs");
1381 chainon (field_decl_chain, field_decl);
1383 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1386 /* Create the initial value for the `defs' field of _objc_symtab.
1387 This is a CONSTRUCTOR. */
1389 static tree
1390 init_def_list (type)
1391 tree type;
1393 tree expr, initlist = NULL_TREE;
1394 struct imp_entry *impent;
1396 if (imp_count)
1397 for (impent = imp_list; impent; impent = impent->next)
1399 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1401 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1402 initlist = tree_cons (NULL_TREE, expr, initlist);
1406 if (cat_count)
1407 for (impent = imp_list; impent; impent = impent->next)
1409 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1411 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1412 initlist = tree_cons (NULL_TREE, expr, initlist);
1416 if (!flag_next_runtime)
1418 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1419 tree expr;
1421 if (static_instances_decl)
1422 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1423 else
1424 expr = build_int_2 (0, 0);
1426 initlist = tree_cons (NULL_TREE, expr, initlist);
1429 return build_constructor (type, nreverse (initlist));
1432 /* Construct the initial value for all of _objc_symtab. */
1434 static tree
1435 init_objc_symtab (type)
1436 tree type;
1438 tree initlist;
1440 /* sel_ref_cnt = { ..., 5, ... } */
1442 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1444 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1446 if (flag_next_runtime || ! sel_ref_chain)
1447 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1448 else
1449 initlist = tree_cons (NULL_TREE,
1450 build_unary_op (ADDR_EXPR,
1451 UOBJC_SELECTOR_TABLE_decl, 1),
1452 initlist);
1454 /* cls_def_cnt = { ..., 5, ... } */
1456 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1458 /* cat_def_cnt = { ..., 5, ... } */
1460 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1462 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1464 if (imp_count || cat_count || static_instances_decl)
1467 tree field = TYPE_FIELDS (type);
1468 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1470 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1471 initlist);
1474 return build_constructor (type, nreverse (initlist));
1477 /* Push forward-declarations of all the categories
1478 so that init_def_list can use them in a CONSTRUCTOR. */
1480 static void
1481 forward_declare_categories ()
1483 struct imp_entry *impent;
1484 tree sav = implementation_context;
1486 for (impent = imp_list; impent; impent = impent->next)
1488 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1490 /* Set an invisible arg to synth_id_with_class_suffix. */
1491 implementation_context = impent->imp_context;
1492 impent->class_decl
1493 = create_builtin_decl (VAR_DECL, objc_category_template,
1494 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
1497 implementation_context = sav;
1500 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
1501 and initialized appropriately. */
1503 static void
1504 generate_objc_symtab_decl ()
1506 tree sc_spec;
1508 if (!objc_category_template)
1509 build_category_template ();
1511 /* forward declare categories */
1512 if (cat_count)
1513 forward_declare_categories ();
1515 if (!objc_symtab_template)
1516 build_objc_symtab_template ();
1518 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1520 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1521 tree_cons (NULL_TREE,
1522 objc_symtab_template, sc_spec),
1524 NULL_TREE, NULL_TREE);
1526 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1527 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1528 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1529 finish_decl (UOBJC_SYMBOLS_decl,
1530 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1531 NULL_TREE);
1534 static tree
1535 init_module_descriptor (type)
1536 tree type;
1538 tree initlist, expr;
1540 /* version = { 1, ... } */
1542 expr = build_int_2 (OBJC_VERSION, 0);
1543 initlist = build_tree_list (NULL_TREE, expr);
1545 /* size = { ..., sizeof (struct objc_module), ... } */
1547 expr = size_in_bytes (objc_module_template);
1548 initlist = tree_cons (NULL_TREE, expr, initlist);
1550 /* name = { ..., "foo.m", ... } */
1552 expr = add_objc_string (get_identifier (input_filename), class_names);
1553 initlist = tree_cons (NULL_TREE, expr, initlist);
1555 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1557 if (UOBJC_SYMBOLS_decl)
1558 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1559 else
1560 expr = build_int_2 (0, 0);
1561 initlist = tree_cons (NULL_TREE, expr, initlist);
1563 return build_constructor (type, nreverse (initlist));
1566 /* Write out the data structures to describe Objective C classes defined.
1567 If appropriate, compile and output a setup function to initialize them.
1568 Return a string which is the name of a function to call to initialize
1569 the Objective C data structures for this file (and perhaps for other files
1570 also).
1572 struct objc_module { ... } _OBJC_MODULE = { ... }; */
1574 static char *
1575 build_module_descriptor ()
1577 tree decl_specs, field_decl, field_decl_chain;
1579 objc_module_template
1580 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1582 /* Long version; */
1584 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1585 field_decl = get_identifier ("version");
1586 field_decl
1587 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1588 field_decl_chain = field_decl;
1590 /* long size; */
1592 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1593 field_decl = get_identifier ("size");
1594 field_decl
1595 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1596 chainon (field_decl_chain, field_decl);
1598 /* char *name; */
1600 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1601 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1602 field_decl
1603 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1604 chainon (field_decl_chain, field_decl);
1606 /* struct objc_symtab *symtab; */
1608 decl_specs = get_identifier (UTAG_SYMTAB);
1609 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1610 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1611 field_decl
1612 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1613 chainon (field_decl_chain, field_decl);
1615 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1617 /* Create an instance of "objc_module". */
1619 decl_specs = tree_cons (NULL_TREE, objc_module_template,
1620 build_tree_list (NULL_TREE,
1621 ridpointers[(int) RID_STATIC]));
1623 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1624 decl_specs, 1, NULL_TREE, NULL_TREE);
1626 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1627 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1628 finish_decl (UOBJC_MODULES_decl,
1629 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1630 NULL_TREE);
1632 /* Mark the decl to avoid "defined but not used" warning. */
1633 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1635 /* Generate a constructor call for the module descriptor.
1636 This code was generated by reading the grammar rules
1637 of c-parse.in; Therefore, it may not be the most efficient
1638 way of generating the requisite code. */
1640 if (flag_next_runtime)
1641 return 0;
1644 tree parms, function_decl, decelerator, void_list_node;
1645 tree function_type;
1646 extern tree get_file_function_name ();
1647 tree init_function_name = get_file_function_name ('I');
1649 /* Declare void __objc_execClass (void *); */
1651 void_list_node = build_tree_list (NULL_TREE, void_type_node);
1652 function_type
1653 = build_function_type (void_type_node,
1654 tree_cons (NULL_TREE, ptr_type_node,
1655 void_list_node));
1656 function_decl = build_decl (FUNCTION_DECL,
1657 get_identifier (TAG_EXECCLASS),
1658 function_type);
1659 DECL_EXTERNAL (function_decl) = 1;
1660 DECL_ARTIFICIAL (function_decl) = 1;
1661 TREE_PUBLIC (function_decl) = 1;
1663 pushdecl (function_decl);
1664 rest_of_decl_compilation (function_decl, 0, 0, 0);
1666 parms
1667 = build_tree_list (NULL_TREE,
1668 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1669 decelerator = build_function_call (function_decl, parms);
1671 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1673 start_function (void_list_node,
1674 build_parse_node (CALL_EXPR, init_function_name,
1675 /* This has the format of the output
1676 of get_parm_info. */
1677 tree_cons (NULL_TREE, NULL_TREE,
1678 void_list_node),
1679 NULL_TREE),
1680 NULL_TREE, NULL_TREE, 0);
1681 #if 0 /* This should be turned back on later
1682 for the systems where collect is not needed. */
1683 /* Make these functions nonglobal
1684 so each file can use the same name. */
1685 TREE_PUBLIC (current_function_decl) = 0;
1686 #endif
1687 TREE_USED (current_function_decl) = 1;
1688 store_parm_decls ();
1690 assemble_external (function_decl);
1691 c_expand_expr_stmt (decelerator);
1693 TREE_PUBLIC (current_function_decl) = 1;
1695 function_decl = current_function_decl;
1696 finish_function (0);
1698 /* Return the name of the constructor function. */
1699 return XSTR (XEXP (DECL_RTL (function_decl), 0), 0);
1703 /* extern const char _OBJC_STRINGS[]; */
1705 static void
1706 generate_forward_declaration_to_string_table ()
1708 tree sc_spec, decl_specs, expr_decl;
1710 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1711 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1713 expr_decl
1714 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1716 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1719 /* Return the DECL of the string IDENT in the SECTION. */
1721 static tree
1722 get_objc_string_decl (ident, section)
1723 tree ident;
1724 enum string_section section;
1726 tree chain, decl;
1728 if (section == class_names)
1729 chain = class_names_chain;
1730 else if (section == meth_var_names)
1731 chain = meth_var_names_chain;
1732 else if (section == meth_var_types)
1733 chain = meth_var_types_chain;
1735 for (; chain != 0; chain = TREE_VALUE (chain))
1736 if (TREE_VALUE (chain) == ident)
1737 return (TREE_PURPOSE (chain));
1739 abort ();
1740 return NULL_TREE;
1743 /* Output references to all statically allocated objects. Return the DECL
1744 for the array built. */
1746 static tree
1747 generate_static_references ()
1749 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1750 tree class_name, class, decl, instance, idecl, initlist;
1751 tree cl_chain, in_chain, type;
1752 int num_inst, num_class;
1753 char buf[256];
1755 if (flag_next_runtime)
1756 abort ();
1758 for (cl_chain = objc_static_instances, num_class = 0;
1759 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1761 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1762 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1764 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1765 ident = get_identifier (buf);
1767 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1768 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1769 build_tree_list (NULL_TREE,
1770 ridpointers[(int) RID_STATIC]));
1771 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1772 DECL_CONTEXT (decl) = 0;
1773 DECL_ARTIFICIAL (decl) = 1;
1775 /* Output {class_name, ...}. */
1776 class = TREE_VALUE (cl_chain);
1777 class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
1778 initlist = build_tree_list (NULL_TREE,
1779 build_unary_op (ADDR_EXPR, class_name, 1));
1781 /* Output {..., instance, ...}. */
1782 for (in_chain = TREE_PURPOSE (cl_chain);
1783 in_chain; in_chain = TREE_CHAIN (in_chain))
1785 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1786 initlist = tree_cons (NULL_TREE, expr, initlist);
1789 /* Output {..., NULL}. */
1790 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1792 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
1793 finish_decl (decl, expr, NULL_TREE);
1794 TREE_USED (decl) = 1;
1796 type = build_array_type (build_pointer_type (void_type_node), 0);
1797 decl = build_decl (VAR_DECL, ident, type);
1798 make_decl_rtl (decl, 0, 1);
1799 TREE_USED (decl) = 1;
1800 decls
1801 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
1804 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
1805 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
1806 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1807 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1808 build_tree_list (NULL_TREE,
1809 ridpointers[(int) RID_STATIC]));
1810 static_instances_decl
1811 = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1812 TREE_USED (static_instances_decl) = 1;
1813 DECL_CONTEXT (static_instances_decl) = 0;
1814 DECL_ARTIFICIAL (static_instances_decl) = 1;
1815 end_temporary_allocation ();
1816 expr = build_constructor (TREE_TYPE (static_instances_decl),
1817 nreverse (decls));
1818 finish_decl (static_instances_decl, expr, NULL_TREE);
1821 /* Output all strings. */
1823 static void
1824 generate_strings ()
1826 tree sc_spec, decl_specs, expr_decl;
1827 tree chain, string_expr;
1828 tree string, decl;
1830 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
1832 string = TREE_VALUE (chain);
1833 decl = TREE_PURPOSE (chain);
1834 sc_spec
1835 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1836 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1837 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1838 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1839 end_temporary_allocation ();
1840 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1841 IDENTIFIER_POINTER (string));
1842 finish_decl (decl, string_expr, NULL_TREE);
1845 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
1847 string = TREE_VALUE (chain);
1848 decl = TREE_PURPOSE (chain);
1849 sc_spec
1850 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1851 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1852 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1853 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1854 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1855 IDENTIFIER_POINTER (string));
1856 finish_decl (decl, string_expr, NULL_TREE);
1859 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
1861 string = TREE_VALUE (chain);
1862 decl = TREE_PURPOSE (chain);
1863 sc_spec
1864 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1865 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1866 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1867 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1868 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1869 IDENTIFIER_POINTER (string));
1870 finish_decl (decl, string_expr, NULL_TREE);
1874 static tree
1875 build_selector_reference_decl (name)
1876 tree name;
1878 tree decl, ident;
1879 char buf[256];
1880 static int idx = 0;
1882 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
1884 push_obstacks_nochange ();
1885 end_temporary_allocation ();
1887 ident = get_identifier (buf);
1889 decl = build_decl (VAR_DECL, ident, selector_type);
1890 DECL_EXTERNAL (decl) = 1;
1891 TREE_PUBLIC (decl) = 1;
1892 TREE_USED (decl) = 1;
1893 TREE_READONLY (decl) = 1;
1894 DECL_ARTIFICIAL (decl) = 1;
1895 DECL_CONTEXT (decl) = 0;
1897 make_decl_rtl (decl, 0, 1);
1898 pushdecl_top_level (decl);
1900 pop_obstacks ();
1902 return decl;
1905 /* Just a handy wrapper for add_objc_string. */
1907 static tree
1908 build_selector (ident)
1909 tree ident;
1911 tree expr = add_objc_string (ident, meth_var_names);
1912 if (flag_typed_selectors)
1913 return expr;
1914 else
1915 return build_c_cast (selector_type, expr); /* cast! */
1918 /* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
1919 The cast stops the compiler from issuing the following message:
1920 grok.m: warning: initialization of non-const * pointer from const *
1921 grok.m: warning: initialization between incompatible pointer types. */
1923 static tree
1924 build_msg_pool_reference (offset)
1925 int offset;
1927 tree expr = build_int_2 (offset, 0);
1928 tree cast;
1930 expr = build_array_ref (UOBJC_STRINGS_decl, expr);
1931 expr = build_unary_op (ADDR_EXPR, expr, 0);
1933 cast = build_tree_list (build_tree_list (NULL_TREE,
1934 ridpointers[(int) RID_CHAR]),
1935 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
1936 TREE_TYPE (expr) = groktypename (cast);
1937 return expr;
1940 static tree
1941 init_selector (offset)
1942 int offset;
1944 tree expr = build_msg_pool_reference (offset);
1945 TREE_TYPE (expr) = selector_type;
1946 return expr;
1949 static void
1950 build_selector_translation_table ()
1952 tree sc_spec, decl_specs;
1953 tree chain, initlist = NULL_TREE;
1954 int offset = 0;
1955 tree decl, var_decl, name;
1957 /* The corresponding pop_obstacks is in finish_decl,
1958 called at the end of this function. */
1959 if (! flag_next_runtime)
1960 push_obstacks_nochange ();
1962 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1964 tree expr;
1966 expr = build_selector (TREE_VALUE (chain));
1968 if (flag_next_runtime)
1970 name = DECL_NAME (TREE_PURPOSE (chain));
1972 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1974 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
1975 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
1977 var_decl = name;
1979 /* The `decl' that is returned from start_decl is the one that we
1980 forward declared in `build_selector_reference' */
1981 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1984 /* add one for the '\0' character */
1985 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1987 if (flag_next_runtime)
1988 finish_decl (decl, expr, NULL_TREE);
1989 else
1991 if (flag_typed_selectors)
1993 tree eltlist = NULL_TREE;
1994 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
1995 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
1996 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
1997 expr = build_constructor (objc_selector_template,
1998 nreverse (eltlist));
2000 initlist = tree_cons (NULL_TREE, expr, initlist);
2005 if (! flag_next_runtime)
2007 /* Cause the variable and its initial value to be actually output. */
2008 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
2009 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
2010 /* NULL terminate the list and fix the decl for output. */
2011 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2012 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1;
2013 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2014 nreverse (initlist));
2015 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
2016 current_function_decl = NULL_TREE;
2020 static tree
2021 get_proto_encoding (proto)
2022 tree proto;
2024 tree encoding;
2025 if (proto)
2027 tree tmp_decl;
2029 if (! METHOD_ENCODING (proto))
2031 tmp_decl = build_tmp_function_decl ();
2032 hack_method_prototype (proto, tmp_decl);
2033 encoding = encode_method_prototype (proto, tmp_decl);
2034 METHOD_ENCODING (proto) = encoding;
2036 else
2037 encoding = METHOD_ENCODING (proto);
2039 return add_objc_string (encoding, meth_var_types);
2041 else
2042 return build_int_2 (0, 0);
2045 /* sel_ref_chain is a list whose "value" fields will be instances of
2046 identifier_node that represent the selector. */
2048 static tree
2049 build_typed_selector_reference (ident, proto)
2050 tree ident, proto;
2052 tree *chain = &sel_ref_chain;
2053 tree expr;
2054 int index = 0;
2056 while (*chain)
2058 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
2059 goto return_at_index;
2061 index++;
2062 chain = &TREE_CHAIN (*chain);
2065 *chain = perm_tree_cons (proto, ident, NULL_TREE);
2067 return_at_index:
2068 expr = build_unary_op (ADDR_EXPR,
2069 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2070 build_int_2 (index, 0)),
2072 return build_c_cast (selector_type, expr);
2075 static tree
2076 build_selector_reference (ident)
2077 tree ident;
2079 tree *chain = &sel_ref_chain;
2080 tree expr;
2081 int index = 0;
2083 while (*chain)
2085 if (TREE_VALUE (*chain) == ident)
2086 return (flag_next_runtime
2087 ? TREE_PURPOSE (*chain)
2088 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2089 build_int_2 (index, 0)));
2091 index++;
2092 chain = &TREE_CHAIN (*chain);
2095 expr = build_selector_reference_decl (ident);
2097 *chain = perm_tree_cons (expr, ident, NULL_TREE);
2099 return (flag_next_runtime
2100 ? expr
2101 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2102 build_int_2 (index, 0)));
2105 static tree
2106 build_class_reference_decl (name)
2107 tree name;
2109 tree decl, ident;
2110 char buf[256];
2111 static int idx = 0;
2113 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
2115 push_obstacks_nochange ();
2116 end_temporary_allocation ();
2118 ident = get_identifier (buf);
2120 decl = build_decl (VAR_DECL, ident, objc_class_type);
2121 DECL_EXTERNAL (decl) = 1;
2122 TREE_PUBLIC (decl) = 1;
2123 TREE_USED (decl) = 1;
2124 TREE_READONLY (decl) = 1;
2125 DECL_CONTEXT (decl) = 0;
2126 DECL_ARTIFICIAL (decl) = 1;
2128 make_decl_rtl (decl, 0, 1);
2129 pushdecl_top_level (decl);
2131 pop_obstacks ();
2133 return decl;
2136 /* Create a class reference, but don't create a variable to reference
2137 it. */
2139 static void
2140 add_class_reference (ident)
2141 tree ident;
2143 tree chain;
2145 if ((chain = cls_ref_chain))
2147 tree tail;
2150 if (ident == TREE_VALUE (chain))
2151 return;
2153 tail = chain;
2154 chain = TREE_CHAIN (chain);
2156 while (chain);
2158 /* Append to the end of the list */
2159 TREE_CHAIN (tail) = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2161 else
2162 cls_ref_chain = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2165 /* Get a class reference, creating it if necessary. Also create the
2166 reference variable. */
2168 tree
2169 get_class_reference (ident)
2170 tree ident;
2172 if (flag_next_runtime)
2174 tree *chain;
2175 tree decl;
2177 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2178 if (TREE_VALUE (*chain) == ident)
2180 if (! TREE_PURPOSE (*chain))
2181 TREE_PURPOSE (*chain) = build_class_reference_decl (ident);
2183 return TREE_PURPOSE (*chain);
2186 decl = build_class_reference_decl (ident);
2187 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2188 return decl;
2190 else
2192 tree params;
2194 add_class_reference (ident);
2196 params = build_tree_list (NULL_TREE,
2197 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2198 IDENTIFIER_POINTER (ident)));
2200 assemble_external (objc_get_class_decl);
2201 return build_function_call (objc_get_class_decl, params);
2205 /* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances
2206 of identifier_node that represent the selector. It returns the
2207 offset of the selector from the beginning of the _OBJC_STRINGS
2208 pool. This offset is typically used by init_selector during code
2209 generation.
2211 For each string section we have a chain which maps identifier nodes
2212 to decls for the strings. */
2214 static tree
2215 add_objc_string (ident, section)
2216 tree ident;
2217 enum string_section section;
2219 tree *chain, decl;
2221 if (section == class_names)
2222 chain = &class_names_chain;
2223 else if (section == meth_var_names)
2224 chain = &meth_var_names_chain;
2225 else if (section == meth_var_types)
2226 chain = &meth_var_types_chain;
2228 while (*chain)
2230 if (TREE_VALUE (*chain) == ident)
2231 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2233 chain = &TREE_CHAIN (*chain);
2236 decl = build_objc_string_decl (ident, section);
2238 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2240 return build_unary_op (ADDR_EXPR, decl, 1);
2243 static tree
2244 build_objc_string_decl (name, section)
2245 tree name;
2246 enum string_section section;
2248 tree decl, ident;
2249 char buf[256];
2250 static int class_names_idx = 0;
2251 static int meth_var_names_idx = 0;
2252 static int meth_var_types_idx = 0;
2254 if (section == class_names)
2255 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2256 else if (section == meth_var_names)
2257 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2258 else if (section == meth_var_types)
2259 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2261 push_obstacks_nochange ();
2262 end_temporary_allocation ();
2263 ident = get_identifier (buf);
2265 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2266 DECL_EXTERNAL (decl) = 1;
2267 TREE_PUBLIC (decl) = 1;
2268 TREE_USED (decl) = 1;
2269 TREE_READONLY (decl) = 1;
2270 TREE_CONSTANT (decl) = 1;
2271 DECL_CONTEXT (decl) = 0;
2272 DECL_ARTIFICIAL (decl) = 1;
2274 make_decl_rtl (decl, 0, 1);
2275 pushdecl_top_level (decl);
2277 pop_obstacks ();
2279 return decl;
2283 void
2284 objc_declare_alias (alias_ident, class_ident)
2285 tree alias_ident;
2286 tree class_ident;
2288 if (!doing_objc_thang)
2289 objc_fatal ();
2291 if (is_class_name (class_ident) != class_ident)
2292 warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2293 else if (is_class_name (alias_ident))
2294 warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2295 else
2296 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
2299 void
2300 objc_declare_class (ident_list)
2301 tree ident_list;
2303 tree list;
2305 if (!doing_objc_thang)
2306 objc_fatal ();
2308 for (list = ident_list; list; list = TREE_CHAIN (list))
2310 tree ident = TREE_VALUE (list);
2311 tree decl;
2313 if ((decl = lookup_name (ident)))
2315 error ("`%s' redeclared as different kind of symbol",
2316 IDENTIFIER_POINTER (ident));
2317 error_with_decl (decl, "previous declaration of `%s'");
2320 if (! is_class_name (ident))
2322 tree record = xref_tag (RECORD_TYPE, ident);
2323 TREE_STATIC_TEMPLATE (record) = 1;
2324 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2329 tree
2330 is_class_name (ident)
2331 tree ident;
2333 tree chain;
2335 if (lookup_interface (ident))
2336 return ident;
2338 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2340 if (ident == TREE_VALUE (chain))
2341 return ident;
2344 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2346 if (ident == TREE_VALUE (chain))
2347 return TREE_PURPOSE (chain);
2350 return 0;
2353 tree
2354 lookup_interface (ident)
2355 tree ident;
2357 tree chain;
2359 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2361 if (ident == CLASS_NAME (chain))
2362 return chain;
2364 return NULL_TREE;
2367 static tree
2368 objc_copy_list (list, head)
2369 tree list;
2370 tree *head;
2372 tree newlist = NULL_TREE, tail = NULL_TREE;
2374 while (list)
2376 tail = copy_node (list);
2378 /* The following statement fixes a bug when inheriting instance
2379 variables that are declared to be bitfields. finish_struct
2380 expects to find the width of the bitfield in DECL_INITIAL,
2381 which it nulls out after processing the decl of the super
2382 class...rather than change the way finish_struct works (which
2383 is risky), I create the situation it expects...s.naroff
2384 (7/23/89). */
2386 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
2387 DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
2389 newlist = chainon (newlist, tail);
2390 list = TREE_CHAIN (list);
2393 *head = newlist;
2394 return tail;
2397 /* Used by: build_private_template, get_class_ivars, and
2398 continue_class. COPY is 1 when called from @defs. In this case
2399 copy all fields. Otherwise don't copy leaf ivars since we rely on
2400 them being side-effected exactly once by finish_struct. */
2402 static tree
2403 build_ivar_chain (interface, copy)
2404 tree interface;
2405 int copy;
2407 tree my_name, super_name, ivar_chain;
2409 my_name = CLASS_NAME (interface);
2410 super_name = CLASS_SUPER_NAME (interface);
2412 /* Possibly copy leaf ivars. */
2413 if (copy)
2414 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
2415 else
2416 ivar_chain = CLASS_IVARS (interface);
2418 while (super_name)
2420 tree op1;
2421 tree super_interface = lookup_interface (super_name);
2423 if (!super_interface)
2425 /* fatal did not work with 2 args...should fix */
2426 error ("Cannot find interface declaration for `%s', superclass of `%s'",
2427 IDENTIFIER_POINTER (super_name),
2428 IDENTIFIER_POINTER (my_name));
2429 exit (FATAL_EXIT_CODE);
2432 if (super_interface == interface)
2434 fatal ("Circular inheritance in interface declaration for `%s'",
2435 IDENTIFIER_POINTER (super_name));
2438 interface = super_interface;
2439 my_name = CLASS_NAME (interface);
2440 super_name = CLASS_SUPER_NAME (interface);
2442 op1 = CLASS_IVARS (interface);
2443 if (op1)
2445 tree head, tail = objc_copy_list (op1, &head);
2447 /* Prepend super class ivars...make a copy of the list, we
2448 do not want to alter the original. */
2449 TREE_CHAIN (tail) = ivar_chain;
2450 ivar_chain = head;
2453 return ivar_chain;
2456 /* struct <classname> {
2457 struct objc_class *isa;
2459 }; */
2461 static tree
2462 build_private_template (class)
2463 tree class;
2465 tree ivar_context;
2467 if (CLASS_STATIC_TEMPLATE (class))
2469 uprivate_record = CLASS_STATIC_TEMPLATE (class);
2470 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
2472 else
2474 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
2476 ivar_context = build_ivar_chain (class, 0);
2478 finish_struct (uprivate_record, ivar_context, NULL_TREE);
2480 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
2482 /* mark this record as class template - for class type checking */
2483 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
2486 instance_type
2487 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
2488 uprivate_record),
2489 build1 (INDIRECT_REF, NULL_TREE,
2490 NULL_TREE)));
2492 return ivar_context;
2495 /* Begin code generation for protocols... */
2497 /* struct objc_protocol {
2498 char *protocol_name;
2499 struct objc_protocol **protocol_list;
2500 struct objc_method_desc *instance_methods;
2501 struct objc_method_desc *class_methods;
2502 }; */
2504 static tree
2505 build_protocol_template ()
2507 tree decl_specs, field_decl, field_decl_chain;
2508 tree template;
2510 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
2512 /* struct objc_class *isa; */
2514 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2515 get_identifier (UTAG_CLASS)));
2516 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
2517 field_decl
2518 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2519 field_decl_chain = field_decl;
2521 /* char *protocol_name; */
2523 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
2524 field_decl
2525 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
2526 field_decl
2527 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2528 chainon (field_decl_chain, field_decl);
2530 /* struct objc_protocol **protocol_list; */
2532 decl_specs = build_tree_list (NULL_TREE, template);
2533 field_decl
2534 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
2535 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
2536 field_decl
2537 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2538 chainon (field_decl_chain, field_decl);
2540 /* struct objc_method_list *instance_methods; */
2542 decl_specs
2543 = build_tree_list (NULL_TREE,
2544 xref_tag (RECORD_TYPE,
2545 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2546 field_decl
2547 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
2548 field_decl
2549 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2550 chainon (field_decl_chain, field_decl);
2552 /* struct objc_method_list *class_methods; */
2554 decl_specs
2555 = build_tree_list (NULL_TREE,
2556 xref_tag (RECORD_TYPE,
2557 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2558 field_decl
2559 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
2560 field_decl
2561 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2562 chainon (field_decl_chain, field_decl);
2564 return finish_struct (template, field_decl_chain, NULL_TREE);
2567 static tree
2568 build_descriptor_table_initializer (type, entries)
2569 tree type;
2570 tree entries;
2572 tree initlist = NULL_TREE;
2576 tree eltlist = NULL_TREE;
2578 eltlist
2579 = tree_cons (NULL_TREE,
2580 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
2581 eltlist
2582 = tree_cons (NULL_TREE,
2583 add_objc_string (METHOD_ENCODING (entries),
2584 meth_var_types),
2585 eltlist);
2587 initlist
2588 = tree_cons (NULL_TREE,
2589 build_constructor (type, nreverse (eltlist)), initlist);
2591 entries = TREE_CHAIN (entries);
2593 while (entries);
2595 return build_constructor (build_array_type (type, 0), nreverse (initlist));
2598 /* struct objc_method_prototype_list {
2599 int count;
2600 struct objc_method_prototype {
2601 SEL name;
2602 char *types;
2603 } list[1];
2604 }; */
2606 static tree
2607 build_method_prototype_list_template (list_type, size)
2608 tree list_type;
2609 int size;
2611 tree objc_ivar_list_record;
2612 tree decl_specs, field_decl, field_decl_chain;
2614 /* Generate an unnamed struct definition. */
2616 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
2618 /* int method_count; */
2620 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
2621 field_decl = get_identifier ("method_count");
2623 field_decl
2624 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2625 field_decl_chain = field_decl;
2627 /* struct objc_method method_list[]; */
2629 decl_specs = build_tree_list (NULL_TREE, list_type);
2630 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2631 build_int_2 (size, 0));
2633 field_decl
2634 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2635 chainon (field_decl_chain, field_decl);
2637 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
2639 return objc_ivar_list_record;
2642 static tree
2643 build_method_prototype_template ()
2645 tree proto_record;
2646 tree decl_specs, field_decl, field_decl_chain;
2648 proto_record
2649 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2651 #ifdef OBJC_INT_SELECTORS
2652 /* unsigned int _cmd; */
2653 decl_specs
2654 = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE);
2655 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
2656 field_decl = get_identifier ("_cmd");
2657 #else /* OBJC_INT_SELECTORS */
2658 /* struct objc_selector *_cmd; */
2659 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
2660 get_identifier (TAG_SELECTOR)), NULL_TREE);
2661 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
2662 #endif /* OBJC_INT_SELECTORS */
2664 field_decl
2665 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2666 field_decl_chain = field_decl;
2668 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
2669 field_decl
2670 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
2671 field_decl
2672 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2673 chainon (field_decl_chain, field_decl);
2675 finish_struct (proto_record, field_decl_chain, NULL_TREE);
2677 return proto_record;
2680 /* True if last call to forwarding_offset yielded a register offset. */
2681 static int offset_is_register;
2683 static int
2684 forwarding_offset (parm)
2685 tree parm;
2687 int offset_in_bytes;
2689 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2691 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2693 /* ??? Here we assume that the parm address is indexed
2694 off the frame pointer or arg pointer.
2695 If that is not true, we produce meaningless results,
2696 but do not crash. */
2697 if (GET_CODE (addr) == PLUS
2698 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2699 offset_in_bytes = INTVAL (XEXP (addr, 1));
2700 else
2701 offset_in_bytes = 0;
2703 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2704 offset_is_register = 0;
2706 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2708 int regno = REGNO (DECL_INCOMING_RTL (parm));
2709 offset_in_bytes = apply_args_register_offset (regno);
2710 offset_is_register = 1;
2712 else
2713 return 0;
2715 /* This is the case where the parm is passed as an int or double
2716 and it is converted to a char, short or float and stored back
2717 in the parmlist. In this case, describe the parm
2718 with the variable's declared type, and adjust the address
2719 if the least significant bytes (which we are using) are not
2720 the first ones. */
2721 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2722 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2723 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2725 return offset_in_bytes;
2728 static tree
2729 encode_method_prototype (method_decl, func_decl)
2730 tree method_decl;
2731 tree func_decl;
2733 tree parms;
2734 int stack_size, i;
2735 tree user_args;
2736 int max_parm_end = 0;
2737 char buf[40];
2738 tree result;
2740 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
2741 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2743 /* C type. */
2744 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2745 obstack_object_size (&util_obstack),
2746 OBJC_ENCODE_INLINE_DEFS);
2748 /* Stack size. */
2749 for (parms = DECL_ARGUMENTS (func_decl); parms;
2750 parms = TREE_CHAIN (parms))
2752 int parm_end = (forwarding_offset (parms)
2753 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
2754 / BITS_PER_UNIT));
2756 if (!offset_is_register && max_parm_end < parm_end)
2757 max_parm_end = parm_end;
2760 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2762 sprintf (buf, "%d", stack_size);
2763 obstack_grow (&util_obstack, buf, strlen (buf));
2765 user_args = METHOD_SEL_ARGS (method_decl);
2767 /* Argument types. */
2768 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2769 parms = TREE_CHAIN (parms), i++)
2771 /* Process argument qualifiers for user supplied arguments. */
2772 if (i > 1)
2774 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2775 user_args = TREE_CHAIN (user_args);
2778 /* Type. */
2779 encode_type (TREE_TYPE (parms),
2780 obstack_object_size (&util_obstack),
2781 OBJC_ENCODE_INLINE_DEFS);
2783 /* Compute offset. */
2784 sprintf (buf, "%d", forwarding_offset (parms));
2786 /* Indicate register. */
2787 if (offset_is_register)
2788 obstack_1grow (&util_obstack, '+');
2790 obstack_grow (&util_obstack, buf, strlen (buf));
2793 obstack_1grow (&util_obstack, '\0');
2794 result = get_identifier (obstack_finish (&util_obstack));
2795 obstack_free (&util_obstack, util_firstobj);
2796 return result;
2799 static tree
2800 generate_descriptor_table (type, name, size, list, proto)
2801 tree type;
2802 char *name;
2803 int size;
2804 tree list;
2805 tree proto;
2807 tree sc_spec, decl_specs, decl, initlist;
2809 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2810 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
2812 decl = start_decl (synth_id_with_class_suffix (name, proto),
2813 decl_specs, 1, NULL_TREE, NULL_TREE);
2815 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
2816 initlist = tree_cons (NULL_TREE, list, initlist);
2818 finish_decl (decl, build_constructor (type, nreverse (initlist)),
2819 NULL_TREE);
2821 return decl;
2824 static void
2825 generate_method_descriptors (protocol) /* generate_dispatch_tables */
2826 tree protocol;
2828 static tree objc_method_prototype_template;
2829 tree initlist, chain, method_list_template;
2830 tree cast, variable_length_type;
2831 int size;
2833 if (!objc_method_prototype_template)
2834 objc_method_prototype_template = build_method_prototype_template ();
2836 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2837 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
2838 NULL_TREE);
2839 variable_length_type = groktypename (cast);
2841 chain = PROTOCOL_CLS_METHODS (protocol);
2842 if (chain)
2844 size = list_length (chain);
2846 method_list_template
2847 = build_method_prototype_list_template (objc_method_prototype_template,
2848 size);
2850 initlist
2851 = build_descriptor_table_initializer (objc_method_prototype_template,
2852 chain);
2854 UOBJC_CLASS_METHODS_decl
2855 = generate_descriptor_table (method_list_template,
2856 "_OBJC_PROTOCOL_CLASS_METHODS",
2857 size, initlist, protocol);
2858 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
2860 else
2861 UOBJC_CLASS_METHODS_decl = 0;
2863 chain = PROTOCOL_NST_METHODS (protocol);
2864 if (chain)
2866 size = list_length (chain);
2868 method_list_template
2869 = build_method_prototype_list_template (objc_method_prototype_template,
2870 size);
2871 initlist
2872 = build_descriptor_table_initializer (objc_method_prototype_template,
2873 chain);
2875 UOBJC_INSTANCE_METHODS_decl
2876 = generate_descriptor_table (method_list_template,
2877 "_OBJC_PROTOCOL_INSTANCE_METHODS",
2878 size, initlist, protocol);
2879 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
2881 else
2882 UOBJC_INSTANCE_METHODS_decl = 0;
2885 static tree
2886 build_tmp_function_decl ()
2888 tree decl_specs, expr_decl, parms;
2889 static int xxx = 0;
2890 char buffer[80];
2892 /* struct objc_object *objc_xxx (id, SEL, ...); */
2893 pushlevel (0);
2894 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
2895 push_parm_decl (build_tree_list
2896 (build_tree_list (decl_specs,
2897 build1 (INDIRECT_REF, NULL_TREE,
2898 NULL_TREE)),
2899 build_tree_list (NULL_TREE, NULL_TREE)));
2901 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2902 get_identifier (TAG_SELECTOR)));
2903 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
2905 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
2906 build_tree_list (NULL_TREE, NULL_TREE)));
2907 parms = get_parm_info (0);
2908 poplevel (0, 0, 0);
2910 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
2911 sprintf (buffer, "__objc_tmp_%x", xxx++);
2912 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
2913 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
2915 return define_decl (expr_decl, decl_specs);
2918 static void
2919 hack_method_prototype (nst_methods, tmp_decl)
2920 tree nst_methods;
2921 tree tmp_decl;
2923 tree parms;
2924 tree parm;
2926 /* Hack to avoid problem with static typing of self arg. */
2927 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
2928 start_method_def (nst_methods);
2929 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
2931 if (METHOD_ADD_ARGS (nst_methods) == (tree) 1)
2932 parms = get_parm_info (0); /* we have a `, ...' */
2933 else
2934 parms = get_parm_info (1); /* place a `void_at_end' */
2936 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */
2938 /* Usually called from store_parm_decls -> init_function_start. */
2940 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
2941 current_function_decl = tmp_decl;
2944 /* Code taken from start_function. */
2945 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
2946 /* Promote the value to int before returning it. */
2947 if (TREE_CODE (restype) == INTEGER_TYPE
2948 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
2949 restype = integer_type_node;
2950 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
2953 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
2954 DECL_CONTEXT (parm) = tmp_decl;
2956 init_function_start (tmp_decl, "objc-act", 0);
2958 /* Typically called from expand_function_start for function definitions. */
2959 assign_parms (tmp_decl, 0);
2961 /* install return type */
2962 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
2966 static void
2967 generate_protocol_references (plist)
2968 tree plist;
2970 tree lproto;
2972 /* Forward declare protocols referenced. */
2973 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2975 tree proto = TREE_VALUE (lproto);
2977 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
2978 && PROTOCOL_NAME (proto))
2980 if (! PROTOCOL_FORWARD_DECL (proto))
2981 build_protocol_reference (proto);
2983 if (PROTOCOL_LIST (proto))
2984 generate_protocol_references (PROTOCOL_LIST (proto));
2989 static void
2990 generate_protocols ()
2992 tree p, tmp_decl, encoding;
2993 tree sc_spec, decl_specs, decl;
2994 tree initlist, protocol_name_expr, refs_decl, refs_expr;
2995 tree cast_type2 = 0;
2997 tmp_decl = build_tmp_function_decl ();
2999 if (! objc_protocol_template)
3000 objc_protocol_template = build_protocol_template ();
3002 /* If a protocol was directly referenced, pull in indirect references. */
3003 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3004 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3005 generate_protocol_references (PROTOCOL_LIST (p));
3007 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3009 tree nst_methods = PROTOCOL_NST_METHODS (p);
3010 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3012 /* If protocol wasn't referenced, don't generate any code. */
3013 if (! PROTOCOL_FORWARD_DECL (p))
3014 continue;
3016 /* Make sure we link in the Protocol class. */
3017 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3019 while (nst_methods)
3021 if (! METHOD_ENCODING (nst_methods))
3023 hack_method_prototype (nst_methods, tmp_decl);
3024 encoding = encode_method_prototype (nst_methods, tmp_decl);
3025 METHOD_ENCODING (nst_methods) = encoding;
3027 nst_methods = TREE_CHAIN (nst_methods);
3030 while (cls_methods)
3032 if (! METHOD_ENCODING (cls_methods))
3034 hack_method_prototype (cls_methods, tmp_decl);
3035 encoding = encode_method_prototype (cls_methods, tmp_decl);
3036 METHOD_ENCODING (cls_methods) = encoding;
3039 cls_methods = TREE_CHAIN (cls_methods);
3041 generate_method_descriptors (p);
3043 if (PROTOCOL_LIST (p))
3044 refs_decl = generate_protocol_list (p);
3045 else
3046 refs_decl = 0;
3048 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3050 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3051 NULL_TREE);
3052 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3054 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3055 decl_specs, 1, NULL_TREE, NULL_TREE);
3057 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3059 if (refs_decl)
3061 if (!cast_type2)
3062 cast_type2
3063 = groktypename
3064 (build_tree_list (build_tree_list (NULL_TREE,
3065 objc_protocol_template),
3066 build1 (INDIRECT_REF, NULL_TREE,
3067 build1 (INDIRECT_REF, NULL_TREE,
3068 NULL_TREE))));
3070 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3071 TREE_TYPE (refs_expr) = cast_type2;
3073 else
3074 refs_expr = build_int_2 (0, 0);
3076 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3077 by generate_method_descriptors, which is called above. */
3078 initlist = build_protocol_initializer (TREE_TYPE (decl),
3079 protocol_name_expr, refs_expr,
3080 UOBJC_INSTANCE_METHODS_decl,
3081 UOBJC_CLASS_METHODS_decl);
3082 finish_decl (decl, initlist, NULL_TREE);
3084 /* Mark the decl as used to avoid "defined but not used" warning. */
3085 TREE_USED (decl) = 1;
3089 static tree
3090 build_protocol_initializer (type, protocol_name, protocol_list,
3091 instance_methods, class_methods)
3092 tree type;
3093 tree protocol_name;
3094 tree protocol_list;
3095 tree instance_methods;
3096 tree class_methods;
3098 tree initlist = NULL_TREE, expr;
3099 static tree cast_type = 0;
3101 if (!cast_type)
3102 cast_type
3103 = groktypename
3104 (build_tree_list
3105 (build_tree_list (NULL_TREE,
3106 xref_tag (RECORD_TYPE,
3107 get_identifier (UTAG_CLASS))),
3108 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3110 /* Filling the "isa" in with one allows the runtime system to
3111 detect that the version change...should remove before final release. */
3113 expr = build_int_2 (PROTOCOL_VERSION, 0);
3114 TREE_TYPE (expr) = cast_type;
3115 initlist = tree_cons (NULL_TREE, expr, initlist);
3116 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3117 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3119 if (!instance_methods)
3120 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3121 else
3123 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3124 initlist = tree_cons (NULL_TREE, expr, initlist);
3127 if (!class_methods)
3128 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3129 else
3131 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3132 initlist = tree_cons (NULL_TREE, expr, initlist);
3135 return build_constructor (type, nreverse (initlist));
3138 /* struct objc_category {
3139 char *category_name;
3140 char *class_name;
3141 struct objc_method_list *instance_methods;
3142 struct objc_method_list *class_methods;
3143 struct objc_protocol_list *protocols;
3144 }; */
3146 static void
3147 build_category_template ()
3149 tree decl_specs, field_decl, field_decl_chain;
3151 objc_category_template = start_struct (RECORD_TYPE,
3152 get_identifier (UTAG_CATEGORY));
3153 /* char *category_name; */
3155 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3156 field_decl
3157 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3158 field_decl
3159 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3160 field_decl_chain = field_decl;
3162 /* char *class_name; */
3164 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3165 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3166 field_decl
3167 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3168 chainon (field_decl_chain, field_decl);
3170 /* struct objc_method_list *instance_methods; */
3172 decl_specs = build_tree_list (NULL_TREE,
3173 xref_tag (RECORD_TYPE,
3174 get_identifier (UTAG_METHOD_LIST)));
3175 field_decl
3176 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3177 field_decl
3178 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3179 chainon (field_decl_chain, field_decl);
3181 /* struct objc_method_list *class_methods; */
3183 decl_specs = build_tree_list (NULL_TREE,
3184 xref_tag (RECORD_TYPE,
3185 get_identifier (UTAG_METHOD_LIST)));
3186 field_decl
3187 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3188 field_decl
3189 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3190 chainon (field_decl_chain, field_decl);
3192 /* struct objc_protocol **protocol_list; */
3194 decl_specs = build_tree_list (NULL_TREE,
3195 xref_tag (RECORD_TYPE,
3196 get_identifier (UTAG_PROTOCOL)));
3197 field_decl
3198 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3199 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3200 field_decl
3201 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3202 chainon (field_decl_chain, field_decl);
3204 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3207 /* struct objc_selector {
3208 void *sel_id;
3209 char *sel_type;
3210 }; */
3212 static void
3213 build_selector_template ()
3216 tree decl_specs, field_decl, field_decl_chain;
3218 objc_selector_template
3219 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3221 /* void *sel_id; */
3223 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3224 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3225 field_decl
3226 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3227 field_decl_chain = field_decl;
3229 /* char *sel_type; */
3231 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3232 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3233 field_decl
3234 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3235 chainon (field_decl_chain, field_decl);
3237 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3240 /* struct objc_class {
3241 struct objc_class *isa;
3242 struct objc_class *super_class;
3243 char *name;
3244 long version;
3245 long info;
3246 long instance_size;
3247 struct objc_ivar_list *ivars;
3248 struct objc_method_list *methods;
3249 if (flag_next_runtime)
3250 struct objc_cache *cache;
3251 else {
3252 struct sarray *dtable;
3253 struct objc_class *subclass_list;
3254 struct objc_class *sibling_class;
3256 struct objc_protocol_list *protocols;
3257 }; */
3259 static void
3260 build_class_template ()
3262 tree decl_specs, field_decl, field_decl_chain;
3264 objc_class_template
3265 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3267 /* struct objc_class *isa; */
3269 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3270 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3271 field_decl
3272 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3273 field_decl_chain = field_decl;
3275 /* struct objc_class *super_class; */
3277 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3278 field_decl
3279 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3280 field_decl
3281 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3282 chainon (field_decl_chain, field_decl);
3284 /* char *name; */
3286 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3287 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3288 field_decl
3289 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3290 chainon (field_decl_chain, field_decl);
3292 /* long version; */
3294 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3295 field_decl = get_identifier ("version");
3296 field_decl
3297 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3298 chainon (field_decl_chain, field_decl);
3300 /* long info; */
3302 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3303 field_decl = get_identifier ("info");
3304 field_decl
3305 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3306 chainon (field_decl_chain, field_decl);
3308 /* long instance_size; */
3310 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3311 field_decl = get_identifier ("instance_size");
3312 field_decl
3313 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3314 chainon (field_decl_chain, field_decl);
3316 /* struct objc_ivar_list *ivars; */
3318 decl_specs = build_tree_list (NULL_TREE,
3319 xref_tag (RECORD_TYPE,
3320 get_identifier (UTAG_IVAR_LIST)));
3321 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3322 field_decl
3323 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3324 chainon (field_decl_chain, field_decl);
3326 /* struct objc_method_list *methods; */
3328 decl_specs = build_tree_list (NULL_TREE,
3329 xref_tag (RECORD_TYPE,
3330 get_identifier (UTAG_METHOD_LIST)));
3331 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3332 field_decl
3333 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3334 chainon (field_decl_chain, field_decl);
3336 if (flag_next_runtime)
3338 /* struct objc_cache *cache; */
3340 decl_specs = build_tree_list (NULL_TREE,
3341 xref_tag (RECORD_TYPE,
3342 get_identifier ("objc_cache")));
3343 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3344 field_decl = grokfield (input_filename, lineno, field_decl,
3345 decl_specs, NULL_TREE);
3346 chainon (field_decl_chain, field_decl);
3348 else
3350 /* struct sarray *dtable; */
3352 decl_specs = build_tree_list (NULL_TREE,
3353 xref_tag (RECORD_TYPE,
3354 get_identifier ("sarray")));
3355 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3356 field_decl = grokfield (input_filename, lineno, field_decl,
3357 decl_specs, NULL_TREE);
3358 chainon (field_decl_chain, field_decl);
3360 /* struct objc_class *subclass_list; */
3362 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3363 field_decl
3364 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3365 field_decl = grokfield (input_filename, lineno, field_decl,
3366 decl_specs, NULL_TREE);
3367 chainon (field_decl_chain, field_decl);
3369 /* struct objc_class *sibling_class; */
3371 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3372 field_decl
3373 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3374 field_decl = grokfield (input_filename, lineno, field_decl,
3375 decl_specs, NULL_TREE);
3376 chainon (field_decl_chain, field_decl);
3379 /* struct objc_protocol **protocol_list; */
3381 decl_specs = build_tree_list (NULL_TREE,
3382 xref_tag (RECORD_TYPE,
3383 get_identifier (UTAG_PROTOCOL)));
3384 field_decl
3385 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3386 field_decl
3387 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3388 field_decl = grokfield (input_filename, lineno, field_decl,
3389 decl_specs, NULL_TREE);
3390 chainon (field_decl_chain, field_decl);
3393 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3396 /* Generate appropriate forward declarations for an implementation. */
3398 static void
3399 synth_forward_declarations ()
3401 tree sc_spec, decl_specs, an_id;
3403 /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3405 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
3407 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3408 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3409 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3410 TREE_USED (UOBJC_CLASS_decl) = 1;
3411 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3413 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3415 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3416 implementation_context);
3418 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3419 TREE_USED (UOBJC_METACLASS_decl) = 1;
3420 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3422 /* Pre-build the following entities - for speed/convenience. */
3424 an_id = get_identifier ("super_class");
3425 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3426 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3429 static void
3430 error_with_ivar (message, decl, rawdecl)
3431 char *message;
3432 tree decl;
3433 tree rawdecl;
3435 count_error (0);
3437 report_error_function (DECL_SOURCE_FILE (decl));
3439 fprintf (stderr, "%s:%d: ",
3440 DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
3441 bzero (errbuf, BUFSIZE);
3442 fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
3445 #define USERTYPE(t) \
3446 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
3447 || TREE_CODE (t) == ENUMERAL_TYPE)
3449 static void
3450 check_ivars (inter, imp)
3451 tree inter;
3452 tree imp;
3454 tree intdecls = CLASS_IVARS (inter);
3455 tree impdecls = CLASS_IVARS (imp);
3456 tree rawintdecls = CLASS_RAW_IVARS (inter);
3457 tree rawimpdecls = CLASS_RAW_IVARS (imp);
3459 while (1)
3461 tree t1, t2;
3463 if (intdecls == 0 && impdecls == 0)
3464 break;
3465 if (intdecls == 0 || impdecls == 0)
3467 error ("inconsistent instance variable specification");
3468 break;
3471 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3473 if (!comptypes (t1, t2))
3475 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3477 error_with_ivar ("conflicting instance variable type",
3478 impdecls, rawimpdecls);
3479 error_with_ivar ("previous declaration of",
3480 intdecls, rawintdecls);
3482 else /* both the type and the name don't match */
3484 error ("inconsistent instance variable specification");
3485 break;
3489 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3491 error_with_ivar ("conflicting instance variable name",
3492 impdecls, rawimpdecls);
3493 error_with_ivar ("previous declaration of",
3494 intdecls, rawintdecls);
3497 intdecls = TREE_CHAIN (intdecls);
3498 impdecls = TREE_CHAIN (impdecls);
3499 rawintdecls = TREE_CHAIN (rawintdecls);
3500 rawimpdecls = TREE_CHAIN (rawimpdecls);
3504 /* Set super_type to the data type node for struct objc_super *,
3505 first defining struct objc_super itself.
3506 This needs to be done just once per compilation. */
3508 static tree
3509 build_super_template ()
3511 tree record, decl_specs, field_decl, field_decl_chain;
3513 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3515 /* struct objc_object *self; */
3517 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3518 field_decl = get_identifier ("self");
3519 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3520 field_decl = grokfield (input_filename, lineno,
3521 field_decl, decl_specs, NULL_TREE);
3522 field_decl_chain = field_decl;
3524 /* struct objc_class *class; */
3526 decl_specs = get_identifier (UTAG_CLASS);
3527 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3528 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3530 field_decl = grokfield (input_filename, lineno,
3531 field_decl, decl_specs, NULL_TREE);
3532 chainon (field_decl_chain, field_decl);
3534 finish_struct (record, field_decl_chain, NULL_TREE);
3536 /* `struct objc_super *' */
3537 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3538 record),
3539 build1 (INDIRECT_REF,
3540 NULL_TREE, NULL_TREE)));
3541 return record;
3544 /* struct objc_ivar {
3545 char *ivar_name;
3546 char *ivar_type;
3547 int ivar_offset;
3548 }; */
3550 static tree
3551 build_ivar_template ()
3553 tree objc_ivar_id, objc_ivar_record;
3554 tree decl_specs, field_decl, field_decl_chain;
3556 objc_ivar_id = get_identifier (UTAG_IVAR);
3557 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3559 /* char *ivar_name; */
3561 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3562 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3564 field_decl = grokfield (input_filename, lineno, field_decl,
3565 decl_specs, NULL_TREE);
3566 field_decl_chain = field_decl;
3568 /* char *ivar_type; */
3570 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3571 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3573 field_decl = grokfield (input_filename, lineno, field_decl,
3574 decl_specs, NULL_TREE);
3575 chainon (field_decl_chain, field_decl);
3577 /* int ivar_offset; */
3579 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3580 field_decl = get_identifier ("ivar_offset");
3582 field_decl = grokfield (input_filename, lineno, field_decl,
3583 decl_specs, NULL_TREE);
3584 chainon (field_decl_chain, field_decl);
3586 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3588 return objc_ivar_record;
3591 /* struct {
3592 int ivar_count;
3593 struct objc_ivar ivar_list[ivar_count];
3594 }; */
3596 static tree
3597 build_ivar_list_template (list_type, size)
3598 tree list_type;
3599 int size;
3601 tree objc_ivar_list_record;
3602 tree decl_specs, field_decl, field_decl_chain;
3604 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3606 /* int ivar_count; */
3608 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3609 field_decl = get_identifier ("ivar_count");
3611 field_decl = grokfield (input_filename, lineno, field_decl,
3612 decl_specs, NULL_TREE);
3613 field_decl_chain = field_decl;
3615 /* struct objc_ivar ivar_list[]; */
3617 decl_specs = build_tree_list (NULL_TREE, list_type);
3618 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3619 build_int_2 (size, 0));
3621 field_decl = grokfield (input_filename, lineno,
3622 field_decl, decl_specs, NULL_TREE);
3623 chainon (field_decl_chain, field_decl);
3625 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3627 return objc_ivar_list_record;
3630 /* struct {
3631 int method_next;
3632 int method_count;
3633 struct objc_method method_list[method_count];
3634 }; */
3636 static tree
3637 build_method_list_template (list_type, size)
3638 tree list_type;
3639 int size;
3641 tree objc_ivar_list_record;
3642 tree decl_specs, field_decl, field_decl_chain;
3644 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3646 /* int method_next; */
3648 decl_specs
3649 = build_tree_list
3650 (NULL_TREE,
3651 xref_tag (RECORD_TYPE,
3652 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3653 field_decl
3654 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3655 field_decl = grokfield (input_filename, lineno, field_decl,
3656 decl_specs, NULL_TREE);
3657 field_decl_chain = field_decl;
3659 /* int method_count; */
3661 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3662 field_decl = get_identifier ("method_count");
3664 field_decl = grokfield (input_filename, lineno,
3665 field_decl, decl_specs, NULL_TREE);
3666 chainon (field_decl_chain, field_decl);
3668 /* struct objc_method method_list[]; */
3670 decl_specs = build_tree_list (NULL_TREE, list_type);
3671 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3672 build_int_2 (size, 0));
3674 field_decl = grokfield (input_filename, lineno,
3675 field_decl, decl_specs, NULL_TREE);
3676 chainon (field_decl_chain, field_decl);
3678 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3680 return objc_ivar_list_record;
3683 static tree
3684 build_ivar_list_initializer (type, field_decl)
3685 tree type;
3686 tree field_decl;
3688 tree initlist = NULL_TREE;
3692 tree ivar = NULL_TREE;
3694 /* Set name. */
3695 if (DECL_NAME (field_decl))
3696 ivar = tree_cons (NULL_TREE,
3697 add_objc_string (DECL_NAME (field_decl),
3698 meth_var_names),
3699 ivar);
3700 else
3701 /* Unnamed bit-field ivar (yuck). */
3702 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3704 /* Set type. */
3705 encode_field_decl (field_decl,
3706 obstack_object_size (&util_obstack),
3707 OBJC_ENCODE_DONT_INLINE_DEFS);
3709 /* Null terminate string. */
3710 obstack_1grow (&util_obstack, 0);
3711 ivar
3712 = tree_cons
3713 (NULL_TREE,
3714 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3715 meth_var_types),
3716 ivar);
3717 obstack_free (&util_obstack, util_firstobj);
3719 /* set offset */
3720 ivar
3721 = tree_cons
3722 (NULL_TREE,
3723 build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl))
3724 / BITS_PER_UNIT),
3726 ivar);
3728 initlist = tree_cons (NULL_TREE,
3729 build_constructor (type, nreverse (ivar)),
3730 initlist);
3732 field_decl = TREE_CHAIN (field_decl);
3734 while (field_decl);
3736 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3739 static tree
3740 generate_ivars_list (type, name, size, list)
3741 tree type;
3742 char *name;
3743 int size;
3744 tree list;
3746 tree sc_spec, decl_specs, decl, initlist;
3748 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3749 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3751 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3752 decl_specs, 1, NULL_TREE, NULL_TREE);
3754 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3755 initlist = tree_cons (NULL_TREE, list, initlist);
3757 finish_decl (decl,
3758 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3759 NULL_TREE);
3761 return decl;
3764 static void
3765 generate_ivar_lists ()
3767 tree initlist, ivar_list_template, chain;
3768 tree cast, variable_length_type;
3769 int size;
3771 generating_instance_variables = 1;
3773 if (!objc_ivar_template)
3774 objc_ivar_template = build_ivar_template ();
3776 cast
3777 = build_tree_list
3778 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3779 get_identifier (UTAG_IVAR_LIST))),
3780 NULL_TREE);
3781 variable_length_type = groktypename (cast);
3783 /* Only generate class variables for the root of the inheritance
3784 hierarchy since these will be the same for every class. */
3786 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3787 && (chain = TYPE_FIELDS (objc_class_template)))
3789 size = list_length (chain);
3791 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3792 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3794 UOBJC_CLASS_VARIABLES_decl
3795 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3796 size, initlist);
3797 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3799 else
3800 UOBJC_CLASS_VARIABLES_decl = 0;
3802 chain = CLASS_IVARS (implementation_template);
3803 if (chain)
3805 size = list_length (chain);
3806 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3807 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3809 UOBJC_INSTANCE_VARIABLES_decl
3810 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3811 size, initlist);
3812 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3814 else
3815 UOBJC_INSTANCE_VARIABLES_decl = 0;
3817 generating_instance_variables = 0;
3820 static tree
3821 build_dispatch_table_initializer (type, entries)
3822 tree type;
3823 tree entries;
3825 tree initlist = NULL_TREE;
3829 tree elemlist = NULL_TREE;
3831 elemlist = tree_cons (NULL_TREE,
3832 build_selector (METHOD_SEL_NAME (entries)),
3833 NULL_TREE);
3835 elemlist = tree_cons (NULL_TREE,
3836 add_objc_string (METHOD_ENCODING (entries),
3837 meth_var_types),
3838 elemlist);
3840 elemlist = tree_cons (NULL_TREE,
3841 build_unary_op (ADDR_EXPR,
3842 METHOD_DEFINITION (entries), 1),
3843 elemlist);
3845 initlist = tree_cons (NULL_TREE,
3846 build_constructor (type, nreverse (elemlist)),
3847 initlist);
3849 entries = TREE_CHAIN (entries);
3851 while (entries);
3853 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3856 /* To accomplish method prototyping without generating all kinds of
3857 inane warnings, the definition of the dispatch table entries were
3858 changed from:
3860 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
3862 struct objc_method { SEL _cmd; ...; void *_imp; }; */
3864 static tree
3865 build_method_template ()
3867 tree _SLT_record;
3868 tree decl_specs, field_decl, field_decl_chain;
3870 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
3872 #ifdef OBJC_INT_SELECTORS
3873 /* unsigned int _cmd; */
3874 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED],
3875 NULL_TREE);
3876 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
3877 field_decl = get_identifier ("_cmd");
3878 #else /* not OBJC_INT_SELECTORS */
3879 /* struct objc_selector *_cmd; */
3880 decl_specs = tree_cons (NULL_TREE,
3881 xref_tag (RECORD_TYPE,
3882 get_identifier (TAG_SELECTOR)),
3883 NULL_TREE);
3884 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
3885 #endif /* not OBJC_INT_SELECTORS */
3887 field_decl = grokfield (input_filename, lineno, field_decl,
3888 decl_specs, NULL_TREE);
3889 field_decl_chain = field_decl;
3891 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
3892 field_decl = build1 (INDIRECT_REF, NULL_TREE,
3893 get_identifier ("method_types"));
3894 field_decl = grokfield (input_filename, lineno, field_decl,
3895 decl_specs, NULL_TREE);
3896 chainon (field_decl_chain, field_decl);
3898 /* void *_imp; */
3900 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
3901 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
3902 field_decl = grokfield (input_filename, lineno, field_decl,
3903 decl_specs, NULL_TREE);
3904 chainon (field_decl_chain, field_decl);
3906 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
3908 return _SLT_record;
3912 static tree
3913 generate_dispatch_table (type, name, size, list)
3914 tree type;
3915 char *name;
3916 int size;
3917 tree list;
3919 tree sc_spec, decl_specs, decl, initlist;
3921 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3922 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3924 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3925 decl_specs, 1, NULL_TREE, NULL_TREE);
3927 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
3928 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
3929 initlist = tree_cons (NULL_TREE, list, initlist);
3931 finish_decl (decl,
3932 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3933 NULL_TREE);
3935 return decl;
3938 static void
3939 generate_dispatch_tables ()
3941 tree initlist, chain, method_list_template;
3942 tree cast, variable_length_type;
3943 int size;
3945 if (!objc_method_template)
3946 objc_method_template = build_method_template ();
3948 cast
3949 = build_tree_list
3950 (build_tree_list (NULL_TREE,
3951 xref_tag (RECORD_TYPE,
3952 get_identifier (UTAG_METHOD_LIST))),
3953 NULL_TREE);
3955 variable_length_type = groktypename (cast);
3957 chain = CLASS_CLS_METHODS (implementation_context);
3958 if (chain)
3960 size = list_length (chain);
3962 method_list_template
3963 = build_method_list_template (objc_method_template, size);
3964 initlist
3965 = build_dispatch_table_initializer (objc_method_template, chain);
3967 UOBJC_CLASS_METHODS_decl
3968 = generate_dispatch_table (method_list_template,
3969 ((TREE_CODE (implementation_context)
3970 == CLASS_IMPLEMENTATION_TYPE)
3971 ? "_OBJC_CLASS_METHODS"
3972 : "_OBJC_CATEGORY_CLASS_METHODS"),
3973 size, initlist);
3974 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
3976 else
3977 UOBJC_CLASS_METHODS_decl = 0;
3979 chain = CLASS_NST_METHODS (implementation_context);
3980 if (chain)
3982 size = list_length (chain);
3984 method_list_template
3985 = build_method_list_template (objc_method_template, size);
3986 initlist
3987 = build_dispatch_table_initializer (objc_method_template, chain);
3989 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
3990 UOBJC_INSTANCE_METHODS_decl
3991 = generate_dispatch_table (method_list_template,
3992 "_OBJC_INSTANCE_METHODS",
3993 size, initlist);
3994 else
3995 /* We have a category. */
3996 UOBJC_INSTANCE_METHODS_decl
3997 = generate_dispatch_table (method_list_template,
3998 "_OBJC_CATEGORY_INSTANCE_METHODS",
3999 size, initlist);
4000 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4002 else
4003 UOBJC_INSTANCE_METHODS_decl = 0;
4006 static tree
4007 generate_protocol_list (i_or_p)
4008 tree i_or_p;
4010 static tree cast_type = 0;
4011 tree initlist, decl_specs, sc_spec;
4012 tree refs_decl, expr_decl, lproto, e, plist;
4013 int size = 0;
4015 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4016 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4017 plist = CLASS_PROTOCOL_LIST (i_or_p);
4018 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4019 plist = PROTOCOL_LIST (i_or_p);
4020 else
4021 abort ();
4023 if (!cast_type)
4024 cast_type
4025 = groktypename
4026 (build_tree_list
4027 (build_tree_list (NULL_TREE,
4028 xref_tag (RECORD_TYPE,
4029 get_identifier (UTAG_PROTOCOL))),
4030 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4032 /* Compute size. */
4033 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4034 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4035 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4036 size++;
4038 /* Build initializer. */
4039 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4041 e = build_int_2 (size, 0);
4042 TREE_TYPE (e) = cast_type;
4043 initlist = tree_cons (NULL_TREE, e, initlist);
4045 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4047 tree pval = TREE_VALUE (lproto);
4049 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4050 && PROTOCOL_FORWARD_DECL (pval))
4052 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4053 initlist = tree_cons (NULL_TREE, e, initlist);
4057 /* static struct objc_protocol *refs[n]; */
4059 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4060 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4061 get_identifier (UTAG_PROTOCOL)),
4062 sc_spec);
4064 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4065 expr_decl = build_nt (ARRAY_REF,
4066 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4067 i_or_p),
4068 build_int_2 (size + 2, 0));
4069 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4070 expr_decl = build_nt (ARRAY_REF,
4071 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4072 i_or_p),
4073 build_int_2 (size + 2, 0));
4074 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4075 expr_decl
4076 = build_nt (ARRAY_REF,
4077 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4078 i_or_p),
4079 build_int_2 (size + 2, 0));
4081 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4083 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
4085 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
4086 nreverse (initlist)),
4087 NULL_TREE);
4089 return refs_decl;
4092 static tree
4093 build_category_initializer (type, cat_name, class_name,
4094 instance_methods, class_methods, protocol_list)
4095 tree type;
4096 tree cat_name;
4097 tree class_name;
4098 tree instance_methods;
4099 tree class_methods;
4100 tree protocol_list;
4102 tree initlist = NULL_TREE, expr;
4104 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4105 initlist = tree_cons (NULL_TREE, class_name, initlist);
4107 if (!instance_methods)
4108 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4109 else
4111 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4112 initlist = tree_cons (NULL_TREE, expr, initlist);
4114 if (!class_methods)
4115 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4116 else
4118 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4119 initlist = tree_cons (NULL_TREE, expr, initlist);
4122 /* protocol_list = */
4123 if (!protocol_list)
4124 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4125 else
4127 static tree cast_type2;
4129 if (!cast_type2)
4130 cast_type2
4131 = groktypename
4132 (build_tree_list
4133 (build_tree_list (NULL_TREE,
4134 xref_tag (RECORD_TYPE,
4135 get_identifier (UTAG_PROTOCOL))),
4136 build1 (INDIRECT_REF, NULL_TREE,
4137 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4139 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4140 TREE_TYPE (expr) = cast_type2;
4141 initlist = tree_cons (NULL_TREE, expr, initlist);
4144 return build_constructor (type, nreverse (initlist));
4147 /* struct objc_class {
4148 struct objc_class *isa;
4149 struct objc_class *super_class;
4150 char *name;
4151 long version;
4152 long info;
4153 long instance_size;
4154 struct objc_ivar_list *ivars;
4155 struct objc_method_list *methods;
4156 if (flag_next_runtime)
4157 struct objc_cache *cache;
4158 else {
4159 struct sarray *dtable;
4160 struct objc_class *subclass_list;
4161 struct objc_class *sibling_class;
4163 struct objc_protocol_list *protocols;
4164 }; */
4166 static tree
4167 build_shared_structure_initializer (type, isa, super, name, size, status,
4168 dispatch_table, ivar_list, protocol_list)
4169 tree type;
4170 tree isa;
4171 tree super;
4172 tree name;
4173 tree size;
4174 int status;
4175 tree dispatch_table;
4176 tree ivar_list;
4177 tree protocol_list;
4179 tree initlist = NULL_TREE, expr;
4181 /* isa = */
4182 initlist = tree_cons (NULL_TREE, isa, initlist);
4184 /* super_class = */
4185 initlist = tree_cons (NULL_TREE, super, initlist);
4187 /* name = */
4188 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4190 /* version = */
4191 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4193 /* info = */
4194 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4196 /* instance_size = */
4197 initlist = tree_cons (NULL_TREE, size, initlist);
4199 /* objc_ivar_list = */
4200 if (!ivar_list)
4201 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4202 else
4204 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4205 initlist = tree_cons (NULL_TREE, expr, initlist);
4208 /* objc_method_list = */
4209 if (!dispatch_table)
4210 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4211 else
4213 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4214 initlist = tree_cons (NULL_TREE, expr, initlist);
4217 if (flag_next_runtime)
4218 /* method_cache = */
4219 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4220 else
4222 /* dtable = */
4223 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4225 /* subclass_list = */
4226 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4228 /* sibling_class = */
4229 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4232 /* protocol_list = */
4233 if (! protocol_list)
4234 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4235 else
4237 static tree cast_type2;
4239 if (!cast_type2)
4240 cast_type2
4241 = groktypename
4242 (build_tree_list
4243 (build_tree_list (NULL_TREE,
4244 xref_tag (RECORD_TYPE,
4245 get_identifier (UTAG_PROTOCOL))),
4246 build1 (INDIRECT_REF, NULL_TREE,
4247 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4249 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4250 TREE_TYPE (expr) = cast_type2;
4251 initlist = tree_cons (NULL_TREE, expr, initlist);
4254 return build_constructor (type, nreverse (initlist));
4257 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
4259 static void
4260 generate_category (cat)
4261 tree cat;
4263 tree sc_spec, decl_specs, decl;
4264 tree initlist, cat_name_expr, class_name_expr;
4265 tree protocol_decl, category;
4267 add_class_reference (CLASS_NAME (cat));
4268 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4270 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4272 category = CLASS_CATEGORY_LIST (implementation_template);
4274 /* find the category interface from the class it is associated with */
4275 while (category)
4277 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4278 break;
4279 category = CLASS_CATEGORY_LIST (category);
4282 if (category && CLASS_PROTOCOL_LIST (category))
4284 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4285 protocol_decl = generate_protocol_list (category);
4287 else
4288 protocol_decl = 0;
4290 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4291 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4293 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4294 implementation_context),
4295 decl_specs, 1, NULL_TREE, NULL_TREE);
4297 initlist = build_category_initializer (TREE_TYPE (decl),
4298 cat_name_expr, class_name_expr,
4299 UOBJC_INSTANCE_METHODS_decl,
4300 UOBJC_CLASS_METHODS_decl,
4301 protocol_decl);
4303 TREE_USED (decl) = 1;
4304 finish_decl (decl, initlist, NULL_TREE);
4307 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4308 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4310 static void
4311 generate_shared_structures ()
4313 tree sc_spec, decl_specs, decl;
4314 tree name_expr, super_expr, root_expr;
4315 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4316 tree cast_type, initlist, protocol_decl;
4318 my_super_id = CLASS_SUPER_NAME (implementation_template);
4319 if (my_super_id)
4321 add_class_reference (my_super_id);
4323 /* Compute "my_root_id" - this is required for code generation.
4324 the "isa" for all meta class structures points to the root of
4325 the inheritance hierarchy (e.g. "__Object")... */
4326 my_root_id = my_super_id;
4329 tree my_root_int = lookup_interface (my_root_id);
4331 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4332 my_root_id = CLASS_SUPER_NAME (my_root_int);
4333 else
4334 break;
4336 while (1);
4338 else
4339 /* No super class. */
4340 my_root_id = CLASS_NAME (implementation_template);
4342 cast_type
4343 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4344 objc_class_template),
4345 build1 (INDIRECT_REF,
4346 NULL_TREE, NULL_TREE)));
4348 name_expr = add_objc_string (CLASS_NAME (implementation_template),
4349 class_names);
4351 /* Install class `isa' and `super' pointers at runtime. */
4352 if (my_super_id)
4354 super_expr = add_objc_string (my_super_id, class_names);
4355 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4357 else
4358 super_expr = build_int_2 (0, 0);
4360 root_expr = add_objc_string (my_root_id, class_names);
4361 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4363 if (CLASS_PROTOCOL_LIST (implementation_template))
4365 generate_protocol_references
4366 (CLASS_PROTOCOL_LIST (implementation_template));
4367 protocol_decl = generate_protocol_list (implementation_template);
4369 else
4370 protocol_decl = 0;
4372 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4374 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4375 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4377 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4378 NULL_TREE, NULL_TREE);
4380 initlist
4381 = build_shared_structure_initializer
4382 (TREE_TYPE (decl),
4383 root_expr, super_expr, name_expr,
4384 build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template))
4385 / BITS_PER_UNIT),
4387 2 /*CLS_META*/,
4388 UOBJC_CLASS_METHODS_decl,
4389 UOBJC_CLASS_VARIABLES_decl,
4390 protocol_decl);
4392 finish_decl (decl, initlist, NULL_TREE);
4394 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4396 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4397 NULL_TREE, NULL_TREE);
4399 initlist
4400 = build_shared_structure_initializer
4401 (TREE_TYPE (decl),
4402 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4403 super_expr, name_expr,
4404 build_int_2
4405 ((TREE_INT_CST_LOW
4406 (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template)))
4407 / BITS_PER_UNIT),
4409 1 /*CLS_FACTORY*/,
4410 UOBJC_INSTANCE_METHODS_decl,
4411 UOBJC_INSTANCE_VARIABLES_decl,
4412 protocol_decl);
4414 finish_decl (decl, initlist, NULL_TREE);
4417 static tree
4418 synth_id_with_class_suffix (preamble, ctxt)
4419 char *preamble;
4420 tree ctxt;
4422 char *string;
4423 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4424 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4426 char *class_name
4427 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4428 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4429 sprintf (string, "%s_%s", preamble,
4430 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4432 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4433 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4435 /* We have a category. */
4436 char *class_name
4437 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4438 char *class_super_name
4439 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
4440 string = (char *) alloca (strlen (preamble)
4441 + strlen (class_name)
4442 + strlen (class_super_name)
4443 + 3);
4444 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4446 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4448 char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4449 string
4450 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4451 sprintf (string, "%s_%s", preamble, protocol_name);
4453 return get_identifier (string);
4456 static int
4457 is_objc_type_qualifier (node)
4458 tree node;
4460 return (TREE_CODE (node) == IDENTIFIER_NODE
4461 && (node == ridpointers [(int) RID_CONST]
4462 || node == ridpointers [(int) RID_VOLATILE]
4463 || node == ridpointers [(int) RID_IN]
4464 || node == ridpointers [(int) RID_OUT]
4465 || node == ridpointers [(int) RID_INOUT]
4466 || node == ridpointers [(int) RID_BYCOPY]
4467 || node == ridpointers [(int) RID_ONEWAY]));
4470 /* If type is empty or only type qualifiers are present, add default
4471 type of id (otherwise grokdeclarator will default to int). */
4473 static tree
4474 adjust_type_for_id_default (type)
4475 tree type;
4477 tree declspecs, chain;
4479 if (!type)
4480 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4481 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4483 declspecs = TREE_PURPOSE (type);
4485 /* Determine if a typespec is present. */
4486 for (chain = declspecs;
4487 chain;
4488 chain = TREE_CHAIN (chain))
4490 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4491 return type;
4494 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4495 declspecs),
4496 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4499 /* Usage:
4500 keyworddecl:
4501 selector ':' '(' typename ')' identifier
4503 Purpose:
4504 Transform an Objective-C keyword argument into
4505 the C equivalent parameter declarator.
4507 In: key_name, an "identifier_node" (optional).
4508 arg_type, a "tree_list" (optional).
4509 arg_name, an "identifier_node".
4511 Note: It would be really nice to strongly type the preceding
4512 arguments in the function prototype; however, then I
4513 could not use the "accessor" macros defined in "tree.h".
4515 Out: an instance of "keyword_decl". */
4517 tree
4518 build_keyword_decl (key_name, arg_type, arg_name)
4519 tree key_name;
4520 tree arg_type;
4521 tree arg_name;
4523 tree keyword_decl;
4525 /* If no type is specified, default to "id". */
4526 arg_type = adjust_type_for_id_default (arg_type);
4528 keyword_decl = make_node (KEYWORD_DECL);
4530 TREE_TYPE (keyword_decl) = arg_type;
4531 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4532 KEYWORD_KEY_NAME (keyword_decl) = key_name;
4534 return keyword_decl;
4537 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
4539 static tree
4540 build_keyword_selector (selector)
4541 tree selector;
4543 int len = 0;
4544 tree key_chain, key_name;
4545 char *buf;
4547 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4549 if (TREE_CODE (selector) == KEYWORD_DECL)
4550 key_name = KEYWORD_KEY_NAME (key_chain);
4551 else if (TREE_CODE (selector) == TREE_LIST)
4552 key_name = TREE_PURPOSE (key_chain);
4554 if (key_name)
4555 len += IDENTIFIER_LENGTH (key_name) + 1;
4556 else
4557 /* Just a ':' arg. */
4558 len++;
4561 buf = (char *)alloca (len + 1);
4562 bzero (buf, len + 1);
4564 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4566 if (TREE_CODE (selector) == KEYWORD_DECL)
4567 key_name = KEYWORD_KEY_NAME (key_chain);
4568 else if (TREE_CODE (selector) == TREE_LIST)
4569 key_name = TREE_PURPOSE (key_chain);
4571 if (key_name)
4572 strcat (buf, IDENTIFIER_POINTER (key_name));
4573 strcat (buf, ":");
4576 return get_identifier (buf);
4579 /* Used for declarations and definitions. */
4581 tree
4582 build_method_decl (code, ret_type, selector, add_args)
4583 enum tree_code code;
4584 tree ret_type;
4585 tree selector;
4586 tree add_args;
4588 tree method_decl;
4590 /* If no type is specified, default to "id". */
4591 ret_type = adjust_type_for_id_default (ret_type);
4593 method_decl = make_node (code);
4594 TREE_TYPE (method_decl) = ret_type;
4596 /* If we have a keyword selector, create an identifier_node that
4597 represents the full selector name (`:' included)... */
4598 if (TREE_CODE (selector) == KEYWORD_DECL)
4600 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4601 METHOD_SEL_ARGS (method_decl) = selector;
4602 METHOD_ADD_ARGS (method_decl) = add_args;
4604 else
4606 METHOD_SEL_NAME (method_decl) = selector;
4607 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4608 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4611 return method_decl;
4614 #define METHOD_DEF 0
4615 #define METHOD_REF 1
4617 /* Used by `build_message_expr' and `comp_method_types'. Return an
4618 argument list for method METH. CONTEXT is either METHOD_DEF or
4619 METHOD_REF, saying whether we are trying to define a method or call
4620 one. SUPERFLAG says this is for a send to super; this makes a
4621 difference for the NeXT calling sequence in which the lookup and
4622 the method call are done together. */
4624 static tree
4625 get_arg_type_list (meth, context, superflag)
4626 tree meth;
4627 int context;
4628 int superflag;
4630 tree arglist, akey;
4632 /* Receiver type. */
4633 if (flag_next_runtime && superflag)
4634 arglist = build_tree_list (NULL_TREE, super_type);
4635 else if (context == METHOD_DEF)
4636 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4637 else
4638 arglist = build_tree_list (NULL_TREE, id_type);
4640 /* Selector type - will eventually change to `int'. */
4641 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4643 /* Build a list of argument types. */
4644 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4646 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4647 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4650 if (METHOD_ADD_ARGS (meth) == (tree)1)
4651 /* We have a `, ...' immediately following the selector,
4652 finalize the arglist...simulate get_parm_info (0). */
4654 else if (METHOD_ADD_ARGS (meth))
4656 /* we have a variable length selector */
4657 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4658 chainon (arglist, add_arg_list);
4660 else
4661 /* finalize the arglist...simulate get_parm_info (1) */
4662 chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4664 return arglist;
4667 static tree
4668 check_duplicates (hsh)
4669 hash hsh;
4671 tree meth = NULL_TREE;
4673 if (hsh)
4675 meth = hsh->key;
4677 if (hsh->list)
4679 /* We have two methods with the same name and different types. */
4680 attr loop;
4681 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4683 warning ("multiple declarations for method `%s'",
4684 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4686 warn_with_method ("using", type, meth);
4687 for (loop = hsh->list; loop; loop = loop->next)
4688 warn_with_method ("also found", type, loop->value);
4691 return meth;
4694 /* If RECEIVER is a class reference, return the identifier node for the
4695 referenced class. RECEIVER is created by get_class_reference, so we
4696 check the exact form created depending on which runtimes are used. */
4698 static tree
4699 receiver_is_class_object (receiver)
4700 tree receiver;
4702 tree chain, exp, arg;
4703 if (flag_next_runtime)
4705 /* The receiver is a variable created by build_class_reference_decl. */
4706 if (TREE_CODE (receiver) == VAR_DECL
4707 && TREE_TYPE (receiver) == objc_class_type)
4708 /* Look up the identifier. */
4709 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4710 if (TREE_PURPOSE (chain) == receiver)
4711 return TREE_VALUE (chain);
4713 else
4715 /* The receiver is a function call that returns an id. Check if
4716 it is a call to objc_getClass, if so, pick up the class name. */
4717 if ((exp = TREE_OPERAND (receiver, 0))
4718 && TREE_CODE (exp) == ADDR_EXPR
4719 && (exp = TREE_OPERAND (exp, 0))
4720 && TREE_CODE (exp) == FUNCTION_DECL
4721 && exp == objc_get_class_decl
4722 /* we have a call to objc_getClass! */
4723 && (arg = TREE_OPERAND (receiver, 1))
4724 && TREE_CODE (arg) == TREE_LIST
4725 && (arg = TREE_VALUE (arg)))
4727 STRIP_NOPS (arg);
4728 if (TREE_CODE (arg) == ADDR_EXPR
4729 && (arg = TREE_OPERAND (arg, 0))
4730 && TREE_CODE (arg) == STRING_CST)
4731 /* Finally, we have the class name. */
4732 return get_identifier (TREE_STRING_POINTER (arg));
4735 return 0;
4738 /* If we are currently building a message expr, this holds
4739 the identifier of the selector of the message. This is
4740 used when printing warnings about argument mismatches. */
4742 static tree building_objc_message_expr = 0;
4744 tree
4745 maybe_building_objc_message_expr ()
4747 return building_objc_message_expr;
4750 /* Construct an expression for sending a message.
4751 MESS has the object to send to in TREE_PURPOSE
4752 and the argument list (including selector) in TREE_VALUE.
4754 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4755 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
4757 tree
4758 build_message_expr (mess)
4759 tree mess;
4761 tree receiver = TREE_PURPOSE (mess);
4762 tree selector, self_object;
4763 tree rtype, sel_name;
4764 tree args = TREE_VALUE (mess);
4765 tree method_params = NULL_TREE;
4766 tree method_prototype = NULL_TREE;
4767 tree retval;
4768 int statically_typed = 0, statically_allocated = 0;
4769 tree class_ident = 0;
4771 /* 1 if this is sending to the superclass. */
4772 int super;
4774 if (!doing_objc_thang)
4775 objc_fatal ();
4777 if (TREE_CODE (receiver) == ERROR_MARK)
4778 return error_mark_node;
4780 /* Determine receiver type. */
4781 rtype = TREE_TYPE (receiver);
4782 super = IS_SUPER (rtype);
4784 if (! super)
4786 if (TREE_STATIC_TEMPLATE (rtype))
4787 statically_allocated = 1;
4788 else if (TREE_CODE (rtype) == POINTER_TYPE
4789 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4790 statically_typed = 1;
4791 else if ((flag_next_runtime
4792 || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
4793 && (class_ident = receiver_is_class_object (receiver)))
4795 else if (! IS_ID (rtype)
4796 /* Allow any type that matches objc_class_type. */
4797 && ! comptypes (rtype, objc_class_type))
4799 bzero (errbuf, BUFSIZE);
4800 warning ("invalid receiver type `%s'",
4801 gen_declaration (rtype, errbuf));
4804 if (statically_allocated)
4805 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4807 /* Don't evaluate the receiver twice. */
4808 receiver = save_expr (receiver);
4809 self_object = receiver;
4811 else
4812 /* If sending to `super', use current self as the object. */
4813 self_object = self_decl;
4815 /* Obtain the full selector name. */
4817 if (TREE_CODE (args) == IDENTIFIER_NODE)
4818 /* A unary selector. */
4819 sel_name = args;
4820 else if (TREE_CODE (args) == TREE_LIST)
4821 sel_name = build_keyword_selector (args);
4823 /* Build the parameter list to give to the method. */
4825 method_params = NULL_TREE;
4826 if (TREE_CODE (args) == TREE_LIST)
4828 tree chain = args, prev = NULL_TREE;
4830 /* We have a keyword selector--check for comma expressions. */
4831 while (chain)
4833 tree element = TREE_VALUE (chain);
4835 /* We have a comma expression, must collapse... */
4836 if (TREE_CODE (element) == TREE_LIST)
4838 if (prev)
4839 TREE_CHAIN (prev) = element;
4840 else
4841 args = element;
4843 prev = chain;
4844 chain = TREE_CHAIN (chain);
4846 method_params = args;
4849 /* Determine operation return type. */
4851 if (IS_SUPER (rtype))
4853 tree iface;
4855 if (CLASS_SUPER_NAME (implementation_template))
4857 iface
4858 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
4860 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4861 method_prototype = lookup_instance_method_static (iface, sel_name);
4862 else
4863 method_prototype = lookup_class_method_static (iface, sel_name);
4865 if (iface && !method_prototype)
4866 warning ("`%s' does not respond to `%s'",
4867 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
4868 IDENTIFIER_POINTER (sel_name));
4870 else
4872 error ("no super class declared in interface for `%s'",
4873 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4874 return error_mark_node;
4878 else if (statically_allocated)
4880 tree ctype = TREE_TYPE (rtype);
4881 tree iface = lookup_interface (TYPE_NAME (rtype));
4883 if (iface)
4884 method_prototype = lookup_instance_method_static (iface, sel_name);
4886 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4887 method_prototype
4888 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4889 sel_name, 0);
4891 if (!method_prototype)
4892 warning ("`%s' does not respond to `%s'",
4893 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
4894 IDENTIFIER_POINTER (sel_name));
4896 else if (statically_typed)
4898 tree ctype = TREE_TYPE (rtype);
4900 /* `self' is now statically_typed. All methods should be visible
4901 within the context of the implementation. */
4902 if (implementation_context
4903 && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
4905 method_prototype
4906 = lookup_instance_method_static (implementation_template,
4907 sel_name);
4909 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4910 method_prototype
4911 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4912 sel_name, 0);
4914 if (! method_prototype
4915 && implementation_template != implementation_context)
4916 /* The method is not published in the interface. Check
4917 locally. */
4918 method_prototype
4919 = lookup_method (CLASS_NST_METHODS (implementation_context),
4920 sel_name);
4922 else
4924 tree iface;
4926 if ((iface = lookup_interface (TYPE_NAME (ctype))))
4927 method_prototype = lookup_instance_method_static (iface, sel_name);
4929 if (! method_prototype)
4931 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
4932 if (protocol_list)
4933 method_prototype
4934 = lookup_method_in_protocol_list (protocol_list,
4935 sel_name, 0);
4939 if (!method_prototype)
4940 warning ("`%s' does not respond to `%s'",
4941 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
4942 IDENTIFIER_POINTER (sel_name));
4944 else if (class_ident)
4946 if (implementation_context
4947 && CLASS_NAME (implementation_context) == class_ident)
4949 method_prototype
4950 = lookup_class_method_static (implementation_template, sel_name);
4952 if (!method_prototype
4953 && implementation_template != implementation_context)
4954 /* The method is not published in the interface. Check
4955 locally. */
4956 method_prototype
4957 = lookup_method (CLASS_CLS_METHODS (implementation_context),
4958 sel_name);
4960 else
4962 tree iface;
4964 if ((iface = lookup_interface (class_ident)))
4965 method_prototype = lookup_class_method_static (iface, sel_name);
4968 if (!method_prototype)
4970 warning ("cannot find class (factory) method.");
4971 warning ("return type for `%s' defaults to id",
4972 IDENTIFIER_POINTER (sel_name));
4975 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
4977 /* An anonymous object that has been qualified with a protocol. */
4979 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
4981 method_prototype = lookup_method_in_protocol_list (protocol_list,
4982 sel_name, 0);
4984 if (!method_prototype)
4986 hash hsh;
4988 warning ("method `%s' not implemented by protocol.",
4989 IDENTIFIER_POINTER (sel_name));
4991 /* Try and find the method signature in the global pools. */
4993 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
4994 hsh = hash_lookup (cls_method_hash_list, sel_name);
4996 if (!(method_prototype = check_duplicates (hsh)))
4997 warning ("return type defaults to id");
5000 else
5002 hash hsh;
5004 /* We think we have an instance...loophole: extern id Object; */
5005 hsh = hash_lookup (nst_method_hash_list, sel_name);
5006 if (!hsh)
5007 /* For various loopholes, like sending messages to self in a
5008 factory context. */
5009 hsh = hash_lookup (cls_method_hash_list, sel_name);
5011 method_prototype = check_duplicates (hsh);
5012 if (!method_prototype)
5014 warning ("cannot find method.");
5015 warning ("return type for `%s' defaults to id",
5016 IDENTIFIER_POINTER (sel_name));
5020 /* Save the selector name for printing error messages. */
5021 building_objc_message_expr = sel_name;
5023 /* Build the parameters list for looking up the method.
5024 These are the object itself and the selector. */
5026 if (flag_typed_selectors)
5027 selector = build_typed_selector_reference (sel_name, method_prototype);
5028 else
5029 selector = build_selector_reference (sel_name);
5031 retval = build_objc_method_call (super, method_prototype,
5032 receiver, self_object,
5033 selector, method_params);
5035 building_objc_message_expr = 0;
5037 return retval;
5040 /* Build a tree expression to send OBJECT the operation SELECTOR,
5041 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5042 assuming the method has prototype METHOD_PROTOTYPE.
5043 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5044 Use METHOD_PARAMS as list of args to pass to the method.
5045 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5047 static tree
5048 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
5049 selector, method_params)
5050 int super_flag;
5051 tree method_prototype, lookup_object, object, selector, method_params;
5053 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
5054 tree rcv_p = (super_flag
5055 ? build_pointer_type (xref_tag (RECORD_TYPE,
5056 get_identifier (TAG_SUPER)))
5057 : id_type);
5059 if (flag_next_runtime)
5061 if (! method_prototype)
5063 method_params = tree_cons (NULL_TREE, lookup_object,
5064 tree_cons (NULL_TREE, selector,
5065 method_params));
5066 assemble_external (sender);
5067 return build_function_call (sender, method_params);
5069 else
5071 /* This is a real kludge, but it is used only for the Next.
5072 Clobber the data type of SENDER temporarily to accept
5073 all the arguments for this operation, and to return
5074 whatever this operation returns. */
5075 tree arglist = NULL_TREE;
5076 tree retval;
5078 /* Save the proper contents of SENDER's data type. */
5079 tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5080 tree savret = TREE_TYPE (TREE_TYPE (sender));
5082 /* Install this method's argument types. */
5083 arglist = get_arg_type_list (method_prototype, METHOD_REF,
5084 super_flag);
5085 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5087 /* Install this method's return type. */
5088 TREE_TYPE (TREE_TYPE (sender))
5089 = groktypename (TREE_TYPE (method_prototype));
5091 /* Call SENDER with all the parameters. This will do type
5092 checking using the arg types for this method. */
5093 method_params = tree_cons (NULL_TREE, lookup_object,
5094 tree_cons (NULL_TREE, selector,
5095 method_params));
5096 assemble_external (sender);
5097 retval = build_function_call (sender, method_params);
5099 /* Restore SENDER's return/argument types. */
5100 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5101 TREE_TYPE (TREE_TYPE (sender)) = savret;
5102 return retval;
5105 else
5107 /* This is the portable way.
5108 First call the lookup function to get a pointer to the method,
5109 then cast the pointer, then call it with the method arguments. */
5110 tree method;
5112 /* Avoid trouble since we may evaluate each of these twice. */
5113 object = save_expr (object);
5114 selector = save_expr (selector);
5116 lookup_object = build_c_cast (rcv_p, lookup_object);
5118 assemble_external (sender);
5119 method
5120 = build_function_call (sender,
5121 tree_cons (NULL_TREE, lookup_object,
5122 tree_cons (NULL_TREE, selector,
5123 NULL_TREE)));
5125 /* If we have a method prototype, construct the data type this
5126 method needs, and cast what we got from SENDER into a pointer
5127 to that type. */
5128 if (method_prototype)
5130 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5131 super_flag);
5132 tree valtype = groktypename (TREE_TYPE (method_prototype));
5133 tree fake_function_type = build_function_type (valtype, arglist);
5134 TREE_TYPE (method) = build_pointer_type (fake_function_type);
5136 else
5137 TREE_TYPE (method)
5138 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5140 /* Pass the object to the method. */
5141 assemble_external (method);
5142 return build_function_call (method,
5143 tree_cons (NULL_TREE, object,
5144 tree_cons (NULL_TREE, selector,
5145 method_params)));
5149 static void
5150 build_protocol_reference (p)
5151 tree p;
5153 tree decl, ident, ptype;
5155 push_obstacks_nochange ();
5156 end_temporary_allocation ();
5158 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5160 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5161 ptype
5162 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5163 objc_protocol_template),
5164 NULL_TREE));
5166 if (IDENTIFIER_GLOBAL_VALUE (ident))
5167 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
5168 else
5170 decl = build_decl (VAR_DECL, ident, ptype);
5171 DECL_EXTERNAL (decl) = 1;
5172 TREE_PUBLIC (decl) = 1;
5173 TREE_USED (decl) = 1;
5174 DECL_ARTIFICIAL (decl) = 1;
5176 make_decl_rtl (decl, 0, 1);
5177 pushdecl_top_level (decl);
5180 PROTOCOL_FORWARD_DECL (p) = decl;
5181 pop_obstacks ();
5184 tree
5185 build_protocol_expr (protoname)
5186 tree protoname;
5188 tree expr;
5189 tree p;
5191 if (!doing_objc_thang)
5192 objc_fatal ();
5194 p = lookup_protocol (protoname);
5196 if (!p)
5198 error ("Cannot find protocol declaration for `%s'",
5199 IDENTIFIER_POINTER (protoname));
5200 return error_mark_node;
5203 if (!PROTOCOL_FORWARD_DECL (p))
5204 build_protocol_reference (p);
5206 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5208 TREE_TYPE (expr) = protocol_type;
5210 return expr;
5213 tree
5214 build_selector_expr (selnamelist)
5215 tree selnamelist;
5217 tree selname;
5219 if (!doing_objc_thang)
5220 objc_fatal ();
5222 /* Obtain the full selector name. */
5223 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5224 /* A unary selector. */
5225 selname = selnamelist;
5226 else if (TREE_CODE (selnamelist) == TREE_LIST)
5227 selname = build_keyword_selector (selnamelist);
5229 if (flag_typed_selectors)
5230 return build_typed_selector_reference (selname, 0);
5231 else
5232 return build_selector_reference (selname);
5235 tree
5236 build_encode_expr (type)
5237 tree type;
5239 tree result;
5240 char *string;
5242 if (!doing_objc_thang)
5243 objc_fatal ();
5245 encode_type (type, obstack_object_size (&util_obstack),
5246 OBJC_ENCODE_INLINE_DEFS);
5247 obstack_1grow (&util_obstack, 0); /* null terminate string */
5248 string = obstack_finish (&util_obstack);
5250 /* Synthesize a string that represents the encoded struct/union. */
5251 result = my_build_string (strlen (string) + 1, string);
5252 obstack_free (&util_obstack, util_firstobj);
5253 return result;
5256 tree
5257 build_ivar_reference (id)
5258 tree id;
5260 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
5262 /* Historically, a class method that produced objects (factory
5263 method) would assign `self' to the instance that it
5264 allocated. This would effectively turn the class method into
5265 an instance method. Following this assignment, the instance
5266 variables could be accessed. That practice, while safe,
5267 violates the simple rule that a class method should not refer
5268 to an instance variable. It's better to catch the cases
5269 where this is done unknowingly than to support the above
5270 paradigm. */
5271 warning ("instance variable `%s' accessed in class method",
5272 IDENTIFIER_POINTER (id));
5273 TREE_TYPE (self_decl) = instance_type; /* cast */
5276 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5279 #define HASH_ALLOC_LIST_SIZE 170
5280 #define ATTR_ALLOC_LIST_SIZE 170
5281 #define SIZEHASHTABLE 257
5283 /* make positive */
5284 #define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff)
5286 static void
5287 hash_init ()
5289 nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5290 cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5292 if (!nst_method_hash_list || !cls_method_hash_list)
5293 perror ("unable to allocate space in objc-tree.c");
5294 else
5296 int i;
5298 for (i = 0; i < SIZEHASHTABLE; i++)
5300 nst_method_hash_list[i] = 0;
5301 cls_method_hash_list[i] = 0;
5306 static void
5307 hash_enter (hashlist, method)
5308 hash *hashlist;
5309 tree method;
5311 static hash hash_alloc_list = 0;
5312 static int hash_alloc_index = 0;
5313 hash obj;
5314 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5316 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
5318 hash_alloc_index = 0;
5319 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
5320 * HASH_ALLOC_LIST_SIZE);
5321 if (! hash_alloc_list)
5322 perror ("unable to allocate in objc-tree.c");
5324 obj = &hash_alloc_list[hash_alloc_index++];
5325 obj->list = 0;
5326 obj->next = hashlist[slot];
5327 obj->key = method;
5329 hashlist[slot] = obj; /* append to front */
5332 static hash
5333 hash_lookup (hashlist, sel_name)
5334 hash *hashlist;
5335 tree sel_name;
5337 hash target;
5339 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
5341 while (target)
5343 if (sel_name == METHOD_SEL_NAME (target->key))
5344 return target;
5346 target = target->next;
5348 return 0;
5351 static void
5352 hash_add_attr (entry, value)
5353 hash entry;
5354 tree value;
5356 static attr attr_alloc_list = 0;
5357 static int attr_alloc_index = 0;
5358 attr obj;
5360 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
5362 attr_alloc_index = 0;
5363 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
5364 * ATTR_ALLOC_LIST_SIZE);
5365 if (! attr_alloc_list)
5366 perror ("unable to allocate in objc-tree.c");
5368 obj = &attr_alloc_list[attr_alloc_index++];
5369 obj->next = entry->list;
5370 obj->value = value;
5372 entry->list = obj; /* append to front */
5375 static tree
5376 lookup_method (mchain, method)
5377 tree mchain;
5378 tree method;
5380 tree key;
5382 if (TREE_CODE (method) == IDENTIFIER_NODE)
5383 key = method;
5384 else
5385 key = METHOD_SEL_NAME (method);
5387 while (mchain)
5389 if (METHOD_SEL_NAME (mchain) == key)
5390 return mchain;
5391 mchain = TREE_CHAIN (mchain);
5393 return NULL_TREE;
5396 static tree
5397 lookup_instance_method_static (interface, ident)
5398 tree interface;
5399 tree ident;
5401 tree inter = interface;
5402 tree chain = CLASS_NST_METHODS (inter);
5403 tree meth = NULL_TREE;
5407 if ((meth = lookup_method (chain, ident)))
5408 return meth;
5410 if (CLASS_CATEGORY_LIST (inter))
5412 tree category = CLASS_CATEGORY_LIST (inter);
5413 chain = CLASS_NST_METHODS (category);
5417 if ((meth = lookup_method (chain, ident)))
5418 return meth;
5420 /* Check for instance methods in protocols in categories. */
5421 if (CLASS_PROTOCOL_LIST (category))
5423 if ((meth = (lookup_method_in_protocol_list
5424 (CLASS_PROTOCOL_LIST (category), ident, 0))))
5425 return meth;
5428 if ((category = CLASS_CATEGORY_LIST (category)))
5429 chain = CLASS_NST_METHODS (category);
5431 while (category);
5434 if (CLASS_PROTOCOL_LIST (inter))
5436 if ((meth = (lookup_method_in_protocol_list
5437 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5438 return meth;
5441 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5442 chain = CLASS_NST_METHODS (inter);
5444 while (inter);
5446 return meth;
5449 static tree
5450 lookup_class_method_static (interface, ident)
5451 tree interface;
5452 tree ident;
5454 tree inter = interface;
5455 tree chain = CLASS_CLS_METHODS (inter);
5456 tree meth = NULL_TREE;
5457 tree root_inter = NULL_TREE;
5461 if ((meth = lookup_method (chain, ident)))
5462 return meth;
5464 if (CLASS_CATEGORY_LIST (inter))
5466 tree category = CLASS_CATEGORY_LIST (inter);
5467 chain = CLASS_CLS_METHODS (category);
5471 if ((meth = lookup_method (chain, ident)))
5472 return meth;
5474 /* Check for class methods in protocols in categories. */
5475 if (CLASS_PROTOCOL_LIST (category))
5477 if ((meth = (lookup_method_in_protocol_list
5478 (CLASS_PROTOCOL_LIST (category), ident, 1))))
5479 return meth;
5482 if ((category = CLASS_CATEGORY_LIST (category)))
5483 chain = CLASS_CLS_METHODS (category);
5485 while (category);
5488 /* Check for class methods in protocols. */
5489 if (CLASS_PROTOCOL_LIST (inter))
5491 if ((meth = (lookup_method_in_protocol_list
5492 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5493 return meth;
5496 root_inter = inter;
5497 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5498 chain = CLASS_CLS_METHODS (inter);
5500 while (inter);
5502 /* Simulate wrap around. */
5503 return lookup_instance_method_static (root_inter, ident);
5506 tree
5507 add_class_method (class, method)
5508 tree class;
5509 tree method;
5511 tree mth;
5512 hash hsh;
5514 /* We will have allocated the method parameter declarations on the
5515 maybepermanent_obstack. Need to make sure they stick around! */
5516 preserve_data ();
5518 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5520 /* put method on list in reverse order */
5521 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5522 CLASS_CLS_METHODS (class) = method;
5524 else
5526 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5527 error ("duplicate definition of class method `%s'.",
5528 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5529 else
5531 /* Check types; if different, complain. */
5532 if (!comp_proto_with_proto (method, mth))
5533 error ("duplicate declaration of class method `%s'.",
5534 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5538 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5540 /* Install on a global chain. */
5541 hash_enter (cls_method_hash_list, method);
5543 else
5545 /* Check types; if different, add to a list. */
5546 if (!comp_proto_with_proto (method, hsh->key))
5547 hash_add_attr (hsh, method);
5549 return method;
5552 tree
5553 add_instance_method (class, method)
5554 tree class;
5555 tree method;
5557 tree mth;
5558 hash hsh;
5560 /* We will have allocated the method parameter declarations on the
5561 maybepermanent_obstack. Need to make sure they stick around! */
5562 preserve_data ();
5564 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5566 /* Put method on list in reverse order. */
5567 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5568 CLASS_NST_METHODS (class) = method;
5570 else
5572 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5573 error ("duplicate definition of instance method `%s'.",
5574 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5575 else
5577 /* Check types; if different, complain. */
5578 if (!comp_proto_with_proto (method, mth))
5579 error ("duplicate declaration of instance method `%s'.",
5580 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5584 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5586 /* Install on a global chain. */
5587 hash_enter (nst_method_hash_list, method);
5589 else
5591 /* Check types; if different, add to a list. */
5592 if (!comp_proto_with_proto (method, hsh->key))
5593 hash_add_attr (hsh, method);
5595 return method;
5598 static tree
5599 add_class (class)
5600 tree class;
5602 /* Put interfaces on list in reverse order. */
5603 TREE_CHAIN (class) = interface_chain;
5604 interface_chain = class;
5605 return interface_chain;
5608 static void
5609 add_category (class, category)
5610 tree class;
5611 tree category;
5613 /* Put categories on list in reverse order. */
5614 tree cat = CLASS_CATEGORY_LIST (class);
5616 while (cat)
5618 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5619 warning ("duplicate interface declaration for category `%s(%s)'",
5620 IDENTIFIER_POINTER (CLASS_NAME (class)),
5621 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5622 cat = CLASS_CATEGORY_LIST (cat);
5625 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5626 CLASS_CATEGORY_LIST (class) = category;
5629 /* Called after parsing each instance variable declaration. Necessary to
5630 preserve typedefs and implement public/private...
5632 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
5634 tree
5635 add_instance_variable (class, public, declarator, declspecs, width)
5636 tree class;
5637 int public;
5638 tree declarator;
5639 tree declspecs;
5640 tree width;
5642 tree field_decl, raw_decl;
5644 raw_decl = build_tree_list (declspecs, declarator);
5646 if (CLASS_RAW_IVARS (class))
5647 chainon (CLASS_RAW_IVARS (class), raw_decl);
5648 else
5649 CLASS_RAW_IVARS (class) = raw_decl;
5651 field_decl = grokfield (input_filename, lineno,
5652 declarator, declspecs, width);
5654 /* Overload the public attribute, it is not used for FIELD_DECLs. */
5655 switch (public)
5657 case 0:
5658 TREE_PUBLIC (field_decl) = 0;
5659 TREE_PRIVATE (field_decl) = 0;
5660 TREE_PROTECTED (field_decl) = 1;
5661 break;
5663 case 1:
5664 TREE_PUBLIC (field_decl) = 1;
5665 TREE_PRIVATE (field_decl) = 0;
5666 TREE_PROTECTED (field_decl) = 0;
5667 break;
5669 case 2:
5670 TREE_PUBLIC (field_decl) = 0;
5671 TREE_PRIVATE (field_decl) = 1;
5672 TREE_PROTECTED (field_decl) = 0;
5673 break;
5677 if (CLASS_IVARS (class))
5678 chainon (CLASS_IVARS (class), field_decl);
5679 else
5680 CLASS_IVARS (class) = field_decl;
5682 return class;
5685 tree
5686 is_ivar (decl_chain, ident)
5687 tree decl_chain;
5688 tree ident;
5690 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5691 if (DECL_NAME (decl_chain) == ident)
5692 return decl_chain;
5693 return NULL_TREE;
5696 /* True if the ivar is private and we are not in its implementation. */
5699 is_private (decl)
5700 tree decl;
5702 if (TREE_PRIVATE (decl)
5703 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5705 error ("instance variable `%s' is declared private",
5706 IDENTIFIER_POINTER (DECL_NAME (decl)));
5707 return 1;
5709 else
5710 return 0;
5713 /* We have an instance variable reference;, check to see if it is public. */
5716 is_public (expr, identifier)
5717 tree expr;
5718 tree identifier;
5720 tree basetype = TREE_TYPE (expr);
5721 enum tree_code code = TREE_CODE (basetype);
5722 tree decl;
5724 if (code == RECORD_TYPE)
5726 if (TREE_STATIC_TEMPLATE (basetype))
5728 if (!lookup_interface (TYPE_NAME (basetype)))
5730 error ("Cannot find interface declaration for `%s'",
5731 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5732 return 0;
5735 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5737 if (TREE_PUBLIC (decl))
5738 return 1;
5740 /* Important difference between the Stepstone translator:
5741 all instance variables should be public within the context
5742 of the implementation. */
5743 if (implementation_context
5744 && (((TREE_CODE (implementation_context)
5745 == CLASS_IMPLEMENTATION_TYPE)
5746 || (TREE_CODE (implementation_context)
5747 == CATEGORY_IMPLEMENTATION_TYPE))
5748 && (CLASS_NAME (implementation_context)
5749 == TYPE_NAME (basetype))))
5750 return ! is_private (decl);
5752 error ("instance variable `%s' is declared %s",
5753 IDENTIFIER_POINTER (identifier),
5754 TREE_PRIVATE (decl) ? "private" : "protected");
5755 return 0;
5759 else if (implementation_context && (basetype == objc_object_reference))
5761 TREE_TYPE (expr) = uprivate_record;
5762 warning ("static access to object of type `id'");
5766 return 1;
5769 /* Implement @defs (<classname>) within struct bodies. */
5771 tree
5772 get_class_ivars (interface)
5773 tree interface;
5775 if (!doing_objc_thang)
5776 objc_fatal ();
5778 return build_ivar_chain (interface, 1);
5781 /* Make sure all entries in CHAIN are also in LIST. */
5783 static int
5784 check_methods (chain, list, mtype)
5785 tree chain;
5786 tree list;
5787 int mtype;
5789 int first = 1;
5791 while (chain)
5793 if (!lookup_method (list, chain))
5795 if (first)
5797 if (TREE_CODE (implementation_context)
5798 == CLASS_IMPLEMENTATION_TYPE)
5799 warning ("incomplete implementation of class `%s'",
5800 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
5801 else if (TREE_CODE (implementation_context)
5802 == CATEGORY_IMPLEMENTATION_TYPE)
5803 warning ("incomplete implementation of category `%s'",
5804 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
5805 first = 0;
5808 warning ("method definition for `%c%s' not found",
5809 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5812 chain = TREE_CHAIN (chain);
5815 return first;
5818 static int
5819 conforms_to_protocol (class, protocol)
5820 tree class;
5821 tree protocol;
5823 while (protocol)
5825 tree p = CLASS_PROTOCOL_LIST (class);
5827 while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
5828 p = TREE_CHAIN (p);
5830 if (!p)
5832 tree super = (CLASS_SUPER_NAME (class)
5833 ? lookup_interface (CLASS_SUPER_NAME (class))
5834 : NULL_TREE);
5835 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5836 if (!tmp)
5837 return 0;
5840 protocol = TREE_CHAIN (protocol);
5843 return 1;
5846 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
5847 CONTEXT. This is one of two mechanisms to check protocol integrity. */
5849 static int
5850 check_methods_accessible (chain, context, mtype)
5851 tree chain;
5852 tree context;
5853 int mtype;
5855 int first = 1;
5856 tree list;
5857 tree base_context = context;
5859 while (chain)
5861 context = base_context;
5862 while (context)
5864 if (mtype == '+')
5865 list = CLASS_CLS_METHODS (context);
5866 else
5867 list = CLASS_NST_METHODS (context);
5869 if (lookup_method (list, chain))
5870 break;
5872 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
5873 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
5874 context = (CLASS_SUPER_NAME (context)
5875 ? lookup_interface (CLASS_SUPER_NAME (context))
5876 : NULL_TREE);
5878 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
5879 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
5880 context = (CLASS_NAME (context)
5881 ? lookup_interface (CLASS_NAME (context))
5882 : NULL_TREE);
5883 else
5884 abort ();
5887 if (context == NULL_TREE)
5889 if (first)
5891 if (TREE_CODE (implementation_context)
5892 == CLASS_IMPLEMENTATION_TYPE)
5893 warning ("incomplete implementation of class `%s'",
5894 IDENTIFIER_POINTER
5895 (CLASS_NAME (implementation_context)));
5896 else if (TREE_CODE (implementation_context)
5897 == CATEGORY_IMPLEMENTATION_TYPE)
5898 warning ("incomplete implementation of category `%s'",
5899 IDENTIFIER_POINTER
5900 (CLASS_SUPER_NAME (implementation_context)));
5901 first = 0;
5903 warning ("method definition for `%c%s' not found",
5904 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5907 chain = TREE_CHAIN (chain); /* next method... */
5909 return first;
5912 static void
5913 check_protocols (proto_list, type, name)
5914 tree proto_list;
5915 char *type;
5916 char *name;
5918 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
5920 tree p = TREE_VALUE (proto_list);
5922 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
5924 int f1, f2;
5926 /* Ensure that all protocols have bodies. */
5927 if (flag_warn_protocol) {
5928 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
5929 CLASS_CLS_METHODS (implementation_context),
5930 '+');
5931 f2 = check_methods (PROTOCOL_NST_METHODS (p),
5932 CLASS_NST_METHODS (implementation_context),
5933 '-');
5934 } else {
5935 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
5936 implementation_context,
5937 '+');
5938 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
5939 implementation_context,
5940 '-');
5943 if (!f1 || !f2)
5944 warning ("%s `%s' does not fully implement the `%s' protocol",
5945 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
5948 else
5949 ; /* An identifier if we could not find a protocol. */
5951 /* Check protocols recursively. */
5952 if (PROTOCOL_LIST (p))
5954 tree super_class
5955 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
5956 if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
5957 check_protocols (PROTOCOL_LIST (p), type, name);
5962 /* Make sure that the class CLASS_NAME is defined
5963 CODE says which kind of thing CLASS_NAME ought to be.
5964 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
5965 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.
5967 If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange
5968 whose matching pop is in continue_class. */
5970 tree
5971 start_class (code, class_name, super_name, protocol_list)
5972 enum tree_code code;
5973 tree class_name;
5974 tree super_name;
5975 tree protocol_list;
5977 tree class, decl;
5979 if (code == CLASS_INTERFACE_TYPE)
5981 push_obstacks_nochange ();
5982 end_temporary_allocation ();
5985 if (!doing_objc_thang)
5986 objc_fatal ();
5988 class = make_node (code);
5989 TYPE_BINFO (class) = make_tree_vec (5);
5991 CLASS_NAME (class) = class_name;
5992 CLASS_SUPER_NAME (class) = super_name;
5993 CLASS_CLS_METHODS (class) = NULL_TREE;
5995 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
5997 error ("`%s' redeclared as different kind of symbol",
5998 IDENTIFIER_POINTER (class_name));
5999 error_with_decl (decl, "previous declaration of `%s'");
6002 if (code == CLASS_IMPLEMENTATION_TYPE)
6005 static tree implemented_classes = 0;
6006 tree chain = implemented_classes;
6007 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6008 if (TREE_VALUE (chain) == class_name)
6010 error ("reimplementation of class `%s'",
6011 IDENTIFIER_POINTER (class_name));
6012 return error_mark_node;
6014 implemented_classes = perm_tree_cons (NULL_TREE, class_name,
6015 implemented_classes);
6018 /* Pre-build the following entities - for speed/convenience. */
6019 if (!self_id)
6020 self_id = get_identifier ("self");
6021 if (!ucmd_id)
6022 ucmd_id = get_identifier ("_cmd");
6023 if (!unused_list)
6024 unused_list
6025 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6026 if (!objc_super_template)
6027 objc_super_template = build_super_template ();
6029 /* Reset for multiple classes per file. */
6030 method_slot = 0;
6032 implementation_context = class;
6034 /* Lookup the interface for this implementation. */
6036 if (!(implementation_template = lookup_interface (class_name)))
6038 warning ("Cannot find interface declaration for `%s'",
6039 IDENTIFIER_POINTER (class_name));
6040 add_class (implementation_template = implementation_context);
6043 /* If a super class has been specified in the implementation,
6044 insure it conforms to the one specified in the interface. */
6046 if (super_name
6047 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6049 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6050 char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6051 error ("conflicting super class name `%s'",
6052 IDENTIFIER_POINTER (super_name));
6053 error ("previous declaration of `%s'", name);
6056 else if (! super_name)
6058 CLASS_SUPER_NAME (implementation_context)
6059 = CLASS_SUPER_NAME (implementation_template);
6063 else if (code == CLASS_INTERFACE_TYPE)
6065 if (lookup_interface (class_name))
6066 warning ("duplicate interface declaration for class `%s'",
6067 IDENTIFIER_POINTER (class_name));
6068 else
6069 add_class (class);
6071 if (protocol_list)
6072 CLASS_PROTOCOL_LIST (class)
6073 = lookup_and_install_protocols (protocol_list);
6076 else if (code == CATEGORY_INTERFACE_TYPE)
6078 tree class_category_is_assoc_with;
6080 /* For a category, class_name is really the name of the class that
6081 the following set of methods will be associated with. We must
6082 find the interface so that can derive the objects template. */
6084 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6086 error ("Cannot find interface declaration for `%s'",
6087 IDENTIFIER_POINTER (class_name));
6088 exit (FATAL_EXIT_CODE);
6090 else
6091 add_category (class_category_is_assoc_with, class);
6093 if (protocol_list)
6094 CLASS_PROTOCOL_LIST (class)
6095 = lookup_and_install_protocols (protocol_list);
6098 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6100 /* Pre-build the following entities for speed/convenience. */
6101 if (!self_id)
6102 self_id = get_identifier ("self");
6103 if (!ucmd_id)
6104 ucmd_id = get_identifier ("_cmd");
6105 if (!unused_list)
6106 unused_list
6107 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6108 if (!objc_super_template)
6109 objc_super_template = build_super_template ();
6111 /* Reset for multiple classes per file. */
6112 method_slot = 0;
6114 implementation_context = class;
6116 /* For a category, class_name is really the name of the class that
6117 the following set of methods will be associated with. We must
6118 find the interface so that can derive the objects template. */
6120 if (!(implementation_template = lookup_interface (class_name)))
6122 error ("Cannot find interface declaration for `%s'",
6123 IDENTIFIER_POINTER (class_name));
6124 exit (FATAL_EXIT_CODE);
6127 return class;
6130 tree
6131 continue_class (class)
6132 tree class;
6134 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6135 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6137 struct imp_entry *imp_entry;
6138 tree ivar_context;
6140 /* Check consistency of the instance variables. */
6142 if (CLASS_IVARS (class))
6143 check_ivars (implementation_template, class);
6145 /* code generation */
6147 ivar_context = build_private_template (implementation_template);
6149 if (!objc_class_template)
6150 build_class_template ();
6152 if (!(imp_entry
6153 = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
6154 perror ("unable to allocate in objc-tree.c");
6156 imp_entry->next = imp_list;
6157 imp_entry->imp_context = class;
6158 imp_entry->imp_template = implementation_template;
6160 synth_forward_declarations ();
6161 imp_entry->class_decl = UOBJC_CLASS_decl;
6162 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6164 /* Append to front and increment count. */
6165 imp_list = imp_entry;
6166 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6167 imp_count++;
6168 else
6169 cat_count++;
6171 return ivar_context;
6174 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6176 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6178 if (!TYPE_FIELDS (record))
6180 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
6181 CLASS_STATIC_TEMPLATE (class) = record;
6183 /* Mark this record as a class template for static typing. */
6184 TREE_STATIC_TEMPLATE (record) = 1;
6187 return NULL_TREE;
6190 else
6191 return error_mark_node;
6194 /* This is called once we see the "@end" in an interface/implementation. */
6196 void
6197 finish_class (class)
6198 tree class;
6200 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6202 /* All code generation is done in finish_objc. */
6204 if (implementation_template != implementation_context)
6206 /* Ensure that all method listed in the interface contain bodies. */
6207 check_methods (CLASS_CLS_METHODS (implementation_template),
6208 CLASS_CLS_METHODS (implementation_context), '+');
6209 check_methods (CLASS_NST_METHODS (implementation_template),
6210 CLASS_NST_METHODS (implementation_context), '-');
6212 if (CLASS_PROTOCOL_LIST (implementation_template))
6213 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6214 "class",
6215 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
6219 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6221 tree category = CLASS_CATEGORY_LIST (implementation_template);
6223 /* Find the category interface from the class it is associated with. */
6224 while (category)
6226 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6227 break;
6228 category = CLASS_CATEGORY_LIST (category);
6231 if (category)
6233 /* Ensure all method listed in the interface contain bodies. */
6234 check_methods (CLASS_CLS_METHODS (category),
6235 CLASS_CLS_METHODS (implementation_context), '+');
6236 check_methods (CLASS_NST_METHODS (category),
6237 CLASS_NST_METHODS (implementation_context), '-');
6239 if (CLASS_PROTOCOL_LIST (category))
6240 check_protocols (CLASS_PROTOCOL_LIST (category),
6241 "category",
6242 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
6246 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6248 tree decl_specs;
6249 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6250 char *string = (char *) alloca (strlen (class_name) + 3);
6252 /* extern struct objc_object *_<my_name>; */
6254 sprintf (string, "_%s", class_name);
6256 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6257 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6258 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6259 decl_specs);
6263 static tree
6264 add_protocol (protocol)
6265 tree protocol;
6267 /* Put protocol on list in reverse order. */
6268 TREE_CHAIN (protocol) = protocol_chain;
6269 protocol_chain = protocol;
6270 return protocol_chain;
6273 static tree
6274 lookup_protocol (ident)
6275 tree ident;
6277 tree chain;
6279 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6281 if (ident == PROTOCOL_NAME (chain))
6282 return chain;
6285 return NULL_TREE;
6288 tree
6289 start_protocol (code, name, list)
6290 enum tree_code code;
6291 tree name;
6292 tree list;
6294 tree protocol;
6296 if (!doing_objc_thang)
6297 objc_fatal ();
6299 /* This is as good a place as any. Need to invoke push_tag_toplevel. */
6300 if (!objc_protocol_template)
6301 objc_protocol_template = build_protocol_template ();
6303 protocol = make_node (code);
6304 TYPE_BINFO (protocol) = make_tree_vec (2);
6306 PROTOCOL_NAME (protocol) = name;
6307 PROTOCOL_LIST (protocol) = list;
6309 lookup_and_install_protocols (list);
6311 if (lookup_protocol (name))
6312 warning ("duplicate declaration for protocol `%s'",
6313 IDENTIFIER_POINTER (name));
6314 else
6315 add_protocol (protocol);
6317 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6319 return protocol;
6322 void
6323 finish_protocol (protocol)
6324 tree protocol;
6329 /* "Encode" a data type into a string, which grows in util_obstack.
6330 ??? What is the FORMAT? Someone please document this! */
6332 static void
6333 encode_type_qualifiers (declspecs)
6334 tree declspecs;
6336 tree spec;
6338 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6340 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6341 obstack_1grow (&util_obstack, 'r');
6342 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6343 obstack_1grow (&util_obstack, 'n');
6344 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6345 obstack_1grow (&util_obstack, 'N');
6346 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6347 obstack_1grow (&util_obstack, 'o');
6348 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6349 obstack_1grow (&util_obstack, 'O');
6350 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6351 obstack_1grow (&util_obstack, 'V');
6355 /* Encode a pointer type. */
6357 static void
6358 encode_pointer (type, curtype, format)
6359 tree type;
6360 int curtype;
6361 int format;
6363 tree pointer_to = TREE_TYPE (type);
6365 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6367 if (TYPE_NAME (pointer_to)
6368 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6370 char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6372 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6374 obstack_1grow (&util_obstack, '@');
6375 return;
6377 else if (TREE_STATIC_TEMPLATE (pointer_to))
6379 if (generating_instance_variables)
6381 obstack_1grow (&util_obstack, '@');
6382 obstack_1grow (&util_obstack, '"');
6383 obstack_grow (&util_obstack, name, strlen (name));
6384 obstack_1grow (&util_obstack, '"');
6385 return;
6387 else
6389 obstack_1grow (&util_obstack, '@');
6390 return;
6393 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6395 obstack_1grow (&util_obstack, '#');
6396 return;
6398 #ifndef OBJC_INT_SELECTORS
6399 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6401 obstack_1grow (&util_obstack, ':');
6402 return;
6404 #endif /* OBJC_INT_SELECTORS */
6407 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6408 && TYPE_MODE (pointer_to) == QImode)
6410 obstack_1grow (&util_obstack, '*');
6411 return;
6414 /* We have a type that does not get special treatment. */
6416 /* NeXT extension */
6417 obstack_1grow (&util_obstack, '^');
6418 encode_type (pointer_to, curtype, format);
6421 static void
6422 encode_array (type, curtype, format)
6423 tree type;
6424 int curtype;
6425 int format;
6427 tree an_int_cst = TYPE_SIZE (type);
6428 tree array_of = TREE_TYPE (type);
6429 char buffer[40];
6431 /* An incomplete array is treated like a pointer. */
6432 if (an_int_cst == NULL)
6434 encode_pointer (type, curtype, format);
6435 return;
6438 sprintf (buffer, "[%d",
6439 (TREE_INT_CST_LOW (an_int_cst)
6440 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6442 obstack_grow (&util_obstack, buffer, strlen (buffer));
6443 encode_type (array_of, curtype, format);
6444 obstack_1grow (&util_obstack, ']');
6445 return;
6448 static void
6449 encode_aggregate_within (type, curtype, format, left, right)
6450 tree type;
6451 int curtype;
6452 int format;
6453 char left;
6454 char right;
6456 if (obstack_object_size (&util_obstack) > 0
6457 && *(obstack_next_free (&util_obstack) - 1) == '^')
6459 tree name = TYPE_NAME (type);
6461 /* we have a reference; this is a NeXT extension. */
6463 if (obstack_object_size (&util_obstack) - curtype == 1
6464 && format == OBJC_ENCODE_INLINE_DEFS)
6466 /* Output format of struct for first level only. */
6467 tree fields = TYPE_FIELDS (type);
6469 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6471 obstack_1grow (&util_obstack, left);
6472 obstack_grow (&util_obstack,
6473 IDENTIFIER_POINTER (name),
6474 strlen (IDENTIFIER_POINTER (name)));
6475 obstack_1grow (&util_obstack, '=');
6477 else
6479 obstack_1grow (&util_obstack, left);
6480 obstack_grow (&util_obstack, "?=", 2);
6483 for ( ; fields; fields = TREE_CHAIN (fields))
6484 encode_field_decl (fields, curtype, format);
6486 obstack_1grow (&util_obstack, right);
6489 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6491 obstack_1grow (&util_obstack, left);
6492 obstack_grow (&util_obstack,
6493 IDENTIFIER_POINTER (name),
6494 strlen (IDENTIFIER_POINTER (name)));
6495 obstack_1grow (&util_obstack, right);
6498 else
6500 /* We have an untagged structure or a typedef. */
6501 obstack_1grow (&util_obstack, left);
6502 obstack_1grow (&util_obstack, '?');
6503 obstack_1grow (&util_obstack, right);
6507 else
6509 tree name = TYPE_NAME (type);
6510 tree fields = TYPE_FIELDS (type);
6512 if (format == OBJC_ENCODE_INLINE_DEFS
6513 || generating_instance_variables)
6515 obstack_1grow (&util_obstack, left);
6516 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6517 obstack_grow (&util_obstack,
6518 IDENTIFIER_POINTER (name),
6519 strlen (IDENTIFIER_POINTER (name)));
6520 else
6521 obstack_1grow (&util_obstack, '?');
6523 obstack_1grow (&util_obstack, '=');
6525 for (; fields; fields = TREE_CHAIN (fields))
6527 if (generating_instance_variables)
6529 tree fname = DECL_NAME (fields);
6531 obstack_1grow (&util_obstack, '"');
6532 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6534 obstack_grow (&util_obstack,
6535 IDENTIFIER_POINTER (fname),
6536 strlen (IDENTIFIER_POINTER (fname)));
6539 obstack_1grow (&util_obstack, '"');
6542 encode_field_decl (fields, curtype, format);
6545 obstack_1grow (&util_obstack, right);
6548 else
6550 obstack_1grow (&util_obstack, left);
6551 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6552 obstack_grow (&util_obstack,
6553 IDENTIFIER_POINTER (name),
6554 strlen (IDENTIFIER_POINTER (name)));
6555 else
6556 /* We have an untagged structure or a typedef. */
6557 obstack_1grow (&util_obstack, '?');
6559 obstack_1grow (&util_obstack, right);
6564 static void
6565 encode_aggregate (type, curtype, format)
6566 tree type;
6567 int curtype;
6568 int format;
6570 enum tree_code code = TREE_CODE (type);
6572 switch (code)
6574 case RECORD_TYPE:
6576 encode_aggregate_within(type, curtype, format, '{', '}');
6577 break;
6579 case UNION_TYPE:
6581 encode_aggregate_within(type, curtype, format, '(', ')');
6582 break;
6585 case ENUMERAL_TYPE:
6586 obstack_1grow (&util_obstack, 'i');
6587 break;
6591 /* Support bitfields. The current version of Objective-C does not support
6592 them. The string will consist of one or more "b:n"'s where n is an
6593 integer describing the width of the bitfield. Currently, classes in
6594 the kit implement a method "-(char *)describeBitfieldStruct:" that
6595 simulates this. If they do not implement this method, the archiver
6596 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6597 according to the GNU compiler. After looking at the "kit", it appears
6598 that all classes currently rely on this default behavior, rather than
6599 hand generating this string (which is tedious). */
6601 static void
6602 encode_bitfield (width, format)
6603 int width;
6604 int format;
6606 char buffer[40];
6607 sprintf (buffer, "b%d", width);
6608 obstack_grow (&util_obstack, buffer, strlen (buffer));
6611 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6613 static void
6614 encode_type (type, curtype, format)
6615 tree type;
6616 int curtype;
6617 int format;
6619 enum tree_code code = TREE_CODE (type);
6621 if (code == INTEGER_TYPE)
6623 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
6624 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
6626 /* Unsigned integer types. */
6628 if (TYPE_MODE (type) == QImode)
6629 obstack_1grow (&util_obstack, 'C');
6630 else if (TYPE_MODE (type) == HImode)
6631 obstack_1grow (&util_obstack, 'S');
6632 else if (TYPE_MODE (type) == SImode)
6634 if (type == long_unsigned_type_node)
6635 obstack_1grow (&util_obstack, 'L');
6636 else
6637 obstack_1grow (&util_obstack, 'I');
6639 else if (TYPE_MODE (type) == DImode)
6640 obstack_1grow (&util_obstack, 'Q');
6643 else
6644 /* Signed integer types. */
6646 if (TYPE_MODE (type) == QImode)
6647 obstack_1grow (&util_obstack, 'c');
6648 else if (TYPE_MODE (type) == HImode)
6649 obstack_1grow (&util_obstack, 's');
6650 else if (TYPE_MODE (type) == SImode)
6652 if (type == long_integer_type_node)
6653 obstack_1grow (&util_obstack, 'l');
6654 else
6655 obstack_1grow (&util_obstack, 'i');
6658 else if (TYPE_MODE (type) == DImode)
6659 obstack_1grow (&util_obstack, 'q');
6663 else if (code == REAL_TYPE)
6665 /* Floating point types. */
6667 if (TYPE_MODE (type) == SFmode)
6668 obstack_1grow (&util_obstack, 'f');
6669 else if (TYPE_MODE (type) == DFmode
6670 || TYPE_MODE (type) == TFmode)
6671 obstack_1grow (&util_obstack, 'd');
6674 else if (code == VOID_TYPE)
6675 obstack_1grow (&util_obstack, 'v');
6677 else if (code == ARRAY_TYPE)
6678 encode_array (type, curtype, format);
6680 else if (code == POINTER_TYPE)
6681 encode_pointer (type, curtype, format);
6683 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6684 encode_aggregate (type, curtype, format);
6686 else if (code == FUNCTION_TYPE) /* '?' */
6687 obstack_1grow (&util_obstack, '?');
6690 static void
6691 encode_field_decl (field_decl, curtype, format)
6692 tree field_decl;
6693 int curtype;
6694 int format;
6696 tree type;
6698 /* If this field is obviously a bitfield, or is a bitfield that has been
6699 clobbered to look like a ordinary integer mode, go ahead and generate
6700 the bitfield typing information. */
6701 type = TREE_TYPE (field_decl);
6702 if (DECL_BIT_FIELD (field_decl))
6703 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6704 else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
6705 && DECL_FIELD_SIZE (field_decl)
6706 && TYPE_MODE (type) > DECL_MODE (field_decl))
6707 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6708 else
6709 encode_type (TREE_TYPE (field_decl), curtype, format);
6712 static tree
6713 expr_last (complex_expr)
6714 tree complex_expr;
6716 tree next;
6718 if (complex_expr)
6719 while ((next = TREE_OPERAND (complex_expr, 0)))
6720 complex_expr = next;
6722 return complex_expr;
6725 /* The selector of the current method,
6726 or NULL if we aren't compiling a method. */
6728 tree
6729 maybe_objc_method_name (decl)
6730 tree decl;
6732 if (method_context)
6733 return METHOD_SEL_NAME (method_context);
6734 else
6735 return 0;
6738 /* Transform a method definition into a function definition as follows:
6739 - synthesize the first two arguments, "self" and "_cmd". */
6741 void
6742 start_method_def (method)
6743 tree method;
6745 tree decl_specs;
6747 /* Required to implement _msgSuper. */
6748 method_context = method;
6749 UOBJC_SUPER_decl = NULL_TREE;
6751 /* Must be called BEFORE start_function. */
6752 pushlevel (0);
6754 /* Generate prototype declarations for arguments..."new-style". */
6756 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
6757 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
6758 else
6759 /* Really a `struct objc_class *'. However, we allow people to
6760 assign to self, which changes its type midstream. */
6761 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
6763 push_parm_decl (build_tree_list
6764 (build_tree_list (decl_specs,
6765 build1 (INDIRECT_REF, NULL_TREE, self_id)),
6766 build_tree_list (unused_list, NULL_TREE)));
6768 #ifdef OBJC_INT_SELECTORS
6769 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]);
6770 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
6771 push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id),
6772 build_tree_list (unused_list, NULL_TREE)));
6773 #else /* not OBJC_INT_SELECTORS */
6774 decl_specs = build_tree_list (NULL_TREE,
6775 xref_tag (RECORD_TYPE,
6776 get_identifier (TAG_SELECTOR)));
6777 push_parm_decl (build_tree_list
6778 (build_tree_list (decl_specs,
6779 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
6780 build_tree_list (unused_list, NULL_TREE)));
6781 #endif /* not OBJC_INT_SELECTORS */
6783 /* Generate argument declarations if a keyword_decl. */
6784 if (METHOD_SEL_ARGS (method))
6786 tree arglist = METHOD_SEL_ARGS (method);
6789 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
6790 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
6792 if (arg_decl)
6794 tree last_expr = expr_last (arg_decl);
6796 /* Unite the abstract decl with its name. */
6797 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
6798 push_parm_decl (build_tree_list
6799 (build_tree_list (arg_spec, arg_decl),
6800 build_tree_list (NULL_TREE, NULL_TREE)));
6802 /* Unhook: restore the abstract declarator. */
6803 TREE_OPERAND (last_expr, 0) = NULL_TREE;
6806 else
6807 push_parm_decl (build_tree_list
6808 (build_tree_list (arg_spec,
6809 KEYWORD_ARG_NAME (arglist)),
6810 build_tree_list (NULL_TREE, NULL_TREE)));
6812 arglist = TREE_CHAIN (arglist);
6814 while (arglist);
6817 if (METHOD_ADD_ARGS (method) > (tree)1)
6819 /* We have a variable length selector - in "prototype" format. */
6820 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
6821 while (akey)
6823 /* This must be done prior to calling pushdecl. pushdecl is
6824 going to change our chain on us. */
6825 tree nextkey = TREE_CHAIN (akey);
6826 pushdecl (akey);
6827 akey = nextkey;
6832 static void
6833 warn_with_method (message, mtype, method)
6834 char *message;
6835 int mtype;
6836 tree method;
6838 if (count_error (1) == 0)
6839 return;
6841 report_error_function (DECL_SOURCE_FILE (method));
6843 fprintf (stderr, "%s:%d: warning: ",
6844 DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
6845 bzero (errbuf, BUFSIZE);
6846 fprintf (stderr, "%s `%c%s'\n",
6847 message, mtype, gen_method_decl (method, errbuf));
6850 /* Return 1 if METHOD is consistent with PROTO. */
6852 static int
6853 comp_method_with_proto (method, proto)
6854 tree method, proto;
6856 static tree function_type = 0;
6858 /* Create a function_type node once. */
6859 if (!function_type)
6861 push_obstacks_nochange ();
6862 end_temporary_allocation ();
6863 function_type = make_node (FUNCTION_TYPE);
6864 pop_obstacks ();
6867 /* Install argument types - normally set by build_function_type. */
6868 TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
6870 /* install return type */
6871 TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
6873 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
6876 /* Return 1 if PROTO1 is consistent with PROTO2. */
6878 static int
6879 comp_proto_with_proto (proto1, proto2)
6880 tree proto1, proto2;
6882 static tree function_type1 = 0, function_type2 = 0;
6884 /* Create a couple function_type node's once. */
6885 if (!function_type1)
6887 push_obstacks_nochange ();
6888 end_temporary_allocation ();
6889 function_type1 = make_node (FUNCTION_TYPE);
6890 function_type2 = make_node (FUNCTION_TYPE);
6891 pop_obstacks ();
6894 /* Install argument types; normally set by build_function_type. */
6895 TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
6896 TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
6898 /* Install return type. */
6899 TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
6900 TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
6902 return comptypes (function_type1, function_type2);
6905 /* - Generate an identifier for the function. the format is "_n_cls",
6906 where 1 <= n <= nMethods, and cls is the name the implementation we
6907 are processing.
6908 - Install the return type from the method declaration.
6909 - If we have a prototype, check for type consistency. */
6911 static void
6912 really_start_method (method, parmlist)
6913 tree method, parmlist;
6915 tree sc_spec, ret_spec, ret_decl, decl_specs;
6916 tree method_decl, method_id;
6917 char *buf, *sel_name, *class_name, *cat_name;
6919 /* Synth the storage class & assemble the return type. */
6920 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
6921 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
6922 decl_specs = chainon (sc_spec, ret_spec);
6924 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
6925 class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
6926 cat_name = ((TREE_CODE (implementation_context)
6927 == CLASS_IMPLEMENTATION_TYPE)
6928 ? NULL
6929 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
6930 method_slot++;
6932 /* Make sure this is big enough for any plausible method label. */
6933 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
6934 + (cat_name ? strlen (cat_name) : 0));
6936 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
6937 class_name, cat_name, sel_name, method_slot);
6939 method_id = get_identifier (buf);
6941 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
6943 /* Check the declarator portion of the return type for the method. */
6944 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
6946 /* Unite the complex decl (specified in the abstract decl) with the
6947 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
6948 tree save_expr = expr_last (ret_decl);
6950 TREE_OPERAND (save_expr, 0) = method_decl;
6951 method_decl = ret_decl;
6953 /* Fool the parser into thinking it is starting a function. */
6954 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
6956 /* Unhook: this has the effect of restoring the abstract declarator. */
6957 TREE_OPERAND (save_expr, 0) = NULL_TREE;
6960 else
6962 TREE_VALUE (TREE_TYPE (method)) = method_decl;
6964 /* Fool the parser into thinking it is starting a function. */
6965 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
6967 /* Unhook: this has the effect of restoring the abstract declarator. */
6968 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
6971 METHOD_DEFINITION (method) = current_function_decl;
6973 if (implementation_template != implementation_context)
6975 tree proto;
6977 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
6978 proto = lookup_instance_method_static (implementation_template,
6979 METHOD_SEL_NAME (method));
6980 else
6981 proto = lookup_class_method_static (implementation_template,
6982 METHOD_SEL_NAME (method));
6984 if (proto && ! comp_method_with_proto (method, proto))
6986 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
6988 warn_with_method ("conflicting types for", type, method);
6989 warn_with_method ("previous declaration of", type, proto);
6994 /* The following routine is always called...this "architecture" is to
6995 accommodate "old-style" variable length selectors.
6997 - a:a b:b // prototype ; id c; id d; // old-style. */
6999 void
7000 continue_method_def ()
7002 tree parmlist;
7004 if (METHOD_ADD_ARGS (method_context) == (tree)1)
7005 /* We have a `, ...' immediately following the selector. */
7006 parmlist = get_parm_info (0);
7007 else
7008 parmlist = get_parm_info (1); /* place a `void_at_end' */
7010 /* Set self_decl from the first argument...this global is used by
7011 build_ivar_reference calling build_indirect_ref. */
7012 self_decl = TREE_PURPOSE (parmlist);
7014 poplevel (0, 0, 0);
7015 really_start_method (method_context, parmlist);
7016 store_parm_decls ();
7019 /* Called by the parser, from the `pushlevel' production. */
7021 void
7022 add_objc_decls ()
7024 if (!UOBJC_SUPER_decl)
7026 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7027 build_tree_list (NULL_TREE,
7028 objc_super_template),
7029 0, NULL_TREE, NULL_TREE);
7031 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7033 /* This prevents `unused variable' warnings when compiling with -Wall. */
7034 TREE_USED (UOBJC_SUPER_decl) = 1;
7035 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7039 /* _n_Method (id self, SEL sel, ...)
7041 struct objc_super _S;
7042 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7043 } */
7045 tree
7046 get_super_receiver ()
7048 if (method_context)
7050 tree super_expr, super_expr_list;
7052 /* Set receiver to self. */
7053 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7054 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7055 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7057 /* Set class to begin searching. */
7058 super_expr = build_component_ref (UOBJC_SUPER_decl,
7059 get_identifier ("class"));
7061 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7063 /* [_cls, __cls]Super are "pre-built" in
7064 synth_forward_declarations. */
7066 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7067 ((TREE_CODE (method_context)
7068 == INSTANCE_METHOD_DECL)
7069 ? ucls_super_ref
7070 : uucls_super_ref));
7073 else
7074 /* We have a category. */
7076 tree super_name = CLASS_SUPER_NAME (implementation_template);
7077 tree super_class;
7079 if (!super_name)
7081 error ("no super class declared in interface for `%s'",
7082 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7083 return error_mark_node;
7086 if (flag_next_runtime)
7088 super_class = get_class_reference (super_name);
7089 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
7090 super_class
7091 = build_component_ref (build_indirect_ref (super_class, "->"),
7092 get_identifier ("isa"));
7094 else
7096 add_class_reference (super_name);
7097 super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
7098 ? objc_get_class_decl : objc_get_meta_class_decl);
7099 assemble_external (super_class);
7100 super_class
7101 = build_function_call
7102 (super_class,
7103 build_tree_list
7104 (NULL_TREE,
7105 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7106 IDENTIFIER_POINTER (super_name))));
7109 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7110 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7113 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7115 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7116 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7118 return build_compound_expr (super_expr_list);
7120 else
7122 error ("[super ...] must appear in a method context");
7123 return error_mark_node;
7127 static tree
7128 encode_method_def (func_decl)
7129 tree func_decl;
7131 tree parms;
7132 int stack_size;
7133 int max_parm_end = 0;
7134 char buffer[40];
7135 tree result;
7137 /* Return type. */
7138 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7139 obstack_object_size (&util_obstack),
7140 OBJC_ENCODE_INLINE_DEFS);
7142 /* Stack size. */
7143 for (parms = DECL_ARGUMENTS (func_decl); parms;
7144 parms = TREE_CHAIN (parms))
7146 int parm_end = (forwarding_offset (parms)
7147 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
7148 / BITS_PER_UNIT));
7150 if (!offset_is_register && parm_end > max_parm_end)
7151 max_parm_end = parm_end;
7154 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7156 sprintf (buffer, "%d", stack_size);
7157 obstack_grow (&util_obstack, buffer, strlen (buffer));
7159 /* Argument types. */
7160 for (parms = DECL_ARGUMENTS (func_decl); parms;
7161 parms = TREE_CHAIN (parms))
7163 /* Type. */
7164 encode_type (TREE_TYPE (parms),
7165 obstack_object_size (&util_obstack),
7166 OBJC_ENCODE_INLINE_DEFS);
7168 /* Compute offset. */
7169 sprintf (buffer, "%d", forwarding_offset (parms));
7171 /* Indicate register. */
7172 if (offset_is_register)
7173 obstack_1grow (&util_obstack, '+');
7175 obstack_grow (&util_obstack, buffer, strlen (buffer));
7178 obstack_1grow (&util_obstack, 0);
7179 result = get_identifier (obstack_finish (&util_obstack));
7180 obstack_free (&util_obstack, util_firstobj);
7181 return result;
7184 void
7185 finish_method_def ()
7187 METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
7189 finish_function (0);
7191 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7192 since the optimizer may find "may be used before set" errors. */
7193 method_context = NULL_TREE;
7197 lang_report_error_function (decl)
7198 tree decl;
7200 if (method_context)
7202 fprintf (stderr, "In method `%s'\n",
7203 IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
7204 return 1;
7207 else
7208 return 0;
7211 static int
7212 is_complex_decl (type)
7213 tree type;
7215 return (TREE_CODE (type) == ARRAY_TYPE
7216 || TREE_CODE (type) == FUNCTION_TYPE
7217 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7221 /* Code to convert a decl node into text for a declaration in C. */
7223 static char tmpbuf[256];
7225 static void
7226 adorn_decl (decl, str)
7227 tree decl;
7228 char *str;
7230 enum tree_code code = TREE_CODE (decl);
7232 if (code == ARRAY_REF)
7234 tree an_int_cst = TREE_OPERAND (decl, 1);
7236 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7237 sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (an_int_cst));
7238 else
7239 strcat (str, "[]");
7242 else if (code == ARRAY_TYPE)
7244 tree an_int_cst = TYPE_SIZE (decl);
7245 tree array_of = TREE_TYPE (decl);
7247 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7248 sprintf (str + strlen (str), "[%d]",
7249 (TREE_INT_CST_LOW (an_int_cst)
7250 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7251 else
7252 strcat (str, "[]");
7255 else if (code == CALL_EXPR)
7257 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7259 strcat (str, "(");
7260 while (chain)
7262 gen_declaration (chain, str);
7263 chain = TREE_CHAIN (chain);
7264 if (chain)
7265 strcat (str, ", ");
7267 strcat (str, ")");
7270 else if (code == FUNCTION_TYPE)
7272 tree chain = TYPE_ARG_TYPES (decl);
7274 strcat (str, "(");
7275 while (chain && TREE_VALUE (chain) != void_type_node)
7277 gen_declaration (TREE_VALUE (chain), str);
7278 chain = TREE_CHAIN (chain);
7279 if (chain && TREE_VALUE (chain) != void_type_node)
7280 strcat (str, ", ");
7282 strcat (str, ")");
7285 else if (code == INDIRECT_REF)
7287 strcpy (tmpbuf, "*");
7288 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7290 tree chain;
7292 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7293 chain;
7294 chain = TREE_CHAIN (chain))
7296 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7298 strcat (tmpbuf, " ");
7299 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7302 if (str[0])
7303 strcat (tmpbuf, " ");
7305 strcat (tmpbuf, str);
7306 strcpy (str, tmpbuf);
7309 else if (code == POINTER_TYPE)
7311 strcpy (tmpbuf, "*");
7312 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7314 if (TREE_READONLY (decl))
7315 strcat (tmpbuf, " const");
7316 if (TYPE_VOLATILE (decl))
7317 strcat (tmpbuf, " volatile");
7318 if (str[0])
7319 strcat (tmpbuf, " ");
7321 strcat (tmpbuf, str);
7322 strcpy (str, tmpbuf);
7326 static char *
7327 gen_declarator (decl, buf, name)
7328 tree decl;
7329 char *buf;
7330 char *name;
7332 if (decl)
7334 enum tree_code code = TREE_CODE (decl);
7335 char *str;
7336 tree op;
7337 int wrap = 0;
7339 switch (code)
7341 case ARRAY_REF:
7342 case INDIRECT_REF:
7343 case CALL_EXPR:
7344 op = TREE_OPERAND (decl, 0);
7346 /* We have a pointer to a function or array...(*)(), (*)[] */
7347 if ((code == ARRAY_REF || code == CALL_EXPR)
7348 && op && TREE_CODE (op) == INDIRECT_REF)
7349 wrap = 1;
7351 str = gen_declarator (op, buf, name);
7353 if (wrap)
7355 strcpy (tmpbuf, "(");
7356 strcat (tmpbuf, str);
7357 strcat (tmpbuf, ")");
7358 strcpy (str, tmpbuf);
7361 adorn_decl (decl, str);
7362 break;
7364 case ARRAY_TYPE:
7365 case FUNCTION_TYPE:
7366 case POINTER_TYPE:
7367 strcpy (buf, name);
7368 str = buf;
7370 /* This clause is done iteratively rather than recursively. */
7373 op = (is_complex_decl (TREE_TYPE (decl))
7374 ? TREE_TYPE (decl) : NULL_TREE);
7376 adorn_decl (decl, str);
7378 /* We have a pointer to a function or array...(*)(), (*)[] */
7379 if (code == POINTER_TYPE
7380 && op && (TREE_CODE (op) == FUNCTION_TYPE
7381 || TREE_CODE (op) == ARRAY_TYPE))
7383 strcpy (tmpbuf, "(");
7384 strcat (tmpbuf, str);
7385 strcat (tmpbuf, ")");
7386 strcpy (str, tmpbuf);
7389 decl = (is_complex_decl (TREE_TYPE (decl))
7390 ? TREE_TYPE (decl) : NULL_TREE);
7393 while (decl && (code = TREE_CODE (decl)))
7396 break;
7398 case IDENTIFIER_NODE:
7399 /* Will only happen if we are processing a "raw" expr-decl. */
7400 strcpy (buf, IDENTIFIER_POINTER (decl));
7401 return buf;
7404 return str;
7407 else
7408 /* We have an abstract declarator or a _DECL node. */
7410 strcpy (buf, name);
7411 return buf;
7415 static void
7416 gen_declspecs (declspecs, buf, raw)
7417 tree declspecs;
7418 char *buf;
7419 int raw;
7421 if (raw)
7423 tree chain;
7425 for (chain = nreverse (copy_list (declspecs));
7426 chain; chain = TREE_CHAIN (chain))
7428 tree aspec = TREE_VALUE (chain);
7430 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7431 strcat (buf, IDENTIFIER_POINTER (aspec));
7432 else if (TREE_CODE (aspec) == RECORD_TYPE)
7434 if (TYPE_NAME (aspec))
7436 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7438 if (! TREE_STATIC_TEMPLATE (aspec))
7439 strcat (buf, "struct ");
7440 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7442 /* NEW!!! */
7443 if (protocol_list)
7445 tree chain = protocol_list;
7447 strcat (buf, " <");
7448 while (chain)
7450 strcat (buf,
7451 IDENTIFIER_POINTER
7452 (PROTOCOL_NAME (TREE_VALUE (chain))));
7453 chain = TREE_CHAIN (chain);
7454 if (chain)
7455 strcat (buf, ", ");
7457 strcat (buf, ">");
7461 else
7462 strcat (buf, "untagged struct");
7465 else if (TREE_CODE (aspec) == UNION_TYPE)
7467 if (TYPE_NAME (aspec))
7469 if (! TREE_STATIC_TEMPLATE (aspec))
7470 strcat (buf, "union ");
7471 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7473 else
7474 strcat (buf, "untagged union");
7477 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7479 if (TYPE_NAME (aspec))
7481 if (! TREE_STATIC_TEMPLATE (aspec))
7482 strcat (buf, "enum ");
7483 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7485 else
7486 strcat (buf, "untagged enum");
7489 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7490 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7492 else if (IS_ID (aspec))
7494 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7496 strcat (buf, "id");
7497 if (protocol_list)
7499 tree chain = protocol_list;
7501 strcat (buf, " <");
7502 while (chain)
7504 strcat (buf,
7505 IDENTIFIER_POINTER
7506 (PROTOCOL_NAME (TREE_VALUE (chain))));
7507 chain = TREE_CHAIN (chain);
7508 if (chain)
7509 strcat (buf, ", ");
7511 strcat (buf, ">");
7514 if (TREE_CHAIN (chain))
7515 strcat (buf, " ");
7518 else
7520 /* Type qualifiers. */
7521 if (TREE_READONLY (declspecs))
7522 strcat (buf, "const ");
7523 if (TYPE_VOLATILE (declspecs))
7524 strcat (buf, "volatile ");
7526 switch (TREE_CODE (declspecs))
7528 /* Type specifiers. */
7530 case INTEGER_TYPE:
7531 declspecs = TYPE_MAIN_VARIANT (declspecs);
7533 /* Signed integer types. */
7535 if (declspecs == short_integer_type_node)
7536 strcat (buf, "short int ");
7537 else if (declspecs == integer_type_node)
7538 strcat (buf, "int ");
7539 else if (declspecs == long_integer_type_node)
7540 strcat (buf, "long int ");
7541 else if (declspecs == long_long_integer_type_node)
7542 strcat (buf, "long long int ");
7543 else if (declspecs == signed_char_type_node
7544 || declspecs == char_type_node)
7545 strcat (buf, "char ");
7547 /* Unsigned integer types. */
7549 else if (declspecs == short_unsigned_type_node)
7550 strcat (buf, "unsigned short ");
7551 else if (declspecs == unsigned_type_node)
7552 strcat (buf, "unsigned int ");
7553 else if (declspecs == long_unsigned_type_node)
7554 strcat (buf, "unsigned long ");
7555 else if (declspecs == long_long_unsigned_type_node)
7556 strcat (buf, "unsigned long long ");
7557 else if (declspecs == unsigned_char_type_node)
7558 strcat (buf, "unsigned char ");
7559 break;
7561 case REAL_TYPE:
7562 declspecs = TYPE_MAIN_VARIANT (declspecs);
7564 if (declspecs == float_type_node)
7565 strcat (buf, "float ");
7566 else if (declspecs == double_type_node)
7567 strcat (buf, "double ");
7568 else if (declspecs == long_double_type_node)
7569 strcat (buf, "long double ");
7570 break;
7572 case RECORD_TYPE:
7573 if (TYPE_NAME (declspecs)
7574 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7576 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7578 if (! TREE_STATIC_TEMPLATE (declspecs))
7579 strcat (buf, "struct ");
7580 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7582 if (protocol_list)
7584 tree chain = protocol_list;
7586 strcat (buf, " <");
7587 while (chain)
7589 strcat (buf,
7590 IDENTIFIER_POINTER
7591 (PROTOCOL_NAME (TREE_VALUE (chain))));
7592 chain = TREE_CHAIN (chain);
7593 if (chain)
7594 strcat (buf, ", ");
7596 strcat (buf, ">");
7600 else
7601 strcat (buf, "untagged struct");
7603 strcat (buf, " ");
7604 break;
7606 case UNION_TYPE:
7607 if (TYPE_NAME (declspecs)
7608 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7610 strcat (buf, "union ");
7611 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7612 strcat (buf, " ");
7615 else
7616 strcat (buf, "untagged union ");
7617 break;
7619 case ENUMERAL_TYPE:
7620 if (TYPE_NAME (declspecs)
7621 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7623 strcat (buf, "enum ");
7624 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7625 strcat (buf, " ");
7628 else
7629 strcat (buf, "untagged enum ");
7630 break;
7632 case VOID_TYPE:
7633 strcat (buf, "void ");
7634 break;
7636 case POINTER_TYPE:
7638 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7640 strcat (buf, "id");
7641 if (protocol_list)
7643 tree chain = protocol_list;
7645 strcat (buf, " <");
7646 while (chain)
7648 strcat (buf,
7649 IDENTIFIER_POINTER
7650 (PROTOCOL_NAME (TREE_VALUE (chain))));
7651 chain = TREE_CHAIN (chain);
7652 if (chain)
7653 strcat (buf, ", ");
7656 strcat (buf, ">");
7663 static char *
7664 gen_declaration (atype_or_adecl, buf)
7665 tree atype_or_adecl;
7666 char *buf;
7668 char declbuf[256];
7670 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7672 tree declspecs; /* "identifier_node", "record_type" */
7673 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7675 /* We have a "raw", abstract declarator (typename). */
7676 declarator = TREE_VALUE (atype_or_adecl);
7677 declspecs = TREE_PURPOSE (atype_or_adecl);
7679 gen_declspecs (declspecs, buf, 1);
7680 if (declarator)
7682 strcat (buf, " ");
7683 strcat (buf, gen_declarator (declarator, declbuf, ""));
7687 else
7689 tree atype;
7690 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7691 tree declarator; /* "array_type", "function_type", "pointer_type". */
7693 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7694 || TREE_CODE (atype_or_adecl) == PARM_DECL
7695 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7696 atype = TREE_TYPE (atype_or_adecl);
7697 else
7698 /* Assume we have a *_type node. */
7699 atype = atype_or_adecl;
7701 if (is_complex_decl (atype))
7703 tree chain;
7705 /* Get the declaration specifier; it is at the end of the list. */
7706 declarator = chain = atype;
7708 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7709 while (is_complex_decl (chain));
7710 declspecs = chain;
7713 else
7715 declspecs = atype;
7716 declarator = NULL_TREE;
7719 gen_declspecs (declspecs, buf, 0);
7721 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7722 || TREE_CODE (atype_or_adecl) == PARM_DECL
7723 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7725 char *decl_name = (DECL_NAME (atype_or_adecl)
7726 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))
7727 : "");
7729 if (declarator)
7731 strcat (buf, " ");
7732 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7735 else if (decl_name[0])
7737 strcat (buf, " ");
7738 strcat (buf, decl_name);
7741 else if (declarator)
7743 strcat (buf, " ");
7744 strcat (buf, gen_declarator (declarator, declbuf, ""));
7748 return buf;
7751 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
7753 static char *
7754 gen_method_decl (method, buf)
7755 tree method;
7756 char *buf;
7758 tree chain;
7760 if (RAW_TYPESPEC (method) != objc_object_reference)
7762 strcpy (buf, "(");
7763 gen_declaration (TREE_TYPE (method), buf);
7764 strcat (buf, ")");
7767 chain = METHOD_SEL_ARGS (method);
7768 if (chain)
7770 /* We have a chain of keyword_decls. */
7773 if (KEYWORD_KEY_NAME (chain))
7774 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
7776 strcat (buf, ":");
7777 if (RAW_TYPESPEC (chain) != objc_object_reference)
7779 strcat (buf, "(");
7780 gen_declaration (TREE_TYPE (chain), buf);
7781 strcat (buf, ")");
7784 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
7785 if ((chain = TREE_CHAIN (chain)))
7786 strcat (buf, " ");
7788 while (chain);
7790 if (METHOD_ADD_ARGS (method) == (tree)1)
7791 strcat (buf, ", ...");
7792 else if (METHOD_ADD_ARGS (method))
7794 /* We have a tree list node as generate by get_parm_info. */
7795 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7797 /* Know we have a chain of parm_decls. */
7798 while (chain)
7800 strcat (buf, ", ");
7801 gen_declaration (chain, buf);
7802 chain = TREE_CHAIN (chain);
7807 else
7808 /* We have a unary selector. */
7809 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
7811 return buf;
7814 /* Debug info. */
7816 static void
7817 dump_interface (fp, chain)
7818 FILE *fp;
7819 tree chain;
7821 char *buf = (char *)xmalloc (256);
7822 char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
7823 tree ivar_decls = CLASS_RAW_IVARS (chain);
7824 tree nst_methods = CLASS_NST_METHODS (chain);
7825 tree cls_methods = CLASS_CLS_METHODS (chain);
7827 fprintf (fp, "\n@interface %s", my_name);
7829 if (CLASS_SUPER_NAME (chain))
7831 char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
7832 fprintf (fp, " : %s\n", super_name);
7834 else
7835 fprintf (fp, "\n");
7837 if (ivar_decls)
7839 fprintf (fp, "{\n");
7842 bzero (buf, 256);
7843 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
7844 ivar_decls = TREE_CHAIN (ivar_decls);
7846 while (ivar_decls);
7847 fprintf (fp, "}\n");
7850 while (nst_methods)
7852 bzero (buf, 256);
7853 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
7854 nst_methods = TREE_CHAIN (nst_methods);
7857 while (cls_methods)
7859 bzero (buf, 256);
7860 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
7861 cls_methods = TREE_CHAIN (cls_methods);
7863 fprintf (fp, "\n@end");
7866 static void
7867 init_objc ()
7869 /* Add the special tree codes of Objective C to the tables. */
7871 #define LAST_CODE LAST_AND_UNUSED_TREE_CODE
7873 gcc_obstack_init (&util_obstack);
7874 util_firstobj = (char *) obstack_finish (&util_obstack);
7876 tree_code_type
7877 = (char **) xrealloc (tree_code_type,
7878 sizeof (char *) * LAST_OBJC_TREE_CODE);
7879 tree_code_length
7880 = (int *) xrealloc (tree_code_length,
7881 sizeof (int) * LAST_OBJC_TREE_CODE);
7882 tree_code_name
7883 = (char **) xrealloc (tree_code_name,
7884 sizeof (char *) * LAST_OBJC_TREE_CODE);
7885 bcopy ((char *) objc_tree_code_type,
7886 (char *) (tree_code_type + (int) LAST_CODE),
7887 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
7888 * sizeof (char *)));
7889 bcopy ((char *) objc_tree_code_length,
7890 (char *) (tree_code_length + (int) LAST_CODE),
7891 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
7892 * sizeof (int)));
7893 bcopy ((char *) objc_tree_code_name,
7894 (char *) (tree_code_name + (int) LAST_CODE),
7895 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
7896 * sizeof (char *)));
7898 errbuf = (char *)xmalloc (BUFSIZE);
7899 hash_init ();
7900 synth_module_prologue ();
7903 static void
7904 finish_objc ()
7906 struct imp_entry *impent;
7907 tree chain;
7908 /* The internally generated initializers appear to have missing braces.
7909 Don't warn about this. */
7910 int save_warn_missing_braces = warn_missing_braces;
7911 warn_missing_braces = 0;
7913 generate_forward_declaration_to_string_table ();
7915 #ifdef OBJC_PROLOGUE
7916 OBJC_PROLOGUE;
7917 #endif
7919 /* Process the static instances here because initialization of objc_symtab
7920 dependens on them. */
7921 if (objc_static_instances)
7922 generate_static_references ();
7924 if (implementation_context || class_names_chain
7925 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
7926 generate_objc_symtab_decl ();
7928 for (impent = imp_list; impent; impent = impent->next)
7930 implementation_context = impent->imp_context;
7931 implementation_template = impent->imp_template;
7933 UOBJC_CLASS_decl = impent->class_decl;
7934 UOBJC_METACLASS_decl = impent->meta_decl;
7936 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7938 /* all of the following reference the string pool... */
7939 generate_ivar_lists ();
7940 generate_dispatch_tables ();
7941 generate_shared_structures ();
7943 else
7945 generate_dispatch_tables ();
7946 generate_category (implementation_context);
7950 /* If we are using an array of selectors, we must always
7951 finish up the array decl even if no selectors were used. */
7952 if (! flag_next_runtime || sel_ref_chain)
7953 build_selector_translation_table ();
7955 if (protocol_chain)
7956 generate_protocols ();
7958 if (implementation_context || class_names_chain || objc_static_instances
7959 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
7961 /* Arrange for Objc data structures to be initialized at run time. */
7962 char *init_name = build_module_descriptor ();
7963 if (init_name)
7964 assemble_constructor (init_name);
7967 /* Dump the class references. This forces the appropriate classes
7968 to be linked into the executable image, preserving unix archive
7969 semantics. This can be removed when we move to a more dynamically
7970 linked environment. */
7972 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
7974 handle_class_ref (chain);
7975 if (TREE_PURPOSE (chain))
7976 generate_classref_translation_entry (chain);
7979 for (impent = imp_list; impent; impent = impent->next)
7980 handle_impent (impent);
7982 /* Dump the string table last. */
7984 generate_strings ();
7986 if (flag_gen_declaration)
7988 add_class (implementation_context);
7989 dump_interface (gen_declaration_file, implementation_context);
7992 if (warn_selector)
7994 int slot;
7995 hash hsh;
7997 /* Run through the selector hash tables and print a warning for any
7998 selector which has multiple methods. */
8000 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8001 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8002 if (hsh->list)
8004 tree meth = hsh->key;
8005 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8006 ? '-' : '+');
8007 attr loop;
8009 warning ("potential selector conflict for method `%s'",
8010 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8011 warn_with_method ("found", type, meth);
8012 for (loop = hsh->list; loop; loop = loop->next)
8013 warn_with_method ("found", type, loop->value);
8016 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8017 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8018 if (hsh->list)
8020 tree meth = hsh->key;
8021 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8022 ? '-' : '+');
8023 attr loop;
8025 warning ("potential selector conflict for method `%s'",
8026 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8027 warn_with_method ("found", type, meth);
8028 for (loop = hsh->list; loop; loop = loop->next)
8029 warn_with_method ("found", type, loop->value);
8033 warn_missing_braces = save_warn_missing_braces;
8036 /* Subroutines of finish_objc. */
8038 static void
8039 generate_classref_translation_entry (chain)
8040 tree chain;
8042 tree expr, name, decl_specs, decl, sc_spec;
8043 tree type;
8045 type = TREE_TYPE (TREE_PURPOSE (chain));
8047 expr = add_objc_string (TREE_VALUE (chain), class_names);
8048 expr = build_c_cast (type, expr); /* cast! */
8050 name = DECL_NAME (TREE_PURPOSE (chain));
8052 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8054 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8055 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8057 /* The decl that is returned from start_decl is the one that we
8058 forward declared in build_class_reference. */
8059 decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE);
8060 finish_decl (decl, expr, NULL_TREE);
8061 return;
8064 static void
8065 handle_class_ref (chain)
8066 tree chain;
8068 char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8069 if (! flag_next_runtime)
8071 tree decl;
8072 char *string = (char *) alloca (strlen (name) + 30);
8073 tree exp;
8075 sprintf (string, "%sobjc_class_name_%s",
8076 (flag_next_runtime ? "." : "__"), name);
8078 /* Make a decl for this name, so we can use its address in a tree. */
8079 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8080 DECL_EXTERNAL (decl) = 1;
8081 TREE_PUBLIC (decl) = 1;
8083 pushdecl (decl);
8084 rest_of_decl_compilation (decl, 0, 0, 0);
8086 /* Make following constant read-only (why not)? */
8087 readonly_data_section ();
8089 exp = build1 (ADDR_EXPR, string_type_node, decl);
8091 /* Align the section properly. */
8092 assemble_constant_align (exp);
8094 /* Inform the assembler about this new external thing. */
8095 assemble_external (decl);
8097 /* Output a constant to reference this address. */
8098 output_constant (exp, int_size_in_bytes (string_type_node));
8100 else
8102 /* This overreliance on our assembler (i.e. lack of portability)
8103 should be dealt with at some point. The GNU strategy (above)
8104 won't work either, but it is a start. */
8105 char *string = (char *) alloca (strlen (name) + 30);
8106 sprintf (string, ".reference .objc_class_name_%s", name);
8107 assemble_asm (my_build_string (strlen (string) + 1, string));
8111 static void
8112 handle_impent (impent)
8113 struct imp_entry *impent;
8115 implementation_context = impent->imp_context;
8116 implementation_template = impent->imp_template;
8118 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8120 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8121 char *string = (char *) alloca (strlen (class_name) + 30);
8123 if (flag_next_runtime)
8125 /* Grossly unportable.
8126 People should know better than to assume
8127 such things about assembler syntax! */
8128 sprintf (string, ".objc_class_name_%s=0", class_name);
8129 assemble_asm (my_build_string (strlen (string) + 1, string));
8131 sprintf (string, ".globl .objc_class_name_%s", class_name);
8132 assemble_asm (my_build_string (strlen (string) + 1, string));
8135 else
8137 sprintf (string, "%sobjc_class_name_%s",
8138 (flag_next_runtime ? "." : "__"), class_name);
8139 assemble_global (string);
8140 assemble_label (string);
8144 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8146 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8147 char *class_super_name
8148 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8149 char *string = (char *) alloca (strlen (class_name)
8150 + strlen (class_super_name) + 30);
8152 /* Do the same for categories. Even though no references to these
8153 symbols are generated automatically by the compiler, it gives
8154 you a handle to pull them into an archive by hand. */
8155 if (flag_next_runtime)
8157 /* Grossly unportable. */
8158 sprintf (string, ".objc_category_name_%s_%s=0",
8159 class_name, class_super_name);
8160 assemble_asm (my_build_string (strlen (string) + 1, string));
8162 sprintf (string, ".globl .objc_category_name_%s_%s",
8163 class_name, class_super_name);
8164 assemble_asm (my_build_string (strlen (string) + 1, string));
8167 else
8169 sprintf (string, "%sobjc_category_name_%s_%s",
8170 (flag_next_runtime ? "." : "__"),
8171 class_name, class_super_name);
8172 assemble_global (string);
8173 assemble_label (string);
8178 #ifdef DEBUG
8180 static void
8181 objc_debug (fp)
8182 FILE *fp;
8184 char *buf = (char *)xmalloc (256);
8186 { /* dump function prototypes */
8187 tree loop = UOBJC_MODULES_decl;
8189 fprintf (fp, "\n\nfunction prototypes:\n");
8190 while (loop)
8192 if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
8194 /* We have a function definition: generate prototype. */
8195 bzero (errbuf, BUFSIZE);
8196 gen_declaration (loop, errbuf);
8197 fprintf (fp, "%s;\n", errbuf);
8199 loop = TREE_CHAIN (loop);
8203 /* Dump global chains. */
8204 tree loop;
8205 int i, index = 0, offset = 0;
8206 hash hashlist;
8208 for (i = 0; i < SIZEHASHTABLE; i++)
8210 if (hashlist = nst_method_hash_list[i])
8212 fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
8215 bzero (buf, 256);
8216 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8217 hashlist = hashlist->next;
8219 while (hashlist);
8223 for (i = 0; i < SIZEHASHTABLE; i++)
8225 if (hashlist = cls_method_hash_list[i])
8227 fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
8230 bzero (buf, 256);
8231 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8232 hashlist = hashlist->next;
8234 while (hashlist);
8238 fprintf (fp, "\nsel_refdef_chain:\n");
8239 for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
8241 fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
8242 IDENTIFIER_POINTER (TREE_VALUE (loop)));
8243 index++;
8244 /* add one for the '\0' character */
8245 offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
8248 fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
8251 #endif
8253 void
8254 print_lang_statistics ()