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

source code of gcc/objc/objc-gnu-runtime-abi-01.cc