Added support for the 64-bit Apple Objective-C runtime
[official-gcc.git] / gcc / objc / objc-gnu-runtime-abi-01.c
bloba13f0158b1c47f7ce68e02ac68528004f2a06c08
1 /* GNU Runtime (ABI-0/1) private.
2 Copyright (C) 2011 Free Software Foundation, Inc.
3 Contributed by Iain Sandoe (split from objc-act.c)
5 This file is part of GCC.
7 GCC 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 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
27 #ifdef OBJCPLUS
28 #include "cp-tree.h"
29 #else
30 #include "c-tree.h"
31 #include "c-lang.h"
32 #endif
34 #include "langhooks.h"
35 #include "c-family/c-objc.h"
36 #include "objc-act.h"
38 /* When building Objective-C++, we are not linking against the C front-end
39 and so need to replicate the C tree-construction functions in some way. */
40 #ifdef OBJCPLUS
41 #define OBJCP_REMAP_FUNCTIONS
42 #include "objcp-decl.h"
43 #endif /* OBJCPLUS */
45 #include "toplev.h"
46 #include "ggc.h"
47 #include "tree-iterator.h"
49 #include "objc-runtime-hooks.h"
50 #include "objc-runtime-shared-support.h"
52 /* GNU runtime private definitions. */
53 #define DEF_CONSTANT_STRING_CLASS_NAME "NXConstantString"
55 #define TAG_GETCLASS "objc_get_class"
56 #define TAG_GETMETACLASS "objc_get_meta_class"
58 #define TAG_MSGSEND "objc_msg_lookup"
59 #define TAG_MSGSENDSUPER "objc_msg_lookup_super"
61 /* GNU-specific tags. */
63 #define TAG_EXECCLASS "__objc_exec_class"
64 #define TAG_GNUINIT "__objc_gnu_init"
66 /* The version identifies which language generation and runtime
67 the module (file) was compiled for, and is recorded in the
68 module descriptor. */
69 #define OBJC_VERSION 8
71 #define PROTOCOL_VERSION 2
73 /* This macro provides a method of removing ambiguity between runtimes
74 when LTO is in use on targets supporting multiple runtimes.
76 For example, at present, any target that includes an implementation of
77 the NeXT runtime needs to place Objective-C meta-data into specific
78 named sections. This should _not_ be done for the GNU runtime, and the
79 folowing macro is used to attach Objective-C private attributes that may
80 be used to identify the runtime for which the meta-data are intended. */
82 #define OBJCMETA(DECL,VERS,KIND) \
83 if (VERS) \
84 DECL_ATTRIBUTES (DECL) = build_tree_list ((VERS), (KIND));
86 #ifndef TARGET_64BIT
87 #define TARGET_64BIT 0
88 #endif
90 static void gnu_runtime_01_initialize (void);
92 static void build_selector_template (void);
94 static tree gnu_runtime_abi_01_super_superclassfield_id (void);
96 static tree gnu_runtime_abi_01_class_decl (tree);
97 static tree gnu_runtime_abi_01_metaclass_decl (tree);
98 static tree gnu_runtime_abi_01_category_decl (tree);
99 static tree gnu_runtime_abi_01_protocol_decl (tree);
100 static tree gnu_runtime_abi_01_string_decl (tree, const char *, string_section);
102 static tree gnu_runtime_abi_01_get_class_reference (tree);
103 static tree gnu_runtime_abi_01_build_typed_selector_reference (location_t, tree,
104 tree);
105 static tree gnu_runtime_abi_01_get_protocol_reference (location_t, tree);
106 static tree gnu_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
107 static tree gnu_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
108 static tree gnu_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
110 static tree gnu_runtime_abi_01_receiver_is_class_object (tree);
111 static tree gnu_runtime_abi_01_get_arg_type_list_base (tree, int, int);
112 static tree gnu_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
113 tree, tree, tree, int);
115 static bool gnu_runtime_abi_01_setup_const_string_class_decl (void);
116 static tree gnu_runtime_abi_01_build_const_string_constructor (location_t, tree,int);
118 static void objc_generate_v1_gnu_metadata (void);
120 static tree objc_eh_runtime_type (tree type);
121 static tree objc_eh_personality (void);
122 static tree objc_build_exc_ptr (struct objc_try_context **);
123 static tree build_throw_stmt (location_t, tree, bool);
124 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
125 static void finish_catch (struct objc_try_context **, tree);
126 static tree finish_try_stmt (struct objc_try_context **);
128 bool
129 objc_gnu_runtime_abi_01_init (objc_runtime_hooks *rthooks)
131 /* GNU runtime does not need the compiler to change code in order to do GC. */
132 if (flag_objc_gc)
134 warning_at (0, 0, "%<-fobjc-gc%> is ignored for %<-fgnu-runtime%>");
135 flag_objc_gc = 0;
138 /* Although I guess we could, we don't currently support SJLJ exceptions for the
139 GNU runtime. */
140 if (flag_objc_sjlj_exceptions)
142 inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for %<-fgnu-runtime%>");
143 flag_objc_sjlj_exceptions = 0;
146 rthooks->initialize = gnu_runtime_01_initialize;
147 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
148 rthooks->tag_getclass = TAG_GETCLASS;
149 rthooks->super_superclassfield_ident = gnu_runtime_abi_01_super_superclassfield_id;
151 rthooks->class_decl = gnu_runtime_abi_01_class_decl;
152 rthooks->metaclass_decl = gnu_runtime_abi_01_metaclass_decl;
153 rthooks->category_decl = gnu_runtime_abi_01_category_decl;
154 rthooks->protocol_decl = gnu_runtime_abi_01_protocol_decl;
155 rthooks->string_decl = gnu_runtime_abi_01_string_decl;
157 rthooks->get_class_reference = gnu_runtime_abi_01_get_class_reference;
158 rthooks->build_selector_reference = gnu_runtime_abi_01_build_typed_selector_reference;
159 rthooks->get_protocol_reference = gnu_runtime_abi_01_get_protocol_reference;
160 rthooks->build_ivar_reference = gnu_runtime_abi_01_build_ivar_ref;
161 rthooks->get_class_super_ref = gnu_runtime_abi_01_get_class_super_ref;
162 rthooks->get_category_super_ref = gnu_runtime_abi_01_get_category_super_ref;
164 rthooks->receiver_is_class_object = gnu_runtime_abi_01_receiver_is_class_object;
165 rthooks->get_arg_type_list_base = gnu_runtime_abi_01_get_arg_type_list_base;
166 rthooks->build_objc_method_call = gnu_runtime_abi_01_build_objc_method_call;
168 rthooks->setup_const_string_class_decl =
169 gnu_runtime_abi_01_setup_const_string_class_decl;
170 rthooks->build_const_string_constructor =
171 gnu_runtime_abi_01_build_const_string_constructor;
173 rthooks->build_throw_stmt = build_throw_stmt;
174 rthooks->build_exc_ptr = objc_build_exc_ptr;
175 rthooks->begin_catch = begin_catch;
176 rthooks->finish_catch = finish_catch;
177 rthooks->finish_try_stmt = finish_try_stmt;
179 rthooks->generate_metadata = objc_generate_v1_gnu_metadata;
180 return true;
183 static void build_selector_table_decl (void);
184 static void build_class_template (void);
185 static void build_category_template (void);
186 static void build_protocol_template (void);
188 static GTY(()) tree objc_meta;
189 static GTY(()) tree meta_base;
191 static void gnu_runtime_01_initialize (void)
193 tree type, ftype, IMP_type;
195 /* We do not need to mark GNU ObjC metadata for different sections,
196 however, we do need to make sure that it is not mistaken for NeXT
197 metadata. */
198 objc_meta = get_identifier ("OBJC1METG");
199 meta_base = get_identifier ("NONE");
201 /* Declare type of selector-objects that represent an operation name. */
202 /* `const struct objc_selector *' */
203 type = xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR));
204 type = build_qualified_type (type, TYPE_QUAL_CONST);
205 objc_selector_type = build_pointer_type (type);
207 /* typedef id (*IMP)(id, SEL, ...); */
208 ftype = build_varargs_function_type_list (objc_object_type,
209 objc_object_type,
210 objc_selector_type,
211 NULL_TREE);
213 IMP_type = build_pointer_type (ftype);
215 build_class_template ();
216 build_super_template ();
217 build_protocol_template ();
218 build_category_template ();
220 /* GNU runtime messenger entry points. */
221 /* TREE_NOTHROW is cleared for the message-sending functions,
222 because the function that gets called can throw in Obj-C++, or
223 could itself call something that can throw even in Obj-C. */
225 /* IMP objc_msg_lookup (id, SEL); */
226 type = build_function_type_list (IMP_type,
227 objc_object_type,
228 objc_selector_type,
229 NULL_TREE);
231 umsg_decl = add_builtin_function (TAG_MSGSEND,
232 type, 0, NOT_BUILT_IN,
233 NULL, NULL_TREE);
234 TREE_NOTHROW (umsg_decl) = 0;
236 /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
237 type = build_function_type_list (IMP_type,
238 objc_super_type,
239 objc_selector_type,
240 NULL_TREE);
242 umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
243 type, 0, NOT_BUILT_IN,
244 NULL, NULL_TREE);
245 TREE_NOTHROW (umsg_super_decl) = 0;
247 /* The following GNU runtime entry point is called to initialize
248 each module:
250 __objc_exec_class (void *); */
251 type = build_function_type_list (void_type_node,
252 ptr_type_node,
253 NULL_TREE);
255 execclass_decl = add_builtin_function (TAG_EXECCLASS,
256 type, 0, NOT_BUILT_IN,
257 NULL, NULL_TREE);
259 type = build_function_type_list (objc_object_type,
260 const_string_type_node,
261 NULL_TREE);
263 /* id objc_getClass (const char *); */
264 objc_get_class_decl
265 = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
266 NULL, NULL_TREE);
268 /* id objc_getMetaClass (const char *); */
269 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS, type,
270 0, NOT_BUILT_IN, NULL,
271 NULL_TREE);
273 /* static SEL _OBJC_SELECTOR_TABLE[]; */
274 build_selector_table_decl ();
276 /* Stuff for properties.
277 The codegen relies on this being NULL for GNU. */
278 objc_copyStruct_decl = NULL_TREE;
280 /* This is the type of all of the following functions
281 bjc_getPropertyStruct() and objc_setPropertyStruct(). */
282 type = build_function_type_list (void_type_node,
283 ptr_type_node,
284 const_ptr_type_node,
285 ptrdiff_type_node,
286 boolean_type_node,
287 boolean_type_node,
288 NULL_TREE);
290 /* Declare the following function:
291 void
292 objc_getPropertyStruct (void *destination, const void *source,
293 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
294 objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct",
295 type, 0, NOT_BUILT_IN,
296 NULL, NULL_TREE);
297 TREE_NOTHROW (objc_getPropertyStruct_decl) = 0;
298 /* Declare the following function:
299 void
300 objc_setPropertyStruct (void *destination, const void *source,
301 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
302 objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct",
303 type, 0, NOT_BUILT_IN,
304 NULL, NULL_TREE);
305 TREE_NOTHROW (objc_setPropertyStruct_decl) = 0;
307 using_eh_for_cleanups ();
308 lang_hooks.eh_runtime_type = objc_eh_runtime_type;
309 lang_hooks.eh_personality = objc_eh_personality;
312 /* --- templates --- */
313 /* struct _objc_selector {
314 SEL sel_id;
315 char *sel_type;
316 }; */
318 static void
319 build_selector_template (void)
321 tree decls, *chain = NULL;
323 objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
325 /* SEL sel_id; */
326 decls = add_field_decl (objc_selector_type, "sel_id", &chain);
328 /* char *sel_type; */
329 add_field_decl (string_type_node, "sel_type", &chain);
331 objc_finish_struct (objc_selector_template, decls);
334 /* struct _objc_class {
335 struct _objc_class *isa;
336 struct _objc_class *super_class;
337 char *name;
338 long version;
339 long info;
340 long instance_size;
341 struct _objc_ivar_list *ivars;
342 struct _objc_method_list *methods;
343 struct sarray *dtable;
344 struct _objc_class *subclass_list;
345 struct _objc_class *sibling_class;
346 struct _objc_protocol_list *protocols;
347 void *gc_object_type;
348 }; */
350 static void
351 build_class_template (void)
353 tree ptype, decls, *chain = NULL;
355 objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
357 /* struct _objc_class *isa; */
358 decls = add_field_decl (build_pointer_type (objc_class_template),
359 "isa", &chain);
361 /* struct _objc_class *super_class; */
362 add_field_decl (build_pointer_type (objc_class_template),
363 "super_class", &chain);
365 /* char *name; */
366 add_field_decl (string_type_node, "name", &chain);
368 /* long version; */
369 add_field_decl (long_integer_type_node, "version", &chain);
371 /* long info; */
372 add_field_decl (long_integer_type_node, "info", &chain);
374 /* long instance_size; */
375 add_field_decl (long_integer_type_node, "instance_size", &chain);
377 /* struct _objc_ivar_list *ivars; */
378 add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
380 /* struct _objc_method_list *methods; */
381 add_field_decl (objc_method_list_ptr, "methods", &chain);
383 /* struct sarray *dtable; */
384 ptype = build_pointer_type(xref_tag (RECORD_TYPE,
385 get_identifier ("sarray")));
386 add_field_decl (ptype, "dtable", &chain);
388 /* struct objc_class *subclass_list; */
389 ptype = build_pointer_type (objc_class_template);
390 add_field_decl (ptype, "subclass_list", &chain);
392 /* struct objc_class *sibling_class; */
393 ptype = build_pointer_type (objc_class_template);
394 add_field_decl (ptype, "sibling_class", &chain);
396 /* struct _objc_protocol **protocol_list; */
397 ptype = build_pointer_type (build_pointer_type
398 (xref_tag (RECORD_TYPE,
399 get_identifier (UTAG_PROTOCOL))));
400 add_field_decl (ptype, "protocol_list", &chain);
402 /* void *gc_object_type; */
403 add_field_decl (build_pointer_type (void_type_node),
404 "gc_object_type", &chain);
406 objc_finish_struct (objc_class_template, decls);
409 /* struct _objc_category {
410 char *category_name;
411 char *class_name;
412 struct _objc_method_list *instance_methods;
413 struct _objc_method_list *class_methods;
414 struct _objc_protocol_list *protocols;
415 }; */
417 static void
418 build_category_template (void)
420 tree ptype, decls, *chain = NULL;
422 objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
424 /* char *category_name; */
425 decls = add_field_decl (string_type_node, "category_name", &chain);
427 /* char *class_name; */
428 add_field_decl (string_type_node, "class_name", &chain);
430 /* struct _objc_method_list *instance_methods; */
431 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
433 /* struct _objc_method_list *class_methods; */
434 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
436 /* struct _objc_protocol **protocol_list; */
437 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
438 add_field_decl (ptype, "protocol_list", &chain);
440 objc_finish_struct (objc_category_template, decls);
443 /* struct _objc_protocol {
444 struct _objc_class *isa;
445 char *protocol_name;
446 struct _objc_protocol **protocol_list;
447 struct _objc__method_prototype_list *instance_methods;
448 struct _objc__method_prototype_list *class_methods;
449 }; */
451 static void
452 build_protocol_template (void)
454 tree ptype, decls, *chain = NULL;
456 objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
458 /* struct _objc_class *isa; */
459 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
460 get_identifier (UTAG_CLASS)));
461 decls = add_field_decl (ptype, "isa", &chain);
463 /* char *protocol_name; */
464 add_field_decl (string_type_node, "protocol_name", &chain);
466 /* struct _objc_protocol **protocol_list; */
467 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
468 add_field_decl (ptype, "protocol_list", &chain);
470 /* struct _objc__method_prototype_list *instance_methods; */
471 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
473 /* struct _objc__method_prototype_list *class_methods; */
474 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
476 objc_finish_struct (objc_protocol_template, decls);
479 /* --- names, decls + identifers --- */
481 static void
482 build_selector_table_decl (void)
484 tree temp;
486 build_selector_template ();
487 temp = build_array_type (objc_selector_template, NULL_TREE);
489 UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
490 OBJCMETA (UOBJC_SELECTOR_TABLE_decl, objc_meta, meta_base);
494 static tree
495 gnu_runtime_abi_01_super_superclassfield_id (void)
497 if (!super_superclassfield_id)
498 super_superclassfield_id = get_identifier ("super_class");
499 return super_superclassfield_id;
503 static tree
504 gnu_runtime_abi_01_class_decl (tree klass)
506 tree decl;
507 char buf[BUFSIZE];
508 snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
509 IDENTIFIER_POINTER (CLASS_NAME (klass)));
510 decl = start_var_decl (objc_class_template, buf);
511 OBJCMETA (decl, objc_meta, meta_base);
512 return decl;
515 static tree
516 gnu_runtime_abi_01_metaclass_decl (tree klass)
518 tree decl;
519 char buf[BUFSIZE];
520 snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
521 IDENTIFIER_POINTER (CLASS_NAME (klass)));
522 decl = start_var_decl (objc_class_template, buf);
523 OBJCMETA (decl, objc_meta, meta_base);
524 return decl;
527 static tree
528 gnu_runtime_abi_01_category_decl (tree klass)
530 tree decl;
531 char buf[BUFSIZE];
532 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
533 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
534 IDENTIFIER_POINTER (CLASS_NAME (klass)));
535 decl = start_var_decl (objc_category_template, buf);
536 OBJCMETA (decl, objc_meta, meta_base);
537 return decl;
540 static tree
541 gnu_runtime_abi_01_protocol_decl (tree p)
543 tree decl;
544 char buf[BUFSIZE];
546 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
547 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
548 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
549 decl = start_var_decl (objc_protocol_template, buf);
550 OBJCMETA (decl, objc_meta, meta_base);
551 return decl;
554 static tree
555 gnu_runtime_abi_01_string_decl (tree type, const char *name,
556 string_section where ATTRIBUTE_UNUSED)
558 tree decl = start_var_decl (type, name);
559 OBJCMETA (decl, objc_meta, meta_base);
560 return decl;
563 /* --- entry --- */
565 static tree
566 gnu_runtime_abi_01_get_class_reference (tree ident)
568 tree params;
570 add_class_reference (ident);
572 params = build_tree_list (NULL_TREE, my_build_string_pointer
573 (IDENTIFIER_LENGTH (ident) + 1,
574 IDENTIFIER_POINTER (ident)));
576 /* assemble_external (objc_get_class_decl);*/
577 return build_function_call (input_location, objc_get_class_decl, params);
580 /* Used by get_arg_type_list.
581 Return the types for receiver & _cmd at the start of a method argument list.
582 context is either METHOD_DEF or METHOD_REF, saying whether we are trying
583 to define a method or call one. superflag says this is for a send to super.
584 meth may be NULL, in the case that there is no prototype. */
586 static tree
587 gnu_runtime_abi_01_get_arg_type_list_base (tree meth, int context,
588 int superflag ATTRIBUTE_UNUSED)
590 tree arglist;
592 /* Receiver type. */
593 if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
594 arglist = build_tree_list (NULL_TREE, objc_instance_type);
595 else
596 arglist = build_tree_list (NULL_TREE, objc_object_type);
598 /* Selector type - will eventually change to `int'. */
599 chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
600 return arglist;
603 /* Unused for GNU runtime. */
604 static tree
605 gnu_runtime_abi_01_receiver_is_class_object (tree a ATTRIBUTE_UNUSED)
607 return NULL_TREE;
610 /* sel_ref_chain is a list whose "value" fields will be instances of
611 identifier_node that represent the selector. LOC is the location of
612 the @selector. */
614 static tree
615 gnu_runtime_abi_01_build_typed_selector_reference (location_t loc, tree ident,
616 tree prototype)
618 tree *chain = &sel_ref_chain;
619 tree expr;
620 int index = 0;
622 while (*chain)
624 /* When we do a lookup for @selector () we have no idea of the
625 prototype - so match the first we find. */
626 if (TREE_VALUE (*chain) == ident
627 && (!prototype || TREE_PURPOSE (*chain) == prototype))
628 goto return_at_index;
630 index++;
631 chain = &TREE_CHAIN (*chain);
634 *chain = tree_cons (prototype, ident, NULL_TREE);
636 /* TODO: Use a vec and keep this in it to (a) avoid re-creating and
637 (b) provide better diagnostics for the first time an undefined
638 selector is used. */
639 return_at_index:
640 expr = build_unary_op (loc, ADDR_EXPR,
641 build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
642 build_int_cst (NULL_TREE, index)),
644 return convert (objc_selector_type, expr);
647 /* Build a tree expression to send OBJECT the operation SELECTOR,
648 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
649 assuming the method has prototype METHOD_PROTOTYPE.
650 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
651 LOC is the location of the expression to build.
652 Use METHOD_PARAMS as list of args to pass to the method.
653 If SUPER_FLAG is nonzero, we look up the superclass's method. */
655 static tree
656 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
657 tree lookup_object, tree selector,
658 tree method_params)
660 tree sender = (super_flag ? umsg_super_decl
661 : (flag_objc_direct_dispatch ? umsg_fast_decl
662 : umsg_decl));
663 tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
664 VEC(tree, gc) *parms;
665 VEC(tree, gc) *tv;
666 unsigned nparm = (method_params ? list_length (method_params) : 0);
668 /* If a prototype for the method to be called exists, then cast
669 the sender's return type and arguments to match that of the method.
670 Otherwise, leave sender as is. */
671 tree ret_type
672 = (method_prototype
673 ? TREE_VALUE (TREE_TYPE (method_prototype))
674 : objc_object_type);
676 tree method_param_types =
677 get_arg_type_list (method_prototype, METHOD_REF, super_flag);
678 tree ftype = build_function_type (ret_type, method_param_types);
679 tree sender_cast;
680 tree method, t;
682 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
683 ftype = build_type_attribute_variant (ftype,
684 METHOD_TYPE_ATTRIBUTES
685 (method_prototype));
687 sender_cast = build_pointer_type (ftype);
689 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
691 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
692 lookup_object = save_expr (lookup_object);
694 /* Param list + 2 slots for object and selector. */
695 parms = VEC_alloc (tree, gc, nparm + 2);
696 tv = VEC_alloc (tree, gc, 2);
698 /* First, call the lookup function to get a pointer to the method,
699 then cast the pointer, then call it with the method arguments. */
700 VEC_quick_push (tree, tv, lookup_object);
701 VEC_quick_push (tree, tv, selector);
702 method = build_function_call_vec (loc, sender, tv, NULL);
703 VEC_free (tree, gc, tv);
705 /* Pass the appropriate object to the method. */
706 VEC_quick_push (tree, parms, (super_flag ? self_decl : lookup_object));
708 /* Pass the selector to the method. */
709 VEC_quick_push (tree, parms, selector);
710 /* Now append the remainder of the parms. */
711 if (nparm)
712 for (; method_params; method_params = TREE_CHAIN (method_params))
713 VEC_quick_push (tree, parms, TREE_VALUE (method_params));
715 /* Build an obj_type_ref, with the correct cast for the method call. */
716 t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
717 t = build_function_call_vec (loc, t, parms, NULL);
718 VEC_free (tree, gc, parms);
719 return t;
722 static tree
723 gnu_runtime_abi_01_build_objc_method_call (location_t loc,
724 tree method_prototype,
725 tree receiver,
726 tree rtype ATTRIBUTE_UNUSED,
727 tree sel_name,
728 tree method_params,
729 int super ATTRIBUTE_UNUSED)
731 tree selector =
732 gnu_runtime_abi_01_build_typed_selector_reference (loc,
733 sel_name,
734 method_prototype);
736 return build_objc_method_call (loc, super, method_prototype, receiver,
737 selector, method_params);
740 static tree
741 gnu_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
743 tree expr, protocol_struct_type, *chain;
744 if (!PROTOCOL_FORWARD_DECL (p))
745 PROTOCOL_FORWARD_DECL (p) = gnu_runtime_abi_01_protocol_decl (p);
747 expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
749 /* ??? Ideally we'd build the reference with objc_protocol_type directly,
750 if we have it, rather than converting it here. */
751 expr = convert (objc_protocol_type, expr);
753 /* The @protocol() expression is being compiled into a pointer to a
754 statically allocated instance of the Protocol class. To become
755 usable at runtime, the 'isa' pointer of the instance need to be
756 fixed up at runtime by the runtime library, to point to the
757 actual 'Protocol' class. */
759 /* For the GNU runtime, put the static Protocol instance in the list
760 of statically allocated instances, so that we make sure that its
761 'isa' pointer is fixed up at runtime by the GNU runtime library
762 to point to the Protocol class (at runtime, when loading the
763 module, the GNU runtime library loops on the statically allocated
764 instances (as found in the defs field in objc_symtab) and fixups
765 all the 'isa' pointers of those objects). */
767 /* This type is a struct containing the fields of a Protocol
768 object. (Cfr. objc_protocol_type instead is the type of a pointer
769 to such a struct). */
770 protocol_struct_type = xref_tag (RECORD_TYPE,
771 get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
773 /* Look for the list of Protocol statically allocated instances
774 to fixup at runtime. Create a new list to hold Protocol
775 statically allocated instances, if the list is not found. At
776 present there is only another list, holding NSConstantString
777 static instances to be fixed up at runtime. */
779 for (chain = &objc_static_instances;
780 *chain && TREE_VALUE (*chain) != protocol_struct_type;
781 chain = &TREE_CHAIN (*chain));
783 if (!*chain)
785 *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
786 add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
787 class_names);
790 /* Add this statically allocated instance to the Protocol list. */
791 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
792 PROTOCOL_FORWARD_DECL (p),
793 TREE_PURPOSE (*chain));
794 return expr;
797 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
799 static tree
800 gnu_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
801 tree base, tree id)
803 return objc_build_component_ref (base, id);
806 /* We build super class references as we need them (but keep them once
807 built for the sake of efficiency). */
809 static tree
810 gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
811 struct imp_entry *imp, bool inst_meth)
813 if (inst_meth)
815 if (!ucls_super_ref)
816 ucls_super_ref =
817 objc_build_component_ref (imp->class_decl,
818 get_identifier ("super_class"));
819 return ucls_super_ref;
821 else
823 if (!uucls_super_ref)
824 uucls_super_ref =
825 objc_build_component_ref (imp->meta_decl,
826 get_identifier ("super_class"));
827 return uucls_super_ref;
831 static tree
832 gnu_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
833 struct imp_entry *imp, bool inst_meth)
835 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
836 tree super_class;
838 add_class_reference (super_name);
839 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
840 /* assemble_external (super_class);*/
841 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
842 IDENTIFIER_POINTER (super_name));
843 /* super_class = get_{meta_}class("CLASS_SUPER_NAME"); */
844 return build_function_call (input_location,
845 super_class,
846 build_tree_list (NULL_TREE, super_name));
849 static bool
850 gnu_runtime_abi_01_setup_const_string_class_decl (void)
852 /* Do nothing, and create no error. */
853 return true;
856 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
858 static GTY(()) int num_static_inst;
860 static tree
861 objc_add_static_instance (tree constructor, tree class_decl)
863 tree *chain, decl;
864 char buf[BUFSIZE];
866 /* Find the list of static instances for the CLASS_DECL. Create one if
867 not found. */
868 for (chain = &objc_static_instances;
869 *chain && TREE_VALUE (*chain) != class_decl;
870 chain = &TREE_CHAIN (*chain));
871 if (!*chain)
873 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
874 add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
877 snprintf (buf, BUFSIZE, "_OBJC_INSTANCE_%d", num_static_inst++);
878 decl = build_decl (input_location,
879 VAR_DECL, get_identifier (buf), class_decl);
880 TREE_STATIC (decl) = 1;
881 DECL_ARTIFICIAL (decl) = 1;
882 TREE_USED (decl) = 1;
883 DECL_INITIAL (decl) = constructor;
884 DECL_CONTEXT (decl) = NULL;
885 OBJCMETA (decl, objc_meta, meta_base);
887 /* We may be writing something else just now.
888 Postpone till end of input. */
889 DECL_DEFER_OUTPUT (decl) = 1;
890 pushdecl_top_level (decl);
891 rest_of_decl_compilation (decl, 1, 0);
893 /* Add the DECL to the head of this CLASS' list. */
894 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
896 return decl;
899 static tree
900 gnu_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
901 int length)
903 tree constructor, fields;
904 VEC(constructor_elt,gc) *v = NULL;
906 /* GNU: (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length }) */
907 fields = TYPE_FIELDS (internal_const_str_type);
908 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, 0));
910 fields = DECL_CHAIN (fields);
911 CONSTRUCTOR_APPEND_ELT (v, fields, build_unary_op (loc,
912 ADDR_EXPR, string, 1));
914 fields = DECL_CHAIN (fields);
915 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
916 constructor = objc_build_constructor (internal_const_str_type, v);
918 constructor = objc_add_static_instance (constructor, constant_string_type);
919 return constructor;
922 /* --- metadata - module initializer --- */
924 /* The GNU runtime requires us to provide a static initializer function
925 for each module:
927 static void __objc_gnu_init (void) {
928 __objc_exec_class (&L_OBJC_MODULES);
929 } */
932 static void
933 build_module_initializer_routine (void)
935 tree body;
937 #ifdef OBJCPLUS
938 push_lang_context (lang_name_c); /* extern "C" */
939 #endif
941 objc_push_parm (build_decl (input_location,
942 PARM_DECL, NULL_TREE, void_type_node));
943 #ifdef OBJCPLUS
944 objc_start_function (get_identifier (TAG_GNUINIT),
945 build_function_type_list (void_type_node, NULL_TREE),
946 NULL_TREE, NULL_TREE);
947 #else
948 objc_start_function (get_identifier (TAG_GNUINIT),
949 build_function_type_list (void_type_node, NULL_TREE),
950 NULL_TREE, objc_get_parm_info (0));
951 #endif
952 body = c_begin_compound_stmt (true);
953 add_stmt (build_function_call
954 (input_location,
955 execclass_decl,
956 build_tree_list
957 (NULL_TREE,
958 build_unary_op (input_location, ADDR_EXPR,
959 UOBJC_MODULES_decl, 0))));
960 add_stmt (c_end_compound_stmt (input_location, body, true));
962 TREE_PUBLIC (current_function_decl) = 0;
964 #ifndef OBJCPLUS
965 /* For Objective-C++, we will need to call __objc_gnu_init
966 from objc_generate_static_init_call() below. */
967 DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
968 #endif
970 GNU_INIT_decl = current_function_decl;
971 finish_function ();
973 #ifdef OBJCPLUS
974 pop_lang_context ();
975 #endif
978 #ifdef OBJCPLUS
979 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
980 to be called by the module initializer routine. */
983 objc_static_init_needed_p (void)
985 return (GNU_INIT_decl != NULL_TREE);
988 /* Generate a call to the __objc_gnu_init initializer function. */
990 tree
991 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
993 add_stmt (build_stmt (input_location, EXPR_STMT,
994 build_function_call (input_location,
995 GNU_INIT_decl, NULL_TREE)));
997 return ctors;
999 #endif /* OBJCPLUS */
1001 /* --- Output GNU Meta-data --- */
1003 static void
1004 generate_classref_translation_entry (tree chain)
1006 tree expr, decl, type;
1008 decl = TREE_PURPOSE (chain);
1009 type = TREE_TYPE (decl);
1011 expr = add_objc_string (TREE_VALUE (chain), class_names);
1012 expr = convert (type, expr); /* cast! */
1014 /* This is a class reference. It is re-written by the runtime,
1015 but will be optimized away unless we force it. */
1016 DECL_PRESERVE_P (decl) = 1;
1017 OBJCMETA (decl, objc_meta, meta_base);
1018 finish_var_decl (decl, expr);
1019 return;
1023 static void
1024 handle_impent (struct imp_entry *impent)
1026 char *string;
1028 /* objc_implementation_context = impent->imp_context;
1029 implementation_template = impent->imp_template;*/
1031 switch (TREE_CODE (impent->imp_context))
1033 case CLASS_IMPLEMENTATION_TYPE:
1035 const char *const class_name =
1036 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1038 string = (char *) alloca (strlen (class_name) + 30);
1040 sprintf (string, "__objc_class_name_%s", class_name);
1041 break;
1043 case CATEGORY_IMPLEMENTATION_TYPE:
1045 const char *const class_name =
1046 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1047 const char *const class_super_name =
1048 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
1050 string = (char *) alloca (strlen (class_name)
1051 + strlen (class_super_name) + 30);
1053 /* Do the same for categories. Even though no references to
1054 these symbols are generated automatically by the compiler,
1055 it gives you a handle to pull them into an archive by
1056 hand. */
1057 sprintf (string, "*__objc_category_name_%s_%s", class_name, class_super_name);
1058 break;
1060 default:
1061 return;
1065 tree decl, init;
1067 init = integer_zero_node;
1068 decl = build_decl (input_location,
1069 VAR_DECL, get_identifier (string), TREE_TYPE (init));
1070 TREE_PUBLIC (decl) = 1;
1071 TREE_READONLY (decl) = 1;
1072 TREE_USED (decl) = 1;
1073 TREE_CONSTANT (decl) = 1;
1074 DECL_CONTEXT (decl) = NULL_TREE;
1075 DECL_ARTIFICIAL (decl) = 1;
1076 TREE_STATIC (decl) = 1;
1077 DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
1078 /* We must force the reference. */
1079 DECL_PRESERVE_P (decl) = 1;
1081 finish_var_decl(decl, init) ;
1085 tree
1086 build_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1087 tree inst_methods, tree class_methods)
1089 tree expr, ttyp;
1090 location_t loc;
1091 VEC(constructor_elt,gc) *inits = NULL;
1093 /* TODO: pass the loc in or find it from args. */
1094 loc = input_location;
1095 ttyp = build_pointer_type (xref_tag (RECORD_TYPE,
1096 get_identifier (UTAG_CLASS)));
1097 /* Filling the "isa" in with a version allows the runtime system to
1098 detect this ... */
1099 expr = build_int_cst (ttyp, PROTOCOL_VERSION);
1101 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1103 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1104 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1106 ttyp = objc_method_proto_list_ptr;
1107 if (inst_methods)
1108 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1109 else
1110 expr = convert (ttyp, null_pointer_node);
1111 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1113 if (class_methods)
1114 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1115 else
1116 expr = convert (ttyp, null_pointer_node);
1117 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1119 return objc_build_constructor (type, inits);
1122 static tree
1123 generate_protocol_list (tree i_or_p, tree klass_ctxt)
1125 tree array_type, ptype, refs_decl, lproto, e, plist;
1126 VEC(constructor_elt,gc) *v = NULL;
1127 char buf[BUFSIZE];
1128 int size = 0;
1130 switch (TREE_CODE (i_or_p))
1132 case CLASS_INTERFACE_TYPE:
1133 case CATEGORY_INTERFACE_TYPE:
1134 plist = CLASS_PROTOCOL_LIST (i_or_p);
1135 break;
1136 case PROTOCOL_INTERFACE_TYPE:
1137 plist = PROTOCOL_LIST (i_or_p);
1138 break;
1139 default:
1140 gcc_unreachable ();
1143 /* Compute size. */
1144 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1145 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1146 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1147 size++;
1149 /* Build initializer. */
1150 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1151 e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1152 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1154 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1156 tree pval = TREE_VALUE (lproto);
1158 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1159 && PROTOCOL_FORWARD_DECL (pval))
1161 tree fwref = PROTOCOL_FORWARD_DECL (pval);
1162 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1163 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1164 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1168 /* static struct objc_protocol *refs[n]; */
1170 switch (TREE_CODE (i_or_p))
1172 case PROTOCOL_INTERFACE_TYPE:
1173 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1174 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1175 break;
1176 case CLASS_INTERFACE_TYPE:
1177 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1178 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1179 break;
1180 case CATEGORY_INTERFACE_TYPE:
1181 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1182 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1183 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1184 break;
1185 default:
1186 gcc_unreachable ();
1189 ptype = build_pointer_type (objc_protocol_template);
1190 array_type = build_sized_array_type (ptype, size + 3);
1191 refs_decl = start_var_decl (array_type, buf);
1192 OBJCMETA (refs_decl, objc_meta, meta_base);
1193 finish_var_decl (refs_decl,
1194 objc_build_constructor (TREE_TYPE (refs_decl), v));
1196 return refs_decl;
1199 static tree
1200 generate_v1_meth_descriptor_table (tree chain, tree protocol, const char *prefix)
1202 tree method_list_template, initlist, decl;
1203 int size;
1204 VEC(constructor_elt,gc) *v = NULL;
1205 char buf[BUFSIZE];
1207 if (!chain || !prefix)
1208 return NULL_TREE;
1210 if (!objc_method_prototype_template)
1211 objc_method_prototype_template = build_method_prototype_template ();
1213 size = list_length (chain);
1214 method_list_template =
1215 build_method_prototype_list_template (objc_method_prototype_template,
1216 size);
1217 snprintf (buf, BUFSIZE, "%s_%s", prefix,
1218 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1220 decl = start_var_decl (method_list_template, buf);
1222 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1223 initlist =
1224 build_descriptor_table_initializer (objc_method_prototype_template,
1225 chain);
1226 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1227 OBJCMETA (decl, objc_meta, meta_base);
1228 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1229 return decl;
1232 /* For each protocol which was referenced either from a @protocol()
1233 expression, or because a class/category implements it (then a
1234 pointer to the protocol is stored in the struct describing the
1235 class/category), we create a statically allocated instance of the
1236 Protocol class. The code is written in such a way as to generate
1237 as few Protocol objects as possible; we generate a unique Protocol
1238 instance for each protocol, and we don't generate a Protocol
1239 instance if the protocol is never referenced (either from a
1240 @protocol() or from a class/category implementation). These
1241 statically allocated objects can be referred to via the static
1242 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1244 The statically allocated Protocol objects that we generate here
1245 need to be fixed up at runtime in order to be used: the 'isa'
1246 pointer of the objects need to be set up to point to the 'Protocol'
1247 class, as known at runtime.
1249 The GNU runtime fixes up all protocols before user code from the module
1250 is executed; it requires pointers to those symbols
1251 to be put in the objc_symtab (which is then passed as argument to
1252 the function __objc_exec_class() which the compiler sets up to be
1253 executed automatically when the module is loaded); setup of those
1254 Protocol objects happen in two ways in the GNU runtime: all
1255 Protocol objects referred to by a class or category implementation
1256 are fixed up when the class/category is loaded; all Protocol
1257 objects referred to by a @protocol() expression are added by the
1258 compiler to the list of statically allocated instances to fixup
1259 (the same list holding the statically allocated constant string
1260 objects). Because, as explained above, the compiler generates as
1261 few Protocol objects as possible, some Protocol object might end up
1262 being referenced multiple times when compiled with the GNU runtime,
1263 and end up being fixed up multiple times at runtime initialization.
1264 But that doesn't hurt, it's just a little inefficient. */
1266 static void
1267 generate_protocols (void)
1269 tree p, encoding;
1270 tree decl;
1271 tree initlist, protocol_name_expr, refs_decl, refs_expr;
1273 /* If a protocol was directly referenced, pull in indirect references. */
1274 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1275 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1276 generate_protocol_references (PROTOCOL_LIST (p));
1278 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1280 tree nst_methods = PROTOCOL_NST_METHODS (p);
1281 tree cls_methods = PROTOCOL_CLS_METHODS (p);
1283 /* If protocol wasn't referenced, don't generate any code. */
1284 decl = PROTOCOL_FORWARD_DECL (p);
1286 if (!decl)
1287 continue;
1289 /* Make sure we link in the Protocol class. */
1290 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1292 while (nst_methods)
1294 if (! METHOD_ENCODING (nst_methods))
1296 encoding = encode_method_prototype (nst_methods);
1297 METHOD_ENCODING (nst_methods) = encoding;
1299 nst_methods = DECL_CHAIN (nst_methods);
1302 UOBJC_INSTANCE_METHODS_decl =
1303 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1304 "_OBJC_PROTOCOL_INSTANCE_METHODS");
1306 while (cls_methods)
1308 if (! METHOD_ENCODING (cls_methods))
1310 encoding = encode_method_prototype (cls_methods);
1311 METHOD_ENCODING (cls_methods) = encoding;
1314 cls_methods = DECL_CHAIN (cls_methods);
1317 UOBJC_CLASS_METHODS_decl =
1318 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1319 "_OBJC_PROTOCOL_CLASS_METHODS");
1320 /* generate_method_descriptors (p);*/
1322 if (PROTOCOL_LIST (p))
1323 refs_decl = generate_protocol_list (p, NULL_TREE);
1324 else
1325 refs_decl = 0;
1327 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1328 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1330 if (refs_decl)
1331 refs_expr = convert (build_pointer_type (build_pointer_type
1332 (objc_protocol_template)),
1333 build_unary_op (input_location,
1334 ADDR_EXPR, refs_decl, 0));
1335 else
1336 refs_expr = build_int_cst (NULL_TREE, 0);
1338 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
1339 by generate_method_descriptors, which is called above. */
1340 initlist = build_protocol_initializer (TREE_TYPE (decl),
1341 protocol_name_expr, refs_expr,
1342 UOBJC_INSTANCE_METHODS_decl,
1343 UOBJC_CLASS_METHODS_decl);
1344 finish_var_decl (decl, initlist);
1348 static tree
1349 generate_dispatch_table (tree chain, const char *name)
1351 tree decl, method_list_template, initlist;
1352 VEC(constructor_elt,gc) *v = NULL;
1353 int size = list_length (chain);
1355 if (!objc_method_template)
1356 objc_method_template = build_method_template ();
1358 method_list_template = build_method_list_template (objc_method_template,
1359 size);
1360 initlist = build_dispatch_table_initializer (objc_method_template, chain);
1362 decl = start_var_decl (method_list_template, name);
1364 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1365 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1366 build_int_cst (integer_type_node, size));
1367 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1369 OBJCMETA (decl, objc_meta, meta_base);
1370 finish_var_decl (decl,
1371 objc_build_constructor (TREE_TYPE (decl), v));
1373 return decl;
1376 /* Init a category. */
1377 static tree
1378 build_category_initializer (tree type, tree cat_name, tree class_name,
1379 tree inst_methods, tree class_methods,
1380 tree protocol_list)
1382 tree expr, ltyp;
1383 location_t loc;
1384 VEC(constructor_elt,gc) *v = NULL;
1386 /* TODO: pass the loc in or find it from args. */
1387 /* TODO: pass the loc in or find it from args. */
1388 loc = UNKNOWN_LOCATION;
1389 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1390 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1392 ltyp = objc_method_list_ptr;
1393 if (inst_methods)
1394 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1395 else
1396 expr = convert (ltyp, null_pointer_node);
1397 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1399 if (class_methods)
1400 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1401 else
1402 expr = convert (ltyp, null_pointer_node);
1403 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1405 /* protocol_list = */
1406 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1407 if (protocol_list)
1408 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1409 else
1410 expr = convert (ltyp, null_pointer_node);
1411 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1413 return objc_build_constructor (type, v);
1416 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1418 static void
1419 generate_category (struct imp_entry *impent)
1421 tree initlist, cat_name_expr, class_name_expr;
1422 tree protocol_decl, category, cat_decl;
1423 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1424 tree cat = impent->imp_context;
1425 char buf[BUFSIZE];
1427 cat_decl = impent->class_decl;
1429 add_class_reference (CLASS_NAME (cat));
1430 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1432 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1434 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1436 if (category && CLASS_PROTOCOL_LIST (category))
1438 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1439 protocol_decl = generate_protocol_list (category, cat);
1441 else
1442 protocol_decl = 0;
1444 if (CLASS_NST_METHODS (cat))
1446 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1447 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1448 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1449 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf);
1452 if (CLASS_CLS_METHODS (cat))
1454 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1455 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1456 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1457 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf);
1460 initlist = build_category_initializer (TREE_TYPE (cat_decl),
1461 cat_name_expr, class_name_expr,
1462 inst_methods, class_methods,
1463 protocol_decl);
1464 /* Finish and initialize the forward decl. */
1465 finish_var_decl (cat_decl, initlist);
1466 impent->class_decl = cat_decl;
1469 /* struct _objc_class {
1470 struct objc_class *isa;
1471 struct objc_class *super_class;
1472 char *name;
1473 long version;
1474 long info;
1475 long instance_size;
1476 struct objc_ivar_list *ivars;
1477 struct objc_method_list *methods;
1478 if (flag_next_runtime)
1479 struct objc_cache *cache;
1480 else {
1481 struct sarray *dtable;
1482 struct objc_class *subclass_list;
1483 struct objc_class *sibling_class;
1485 struct objc_protocol_list *protocols;
1486 if (flag_next_runtime)
1487 void *sel_id;
1488 void *gc_object_type;
1489 }; */
1491 static tree
1492 build_shared_structure_initializer (tree type, tree isa, tree super,
1493 tree name, tree size, int status,
1494 tree dispatch_table, tree ivar_list,
1495 tree protocol_list)
1497 tree expr, ltyp;
1498 VEC(constructor_elt,gc) *v = NULL;
1500 /* isa = */
1501 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1503 /* super_class = */
1504 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1506 /* name = */
1507 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1509 /* version = */
1510 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1511 build_int_cst (long_integer_type_node, 0));
1513 /* info = */
1514 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1515 build_int_cst (long_integer_type_node, status));
1517 /* instance_size = */
1518 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1519 convert (long_integer_type_node, size));
1521 /* objc_ivar_list = */
1522 if (!ivar_list)
1523 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1524 build_int_cst (objc_ivar_list_ptr, 0));
1525 else
1527 expr = convert (objc_ivar_list_ptr,
1528 build_unary_op (input_location, ADDR_EXPR,
1529 ivar_list, 0));
1530 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1533 /* objc_method_list = */
1534 if (!dispatch_table)
1535 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1536 convert (objc_method_list_ptr, null_pointer_node));
1537 else
1539 expr = convert (objc_method_list_ptr,
1540 build_unary_op (input_location, ADDR_EXPR,
1541 dispatch_table, 0));
1542 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1545 if (flag_next_runtime)
1547 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
1548 get_identifier ("objc_cache")));
1549 /* method_cache = */
1550 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
1552 else
1554 /* dtable = */
1555 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1557 /* subclass_list = */
1558 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1560 /* sibling_class = */
1561 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1564 /* protocol_list = */
1565 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1566 if (! protocol_list)
1567 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (ltyp, 0));
1568 else
1570 expr = convert (ltyp,
1571 build_unary_op (input_location, ADDR_EXPR,
1572 protocol_list, 0));
1573 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1576 if (flag_next_runtime)
1577 /* sel_id = NULL */
1578 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1580 /* gc_object_type = NULL */
1581 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1583 return objc_build_constructor (type, v);
1587 static tree
1588 generate_ivars_list (tree chain, const char *name)
1590 tree initlist, ivar_list_template, decl;
1591 int size;
1592 VEC(constructor_elt,gc) *inits = NULL;
1594 if (!chain)
1595 return NULL_TREE;
1597 if (!objc_ivar_template)
1598 objc_ivar_template = build_ivar_template ();
1600 size = ivar_list_length (chain);
1602 generating_instance_variables = 1;
1603 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1604 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1605 generating_instance_variables = 0;
1607 decl = start_var_decl (ivar_list_template, name);
1609 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1610 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1612 OBJCMETA (decl, objc_meta, meta_base);
1613 finish_var_decl (decl,
1614 objc_build_constructor (TREE_TYPE (decl), inits));
1616 return decl;
1619 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1620 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1622 static void
1623 generate_class_structures (struct imp_entry *impent)
1625 tree name_expr, super_expr, root_expr, class_decl, meta_decl;
1626 tree my_root_id, my_super_id;
1627 tree cast_type, initlist, protocol_decl;
1628 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1629 tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
1630 location_t loc;
1631 char buf[BUFSIZE];
1632 int cls_flags = 0 ;
1634 /* objc_implementation_context = impent->imp_context;
1635 implementation_template = impent->imp_template;*/
1636 class_decl = impent->class_decl;
1637 meta_decl = impent->meta_decl;
1638 /* UOBJC_CLASS_decl = impent->class_decl;
1639 UOBJC_METACLASS_decl = impent->meta_decl;*/
1641 loc = DECL_SOURCE_LOCATION (impent->class_decl);
1643 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
1644 if (my_super_id)
1646 add_class_reference (my_super_id);
1648 /* Compute "my_root_id" - this is required for code generation.
1649 the "isa" for all meta class structures points to the root of
1650 the inheritance hierarchy (e.g. "__Object")... */
1651 my_root_id = my_super_id;
1654 tree my_root_int = lookup_interface (my_root_id);
1656 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
1657 my_root_id = CLASS_SUPER_NAME (my_root_int);
1658 else
1659 break;
1661 while (1);
1663 else
1664 /* No super class. */
1665 my_root_id = CLASS_NAME (impent->imp_template);
1667 cast_type = build_pointer_type (objc_class_template);
1668 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
1669 class_names);
1671 /* Install class `isa' and `super' pointers at runtime. */
1672 if (my_super_id)
1673 super_expr = add_objc_string (my_super_id, class_names);
1674 else
1675 super_expr = null_pointer_node;
1677 super_expr = build_c_cast (loc, cast_type, super_expr);
1679 root_expr = add_objc_string (my_root_id, class_names);
1680 root_expr = build_c_cast (loc, cast_type, root_expr);
1682 if (CLASS_PROTOCOL_LIST (impent->imp_template))
1684 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
1685 protocol_decl = generate_protocol_list (impent->imp_template,
1686 impent->imp_context);
1688 else
1689 protocol_decl = NULL_TREE;
1691 if (CLASS_CLS_METHODS (impent->imp_context))
1693 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
1694 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1695 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
1696 buf);
1699 if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
1700 && (chain = TYPE_FIELDS (objc_class_template)))
1702 snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
1703 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1704 class_ivars = generate_ivars_list (chain, buf);
1707 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
1709 initlist =
1710 build_shared_structure_initializer
1711 (TREE_TYPE (meta_decl),
1712 root_expr, super_expr, name_expr,
1713 convert (integer_type_node,
1714 TYPE_SIZE_UNIT (objc_class_template)),
1715 CLS_META, class_methods, class_ivars,
1716 protocol_decl);
1718 finish_var_decl (meta_decl, initlist);
1719 impent->meta_decl = meta_decl;
1721 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1722 if (CLASS_NST_METHODS (impent->imp_context))
1724 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
1725 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1726 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
1727 buf);
1730 if ((chain = CLASS_IVARS (impent->imp_template)))
1732 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
1733 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1734 inst_ivars = generate_ivars_list (chain, buf);
1737 initlist =
1738 build_shared_structure_initializer
1739 (TREE_TYPE (class_decl),
1740 build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
1741 super_expr, name_expr,
1742 convert (integer_type_node,
1743 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
1744 (impent->imp_template))),
1745 CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
1746 protocol_decl);
1748 finish_var_decl (class_decl, initlist);
1749 impent->class_decl = class_decl;
1752 /* --- Output GNU Metadata --- */
1754 /* TODO: Make this into an array of refs. */
1755 static void
1756 handle_class_ref (tree chain)
1758 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
1759 char *string = (char *) alloca (strlen (name) + 30);
1760 tree decl;
1761 tree exp;
1763 sprintf (string, "__objc_class_name_%s", name);
1765 /* Make a decl for this name, so we can use its address in a tree. */
1766 decl = build_decl (input_location,
1767 VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
1768 DECL_EXTERNAL (decl) = 1;
1769 TREE_PUBLIC (decl) = 1;
1770 DECL_CONTEXT (decl) = NULL_TREE;
1771 finish_var_decl (decl, 0);
1773 /* Make a decl for the address. */
1774 sprintf (string, "__objc_class_ref_%s", name);
1775 exp = build1 (ADDR_EXPR, string_type_node, decl);
1776 decl = build_decl (input_location,
1777 VAR_DECL, get_identifier (string), string_type_node);
1778 TREE_STATIC (decl) = 1;
1779 TREE_USED (decl) = 1;
1780 DECL_READ_P (decl) = 1;
1781 DECL_ARTIFICIAL (decl) = 1;
1782 DECL_INITIAL (decl) = error_mark_node;
1784 /* We must force the reference. */
1785 DECL_PRESERVE_P (decl) = 1;
1787 DECL_CONTEXT (decl) = NULL_TREE;
1788 finish_var_decl (decl, exp);
1791 static tree
1792 get_proto_encoding (tree proto)
1794 tree encoding;
1795 if (proto)
1797 if (! METHOD_ENCODING (proto))
1799 encoding = encode_method_prototype (proto);
1800 METHOD_ENCODING (proto) = encoding;
1802 else
1803 encoding = METHOD_ENCODING (proto);
1805 return add_objc_string (encoding, meth_var_types);
1807 else
1808 return build_int_cst (NULL_TREE, 0);
1811 static void
1812 build_gnu_selector_translation_table (void)
1814 tree chain, expr;
1815 VEC(constructor_elt,gc) *inits = NULL;
1816 VEC(constructor_elt,gc) *v ;
1818 /* Cause the selector table (previously forward-declared)
1819 to be actually output. */
1821 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1823 tree encoding;
1824 if (warn_selector)
1826 /* TODO: improve on the location for the diagnostic. */
1827 location_t loc = input_location;
1828 diagnose_missing_method (TREE_VALUE (chain), loc);
1831 v = NULL;
1832 expr = build_selector (TREE_VALUE (chain));
1833 encoding = get_proto_encoding (TREE_PURPOSE (chain));
1834 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1835 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, encoding);
1836 expr = objc_build_constructor (objc_selector_template, v);
1838 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1839 } /* each element in the chain */
1841 /* List terminator. */
1842 v = NULL;
1843 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1844 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1845 expr = objc_build_constructor (objc_selector_template, v);
1847 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1848 expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
1849 inits);
1850 finish_var_decl (UOBJC_SELECTOR_TABLE_decl, expr);
1853 /* Output references to all statically allocated objects. Return the DECL
1854 for the array built. */
1856 static void
1857 generate_static_references (void)
1859 tree expr = NULL_TREE;
1860 tree class_name, klass, decl;
1861 tree cl_chain, in_chain, type
1862 = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
1863 int num_inst, num_class;
1864 char buf[BUFSIZE];
1865 VEC(constructor_elt,gc) *decls = NULL;
1867 if (flag_next_runtime)
1868 gcc_unreachable ();
1870 for (cl_chain = objc_static_instances, num_class = 0;
1871 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1873 VEC(constructor_elt,gc) *v = NULL;
1875 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1876 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1878 snprintf (buf, BUFSIZE, "_OBJC_STATIC_INSTANCES_%d", num_class);
1879 decl = start_var_decl (type, buf);
1881 /* Output {class_name, ...}. */
1882 klass = TREE_VALUE (cl_chain);
1883 class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
1884 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1885 build_unary_op (input_location,
1886 ADDR_EXPR, class_name, 1));
1888 /* Output {..., instance, ...}. */
1889 for (in_chain = TREE_PURPOSE (cl_chain);
1890 in_chain; in_chain = TREE_CHAIN (in_chain))
1892 expr = build_unary_op (input_location,
1893 ADDR_EXPR, TREE_VALUE (in_chain), 1);
1894 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1897 /* Output {..., NULL}. */
1898 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1900 expr = objc_build_constructor (TREE_TYPE (decl), v);
1901 OBJCMETA (decl, objc_meta, meta_base);
1902 finish_var_decl (decl, expr);
1903 CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
1904 build_unary_op (input_location,
1905 ADDR_EXPR, decl, 1));
1908 CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
1909 expr = objc_build_constructor (type, decls);
1910 static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
1911 OBJCMETA (static_instances_decl, objc_meta, meta_base);
1912 finish_var_decl (static_instances_decl, expr);
1915 /* Create the initial value for the `defs' field of _objc_symtab.
1916 This is a CONSTRUCTOR. */
1918 static tree
1919 init_def_list (tree type)
1921 tree expr;
1922 struct imp_entry *impent;
1923 location_t loc;
1924 VEC(constructor_elt,gc) *v = NULL;
1926 if (imp_count)
1927 for (impent = imp_list; impent; impent = impent->next)
1929 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1931 loc = DECL_SOURCE_LOCATION (impent->class_decl);
1932 expr = build_unary_op (loc,
1933 ADDR_EXPR, impent->class_decl, 0);
1934 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1938 if (cat_count)
1939 for (impent = imp_list; impent; impent = impent->next)
1941 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1943 loc = DECL_SOURCE_LOCATION (impent->class_decl);
1944 expr = build_unary_op (loc,
1945 ADDR_EXPR, impent->class_decl, 0);
1946 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1950 loc = UNKNOWN_LOCATION;
1951 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1952 if (static_instances_decl)
1953 expr = build_unary_op (loc, ADDR_EXPR, static_instances_decl, 0);
1954 else
1955 expr = integer_zero_node;
1956 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1958 return objc_build_constructor (type, v);
1961 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1963 /* Predefine the following data type:
1965 struct _objc_symtab
1967 long sel_ref_cnt;
1968 SEL *refs;
1969 short cls_def_cnt;
1970 short cat_def_cnt;
1971 void *defs[cls_def_cnt + cat_def_cnt];
1972 }; */
1974 static void
1975 build_objc_symtab_template (void)
1977 tree fields, array_type, *chain = NULL;
1978 int index;
1980 objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
1982 /* long sel_ref_cnt; */
1983 fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
1985 /* SEL *refs; */
1986 add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
1988 /* short cls_def_cnt; */
1989 add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
1991 /* short cat_def_cnt; */
1992 add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
1994 if (TARGET_64BIT)
1995 add_field_decl (integer_type_node, "_explicit_padder", &chain);
1997 /* void *defs[imp_count + cat_count (+ 1)]; */
1998 /* NB: The index is one less than the size of the array. */
1999 index = imp_count + cat_count;
2000 array_type = build_sized_array_type (ptr_type_node, index + 1);
2001 add_field_decl (array_type, "defs", &chain);
2003 objc_finish_struct (objc_symtab_template, fields);
2005 /* Construct the initial value for all of _objc_symtab. */
2007 static tree
2008 init_objc_symtab (tree type)
2010 tree field, expr, ltyp;
2011 location_t loc;
2012 VEC(constructor_elt,gc) *v = NULL;
2014 loc = UNKNOWN_LOCATION;
2016 /* sel_ref_cnt = { ..., 5, ... } */
2018 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2019 build_int_cst (long_integer_type_node, 0));
2021 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2023 ltyp = build_pointer_type (objc_selector_type);
2024 if (sel_ref_chain)
2025 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR,
2026 UOBJC_SELECTOR_TABLE_decl, 1));
2027 else
2028 expr = convert (ltyp, null_pointer_node);
2029 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2031 /* cls_def_cnt = { ..., 5, ... } */
2033 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2034 build_int_cst (short_integer_type_node, imp_count));
2036 /* cat_def_cnt = { ..., 5, ... } */
2038 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2039 build_int_cst (short_integer_type_node, cat_count));
2040 if (TARGET_64BIT)
2041 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2042 build_int_cst (integer_type_node, 0));
2044 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2046 field = TYPE_FIELDS (type);
2047 if (TARGET_64BIT)
2048 field = DECL_CHAIN (field);
2049 field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2051 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2053 return objc_build_constructor (type, v);
2056 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2057 and initialized appropriately. */
2059 static void
2060 generate_objc_symtab_decl (void)
2062 build_objc_symtab_template ();
2063 UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2064 OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_base);
2065 finish_var_decl (UOBJC_SYMBOLS_decl,
2066 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2069 static void
2070 objc_generate_v1_gnu_metadata (void)
2072 struct imp_entry *impent;
2073 tree chain;
2075 /* Process the static instances here because initialization of objc_symtab
2076 depends on them. */
2077 if (objc_static_instances)
2078 generate_static_references ();
2080 objc_implementation_context =
2081 implementation_template =
2082 UOBJC_CLASS_decl =
2083 UOBJC_METACLASS_decl = NULL_TREE;
2085 for (impent = imp_list; impent; impent = impent->next)
2087 /* If -gen-decls is present, Dump the @interface of each class.
2088 TODO: Dump the classes in the order they were found, rather than in
2089 reverse order as we are doing now. */
2090 if (flag_gen_declaration)
2091 dump_interface (gen_declaration_file, impent->imp_context);
2093 /* all of the following reference the string pool... */
2094 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2095 generate_class_structures (impent);
2096 else
2097 generate_category (impent);
2100 /* If we are using an array of selectors, we must always
2101 finish up the array decl even if no selectors were used. */
2102 build_gnu_selector_translation_table ();
2104 if (protocol_chain)
2105 generate_protocols ();
2107 /* Arrange for ObjC data structures to be initialized at run time. */
2108 generate_objc_symtab_decl ();
2109 /* Make sure that the meta-data are identified as being GNU-runtime. */
2110 build_module_descriptor (OBJC_VERSION,
2111 build_tree_list (objc_meta, meta_base));
2112 build_module_initializer_routine ();
2114 /* Dump the class references. This forces the appropriate classes
2115 to be linked into the executable image, preserving unix archive
2116 semantics. This can be removed when we move to a more dynamically
2117 linked environment. */
2119 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2121 handle_class_ref (chain);
2122 if (TREE_PURPOSE (chain))
2123 generate_classref_translation_entry (chain);
2126 for (impent = imp_list; impent; impent = impent->next)
2127 handle_impent (impent);
2129 generate_strings ();
2132 /* --- exceptions --- */
2134 static GTY(()) tree objc_eh_personality_decl;
2136 static tree
2137 objc_eh_runtime_type (tree type)
2139 tree ident, eh_id, decl, str;
2141 if (type == error_mark_node
2142 || errorcount || sorrycount)
2144 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2145 to prevent an ICE. Note that we know that the compiler will
2146 terminate with an error and this 'ErrorMarkNode' class name will
2147 never be actually used. */
2148 ident = get_identifier ("ErrorMarkNode");
2149 goto make_err_class;
2152 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2153 /* We don't want to identify 'id' for GNU. Instead, build a 0
2154 entry in the exceptions table. */
2155 return null_pointer_node;
2157 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2159 #ifdef OBJCPLUS
2160 /* This routine is also called for c++ catch clauses; in which case,
2161 we use the c++ typeinfo decl. */
2162 return build_eh_type_type (type);
2163 #else
2164 error ("non-objective-c type '%T' cannot be caught", type);
2165 ident = get_identifier ("ErrorMarkNode");
2166 goto make_err_class;
2167 #endif
2169 else
2170 ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2172 make_err_class:
2173 /* If this class was already referenced, then it will be output during
2174 meta-data emission, so we don't need to do it here. */
2175 decl = get_objc_string_decl (ident, class_names);
2176 eh_id = add_objc_string (ident, class_names);
2177 if (!decl)
2179 /* Not found ... so we need to build it - from the freshly-entered id. */
2180 decl = get_objc_string_decl (ident, class_names);
2181 str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2182 IDENTIFIER_POINTER (ident));
2183 /* We have to finalize this var here, because this might be called after
2184 all the other metadata strings have been emitted. */
2185 finish_var_decl (decl, str);
2187 return eh_id;
2190 static tree
2191 objc_eh_personality (void)
2193 if (!objc_eh_personality_decl)
2194 #ifndef OBJCPLUS
2195 objc_eh_personality_decl = build_personality_function ("gnu_objc");
2196 #else
2197 objc_eh_personality_decl = build_personality_function ("gxx");
2198 #endif
2199 return objc_eh_personality_decl;
2202 /* -- interfaces --- */
2204 static tree
2205 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2207 tree t;
2208 VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
2209 /* A throw is just a call to the runtime throw function with the
2210 object as a parameter. */
2211 VEC_quick_push (tree, parms, throw_expr);
2212 t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
2213 VEC_free (tree, gc, parms);
2214 return add_stmt (t);
2217 /* Build __builtin_eh_pointer. */
2219 static tree
2220 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
2222 tree t;
2223 t = built_in_decls[BUILT_IN_EH_POINTER];
2224 t = build_call_expr (t, 1, integer_zero_node);
2225 return fold_convert (objc_object_type, t);
2228 static tree
2229 begin_catch (struct objc_try_context **cur_try_context, tree type,
2230 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2232 tree t;
2233 /* Record the data for the catch in the try context so that we can
2234 finalize it later. */
2235 if (ellipsis)
2236 t = build_stmt (input_location, CATCH_EXPR, NULL, compound);
2237 else
2238 t = build_stmt (input_location, CATCH_EXPR, type, compound);
2239 (*cur_try_context)->current_catch = t;
2241 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
2242 t = objc_build_exc_ptr (cur_try_context);
2243 t = convert (TREE_TYPE (decl), t);
2244 return build2 (MODIFY_EXPR, void_type_node, decl, t);
2247 static void
2248 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2250 append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2253 static tree
2254 finish_try_stmt (struct objc_try_context **cur_try_context)
2256 struct objc_try_context *c = *cur_try_context;
2257 tree stmt = c->try_body;
2258 if (c->catch_list)
2259 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2260 if (c->finally_body)
2261 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2262 return stmt;
2265 #include "gt-objc-objc-gnu-runtime-abi-01.h"