]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/objc/objc-gnu-runtime-abi-01.c
Update copyright years.
[thirdparty/gcc.git] / gcc / objc / objc-gnu-runtime-abi-01.c
1 /* GNU Runtime ABI version 8
2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
3 Contributed by Iain Sandoe (split from objc-act.c)
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "options.h"
25 #include "tree.h"
26 #include "stringpool.h"
27 #include "attribs.h"
28
29 #ifdef OBJCPLUS
30 #include "cp/cp-tree.h"
31 #else
32 #include "c/c-tree.h"
33 #include "c/c-lang.h"
34 #endif
35
36 #include "langhooks.h"
37 #include "c-family/c-objc.h"
38 #include "objc-act.h"
39
40 /* When building Objective-C++, we are not linking against the C front-end
41 and so need to replicate the C tree-construction functions in some way. */
42 #ifdef OBJCPLUS
43 #define OBJCP_REMAP_FUNCTIONS
44 #include "objcp-decl.h"
45 #endif /* OBJCPLUS */
46
47 #include "toplev.h"
48 #include "tree-iterator.h"
49
50 #include "objc-runtime-hooks.h"
51 #include "objc-runtime-shared-support.h"
52 #include "objc-encoding.h"
53
54 /* GNU runtime private definitions. */
55 #define DEF_CONSTANT_STRING_CLASS_NAME "NXConstantString"
56
57 #define TAG_GETCLASS "objc_get_class"
58 #define TAG_GETMETACLASS "objc_get_meta_class"
59
60 #define TAG_MSGSEND "objc_msg_lookup"
61 #define TAG_MSGSENDSUPER "objc_msg_lookup_super"
62
63 /* GNU-specific tags. */
64
65 #define TAG_EXECCLASS "__objc_exec_class"
66 #define TAG_GNUINIT "__objc_gnu_init"
67
68 /* The version identifies which language generation and runtime
69 the module (file) was compiled for, and is recorded in the
70 module descriptor. */
71 #define OBJC_VERSION 8
72
73 #define PROTOCOL_VERSION 2
74
75 /* This macro provides a method of removing ambiguity between runtimes
76 when LTO is in use on targets supporting multiple runtimes.
77
78 For example, at present, any target that includes an implementation of
79 the NeXT runtime needs to place Objective-C meta-data into specific
80 named sections. This should _not_ be done for the GNU runtime, and the
81 following macro is used to attach Objective-C private attributes that may
82 be used to identify the runtime for which the meta-data are intended. */
83
84 #define OBJCMETA(DECL,VERS,KIND) \
85 if (VERS) \
86 DECL_ATTRIBUTES (DECL) = build_tree_list ((VERS), (KIND));
87
88 static void gnu_runtime_01_initialize (void);
89
90 static void build_selector_template (void);
91
92 static tree gnu_runtime_abi_01_super_superclassfield_id (void);
93
94 static tree gnu_runtime_abi_01_class_decl (tree);
95 static tree gnu_runtime_abi_01_metaclass_decl (tree);
96 static tree gnu_runtime_abi_01_category_decl (tree);
97 static tree gnu_runtime_abi_01_protocol_decl (tree);
98 static tree gnu_runtime_abi_01_string_decl (tree, const char *, string_section);
99
100 static tree gnu_runtime_abi_01_get_class_reference (tree);
101 static tree gnu_runtime_abi_01_build_typed_selector_reference (location_t, tree,
102 tree);
103 static tree gnu_runtime_abi_01_get_protocol_reference (location_t, tree);
104 static tree gnu_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
105 static tree gnu_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
106 static tree gnu_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
107
108 static tree gnu_runtime_abi_01_receiver_is_class_object (tree);
109 static void gnu_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **,
110 tree, int, int);
111 static tree gnu_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
112 tree, tree, tree, int);
113
114 static bool gnu_runtime_abi_01_setup_const_string_class_decl (void);
115 static tree gnu_runtime_abi_01_build_const_string_constructor (location_t, tree,int);
116
117 static void objc_generate_v1_gnu_metadata (void);
118
119 static tree objc_eh_runtime_type (tree type);
120 static tree objc_eh_personality (void);
121 static tree objc_build_exc_ptr (struct objc_try_context **);
122 static tree build_throw_stmt (location_t, tree, bool);
123 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
124 static void finish_catch (struct objc_try_context **, tree);
125 static tree finish_try_stmt (struct objc_try_context **);
126
127 bool
128 objc_gnu_runtime_abi_01_init (objc_runtime_hooks *rthooks)
129 {
130 /* GNU runtime does not need the compiler to change code in order to do GC. */
131 if (flag_objc_gc)
132 {
133 warning_at (UNKNOWN_LOCATION, 0,
134 "%<-fobjc-gc%> is ignored for %<-fgnu-runtime%>");
135 flag_objc_gc = 0;
136 }
137
138 /* Although I guess we could, we don't currently support SJLJ exceptions for the
139 GNU runtime. */
140 if (flag_objc_sjlj_exceptions)
141 {
142 inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for %<-fgnu-runtime%>");
143 flag_objc_sjlj_exceptions = 0;
144 }
145
146 /* TODO: Complain if -fobjc-abi-version=N was used. */
147
148 /* TODO: Complain if -fobj-nilcheck was used. */
149
150 rthooks->initialize = gnu_runtime_01_initialize;
151 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
152 rthooks->tag_getclass = TAG_GETCLASS;
153 rthooks->super_superclassfield_ident = gnu_runtime_abi_01_super_superclassfield_id;
154
155 rthooks->class_decl = gnu_runtime_abi_01_class_decl;
156 rthooks->metaclass_decl = gnu_runtime_abi_01_metaclass_decl;
157 rthooks->category_decl = gnu_runtime_abi_01_category_decl;
158 rthooks->protocol_decl = gnu_runtime_abi_01_protocol_decl;
159 rthooks->string_decl = gnu_runtime_abi_01_string_decl;
160
161 rthooks->get_class_reference = gnu_runtime_abi_01_get_class_reference;
162 rthooks->build_selector_reference = gnu_runtime_abi_01_build_typed_selector_reference;
163 rthooks->get_protocol_reference = gnu_runtime_abi_01_get_protocol_reference;
164 rthooks->build_ivar_reference = gnu_runtime_abi_01_build_ivar_ref;
165 rthooks->get_class_super_ref = gnu_runtime_abi_01_get_class_super_ref;
166 rthooks->get_category_super_ref = gnu_runtime_abi_01_get_category_super_ref;
167
168 rthooks->receiver_is_class_object = gnu_runtime_abi_01_receiver_is_class_object;
169 rthooks->get_arg_type_list_base = gnu_runtime_abi_01_get_arg_type_list_base;
170 rthooks->build_objc_method_call = gnu_runtime_abi_01_build_objc_method_call;
171
172 rthooks->setup_const_string_class_decl =
173 gnu_runtime_abi_01_setup_const_string_class_decl;
174 rthooks->build_const_string_constructor =
175 gnu_runtime_abi_01_build_const_string_constructor;
176
177 rthooks->build_throw_stmt = build_throw_stmt;
178 rthooks->build_exc_ptr = objc_build_exc_ptr;
179 rthooks->begin_catch = begin_catch;
180 rthooks->finish_catch = finish_catch;
181 rthooks->finish_try_stmt = finish_try_stmt;
182
183 rthooks->generate_metadata = objc_generate_v1_gnu_metadata;
184 return true;
185 }
186
187 static void build_selector_table_decl (void);
188 static void build_class_template (void);
189 static void build_category_template (void);
190 static void build_protocol_template (void);
191
192 static GTY(()) tree objc_meta;
193 static GTY(()) tree meta_base;
194
195 static void gnu_runtime_01_initialize (void)
196 {
197 tree type, ftype, IMP_type;
198
199 /* We do not need to mark GNU ObjC metadata for different sections,
200 however, we do need to make sure that it is not mistaken for NeXT
201 metadata. */
202 objc_meta = get_identifier ("OBJC1METG");
203 meta_base = get_identifier ("NONE");
204
205 /* Declare type of selector-objects that represent an operation name. */
206 /* `const struct objc_selector *' */
207 type = xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR));
208 type = build_qualified_type (type, TYPE_QUAL_CONST);
209 objc_selector_type = build_pointer_type (type);
210
211 /* typedef id (*IMP)(id, SEL, ...); */
212 ftype = build_varargs_function_type_list (objc_object_type,
213 objc_object_type,
214 objc_selector_type,
215 NULL_TREE);
216
217 IMP_type = build_pointer_type (ftype);
218
219 build_class_template ();
220 build_super_template ();
221 build_protocol_template ();
222 build_category_template ();
223
224 /* GNU runtime messenger entry points. */
225 /* TREE_NOTHROW is cleared for the message-sending functions,
226 because the function that gets called can throw in Obj-C++, or
227 could itself call something that can throw even in Obj-C. */
228
229 /* IMP objc_msg_lookup (id, SEL); */
230 type = build_function_type_list (IMP_type,
231 objc_object_type,
232 objc_selector_type,
233 NULL_TREE);
234
235 umsg_decl = add_builtin_function (TAG_MSGSEND,
236 type, 0, NOT_BUILT_IN,
237 NULL, NULL_TREE);
238 TREE_NOTHROW (umsg_decl) = 0;
239
240 /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
241 type = build_function_type_list (IMP_type,
242 objc_super_type,
243 objc_selector_type,
244 NULL_TREE);
245
246 umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
247 type, 0, NOT_BUILT_IN,
248 NULL, NULL_TREE);
249 TREE_NOTHROW (umsg_super_decl) = 0;
250
251 /* The following GNU runtime entry point is called to initialize
252 each module:
253
254 __objc_exec_class (void *); */
255 type = build_function_type_list (void_type_node,
256 ptr_type_node,
257 NULL_TREE);
258
259 execclass_decl = add_builtin_function (TAG_EXECCLASS,
260 type, 0, NOT_BUILT_IN,
261 NULL, NULL_TREE);
262
263 type = build_function_type_list (objc_object_type,
264 const_string_type_node,
265 NULL_TREE);
266
267 /* id objc_getClass (const char *); */
268 objc_get_class_decl
269 = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
270 NULL, NULL_TREE);
271
272 /* id objc_getMetaClass (const char *); */
273 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS, type,
274 0, NOT_BUILT_IN, NULL,
275 NULL_TREE);
276
277 /* static SEL _OBJC_SELECTOR_TABLE[]; */
278 build_selector_table_decl ();
279
280 /* Stuff for properties.
281 The codegen relies on this being NULL for GNU. */
282 objc_copyStruct_decl = NULL_TREE;
283
284 /* This is the type of all of the following functions
285 bjc_getPropertyStruct() and objc_setPropertyStruct(). */
286 type = build_function_type_list (void_type_node,
287 ptr_type_node,
288 const_ptr_type_node,
289 ptrdiff_type_node,
290 boolean_type_node,
291 boolean_type_node,
292 NULL_TREE);
293
294 /* Declare the following function:
295 void
296 objc_getPropertyStruct (void *destination, const void *source,
297 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
298 objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct",
299 type, 0, NOT_BUILT_IN,
300 NULL, NULL_TREE);
301 TREE_NOTHROW (objc_getPropertyStruct_decl) = 0;
302 /* Declare the following function:
303 void
304 objc_setPropertyStruct (void *destination, const void *source,
305 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
306 objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct",
307 type, 0, NOT_BUILT_IN,
308 NULL, NULL_TREE);
309 TREE_NOTHROW (objc_setPropertyStruct_decl) = 0;
310
311 using_eh_for_cleanups ();
312 lang_hooks.eh_runtime_type = objc_eh_runtime_type;
313 lang_hooks.eh_personality = objc_eh_personality;
314 }
315
316 /* --- templates --- */
317 /* struct _objc_selector {
318 SEL sel_id;
319 char *sel_type;
320 }; */
321
322 static void
323 build_selector_template (void)
324 {
325 tree decls, *chain = NULL;
326
327 objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
328
329 /* SEL sel_id; */
330 decls = add_field_decl (objc_selector_type, "sel_id", &chain);
331
332 /* char *sel_type; */
333 add_field_decl (string_type_node, "sel_type", &chain);
334
335 objc_finish_struct (objc_selector_template, decls);
336 }
337
338 /* struct _objc_class {
339 struct _objc_class *isa;
340 struct _objc_class *super_class;
341 char *name;
342 long version;
343 long info;
344 long instance_size;
345 struct _objc_ivar_list *ivars;
346 struct _objc_method_list *methods;
347 struct sarray *dtable;
348 struct _objc_class *subclass_list;
349 struct _objc_class *sibling_class;
350 struct _objc_protocol_list *protocols;
351 void *gc_object_type;
352 }; */
353
354 static void
355 build_class_template (void)
356 {
357 tree ptype, decls, *chain = NULL;
358
359 objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
360
361 /* struct _objc_class *isa; */
362 decls = add_field_decl (build_pointer_type (objc_class_template),
363 "isa", &chain);
364
365 /* struct _objc_class *super_class; */
366 add_field_decl (build_pointer_type (objc_class_template),
367 "super_class", &chain);
368
369 /* char *name; */
370 add_field_decl (string_type_node, "name", &chain);
371
372 /* long version; */
373 add_field_decl (long_integer_type_node, "version", &chain);
374
375 /* long info; */
376 add_field_decl (long_integer_type_node, "info", &chain);
377
378 /* long instance_size; */
379 add_field_decl (long_integer_type_node, "instance_size", &chain);
380
381 /* struct _objc_ivar_list *ivars; */
382 add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
383
384 /* struct _objc_method_list *methods; */
385 add_field_decl (objc_method_list_ptr, "methods", &chain);
386
387 /* struct sarray *dtable; */
388 ptype = build_pointer_type(xref_tag (RECORD_TYPE,
389 get_identifier ("sarray")));
390 add_field_decl (ptype, "dtable", &chain);
391
392 /* struct objc_class *subclass_list; */
393 ptype = build_pointer_type (objc_class_template);
394 add_field_decl (ptype, "subclass_list", &chain);
395
396 /* struct objc_class *sibling_class; */
397 ptype = build_pointer_type (objc_class_template);
398 add_field_decl (ptype, "sibling_class", &chain);
399
400 /* struct _objc_protocol **protocol_list; */
401 ptype = build_pointer_type (build_pointer_type
402 (xref_tag (RECORD_TYPE,
403 get_identifier (UTAG_PROTOCOL))));
404 add_field_decl (ptype, "protocol_list", &chain);
405
406 /* void *gc_object_type; */
407 add_field_decl (build_pointer_type (void_type_node),
408 "gc_object_type", &chain);
409
410 objc_finish_struct (objc_class_template, decls);
411 }
412
413 /* struct _objc_category {
414 char *category_name;
415 char *class_name;
416 struct _objc_method_list *instance_methods;
417 struct _objc_method_list *class_methods;
418 struct _objc_protocol_list *protocols;
419 }; */
420
421 static void
422 build_category_template (void)
423 {
424 tree ptype, decls, *chain = NULL;
425
426 objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
427
428 /* char *category_name; */
429 decls = add_field_decl (string_type_node, "category_name", &chain);
430
431 /* char *class_name; */
432 add_field_decl (string_type_node, "class_name", &chain);
433
434 /* struct _objc_method_list *instance_methods; */
435 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
436
437 /* struct _objc_method_list *class_methods; */
438 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
439
440 /* struct _objc_protocol **protocol_list; */
441 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
442 add_field_decl (ptype, "protocol_list", &chain);
443
444 objc_finish_struct (objc_category_template, decls);
445 }
446
447 /* struct _objc_protocol {
448 struct _objc_class *isa;
449 char *protocol_name;
450 struct _objc_protocol **protocol_list;
451 struct _objc__method_prototype_list *instance_methods;
452 struct _objc__method_prototype_list *class_methods;
453 }; */
454
455 static void
456 build_protocol_template (void)
457 {
458 tree ptype, decls, *chain = NULL;
459
460 objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
461
462 /* struct _objc_class *isa; */
463 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
464 get_identifier (UTAG_CLASS)));
465 decls = add_field_decl (ptype, "isa", &chain);
466
467 /* char *protocol_name; */
468 add_field_decl (string_type_node, "protocol_name", &chain);
469
470 /* struct _objc_protocol **protocol_list; */
471 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
472 add_field_decl (ptype, "protocol_list", &chain);
473
474 /* struct _objc__method_prototype_list *instance_methods; */
475 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
476
477 /* struct _objc__method_prototype_list *class_methods; */
478 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
479
480 objc_finish_struct (objc_protocol_template, decls);
481 }
482
483 /* --- names, decls + identifiers --- */
484
485 static void
486 build_selector_table_decl (void)
487 {
488 tree temp;
489
490 build_selector_template ();
491 temp = build_array_type (objc_selector_template, NULL_TREE);
492
493 UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
494 /* Squash `defined but not used' warning check_global_declaration. */
495 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
496 OBJCMETA (UOBJC_SELECTOR_TABLE_decl, objc_meta, meta_base);
497 }
498
499
500 static tree
501 gnu_runtime_abi_01_super_superclassfield_id (void)
502 {
503 if (!super_superclassfield_id)
504 super_superclassfield_id = get_identifier ("super_class");
505 return super_superclassfield_id;
506 }
507
508
509 static tree
510 gnu_runtime_abi_01_class_decl (tree klass)
511 {
512 tree decl;
513 char buf[BUFSIZE];
514 snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
515 IDENTIFIER_POINTER (CLASS_NAME (klass)));
516 decl = start_var_decl (objc_class_template, buf);
517 OBJCMETA (decl, objc_meta, meta_base);
518 return decl;
519 }
520
521 static tree
522 gnu_runtime_abi_01_metaclass_decl (tree klass)
523 {
524 tree decl;
525 char buf[BUFSIZE];
526 snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
527 IDENTIFIER_POINTER (CLASS_NAME (klass)));
528 decl = start_var_decl (objc_class_template, buf);
529 OBJCMETA (decl, objc_meta, meta_base);
530 return decl;
531 }
532
533 static tree
534 gnu_runtime_abi_01_category_decl (tree klass)
535 {
536 tree decl;
537 char buf[BUFSIZE];
538 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
539 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
540 IDENTIFIER_POINTER (CLASS_NAME (klass)));
541 decl = start_var_decl (objc_category_template, buf);
542 OBJCMETA (decl, objc_meta, meta_base);
543 return decl;
544 }
545
546 static tree
547 gnu_runtime_abi_01_protocol_decl (tree p)
548 {
549 tree decl;
550 char buf[BUFSIZE];
551
552 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
553 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
554 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
555 decl = start_var_decl (objc_protocol_template, buf);
556 OBJCMETA (decl, objc_meta, meta_base);
557 return decl;
558 }
559
560 static tree
561 gnu_runtime_abi_01_string_decl (tree type, const char *name,
562 string_section where ATTRIBUTE_UNUSED)
563 {
564 tree decl = start_var_decl (type, name);
565 OBJCMETA (decl, objc_meta, meta_base);
566 return decl;
567 }
568
569 /* --- entry --- */
570
571 static tree
572 gnu_runtime_abi_01_get_class_reference (tree ident)
573 {
574 tree params;
575
576 add_class_reference (ident);
577
578 params = build_tree_list (NULL_TREE, my_build_string_pointer
579 (IDENTIFIER_LENGTH (ident) + 1,
580 IDENTIFIER_POINTER (ident)));
581
582 return build_function_call (input_location, objc_get_class_decl, params);
583 }
584
585 /* Used by build_function_type_for_method. Append the types for
586 receiver & _cmd at the start of a method argument list to ARGTYPES.
587 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
588 trying to define a method or call one. SUPERFLAG says this is for a
589 send to super. METH may be NULL, in the case that there is no
590 prototype. */
591
592 static void
593 gnu_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
594 tree meth, int context,
595 int superflag ATTRIBUTE_UNUSED)
596 {
597 tree receiver_type;
598
599 if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
600 receiver_type = objc_instance_type;
601 else
602 receiver_type = objc_object_type;
603
604 vec_safe_push (*argtypes, receiver_type);
605 /* Selector type - will eventually change to `int'. */
606 vec_safe_push (*argtypes, objc_selector_type);
607 }
608
609 /* Unused for GNU runtime. */
610 static tree
611 gnu_runtime_abi_01_receiver_is_class_object (tree a ATTRIBUTE_UNUSED)
612 {
613 return NULL_TREE;
614 }
615
616 /* sel_ref_chain is a list whose "value" fields will be instances of
617 identifier_node that represent the selector. LOC is the location of
618 the @selector. */
619
620 static tree
621 gnu_runtime_abi_01_build_typed_selector_reference (location_t loc, tree ident,
622 tree prototype)
623 {
624 tree *chain = &sel_ref_chain;
625 tree expr;
626 int index = 0;
627
628 while (*chain)
629 {
630 /* When we do a lookup for @selector () we have no idea of the
631 prototype - so match the first we find. */
632 if (TREE_VALUE (*chain) == ident
633 && (!prototype || TREE_PURPOSE (*chain) == prototype))
634 goto return_at_index;
635
636 index++;
637 chain = &TREE_CHAIN (*chain);
638 }
639
640 *chain = tree_cons (prototype, ident, NULL_TREE);
641
642 /* TODO: Use a vec and keep this in it to (a) avoid re-creating and
643 (b) provide better diagnostics for the first time an undefined
644 selector is used. */
645 return_at_index:
646 expr = build_unary_op (loc, ADDR_EXPR,
647 build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
648 build_int_cst (NULL_TREE, index)),
649 1);
650 return convert (objc_selector_type, expr);
651 }
652
653 /* Build a tree expression to send OBJECT the operation SELECTOR,
654 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
655 assuming the method has prototype METHOD_PROTOTYPE.
656 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
657 LOC is the location of the expression to build.
658 Use METHOD_PARAMS as list of args to pass to the method.
659 If SUPER_FLAG is nonzero, we look up the superclass's method. */
660
661 static tree
662 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
663 tree lookup_object, tree selector,
664 tree method_params)
665 {
666 tree sender = (super_flag ? umsg_super_decl
667 : (flag_objc_direct_dispatch ? umsg_fast_decl
668 : umsg_decl));
669 tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
670 vec<tree, va_gc> *parms;
671 vec<tree, va_gc> *tv;
672 unsigned nparm = (method_params ? list_length (method_params) : 0);
673
674 /* If a prototype for the method to be called exists, then cast
675 the sender's return type and arguments to match that of the method.
676 Otherwise, leave sender as is. */
677 tree ret_type
678 = (method_prototype
679 ? TREE_VALUE (TREE_TYPE (method_prototype))
680 : objc_object_type);
681 tree ftype
682 = build_function_type_for_method (ret_type, method_prototype,
683 METHOD_REF, super_flag);
684 tree sender_cast;
685 tree method, t;
686
687 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
688 ftype = build_type_attribute_variant (ftype,
689 METHOD_TYPE_ATTRIBUTES
690 (method_prototype));
691
692 sender_cast = build_pointer_type (ftype);
693
694 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
695
696 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
697 lookup_object = save_expr (lookup_object);
698
699 /* Param list + 2 slots for object and selector. */
700 vec_alloc (parms, nparm + 2);
701 vec_alloc (tv, 2);
702
703 /* First, call the lookup function to get a pointer to the method,
704 then cast the pointer, then call it with the method arguments. */
705 tv->quick_push (lookup_object);
706 tv->quick_push (selector);
707 method = build_function_call_vec (loc, vNULL, sender, tv, NULL);
708 vec_free (tv);
709
710 /* Pass the appropriate object to the method. */
711 parms->quick_push ((super_flag ? self_decl : lookup_object));
712
713 /* Pass the selector to the method. */
714 parms->quick_push (selector);
715 /* Now append the remainder of the parms. */
716 if (nparm)
717 for (; method_params; method_params = TREE_CHAIN (method_params))
718 parms->quick_push (TREE_VALUE (method_params));
719
720 /* Build an obj_type_ref, with the correct cast for the method call. */
721 t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
722 t = build_function_call_vec (loc, vNULL, t, parms, NULL);
723 vec_free (parms);
724 return t;
725 }
726
727 static tree
728 gnu_runtime_abi_01_build_objc_method_call (location_t loc,
729 tree method_prototype,
730 tree receiver,
731 tree rtype ATTRIBUTE_UNUSED,
732 tree sel_name,
733 tree method_params,
734 int super ATTRIBUTE_UNUSED)
735 {
736 tree selector =
737 gnu_runtime_abi_01_build_typed_selector_reference (loc,
738 sel_name,
739 method_prototype);
740
741 return build_objc_method_call (loc, super, method_prototype, receiver,
742 selector, method_params);
743 }
744
745 static tree
746 gnu_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
747 {
748 tree expr, protocol_struct_type, *chain;
749 if (!PROTOCOL_FORWARD_DECL (p))
750 PROTOCOL_FORWARD_DECL (p) = gnu_runtime_abi_01_protocol_decl (p);
751
752 expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
753
754 /* ??? Ideally we'd build the reference with objc_protocol_type directly,
755 if we have it, rather than converting it here. */
756 expr = convert (objc_protocol_type, expr);
757
758 /* The @protocol() expression is being compiled into a pointer to a
759 statically allocated instance of the Protocol class. To become
760 usable at runtime, the 'isa' pointer of the instance need to be
761 fixed up at runtime by the runtime library, to point to the
762 actual 'Protocol' class. */
763
764 /* For the GNU runtime, put the static Protocol instance in the list
765 of statically allocated instances, so that we make sure that its
766 'isa' pointer is fixed up at runtime by the GNU runtime library
767 to point to the Protocol class (at runtime, when loading the
768 module, the GNU runtime library loops on the statically allocated
769 instances (as found in the defs field in objc_symtab) and fixups
770 all the 'isa' pointers of those objects). */
771
772 /* This type is a struct containing the fields of a Protocol
773 object. (Cfr. objc_protocol_type instead is the type of a pointer
774 to such a struct). */
775 protocol_struct_type = xref_tag (RECORD_TYPE,
776 get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
777
778 /* Look for the list of Protocol statically allocated instances
779 to fixup at runtime. Create a new list to hold Protocol
780 statically allocated instances, if the list is not found. At
781 present there is only another list, holding NSConstantString
782 static instances to be fixed up at runtime. */
783
784 for (chain = &objc_static_instances;
785 *chain && TREE_VALUE (*chain) != protocol_struct_type;
786 chain = &TREE_CHAIN (*chain));
787
788 if (!*chain)
789 {
790 *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
791 add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
792 class_names);
793 }
794
795 /* Add this statically allocated instance to the Protocol list. */
796 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
797 PROTOCOL_FORWARD_DECL (p),
798 TREE_PURPOSE (*chain));
799 return expr;
800 }
801
802 /* For ABI 8 an IVAR is just a fixed offset in the class struct. */
803
804 static tree
805 gnu_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
806 tree base, tree id)
807 {
808 return objc_build_component_ref (base, id);
809 }
810
811 /* We build super class references as we need them (but keep them once
812 built for the sake of efficiency). */
813
814 static tree
815 gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
816 struct imp_entry *imp, bool inst_meth)
817 {
818 if (inst_meth)
819 {
820 if (!ucls_super_ref)
821 ucls_super_ref =
822 objc_build_component_ref (imp->class_decl,
823 get_identifier ("super_class"));
824 return ucls_super_ref;
825 }
826 else
827 {
828 if (!uucls_super_ref)
829 uucls_super_ref =
830 objc_build_component_ref (imp->meta_decl,
831 get_identifier ("super_class"));
832 return uucls_super_ref;
833 }
834 }
835
836 static tree
837 gnu_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
838 struct imp_entry *imp, bool inst_meth)
839 {
840 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
841 tree super_class;
842
843 add_class_reference (super_name);
844 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
845 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
846 IDENTIFIER_POINTER (super_name));
847 /* super_class = get_{meta_}class("CLASS_SUPER_NAME"); */
848 return build_function_call (input_location,
849 super_class,
850 build_tree_list (NULL_TREE, super_name));
851 }
852
853 static bool
854 gnu_runtime_abi_01_setup_const_string_class_decl (void)
855 {
856 /* Do nothing, and create no error. */
857 return true;
858 }
859
860 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
861
862 static GTY(()) int num_static_inst;
863
864 static tree
865 objc_add_static_instance (tree constructor, tree class_decl)
866 {
867 tree *chain, decl;
868 char buf[BUFSIZE];
869
870 /* Find the list of static instances for the CLASS_DECL. Create one if
871 not found. */
872 for (chain = &objc_static_instances;
873 *chain && TREE_VALUE (*chain) != class_decl;
874 chain = &TREE_CHAIN (*chain));
875 if (!*chain)
876 {
877 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
878 add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
879 }
880
881 snprintf (buf, BUFSIZE, "_OBJC_INSTANCE_%d", num_static_inst++);
882 decl = build_decl (input_location,
883 VAR_DECL, get_identifier (buf), class_decl);
884 TREE_STATIC (decl) = 1;
885 DECL_ARTIFICIAL (decl) = 1;
886 TREE_USED (decl) = 1;
887 DECL_INITIAL (decl) = constructor;
888 DECL_CONTEXT (decl) = NULL;
889 OBJCMETA (decl, objc_meta, meta_base);
890
891 /* We may be writing something else just now.
892 Postpone till end of input. */
893 DECL_DEFER_OUTPUT (decl) = 1;
894 lang_hooks.decls.pushdecl (decl);
895 rest_of_decl_compilation (decl, 1, 0);
896
897 /* Add the DECL to the head of this CLASS' list. */
898 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
899
900 return decl;
901 }
902
903 static tree
904 gnu_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
905 int length)
906 {
907 tree constructor, fields;
908 vec<constructor_elt, va_gc> *v = NULL;
909
910 /* GNU: (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length }) */
911 fields = TYPE_FIELDS (internal_const_str_type);
912 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, 0));
913
914 fields = DECL_CHAIN (fields);
915 CONSTRUCTOR_APPEND_ELT (v, fields, build_unary_op (loc,
916 ADDR_EXPR, string, 1));
917
918 fields = DECL_CHAIN (fields);
919 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
920 constructor = objc_build_constructor (internal_const_str_type, v);
921
922 constructor = objc_add_static_instance (constructor, constant_string_type);
923 return constructor;
924 }
925
926 /* --- metadata - module initializer --- */
927
928 /* The GNU runtime requires us to provide a static initializer function
929 for each module:
930
931 static void __objc_gnu_init (void) {
932 __objc_exec_class (&L_OBJC_MODULES);
933 } */
934
935
936 static void
937 build_module_initializer_routine (void)
938 {
939 tree body;
940
941 #ifdef OBJCPLUS
942 push_lang_context (lang_name_c); /* extern "C" */
943 #endif
944
945 objc_push_parm (build_decl (input_location,
946 PARM_DECL, NULL_TREE, void_type_node));
947 #ifdef OBJCPLUS
948 objc_start_function (get_identifier (TAG_GNUINIT),
949 build_function_type_list (void_type_node, NULL_TREE),
950 NULL_TREE, NULL_TREE);
951 #else
952 objc_start_function (get_identifier (TAG_GNUINIT),
953 build_function_type_list (void_type_node, NULL_TREE),
954 NULL_TREE, objc_get_parm_info (0, NULL_TREE));
955 #endif
956 body = c_begin_compound_stmt (true);
957 add_stmt (build_function_call
958 (input_location,
959 execclass_decl,
960 build_tree_list
961 (NULL_TREE,
962 build_unary_op (input_location, ADDR_EXPR,
963 UOBJC_MODULES_decl, 0))));
964 add_stmt (c_end_compound_stmt (input_location, body, true));
965
966 TREE_PUBLIC (current_function_decl) = 0;
967
968 #ifndef OBJCPLUS
969 /* For Objective-C++, we will need to call __objc_gnu_init
970 from objc_generate_static_init_call() below. */
971 DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
972 #endif
973
974 GNU_INIT_decl = current_function_decl;
975 finish_function ();
976
977 #ifdef OBJCPLUS
978 pop_lang_context ();
979 #endif
980 }
981
982 #ifdef OBJCPLUS
983 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
984 to be called by the module initializer routine. */
985
986 int
987 objc_static_init_needed_p (void)
988 {
989 return (GNU_INIT_decl != NULL_TREE);
990 }
991
992 /* Generate a call to the __objc_gnu_init initializer function. */
993
994 tree
995 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
996 {
997 add_stmt (build_stmt (input_location, EXPR_STMT,
998 build_function_call (input_location,
999 GNU_INIT_decl, NULL_TREE)));
1000
1001 return ctors;
1002 }
1003 #endif /* OBJCPLUS */
1004
1005 /* --- Output GNU Meta-data --- */
1006
1007 static void
1008 generate_classref_translation_entry (tree chain)
1009 {
1010 tree expr, decl, type;
1011
1012 decl = TREE_PURPOSE (chain);
1013 type = TREE_TYPE (decl);
1014
1015 expr = add_objc_string (TREE_VALUE (chain), class_names);
1016 expr = convert (type, expr); /* cast! */
1017
1018 /* This is a class reference. It is re-written by the runtime,
1019 but will be optimized away unless we force it. */
1020 DECL_PRESERVE_P (decl) = 1;
1021 OBJCMETA (decl, objc_meta, meta_base);
1022 finish_var_decl (decl, expr);
1023 return;
1024 }
1025
1026
1027 static void
1028 handle_impent (struct imp_entry *impent)
1029 {
1030 char *string;
1031
1032 /* objc_implementation_context = impent->imp_context;
1033 implementation_template = impent->imp_template;*/
1034
1035 switch (TREE_CODE (impent->imp_context))
1036 {
1037 case CLASS_IMPLEMENTATION_TYPE:
1038 {
1039 const char *const class_name =
1040 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1041
1042 string = (char *) alloca (strlen (class_name) + 30);
1043
1044 sprintf (string, "__objc_class_name_%s", class_name);
1045 break;
1046 }
1047 case CATEGORY_IMPLEMENTATION_TYPE:
1048 {
1049 const char *const class_name =
1050 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1051 const char *const class_super_name =
1052 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
1053
1054 string = (char *) alloca (strlen (class_name)
1055 + strlen (class_super_name) + 30);
1056
1057 /* Do the same for categories. Even though no references to
1058 these symbols are generated automatically by the compiler,
1059 it gives you a handle to pull them into an archive by
1060 hand. */
1061 sprintf (string, "*__objc_category_name_%s_%s", class_name, class_super_name);
1062 break;
1063 }
1064 default:
1065 return;
1066 }
1067
1068 {
1069 tree decl, init;
1070
1071 init = integer_zero_node;
1072 decl = build_decl (input_location,
1073 VAR_DECL, get_identifier (string), TREE_TYPE (init));
1074 TREE_PUBLIC (decl) = 1;
1075 TREE_READONLY (decl) = 1;
1076 TREE_USED (decl) = 1;
1077 TREE_CONSTANT (decl) = 1;
1078 DECL_CONTEXT (decl) = NULL_TREE;
1079 DECL_ARTIFICIAL (decl) = 1;
1080 TREE_STATIC (decl) = 1;
1081 DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
1082 /* We must force the reference. */
1083 DECL_PRESERVE_P (decl) = 1;
1084
1085 finish_var_decl(decl, init) ;
1086 }
1087 }
1088
1089 tree
1090 build_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1091 tree inst_methods, tree class_methods)
1092 {
1093 tree expr, ttyp;
1094 location_t loc;
1095 vec<constructor_elt, va_gc> *inits = NULL;
1096
1097 /* TODO: pass the loc in or find it from args. */
1098 loc = input_location;
1099 ttyp = build_pointer_type (xref_tag (RECORD_TYPE,
1100 get_identifier (UTAG_CLASS)));
1101 /* Filling the "isa" in with a version allows the runtime system to
1102 detect this ... */
1103 expr = build_int_cst (ttyp, PROTOCOL_VERSION);
1104
1105 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1106
1107 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1108 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1109
1110 ttyp = objc_method_proto_list_ptr;
1111 if (inst_methods)
1112 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1113 else
1114 expr = convert (ttyp, null_pointer_node);
1115 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1116
1117 if (class_methods)
1118 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1119 else
1120 expr = convert (ttyp, null_pointer_node);
1121 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1122
1123 return objc_build_constructor (type, inits);
1124 }
1125
1126 static tree
1127 generate_protocol_list (tree i_or_p, tree klass_ctxt)
1128 {
1129 tree array_type, ptype, refs_decl, lproto, e, plist;
1130 vec<constructor_elt, va_gc> *v = NULL;
1131 char buf[BUFSIZE];
1132 int size = 0;
1133
1134 switch (TREE_CODE (i_or_p))
1135 {
1136 case CLASS_INTERFACE_TYPE:
1137 case CATEGORY_INTERFACE_TYPE:
1138 plist = CLASS_PROTOCOL_LIST (i_or_p);
1139 break;
1140 case PROTOCOL_INTERFACE_TYPE:
1141 plist = PROTOCOL_LIST (i_or_p);
1142 break;
1143 default:
1144 gcc_unreachable ();
1145 }
1146
1147 /* Compute size. */
1148 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1149 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1150 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1151 size++;
1152
1153 /* Build initializer. */
1154 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1155 e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1156 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1157
1158 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1159 {
1160 tree pval = TREE_VALUE (lproto);
1161
1162 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1163 && PROTOCOL_FORWARD_DECL (pval))
1164 {
1165 tree fwref = PROTOCOL_FORWARD_DECL (pval);
1166 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1167 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1168 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1169 }
1170 }
1171
1172 /* static struct objc_protocol *refs[n]; */
1173
1174 switch (TREE_CODE (i_or_p))
1175 {
1176 case PROTOCOL_INTERFACE_TYPE:
1177 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1178 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1179 break;
1180 case CLASS_INTERFACE_TYPE:
1181 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1182 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1183 break;
1184 case CATEGORY_INTERFACE_TYPE:
1185 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1186 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1187 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1188 break;
1189 default:
1190 gcc_unreachable ();
1191 }
1192
1193 ptype = build_pointer_type (objc_protocol_template);
1194 array_type = build_sized_array_type (ptype, size + 3);
1195 refs_decl = start_var_decl (array_type, buf);
1196 OBJCMETA (refs_decl, objc_meta, meta_base);
1197 finish_var_decl (refs_decl,
1198 objc_build_constructor (TREE_TYPE (refs_decl), v));
1199
1200 return refs_decl;
1201 }
1202
1203 static tree
1204 generate_v1_meth_descriptor_table (tree chain, tree protocol, const char *prefix)
1205 {
1206 tree method_list_template, initlist, decl;
1207 int size;
1208 vec<constructor_elt, va_gc> *v = NULL;
1209 char buf[BUFSIZE];
1210
1211 if (!chain || !prefix)
1212 return NULL_TREE;
1213
1214 if (!objc_method_prototype_template)
1215 objc_method_prototype_template = build_method_prototype_template ();
1216
1217 size = list_length (chain);
1218 method_list_template =
1219 build_method_prototype_list_template (objc_method_prototype_template,
1220 size);
1221 snprintf (buf, BUFSIZE, "%s_%s", prefix,
1222 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1223
1224 decl = start_var_decl (method_list_template, buf);
1225
1226 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1227 initlist =
1228 build_descriptor_table_initializer (objc_method_prototype_template,
1229 chain);
1230 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1231 OBJCMETA (decl, objc_meta, meta_base);
1232 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1233 return decl;
1234 }
1235
1236 /* For each protocol which was referenced either from a @protocol()
1237 expression, or because a class/category implements it (then a
1238 pointer to the protocol is stored in the struct describing the
1239 class/category), we create a statically allocated instance of the
1240 Protocol class. The code is written in such a way as to generate
1241 as few Protocol objects as possible; we generate a unique Protocol
1242 instance for each protocol, and we don't generate a Protocol
1243 instance if the protocol is never referenced (either from a
1244 @protocol() or from a class/category implementation). These
1245 statically allocated objects can be referred to via the static
1246 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1247
1248 The statically allocated Protocol objects that we generate here
1249 need to be fixed up at runtime in order to be used: the 'isa'
1250 pointer of the objects need to be set up to point to the 'Protocol'
1251 class, as known at runtime.
1252
1253 The GNU runtime fixes up all protocols before user code from the module
1254 is executed; it requires pointers to those symbols
1255 to be put in the objc_symtab (which is then passed as argument to
1256 the function __objc_exec_class() which the compiler sets up to be
1257 executed automatically when the module is loaded); setup of those
1258 Protocol objects happen in two ways in the GNU runtime: all
1259 Protocol objects referred to by a class or category implementation
1260 are fixed up when the class/category is loaded; all Protocol
1261 objects referred to by a @protocol() expression are added by the
1262 compiler to the list of statically allocated instances to fixup
1263 (the same list holding the statically allocated constant string
1264 objects). Because, as explained above, the compiler generates as
1265 few Protocol objects as possible, some Protocol object might end up
1266 being referenced multiple times when compiled with the GNU runtime,
1267 and end up being fixed up multiple times at runtime initialization.
1268 But that doesn't hurt, it's just a little inefficient. */
1269
1270 static void
1271 generate_protocols (void)
1272 {
1273 tree p, encoding;
1274 tree decl;
1275 tree initlist, protocol_name_expr, refs_decl, refs_expr;
1276
1277 /* If a protocol was directly referenced, pull in indirect references. */
1278 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1279 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1280 generate_protocol_references (PROTOCOL_LIST (p));
1281
1282 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1283 {
1284 tree nst_methods = PROTOCOL_NST_METHODS (p);
1285 tree cls_methods = PROTOCOL_CLS_METHODS (p);
1286
1287 /* If protocol wasn't referenced, don't generate any code. */
1288 decl = PROTOCOL_FORWARD_DECL (p);
1289
1290 if (!decl)
1291 continue;
1292
1293 /* Make sure we link in the Protocol class. */
1294 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1295
1296 while (nst_methods)
1297 {
1298 if (! METHOD_ENCODING (nst_methods))
1299 {
1300 encoding = encode_method_prototype (nst_methods);
1301 METHOD_ENCODING (nst_methods) = encoding;
1302 }
1303 nst_methods = DECL_CHAIN (nst_methods);
1304 }
1305
1306 UOBJC_INSTANCE_METHODS_decl =
1307 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1308 "_OBJC_PROTOCOL_INSTANCE_METHODS");
1309
1310 while (cls_methods)
1311 {
1312 if (! METHOD_ENCODING (cls_methods))
1313 {
1314 encoding = encode_method_prototype (cls_methods);
1315 METHOD_ENCODING (cls_methods) = encoding;
1316 }
1317
1318 cls_methods = DECL_CHAIN (cls_methods);
1319 }
1320
1321 UOBJC_CLASS_METHODS_decl =
1322 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1323 "_OBJC_PROTOCOL_CLASS_METHODS");
1324 /* generate_method_descriptors (p);*/
1325
1326 if (PROTOCOL_LIST (p))
1327 refs_decl = generate_protocol_list (p, NULL_TREE);
1328 else
1329 refs_decl = 0;
1330
1331 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1332 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1333
1334 if (refs_decl)
1335 refs_expr = convert (build_pointer_type (build_pointer_type
1336 (objc_protocol_template)),
1337 build_unary_op (input_location,
1338 ADDR_EXPR, refs_decl, 0));
1339 else
1340 refs_expr = build_int_cst (NULL_TREE, 0);
1341
1342 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
1343 by generate_method_descriptors, which is called above. */
1344 initlist = build_protocol_initializer (TREE_TYPE (decl),
1345 protocol_name_expr, refs_expr,
1346 UOBJC_INSTANCE_METHODS_decl,
1347 UOBJC_CLASS_METHODS_decl);
1348 finish_var_decl (decl, initlist);
1349 }
1350 }
1351
1352 static tree
1353 generate_dispatch_table (tree chain, const char *name)
1354 {
1355 tree decl, method_list_template, initlist;
1356 vec<constructor_elt, va_gc> *v = NULL;
1357 int size = list_length (chain);
1358
1359 if (!objc_method_template)
1360 objc_method_template = build_method_template ();
1361
1362 method_list_template = build_method_list_template (objc_method_template,
1363 size);
1364 initlist = build_dispatch_table_initializer (objc_method_template, chain);
1365
1366 decl = start_var_decl (method_list_template, name);
1367
1368 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1369 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1370 build_int_cst (integer_type_node, size));
1371 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1372
1373 OBJCMETA (decl, objc_meta, meta_base);
1374 finish_var_decl (decl,
1375 objc_build_constructor (TREE_TYPE (decl), v));
1376
1377 return decl;
1378 }
1379
1380 /* Init a category. */
1381 static tree
1382 build_category_initializer (tree type, tree cat_name, tree class_name,
1383 tree inst_methods, tree class_methods,
1384 tree protocol_list)
1385 {
1386 tree expr, ltyp;
1387 location_t loc;
1388 vec<constructor_elt, va_gc> *v = NULL;
1389
1390 /* TODO: pass the loc in or find it from args. */
1391 /* TODO: pass the loc in or find it from args. */
1392 loc = UNKNOWN_LOCATION;
1393 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1394 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1395
1396 ltyp = objc_method_list_ptr;
1397 if (inst_methods)
1398 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1399 else
1400 expr = convert (ltyp, null_pointer_node);
1401 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1402
1403 if (class_methods)
1404 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1405 else
1406 expr = convert (ltyp, null_pointer_node);
1407 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1408
1409 /* protocol_list = */
1410 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1411 if (protocol_list)
1412 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1413 else
1414 expr = convert (ltyp, null_pointer_node);
1415 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1416
1417 return objc_build_constructor (type, v);
1418 }
1419
1420 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1421
1422 static void
1423 generate_category (struct imp_entry *impent)
1424 {
1425 tree initlist, cat_name_expr, class_name_expr;
1426 tree protocol_decl, category, cat_decl;
1427 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1428 tree cat = impent->imp_context;
1429 char buf[BUFSIZE];
1430
1431 cat_decl = impent->class_decl;
1432
1433 add_class_reference (CLASS_NAME (cat));
1434 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1435
1436 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1437
1438 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1439
1440 if (category && CLASS_PROTOCOL_LIST (category))
1441 {
1442 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1443 protocol_decl = generate_protocol_list (category, cat);
1444 }
1445 else
1446 protocol_decl = 0;
1447
1448 if (CLASS_NST_METHODS (cat))
1449 {
1450 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1451 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1452 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1453 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf);
1454 }
1455
1456 if (CLASS_CLS_METHODS (cat))
1457 {
1458 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1459 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1460 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1461 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf);
1462 }
1463
1464 initlist = build_category_initializer (TREE_TYPE (cat_decl),
1465 cat_name_expr, class_name_expr,
1466 inst_methods, class_methods,
1467 protocol_decl);
1468 /* Finish and initialize the forward decl. */
1469 finish_var_decl (cat_decl, initlist);
1470 impent->class_decl = cat_decl;
1471 }
1472
1473 /* struct _objc_class {
1474 struct objc_class *isa;
1475 struct objc_class *super_class;
1476 char *name;
1477 long version;
1478 long info;
1479 long instance_size;
1480 struct objc_ivar_list *ivars;
1481 struct objc_method_list *methods;
1482 struct sarray *dtable;
1483 struct objc_class *subclass_list;
1484 struct objc_class *sibling_class;
1485 struct objc_protocol_list *protocols;
1486 void *gc_object_type;
1487 }; */
1488
1489 static tree
1490 build_shared_structure_initializer (tree type, tree isa, tree super,
1491 tree name, tree size, int status,
1492 tree dispatch_table, tree ivar_list,
1493 tree protocol_list)
1494 {
1495 tree expr, ltyp;
1496 vec<constructor_elt, va_gc> *v = NULL;
1497
1498 /* isa = */
1499 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1500
1501 /* super_class = */
1502 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1503
1504 /* name = */
1505 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1506
1507 /* version = */
1508 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1509 build_int_cst (long_integer_type_node, 0));
1510
1511 /* info = */
1512 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1513 build_int_cst (long_integer_type_node, status));
1514
1515 /* instance_size = */
1516 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1517 convert (long_integer_type_node, size));
1518
1519 /* objc_ivar_list = */
1520 if (!ivar_list)
1521 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1522 build_int_cst (objc_ivar_list_ptr, 0));
1523 else
1524 {
1525 expr = convert (objc_ivar_list_ptr,
1526 build_unary_op (input_location, ADDR_EXPR,
1527 ivar_list, 0));
1528 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1529 }
1530
1531 /* objc_method_list = */
1532 if (!dispatch_table)
1533 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1534 convert (objc_method_list_ptr, null_pointer_node));
1535 else
1536 {
1537 expr = convert (objc_method_list_ptr,
1538 build_unary_op (input_location, ADDR_EXPR,
1539 dispatch_table, 0));
1540 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1541 }
1542
1543 /* FIXME: Remove NeXT runtime code. */
1544 if (flag_next_runtime)
1545 {
1546 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
1547 get_identifier ("objc_cache")));
1548 /* method_cache = */
1549 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
1550 }
1551 else
1552 {
1553 /* dtable = */
1554 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1555
1556 /* subclass_list = */
1557 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1558
1559 /* sibling_class = */
1560 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1561 }
1562
1563 /* protocol_list = */
1564 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1565 if (! protocol_list)
1566 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (ltyp, 0));
1567 else
1568 {
1569 expr = convert (ltyp,
1570 build_unary_op (input_location, ADDR_EXPR,
1571 protocol_list, 0));
1572 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1573 }
1574
1575 /* FIXME: Remove NeXT runtime code. */
1576 if (flag_next_runtime)
1577 /* sel_id = NULL */
1578 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1579
1580 /* gc_object_type = NULL */
1581 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1582
1583 return objc_build_constructor (type, v);
1584 }
1585
1586
1587 static tree
1588 generate_ivars_list (tree chain, const char *name)
1589 {
1590 tree initlist, ivar_list_template, decl;
1591 int size;
1592 vec<constructor_elt, va_gc> *inits = NULL;
1593
1594 if (!chain)
1595 return NULL_TREE;
1596
1597 if (!objc_ivar_template)
1598 objc_ivar_template = build_ivar_template ();
1599
1600 size = ivar_list_length (chain);
1601
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;
1606
1607 decl = start_var_decl (ivar_list_template, name);
1608
1609 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1610 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1611
1612 OBJCMETA (decl, objc_meta, meta_base);
1613 finish_var_decl (decl,
1614 objc_build_constructor (TREE_TYPE (decl), inits));
1615
1616 return decl;
1617 }
1618
1619 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1620 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1621
1622 static void
1623 generate_class_structures (struct imp_entry *impent)
1624 {
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 ;
1633
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;*/
1640
1641 loc = DECL_SOURCE_LOCATION (impent->class_decl);
1642
1643 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
1644 if (my_super_id)
1645 {
1646 add_class_reference (my_super_id);
1647
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;
1652 do
1653 {
1654 tree my_root_int = lookup_interface (my_root_id);
1655
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;
1660 }
1661 while (1);
1662 }
1663 else
1664 /* No super class. */
1665 my_root_id = CLASS_NAME (impent->imp_template);
1666
1667 cast_type = build_pointer_type (objc_class_template);
1668 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
1669 class_names);
1670
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;
1676
1677 super_expr = build_c_cast (loc, cast_type, super_expr);
1678
1679 root_expr = add_objc_string (my_root_id, class_names);
1680 root_expr = build_c_cast (loc, cast_type, root_expr);
1681
1682 if (CLASS_PROTOCOL_LIST (impent->imp_template))
1683 {
1684 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
1685 protocol_decl = generate_protocol_list (impent->imp_template,
1686 impent->imp_context);
1687 }
1688 else
1689 protocol_decl = NULL_TREE;
1690
1691 if (CLASS_CLS_METHODS (impent->imp_context))
1692 {
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);
1697 }
1698
1699 if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
1700 && (chain = TYPE_FIELDS (objc_class_template)))
1701 {
1702 snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
1703 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1704 class_ivars = generate_ivars_list (chain, buf);
1705 }
1706
1707 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
1708
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);
1717
1718 finish_var_decl (meta_decl, initlist);
1719 impent->meta_decl = meta_decl;
1720
1721 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1722 if (CLASS_NST_METHODS (impent->imp_context))
1723 {
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);
1728 }
1729
1730 if ((chain = CLASS_IVARS (impent->imp_template)))
1731 {
1732 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
1733 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1734 inst_ivars = generate_ivars_list (chain, buf);
1735 }
1736
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);
1747
1748 finish_var_decl (class_decl, initlist);
1749 impent->class_decl = class_decl;
1750 }
1751
1752 /* --- Output GNU Metadata --- */
1753
1754 /* TODO: Make this into an array of refs. */
1755 static void
1756 handle_class_ref (tree chain)
1757 {
1758 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
1759 char *string = (char *) alloca (strlen (name) + 30);
1760 tree decl;
1761 tree exp;
1762
1763 sprintf (string, "__objc_class_name_%s", name);
1764
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);
1772
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;
1783
1784 /* We must force the reference. */
1785 DECL_PRESERVE_P (decl) = 1;
1786
1787 DECL_CONTEXT (decl) = NULL_TREE;
1788 finish_var_decl (decl, exp);
1789 }
1790
1791 static tree
1792 get_proto_encoding (tree proto)
1793 {
1794 tree encoding;
1795 if (proto)
1796 {
1797 if (! METHOD_ENCODING (proto))
1798 {
1799 encoding = encode_method_prototype (proto);
1800 METHOD_ENCODING (proto) = encoding;
1801 }
1802 else
1803 encoding = METHOD_ENCODING (proto);
1804
1805 return add_objc_string (encoding, meth_var_types);
1806 }
1807 else
1808 return build_int_cst (NULL_TREE, 0);
1809 }
1810
1811 static void
1812 build_gnu_selector_translation_table (void)
1813 {
1814 tree chain, expr;
1815 vec<constructor_elt, va_gc> *inits = NULL;
1816 vec<constructor_elt, va_gc> *v ;
1817
1818 /* Cause the selector table (previously forward-declared)
1819 to be actually output. */
1820
1821 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1822 {
1823 tree encoding;
1824 if (warn_selector)
1825 {
1826 /* TODO: improve on the location for the diagnostic. */
1827 location_t loc = input_location;
1828 diagnose_missing_method (TREE_VALUE (chain), loc);
1829 }
1830
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);
1837
1838 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1839 } /* each element in the chain */
1840
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);
1846
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);
1851 }
1852
1853 /* Output references to all statically allocated objects. Return the DECL
1854 for the array built. */
1855
1856 static void
1857 generate_static_references (void)
1858 {
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, va_gc> *decls = NULL;
1866
1867 /* FIXME: Remove NeXT runtime code. */
1868 if (flag_next_runtime)
1869 gcc_unreachable ();
1870
1871 for (cl_chain = objc_static_instances, num_class = 0;
1872 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1873 {
1874 vec<constructor_elt, va_gc> *v = NULL;
1875
1876 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1877 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1878
1879 snprintf (buf, BUFSIZE, "_OBJC_STATIC_INSTANCES_%d", num_class);
1880 decl = start_var_decl (type, buf);
1881
1882 /* Output {class_name, ...}. */
1883 klass = TREE_VALUE (cl_chain);
1884 class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
1885 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1886 build_unary_op (input_location,
1887 ADDR_EXPR, class_name, 1));
1888
1889 /* Output {..., instance, ...}. */
1890 for (in_chain = TREE_PURPOSE (cl_chain);
1891 in_chain; in_chain = TREE_CHAIN (in_chain))
1892 {
1893 expr = build_unary_op (input_location,
1894 ADDR_EXPR, TREE_VALUE (in_chain), 1);
1895 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1896 }
1897
1898 /* Output {..., NULL}. */
1899 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1900
1901 expr = objc_build_constructor (TREE_TYPE (decl), v);
1902 OBJCMETA (decl, objc_meta, meta_base);
1903 finish_var_decl (decl, expr);
1904 CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
1905 build_unary_op (input_location,
1906 ADDR_EXPR, decl, 1));
1907 }
1908
1909 CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
1910 expr = objc_build_constructor (type, decls);
1911 static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
1912 OBJCMETA (static_instances_decl, objc_meta, meta_base);
1913 finish_var_decl (static_instances_decl, expr);
1914 }
1915
1916 /* Create the initial value for the `defs' field of _objc_symtab.
1917 This is a CONSTRUCTOR. */
1918
1919 static tree
1920 init_def_list (tree type)
1921 {
1922 tree expr;
1923 struct imp_entry *impent;
1924 location_t loc;
1925 vec<constructor_elt, va_gc> *v = NULL;
1926
1927 if (imp_count)
1928 for (impent = imp_list; impent; impent = impent->next)
1929 {
1930 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1931 {
1932 loc = DECL_SOURCE_LOCATION (impent->class_decl);
1933 expr = build_unary_op (loc,
1934 ADDR_EXPR, impent->class_decl, 0);
1935 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1936 }
1937 }
1938
1939 if (cat_count)
1940 for (impent = imp_list; impent; impent = impent->next)
1941 {
1942 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1943 {
1944 loc = DECL_SOURCE_LOCATION (impent->class_decl);
1945 expr = build_unary_op (loc,
1946 ADDR_EXPR, impent->class_decl, 0);
1947 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1948 }
1949 }
1950
1951 loc = UNKNOWN_LOCATION;
1952 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1953 if (static_instances_decl)
1954 expr = build_unary_op (loc, ADDR_EXPR, static_instances_decl, 0);
1955 else
1956 expr = integer_zero_node;
1957 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1958
1959 return objc_build_constructor (type, v);
1960 }
1961
1962 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1963
1964 /* Predefine the following data type:
1965
1966 struct _objc_symtab
1967 {
1968 long sel_ref_cnt;
1969 SEL *refs;
1970 short cls_def_cnt;
1971 short cat_def_cnt;
1972 void *defs[cls_def_cnt + cat_def_cnt];
1973 }; */
1974
1975 static void
1976 build_objc_symtab_template (void)
1977 {
1978 tree fields, array_type, *chain = NULL;
1979 int index;
1980
1981 objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
1982
1983 /* long sel_ref_cnt; */
1984 fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
1985
1986 /* SEL *refs; */
1987 add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
1988
1989 /* short cls_def_cnt; */
1990 add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
1991
1992 /* short cat_def_cnt; */
1993 add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
1994
1995 /* Note that padding will be added here on LP64. */
1996
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);
2002
2003 objc_finish_struct (objc_symtab_template, fields);
2004 }
2005 /* Construct the initial value for all of _objc_symtab. */
2006
2007 static tree
2008 init_objc_symtab (tree type)
2009 {
2010 tree field, expr, ltyp;
2011 location_t loc;
2012 vec<constructor_elt, va_gc> *v = NULL;
2013
2014 loc = UNKNOWN_LOCATION;
2015
2016 /* sel_ref_cnt = { ..., 5, ... } */
2017
2018 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2019 build_int_cst (long_integer_type_node, 0));
2020
2021 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2022
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);
2030
2031 /* cls_def_cnt = { ..., 5, ... } */
2032
2033 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2034 build_int_cst (short_integer_type_node, imp_count));
2035
2036 /* cat_def_cnt = { ..., 5, ... } */
2037
2038 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2039 build_int_cst (short_integer_type_node, cat_count));
2040
2041 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2042
2043 field = TYPE_FIELDS (type);
2044 field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2045
2046 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2047
2048 return objc_build_constructor (type, v);
2049 }
2050
2051 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2052 and initialized appropriately. */
2053
2054 static void
2055 generate_objc_symtab_decl (void)
2056 {
2057 build_objc_symtab_template ();
2058 UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2059 OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_base);
2060 finish_var_decl (UOBJC_SYMBOLS_decl,
2061 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2062 }
2063
2064 static void
2065 objc_generate_v1_gnu_metadata (void)
2066 {
2067 struct imp_entry *impent;
2068 tree chain;
2069
2070 /* Process the static instances here because initialization of objc_symtab
2071 depends on them. */
2072 if (objc_static_instances)
2073 generate_static_references ();
2074
2075 objc_implementation_context =
2076 implementation_template =
2077 UOBJC_CLASS_decl =
2078 UOBJC_METACLASS_decl = NULL_TREE;
2079
2080 for (impent = imp_list; impent; impent = impent->next)
2081 {
2082 /* If -gen-decls is present, Dump the @interface of each class.
2083 TODO: Dump the classes in the order they were found, rather than in
2084 reverse order as we are doing now. */
2085 if (flag_gen_declaration)
2086 dump_interface (gen_declaration_file, impent->imp_context);
2087
2088 /* all of the following reference the string pool... */
2089 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2090 generate_class_structures (impent);
2091 else
2092 generate_category (impent);
2093 }
2094
2095 /* If we are using an array of selectors, we must always
2096 finish up the array decl even if no selectors were used. */
2097 build_gnu_selector_translation_table ();
2098
2099 if (protocol_chain)
2100 generate_protocols ();
2101
2102 /* Arrange for ObjC data structures to be initialized at run time. */
2103 /* FIXME: Have some more elegant way to determine if we need to
2104 generate objc_symtab_decl or not, instead of checking these
2105 global symbols. */
2106 if (imp_list || class_names_chain
2107 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain
2108 || prop_names_attr_chain)
2109 generate_objc_symtab_decl ();
2110
2111 if (imp_list || class_names_chain || objc_static_instances
2112 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
2113 {
2114 /* Make sure that the meta-data are identified as being
2115 GNU-runtime. */
2116 build_module_descriptor (OBJC_VERSION,
2117 build_tree_list (objc_meta, meta_base));
2118 build_module_initializer_routine ();
2119 }
2120
2121 /* Dump the class references. This forces the appropriate classes
2122 to be linked into the executable image, preserving unix archive
2123 semantics. This can be removed when we move to a more dynamically
2124 linked environment. */
2125
2126 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2127 {
2128 handle_class_ref (chain);
2129 if (TREE_PURPOSE (chain))
2130 generate_classref_translation_entry (chain);
2131 }
2132
2133 for (impent = imp_list; impent; impent = impent->next)
2134 handle_impent (impent);
2135
2136 generate_strings ();
2137 }
2138
2139 /* --- exceptions --- */
2140
2141 static GTY(()) tree objc_eh_personality_decl;
2142
2143 static tree
2144 objc_eh_runtime_type (tree type)
2145 {
2146 tree ident, eh_id, decl, str;
2147
2148 if (type == error_mark_node
2149 || errorcount || sorrycount)
2150 {
2151 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2152 to prevent an ICE. Note that we know that the compiler will
2153 terminate with an error and this 'ErrorMarkNode' class name will
2154 never be actually used. */
2155 ident = get_identifier ("ErrorMarkNode");
2156 goto make_err_class;
2157 }
2158
2159 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2160 /* We don't want to identify 'id' for GNU. Instead, build a 0
2161 entry in the exceptions table. */
2162 return null_pointer_node;
2163
2164 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2165 {
2166 #ifdef OBJCPLUS
2167 /* This routine is also called for c++ catch clauses; in which case,
2168 we use the c++ typeinfo decl. */
2169 return build_eh_type_type (type);
2170 #else
2171 error ("non-objective-c type %qT cannot be caught", type);
2172 ident = get_identifier ("ErrorMarkNode");
2173 goto make_err_class;
2174 #endif
2175 }
2176 else
2177 ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2178
2179 make_err_class:
2180 /* If this class was already referenced, then it will be output during
2181 meta-data emission, so we don't need to do it here. */
2182 decl = get_objc_string_decl (ident, class_names);
2183 eh_id = add_objc_string (ident, class_names);
2184 if (!decl)
2185 {
2186 /* Not found ... so we need to build it - from the freshly-entered id. */
2187 decl = get_objc_string_decl (ident, class_names);
2188 str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2189 IDENTIFIER_POINTER (ident));
2190 /* We have to finalize this var here, because this might be called after
2191 all the other metadata strings have been emitted. */
2192 finish_var_decl (decl, str);
2193 }
2194 return eh_id;
2195 }
2196
2197 static tree
2198 objc_eh_personality (void)
2199 {
2200 if (!objc_eh_personality_decl)
2201 #ifndef OBJCPLUS
2202 objc_eh_personality_decl = build_personality_function ("gnu_objc");
2203 #else
2204 objc_eh_personality_decl = build_personality_function ("gxx");
2205 #endif
2206 return objc_eh_personality_decl;
2207 }
2208
2209 /* -- interfaces --- */
2210
2211 static tree
2212 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2213 {
2214 tree t;
2215 vec<tree, va_gc> *parms;
2216 vec_alloc (parms, 1);
2217 /* A throw is just a call to the runtime throw function with the
2218 object as a parameter. */
2219 parms->quick_push (throw_expr);
2220 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms,
2221 NULL);
2222 vec_free (parms);
2223 return add_stmt (t);
2224 }
2225
2226 /* Build __builtin_eh_pointer. */
2227
2228 static tree
2229 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
2230 {
2231 tree t;
2232 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2233 t = build_call_expr (t, 1, integer_zero_node);
2234 return fold_convert (objc_object_type, t);
2235 }
2236
2237 static tree
2238 begin_catch (struct objc_try_context **cur_try_context, tree type,
2239 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2240 {
2241 tree t;
2242 /* Record the data for the catch in the try context so that we can
2243 finalize it later. */
2244 if (ellipsis)
2245 t = build_stmt (input_location, CATCH_EXPR, NULL, compound);
2246 else
2247 t = build_stmt (input_location, CATCH_EXPR, type, compound);
2248 (*cur_try_context)->current_catch = t;
2249
2250 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
2251 t = objc_build_exc_ptr (cur_try_context);
2252 t = convert (TREE_TYPE (decl), t);
2253 return build2 (MODIFY_EXPR, void_type_node, decl, t);
2254 }
2255
2256 static void
2257 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2258 {
2259 append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2260 }
2261
2262 static tree
2263 finish_try_stmt (struct objc_try_context **cur_try_context)
2264 {
2265 struct objc_try_context *c = *cur_try_context;
2266 tree stmt = c->try_body;
2267 if (c->catch_list)
2268 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2269 if (c->finally_body)
2270 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2271 return stmt;
2272 }
2273
2274 #include "gt-objc-objc-gnu-runtime-abi-01.h"