|
|
1.1 root 1: /* Implement classes and message passing for Objective C.
2: Copyright (C) 1992 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: /*
22: * Purpose: This module implements the Objective-C 4.0 language.
23: *
24: * compatibility issues (with the Stepstone translator):
25: *
26: * - does not recognize the following 3.3 constructs.
27: * @requires, @classes, @messages, = (...)
28: * - methods with variable arguments must conform to ANSI standard.
29: * - tagged structure definitions that appear in BOTH the interface
30: * and implementation are not allowed.
31: * - public/private: all instance variables are public within the
32: * context of the implementation...I consider this to be a bug in
33: * the translator.
34: * - statically allocated objects are not supported. the user will
35: * receive an error if this service is requested.
36: *
37: * code generation `options':
38: *
1.1.1.3 root 39: * - OBJC_INT_SELECTORS, OBJC_SELECTORS_WITHOUT_LABELS, NEXT_OBJC_RUNTIME
1.1 root 40: */
41:
42: #include <stdio.h>
43: #include "config.h"
44: #include "tree.h"
45: #include "c-tree.h"
46: #include "c-lex.h"
47: #include "flags.h"
48: #include "objc-actions.h"
49: #include "input.h"
1.1.1.4 ! root 50:
! 51: /* The GNU run time requires the selectors in a vector
! 52: so it can store the operation numbers in them. */
! 53: #ifndef NEXT_OBJC_RUNTIME
! 54: #define OBJC_SELECTORS_WITHOUT_LABELS
! 55: #endif
1.1 root 56:
57: /* Define the special tree codes that we use. */
58:
59: /* Table indexed by tree code giving a string containing a character
60: classifying the tree code. Possibilities are
61: t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */
62:
63: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
64:
65: char *objc_tree_code_type[] = {
66: "x",
67: #include "objc-tree.def"
68: };
69: #undef DEFTREECODE
70:
71: /* Table indexed by tree code giving number of expression
72: operands beyond the fixed part of the node structure.
73: Not used for types or decls. */
74:
75: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
76:
77: int objc_tree_code_length[] = {
78: 0,
79: #include "objc-tree.def"
80: };
81: #undef DEFTREECODE
82:
83: /* Names of tree components.
84: Used for printing out the tree and error messages. */
85: #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
86:
87: char *objc_tree_code_name[] = {
88: "@@dummy",
89: #include "objc-tree.def"
90: };
91: #undef DEFTREECODE
92:
1.1.1.3 root 93: /* Set up for use of obstacks. */
94:
95: #include "obstack.h"
96:
97: #define obstack_chunk_alloc xmalloc
98: #define obstack_chunk_free free
99:
100: /* This obstack is used to accumulate the encoding of a data type. */
101: static struct obstack util_obstack;
102: /* This points to the beginning of obstack contents,
103: so we can free the whole contents. */
104: char *util_firstobj;
105:
1.1 root 106: /* for encode_method_def */
107: #include "rtl.h"
108:
109: #define OBJC_VERSION 2
110:
111: #define NULLT (tree) 0
112:
113: #define OBJC_ENCODE_INLINE_DEFS 0
114: #define OBJC_ENCODE_DONT_INLINE_DEFS 1
115:
116: /*** Private Interface (procedures) ***/
117:
118: /* code generation */
119:
120: static void synth_module_prologue ();
121: static char *build_module_descriptor ();
122: static tree init_module_descriptor ();
123: static void build_module_entry ();
124: static tree build_objc_method_call ();
125: static void build_message_selector_pool ();
126: static void build_selector_translation_table ();
127: static tree build_ivar_chain ();
128:
129: static tree build_ivar_template ();
130: static tree build_method_template ();
131: static tree build_private_template ();
132: static void build_class_template ();
133: static void build_category_template ();
134: static tree build_super_template ();
135:
136: static void synth_forward_declarations ();
137: static void generate_ivar_lists ();
138: static void generate_dispatch_tables ();
139: static void generate_shared_structures ();
140:
141: static tree build_msg_pool_reference ();
142: static tree init_selector ();
143: static tree build_keword_selector ();
144: static tree synth_id_with_class_suffix ();
145:
146: /* misc. bookkeeping */
147:
148: typedef struct hashedEntry *hash;
149: typedef struct hashedAttribute *attr;
150:
151: struct hashedAttribute {
152: attr next;
153: tree value;
154: };
155: struct hashedEntry {
156: attr list;
157: hash next;
158: tree key;
159: };
160: static void hash_init ();
161: static void hash_enter ();
162: static hash hash_lookup ();
163: static void hash_add_attr ();
164: static tree lookup_method ();
165: static tree lookup_instance_method_static ();
166: static tree lookup_class_method_static ();
167: static tree add_class ();
168: static int add_selector_reference ();
169: static void add_class_reference ();
170: static int add_objc_string ();
171:
172: /* type encoding */
173:
174: static void encode_aggregate ();
175: static void encode_bitfield ();
176: static void encode_type ();
177: static void encode_field_decl ();
178:
179: static void really_start_method ();
180: static int comp_method_with_proto ();
181: static int comp_proto_with_proto ();
182: static tree get_arg_type_list ();
183: static tree expr_last ();
184:
185: /* utilities for debugging and error diagnostics: */
186:
187: static void warn_with_method ();
188: static void error_with_method ();
189: static void error_with_ivar ();
190: static char *gen_method_decl ();
191: static char *gen_declaration ();
192: static char *gen_declarator ();
193: static int is_complex_decl ();
194: static void adorn_decl ();
195: static void dump_interfaces ();
196:
197: /*** Private Interface (data) ***/
198:
199: /* reserved tag definitions: */
200:
201: #define TYPE_ID "id"
202: #define TAG_OBJECT "objc_object"
203: #define TAG_CLASS "objc_class"
204: #define TAG_SUPER "objc_super"
205: #define TAG_SELECTOR "objc_selector"
206:
207: #define _TAG_CLASS "_objc_class"
208: #define _TAG_IVAR "_objc_ivar"
209: #define _TAG_IVAR_LIST "_objc_ivar_list"
210: #define _TAG_METHOD "_objc_method"
211: #define _TAG_METHOD_LIST "_objc_method_list"
212: #define _TAG_CATEGORY "_objc_category"
213: #define _TAG_MODULE "_objc_module"
214: #define _TAG_SYMTAB "_objc_symtab"
215: #define _TAG_SUPER "_objc_super"
216:
217: /* set by `continue_class ()' and checked by `is_public ()' */
218:
219: #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC(record_type))
220: #define TYPED_OBJECT(type) \
221: (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
222:
223: /* some commonly used instances of "identifier_node". */
224:
1.1.1.2 root 225: static tree self_id, _cmd_id;
1.1 root 226:
227: static tree self_decl, _msg_decl, _msgSuper_decl;
228: static tree objc_getClass_decl, objc_getMetaClass_decl;
229:
1.1.1.2 root 230: static tree super_type, selector_type, id_type, class_type;
1.1 root 231: static tree instance_type;
232:
233: static tree interface_chain = NULLT;
234:
235: /* chains to manage selectors that are referenced and defined in the module */
236:
237: static tree cls_ref_chain = NULLT; /* classes referenced */
238: static tree sel_ref_chain = NULLT; /* selectors referenced */
239: static tree sel_refdef_chain = NULLT; /* selectors references & defined */
240: static int max_selector_index; /* total # of selector referenced */
241:
242: /* hash tables to manage the global pool of method prototypes */
243:
244: static hash *nst_method_hash_list = 0;
245: static hash *cls_method_hash_list = 0;
246:
247: /* the following are used when compiling a class implementation.
248: *
249: * implementation_template will normally be an anInterface, however if
250: * none exists this will be equal to implementation_context...it is
251: * set in start_class.
252: */
253:
254: /* backend data declarations */
255:
256: static tree _OBJC_SYMBOLS_decl;
257: static tree _OBJC_INSTANCE_VARIABLES_decl, _OBJC_CLASS_VARIABLES_decl;
258: static tree _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl;
259: static tree _OBJC_CLASS_decl, _OBJC_METACLASS_decl;
1.1.1.3 root 260: #ifdef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 261: static tree _OBJC_SELECTOR_REFERENCES_decl;
262: #endif
263: static tree _OBJC_MODULES_decl;
264: static tree _OBJC_STRINGS_decl;
265:
266: static tree implementation_context = NULLT,
267: implementation_template = NULLT;
268:
269: struct imp_entry {
270: struct imp_entry *next;
271: tree imp_context;
272: tree imp_template;
273: tree class_decl; /* _OBJC_CLASS_<my_name>; */
274: tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
275: };
276: static struct imp_entry *imp_list = 0;
277: static int imp_count = 0; /* `@implementation' */
278: static int cat_count = 0; /* `@category' */
279:
280: static tree objc_class_template, objc_category_template, _PRIVATE_record;
281: static tree _clsSuper_ref, __clsSuper_ref;
282:
283: static tree objc_method_template, objc_ivar_template;
284: static tree objc_symtab_template, objc_module_template;
285: static tree objc_super_template, objc_object_reference;
286:
287: static tree objc_object_id, objc_class_id;
288: static tree _OBJC_SUPER_decl;
289:
290: static tree method_context = NULLT;
291: static int method_slot = 0; /* used by start_method_def */
292:
293: #define BUFSIZE 512
294:
295: static char *errbuf; /* a buffer for error diagnostics */
296:
297: extern char *strcpy (), *strcat ();
298:
299: extern tree groktypename_in_parm_context ();
300:
301: extern struct obstack permanent_obstack, *current_obstack, *rtl_obstack;
302:
303: /* data imported from toplev.c */
304:
305: extern char *dump_base_name;
306:
307: /* Open and close the file for outputting class declarations, if requested. */
308:
309: int flag_gen_declaration = 0;
310:
311: FILE *gen_declaration_file;
312:
313: /* Warn if multiple methods are seen for the same selector, but with
314: different argument types. */
315:
316: int warn_selector = 0;
317:
318: void
319: lang_init ()
320: {
321: /* the beginning of the file is a new line; check for # */
322: /* With luck, we discover the real source file's name from that
323: and put it in input_filename. */
324: ungetc (check_newline (), finput);
325:
326: /* If gen_declaration desired, open the output file. */
327: if (flag_gen_declaration)
328: {
329: int dump_base_name_length = strlen (dump_base_name);
330: register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
331: strcpy (dumpname, dump_base_name);
332: strcat (dumpname, ".decl");
333: gen_declaration_file = fopen (dumpname, "w");
334: if (gen_declaration_file == 0)
335: pfatal_with_name (dumpname);
336: }
337:
338: if (doing_objc_thang)
339: init_objc ();
340: }
341:
342: void
343: objc_finish ()
344: {
345: if (doing_objc_thang)
346: finish_objc (); /* Objective-C finalization */
347:
348: if (gen_declaration_file)
349: fclose (gen_declaration_file);
350: }
351:
352: void
353: lang_finish ()
354: {
355: }
356:
357: int
358: lang_decode_option (p)
359: char *p;
360: {
361: if (!strcmp (p, "-lang-objc"))
362: doing_objc_thang = 1;
363: else if (!strcmp (p, "-gen-decls"))
364: flag_gen_declaration = 1;
365: else if (!strcmp (p, "-Wselector"))
366: warn_selector = 1;
367: else if (!strcmp (p, "-Wno-selector"))
368: warn_selector = 0;
369: else
370: return c_decode_option (p);
371:
372: return 1;
373: }
374:
375: static tree
376: define_decl (declarator, declspecs)
377: tree declarator;
378: tree declspecs;
379: {
380: tree decl = start_decl (declarator, declspecs, 0);
381: finish_decl (decl, NULLT, NULLT);
382: return decl;
383: }
384:
385: /*
386: * rules for statically typed objects...called from `c-typeck.comptypes'.
387: *
388: * an assignment of the form `a' = `b' is permitted if:
389: *
390: * - `a' is of type "id".
391: * - `a' and `b' are the same class type.
392: * - `a' and `b' are of class types A and B such that B is a descendant
393: * of A.
394: */
395:
396: int
397: maybe_objc_comptypes (lhs, rhs)
398: tree lhs, rhs;
399: {
400: if (doing_objc_thang)
401: return objc_comptypes (lhs, rhs);
402: return 0;
403: }
404:
405: int
406: objc_comptypes (lhs, rhs)
407: tree lhs;
408: tree rhs;
409: {
410: /* `id' = `<class> *', `<class> *' = `id' */
411:
412: if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
413: || (TYPED_OBJECT (lhs) && TYPE_NAME (rhs) == objc_object_id))
414: return 1;
415:
416: /* `id' = `Class', `Class' = `id' */
417:
418:
419: else if ((TYPE_NAME (lhs) == objc_object_id &&
420: TYPE_NAME (rhs) == objc_class_id) ||
421: (TYPE_NAME (lhs) == objc_class_id &&
422: TYPE_NAME (rhs) == objc_object_id))
423: return 1;
424:
425: /* `<class> *' = `<class> *' */
426:
427: else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
428: {
429: tree lname = TYPE_NAME (lhs), rname = TYPE_NAME (rhs);
430:
431: if (lname == rname)
432: return 1;
433: else
434: {
435: /* if the left hand side is a super class of the right hand side,
436: allow it...
437: */
438: tree rinter = lookup_interface (rname);
439:
440: while (rinter)
441: {
442: if (lname == CLASS_SUPER_NAME (rinter))
443: return 1;
444:
445: rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
446: }
447:
448: return 0;
449: }
450: }
451: else
452: return 0;
453: }
454:
455: /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
456:
457: void
458: maybe_objc_check_decl (decl)
459: tree decl;
460: {
461: if (doing_objc_thang)
462: objc_check_decl (decl);
463: }
464:
465: void
466: objc_check_decl (decl)
467: tree decl;
468: {
469: tree type = TREE_TYPE (decl);
470: static int alreadyWarned = 0;
471:
472: if (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
473: {
474: if (!alreadyWarned)
475: {
476: error ("GNU compiler does not support statically allocated objects");
477: alreadyWarned = 1;
478: }
479: error_with_decl (decl, "`%s' cannot be statically allocated");
480: }
481: }
482:
483: /* implement static typing. at this point, we know we have an interface... */
484:
485: tree
486: get_static_reference (interface)
487: tree interface;
488: {
489: return xref_tag (RECORD_TYPE, CLASS_NAME (interface));
490: }
491:
1.1.1.2 root 492: /* Create and push a decl for a built-in external variable or field NAME.
493: CODE says which.
494: TYPE is its data type. */
495:
496: static tree
497: create_builtin_decl (code, type, name)
498: enum tree_code code;
499: tree type;
1.1.1.3 root 500: char *name;
1.1.1.2 root 501: {
502: tree decl = build_decl (code, get_identifier (name), type);
503: if (code == VAR_DECL)
504: {
1.1.1.4 ! root 505: TREE_STATIC (decl) = 1;
1.1.1.2 root 506: make_decl_rtl (decl, 0, 1);
507: pushdecl (decl);
508: }
509: return decl;
510: }
511:
1.1 root 512: /*
513: * purpose: "play" parser, creating/installing representations
514: * of the declarations that are required by Objective-C.
515: *
516: * model:
517: *
518: * type_spec--------->sc_spec
519: * (tree_list) (tree_list)
520: * | |
521: * | |
522: * identifier_node identifier_node
523: */
524: static void
525: synth_module_prologue ()
526: {
1.1.1.2 root 527: tree expr_decl, temp_type;
1.1 root 528:
529: /* defined in `objc.h' */
530: objc_object_id = get_identifier (TAG_OBJECT);
531:
532: objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
533:
1.1.1.2 root 534: id_type = build_pointer_type (objc_object_reference);
1.1 root 535:
536: objc_class_id = get_identifier (TAG_CLASS);
537:
1.1.1.2 root 538: class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
539:
540: /* Declare type of selector-objects that represent an operation name. */
1.1 root 541:
542: #ifdef OBJC_INT_SELECTORS
543: /* `unsigned int' */
1.1.1.2 root 544: selector_type = unsigned_type_node;
1.1 root 545: #else
546: /* `struct objc_selector *' */
1.1.1.2 root 547: selector_type
548: = build_pointer_type (xref_tag (RECORD_TYPE,
549: get_identifier (TAG_SELECTOR)));
1.1 root 550: #endif /* not OBJC_INT_SELECTORS */
551:
552: /* struct objc_object *objc_msgSend (id, SEL, ...); */
553:
1.1.1.2 root 554: temp_type
555: = build_function_type (id_type,
556: tree_cons (NULL_TREE, id_type,
557: tree_cons (NULLT, selector_type, NULLT)));
558:
559: _msg_decl = builtin_function ("objc_msgSend", temp_type, NOT_BUILT_IN, 0);
560:
561: /* struct objc_object *objc_msgSendSuper (void *, SEL, ...); */
562:
563: temp_type
564: = build_function_type (id_type,
565: tree_cons (NULL_TREE, ptr_type_node,
566: tree_cons (NULLT, selector_type, NULLT)));
1.1 root 567:
1.1.1.2 root 568: _msgSuper_decl = builtin_function ("objc_msgSendSuper",
569: temp_type, NOT_BUILT_IN, 0);
1.1 root 570:
571: /* id objc_getClass (); */
1.1.1.2 root 572:
573: temp_type = build_function_type (id_type, NULLT);
1.1 root 574:
1.1.1.2 root 575: objc_getClass_decl
576: = builtin_function ("objc_getClass", temp_type, NOT_BUILT_IN, 0);
1.1 root 577:
578: /* id objc_getMetaClass (); */
579:
1.1.1.2 root 580: objc_getMetaClass_decl
581: = builtin_function ("objc_getMetaClass", temp_type, NOT_BUILT_IN, 0);
1.1 root 582:
583: /* extern SEL _OBJC_SELECTOR_REFERENCES[]; */
584:
1.1.1.3 root 585: #ifdef OBJC_SELECTORS_WITHOUT_LABELS
1.1.1.2 root 586: _OBJC_SELECTOR_REFERENCES_decl
587: = create_builtin_decl (VAR_DECL, build_array_type (selector_type, NULLT),
588: "_OBJC_SELECTOR_REFERENCES");
1.1 root 589: #endif
590: }
591:
592: /*
593: * custom "build_string ()" which sets TREE_TYPE!
594: */
595: static tree
596: my_build_string (len, str)
597: int len;
598: char *str;
599: {
600: int wide_flag = 0;
601: tree aString = build_string (len, str);
602: /*
603: * some code from "combine_strings ()", which is local to c-parse.y.
604: */
605: if (TREE_TYPE (aString) == int_array_type_node)
606: wide_flag = 1;
607:
608: TREE_TYPE (aString) =
609: build_array_type (wide_flag ? integer_type_node : char_type_node,
610: build_index_type (build_int_2 (len - 1, 0)));
611:
612: TREE_CONSTANT (aString) = 1; /* puts string in the ".text" segment */
613: TREE_STATIC (aString) = 1;
614:
615: return aString;
616: }
1.1.1.2 root 617:
618: /* Take care of defining and initializing _OBJC_SYMBOLS. */
619:
620: /* Predefine the following data type:
621:
622: struct _objc_symtab {
623: long sel_ref_cnt;
624: SEL *refs;
625: short cls_def_cnt;
626: short cat_def_cnt;
627: void *defs[cls_def_cnt + cat_def_cnt];
628: }; */
1.1 root 629:
630: static void
631: build_objc_symtab_template ()
632: {
1.1.1.2 root 633: tree field_decl, field_decl_chain, index;
1.1 root 634:
635: objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (_TAG_SYMTAB));
636:
637: /* long sel_ref_cnt; */
638:
1.1.1.2 root 639: field_decl = create_builtin_decl (FIELD_DECL,
640: long_integer_type_node,
641: "sel_ref_cnt");
1.1 root 642: field_decl_chain = field_decl;
643:
1.1.1.2 root 644: /* SEL *refs; */
1.1 root 645:
1.1.1.2 root 646: field_decl = create_builtin_decl (FIELD_DECL,
647: build_pointer_type (selector_type),
648: "refs");
1.1 root 649: chainon (field_decl_chain, field_decl);
650:
651: /* short cls_def_cnt; */
652:
1.1.1.2 root 653: field_decl = create_builtin_decl (FIELD_DECL,
654: short_integer_type_node,
655: "cls_def_cnt");
1.1 root 656: chainon (field_decl_chain, field_decl);
657:
658: /* short cat_def_cnt; */
659:
1.1.1.2 root 660: field_decl = create_builtin_decl (FIELD_DECL,
661: short_integer_type_node,
662: "cat_def_cnt");
1.1 root 663: chainon (field_decl_chain, field_decl);
664:
665: /* void *defs[cls_def_cnt + cat_def_cnt]; */
666:
1.1.1.2 root 667: index = build_index_type (build_int_2 (imp_count + cat_count - 1, 0));
668: field_decl = create_builtin_decl (FIELD_DECL,
669: build_array_type (ptr_type_node, index),
670: "defs");
1.1 root 671: chainon (field_decl_chain, field_decl);
672:
673: finish_struct (objc_symtab_template, field_decl_chain);
674: }
675:
1.1.1.2 root 676: /* Create the initial value for the `defs' field of _objc_symtab.
677: This is a CONSTRUCTOR. */
678:
1.1 root 679: static tree
680: init_def_list ()
681: {
682: tree expr, initlist = NULLT;
683: struct imp_entry *impent;
684:
685: if (imp_count)
686: for (impent = imp_list; impent; impent = impent->next)
687: {
688: if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
689: {
690: expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
691: initlist = tree_cons (NULLT, expr, initlist);
692: }
693: }
694:
695: if (cat_count)
696: for (impent = imp_list; impent; impent = impent->next)
697: {
698: if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
699: {
700: expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
701: initlist = tree_cons (NULLT, expr, initlist);
702: }
703: }
704: return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
705: }
706:
1.1.1.2 root 707: /* Construct the initial value for all of _objc_symtab. */
708:
1.1 root 709: static tree
710: init_objc_symtab ()
711: {
712: tree initlist;
713:
714: /* sel_ref_cnt = { ..., 5, ... } */
715:
716: if (sel_ref_chain)
717: initlist = build_tree_list (NULLT, build_int_2 (max_selector_index, 0));
718: else
719: initlist = build_tree_list (NULLT, build_int_2 (0, 0));
720:
721: /* refs = { ..., _OBJC_SELECTOR_REFERENCES, ... } */
722:
1.1.1.3 root 723: #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 724: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
725: #else
726: if (sel_ref_chain)
727: initlist = tree_cons (NULLT, _OBJC_SELECTOR_REFERENCES_decl, initlist);
728: else
729: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
730: #endif
731:
732: /* cls_def_cnt = { ..., 5, ... } */
733:
734: initlist = tree_cons (NULLT, build_int_2 (imp_count, 0), initlist);
735:
736: /* cat_def_cnt = { ..., 5, ... } */
737:
738: initlist = tree_cons (NULLT, build_int_2 (cat_count, 0), initlist);
739:
740: /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
741:
742: if (imp_count || cat_count)
743: initlist = tree_cons (NULLT, init_def_list (), initlist);
744:
745: return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
746: }
747:
1.1.1.2 root 748: /* Push forward-declarations of all the categories
749: so that init_def_list can use them in a CONSTRUCTOR. */
750:
1.1 root 751: static void
752: forward_declare_categories ()
753: {
754: struct imp_entry *impent;
755: tree sav = implementation_context;
756: for (impent = imp_list; impent; impent = impent->next)
757: {
758: if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
759: {
1.1.1.2 root 760: /* Set an invisible arg to synth_id_with_class_suffix. */
1.1 root 761: implementation_context = impent->imp_context;
1.1.1.2 root 762: impent->class_decl
763: = create_builtin_decl (VAR_DECL, objc_category_template,
1.1.1.3 root 764: IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY")));
1.1 root 765: }
766: }
767: implementation_context = sav;
768: }
769:
1.1.1.2 root 770: /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
771: and initialized appropriately. */
772:
1.1 root 773: static void
774: generate_objc_symtab_decl ()
775: {
776: tree sc_spec;
777:
778: if (!objc_category_template)
779: build_category_template ();
780:
781: /* forward declare categories */
782: if (cat_count)
783: forward_declare_categories ();
784:
785: if (!objc_symtab_template)
786: build_objc_symtab_template ();
787:
788: sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
789:
790: _OBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
791: tree_cons (NULLT, objc_symtab_template, sc_spec), 1);
792:
793: finish_decl (_OBJC_SYMBOLS_decl, init_objc_symtab (), NULLT);
794: }
1.1.1.2 root 795:
1.1 root 796: /*
797: * tree_node------->tree_node----->...
798: * | |
799: * | (value) | (value)
800: * | |
801: * expr expr
802: */
803: static tree
804: init_module_descriptor ()
805: {
806: tree initlist, expr;
807:
808: /* version = { 1, ... } */
809:
810: expr = build_int_2 (OBJC_VERSION, 0);
811: initlist = build_tree_list (NULLT, expr);
812:
813: /* size = { ..., sizeof (struct objc_module), ... } */
814:
815: expr = build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_module_template)) /
816: BITS_PER_UNIT, 0);
817: initlist = tree_cons (NULLT, expr, initlist);
818:
819: /* name = { ..., "foo.m", ... } */
820:
821: expr = build_msg_pool_reference (
822: add_objc_string (get_identifier (input_filename)));
823: initlist = tree_cons (NULLT, expr, initlist);
824:
825: /* symtab = { ..., _OBJC_SYMBOLS, ... } */
826:
827: if (_OBJC_SYMBOLS_decl)
828: expr = build_unary_op (ADDR_EXPR, _OBJC_SYMBOLS_decl, 0);
829: else
830: expr = build_int_2 (0, 0);
831: initlist = tree_cons (NULLT, expr, initlist);
832:
833: return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
834: }
835:
836: /* Write out the data structures to describe Objective C classes defined.
837: If appropriate, compile and output a setup function to initialize them.
838: Return a string which is the name of a function to call to initialize
839: the Objective C data structures for this file (and perhaps for other files
840: also). */
841:
842: static char *
843: build_module_descriptor ()
844: {
845: tree decl_specs, field_decl, field_decl_chain;
846:
847: objc_module_template = start_struct (RECORD_TYPE, get_identifier (_TAG_MODULE));
848:
849: /* long version; */
850:
851: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
852: field_decl = get_identifier ("version");
853: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
854: field_decl_chain = field_decl;
855:
856: /* long size; */
857:
858: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
859: field_decl = get_identifier ("size");
860: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
861: chainon (field_decl_chain, field_decl);
862:
863: /* char *name; */
864:
865: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
866: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
867: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
868: chainon (field_decl_chain, field_decl);
869:
870: /* struct objc_symtab *symtab; */
871:
872: decl_specs = get_identifier (_TAG_SYMTAB);
873: decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
874: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("symtab"));
875: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
876: chainon (field_decl_chain, field_decl);
877:
878: finish_struct (objc_module_template, field_decl_chain);
879:
880: /* create an instance of "objc_module" */
881:
882: decl_specs = tree_cons (NULLT, objc_module_template,
883: build_tree_list (NULLT, ridpointers[(int) RID_STATIC]));
884:
885: _OBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
886: decl_specs, 1);
887:
888: finish_decl (_OBJC_MODULES_decl, init_module_descriptor (), NULLT);
889:
1.1.1.4 ! root 890: /* Mark the decl to avoid "defined but not used" warning. */
! 891: DECL_IN_SYSTEM_HEADER (_OBJC_MODULES_decl) = 1;
1.1 root 892:
893: /* Generate a constructor call for the module descriptor.
894: This code was generated by reading the grammar rules
895: of c-parse.y; Therefore, it may not be the most efficient
896: way of generating the requisite code. */
897: #ifndef NEXT_OBJC_RUNTIME
898: {
899: tree parms, function_decl, decelerator, void_list_node;
900: tree function_type;
901: char *buf;
902: char *global_object_name = 0;
903: tree t;
904:
905: /* Use a global object (which is already required to be unique over
906: the program) rather than the file name (which imposes extra
907: constraints). -- [email protected], 10 Jan 1990. */
908:
909: /* Find the name of some global object defined in this file. */
910: for (t = getdecls (); t; t = TREE_CHAIN (t))
1.1.1.4 ! root 911: if (TREE_PUBLIC (t) && !DECL_EXTERNAL (t) && DECL_INITIAL (t) != 0)
1.1 root 912: {
913: global_object_name = IDENTIFIER_POINTER (DECL_NAME (t));
914: break;
915: }
916:
917: /* If none, use the name of the file. */
918: if (!global_object_name)
919: {
920: char *p, *q;
921: global_object_name
922: = (char *) alloca (strlen (main_input_filename) + 1);
923:
924: p = main_input_filename;
925: q = global_object_name;
926:
927: /* Replace any weird characters in the file name. */
928: for (; *p; p++)
929: if (! ((*p >= '0' && *p <= '9')
930: || (*p >= 'A' && *p <= 'Z')
931: || (*p >= 'a' && *p <= 'z')))
932: *q++ = '_';
933: else
934: *q++ = *p;
935: *q = 0;
936: }
937:
938: /* Make the constructor name from the name we have found. */
939: buf = (char *) xmalloc (sizeof (CONSTRUCTOR_NAME_FORMAT)
940: + strlen (global_object_name));
941: sprintf (buf, CONSTRUCTOR_NAME_FORMAT, global_object_name);
942:
943: /* Declare void __objc_execClass (void*); */
944:
945: void_list_node = build_tree_list (NULL_TREE, void_type_node);
946: function_type
947: = build_function_type (void_type_node,
948: tree_cons (NULL_TREE, ptr_type_node,
949: void_list_node));
950: function_decl = build_decl (FUNCTION_DECL,
951: get_identifier ("__objc_execClass"),
952: function_type);
1.1.1.4 ! root 953: DECL_EXTERNAL (function_decl) = 1;
1.1 root 954: TREE_PUBLIC (function_decl) = 1;
955: pushdecl (function_decl);
956: rest_of_decl_compilation (function_decl, 0, 0, 0);
957:
958: parms
959: = build_tree_list (NULLT,
960: build_unary_op (ADDR_EXPR, _OBJC_MODULES_decl, 0));
961: decelerator = build_function_call (function_decl, parms);
962:
963: /* void __objc_file_init () {objc_execClass(&L_OBJC_MODULES);} */
964:
965: start_function (void_list_node,
966: build_parse_node (CALL_EXPR, get_identifier (buf),
967: /* This has the format of the output
968: of get_parm_info. */
969: tree_cons (NULL_TREE, NULL_TREE,
970: void_list_node),
971: NULL_TREE),
972: 0, 0);
973: #if 0 /* This should be turned back on later
974: for the systems where collect is not needed. */
975: /* Make these functions nonglobal
976: so each file can use the same name. */
977: TREE_PUBLIC (current_function_decl) = 0;
978: #endif
979: TREE_USED (current_function_decl) = 1;
980: store_parm_decls ();
981:
982: assemble_external (function_decl);
983: c_expand_expr_stmt (decelerator);
984:
985: finish_function (0);
986:
987: /* Return the name of the constructor function. */
988: return buf;
989: }
990: #else /* NEXT_OBJC_RUNTIME */
991: return 0;
992: #endif /* NEXT_OBJC_RUNTIME */
993: }
994:
995: /* extern const char _OBJC_STRINGS[]; */
996:
997: static void
998: generate_forward_declaration_to_string_table ()
999: {
1000: tree sc_spec, decl_specs, expr_decl;
1001:
1002: sc_spec = tree_cons (NULLT, ridpointers[(int) RID_EXTERN], NULLT);
1003: decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1004:
1005: expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
1006:
1007: _OBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1008: }
1009:
1010: /* static char _OBJC_STRINGS[] = "..."; */
1011:
1012: static void
1013: build_message_selector_pool ()
1014: {
1015: tree sc_spec, decl_specs, expr_decl;
1016: tree chain, string_expr;
1017: int goolengthtmp = 0, msg_pool_size = 0;
1018: char *string_goo;
1019:
1020: sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1021: decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
1022:
1023: expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
1024:
1025: _OBJC_STRINGS_decl = start_decl (expr_decl, decl_specs, 1);
1026:
1027: for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
1028: msg_pool_size += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1029:
1030: msg_pool_size++;
1031:
1032: string_goo = (char *)xmalloc (msg_pool_size);
1033: bzero (string_goo, msg_pool_size);
1034:
1035: for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
1036: {
1037: strcpy (string_goo + goolengthtmp, IDENTIFIER_POINTER (TREE_VALUE (chain)));
1038: goolengthtmp += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1039: }
1040:
1041: string_expr = my_build_string (msg_pool_size, string_goo);
1042:
1043: finish_decl (_OBJC_STRINGS_decl, string_expr, NULLT);
1044: }
1045:
1046: /*
1047: * synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
1048: *
1049: * the cast stops the compiler from issuing the following message:
1050: *
1051: * grok.m: warning: initialization of non-const * pointer from const *
1052: * grok.m: warning: initialization between incompatible pointer types
1053: */
1054: static tree
1055: build_msg_pool_reference (offset)
1056: int offset;
1057: {
1058: tree expr = build_int_2 (offset, 0);
1059: tree cast;
1060:
1061: expr = build_array_ref (_OBJC_STRINGS_decl, expr);
1062: expr = build_unary_op (ADDR_EXPR, expr, 0);
1063:
1064: cast = build_tree_list (build_tree_list (NULLT, ridpointers[(int) RID_CHAR]),
1065: build1 (INDIRECT_REF, NULLT, NULLT));
1066: TREE_TYPE (expr) = groktypename (cast);
1067: return expr;
1068: }
1069:
1.1.1.3 root 1070: #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 1071: static tree
1072: build_selector_reference (idx)
1073: int idx;
1074: {
1075: tree ref, decl, name, ident;
1076: char buf[256];
1077: struct obstack *save_current_obstack = current_obstack;
1078: struct obstack *save_rtl_obstack = rtl_obstack;
1079:
1080: sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
1081:
1082: /* new stuff */
1083: rtl_obstack = current_obstack = &permanent_obstack;
1084: ident = get_identifier (buf);
1085:
1086: if (IDENTIFIER_GLOBAL_VALUE (ident))
1087: decl = IDENTIFIER_GLOBAL_VALUE (ident); /* set by pushdecl() */
1088: else
1089: {
1.1.1.2 root 1090: decl = build_decl (VAR_DECL, ident, selector_type);
1.1.1.4 ! root 1091: DECL_EXTERNAL (decl) = 1;
1.1 root 1092: TREE_PUBLIC (decl) = 1;
1093: TREE_USED (decl) = 1;
1094:
1095: make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
1096: pushdecl_top_level (decl); /* our `extended/custom' pushdecl in c-decl.c */
1097: }
1098: current_obstack = save_current_obstack;
1099: rtl_obstack = save_rtl_obstack;
1100:
1101: return decl;
1102: }
1103: #endif
1104:
1105: static tree
1106: init_selector (offset)
1107: int offset;
1108: {
1109: tree expr = build_msg_pool_reference (offset);
1.1.1.2 root 1110: TREE_TYPE (expr) = selector_type; /* cast */
1.1 root 1111: return expr;
1112: }
1113:
1114: static void
1115: build_selector_translation_table ()
1116: {
1117: tree sc_spec, decl_specs, expr_decl;
1118: tree chain, initlist = NULLT;
1119: int offset = 0;
1.1.1.3 root 1120: #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 1121: tree decl, var_decl;
1122: int idx = 0;
1123: char buf[256];
1.1.1.2 root 1124: #else
1125: /* The corresponding pop_obstacks is in finish_decl,
1126: called at the end of this function. */
1127: push_obstacks_nochange ();
1.1 root 1128: #endif
1129:
1130: for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1131: {
1132: tree expr;
1133:
1.1.1.3 root 1134: #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 1135: sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
1.1.1.2 root 1136: sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
1.1 root 1137:
1.1.1.2 root 1138: /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
1139: decl_specs = tree_cons (NULLT, selector_type, sc_spec);
1.1 root 1140: var_decl = get_identifier (buf);
1141:
1142: /* the `decl' that is returned from start_decl is the one that we
1143: * forward declared in `build_selector_reference()'
1144: */
1145: decl = start_decl (var_decl, decl_specs, 1);
1146: #endif
1147:
1148: expr = init_selector (offset);
1149:
1150: /* add one for the '\0' character */
1151: offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1152:
1.1.1.3 root 1153: #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 1154: finish_decl (decl, expr, NULLT);
1155: idx++;
1156: #else
1157: initlist = tree_cons (NULLT, expr, initlist);
1158: #endif
1159: }
1160:
1.1.1.3 root 1161: #ifdef OBJC_SELECTORS_WITHOUT_LABELS
1.1.1.4 ! root 1162: /* Cause the variable and its initial value to be actually output. */
! 1163: DECL_EXTERNAL (_OBJC_SELECTOR_REFERENCES_decl) = 0;
! 1164: TREE_STATIC (_OBJC_SELECTOR_REFERENCES_decl) = 1;
! 1165: /* NULL terminate the list and fix the decl for output. */
! 1166: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
1.1.1.2 root 1167: DECL_INITIAL (_OBJC_SELECTOR_REFERENCES_decl) = (tree) 1;
1.1 root 1168: initlist = build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1169: finish_decl (_OBJC_SELECTOR_REFERENCES_decl, initlist, NULLT);
1170: #endif
1171: }
1172:
1173: static void
1174: add_class_reference (ident)
1175: tree ident;
1176: {
1177: tree chain;
1178:
1179: if (chain = cls_ref_chain)
1180: {
1181: tree tail;
1182: do
1183: {
1184: if (ident == TREE_VALUE (chain))
1185: return;
1186:
1187: tail = chain;
1188: chain = TREE_CHAIN (chain);
1189: }
1190: while (chain);
1191:
1192: /* append to the end of the list */
1193: TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1194: }
1195: else
1196: cls_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
1197: }
1198:
1199: /*
1200: * sel_ref_chain is a list whose "value" fields will be instances of
1201: * identifier_node that represent the selector.
1202: */
1203: static int
1204: add_selector_reference (ident)
1205: tree ident;
1206: {
1207: tree chain;
1208: int index = 0;
1209:
1210: /* this adds it to sel_refdef_chain, the global pool of selectors */
1211: add_objc_string (ident);
1212:
1213: if (chain = sel_ref_chain)
1214: {
1215: tree tail;
1216: do
1217: {
1218: if (ident == TREE_VALUE (chain))
1219: return index;
1220:
1221: index++;
1222: tail = chain;
1223: chain = TREE_CHAIN (chain);
1224: }
1225: while (chain);
1226:
1227: /* append to the end of the list */
1228: TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1229: }
1230: else
1231: sel_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
1232:
1233: max_selector_index++;
1234: return index;
1235: }
1236:
1237: /*
1238: * sel_refdef_chain is a list whose "value" fields will be instances of
1239: * identifier_node that represent the selector. It returns the offset of
1240: * the selector from the beginning of the _OBJC_STRINGS pool. This offset
1241: * is typically used by "init_selector ()" during code generation.
1242: */
1243: static int
1244: add_objc_string (ident)
1245: tree ident;
1246: {
1247: tree chain;
1248: int offset = 0;
1249:
1250: if (chain = sel_refdef_chain)
1251: {
1252: tree tail;
1253: do
1254: {
1255: if (ident == TREE_VALUE (chain))
1256: return offset;
1257:
1258: /* add one for the '\0' character */
1259: offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
1260: tail = chain;
1261: chain = TREE_CHAIN (chain);
1262: }
1263: while (chain);
1264:
1265: /* append to the end of the list */
1266: TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
1267: }
1268: else
1269: sel_refdef_chain = perm_tree_cons (NULLT, ident, NULLT);
1270:
1271: return offset;
1272: }
1273:
1274: tree
1275: lookup_interface (ident)
1276: tree ident;
1277: {
1278: tree chain;
1279:
1280: for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
1281: {
1282: if (ident == CLASS_NAME (chain))
1283: return chain;
1284: }
1285: return NULLT;
1286: }
1287:
1288: static tree
1289: objc_copy_list (list, head)
1290: tree list;
1291: tree *head;
1292: {
1293: tree newlist = NULL_TREE, tail = NULL_TREE;
1294:
1295: while (list)
1296: {
1297: tail = copy_node (list);
1298:
1299: /* the following statement fixes a bug when inheriting instance
1300: variables that are declared to be bitfields. finish_struct () expects
1301: to find the width of the bitfield in DECL_INITIAL (), which it
1302: nulls out after processing the decl of the super class...rather
1303: than change the way finish_struct () works (which is risky),
1304: I create the situation it expects...s.naroff (7/23/89).
1305: */
1306: if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
1.1.1.3 root 1307: DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
1.1 root 1308:
1309: newlist = chainon (newlist, tail);
1310: list = TREE_CHAIN (list);
1311: }
1312: *head = newlist;
1313: return tail;
1314: }
1315:
1316: /* used by:
1317: * build_private_template (), get_class_ivars (), and get_static_reference ().
1318: */
1319: static tree
1320: build_ivar_chain (interface)
1321: tree interface;
1322: {
1323: tree my_name, super_name, ivar_chain;
1324:
1325: my_name = CLASS_NAME (interface);
1326: super_name = CLASS_SUPER_NAME (interface);
1327:
1328: /* "leaf" ivars never get copied...there is no reason to. */
1329: ivar_chain = CLASS_IVARS (interface);
1330:
1331: while (super_name)
1332: {
1333: tree op1;
1334: tree super_interface = lookup_interface (super_name);
1335:
1336: if (!super_interface)
1337: {
1338: /* fatal did not work with 2 args...should fix */
1339: error ("Cannot find interface declaration for `%s', superclass of `%s'",
1340: IDENTIFIER_POINTER (super_name), IDENTIFIER_POINTER (my_name));
1341: exit (34);
1342: }
1343: if (super_interface == interface)
1344: {
1345: fatal ("Circular inheritance in interface declaration for `%s'",
1346: IDENTIFIER_POINTER (super_name));
1347: }
1348: interface = super_interface;
1349: my_name = CLASS_NAME (interface);
1350: super_name = CLASS_SUPER_NAME (interface);
1351:
1352: op1 = CLASS_IVARS (interface);
1353: if (op1)
1354: {
1355: tree head, tail = objc_copy_list (op1, &head);
1356:
1357: /* prepend super class ivars...make a copy of the list, we
1358: * do not want to alter the original.
1359: */
1360: TREE_CHAIN (tail) = ivar_chain;
1361: ivar_chain = head;
1362: }
1363: }
1364: return ivar_chain;
1365: }
1366:
1367: /*
1368: * struct <classname> {
1369: * struct objc_class *isa;
1370: * ...
1371: * };
1372: */
1373: static tree
1374: build_private_template (class)
1375: tree class;
1376: {
1377: tree ivar_context;
1378:
1379: if (CLASS_STATIC_TEMPLATE (class))
1380: {
1381: _PRIVATE_record = CLASS_STATIC_TEMPLATE (class);
1382: ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
1383: }
1384: else
1385: {
1386: _PRIVATE_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
1387:
1388: ivar_context = build_ivar_chain (class);
1389:
1390: finish_struct (_PRIVATE_record, ivar_context);
1391:
1392: CLASS_STATIC_TEMPLATE (class) = _PRIVATE_record;
1393:
1394: /* mark this record as class template - for class type checking */
1395: TREE_STATIC_TEMPLATE (_PRIVATE_record) = 1;
1396: }
1397: instance_type = groktypename (
1398: build_tree_list (build_tree_list (NULLT, _PRIVATE_record),
1399: build1 (INDIRECT_REF, NULLT, NULLT)));
1400: return ivar_context;
1401: }
1402:
1403: /*
1404: * struct objc_category {
1405: * char *category_name;
1406: * char *class_name;
1407: * struct objc_method_list *instance_methods;
1408: * struct objc_method_list *class_methods;
1409: * };
1410: */
1411: static void
1412: build_category_template ()
1413: {
1414: tree decl_specs, field_decl, field_decl_chain;
1415:
1416: objc_category_template = start_struct (RECORD_TYPE,
1417: get_identifier (_TAG_CATEGORY));
1418: /* char *category_name; */
1419:
1420: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1421: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("category_name"));
1422: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1423: field_decl_chain = field_decl;
1424:
1425: /* char *class_name; */
1426:
1427: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1428: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_name"));
1429: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1430: chainon (field_decl_chain, field_decl);
1431:
1432: /* struct objc_method_list *instance_methods; */
1433:
1434: decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1435: get_identifier (_TAG_METHOD_LIST)));
1436: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
1437: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1438: chainon (field_decl_chain, field_decl);
1439:
1440: /* struct objc_method_list *class_methods; */
1441:
1442: decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1443: get_identifier (_TAG_METHOD_LIST)));
1444: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
1445: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1446: chainon (field_decl_chain, field_decl);
1447:
1448: finish_struct (objc_category_template, field_decl_chain);
1449: }
1450:
1451: /*
1452: * struct objc_class {
1453: * struct objc_class *isa;
1454: * struct objc_class *super_class;
1455: * char *name;
1456: * long version;
1457: * long info;
1458: * long instance_size;
1459: * struct objc_ivar_list *ivars;
1460: * struct objc_method_list *methods;
1461: * struct objc_cache *cache;
1462: * };
1463: */
1464: static void
1465: build_class_template ()
1466: {
1467: tree decl_specs, field_decl, field_decl_chain;
1468:
1469: objc_class_template = start_struct (RECORD_TYPE, get_identifier (_TAG_CLASS));
1470:
1471: /* struct objc_class *isa; */
1472:
1473: decl_specs = build_tree_list (NULLT, objc_class_template);
1474: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
1475: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1476: field_decl_chain = field_decl;
1477:
1478: /* struct objc_class *super_class; */
1479:
1480: decl_specs = build_tree_list (NULLT, objc_class_template);
1481: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("super_class"));
1482: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1483: chainon (field_decl_chain, field_decl);
1484:
1485: /* char *name; */
1486:
1487: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1488: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
1489: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1490: chainon (field_decl_chain, field_decl);
1491:
1492: /* long version; */
1493:
1494: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1495: field_decl = get_identifier ("version");
1496: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1497: chainon (field_decl_chain, field_decl);
1498:
1499: /* long info; */
1500:
1501: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1502: field_decl = get_identifier ("info");
1503: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1504: chainon (field_decl_chain, field_decl);
1505:
1506: /* long instance_size; */
1507:
1508: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
1509: field_decl = get_identifier ("instance_size");
1510: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1511: chainon (field_decl_chain, field_decl);
1512:
1513: /* struct objc_ivar_list *ivars; */
1514:
1515: decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1516: get_identifier (_TAG_IVAR_LIST)));
1517: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivars"));
1518: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1519: chainon (field_decl_chain, field_decl);
1520:
1521: /* struct objc_method_list *methods; */
1522:
1523: decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1524: get_identifier (_TAG_METHOD_LIST)));
1525: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("methods"));
1526: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1527: chainon (field_decl_chain, field_decl);
1528:
1529: /* struct objc_cache *cache; */
1530:
1531: decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1532: get_identifier ("objc_cache")));
1533: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("cache"));
1534: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1535: chainon (field_decl_chain, field_decl);
1536:
1537: finish_struct (objc_class_template, field_decl_chain);
1538: }
1539:
1540: /*
1541: * generate appropriate forward declarations for an implementation
1542: */
1543: static void
1544: synth_forward_declarations ()
1545: {
1546: tree sc_spec, decl_specs, factory_id, anId;
1547:
1548: /* extern struct objc_class _OBJC_CLASS_<my_name>; */
1549:
1550: anId = synth_id_with_class_suffix ("_OBJC_CLASS");
1551:
1552: sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
1553: decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
1554: _OBJC_CLASS_decl = define_decl (anId, decl_specs);
1555:
1556: /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
1557:
1558: anId = synth_id_with_class_suffix ("_OBJC_METACLASS");
1559:
1560: _OBJC_METACLASS_decl = define_decl (anId, decl_specs);
1561:
1562: /* pre-build the following entities - for speed/convenience. */
1563:
1564: anId = get_identifier ("super_class");
1565: _clsSuper_ref = build_component_ref (_OBJC_CLASS_decl, anId);
1566: __clsSuper_ref = build_component_ref (_OBJC_METACLASS_decl, anId);
1567: }
1568:
1569: static void
1570: error_with_ivar (message, decl, rawdecl)
1571: char *message;
1572: tree decl;
1573: tree rawdecl;
1574: {
1575: count_error (0);
1576: fprintf (stderr, "%s:%d: ",
1577: DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
1578: bzero (errbuf, BUFSIZE);
1579: fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
1580: }
1581:
1582: #define USERTYPE(t) (TREE_CODE (t) == RECORD_TYPE || \
1583: TREE_CODE (t) == UNION_TYPE || \
1584: TREE_CODE (t) == ENUMERAL_TYPE)
1585:
1586: static void
1587: check_ivars (inter, imp)
1588: tree inter;
1589: tree imp;
1590: {
1591: tree intdecls = CLASS_IVARS (inter);
1592: tree impdecls = CLASS_IVARS (imp);
1593: tree rawintdecls = CLASS_RAW_IVARS (inter);
1594: tree rawimpdecls = CLASS_RAW_IVARS (imp);
1595:
1596: while (1)
1597: {
1598: tree t1, t2;
1599:
1600: if (intdecls == 0 && impdecls == 0)
1601: break;
1602: if (intdecls == 0 || impdecls == 0)
1603: {
1604: error ("inconsistent instance variable specification");
1605: break;
1606: }
1607: t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
1608:
1609: if (!comptypes (t1, t2))
1610: {
1611: if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
1612: {
1613: error_with_ivar ("conflicting instance variable type",
1614: impdecls, rawimpdecls);
1615: error_with_ivar ("previous declaration of",
1616: intdecls, rawintdecls);
1617: }
1618: else /* both the type and the name don't match */
1619: {
1620: error ("inconsistent instance variable specification");
1621: break;
1622: }
1623: }
1624: else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
1625: {
1626: error_with_ivar ("conflicting instance variable name",
1627: impdecls, rawimpdecls);
1628: error_with_ivar ("previous declaration of",
1629: intdecls, rawintdecls);
1630: }
1631: intdecls = TREE_CHAIN (intdecls);
1632: impdecls = TREE_CHAIN (impdecls);
1633: rawintdecls = TREE_CHAIN (rawintdecls);
1634: rawimpdecls = TREE_CHAIN (rawimpdecls);
1635: }
1636: }
1637:
1.1.1.4 ! root 1638: /* Set super_type to the data type node for struct objc_super *,
! 1639: first defining struct objc_super itself.
! 1640: This needs to be done just once per compilation. */
! 1641:
1.1 root 1642: static tree
1643: build_super_template ()
1644: {
1645: tree record, decl_specs, field_decl, field_decl_chain;
1646:
1647: record = start_struct (RECORD_TYPE, get_identifier (_TAG_SUPER));
1648:
1649: /* struct objc_object *self; */
1650:
1651: decl_specs = build_tree_list (NULLT, objc_object_reference);
1652: field_decl = get_identifier ("self");
1653: field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
1654: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1655: field_decl_chain = field_decl;
1656:
1657: /* struct objc_class *class; */
1658:
1659: decl_specs = get_identifier (_TAG_CLASS);
1660: decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
1661: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class"));
1662:
1663: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1664: chainon (field_decl_chain, field_decl);
1665:
1666: finish_struct (record, field_decl_chain);
1667:
1668: /* `struct objc_super *' */
1669: super_type = groktypename (build_tree_list (build_tree_list (NULLT, record),
1670: build1 (INDIRECT_REF, NULLT, NULLT)));
1671: return record;
1672: }
1673:
1674: /*
1675: * struct objc_ivar {
1676: * char *ivar_name;
1677: * char *ivar_type;
1678: * int ivar_offset;
1679: * };
1680: */
1681: static tree
1682: build_ivar_template ()
1683: {
1684: tree objc_ivar_id, objc_ivar_record;
1685: tree decl_specs, field_decl, field_decl_chain;
1686:
1687: objc_ivar_id = get_identifier (_TAG_IVAR);
1688: objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
1689:
1690: /* char *ivar_name; */
1691:
1692: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1693: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_name"));
1694:
1695: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1696: field_decl_chain = field_decl;
1697:
1698: /* char *ivar_type; */
1699:
1700: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
1701: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_type"));
1702:
1703: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1704: chainon (field_decl_chain, field_decl);
1705:
1706: /* int ivar_offset; */
1707:
1708: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1709: field_decl = get_identifier ("ivar_offset");
1710:
1711: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1712: chainon (field_decl_chain, field_decl);
1713:
1714: finish_struct (objc_ivar_record, field_decl_chain);
1715:
1716: return objc_ivar_record;
1717: }
1718:
1719: /*
1720: * struct {
1721: * int ivar_count;
1722: * struct objc_ivar ivar_list[ivar_count];
1723: * };
1724: */
1725: static tree
1726: build_ivar_list_template (list_type, size)
1727: tree list_type;
1728: int size;
1729: {
1730: tree objc_ivar_list_id, objc_ivar_list_record;
1731: tree decl_specs, field_decl, field_decl_chain;
1732:
1733: objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
1734:
1735: /* int ivar_count; */
1736:
1737: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1738: field_decl = get_identifier ("ivar_count");
1739:
1740: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1741: field_decl_chain = field_decl;
1742:
1743: /* struct objc_ivar ivar_list[]; */
1744:
1745: decl_specs = build_tree_list (NULLT, list_type);
1746: field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
1747: build_int_2 (size, 0));
1748:
1749: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1750: chainon (field_decl_chain, field_decl);
1751:
1752: finish_struct (objc_ivar_list_record, field_decl_chain);
1753:
1754: return objc_ivar_list_record;
1755: }
1756:
1757: /*
1758: * struct {
1759: * int method_next;
1760: * int method_count;
1761: * struct objc_method method_list[method_count];
1762: * };
1763: */
1764: static tree
1765: build_method_list_template (list_type, size)
1766: tree list_type;
1767: int size;
1768: {
1769: tree objc_ivar_list_id, objc_ivar_list_record;
1770: tree decl_specs, field_decl, field_decl_chain;
1771:
1772: objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
1773:
1774: /* int method_next; */
1775:
1776: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1777: field_decl = get_identifier ("method_next");
1778:
1779: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1780: field_decl_chain = field_decl;
1781:
1782: /* int method_count; */
1783:
1784: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
1785: field_decl = get_identifier ("method_count");
1786:
1787: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1788: chainon (field_decl_chain, field_decl);
1789:
1790: /* struct objc_method method_list[]; */
1791:
1792: decl_specs = build_tree_list (NULLT, list_type);
1793: field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
1794: build_int_2 (size, 0));
1795:
1796: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1797: chainon (field_decl_chain, field_decl);
1798:
1799: finish_struct (objc_ivar_list_record, field_decl_chain);
1800:
1801: return objc_ivar_list_record;
1802: }
1803:
1804: static tree
1805: build_ivar_list_initializer (field_decl, size)
1806: tree field_decl;
1807: int *size;
1808: {
1809: tree initlist = NULLT;
1810:
1811: do
1812: {
1813: int offset;
1814:
1815: /* set name */
1816: if (DECL_NAME (field_decl))
1817: {
1818: offset = add_objc_string (DECL_NAME (field_decl));
1819: initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1820: }
1821: else
1822: {
1823: /* unnamed bit-field ivar (yuck). */
1824: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
1825: }
1826:
1827: /* set type */
1.1.1.3 root 1828: encode_field_decl (field_decl, OBJC_ENCODE_DONT_INLINE_DEFS);
1829: offset = add_objc_string (get_identifier (obstack_finish (&util_obstack)));
1830: obstack_free (&util_obstack, util_firstobj);
1.1 root 1831:
1832: initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1833:
1834: /* set offset */
1835: initlist = tree_cons (NULLT,
1836: build_int_2 (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)) / BITS_PER_UNIT, 0),
1837:
1838: initlist);
1839: (*size)++;
1840: field_decl = TREE_CHAIN (field_decl);
1841: }
1842: while (field_decl);
1843:
1844: return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1845: }
1846:
1847: static tree
1848: generate_ivars_list (type, name, size, list)
1849: tree type;
1850: char *name;
1851: int size;
1852: tree list;
1853: {
1854: tree sc_spec, decl_specs, decl, initlist;
1855:
1856: sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
1857: decl_specs = tree_cons (NULLT, type, sc_spec);
1858:
1859: decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
1860:
1861: initlist = build_tree_list (NULLT, build_int_2 (size, 0));
1862: initlist = tree_cons (NULLT, list, initlist);
1863:
1864: finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
1865:
1866: return decl;
1867: }
1868:
1869: static void
1870: generate_ivar_lists ()
1871: {
1872: tree initlist, ivar_list_template, chain;
1873: tree cast, variable_length_type;
1874: int size;
1875:
1876: if (!objc_ivar_template)
1877: objc_ivar_template = build_ivar_template ();
1878:
1879: cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
1880: get_identifier (_TAG_IVAR_LIST))), NULLT);
1881: variable_length_type = groktypename (cast);
1882:
1883: /* only generate class variables for the root of the inheritance
1884: hierarchy since these will be the same for every class */
1885:
1886: if (CLASS_SUPER_NAME (implementation_template) == NULLT
1887: && (chain = TYPE_FIELDS (objc_class_template)))
1888: {
1889: size = 0;
1890: initlist = build_ivar_list_initializer (chain, &size);
1891:
1892: ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1893:
1894: _OBJC_CLASS_VARIABLES_decl =
1895: generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
1896: size, initlist);
1897: /* cast! */
1898: TREE_TYPE (_OBJC_CLASS_VARIABLES_decl) = variable_length_type;
1899: }
1900: else
1901: _OBJC_CLASS_VARIABLES_decl = 0;
1902:
1903: chain = CLASS_IVARS (implementation_template);
1904: if (chain)
1905: {
1906: size = 0;
1907: initlist = build_ivar_list_initializer (chain, &size);
1908:
1909: ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1910:
1911: _OBJC_INSTANCE_VARIABLES_decl =
1912: generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
1913: size, initlist);
1914: /* cast! */
1915: TREE_TYPE (_OBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
1916: }
1917: else
1918: _OBJC_INSTANCE_VARIABLES_decl = 0;
1919: }
1920:
1921: static tree
1922: build_dispatch_table_initializer (entries, size)
1923: tree entries;
1924: int *size;
1925: {
1926: tree initlist = NULLT;
1927:
1928: do
1929: {
1930: int offset = add_objc_string (METHOD_SEL_NAME (entries));
1931:
1932: initlist = tree_cons (NULLT, init_selector (offset), initlist);
1933:
1934: offset = add_objc_string (METHOD_ENCODING (entries));
1935: initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
1936:
1937: initlist = tree_cons (NULLT, METHOD_DEFINITION (entries), initlist);
1938:
1939: (*size)++;
1940: entries = TREE_CHAIN (entries);
1941: }
1942: while (entries);
1943:
1944: return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
1945: }
1946:
1947: /*
1948: * To accomplish method prototyping without generating all kinds of
1949: * inane warnings, the definition of the dispatch table entries were
1950: * changed from:
1951: *
1952: * struct objc_method { SEL _cmd; id (*_imp)(); };
1953: * to:
1954: * struct objc_method { SEL _cmd; void *_imp; };
1955: */
1956: static tree
1957: build_method_template ()
1958: {
1959: tree _SLT_record;
1960: tree decl_specs, field_decl, field_decl_chain, parms;
1961:
1962: _SLT_record = start_struct (RECORD_TYPE, get_identifier (_TAG_METHOD));
1963:
1964: #ifdef OBJC_INT_SELECTORS
1965: /* unsigned int _cmd; */
1966: decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
1967: decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
1968: field_decl = get_identifier ("_cmd");
1969: #else /* not OBJC_INT_SELECTORS */
1970: /* struct objc_selector *_cmd; */
1971: decl_specs = tree_cons (NULLT,
1972: xref_tag (RECORD_TYPE,
1973: get_identifier (TAG_SELECTOR)),
1974: NULLT);
1975: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
1976: #endif /* not OBJC_INT_SELECTORS */
1977:
1978: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1979: field_decl_chain = field_decl;
1980:
1981: decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
1982: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
1983: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1984: chainon (field_decl_chain, field_decl);
1985:
1986: /* void *_imp; */
1987:
1988: decl_specs = tree_cons (NULLT, ridpointers[(int) RID_VOID], NULLT);
1989: field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_imp"));
1990: field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
1991: chainon (field_decl_chain, field_decl);
1992:
1993: finish_struct (_SLT_record, field_decl_chain);
1994:
1995: return _SLT_record;
1996: }
1997:
1998:
1999: static tree
2000: generate_dispatch_table (type, name, size, list)
2001: tree type;
2002: char *name;
2003: int size;
2004: tree list;
2005: {
2006: tree sc_spec, decl_specs, decl, initlist;
2007:
2008: sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
2009: decl_specs = tree_cons (NULLT, type, sc_spec);
2010:
2011: decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
2012:
2013: initlist = build_tree_list (NULLT, build_int_2 (0, 0));
2014: initlist = tree_cons (NULLT, build_int_2 (size, 0), initlist);
2015: initlist = tree_cons (NULLT, list, initlist);
2016:
2017: finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
2018:
2019: return decl;
2020: }
2021:
2022: static void
2023: generate_dispatch_tables ()
2024: {
2025: tree initlist, chain, method_list_template;
2026: tree cast, variable_length_type;
2027: int size;
2028:
2029: if (!objc_method_template)
2030: objc_method_template = build_method_template ();
2031:
2032: cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
2033: get_identifier (_TAG_METHOD_LIST))), NULLT);
2034: variable_length_type = groktypename (cast);
2035:
2036: chain = CLASS_CLS_METHODS (implementation_context);
2037: if (chain)
2038: {
2039: size = 0;
2040: initlist = build_dispatch_table_initializer (chain, &size);
2041:
2042: method_list_template = build_method_list_template (objc_method_template,
2043: size);
2044: if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
2045: _OBJC_CLASS_METHODS_decl =
2046: generate_dispatch_table (method_list_template,
2047: "_OBJC_CLASS_METHODS",
2048: size, initlist);
2049: else
2050: /* we have a category */
2051: _OBJC_CLASS_METHODS_decl =
2052: generate_dispatch_table (method_list_template,
2053: "_OBJC_CATEGORY_CLASS_METHODS",
2054: size, initlist);
2055: /* cast! */
2056: TREE_TYPE (_OBJC_CLASS_METHODS_decl) = variable_length_type;
2057: }
2058: else
2059: _OBJC_CLASS_METHODS_decl = 0;
2060:
2061: chain = CLASS_NST_METHODS (implementation_context);
2062: if (chain)
2063: {
2064: size = 0;
2065: initlist = build_dispatch_table_initializer (chain, &size);
2066:
2067: method_list_template = build_method_list_template (objc_method_template,
2068: size);
2069: if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
2070: _OBJC_INSTANCE_METHODS_decl =
2071: generate_dispatch_table (method_list_template,
2072: "_OBJC_INSTANCE_METHODS",
2073: size, initlist);
2074: else
2075: /* we have a category */
2076: _OBJC_INSTANCE_METHODS_decl =
2077: generate_dispatch_table (method_list_template,
2078: "_OBJC_CATEGORY_INSTANCE_METHODS",
2079: size, initlist);
2080: /* cast! */
2081: TREE_TYPE (_OBJC_INSTANCE_METHODS_decl) = variable_length_type;
2082: }
2083: else
2084: _OBJC_INSTANCE_METHODS_decl = 0;
2085: }
2086:
2087: static tree
2088: build_category_initializer (cat_name, class_name,
2089: instance_methods, class_methods)
2090: tree cat_name;
2091: tree class_name;
2092: tree instance_methods;
2093: tree class_methods;
2094: {
2095: tree initlist = NULLT, expr;
2096:
2097: initlist = tree_cons (NULLT, cat_name, initlist);
2098: initlist = tree_cons (NULLT, class_name, initlist);
2099:
2100: if (!instance_methods)
2101: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2102: else
2103: {
2104: expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
2105: initlist = tree_cons (NULLT, expr, initlist);
2106: }
2107: if (!class_methods)
2108: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2109: else
2110: {
2111: expr = build_unary_op (ADDR_EXPR, class_methods, 0);
2112: initlist = tree_cons (NULLT, expr, initlist);
2113: }
2114: return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
2115: }
2116:
2117: /*
2118: * struct objc_class {
2119: * struct objc_class *isa;
2120: * struct objc_class *super_class;
2121: * char *name;
2122: * long version;
2123: * long info;
2124: * long instance_size;
2125: * struct objc_ivar_list *ivars;
2126: * struct objc_method_list *methods;
2127: * struct objc_cache *cache;
2128: * };
2129: */
2130: static tree
2131: build_shared_structure_initializer (isa, super, name, size, status,
2132: dispatch_table, ivar_list)
2133: tree isa;
2134: tree super;
2135: tree name;
2136: tree size;
2137: int status;
2138: tree dispatch_table;
2139: tree ivar_list;
2140: {
2141: tree initlist = NULLT, expr;
2142:
2143: /* isa = */
2144: initlist = tree_cons (NULLT, isa, initlist);
2145:
2146: /* super_class = */
2147: initlist = tree_cons (NULLT, super, initlist);
2148:
2149: /* name = */
2150: initlist = tree_cons (NULLT, name, initlist);
2151:
2152: /* version = */
2153: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2154:
2155: /* info = */
1.1.1.4 ! root 2156: initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist);
1.1 root 2157:
2158: /* instance_size = */
2159: initlist = tree_cons (NULLT, size, initlist);
2160:
2161: /* objc_ivar_list = */
2162: if (!ivar_list)
2163: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2164: else
2165: {
2166: expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
2167: initlist = tree_cons (NULLT, expr, initlist);
2168: }
2169:
2170: /* objc_method_list = */
2171: if (!dispatch_table)
2172: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2173: else
2174: {
2175: expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
2176: initlist = tree_cons (NULLT, expr, initlist);
2177: }
2178:
2179: /* method_cache = */
2180: initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
2181:
2182: return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
2183: }
2184:
2185: /*
2186: * static struct objc_category _OBJC_CATEGORY_<name> = { ... };
2187: */
2188: static void
2189: generate_category (cat)
2190: tree cat;
2191: {
2192: tree sc_spec, decl_specs, decl;
2193: tree initlist, cat_name_expr, class_name_expr;
2194: int offset;
2195:
2196: sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
2197: decl_specs = tree_cons (NULLT, objc_category_template, sc_spec);
2198:
2199: decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY"),
2200: decl_specs, 1);
2201:
2202: offset = add_objc_string (CLASS_SUPER_NAME (cat));
2203: cat_name_expr = build_msg_pool_reference (offset);
2204:
2205: offset = add_objc_string (CLASS_NAME (cat));
2206: class_name_expr = build_msg_pool_reference (offset);
2207:
2208: initlist = build_category_initializer (
2209: cat_name_expr, class_name_expr,
2210: _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl);
2211:
2212: finish_decl (decl, initlist, NULLT);
2213: }
2214:
2215: /*
2216: * static struct objc_class _OBJC_METACLASS_Foo={ ... };
2217: * static struct objc_class _OBJC_CLASS_Foo={ ... };
2218: */
2219: static void
2220: generate_shared_structures ()
2221: {
2222: tree sc_spec, decl_specs, expr_decl, decl;
2223: tree name_expr, super_expr, root_expr;
2224: tree my_root_id = NULLT, my_super_id = NULLT;
2225: tree cast_type, initlist;
2226: int offset;
2227:
2228: my_super_id = CLASS_SUPER_NAME (implementation_template);
2229: if (my_super_id)
2230: {
2231: add_class_reference (my_super_id);
2232:
2233: /* compute "my_root_id" - this is required for code generation.
2234: * the "isa" for all meta class structures points to the root of
2235: * the inheritance hierarchy (e.g. "__Object")...
2236: */
2237: my_root_id = my_super_id;
2238: do
2239: {
2240: tree my_root_int = lookup_interface (my_root_id);
2241:
2242: if (my_root_int && CLASS_SUPER_NAME (my_root_int))
2243: my_root_id = CLASS_SUPER_NAME (my_root_int);
2244: else
2245: break;
2246: }
2247: while (1);
2248: }
2249: else /* no super class */
2250: {
2251: my_root_id = CLASS_NAME (implementation_template);
2252: }
2253:
2254: cast_type = groktypename (build_tree_list (build_tree_list (NULLT,
2255: objc_class_template), build1 (INDIRECT_REF, NULLT, NULLT)));
2256:
2257: offset = add_objc_string (CLASS_NAME (implementation_template));
2258: name_expr = build_msg_pool_reference (offset);
2259:
2260: /* install class `isa' and `super' pointers at runtime */
2261: if (my_super_id)
2262: {
2263: offset = add_objc_string (my_super_id);
2264: super_expr = build_msg_pool_reference (offset);
2265: TREE_TYPE (super_expr) = cast_type; /* cast! */
2266: }
2267: else
2268: super_expr = build_int_2 (0, 0);
2269:
2270: offset = add_objc_string (my_root_id);
2271: root_expr = build_msg_pool_reference (offset);
2272: TREE_TYPE (root_expr) = cast_type; /* cast! */
2273:
2274: /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2275:
2276: sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
2277: decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
2278:
2279: decl = start_decl (DECL_NAME (_OBJC_METACLASS_decl), decl_specs, 1);
2280:
2281: initlist = build_shared_structure_initializer (
2282: root_expr, super_expr, name_expr,
2283: build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) / BITS_PER_UNIT, 0),
2284: 2 /*CLS_META*/,
2285: _OBJC_CLASS_METHODS_decl, _OBJC_CLASS_VARIABLES_decl);
2286:
2287: finish_decl (decl, initlist, NULLT);
2288:
2289: /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2290:
2291: decl = start_decl (DECL_NAME (_OBJC_CLASS_decl), decl_specs, 1);
2292:
2293: initlist = build_shared_structure_initializer (
2294: build_unary_op (ADDR_EXPR, _OBJC_METACLASS_decl, 0),
2295: super_expr, name_expr,
2296: build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) / BITS_PER_UNIT, 0),
2297: 1 /*CLS_FACTORY*/,
2298: _OBJC_INSTANCE_METHODS_decl, _OBJC_INSTANCE_VARIABLES_decl);
2299:
2300: finish_decl (decl, initlist, NULLT);
2301: }
2302:
2303: static tree
2304: synth_id_with_class_suffix (preamble)
2305: char *preamble;
2306: {
1.1.1.3 root 2307: char *string;
1.1 root 2308: if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
1.1.1.3 root 2309: {
2310: string = (char *) alloca (strlen (preamble)
2311: + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context)))
2312: + 3);
2313: sprintf (string, "%s_%s", preamble,
2314: IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
2315: }
1.1 root 2316: else
1.1.1.3 root 2317: {
2318: /* we have a category */
2319: string = (char *) alloca (strlen (preamble)
2320: + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context)))
2321: + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)))
2322: + 3);
2323: sprintf (string, "%s_%s_%s", preamble,
2324: IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
2325: IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
2326: }
2327: return get_identifier (string);
1.1 root 2328: }
2329:
2330: /*
2331: * usage:
2332: * keyworddecl:
2333: * selector ':' '(' typename ')' identifier
2334: *
2335: * purpose:
2336: * transform an Objective-C keyword argument into
2337: * the C equivalent parameter declarator.
2338: *
2339: * in: key_name, an "identifier_node" (optional).
2340: * arg_type, a "tree_list" (optional).
2341: * arg_name, an "identifier_node".
2342: *
2343: * note: it would be really nice to strongly type the preceding
2344: * arguments in the function prototype; however, then i
2345: * could not use the "accessor" macros defined in "tree.h".
2346: *
2347: * out: an instance of "keyword_decl".
2348: *
2349: */
2350:
2351: tree
2352: build_keyword_decl (key_name, arg_type, arg_name)
2353: tree key_name;
2354: tree arg_type;
2355: tree arg_name;
2356: {
2357: tree keyword_decl;
2358:
2359: /* if no type is specified, default to "id" */
2360: if (arg_type == NULLT)
2361: arg_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
2362: build1 (INDIRECT_REF, NULLT, NULLT));
2363:
2364: keyword_decl = make_node (KEYWORD_DECL);
2365:
2366: TREE_TYPE (keyword_decl) = arg_type;
2367: KEYWORD_ARG_NAME (keyword_decl) = arg_name;
2368: KEYWORD_KEY_NAME (keyword_decl) = key_name;
2369:
2370: return keyword_decl;
2371: }
2372:
2373: /*
2374: * given a chain of keyword_decl's, synthesize the full keyword selector.
2375: */
2376: static tree
2377: build_keyword_selector (selector)
2378: tree selector;
2379: {
2380: int len = 0;
2381: tree key_chain, key_name;
2382: char *buf;
2383:
2384: for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
2385: {
2386: if (TREE_CODE (selector) == KEYWORD_DECL)
2387: key_name = KEYWORD_KEY_NAME (key_chain);
2388: else if (TREE_CODE (selector) == TREE_LIST)
2389: key_name = TREE_PURPOSE (key_chain);
2390:
2391: if (key_name)
2392: len += IDENTIFIER_LENGTH (key_name) + 1;
2393: else /* just a ':' arg */
2394: len++;
2395: }
2396: buf = (char *)alloca (len + 1);
2397: bzero (buf, len + 1);
2398:
2399: for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
2400: {
2401: if (TREE_CODE (selector) == KEYWORD_DECL)
2402: key_name = KEYWORD_KEY_NAME (key_chain);
2403: else if (TREE_CODE (selector) == TREE_LIST)
2404: key_name = TREE_PURPOSE (key_chain);
2405:
2406: if (key_name)
2407: strcat (buf, IDENTIFIER_POINTER (key_name));
2408: strcat (buf, ":");
2409: }
2410: return get_identifier (buf);
2411: }
2412:
2413: /* used for declarations and definitions */
2414:
2415: tree
2416: build_method_decl (code, ret_type, selector, add_args)
2417: enum tree_code code;
2418: tree ret_type;
2419: tree selector;
2420: tree add_args;
2421: {
2422: tree method_decl;
2423:
2424: /* if no type is specified, default to "id" */
2425: if (ret_type == NULLT)
2426: ret_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
2427: build1 (INDIRECT_REF, NULLT, NULLT));
2428:
2429: method_decl = make_node (code);
2430: TREE_TYPE (method_decl) = ret_type;
2431:
2432: /*
2433: * if we have a keyword selector, create an identifier_node that
2434: * represents the full selector name (`:' included)...
2435: */
2436: if (TREE_CODE (selector) == KEYWORD_DECL)
2437: {
2438: METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
2439: METHOD_SEL_ARGS (method_decl) = selector;
2440: METHOD_ADD_ARGS (method_decl) = add_args;
2441: }
2442: else
2443: {
2444: METHOD_SEL_NAME (method_decl) = selector;
2445: METHOD_SEL_ARGS (method_decl) = NULLT;
2446: METHOD_ADD_ARGS (method_decl) = NULLT;
2447: }
2448:
2449: return method_decl;
2450: }
2451:
2452: #define METHOD_DEF 0
2453: #define METHOD_REF 1
1.1.1.2 root 2454: /* Used by `build_message_expr' and `comp_method_types'.
2455: Return an argument list for method METH.
2456: CONTEXT is either METHOD_DEF or METHOD_REF,
2457: saying whether we are trying to define a method or call one.
2458: SUPERFLAG says this is for a send to super;
2459: this makes a difference for the NeXT calling sequence
2460: in which the lookup and the method call are done together. */
2461:
1.1 root 2462: static tree
2463: get_arg_type_list (meth, context, superflag)
2464: tree meth;
2465: int context;
2466: int superflag;
2467: {
2468: tree arglist, akey;
2469:
1.1.1.2 root 2470: #ifdef NEXT_OBJC_RUNTIME
1.1 root 2471: /* receiver type */
2472: if (superflag)
1.1.1.2 root 2473: {
2474: arglist = build_tree_list (NULLT, super_type);
2475: }
1.1 root 2476: else
1.1.1.2 root 2477: #endif
1.1 root 2478: {
2479: if (context == METHOD_DEF)
2480: arglist = build_tree_list (NULLT, TREE_TYPE (self_decl));
2481: else
2482: arglist = build_tree_list (NULLT, id_type);
2483: }
2484:
2485: /* selector type - will eventually change to `int' */
1.1.1.2 root 2486: chainon (arglist, build_tree_list (NULLT, selector_type));
1.1 root 2487:
2488: /* build a list of argument types */
2489: for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
2490: {
2491: tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
2492: chainon (arglist, build_tree_list (NULLT, TREE_TYPE (arg_decl)));
2493: }
2494:
2495: if (METHOD_ADD_ARGS (meth) == (tree)1)
2496: /*
2497: * we have a `, ...' immediately following the selector,
2498: * finalize the arglist...simulate get_parm_info (0)
2499: */
2500: ;
2501: else if (METHOD_ADD_ARGS (meth))
2502: {
2503: /* we have a variable length selector */
2504: tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
2505: chainon (arglist, add_arg_list);
2506: }
2507: else /* finalize the arglist...simulate get_parm_info (1) */
2508: chainon (arglist, build_tree_list (NULLT, void_type_node));
2509:
2510: return arglist;
2511: }
2512:
2513: static tree
2514: check_duplicates (hsh)
2515: hash hsh;
2516: {
2517: tree meth = NULLT;
2518:
2519: if (hsh)
2520: {
2521: meth = hsh->key;
2522:
2523: if (hsh->list)
2524: {
2525: /* we have two methods with the same name and different types */
2526: attr loop;
2527: char type;
2528:
2529: type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
2530:
2531: warning ("multiple declarations for method `%s'",
2532: IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
2533:
2534: warn_with_method ("using", type, meth);
2535: for (loop = hsh->list; loop; loop = loop->next)
2536: warn_with_method ("also found", type, loop->value);
2537: }
2538: }
2539: return meth;
2540: }
2541:
2542: static tree
2543: receiver_is_class_object (receiver)
2544: tree receiver;
2545: {
2546: /* the receiver is a function call that returns an id...
2547: * ...check if it is a call to objc_getClass, if so, give it
2548: * special treatment.
2549: */
1.1.1.2 root 2550: tree exp = TREE_OPERAND (receiver, 0);
1.1 root 2551:
1.1.1.2 root 2552: if (exp != 0 && (TREE_CODE (exp) == ADDR_EXPR))
1.1 root 2553: {
1.1.1.2 root 2554: exp = TREE_OPERAND (exp, 0);
2555: if (exp != 0
2556: && TREE_CODE (exp) == FUNCTION_DECL && exp == objc_getClass_decl)
1.1 root 2557: {
2558: /* we have a call to objc_getClass! */
1.1.1.2 root 2559: tree arg = TREE_OPERAND (receiver, 1);
2560:
2561: if (arg != 0
2562: && TREE_CODE (arg) == TREE_LIST
2563: && (arg = TREE_VALUE (arg))
2564: && TREE_CODE (arg) == NOP_EXPR
2565: && (arg = TREE_OPERAND (arg, 0))
2566: && TREE_CODE (arg) == ADDR_EXPR
2567: && (arg = TREE_OPERAND (arg, 0))
2568: && TREE_CODE (arg) == STRING_CST)
1.1 root 2569: /* finally, we have the class name */
2570: return get_identifier (TREE_STRING_POINTER (arg));
2571: }
2572: }
2573: return 0;
2574: }
2575:
2576: /* If we are currently building a message expr, this holds
2577: the identifier of the selector of the message. This is
2578: used when printing warnings about argument mismatches. */
2579:
2580: static tree building_objc_message_expr = 0;
2581:
2582: tree
2583: maybe_building_objc_message_expr ()
2584: {
2585: return building_objc_message_expr;
2586: }
2587:
2588: /* Construct an expression for sending a message.
2589: MESS has the object to send to in TREE_PURPOSE
2590: and the argument list (including selector) in TREE_VALUE. */
2591:
2592: tree
2593: build_message_expr (mess)
2594: tree mess;
2595: {
2596: tree receiver = TREE_PURPOSE (mess);
2597: tree selector, self_object;
2598: tree rtype, sel_name;
2599: tree args = TREE_VALUE (mess);
2600: tree method_params = NULLT;
2601: tree method_prototype = NULLT;
2602: int selTransTbl_index;
2603: tree retval;
2604: int statically_typed = 0, statically_allocated = 0;
2605: tree class_ident = 0;
2606:
2607: /* 1 if this is sending to the superclass. */
2608: int super;
2609:
2610: if (!doing_objc_thang)
2611: fatal ("Objective-C text in C source file");
2612:
2613: if (TREE_CODE (receiver) == ERROR_MARK)
2614: return error_mark_node;
2615:
2616: /* determine receiver type */
2617: rtype = TREE_TYPE (receiver);
2618: super = (TREE_TYPE (receiver) == super_type);
2619:
2620: if (! super)
2621: {
2622: if (TREE_STATIC_TEMPLATE (rtype))
2623: statically_allocated = 1;
2624: else if (TREE_CODE (rtype) == POINTER_TYPE
2625: && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
2626: statically_typed = 1;
2627: /* classfix -smn */
2628: else if (TREE_CODE (receiver) == CALL_EXPR && rtype == id_type
2629: && (class_ident = receiver_is_class_object (receiver)))
2630: ;
1.1.1.4 ! root 2631: else if (TYPE_MAIN_VARIANT (rtype) != TYPE_MAIN_VARIANT (id_type)
! 2632: && TYPE_MAIN_VARIANT (rtype) != TYPE_MAIN_VARIANT (class_type))
1.1 root 2633: {
2634: bzero (errbuf, BUFSIZE);
2635: warning ("invalid receiver type `%s'", gen_declaration (rtype, errbuf));
2636: }
2637: if (statically_allocated)
2638: receiver = build_unary_op (ADDR_EXPR, receiver, 0);
2639:
1.1.1.4 ! root 2640: /* Don't evaluate the receiver twice. */
! 2641: receiver = save_expr (receiver);
1.1 root 2642: self_object = receiver;
2643: }
2644: else
2645: /* If sending to `super', use current self as the object. */
2646: self_object = self_decl;
2647:
2648: /* Obtain the full selector name. */
2649:
2650: if (TREE_CODE (args) == IDENTIFIER_NODE)
2651: /* a unary selector */
2652: sel_name = args;
2653: else if (TREE_CODE (args) == TREE_LIST)
2654: sel_name = build_keyword_selector (args);
2655:
2656: selTransTbl_index = add_selector_reference (sel_name);
2657:
2658: /* Build the parameters list for looking up the method.
2659: These are the object itself and the selector. */
2660:
1.1.1.3 root 2661: #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 2662: selector = build_selector_reference (selTransTbl_index);
2663: #else
2664: selector = build_array_ref (_OBJC_SELECTOR_REFERENCES_decl,
2665: build_int_2 (selTransTbl_index, 0));
2666: #endif
2667:
2668: /* Build the parameter list to give to the method. */
2669:
2670: method_params = NULLT;
2671: if (TREE_CODE (args) == TREE_LIST)
2672: {
2673: tree chain = args, prev = NULLT;
2674:
2675: /* We have a keyword selector--check for comma expressions. */
2676: while (chain)
2677: {
2678: tree element = TREE_VALUE (chain);
2679:
2680: /* We have a comma expression, must collapse... */
2681: if (TREE_CODE (element) == TREE_LIST)
2682: {
2683: if (prev)
2684: TREE_CHAIN (prev) = element;
2685: else
2686: args = element;
2687: }
2688: prev = chain;
2689: chain = TREE_CHAIN (chain);
2690: }
2691: method_params = args;
2692: }
2693:
2694: /* Determine operation return type. */
2695:
1.1.1.4 ! root 2696: if (super_type != 0
! 2697: && TYPE_MAIN_VARIANT (rtype) == TYPE_MAIN_VARIANT (super_type))
1.1 root 2698: {
2699: tree iface;
2700:
2701: if (CLASS_SUPER_NAME (implementation_template))
2702: {
2703: iface = lookup_interface (CLASS_SUPER_NAME (implementation_template));
2704:
2705: if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
2706: method_prototype = lookup_instance_method_static (iface, sel_name);
2707: else
2708: method_prototype = lookup_class_method_static (iface, sel_name);
2709:
2710: if (iface && !method_prototype)
2711: warning ("`%s' does not respond to `%s'",
2712: IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
2713: IDENTIFIER_POINTER (sel_name));
2714: }
2715: else
2716: {
2717: error ("no super class declared in interface for `%s'",
2718: IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
2719: return error_mark_node;
2720: }
2721:
2722: }
2723: else if (statically_allocated)
2724: {
2725: tree iface = lookup_interface (TYPE_NAME (rtype));
2726:
2727: if (iface && !(method_prototype = lookup_instance_method_static (iface, sel_name)))
2728: warning ("`%s' does not respond to `%s'",
2729: IDENTIFIER_POINTER (TYPE_NAME (rtype)),
2730: IDENTIFIER_POINTER (sel_name));
2731: }
2732: else if (statically_typed)
2733: {
2734: tree ctype = TREE_TYPE (rtype);
2735:
2736: /* `self' is now statically_typed...all methods should be visible
2737: * within the context of the implementation...
2738: */
2739: if (implementation_context
2740: && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
2741: {
2742: method_prototype = lookup_instance_method_static (implementation_template, sel_name);
2743:
2744: if (!method_prototype && implementation_template != implementation_context)
2745: /* the method is not published in the interface...check locally */
2746: method_prototype = lookup_method (CLASS_NST_METHODS (implementation_context),
2747: sel_name);
2748: }
2749: else
2750: {
2751: tree iface;
2752:
2753: if (iface = lookup_interface (TYPE_NAME (ctype)))
2754: method_prototype = lookup_instance_method_static (iface, sel_name);
2755: }
2756:
2757: if (!method_prototype)
2758: warning ("`%s' does not respond to `%s'",
2759: IDENTIFIER_POINTER (TYPE_NAME (ctype)),
2760: IDENTIFIER_POINTER (sel_name));
2761: }
2762: else if (class_ident)
2763: {
2764: if (implementation_context
2765: && CLASS_NAME (implementation_context) == class_ident)
2766: {
2767: method_prototype
2768: = lookup_class_method_static (implementation_template, sel_name);
2769:
2770: if (!method_prototype
2771: && implementation_template != implementation_context)
2772: /* the method is not published in the interface...check locally */
2773: method_prototype
2774: = lookup_method (CLASS_CLS_METHODS (implementation_context),
2775: sel_name);
2776: }
2777: else
2778: {
2779: tree iface;
2780:
2781: if (iface = lookup_interface (class_ident))
2782: method_prototype = lookup_class_method_static (iface, sel_name);
2783: }
2784:
2785: if (!method_prototype)
2786: {
2787: warning ("cannot find class (factory) method.");
2788: warning ("return type for `%s' defaults to id",
2789: IDENTIFIER_POINTER (sel_name));
2790: }
2791: }
2792: else
2793: {
2794: hash hsh;
2795:
2796: /* we think we have an instance...loophole: extern id Object; */
2797: hsh = hash_lookup (nst_method_hash_list, sel_name);
2798: if (!hsh)
2799: /* for various loopholes...like sending messages to self in a
2800: factory context... */
2801: hsh = hash_lookup (cls_method_hash_list, sel_name);
2802:
2803: method_prototype = check_duplicates (hsh);
2804: if (!method_prototype)
2805: {
2806: warning ("cannot find method.");
2807: warning ("return type for `%s' defaults to id",
2808: IDENTIFIER_POINTER (sel_name));
2809: }
2810: }
2811:
2812: /* Save the selector name for printing error messages. */
2813: building_objc_message_expr = sel_name;
2814:
2815: retval = build_objc_method_call (super, method_prototype,
2816: receiver, self_object,
2817: selector, method_params);
2818:
2819: building_objc_message_expr = 0;
2820:
2821: return retval;
2822: }
2823:
2824: /* Build a tree expression to send OBJECT the operation SELECTOR,
2825: looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
2826: assuming the method has prototype METHOD_PROTOTYPE.
2827: (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
2828: Use METHOD_PARAMS as list of args to pass to the method.
2829: If SUPER_FLAG is nonzero, we look up the superclass's method. */
2830:
2831: static tree
2832: build_objc_method_call (super_flag, method_prototype, lookup_object, object,
2833: selector, method_params)
2834: int super_flag;
2835: tree method_prototype, lookup_object, object, selector, method_params;
2836: {
2837: tree sender = (super_flag ? _msgSuper_decl : _msg_decl);
2838:
2839: #ifdef NEXT_OBJC_RUNTIME
2840: if (!method_prototype)
2841: {
2842: method_params = tree_cons (NULLT, lookup_object,
2843: tree_cons (NULLT, selector, method_params));
2844: return build_function_call (sender, method_params);
2845: }
2846: else
2847: {
2848: /* This is a real kludge, but it is used only for the Next.
2849: Clobber the data type of SENDER temporarily to accept
2850: all the arguments for this operation, and to return
2851: whatever this operation returns. */
2852: tree arglist = NULLT;
2853: tree retval;
2854:
2855: /* Save the proper contents of SENDER's data type. */
2856: tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
2857: tree savret = TREE_TYPE (TREE_TYPE (sender));
2858:
2859: /* Install this method's argument types. */
2860: arglist = get_arg_type_list (method_prototype, METHOD_REF, super_flag);
2861: TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
2862:
2863: /* Install this method's return type. */
2864: TREE_TYPE (TREE_TYPE (sender))
2865: = groktypename (TREE_TYPE (method_prototype));
2866:
2867: /* Call SENDER with all the parameters.
2868: This will do type checking using the arg types for this method. */
2869: method_params = tree_cons (NULLT, lookup_object,
2870: tree_cons (NULLT, selector, method_params));
2871: retval = build_function_call (sender, method_params);
2872:
2873: /* Restore SENDER's return/argument types. */
2874: TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
2875: TREE_TYPE (TREE_TYPE (sender)) = savret;
2876: return retval;
2877: }
2878: #else /* not NEXT_OBJC_RUNTIME */
2879: /* This is the portable way.
2880: First call the lookup function to get a pointer to the method,
2881: then cast the pointer, then call it with the method arguments. */
2882: tree method;
2883:
2884: /* Avoid trouble since we may evaluate each of these twice. */
2885: object = save_expr (object);
2886: selector = save_expr (selector);
2887:
2888: method
2889: = build_function_call (sender,
2890: tree_cons (NULLT, lookup_object,
2891: tree_cons (NULLT, selector, NULLT)));
2892:
2893: /* If we have a method prototype, construct the data type this method needs,
2894: and cast what we got from SENDER into a pointer to that type. */
2895: if (method_prototype)
2896: {
2897: tree arglist = get_arg_type_list (method_prototype, METHOD_REF, super_flag);
2898: tree valtype = groktypename (TREE_TYPE (method_prototype));
2899: tree fake_function_type = build_function_type (valtype, arglist);
2900: TREE_TYPE (method) = build_pointer_type (fake_function_type);
2901: }
2902: else
2903: {
2904: TREE_TYPE (method)
2905: = build_pointer_type (build_function_type (ptr_type_node, NULLT));
2906: }
2907: /* Pass the object to the method. */
2908: return build_function_call (method,
2909: tree_cons (NULLT, object,
2910: tree_cons (NULLT, selector,
2911: method_params)));
2912: #endif /* not NEXT_OBJC_RUNTIME */
2913: }
2914:
2915: tree
2916: build_selector_expr (selnamelist)
2917: tree selnamelist;
2918: {
2919: tree selname;
2920: int selTransTbl_index;
2921:
2922: if (!doing_objc_thang)
2923: fatal ("Objective-C text in C source file");
2924:
2925: /* obtain the full selector name */
2926: if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
2927: /* a unary selector */
2928: selname = selnamelist;
2929: else if (TREE_CODE (selnamelist) == TREE_LIST)
2930: selname = build_keyword_selector (selnamelist);
2931:
2932: selTransTbl_index = add_selector_reference (selname);
2933:
1.1.1.3 root 2934: #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 2935: return build_selector_reference (selTransTbl_index);
2936: #else
2937: /* synthesize a reference into the selector translation table */
2938: return build_array_ref (_OBJC_SELECTOR_REFERENCES_decl,
2939: build_int_2 (selTransTbl_index, 0));
2940: #endif
2941: }
2942:
2943: tree
2944: build_encode_expr (type)
2945: tree type;
2946: {
1.1.1.3 root 2947: tree result;
2948: char *string;
2949:
1.1 root 2950: if (!doing_objc_thang)
2951: fatal ("Objective-C text in C source file");
2952:
1.1.1.3 root 2953: encode_type (type, OBJC_ENCODE_INLINE_DEFS);
1.1.1.4 ! root 2954: obstack_1grow (&util_obstack, 0); /* null terminate string */
1.1.1.3 root 2955: string = obstack_finish (&util_obstack);
1.1 root 2956:
2957: /* synthesize a string that represents the encoded struct/union */
1.1.1.3 root 2958: result = my_build_string (strlen (string) + 1, string);
2959: obstack_free (&util_obstack, util_firstobj);
2960: return result;
1.1 root 2961: }
2962:
2963: tree
2964: build_ivar_reference (id)
2965: tree id;
2966: {
2967: if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
2968: TREE_TYPE (self_decl) = instance_type; /* cast */
2969:
2970: return build_component_ref (build_indirect_ref (self_decl, "->"), id);
2971: }
2972:
2973: #define HASH_ALLOC_LIST_SIZE 170
2974: #define ATTR_ALLOC_LIST_SIZE 170
2975: #define SIZEHASHTABLE 257
2976: #define HASHFUNCTION(key) ((int)key >> 2) /* divide by 4 */
2977:
2978: static void
2979: hash_init ()
2980: {
2981: nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
2982: cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
2983:
2984: if (!nst_method_hash_list || !cls_method_hash_list)
2985: perror ("unable to allocate space in objc-tree.c");
2986: else
2987: {
2988: int i;
2989:
2990: for (i = 0; i < SIZEHASHTABLE; i++)
2991: {
2992: nst_method_hash_list[i] = 0;
2993: cls_method_hash_list[i] = 0;
2994: }
2995: }
2996: }
2997:
2998: static void
2999: hash_enter (hashlist, method)
3000: hash *hashlist;
3001: tree method;
3002: {
3003: static hash hash_alloc_list = 0;
3004: static int hash_alloc_index = 0;
3005: hash obj;
3006: int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
3007:
3008: if (!hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
3009: {
3010: hash_alloc_index = 0;
3011: hash_alloc_list = (hash)xmalloc (sizeof (struct hashedEntry) *
3012: HASH_ALLOC_LIST_SIZE);
3013: if (!hash_alloc_list)
3014: perror ("unable to allocate in objc-tree.c");
3015: }
3016: obj = &hash_alloc_list[hash_alloc_index++];
3017: obj->list = 0;
3018: obj->next = hashlist[slot];
3019: obj->key = method;
3020:
3021: hashlist[slot] = obj; /* append to front */
3022: }
3023:
3024: static hash
3025: hash_lookup (hashlist, sel_name)
3026: hash *hashlist;
3027: tree sel_name;
3028: {
3029: hash target;
3030:
3031: target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
3032:
3033: while (target)
3034: {
3035: if (sel_name == METHOD_SEL_NAME (target->key))
3036: return target;
3037:
3038: target = target->next;
3039: }
3040: return 0;
3041: }
3042:
3043: static void
3044: hash_add_attr (entry, value)
3045: hash entry;
3046: tree value;
3047: {
3048: static attr attr_alloc_list = 0;
3049: static int attr_alloc_index = 0;
3050: attr obj;
3051:
3052: if (!attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
3053: {
3054: attr_alloc_index = 0;
3055: attr_alloc_list = (attr)xmalloc (sizeof (struct hashedAttribute) *
3056: ATTR_ALLOC_LIST_SIZE);
3057: if (!attr_alloc_list)
3058: perror ("unable to allocate in objc-tree.c");
3059: }
3060: obj = &attr_alloc_list[attr_alloc_index++];
3061: obj->next = entry->list;
3062: obj->value = value;
3063:
3064: entry->list = obj; /* append to front */
3065: }
3066:
3067: static tree
3068: lookup_method (mchain, method)
3069: tree mchain;
3070: tree method;
3071: {
3072: tree key;
3073:
3074: if (TREE_CODE (method) == IDENTIFIER_NODE)
3075: key = method;
3076: else
3077: key = METHOD_SEL_NAME (method);
3078:
3079: while (mchain)
3080: {
3081: if (METHOD_SEL_NAME (mchain) == key)
3082: return mchain;
3083: mchain = TREE_CHAIN (mchain);
3084: }
3085: return NULLT;
3086: }
3087:
3088: static tree
3089: lookup_instance_method_static (interface, ident)
3090: tree interface;
3091: tree ident;
3092: {
3093: tree inter = interface;
3094: tree chain = CLASS_NST_METHODS (inter);
3095: tree meth = NULLT;
3096:
3097: do
3098: {
3099: if (meth = lookup_method (chain, ident))
3100: return meth;
3101:
3102: if (CLASS_CATEGORY_LIST (inter))
3103: {
3104: tree category = CLASS_CATEGORY_LIST (inter);
3105: chain = CLASS_NST_METHODS (category);
3106:
3107: do
3108: {
3109: if (meth = lookup_method (chain, ident))
3110: return meth;
3111:
3112: if (category = CLASS_CATEGORY_LIST (category))
3113: chain = CLASS_NST_METHODS (category);
3114: }
3115: while (category);
3116: }
3117:
3118: if (inter = lookup_interface (CLASS_SUPER_NAME (inter)))
3119: chain = CLASS_NST_METHODS (inter);
3120: }
3121: while (inter);
3122:
3123: return meth;
3124: }
3125:
3126: static tree
3127: lookup_class_method_static (interface, ident)
3128: tree interface;
3129: tree ident;
3130: {
3131: tree inter = interface;
3132: tree chain = CLASS_CLS_METHODS (inter);
3133: tree meth = NULLT;
3134:
3135: do
3136: {
3137: if (meth = lookup_method (chain, ident))
3138: return meth;
3139:
3140: if (CLASS_CATEGORY_LIST (inter))
3141: {
3142: tree category = CLASS_CATEGORY_LIST (inter);
3143: chain = CLASS_CLS_METHODS (category);
3144:
3145: do
3146: {
3147: if (meth = lookup_method (chain, ident))
3148: return meth;
3149:
3150: if (category = CLASS_CATEGORY_LIST (category))
3151: chain = CLASS_CLS_METHODS (category);
3152: }
3153: while (category);
3154: }
3155:
3156: if (inter = lookup_interface (CLASS_SUPER_NAME (inter)))
3157: chain = CLASS_CLS_METHODS (inter);
3158: }
3159: while (inter);
3160:
3161: return meth;
3162: }
3163:
3164: tree
3165: add_class_method (class, method)
3166: tree class;
3167: tree method;
3168: {
3169: tree mth;
3170: hash hsh;
3171:
3172: if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
3173: {
3174: /* put method on list in reverse order */
3175: TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
3176: CLASS_CLS_METHODS (class) = method;
3177: }
3178: else
3179: {
3180: if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3181: error ("duplicate definition of class method `%s'.",
3182: IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
3183: else
3184: {
3185: /* check types, if different complain */
3186: if (!comp_proto_with_proto (method, mth))
3187: error ("duplicate declaration of class method `%s'.",
3188: IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
3189: }
3190: }
3191:
3192: if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
3193: {
3194: /* install on a global chain */
3195: hash_enter (cls_method_hash_list, method);
3196: }
3197: else
3198: {
3199: /* check types, if different add to a list */
3200: if (!comp_proto_with_proto (method, hsh->key))
3201: hash_add_attr (hsh, method);
3202: }
3203: return method;
3204: }
3205:
3206: tree
3207: add_instance_method (class, method)
3208: tree class;
3209: tree method;
3210: {
3211: tree mth;
3212: hash hsh;
3213:
3214: if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
3215: {
3216: /* put method on list in reverse order */
3217: TREE_CHAIN (method) = CLASS_NST_METHODS (class);
3218: CLASS_NST_METHODS (class) = method;
3219: }
3220: else
3221: {
3222: if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3223: error ("duplicate definition of instance method `%s'.",
3224: IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
3225: else
3226: {
3227: /* check types, if different complain */
3228: if (!comp_proto_with_proto (method, mth))
3229: error ("duplicate declaration of instance method `%s'.",
3230: IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
3231: }
3232: }
3233:
3234: if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
3235: {
3236: /* install on a global chain */
3237: hash_enter (nst_method_hash_list, method);
3238: }
3239: else
3240: {
3241: /* check types, if different add to a list */
3242: if (!comp_proto_with_proto (method, hsh->key))
3243: hash_add_attr (hsh, method);
3244: }
3245: return method;
3246: }
3247:
3248: static tree
3249: add_class (class)
3250: tree class;
3251: {
3252: /* put interfaces on list in reverse order */
3253: TREE_CHAIN (class) = interface_chain;
3254: interface_chain = class;
3255: return interface_chain;
3256: }
3257:
3258: static void
3259: add_category (class, category)
3260: tree class;
3261: tree category;
3262: {
3263: /* put categories on list in reverse order */
3264: CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
3265: CLASS_CATEGORY_LIST (class) = category;
3266: }
3267:
3268: /* called after parsing each instance variable declaration. Necessary to
3269: * preserve typedefs and implement public/private...
3270: */
3271: tree
3272: add_instance_variable (class, public, declarator, declspecs, width)
3273: tree class;
3274: int public;
3275: tree declarator;
3276: tree declspecs;
3277: tree width;
3278: {
3279: tree field_decl, raw_decl;
3280:
3281: raw_decl = build_tree_list (declspecs /*purpose*/, declarator/*value*/);
3282:
3283: if (CLASS_RAW_IVARS (class))
3284: chainon (CLASS_RAW_IVARS (class), raw_decl);
3285: else
3286: CLASS_RAW_IVARS (class) = raw_decl;
3287:
3288: field_decl = grokfield (input_filename, lineno,
3289: declarator, declspecs, width);
3290:
3291: /* overload the public attribute, it is not used for FIELD_DECL's */
3292: if (public)
3293: TREE_PUBLIC (field_decl) = 1;
3294:
3295: if (CLASS_IVARS (class))
3296: chainon (CLASS_IVARS (class), field_decl);
3297: else
3298: CLASS_IVARS (class) = field_decl;
3299:
3300: return class;
3301: }
3302:
3303: tree
3304: is_ivar (decl_chain, ident)
3305: tree decl_chain;
3306: tree ident;
3307: {
3308: for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
3309: if (DECL_NAME (decl_chain) == ident)
3310: return decl_chain;
3311: return NULL_TREE;
3312: }
3313:
3314: /* we have an instance variable reference, check to see if it is public...*/
3315:
3316: int
3317: is_public (expr, identifier)
3318: tree expr;
3319: tree identifier;
3320: {
3321: tree basetype = TREE_TYPE (expr);
3322: enum tree_code code = TREE_CODE (basetype);
3323: tree decl;
3324:
3325: if (code == RECORD_TYPE)
3326: {
3327: if (TREE_STATIC_TEMPLATE (basetype))
3328: {
3329: if (decl = is_ivar (TYPE_FIELDS (basetype), identifier))
3330: {
1.1.1.3 root 3331: /* important difference between the Stepstone translator:
1.1 root 3332:
3333: all instance variables should be public within the context
3334: of the implementation...
3335: */
3336: if (implementation_context)
3337: {
3338: if ((TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE
3339: && CLASS_NAME (implementation_context) == TYPE_NAME (basetype))
3340: || (TREE_CODE (implementation_context) == CATEGORY_TYPE
3341: && CLASS_NAME (implementation_context) == TYPE_NAME (basetype)))
3342: return 1;
3343: }
3344:
3345: if (TREE_PUBLIC (decl))
3346: return 1;
3347:
3348: error ("instance variable `%s' is declared private",
3349: IDENTIFIER_POINTER (identifier));
3350: return 0;
3351: }
3352: }
3353: else if (implementation_context && (basetype == objc_object_reference))
3354: {
3355: TREE_TYPE (expr) = _PRIVATE_record;
3356: if (extra_warnings)
3357: {
3358: warning ("static access to object of type `id'");
3359: warning ("please change to type `%s *'",
3360: IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
3361: }
3362: }
3363: }
3364: return 1;
3365: }
3366:
3367: /* implement @defs (<classname>) within struct bodies. */
3368:
3369: tree
3370: get_class_ivars (interface)
3371: tree interface;
3372: {
3373: if (!doing_objc_thang)
3374: fatal ("Objective-C text in C source file");
3375:
3376: return build_ivar_chain (interface);
3377: }
3378:
3379: tree
3380: get_class_reference (interface)
3381: tree interface;
3382: {
3383: tree params;
3384:
3385: add_class_reference (CLASS_NAME (interface));
3386:
3387: params = build_tree_list (NULLT,
3388: my_build_string (IDENTIFIER_LENGTH (CLASS_NAME (interface)) + 1,
3389: IDENTIFIER_POINTER (CLASS_NAME (interface))));
3390:
3391: return build_function_call (objc_getClass_decl, params);
3392: }
3393:
3394: /* make sure all entries in "chain" are also in "list" */
3395:
3396: static void
3397: check_methods (chain, list, mtype)
3398: tree chain;
3399: tree list;
3400: int mtype;
3401: {
3402: int first = 1;
3403:
3404: while (chain)
3405: {
3406: if (!lookup_method (list, chain))
3407: {
3408: if (first)
3409: {
3410: if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
3411: warning ("incomplete implementation of class `%s'",
3412: IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
3413: else if (TREE_CODE (implementation_context) == CATEGORY_TYPE)
3414: warning ("incomplete implementation of category `%s'",
3415: IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
3416: first = 0;
3417: }
3418: warning ("method definition for `%c%s' not found",
3419: mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
3420: }
3421: chain = TREE_CHAIN (chain);
3422: }
3423: }
3424:
1.1.1.4 ! root 3425: /* Make sure that the class CLASS_NAME is defined
! 3426: CODE says which kind of thing CLASS_NAME ought to be.
! 3427: It can be INTERFACE_TYPE, IMPLEMENTATION_TYPE, PROTOCOL_TYPE
! 3428: or CATEGORY_TYPE.
! 3429:
! 3430: If CODE is INTERFACE_TYPE, we also do a push_obstacks_nochange
! 3431: whose matching pop is in continue_class. */
! 3432:
1.1 root 3433: tree
3434: start_class (code, class_name, super_name)
3435: enum tree_code code;
3436: tree class_name;
3437: tree super_name;
3438: {
3439: tree class;
3440:
1.1.1.4 ! root 3441: if (code == INTERFACE_TYPE)
! 3442: {
! 3443: push_obstacks_nochange ();
! 3444: end_temporary_allocation ();
! 3445: }
! 3446:
1.1 root 3447: if (!doing_objc_thang)
1.1.1.4 ! root 3448: fatal ("Objective-C text in C source file");
1.1 root 3449:
3450: class = make_node (code);
3451:
3452: CLASS_NAME (class) = class_name;
3453: CLASS_SUPER_NAME (class) = super_name;
3454: CLASS_CLS_METHODS (class) = NULL_TREE;
3455:
3456: if (code == IMPLEMENTATION_TYPE)
3457: {
3458: /* pre-build the following entities - for speed/convenience. */
3459: if (!self_id)
3460: self_id = get_identifier ("self");
3461: if (!_cmd_id)
3462: _cmd_id = get_identifier ("_cmd");
3463:
3464: if (!objc_super_template)
3465: objc_super_template = build_super_template ();
3466:
3467: method_slot = 0; /* reset for multiple classes per file */
3468:
3469: implementation_context = class;
3470:
3471: /* lookup the interface for this implementation. */
3472:
3473: if (!(implementation_template = lookup_interface (class_name)))
3474: {
3475: warning ("Cannot find interface declaration for `%s'",
3476: IDENTIFIER_POINTER (class_name));
3477: add_class (implementation_template = implementation_context);
3478: }
3479:
3480: /* if a super class has been specified in the implementation,
3481: insure it conforms to the one specified in the interface */
3482:
3483: if (super_name
3484: && (super_name != CLASS_SUPER_NAME (implementation_template)))
3485: {
3486: error ("conflicting super class name `%s'",
3487: IDENTIFIER_POINTER (super_name));
3488: error ("previous declaration of `%s'",
3489: IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)));
3490: }
3491: }
3492: else if (code == INTERFACE_TYPE)
3493: {
3494: if (lookup_interface (class_name))
3495: warning ("duplicate interface declaration for class `%s'",
3496: IDENTIFIER_POINTER (class_name));
3497: else
3498: add_class (class);
3499: }
3500: else if (code == PROTOCOL_TYPE)
3501: {
3502: tree class_category_is_assoc_with;
3503:
3504: /* for a category, class_name is really the name of the class that
3505: the following set of methods will be associated with...we must
3506: find the interface so that can derive the objects template */
3507:
3508: if (!(class_category_is_assoc_with = lookup_interface (class_name)))
3509: {
3510: error ("Cannot find interface declaration for `%s'",
3511: IDENTIFIER_POINTER (class_name));
3512: exit (1);
3513: }
3514: else
3515: add_category (class_category_is_assoc_with, class);
3516: }
3517: else if (code == CATEGORY_TYPE)
3518: {
3519: /* pre-build the following entities - for speed/convenience. */
3520: if (!self_id)
3521: self_id = get_identifier ("self");
3522: if (!_cmd_id)
3523: _cmd_id = get_identifier ("_cmd");
3524:
3525: if (!objc_super_template)
3526: objc_super_template = build_super_template ();
3527:
3528: method_slot = 0; /* reset for multiple classes per file */
3529:
3530: implementation_context = class;
3531:
3532: /* for a category, class_name is really the name of the class that
3533: the following set of methods will be associated with...we must
3534: find the interface so that can derive the objects template */
3535:
3536: if (!(implementation_template = lookup_interface (class_name)))
3537: {
3538: error ("Cannot find interface declaration for `%s'",
3539: IDENTIFIER_POINTER (class_name));
3540: exit (1);
3541: }
3542: }
3543: return class;
3544: }
3545:
3546: tree
3547: continue_class (class)
3548: tree class;
3549: {
3550: if (TREE_CODE (class) == IMPLEMENTATION_TYPE
3551: || TREE_CODE (class) == CATEGORY_TYPE)
3552: {
3553: struct imp_entry *impEntry;
3554: tree ivar_context;
3555:
3556: /* check consistency of the instance variables. */
3557:
3558: if (CLASS_IVARS (class))
3559: check_ivars (implementation_template, class);
3560:
3561: /* code generation */
3562:
3563: ivar_context = build_private_template (implementation_template);
3564:
3565: if (!objc_class_template)
3566: build_class_template ();
3567:
3568: if (!(impEntry = (struct imp_entry *)xmalloc (sizeof (struct imp_entry))))
3569: perror ("unable to allocate in objc-tree.c");
3570:
3571: impEntry->next = imp_list;
3572: impEntry->imp_context = class;
3573: impEntry->imp_template = implementation_template;
3574:
3575: synth_forward_declarations ();
3576: impEntry->class_decl = _OBJC_CLASS_decl;
3577: impEntry->meta_decl = _OBJC_METACLASS_decl;
3578:
3579: /* append to front and increment count */
3580: imp_list = impEntry;
3581: if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3582: imp_count++;
3583: else
3584: cat_count++;
3585:
3586: return ivar_context;
3587: }
3588: else if (TREE_CODE (class) == INTERFACE_TYPE)
3589: {
3590: tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
3591:
3592: if (!TYPE_FIELDS (record))
3593: {
3594: finish_struct (record, build_ivar_chain (class));
3595: CLASS_STATIC_TEMPLATE (class) = record;
3596:
3597: /* mark this record as a class template - for static typing */
3598: TREE_STATIC_TEMPLATE (record) = 1;
3599: }
3600: return NULLT;
3601: }
3602: else
3603: return error_mark_node;
3604: }
3605:
3606: /*
3607: * this is called once we see the "@end" in an interface/implementation.
3608: */
3609: void
3610: finish_class (class)
3611: tree class;
3612: {
3613: if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
3614: {
3615: /* all code generation is done in finish_objc */
3616:
3617: if (implementation_template != implementation_context)
3618: {
3619: /* ensure that all method listed in the interface contain bodies! */
3620: check_methods (CLASS_CLS_METHODS (implementation_template),
3621: CLASS_CLS_METHODS (implementation_context), '+');
3622: check_methods (CLASS_NST_METHODS (implementation_template),
3623: CLASS_NST_METHODS (implementation_context), '-');
3624: }
3625: }
3626: else if (TREE_CODE (class) == CATEGORY_TYPE)
3627: {
3628: tree category = CLASS_CATEGORY_LIST (implementation_template);
3629:
3630: /* find the category interface from the class it is associated with */
3631: while (category)
3632: {
3633: if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
3634: break;
3635: category = CLASS_CATEGORY_LIST (category);
3636: }
3637:
3638: if (category)
3639: {
3640: /* ensure that all method listed in the interface contain bodies! */
3641: check_methods (CLASS_CLS_METHODS (category),
3642: CLASS_CLS_METHODS (implementation_context), '+');
3643: check_methods (CLASS_NST_METHODS (category),
3644: CLASS_NST_METHODS (implementation_context), '-');
3645: }
3646: }
3647: else if (TREE_CODE (class) == INTERFACE_TYPE)
3648: {
3649: tree decl_specs;
1.1.1.3 root 3650: char *string = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (class))) + 3);
1.1 root 3651:
3652: /* extern struct objc_object *_<my_name>; */
3653:
1.1.1.3 root 3654: sprintf (string, "_%s", IDENTIFIER_POINTER (CLASS_NAME (class)));
1.1 root 3655:
3656: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
3657: decl_specs = tree_cons (NULLT, objc_object_reference, decl_specs);
1.1.1.3 root 3658: define_decl (build1 (INDIRECT_REF, NULLT, get_identifier (string)),
3659: decl_specs);
1.1 root 3660: }
3661: }
3662:
1.1.1.3 root 3663: /* "Encode" a data type into a string, whichg rows in util_obstack.
3664: ??? What is the FORMAT? Someone please document this! */
3665:
3666: /* Encode a pointer type. */
3667:
1.1 root 3668: static void
1.1.1.3 root 3669: encode_pointer (type, format)
1.1 root 3670: tree type;
3671: int format;
3672: {
3673: tree pointer_to = TREE_TYPE (type);
3674:
3675: if (TREE_CODE (pointer_to) == RECORD_TYPE)
3676: {
3677: if (TYPE_NAME (pointer_to)
3678: && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
3679: {
3680: char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
3681:
1.1.1.3 root 3682: if ((strcmp (name, TAG_OBJECT) == 0) /* '@' */
3683: || TREE_STATIC_TEMPLATE (pointer_to))
1.1 root 3684: {
1.1.1.3 root 3685: obstack_1grow (&util_obstack, '@');
1.1 root 3686: return;
3687: }
3688: else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
3689: {
1.1.1.3 root 3690: obstack_1grow (&util_obstack, '#');
1.1 root 3691: return;
3692: }
3693: #ifndef OBJC_INT_SELECTORS
3694: else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
3695: {
1.1.1.3 root 3696: obstack_1grow (&util_obstack, ':');
1.1 root 3697: return;
3698: }
3699: #endif /* OBJC_INT_SELECTORS */
3700: }
3701: }
3702: else if (TREE_CODE (pointer_to) == INTEGER_TYPE
3703: && TYPE_MODE (pointer_to) == QImode)
3704: {
1.1.1.3 root 3705: obstack_1grow (&util_obstack, '*');
1.1 root 3706: return;
3707: }
3708:
3709: /* we have a type that does not get special treatment... */
3710:
3711: /* NeXT extension */
1.1.1.3 root 3712: obstack_1grow (&util_obstack, '^');
3713: encode_type (pointer_to, format);
1.1 root 3714: }
3715:
3716: static void
1.1.1.3 root 3717: encode_array (type, format)
1.1 root 3718: tree type;
3719: int format;
3720: {
3721: tree anIntCst = TYPE_SIZE (type);
3722: tree array_of = TREE_TYPE (type);
1.1.1.3 root 3723: char buffer[40];
1.1 root 3724:
3725: /* An incomplete array is treated like a pointer. */
3726: if (anIntCst == NULL)
3727: {
3728: /* split for obvious reasons. North-Keys 30 Mar 1991 */
1.1.1.3 root 3729: encode_pointer (type, format);
1.1 root 3730: return;
3731: }
3732:
1.1.1.3 root 3733: sprintf (buffer, "[%d",
1.1 root 3734: TREE_INT_CST_LOW (anIntCst)
3735: / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
1.1.1.3 root 3736: obstack_grow (&util_obstack, buffer, strlen (buffer));
3737: encode_type (array_of, format);
3738: obstack_1grow (&util_obstack, ']');
1.1 root 3739: return;
3740: }
3741:
3742: static void
1.1.1.3 root 3743: encode_aggregate (type, format)
1.1 root 3744: tree type;
3745: int format;
3746: {
3747: enum tree_code code = TREE_CODE (type);
3748:
3749: switch (code)
3750: {
3751: case RECORD_TYPE:
3752: {
1.1.1.4 ! root 3753: int have_pointer = 0;
! 3754:
! 3755: if (obstack_object_size (&util_obstack) > 0
! 3756: && *(obstack_next_free (&util_obstack)-1) == '^')
! 3757: have_pointer = 1;
! 3758:
! 3759: obstack_1grow (&util_obstack, '{');
! 3760: if (TYPE_NAME (type))
1.1 root 3761: {
1.1.1.4 ! root 3762: if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
1.1.1.3 root 3763: {
1.1.1.4 ! root 3764: obstack_grow (&util_obstack,
1.1.1.3 root 3765: IDENTIFIER_POINTER (TYPE_NAME (type)),
3766: strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
3767: }
3768: else /* we have an untagged structure or a typedef */
1.1.1.4 ! root 3769: {
! 3770: obstack_1grow (&util_obstack, '?');
! 3771: }
! 3772: }
! 3773:
! 3774: if (have_pointer
! 3775: || format == OBJC_ENCODE_DONT_INLINE_DEFS)
! 3776: {
! 3777: /* we have a pointer
! 3778: or we don't want the details. */
! 3779: obstack_1grow (&util_obstack, '}');
1.1 root 3780: }
3781: else
3782: {
3783: tree fields = TYPE_FIELDS (type);
1.1.1.4 ! root 3784: obstack_1grow (&util_obstack, '=');
1.1.1.3 root 3785: for ( ; fields; fields = TREE_CHAIN (fields))
3786: encode_field_decl (fields, format);
3787: obstack_1grow (&util_obstack, '}');
1.1 root 3788: }
3789: break;
3790: }
1.1.1.4 ! root 3791:
1.1 root 3792: case UNION_TYPE:
3793: {
1.1.1.4 ! root 3794: int have_pointer = 0;
! 3795:
! 3796: if (obstack_object_size (&util_obstack) > 0
! 3797: && *(obstack_next_free (&util_obstack)-1) == '^')
! 3798: have_pointer = 1;
! 3799:
! 3800: obstack_1grow (&util_obstack, '(');
! 3801: if (have_pointer && TYPE_NAME (type))
1.1 root 3802: {
1.1.1.4 ! root 3803: if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
1.1.1.3 root 3804: {
1.1.1.4 ! root 3805: obstack_grow (&util_obstack,
1.1.1.3 root 3806: IDENTIFIER_POINTER (TYPE_NAME (type)),
3807: strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
3808: }
3809: else /* we have an untagged structure or a typedef */
1.1.1.4 ! root 3810: {
! 3811: obstack_1grow (&util_obstack, '?');
! 3812: }
! 3813: }
! 3814:
! 3815: if (have_pointer
! 3816: || format == OBJC_ENCODE_DONT_INLINE_DEFS)
! 3817: {
! 3818: /* we have a pointer
! 3819: or we don't want the details. */
! 3820: obstack_1grow (&util_obstack, ')');
1.1 root 3821: }
3822: else
3823: {
3824: tree fields = TYPE_FIELDS (type);
1.1.1.3 root 3825: for ( ; fields; fields = TREE_CHAIN (fields))
3826: encode_field_decl (fields, format);
1.1.1.4 ! root 3827: obstack_1grow (&util_obstack, ')');
1.1 root 3828: }
3829: break;
3830: }
1.1.1.3 root 3831:
1.1.1.4 ! root 3832:
1.1 root 3833: case ENUMERAL_TYPE:
1.1.1.3 root 3834: obstack_1grow (&util_obstack, 'i');
1.1 root 3835: break;
3836: }
3837: }
3838:
3839: /*
3840: * support bitfields, the current version of Objective-C does not support
3841: * them. the string will consist of one or more "b:n"'s where n is an
3842: * integer describing the width of the bitfield. Currently, classes in
3843: * the kit implement a method "-(char *)describeBitfieldStruct:" that
3844: * simulates this...if they do not implement this method, the archiver
3845: * assumes the bitfield is 16 bits wide (padded if necessary) and packed
3846: * according to the GNU compiler. After looking at the "kit", it appears
3847: * that all classes currently rely on this default behavior, rather than
3848: * hand generating this string (which is tedious).
3849: */
3850: static void
1.1.1.3 root 3851: encode_bitfield (width, format)
1.1 root 3852: int width;
3853: int format;
3854: {
1.1.1.3 root 3855: char buffer[40];
3856: sprintf (buffer, "b%d", width);
3857: obstack_grow (&util_obstack, buffer, strlen (buffer));
1.1 root 3858: }
3859:
3860: /*
3861: * format will be:
3862: *
3863: * OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS
3864: */
3865: static void
1.1.1.3 root 3866: encode_type (type, format)
1.1 root 3867: tree type;
3868: int format;
3869: {
3870: enum tree_code code = TREE_CODE (type);
3871:
3872: if (code == INTEGER_TYPE)
3873: {
3874: if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0)
3875: {
3876: /* unsigned integer types */
3877:
3878: if (TYPE_MODE (type) == QImode) /* 'C' */
1.1.1.3 root 3879: obstack_1grow (&util_obstack, 'C');
1.1 root 3880: else if (TYPE_MODE (type) == HImode) /* 'S' */
1.1.1.3 root 3881: obstack_1grow (&util_obstack, 'S');
1.1 root 3882: else if (TYPE_MODE (type) == SImode)
3883: {
3884: if (type == long_unsigned_type_node)
1.1.1.3 root 3885: obstack_1grow (&util_obstack, 'L'); /* 'L' */
1.1 root 3886: else
1.1.1.3 root 3887: obstack_1grow (&util_obstack, 'I'); /* 'I' */
1.1 root 3888: }
3889: }
3890: else /* signed integer types */
3891: {
3892: if (TYPE_MODE (type) == QImode) /* 'c' */
1.1.1.3 root 3893: obstack_1grow (&util_obstack, 'c');
1.1 root 3894: else if (TYPE_MODE (type) == HImode) /* 's' */
1.1.1.3 root 3895: obstack_1grow (&util_obstack, 's');
1.1 root 3896: else if (TYPE_MODE (type) == SImode) /* 'i' */
3897: {
3898: if (type == long_integer_type_node)
1.1.1.3 root 3899: obstack_1grow (&util_obstack, 'l'); /* 'l' */
1.1 root 3900: else
1.1.1.3 root 3901: obstack_1grow (&util_obstack, 'i'); /* 'i' */
1.1 root 3902: }
3903: }
3904: }
3905: else if (code == REAL_TYPE)
3906: {
3907: /* floating point types */
3908:
3909: if (TYPE_MODE (type) == SFmode) /* 'f' */
1.1.1.3 root 3910: obstack_1grow (&util_obstack, 'f');
1.1 root 3911: else if (TYPE_MODE (type) == DFmode
3912: || TYPE_MODE (type) == TFmode) /* 'd' */
1.1.1.3 root 3913: obstack_1grow (&util_obstack, 'd');
1.1 root 3914: }
3915:
3916: else if (code == VOID_TYPE) /* 'v' */
1.1.1.3 root 3917: obstack_1grow (&util_obstack, 'v');
1.1 root 3918:
3919: else if (code == ARRAY_TYPE)
1.1.1.3 root 3920: encode_array (type, format);
1.1 root 3921:
3922: else if (code == POINTER_TYPE)
1.1.1.3 root 3923: encode_pointer (type, format);
1.1 root 3924:
3925: else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
1.1.1.3 root 3926: encode_aggregate (type, format);
1.1 root 3927:
3928: else if (code == FUNCTION_TYPE) /* '?' */
1.1.1.3 root 3929: obstack_1grow (&util_obstack, '?');
1.1 root 3930: }
3931:
3932: static void
1.1.1.3 root 3933: encode_field_decl (field_decl, format)
1.1 root 3934: tree field_decl;
3935: int format;
3936: {
3937: if (DECL_BIT_FIELD (field_decl))
1.1.1.3 root 3938: encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
1.1 root 3939: else
1.1.1.3 root 3940: encode_type (TREE_TYPE (field_decl), format);
1.1 root 3941: }
3942:
3943: static tree
3944: expr_last (complex_expr)
3945: tree complex_expr;
3946: {
3947: tree next;
3948:
3949: if (complex_expr)
3950: while (next = TREE_OPERAND (complex_expr, 0))
3951: complex_expr = next;
3952: return complex_expr;
3953: }
3954:
3955: /* The selector of the current method,
3956: or NULL if we aren't compiling a method. */
3957:
3958: tree
3959: maybe_objc_method_name (decl)
3960: tree decl;
3961: {
3962: if (method_context)
3963: return METHOD_SEL_NAME (method_context);
3964: else
3965: return 0;
3966: }
3967:
3968: /*
3969: * Transform a method definition into a function definition as follows:
3970: *
3971: * - synthesize the first two arguments, "self" and "_cmd".
3972: */
3973:
3974: void
3975: start_method_def (method)
3976: tree method;
3977: {
3978: tree decl_specs;
3979:
3980: /* required to implement _msgSuper () */
3981: method_context = method;
3982: _OBJC_SUPER_decl = NULLT;
3983:
3984: pushlevel (0); /* must be called BEFORE "start_function ()" */
3985:
3986: /* generate prototype declarations for arguments..."new-style" */
3987:
3988: if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
3989: decl_specs = build_tree_list (NULLT, _PRIVATE_record);
3990: else
3991: /* really a `struct objc_class *'...however we allow people to
3992: assign to self...which changes its type midstream.
3993: */
3994: decl_specs = build_tree_list (NULLT, objc_object_reference);
3995:
3996: push_parm_decl (build_tree_list (decl_specs,
3997: build1 (INDIRECT_REF, NULLT, self_id)));
3998:
3999: #ifdef OBJC_INT_SELECTORS
4000: decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
4001: decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
4002: push_parm_decl (build_tree_list (decl_specs, _cmd_id));
4003: #else /* not OBJC_INT_SELECTORS */
4004: decl_specs = build_tree_list (NULLT,
4005: xref_tag (RECORD_TYPE,
4006: get_identifier (TAG_SELECTOR)));
4007: push_parm_decl (build_tree_list (decl_specs,
4008: build1 (INDIRECT_REF, NULLT, _cmd_id)));
4009: #endif /* not OBJC_INT_SELECTORS */
4010:
1.1.1.3 root 4011: /* generate argument declarations if a keyword_decl */
1.1 root 4012: if (METHOD_SEL_ARGS (method))
4013: {
4014: tree arglist = METHOD_SEL_ARGS (method);
4015: do
4016: {
4017: tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
4018: tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
4019:
4020: if (arg_decl)
4021: {
4022: tree last_expr = expr_last (arg_decl);
4023:
4024: /* unite the abstract decl with its name */
4025: TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
4026: push_parm_decl (build_tree_list (arg_spec, arg_decl));
4027: /* unhook...restore the abstract declarator */
4028: TREE_OPERAND (last_expr, 0) = NULLT;
4029: }
4030: else
4031: push_parm_decl (build_tree_list (arg_spec, KEYWORD_ARG_NAME (arglist)));
4032:
4033: arglist = TREE_CHAIN (arglist);
4034: }
4035: while (arglist);
4036: }
4037:
4038: if (METHOD_ADD_ARGS (method) > (tree)1)
4039: {
4040: /* we have a variable length selector - in "prototype" format */
4041: tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
4042: while (akey)
4043: {
4044: /* this must be done prior to calling pushdecl (). pushdecl () is
4045: * going to change our chain on us...
4046: */
4047: tree nextkey = TREE_CHAIN (akey);
4048: pushdecl (akey);
4049: akey = nextkey;
4050: }
4051: }
4052: }
4053:
4054: static void
4055: error_with_method (message, mtype, method)
4056: char *message;
4057: char mtype;
4058: tree method;
4059: {
4060: count_error (0);
4061: fprintf (stderr, "%s:%d: ",
4062: DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
4063: bzero (errbuf, BUFSIZE);
4064: fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
4065: }
4066:
4067: static void
4068: warn_with_method (message, mtype, method)
4069: char *message;
4070: char mtype;
4071: tree method;
4072: {
4073: count_error (1);
4074: fprintf (stderr, "%s:%d: ",
4075: DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
4076: bzero (errbuf, BUFSIZE);
4077: fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
4078: }
4079:
4080: /* return 1 if `method' is consistent with `proto' */
4081:
4082: static int
4083: comp_method_with_proto (method, proto)
4084: tree method, proto;
4085: {
4086: static tree function_type = 0;
4087:
4088: /* create a function_type node once */
4089: if (!function_type)
4090: {
4091: struct obstack *ambient_obstack = current_obstack;
4092:
4093: current_obstack = &permanent_obstack;
4094: function_type = make_node (FUNCTION_TYPE);
4095: current_obstack = ambient_obstack;
4096: }
4097:
4098: /* install argument types - normally set by "build_function_type ()". */
4099: TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
4100:
4101: /* install return type */
4102: TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
4103:
4104: return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
4105: }
4106:
4107: /* return 1 if `proto1' is consistent with `proto2' */
4108:
4109: static int
4110: comp_proto_with_proto (proto1, proto2)
4111: tree proto1, proto2;
4112: {
4113: static tree function_type1 = 0, function_type2 = 0;
4114:
4115: /* create a couple function_type node's once */
4116: if (!function_type1)
4117: {
4118: struct obstack *ambient_obstack = current_obstack;
4119:
4120: current_obstack = &permanent_obstack;
4121: function_type1 = make_node (FUNCTION_TYPE);
4122: function_type2 = make_node (FUNCTION_TYPE);
4123: current_obstack = ambient_obstack;
4124: }
4125:
4126: /* install argument types - normally set by "build_function_type ()". */
4127: TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
4128: TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
4129:
4130: /* install return type */
4131: TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
4132: TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
4133:
4134: return comptypes (function_type1, function_type2);
4135: }
4136:
4137: /*
4138: * - generate an identifier for the function. the format is "_n_cls",
4139: * where 1 <= n <= nMethods, and cls is the name the implementation we
4140: * are processing.
4141: * - install the return type from the method declaration.
4142: * - if we have a prototype, check for type consistency.
4143: */
4144: static void
4145: really_start_method (method, parmlist)
4146: tree method, parmlist;
4147: {
4148: tree sc_spec, ret_spec, ret_decl, decl_specs;
4149: tree method_decl, method_id;
1.1.1.2 root 4150: char *buf;
1.1 root 4151:
4152: /* synth the storage class & assemble the return type */
4153: sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
4154: ret_spec = TREE_PURPOSE (TREE_TYPE (method));
4155: decl_specs = chainon (sc_spec, ret_spec);
4156:
4157: if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
1.1.1.2 root 4158: {
4159: /* Make sure this is big enough for any plausible method label. */
4160: buf = (char *) alloca (50
4161: + strlen (IDENTIFIER_POINTER (METHOD_SEL_NAME (method)))
4162: + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))));
1.1 root 4163: #ifdef OBJC_GEN_METHOD_LABEL
1.1.1.2 root 4164: OBJC_GEN_METHOD_LABEL (buf,
4165: TREE_CODE (method) == INSTANCE_METHOD_DECL,
4166: IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4167: NULL,
4168: IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
1.1 root 4169: #else
1.1.1.2 root 4170: sprintf (buf, "_%d_%s", ++method_slot,
4171: IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
1.1 root 4172: #endif
1.1.1.2 root 4173: }
1.1 root 4174: else /* we have a category */
1.1.1.2 root 4175: {
4176: /* Make sure this is big enough for any plausible method label. */
4177: buf = (char *) alloca (50
4178: + strlen (IDENTIFIER_POINTER (METHOD_SEL_NAME (method)))
4179: + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)))
4180: + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))));
1.1 root 4181: #ifdef OBJC_GEN_METHOD_LABEL
1.1.1.2 root 4182: OBJC_GEN_METHOD_LABEL (buf,
4183: TREE_CODE (method) == INSTANCE_METHOD_DECL,
4184: IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4185: IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)),
4186: IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
1.1 root 4187: #else
1.1.1.2 root 4188: sprintf (buf, "_%d_%s_%s", ++method_slot,
4189: IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
4190: IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
1.1 root 4191: #endif
1.1.1.2 root 4192: }
1.1 root 4193:
4194: method_id = get_identifier (buf);
4195:
4196: method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULLT);
4197:
1.1.1.3 root 4198: /* check the declarator portion of the return type for the method */
1.1 root 4199: if (ret_decl = TREE_VALUE (TREE_TYPE (method)))
4200: {
4201: /*
4202: * unite the complex decl (specified in the abstract decl) with the
4203: * function decl just synthesized...(int *), (int (*)()), (int (*)[]).
4204: */
4205: tree save_expr = expr_last (ret_decl);
4206:
4207: TREE_OPERAND (save_expr, 0) = method_decl;
4208: method_decl = ret_decl;
4209: /* fool the parser into thinking it is starting a function */
4210: start_function (decl_specs, method_decl, 0);
4211: /* unhook...this has the effect of restoring the abstract declarator */
4212: TREE_OPERAND (save_expr, 0) = NULLT;
4213: }
4214: else
4215: {
4216: TREE_VALUE (TREE_TYPE (method)) = method_decl;
4217: /* fool the parser into thinking it is starting a function */
4218: start_function (decl_specs, method_decl, 0);
4219: /* unhook...this has the effect of restoring the abstract declarator */
4220: TREE_VALUE (TREE_TYPE (method)) = NULLT;
4221: }
4222:
4223: METHOD_DEFINITION (method) = current_function_decl;
4224:
4225: /* check consistency...start_function (), pushdecl (), duplicate_decls (). */
4226:
4227: if (implementation_template != implementation_context)
4228: {
4229: tree chain, proto;
4230:
4231: if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
4232: chain = CLASS_NST_METHODS (implementation_template);
4233: else
4234: chain = CLASS_CLS_METHODS (implementation_template);
4235:
4236: if (proto = lookup_method (chain, METHOD_SEL_NAME (method)))
4237: {
4238: if (!comp_method_with_proto (method, proto))
4239: {
4240: fprintf (stderr, "%s: In method `%s'\n", input_filename,
4241: IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4242: if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
4243: {
4244: error_with_method ("conflicting types for", '-', method);
4245: error_with_method ("previous declaration of", '-', proto);
4246: }
4247: else
4248: {
4249: error_with_method ("conflicting types for", '+', method);
4250: error_with_method ("previous declaration of", '+', proto);
4251: }
4252: }
4253: }
4254: }
4255: }
4256:
4257: /*
4258: * the following routine is always called...this "architecture" is to
4259: * accommodate "old-style" variable length selectors.
4260: *
4261: * - a:a b:b // prototype ; id c; id d; // old-style
4262: */
4263: void
4264: continue_method_def ()
4265: {
4266: tree parmlist;
4267:
4268: if (METHOD_ADD_ARGS (method_context) == (tree)1)
4269: /*
4270: * we have a `, ...' immediately following the selector.
4271: */
4272: parmlist = get_parm_info (0);
4273: else
4274: parmlist = get_parm_info (1); /* place a `void_at_end' */
4275:
4276: /* set self_decl from the first argument...this global is used by
4277: * build_ivar_reference ().build_indirect_ref ().
4278: */
4279: self_decl = TREE_PURPOSE (parmlist);
4280:
4281: poplevel (0, 0, 0); /* must be called BEFORE "start_function ()" */
4282:
4283: really_start_method (method_context, parmlist);
4284:
4285: store_parm_decls (); /* must be called AFTER "start_function ()" */
4286: }
4287:
4288: void
4289: add_objc_decls ()
4290: {
4291: if (!_OBJC_SUPER_decl)
4292: _OBJC_SUPER_decl = start_decl (get_identifier (_TAG_SUPER),
4293: build_tree_list (NULLT, objc_super_template), 0);
4294:
4295: /* this prevents `unused variable' warnings when compiling with `-Wall' */
1.1.1.4 ! root 4296: DECL_IN_SYSTEM_HEADER (_OBJC_SUPER_decl) = 1;
1.1 root 4297: }
4298:
4299: /*
4300: * _n_Method (id self, SEL sel, ...)
4301: * {
4302: * struct objc_super _S;
4303: *
4304: * _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
4305: * }
4306: */
4307: tree
4308: get_super_receiver ()
4309: {
4310: if (method_context)
4311: {
4312: tree super_expr, super_expr_list;
4313:
4314: /* set receiver to self */
4315: super_expr = build_component_ref (_OBJC_SUPER_decl, self_id);
4316: super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
4317: super_expr_list = build_tree_list (NULLT, super_expr);
4318:
4319: /* set class to begin searching */
4320: super_expr = build_component_ref (_OBJC_SUPER_decl, get_identifier ("class"));
4321:
4322: if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
4323: {
4324: /* [_cls, __cls]Super are "pre-built" in synth_foward_declarations () */
4325:
4326: if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4327: super_expr = build_modify_expr (super_expr, NOP_EXPR, _clsSuper_ref);
4328: else
4329: super_expr = build_modify_expr (super_expr, NOP_EXPR, __clsSuper_ref);
4330: }
4331: else /* we have a category... */
4332: {
4333: tree params, super_name = CLASS_SUPER_NAME (implementation_template);
4334: tree funcCall;
4335:
4336: if (!super_name) /* Barf if super used in a category of Object. */
4337: {
4338: error("no super class declared in interface for `%s'",
4339: IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4340: return error_mark_node;
4341: }
4342:
4343: add_class_reference (super_name);
4344:
4345: params = build_tree_list (NULLT,
4346: my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
4347: IDENTIFIER_POINTER (super_name)));
4348:
4349: if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4350: funcCall = build_function_call (objc_getClass_decl, params);
4351: else
4352: funcCall = build_function_call (objc_getMetaClass_decl, params);
4353:
4354: /* cast! */
4355: TREE_TYPE (funcCall) = TREE_TYPE (_clsSuper_ref);
4356: super_expr = build_modify_expr (super_expr, NOP_EXPR, funcCall);
4357: }
4358: chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
4359:
4360: super_expr = build_unary_op (ADDR_EXPR, _OBJC_SUPER_decl, 0);
4361: chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
4362:
4363: return build_compound_expr (super_expr_list);
4364: }
4365: else
4366: {
4367: error ("[super ...] must appear in a method context");
4368: return error_mark_node;
4369: }
4370: }
4371:
4372: static tree
4373: encode_method_def (func_decl)
4374: tree func_decl;
4375: {
4376: tree parms;
4377: int stack_size = 0;
1.1.1.3 root 4378: char buffer[40];
4379: tree result;
1.1 root 4380:
4381: /* return type */
1.1.1.3 root 4382: encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
1.1 root 4383: OBJC_ENCODE_DONT_INLINE_DEFS);
4384: /* stack size */
4385: for (parms = DECL_ARGUMENTS (func_decl); parms;
4386: parms = TREE_CHAIN (parms))
4387: stack_size += TREE_INT_CST_LOW (TYPE_SIZE (DECL_ARG_TYPE (parms)))
4388: / BITS_PER_UNIT;
4389:
1.1.1.3 root 4390: sprintf (buffer, "%d", stack_size);
4391: obstack_grow (&util_obstack, buffer, strlen (buffer));
1.1 root 4392:
4393: /* argument types */
4394: for (parms = DECL_ARGUMENTS (func_decl); parms;
4395: parms = TREE_CHAIN (parms))
4396: {
4397: int offset_in_bytes;
4398:
4399: /* type */
1.1.1.3 root 4400: encode_type (TREE_TYPE (parms), OBJC_ENCODE_DONT_INLINE_DEFS);
1.1 root 4401:
4402: /* compute offset */
4403: if (GET_CODE (DECL_INCOMING_RTL (parms)) == MEM)
4404: {
4405: rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
4406:
4407: /* ??? Here we assume that the parm address is indexed
4408: off the frame pointer or arg pointer.
4409: If that is not true, we produce meaningless results,
4410: but do not crash. */
4411: if (GET_CODE (addr) == PLUS
4412: && GET_CODE (XEXP (addr, 1)) == CONST_INT)
4413: offset_in_bytes = INTVAL (XEXP (addr, 1));
4414: else
4415: offset_in_bytes = 0;
4416:
4417: /* This is the case where the parm is passed as an int or double
4418: and it is converted to a char, short or float and stored back
4419: in the parmlist. In this case, describe the parm
4420: with the variable's declared type, and adjust the address
4421: if the least significant bytes (which we are using) are not
4422: the first ones. */
4423: #if BYTES_BIG_ENDIAN
4424: if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
4425: offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
4426: - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
4427: #endif
4428: }
4429: else
4430: offset_in_bytes = 0;
4431:
4432: /* The "+ 4" is a total hack to account for the return pc and
4433: saved fp on the 68k. We should redefine this format! */
1.1.1.3 root 4434: sprintf (buffer, "%d", offset_in_bytes + 8);
4435: obstack_grow (&util_obstack, buffer, strlen (buffer));
1.1 root 4436: }
4437:
1.1.1.3 root 4438: result = get_identifier (obstack_finish (&util_obstack));
4439: obstack_free (&util_obstack, util_firstobj);
4440: return result;
1.1 root 4441: }
4442:
4443: void
4444: finish_method_def ()
4445: {
4446: METHOD_ENCODING (method_context) =
4447: encode_method_def (current_function_decl);
4448:
4449: finish_function (0);
4450:
4451: /* this must be done AFTER finish_function, since the optimizer may
4452: find "may be used before set" errors. */
4453: method_context = NULLT; /* required to implement _msgSuper () */
4454: }
4455:
4456: int
4457: lang_report_error_function (decl)
4458: tree decl;
4459: {
4460: if (method_context)
4461: {
4462: fprintf (stderr, "In method `%s'\n",
4463: IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
4464: return 1;
4465: }
4466: else
4467: return 0;
4468: }
4469:
4470: static int
4471: is_complex_decl (type)
4472: tree type;
4473: {
4474: return (TREE_CODE (type) == ARRAY_TYPE
4475: || TREE_CODE (type) == FUNCTION_TYPE
4476: || TREE_CODE (type) == POINTER_TYPE);
4477: }
4478:
4479:
4480: /* Code to convert a decl node into text for a declaration in C. */
4481:
4482: static char tmpbuf[256];
4483:
4484: static void
4485: adorn_decl (decl, str)
4486: tree decl;
4487: char *str;
4488: {
4489: enum tree_code code = TREE_CODE (decl);
4490:
4491: if (code == ARRAY_REF)
4492: {
4493: tree anIntCst = TREE_OPERAND (decl, 1);
4494:
4495: sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (anIntCst));
4496: }
4497: else if (code == ARRAY_TYPE)
4498: {
4499: tree anIntCst = TYPE_SIZE (decl);
4500: tree array_of = TREE_TYPE (decl);
4501:
4502: sprintf (str + strlen (str), "[%d]",
4503: TREE_INT_CST_LOW (anIntCst)/TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
4504: }
4505: else if (code == CALL_EXPR)
4506: strcat (str, "()");
4507: else if (code == FUNCTION_TYPE)
4508: {
4509: tree chain = TYPE_ARG_TYPES (decl); /* a list of types */
4510: strcat (str, "(");
4511: while (chain && TREE_VALUE (chain) != void_type_node)
4512: {
4513: gen_declaration (TREE_VALUE (chain), str);
4514: chain = TREE_CHAIN (chain);
4515: if (chain && TREE_VALUE (chain) != void_type_node)
4516: strcat (str, ",");
4517: }
4518: strcat (str, ")");
4519: }
4520: else
4521: {
4522: strcpy (tmpbuf, "*"); strcat (tmpbuf, str);
4523: strcpy (str, tmpbuf);
4524: }
4525: }
4526:
4527: static char *
4528: gen_declarator (decl, buf, name)
4529: tree decl;
4530: char *buf;
4531: char *name;
4532: {
4533: if (decl)
4534: {
4535: enum tree_code code = TREE_CODE (decl);
4536: char *str;
4537: tree op;
4538: int wrap = 0;
4539:
4540: switch (code)
4541: {
4542: case ARRAY_REF: case INDIRECT_REF: case CALL_EXPR:
4543: {
4544: op = TREE_OPERAND (decl, 0);
4545:
4546: /* we have a pointer to a function or array...(*)(), (*)[] */
4547: if ((code == ARRAY_REF || code == CALL_EXPR) &&
4548: (op && TREE_CODE (op) == INDIRECT_REF))
4549: wrap = 1;
4550:
4551: str = gen_declarator (op, buf, name);
4552:
4553: if (wrap)
4554: {
4555: strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
4556: strcpy (str, tmpbuf);
4557: }
4558:
4559: adorn_decl (decl, str);
4560: break;
4561: }
4562: case ARRAY_TYPE: case FUNCTION_TYPE: case POINTER_TYPE:
4563: {
4564: str = strcpy (buf, name);
4565:
4566: /* this clause is done iteratively...rather than recursively */
4567: do
4568: {
4569: op = is_complex_decl (TREE_TYPE (decl))
4570: ? TREE_TYPE (decl)
4571: : NULLT;
4572:
4573: adorn_decl (decl, str);
4574:
4575: /* we have a pointer to a function or array...(*)(), (*)[] */
4576: if ((code == POINTER_TYPE) &&
4577: (op && (TREE_CODE (op) == FUNCTION_TYPE
4578: || TREE_CODE (op) == ARRAY_TYPE)))
4579: {
4580: strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
4581: strcpy (str, tmpbuf);
4582: }
4583:
4584: decl = is_complex_decl (TREE_TYPE (decl))
4585: ? TREE_TYPE (decl)
4586: : NULLT;
4587: }
4588: while (decl && (code = TREE_CODE (decl)));
4589:
4590: break;
4591: }
4592: case IDENTIFIER_NODE:
4593: /* will only happen if we are processing a "raw" expr-decl. */
4594: return strcpy (buf, IDENTIFIER_POINTER (decl));
4595: }
4596:
4597: return str;
4598: }
4599: else /* we have an abstract declarator or a _DECL node */
4600: {
4601: return strcpy (buf, name);
4602: }
4603: }
4604:
4605: static void
4606: gen_declspecs (declspecs, buf, raw)
4607: tree declspecs;
4608: char *buf;
4609: int raw;
4610: {
4611: if (raw)
4612: {
4613: tree chain;
4614:
4615: for (chain = declspecs; chain; chain = TREE_CHAIN (chain))
4616: {
4617: tree aspec = TREE_VALUE (chain);
4618:
4619: if (TREE_CODE (aspec) == IDENTIFIER_NODE)
4620: strcat (buf, IDENTIFIER_POINTER (aspec));
4621: else if (TREE_CODE (aspec) == RECORD_TYPE)
4622: {
4623: if (TYPE_NAME (aspec))
4624: {
4625: if (!TREE_STATIC_TEMPLATE (aspec))
4626: strcat (buf, "struct ");
4627: strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4628: }
4629: else
4630: strcat (buf, "untagged struct");
4631: }
4632: else if (TREE_CODE (aspec) == UNION_TYPE)
4633: {
4634: if (TYPE_NAME (aspec))
4635: {
4636: if (!TREE_STATIC_TEMPLATE (aspec))
4637: strcat (buf, "union ");
4638: strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4639: }
4640: else
4641: strcat (buf, "untagged union");
4642: }
4643: else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
4644: {
4645: if (TYPE_NAME (aspec))
4646: {
4647: if (!TREE_STATIC_TEMPLATE (aspec))
4648: strcat (buf, "enum ");
4649: strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
4650: }
4651: else
4652: strcat (buf, "untagged enum");
4653: }
4654: strcat (buf, " ");
4655: }
4656: }
4657: else
4658: switch (TREE_CODE (declspecs))
4659: {
4660: /* type specifiers */
4661:
4662: case INTEGER_TYPE: /* signed integer types */
4663:
4664: if (declspecs == short_integer_type_node) /* 's' */
4665: strcat (buf, "short int ");
4666: else if (declspecs == integer_type_node) /* 'i' */
4667: strcat (buf, "int ");
4668: else if (declspecs == long_integer_type_node) /* 'l' */
4669: strcat (buf, "long int ");
4670: else if (declspecs == signed_char_type_node || /* 'c' */
4671: declspecs == char_type_node)
4672: strcat (buf, "char ");
4673:
4674: /* unsigned integer types */
4675:
4676: else if (declspecs == short_unsigned_type_node) /* 'S' */
4677: strcat (buf, "unsigned short ");
4678: else if (declspecs == unsigned_type_node) /* 'I' */
4679: strcat (buf, "unsigned int ");
4680: else if (declspecs == long_unsigned_type_node) /* 'L' */
4681: strcat (buf, "unsigned long ");
4682: else if (declspecs == unsigned_char_type_node) /* 'C' */
4683: strcat (buf, "unsigned char ");
4684: break;
4685:
4686: case REAL_TYPE: /* floating point types */
4687:
4688: if (declspecs == float_type_node) /* 'f' */
4689: strcat (buf, "float ");
4690: else if (declspecs == double_type_node) /* 'd' */
4691: strcat (buf, "double ");
4692: else if (declspecs == long_double_type_node) /* 'd' */
4693: strcat (buf, "long double ");
4694: break;
4695:
4696: case RECORD_TYPE:
4697: if (!TREE_STATIC_TEMPLATE (declspecs))
4698: strcat (buf, "struct ");
4699: if (TYPE_NAME (declspecs) &&
4700: (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4701: {
4702: strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4703: strcat (buf, " ");
4704: }
4705: break;
4706: case UNION_TYPE:
4707: strcat (buf, "union ");
4708: if (TYPE_NAME (declspecs) &&
4709: (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4710: {
4711: strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4712: strcat (buf, " ");
4713: }
4714: break;
4715: case ENUMERAL_TYPE:
4716: strcat (buf, "enum ");
4717: if (TYPE_NAME (declspecs) &&
4718: (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
4719: {
4720: strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
4721: strcat (buf, " ");
4722: }
4723: break;
4724: case VOID_TYPE:
4725: strcat (buf, "void ");
4726: }
4727: }
4728:
4729: static char *
4730: gen_declaration (atype_or_adecl, buf)
4731: tree atype_or_adecl;
4732: char *buf;
4733: {
4734: char declbuf[256];
4735:
4736: if (TREE_CODE (atype_or_adecl) == TREE_LIST)
4737: {
4738: tree declspecs; /* "identifier_node", "record_type" */
4739: tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
4740:
1.1.1.3 root 4741: /* we have a "raw", abstract declarator (typename) */
1.1 root 4742: declarator = TREE_VALUE (atype_or_adecl);
4743: declspecs = TREE_PURPOSE (atype_or_adecl);
4744:
4745: gen_declspecs (declspecs, buf, 1);
4746: strcat (buf, gen_declarator (declarator, declbuf, ""));
4747: }
4748: else
4749: {
4750: tree atype;
4751: tree declspecs; /* "integer_type", "real_type", "record_type"... */
4752: tree declarator; /* "array_type", "function_type", "pointer_type". */
4753:
4754: if (TREE_CODE (atype_or_adecl) == FIELD_DECL
4755: || TREE_CODE (atype_or_adecl) == PARM_DECL
4756: || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
4757: atype = TREE_TYPE (atype_or_adecl);
4758: else
4759: atype = atype_or_adecl; /* assume we have a *_type node */
4760:
4761: if (is_complex_decl (atype))
4762: {
4763: tree chain;
4764:
4765: /* get the declaration specifier...it is at the end of the list */
4766: declarator = chain = atype;
4767: do
4768: chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
4769: while (is_complex_decl (chain));
4770: declspecs = chain;
4771: }
4772: else
4773: {
4774: declspecs = atype;
4775: declarator = NULLT;
4776: }
4777:
4778: gen_declspecs (declspecs, buf, 0);
4779:
4780: if (TREE_CODE (atype_or_adecl) == FIELD_DECL
4781: || TREE_CODE (atype_or_adecl) == PARM_DECL
4782: || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
4783: {
4784: if (declarator)
4785: {
4786: strcat (buf, gen_declarator (declarator, declbuf,
4787: IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))));
4788: }
4789: else
4790: strcat (buf, IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)));
4791: }
4792: else
4793: {
4794: strcat (buf, gen_declarator (declarator, declbuf, ""));
4795: }
4796: }
4797: return buf;
4798: }
4799:
4800: #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
4801:
4802: static char *
4803: gen_method_decl (method, buf)
4804: tree method;
4805: char *buf;
4806: {
4807: tree chain;
4808:
4809: if (RAW_TYPESPEC (method) != objc_object_reference)
4810: {
4811: strcpy (buf, "(");
4812: gen_declaration (TREE_TYPE (method), buf);
4813: strcat (buf, ")");
4814: }
4815:
4816: chain = METHOD_SEL_ARGS (method);
4817: if (chain)
4818: { /* we have a chain of keyword_decls */
4819: do
4820: {
4821: if (KEYWORD_KEY_NAME (chain))
4822: strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
4823:
4824: strcat (buf, ":");
4825: if (RAW_TYPESPEC (chain) != objc_object_reference)
4826: {
4827: strcat (buf, "(");
4828: gen_declaration (TREE_TYPE (chain), buf);
4829: strcat (buf, ")");
4830: }
4831: strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
4832: if (chain = TREE_CHAIN (chain))
4833: strcat (buf, " ");
4834: }
4835: while (chain);
4836:
4837: if (METHOD_ADD_ARGS (method) == (tree)1)
4838: strcat (buf, ", ...");
4839: else if (METHOD_ADD_ARGS (method))
4840: { /* we have a tree list node as generate by `get_parm_info ()' */
4841: chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
4842: /* know we have a chain of parm_decls */
4843: while (chain)
4844: {
4845: strcat (buf, ", ");
4846: gen_declaration (chain, buf);
4847: chain = TREE_CHAIN (chain);
4848: }
4849: }
4850: }
4851: else /* we have a unary selector */
4852: {
4853: strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
4854: }
4855:
4856: return buf;
4857: }
4858:
4859: void
4860: gen_prototype (fp, decl)
4861: FILE *fp;
4862: tree decl;
4863: {
4864: /* we have a function definition - generate prototype */
4865: bzero (errbuf, BUFSIZE);
4866: gen_declaration (decl, errbuf);
4867: fprintf (fp, "%s;\n", errbuf);
4868: }
4869: /*
4870: * debug info...
4871: */
4872: static void
4873: dump_interface (fp, chain)
4874: FILE *fp;
4875: tree chain;
4876: {
4877: char *buf = (char *)xmalloc (256);
4878: char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
4879: tree ivar_decls = CLASS_RAW_IVARS (chain);
4880: tree nst_methods = CLASS_NST_METHODS (chain);
4881: tree cls_methods = CLASS_CLS_METHODS (chain);
4882:
4883: fprintf (fp, "\n@interface %s", my_name);
4884:
4885: if (CLASS_SUPER_NAME (chain))
4886: {
4887: char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
4888: fprintf (fp, " : %s\n", super_name);
4889: }
4890: else
4891: fprintf (fp, "\n");
4892:
4893: if (ivar_decls)
4894: {
4895: fprintf (fp, "{\n");
4896: do
4897: {
4898: bzero (buf, 256);
4899: fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
4900: ivar_decls = TREE_CHAIN (ivar_decls);
4901: }
4902: while (ivar_decls);
4903: fprintf (fp, "}\n");
4904: }
4905:
4906: while (nst_methods)
4907: {
4908: bzero (buf, 256);
4909: fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
4910: nst_methods = TREE_CHAIN (nst_methods);
4911: }
4912:
4913: while (cls_methods)
4914: {
4915: bzero (buf, 256);
4916: fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
4917: cls_methods = TREE_CHAIN (cls_methods);
4918: }
4919: fprintf (fp, "\n@end");
4920: }
4921:
4922: void
4923: init_objc ()
4924: {
4925: /* Add the special tree codes of Objective C to the tables. */
4926:
1.1.1.3 root 4927: gcc_obstack_init (&util_obstack);
4928: util_firstobj = (char *) obstack_finish (&util_obstack);
4929:
1.1 root 4930: tree_code_type
4931: = (char **) realloc (tree_code_type,
4932: sizeof (char *) * LAST_OBJC_TREE_CODE);
4933: tree_code_length
4934: = (int *) realloc (tree_code_length,
4935: sizeof (int) * LAST_OBJC_TREE_CODE);
4936: tree_code_name
4937: = (char **) realloc (tree_code_name,
4938: sizeof (char *) * LAST_OBJC_TREE_CODE);
4939: bcopy (objc_tree_code_type,
4940: tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
4941: (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4942: * sizeof (char *)));
4943: bcopy (objc_tree_code_length,
4944: tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
4945: (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4946: * sizeof (int)));
4947: bcopy (objc_tree_code_name,
4948: tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
4949: (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
4950: * sizeof (char *)));
4951:
4952: errbuf = (char *)xmalloc (BUFSIZE);
4953: hash_init ();
4954: synth_module_prologue ();
4955: }
1.1.1.3 root 4956:
1.1 root 4957: void
4958: finish_objc ()
4959: {
4960: struct imp_entry *impent;
4961: tree chain;
4962:
4963: generate_forward_declaration_to_string_table ();
4964:
4965: #ifdef OBJC_PROLOGUE
4966: OBJC_PROLOGUE;
4967: #endif
4968:
4969: if (implementation_context || sel_refdef_chain)
4970: generate_objc_symtab_decl ();
4971:
4972: for (impent = imp_list; impent; impent = impent->next)
4973: {
4974: implementation_context = impent->imp_context;
4975: implementation_template = impent->imp_template;
4976:
4977: _OBJC_CLASS_decl = impent->class_decl;
4978: _OBJC_METACLASS_decl = impent->meta_decl;
4979:
4980: if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
4981: {
4982: /* all of the following reference the string pool... */
4983: generate_ivar_lists ();
4984: generate_dispatch_tables ();
4985: generate_shared_structures ();
4986: }
4987: else
4988: {
4989: generate_dispatch_tables ();
4990: generate_category (implementation_context);
4991: }
4992: }
4993:
1.1.1.4 ! root 4994: /* If we are using an array of selectors, we must always
! 4995: finish up the array decl even if no selectors were used. */
! 4996: #ifndef OBJC_SELECTORS_WITHOUT_LABELS
1.1 root 4997: if (sel_ref_chain)
1.1.1.4 ! root 4998: #endif
1.1 root 4999: build_selector_translation_table ();
5000:
5001: if (implementation_context || sel_refdef_chain)
5002: {
5003: /* Arrange for Objc data structures to be initialized at run time. */
5004:
5005: char *init_name = build_module_descriptor ();
5006: if (init_name)
5007: assemble_constructor (init_name);
5008: }
5009:
5010: /* dump the string table last */
5011:
5012: if (sel_refdef_chain)
5013: {
5014: build_message_selector_pool ();
5015: }
5016:
5017: /* dump the class references...this forces the appropriate classes
5018: to be linked into the executable image, preserving unix archive
5019: semantics...this can be removed when we move to a more dynamically
5020: linked environment
5021: */
5022: for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
1.1.1.3 root 5023: handle_class_ref (chain);
1.1 root 5024:
5025: for (impent = imp_list; impent; impent = impent->next)
1.1.1.3 root 5026: handle_impent (impent);
1.1 root 5027:
5028: #if 0 /* If GAS has such a bug, let's fix it. */
5029: /*** this fixes a gross bug in the assembler...it `expects' #APP to have
5030: *** a matching #NO_APP, or it crashes (sometimes). app_disable () will
5031: *** insure this is the case. 5/19/89, s.naroff.
5032: ***/
5033: if (cls_ref_chain || imp_list)
5034: app_disable ();
5035: #endif
5036:
5037: if (flag_gen_declaration)
5038: {
5039: add_class (implementation_context);
5040: dump_interface (gen_declaration_file, implementation_context);
5041: }
5042: if (warn_selector)
5043: {
5044: int slot;
5045:
5046: /* Run through the selector hash tables and print a warning for any
5047: selector which has multiple methods. */
5048:
5049: for (slot = 0; slot < SIZEHASHTABLE; slot++)
5050: {
5051: hash hsh;
5052:
5053: for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
5054: {
5055: if (hsh->list)
5056: {
5057: tree meth = hsh->key;
5058: char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5059: ? '-' : '+';
5060: attr loop;
5061:
5062: warning ("potential selector conflict for method `%s'",
5063: IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5064: warn_with_method ("found", type, meth);
5065: for (loop = hsh->list; loop; loop = loop->next)
5066: warn_with_method ("found", type, loop->value);
5067: }
5068: }
5069: }
5070:
5071: for (slot = 0; slot < SIZEHASHTABLE; slot++)
5072: {
5073: hash hsh;
5074:
5075: for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
5076: {
5077: if (hsh->list)
5078: {
5079: tree meth = hsh->key;
5080: char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5081: ? '-' : '+';
5082: attr loop;
5083:
5084: warning ("potential selector conflict for method `%s'",
5085: IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
5086: warn_with_method ("found", type, meth);
5087: for (loop = hsh->list; loop; loop = loop->next)
5088: warn_with_method ("found", type, loop->value);
5089: }
5090: }
5091: }
5092: }
5093: }
1.1.1.3 root 5094:
5095: /* Subroutines of finish_objc. */
5096:
5097: handle_class_ref (chain)
5098: tree chain;
5099: {
5100: tree decl;
5101: char *string
5102: = (char *) alloca (strlen (IDENTIFIER_POINTER (TREE_VALUE (chain))) + 30);
5103:
1.1.1.4 ! root 5104: sprintf (string, "__objc_class_name_%s",
1.1.1.3 root 5105: IDENTIFIER_POINTER (TREE_VALUE (chain)));
5106:
5107: /* Make a decl for this name, so we can use its address in a tree. */
5108: decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
1.1.1.4 ! root 5109: DECL_EXTERNAL (decl) = 1;
1.1.1.3 root 5110: TREE_PUBLIC (decl) = 1;
5111:
5112: pushdecl (decl);
5113: rest_of_decl_compilation (decl, 0, 0, 0);
5114:
5115: /* Make following constant read-only (why not)? */
5116: text_section ();
5117:
5118: /* Output a constant to reference this address. */
5119: output_constant (build1 (ADDR_EXPR, string_type_node, decl),
5120: int_size_in_bytes (string_type_node));
5121: }
1.1 root 5122:
1.1.1.3 root 5123: handle_impent (impent)
5124: struct imp_entry *impent;
5125: {
5126: implementation_context = impent->imp_context;
5127: implementation_template = impent->imp_template;
5128:
5129: if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
5130: {
5131: char *string
5132: = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))) + 30);
5133:
1.1.1.4 ! root 5134: sprintf (string, "__objc_class_name_%s",
1.1.1.3 root 5135: IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
5136: assemble_global (string);
5137: assemble_label (string);
5138: }
5139: else if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
5140: {
5141: char *string
5142: = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)))
5143: + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)))
5144: + 30);
5145:
5146: /* Do the same for categories. Even though no references to these
5147: symbols are generated automatically by the compiler, it gives
5148: you a handle to pull them into an archive by hand. */
1.1.1.4 ! root 5149: sprintf (string, "__objc_category_name_%s_%s",
1.1.1.3 root 5150: IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
5151: IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
5152: assemble_global (string);
5153: assemble_label (string);
5154: }
5155: }
5156:
1.1 root 5157: #ifdef DEBUG
5158:
5159: static void
5160: objc_debug (fp)
5161: FILE *fp;
5162: {
5163: char *buf = (char *)xmalloc (256);
5164:
5165: { /* dump function prototypes */
5166: tree loop = _OBJC_MODULES_decl;
5167:
5168: fprintf (fp, "\n\nfunction prototypes:\n");
5169: while (loop)
5170: {
5171: if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
5172: {
5173: /* we have a function definition - generate prototype */
5174: bzero (errbuf, BUFSIZE);
5175: gen_declaration (loop, errbuf);
5176: fprintf (fp, "%s;\n", errbuf);
5177: }
5178: loop = TREE_CHAIN (loop);
5179: }
5180: }
5181: { /* dump global chains */
5182: tree loop;
5183: int i, index = 0, offset = 0;
5184: hash hashlist;
5185:
5186: for (i = 0; i < SIZEHASHTABLE; i++)
5187: {
5188: if (hashlist = nst_method_hash_list[i])
5189: {
5190: fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
5191: do
5192: {
5193: bzero (buf, 256);
5194: fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
5195: hashlist = hashlist->next;
5196: }
5197: while (hashlist);
5198: }
5199: }
5200: for (i = 0; i < SIZEHASHTABLE; i++)
5201: {
5202: if (hashlist = cls_method_hash_list[i])
5203: {
5204: fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
5205: do
5206: {
5207: bzero (buf, 256);
5208: fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
5209: hashlist = hashlist->next;
5210: }
5211: while (hashlist);
5212: }
5213: }
5214: fprintf (fp, "\nsel_refdef_chain:\n");
5215: for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
5216: {
5217: fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
5218: IDENTIFIER_POINTER (TREE_VALUE (loop)));
5219: index++;
5220: /* add one for the '\0' character */
5221: offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
5222: }
5223: fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
5224: }
5225: }
5226: #endif
5227:
5228: void
5229: print_lang_statistics ()
5230: {
5231: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.