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