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