1 /* GNU Runtime ABI version 8
2 Copyright (C) 2011-2022 Free Software Foundation, Inc.
3 Contributed by Iain Sandoe (split from objc-act.cc)
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
objc_gnu_runtime_abi_01_init(objc_runtime_hooks * rthooks)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
gnu_runtime_01_initialize(void)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 /* 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, 0, 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, 0, 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, 0, 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, 0, 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 0, 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 ("objc_getPropertyStruct",
306 type, 0, 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 ("objc_setPropertyStruct",
314 type, 0, 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
329 static void
build_selector_template(void)330 build_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
361 static void
build_class_template(void)362 build_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
428 static void
build_category_template(void)429 build_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
462 static void
build_protocol_template(void)463 build_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
492 static void
build_selector_table_decl(void)493 build_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
507 static tree
gnu_runtime_abi_01_super_superclassfield_id(void)508 gnu_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
516 static tree
gnu_runtime_abi_01_class_decl(tree klass)517 gnu_runtime_abi_01_class_decl (tree klass)
518 {
519 tree decl;
520 char buf[BUFSIZE];
521 snprintf (buf, BUFSIZE, "_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
528 static tree
gnu_runtime_abi_01_metaclass_decl(tree klass)529 gnu_runtime_abi_01_metaclass_decl (tree klass)
530 {
531 tree decl;
532 char buf[BUFSIZE];
533 snprintf (buf, BUFSIZE, "_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
540 static tree
gnu_runtime_abi_01_category_decl(tree klass)541 gnu_runtime_abi_01_category_decl (tree klass)
542 {
543 tree decl;
544 char buf[BUFSIZE];
545 snprintf (buf, BUFSIZE, "_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
553 static tree
gnu_runtime_abi_01_protocol_decl(tree p)554 gnu_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 (buf, BUFSIZE, "_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
567 static tree
gnu_runtime_abi_01_string_decl(tree type,const char * name,string_section where ATTRIBUTE_UNUSED)568 gnu_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
578 static tree
gnu_runtime_abi_01_get_class_reference(tree ident)579 gnu_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
599 static void
gnu_runtime_abi_01_get_arg_type_list_base(vec<tree,va_gc> ** argtypes,tree meth,int context,int superflag ATTRIBUTE_UNUSED)600 gnu_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 (*argtypes, receiver_type);
612 /* Selector type - will eventually change to `int'. */
613 vec_safe_push (*argtypes, objc_selector_type);
614 }
615
616 /* Unused for GNU runtime. */
617 static tree
gnu_runtime_abi_01_receiver_is_class_object(tree a ATTRIBUTE_UNUSED)618 gnu_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
627 static tree
gnu_runtime_abi_01_build_typed_selector_reference(location_t loc,tree ident,tree prototype)628 gnu_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
668 static tree
build_objc_method_call(location_t loc,int super_flag,tree method_prototype,tree lookup_object,tree selector,tree method_params)669 build_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 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
704 lookup_object = save_expr (lookup_object);
705
706 /* Param list + 2 slots for object and selector. */
707 vec_alloc (parms, nparm + 2);
708 vec_alloc (tv, 2);
709
710 /* First, call the lookup function to get a pointer to the method,
711 then cast the pointer, then call it with the method arguments. */
712 tv->quick_push (lookup_object);
713 tv->quick_push (selector);
714 method = build_function_call_vec (loc, vNULL, sender, tv, NULL);
715 vec_free (tv);
716
717 /* Pass the appropriate object to the method. */
718 parms->quick_push ((super_flag ? self_decl : lookup_object));
719
720 /* Pass the selector to the method. */
721 parms->quick_push (selector);
722 /* Now append the remainder of the parms. */
723 if (nparm)
724 for (; method_params; method_params = TREE_CHAIN (method_params))
725 parms->quick_push (TREE_VALUE (method_params));
726
727 /* Build an obj_type_ref, with the correct cast for the method call. */
728 t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object,
729 build_int_cst (TREE_TYPE (lookup_object), 0));
730 t = build_function_call_vec (loc, vNULL, t, parms, NULL);
731 vec_free (parms);
732 return t;
733 }
734
735 static tree
gnu_runtime_abi_01_build_objc_method_call(location_t loc,tree method_prototype,tree receiver,tree rtype ATTRIBUTE_UNUSED,tree sel_name,tree method_params,int super ATTRIBUTE_UNUSED)736 gnu_runtime_abi_01_build_objc_method_call (location_t loc,
737 tree method_prototype,
738 tree receiver,
739 tree rtype ATTRIBUTE_UNUSED,
740 tree sel_name,
741 tree method_params,
742 int super ATTRIBUTE_UNUSED)
743 {
744 tree selector =
745 gnu_runtime_abi_01_build_typed_selector_reference (loc,
746 sel_name,
747 method_prototype);
748
749 return build_objc_method_call (loc, super, method_prototype, receiver,
750 selector, method_params);
751 }
752
753 static tree
gnu_runtime_abi_01_get_protocol_reference(location_t loc,tree p)754 gnu_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
755 {
756 tree expr, protocol_struct_type, *chain;
757 if (!PROTOCOL_FORWARD_DECL (p))
758 PROTOCOL_FORWARD_DECL (p) = gnu_runtime_abi_01_protocol_decl (p);
759
760 expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
761
762 /* ??? Ideally we'd build the reference with objc_protocol_type directly,
763 if we have it, rather than converting it here. */
764 expr = convert (objc_protocol_type, expr);
765
766 /* The @protocol() expression is being compiled into a pointer to a
767 statically allocated instance of the Protocol class. To become
768 usable at runtime, the 'isa' pointer of the instance need to be
769 fixed up at runtime by the runtime library, to point to the
770 actual 'Protocol' class. */
771
772 /* For the GNU runtime, put the static Protocol instance in the list
773 of statically allocated instances, so that we make sure that its
774 'isa' pointer is fixed up at runtime by the GNU runtime library
775 to point to the Protocol class (at runtime, when loading the
776 module, the GNU runtime library loops on the statically allocated
777 instances (as found in the defs field in objc_symtab) and fixups
778 all the 'isa' pointers of those objects). */
779
780 /* This type is a struct containing the fields of a Protocol
781 object. (Cfr. objc_protocol_type instead is the type of a pointer
782 to such a struct). */
783 protocol_struct_type = xref_tag (RECORD_TYPE,
784 get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
785
786 /* Look for the list of Protocol statically allocated instances
787 to fixup at runtime. Create a new list to hold Protocol
788 statically allocated instances, if the list is not found. At
789 present there is only another list, holding NSConstantString
790 static instances to be fixed up at runtime. */
791
792 for (chain = &objc_static_instances;
793 *chain && TREE_VALUE (*chain) != protocol_struct_type;
794 chain = &TREE_CHAIN (*chain));
795
796 if (!*chain)
797 {
798 *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
799 add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
800 class_names);
801 }
802
803 /* Add this statically allocated instance to the Protocol list. */
804 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
805 PROTOCOL_FORWARD_DECL (p),
806 TREE_PURPOSE (*chain));
807 return expr;
808 }
809
810 /* For ABI 8 an IVAR is just a fixed offset in the class struct. */
811
812 static tree
gnu_runtime_abi_01_build_ivar_ref(location_t loc ATTRIBUTE_UNUSED,tree base,tree id)813 gnu_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
814 tree base, tree id)
815 {
816 return objc_build_component_ref (base, id);
817 }
818
819 /* We build super class references as we need them (but keep them once
820 built for the sake of efficiency). */
821
822 static tree
gnu_runtime_abi_01_get_class_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)823 gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
824 struct imp_entry *imp, bool inst_meth)
825 {
826 if (inst_meth)
827 {
828 if (!ucls_super_ref)
829 ucls_super_ref =
830 objc_build_component_ref (imp->class_decl,
831 get_identifier ("super_class"));
832 return ucls_super_ref;
833 }
834 else
835 {
836 if (!uucls_super_ref)
837 uucls_super_ref =
838 objc_build_component_ref (imp->meta_decl,
839 get_identifier ("super_class"));
840 return uucls_super_ref;
841 }
842 }
843
844 static tree
gnu_runtime_abi_01_get_category_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)845 gnu_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
846 struct imp_entry *imp, bool inst_meth)
847 {
848 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
849 tree super_class;
850
851 add_class_reference (super_name);
852 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
853 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
854 IDENTIFIER_POINTER (super_name));
855 /* super_class = get_{meta_}class("CLASS_SUPER_NAME"); */
856 return build_function_call (input_location,
857 super_class,
858 build_tree_list (NULL_TREE, super_name));
859 }
860
861 static bool
gnu_runtime_abi_01_setup_const_string_class_decl(void)862 gnu_runtime_abi_01_setup_const_string_class_decl (void)
863 {
864 /* Do nothing, and create no error. */
865 return true;
866 }
867
868 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
869
870 static GTY(()) int num_static_inst;
871
872 static tree
objc_add_static_instance(tree constructor,tree class_decl)873 objc_add_static_instance (tree constructor, tree class_decl)
874 {
875 tree *chain, decl;
876 char buf[BUFSIZE];
877
878 /* Find the list of static instances for the CLASS_DECL. Create one if
879 not found. */
880 for (chain = &objc_static_instances;
881 *chain && TREE_VALUE (*chain) != class_decl;
882 chain = &TREE_CHAIN (*chain));
883 if (!*chain)
884 {
885 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
886 add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
887 }
888
889 snprintf (buf, BUFSIZE, "_OBJC_INSTANCE_%d", num_static_inst++);
890 decl = build_decl (input_location,
891 VAR_DECL, get_identifier (buf), class_decl);
892 TREE_STATIC (decl) = 1;
893 DECL_ARTIFICIAL (decl) = 1;
894 TREE_USED (decl) = 1;
895 DECL_INITIAL (decl) = constructor;
896 DECL_CONTEXT (decl) = NULL;
897 OBJCMETA (decl, objc_meta, meta_base);
898
899 /* We may be writing something else just now.
900 Postpone till end of input. */
901 DECL_DEFER_OUTPUT (decl) = 1;
902 lang_hooks.decls.pushdecl (decl);
903 rest_of_decl_compilation (decl, 1, 0);
904
905 /* Add the DECL to the head of this CLASS' list. */
906 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
907
908 return decl;
909 }
910
911 static tree
gnu_runtime_abi_01_build_const_string_constructor(location_t loc,tree string,int length)912 gnu_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
913 int length)
914 {
915 tree constructor, fields;
916 vec<constructor_elt, va_gc> *v = NULL;
917
918 /* GNU: (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length }) */
919 fields = TYPE_FIELDS (internal_const_str_type);
920 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, 0));
921
922 fields = DECL_CHAIN (fields);
923 CONSTRUCTOR_APPEND_ELT (v, fields, build_unary_op (loc,
924 ADDR_EXPR, string, 1));
925
926 fields = DECL_CHAIN (fields);
927 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
928 constructor = objc_build_constructor (internal_const_str_type, v);
929
930 constructor = objc_add_static_instance (constructor, constant_string_type);
931 return constructor;
932 }
933
934 /* --- metadata - module initializer --- */
935
936 /* The GNU runtime requires us to provide a static initializer function
937 for each module:
938
939 static void __objc_gnu_init (void) {
940 __objc_exec_class (&L_OBJC_MODULES);
941 } */
942
943
944 static void
build_module_initializer_routine(void)945 build_module_initializer_routine (void)
946 {
947 tree body;
948
949 #ifdef OBJCPLUS
950 push_lang_context (lang_name_c); /* extern "C" */
951 #endif
952
953 objc_push_parm (build_decl (input_location,
954 PARM_DECL, NULL_TREE, void_type_node));
955 #ifdef OBJCPLUS
956 objc_start_function (get_identifier (TAG_GNUINIT),
957 build_function_type_list (void_type_node, NULL_TREE),
958 NULL_TREE, NULL_TREE);
959 #else
960 objc_start_function (get_identifier (TAG_GNUINIT),
961 build_function_type_list (void_type_node, NULL_TREE),
962 NULL_TREE, objc_get_parm_info (0, NULL_TREE));
963 #endif
964 body = c_begin_compound_stmt (true);
965 add_stmt (build_function_call
966 (input_location,
967 execclass_decl,
968 build_tree_list
969 (NULL_TREE,
970 build_unary_op (input_location, ADDR_EXPR,
971 UOBJC_MODULES_decl, 0))));
972 add_stmt (c_end_compound_stmt (input_location, body, true));
973
974 TREE_PUBLIC (current_function_decl) = 0;
975
976 #ifndef OBJCPLUS
977 /* For Objective-C++, we will need to call __objc_gnu_init
978 from objc_generate_static_init_call() below. */
979 DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
980 #endif
981
982 GNU_INIT_decl = current_function_decl;
983 finish_function ();
984
985 #ifdef OBJCPLUS
986 pop_lang_context ();
987 #endif
988 }
989
990 #ifdef OBJCPLUS
991 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
992 to be called by the module initializer routine. */
993
994 int
objc_static_init_needed_p(void)995 objc_static_init_needed_p (void)
996 {
997 return (GNU_INIT_decl != NULL_TREE);
998 }
999
1000 /* Generate a call to the __objc_gnu_init initializer function. */
1001
1002 tree
objc_generate_static_init_call(tree ctors ATTRIBUTE_UNUSED)1003 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
1004 {
1005 add_stmt (build_stmt (input_location, EXPR_STMT,
1006 build_function_call (input_location,
1007 GNU_INIT_decl, NULL_TREE)));
1008
1009 return ctors;
1010 }
1011 #endif /* OBJCPLUS */
1012
1013 /* --- Output GNU Meta-data --- */
1014
1015 static void
generate_classref_translation_entry(tree chain)1016 generate_classref_translation_entry (tree chain)
1017 {
1018 tree expr, decl, type;
1019
1020 decl = TREE_PURPOSE (chain);
1021 type = TREE_TYPE (decl);
1022
1023 expr = add_objc_string (TREE_VALUE (chain), class_names);
1024 expr = convert (type, expr); /* cast! */
1025
1026 /* This is a class reference. It is re-written by the runtime,
1027 but will be optimized away unless we force it. */
1028 DECL_PRESERVE_P (decl) = 1;
1029 OBJCMETA (decl, objc_meta, meta_base);
1030 finish_var_decl (decl, expr);
1031 return;
1032 }
1033
1034
1035 static void
handle_impent(struct imp_entry * impent)1036 handle_impent (struct imp_entry *impent)
1037 {
1038 char *string;
1039
1040 /* objc_implementation_context = impent->imp_context;
1041 implementation_template = impent->imp_template;*/
1042
1043 switch (TREE_CODE (impent->imp_context))
1044 {
1045 case CLASS_IMPLEMENTATION_TYPE:
1046 {
1047 const char *const class_name =
1048 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1049
1050 string = (char *) alloca (strlen (class_name) + 30);
1051
1052 sprintf (string, "__objc_class_name_%s", class_name);
1053 break;
1054 }
1055 case CATEGORY_IMPLEMENTATION_TYPE:
1056 {
1057 const char *const class_name =
1058 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1059 const char *const class_super_name =
1060 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
1061
1062 string = (char *) alloca (strlen (class_name)
1063 + strlen (class_super_name) + 30);
1064
1065 /* Do the same for categories. Even though no references to
1066 these symbols are generated automatically by the compiler,
1067 it gives you a handle to pull them into an archive by
1068 hand. */
1069 sprintf (string, "*__objc_category_name_%s_%s", class_name, class_super_name);
1070 break;
1071 }
1072 default:
1073 return;
1074 }
1075
1076 {
1077 tree decl, init;
1078
1079 init = integer_zero_node;
1080 decl = build_decl (input_location,
1081 VAR_DECL, get_identifier (string), TREE_TYPE (init));
1082 TREE_PUBLIC (decl) = 1;
1083 TREE_READONLY (decl) = 1;
1084 TREE_USED (decl) = 1;
1085 TREE_CONSTANT (decl) = 1;
1086 DECL_CONTEXT (decl) = NULL_TREE;
1087 DECL_ARTIFICIAL (decl) = 1;
1088 TREE_STATIC (decl) = 1;
1089 DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
1090 /* We must force the reference. */
1091 DECL_PRESERVE_P (decl) = 1;
1092
1093 finish_var_decl(decl, init) ;
1094 }
1095 }
1096
1097 tree
build_protocol_initializer(tree type,tree protocol_name,tree protocol_list,tree inst_methods,tree class_methods)1098 build_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1099 tree inst_methods, tree class_methods)
1100 {
1101 tree expr, ttyp;
1102 location_t loc;
1103 vec<constructor_elt, va_gc> *inits = NULL;
1104
1105 /* TODO: pass the loc in or find it from args. */
1106 loc = input_location;
1107 ttyp = build_pointer_type (xref_tag (RECORD_TYPE,
1108 get_identifier (UTAG_CLASS)));
1109 /* Filling the "isa" in with a version allows the runtime system to
1110 detect this ... */
1111 expr = build_int_cst (ttyp, PROTOCOL_VERSION);
1112
1113 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1114
1115 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1116 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1117
1118 ttyp = objc_method_proto_list_ptr;
1119 if (inst_methods)
1120 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1121 else
1122 expr = convert (ttyp, null_pointer_node);
1123 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1124
1125 if (class_methods)
1126 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1127 else
1128 expr = convert (ttyp, null_pointer_node);
1129 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1130
1131 return objc_build_constructor (type, inits);
1132 }
1133
1134 static tree
generate_protocol_list(tree i_or_p,tree klass_ctxt)1135 generate_protocol_list (tree i_or_p, tree klass_ctxt)
1136 {
1137 tree array_type, ptype, refs_decl, lproto, e, plist;
1138 vec<constructor_elt, va_gc> *v = NULL;
1139 char buf[BUFSIZE];
1140 int size = 0;
1141
1142 switch (TREE_CODE (i_or_p))
1143 {
1144 case CLASS_INTERFACE_TYPE:
1145 case CATEGORY_INTERFACE_TYPE:
1146 plist = CLASS_PROTOCOL_LIST (i_or_p);
1147 break;
1148 case PROTOCOL_INTERFACE_TYPE:
1149 plist = PROTOCOL_LIST (i_or_p);
1150 break;
1151 default:
1152 gcc_unreachable ();
1153 }
1154
1155 /* Compute size. */
1156 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1157 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1158 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1159 size++;
1160
1161 /* Build initializer. */
1162 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1163 e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1164 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1165
1166 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1167 {
1168 tree pval = TREE_VALUE (lproto);
1169
1170 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1171 && PROTOCOL_FORWARD_DECL (pval))
1172 {
1173 tree fwref = PROTOCOL_FORWARD_DECL (pval);
1174 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1175 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1176 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1177 }
1178 }
1179
1180 /* static struct objc_protocol *refs[n]; */
1181
1182 switch (TREE_CODE (i_or_p))
1183 {
1184 case PROTOCOL_INTERFACE_TYPE:
1185 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1186 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1187 break;
1188 case CLASS_INTERFACE_TYPE:
1189 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1190 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1191 break;
1192 case CATEGORY_INTERFACE_TYPE:
1193 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1194 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1195 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1196 break;
1197 default:
1198 gcc_unreachable ();
1199 }
1200
1201 ptype = build_pointer_type (objc_protocol_template);
1202 array_type = build_sized_array_type (ptype, size + 3);
1203 refs_decl = start_var_decl (array_type, buf);
1204 OBJCMETA (refs_decl, objc_meta, meta_base);
1205 finish_var_decl (refs_decl,
1206 objc_build_constructor (TREE_TYPE (refs_decl), v));
1207
1208 return refs_decl;
1209 }
1210
1211 static tree
generate_v1_meth_descriptor_table(tree chain,tree protocol,const char * prefix)1212 generate_v1_meth_descriptor_table (tree chain, tree protocol, const char *prefix)
1213 {
1214 tree method_list_template, initlist, decl;
1215 int size;
1216 vec<constructor_elt, va_gc> *v = NULL;
1217 char buf[BUFSIZE];
1218
1219 if (!chain || !prefix)
1220 return NULL_TREE;
1221
1222 if (!objc_method_prototype_template)
1223 objc_method_prototype_template = build_method_prototype_template ();
1224
1225 size = list_length (chain);
1226 method_list_template =
1227 build_method_prototype_list_template (objc_method_prototype_template,
1228 size);
1229 snprintf (buf, BUFSIZE, "%s_%s", prefix,
1230 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1231
1232 decl = start_var_decl (method_list_template, buf);
1233
1234 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1235 initlist =
1236 build_descriptor_table_initializer (objc_method_prototype_template,
1237 chain);
1238 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1239 OBJCMETA (decl, objc_meta, meta_base);
1240 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1241 return decl;
1242 }
1243
1244 /* For each protocol which was referenced either from a @protocol()
1245 expression, or because a class/category implements it (then a
1246 pointer to the protocol is stored in the struct describing the
1247 class/category), we create a statically allocated instance of the
1248 Protocol class. The code is written in such a way as to generate
1249 as few Protocol objects as possible; we generate a unique Protocol
1250 instance for each protocol, and we don't generate a Protocol
1251 instance if the protocol is never referenced (either from a
1252 @protocol() or from a class/category implementation). These
1253 statically allocated objects can be referred to via the static
1254 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1255
1256 The statically allocated Protocol objects that we generate here
1257 need to be fixed up at runtime in order to be used: the 'isa'
1258 pointer of the objects need to be set up to point to the 'Protocol'
1259 class, as known at runtime.
1260
1261 The GNU runtime fixes up all protocols before user code from the module
1262 is executed; it requires pointers to those symbols
1263 to be put in the objc_symtab (which is then passed as argument to
1264 the function __objc_exec_class() which the compiler sets up to be
1265 executed automatically when the module is loaded); setup of those
1266 Protocol objects happen in two ways in the GNU runtime: all
1267 Protocol objects referred to by a class or category implementation
1268 are fixed up when the class/category is loaded; all Protocol
1269 objects referred to by a @protocol() expression are added by the
1270 compiler to the list of statically allocated instances to fixup
1271 (the same list holding the statically allocated constant string
1272 objects). Because, as explained above, the compiler generates as
1273 few Protocol objects as possible, some Protocol object might end up
1274 being referenced multiple times when compiled with the GNU runtime,
1275 and end up being fixed up multiple times at runtime initialization.
1276 But that doesn't hurt, it's just a little inefficient. */
1277
1278 static void
generate_protocols(void)1279 generate_protocols (void)
1280 {
1281 tree p, encoding;
1282 tree decl;
1283 tree initlist, protocol_name_expr, refs_decl, refs_expr;
1284
1285 /* If a protocol was directly referenced, pull in indirect references. */
1286 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1287 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1288 generate_protocol_references (PROTOCOL_LIST (p));
1289
1290 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1291 {
1292 tree nst_methods = PROTOCOL_NST_METHODS (p);
1293 tree cls_methods = PROTOCOL_CLS_METHODS (p);
1294
1295 /* If protocol wasn't referenced, don't generate any code. */
1296 decl = PROTOCOL_FORWARD_DECL (p);
1297
1298 if (!decl)
1299 continue;
1300
1301 /* Make sure we link in the Protocol class. */
1302 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1303
1304 while (nst_methods)
1305 {
1306 if (! METHOD_ENCODING (nst_methods))
1307 {
1308 encoding = encode_method_prototype (nst_methods);
1309 METHOD_ENCODING (nst_methods) = encoding;
1310 }
1311 nst_methods = DECL_CHAIN (nst_methods);
1312 }
1313
1314 UOBJC_INSTANCE_METHODS_decl =
1315 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1316 "_OBJC_PROTOCOL_INSTANCE_METHODS");
1317
1318 while (cls_methods)
1319 {
1320 if (! METHOD_ENCODING (cls_methods))
1321 {
1322 encoding = encode_method_prototype (cls_methods);
1323 METHOD_ENCODING (cls_methods) = encoding;
1324 }
1325
1326 cls_methods = DECL_CHAIN (cls_methods);
1327 }
1328
1329 UOBJC_CLASS_METHODS_decl =
1330 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1331 "_OBJC_PROTOCOL_CLASS_METHODS");
1332 /* generate_method_descriptors (p);*/
1333
1334 if (PROTOCOL_LIST (p))
1335 refs_decl = generate_protocol_list (p, NULL_TREE);
1336 else
1337 refs_decl = 0;
1338
1339 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1340 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1341
1342 if (refs_decl)
1343 refs_expr = convert (build_pointer_type (build_pointer_type
1344 (objc_protocol_template)),
1345 build_unary_op (input_location,
1346 ADDR_EXPR, refs_decl, 0));
1347 else
1348 refs_expr = build_int_cst (NULL_TREE, 0);
1349
1350 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
1351 by generate_method_descriptors, which is called above. */
1352 initlist = build_protocol_initializer (TREE_TYPE (decl),
1353 protocol_name_expr, refs_expr,
1354 UOBJC_INSTANCE_METHODS_decl,
1355 UOBJC_CLASS_METHODS_decl);
1356 finish_var_decl (decl, initlist);
1357 }
1358 }
1359
1360 static tree
generate_dispatch_table(tree chain,const char * name)1361 generate_dispatch_table (tree chain, const char *name)
1362 {
1363 tree decl, method_list_template, initlist;
1364 vec<constructor_elt, va_gc> *v = NULL;
1365 int size = list_length (chain);
1366
1367 if (!objc_method_template)
1368 objc_method_template = build_method_template ();
1369
1370 method_list_template = build_method_list_template (objc_method_template,
1371 size);
1372 initlist = build_dispatch_table_initializer (objc_method_template, chain);
1373
1374 decl = start_var_decl (method_list_template, name);
1375
1376 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1377 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1378 build_int_cst (integer_type_node, size));
1379 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1380
1381 OBJCMETA (decl, objc_meta, meta_base);
1382 finish_var_decl (decl,
1383 objc_build_constructor (TREE_TYPE (decl), v));
1384
1385 return decl;
1386 }
1387
1388 /* Init a category. */
1389 static tree
build_category_initializer(tree type,tree cat_name,tree class_name,tree inst_methods,tree class_methods,tree protocol_list)1390 build_category_initializer (tree type, tree cat_name, tree class_name,
1391 tree inst_methods, tree class_methods,
1392 tree protocol_list)
1393 {
1394 tree expr, ltyp;
1395 location_t loc;
1396 vec<constructor_elt, va_gc> *v = NULL;
1397
1398 /* TODO: pass the loc in or find it from args. */
1399 /* TODO: pass the loc in or find it from args. */
1400 loc = UNKNOWN_LOCATION;
1401 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1402 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1403
1404 ltyp = objc_method_list_ptr;
1405 if (inst_methods)
1406 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1407 else
1408 expr = convert (ltyp, null_pointer_node);
1409 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1410
1411 if (class_methods)
1412 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1413 else
1414 expr = convert (ltyp, null_pointer_node);
1415 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1416
1417 /* protocol_list = */
1418 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1419 if (protocol_list)
1420 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1421 else
1422 expr = convert (ltyp, null_pointer_node);
1423 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1424
1425 return objc_build_constructor (type, v);
1426 }
1427
1428 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1429
1430 static void
generate_category(struct imp_entry * impent)1431 generate_category (struct imp_entry *impent)
1432 {
1433 tree initlist, cat_name_expr, class_name_expr;
1434 tree protocol_decl, category, cat_decl;
1435 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1436 tree cat = impent->imp_context;
1437 char buf[BUFSIZE];
1438
1439 cat_decl = impent->class_decl;
1440
1441 add_class_reference (CLASS_NAME (cat));
1442 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1443
1444 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1445
1446 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1447
1448 if (category && CLASS_PROTOCOL_LIST (category))
1449 {
1450 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1451 protocol_decl = generate_protocol_list (category, cat);
1452 }
1453 else
1454 protocol_decl = 0;
1455
1456 if (CLASS_NST_METHODS (cat))
1457 {
1458 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1459 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1460 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1461 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf);
1462 }
1463
1464 if (CLASS_CLS_METHODS (cat))
1465 {
1466 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1467 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1468 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1469 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf);
1470 }
1471
1472 initlist = build_category_initializer (TREE_TYPE (cat_decl),
1473 cat_name_expr, class_name_expr,
1474 inst_methods, class_methods,
1475 protocol_decl);
1476 /* Finish and initialize the forward decl. */
1477 finish_var_decl (cat_decl, initlist);
1478 impent->class_decl = cat_decl;
1479 }
1480
1481 /* struct _objc_class {
1482 struct objc_class *isa;
1483 struct objc_class *super_class;
1484 char *name;
1485 long version;
1486 long info;
1487 long instance_size;
1488 struct objc_ivar_list *ivars;
1489 struct objc_method_list *methods;
1490 struct sarray *dtable;
1491 struct objc_class *subclass_list;
1492 struct objc_class *sibling_class;
1493 struct objc_protocol_list *protocols;
1494 void *gc_object_type;
1495 }; */
1496
1497 static tree
build_shared_structure_initializer(tree type,tree isa,tree super,tree name,tree size,int status,tree dispatch_table,tree ivar_list,tree protocol_list)1498 build_shared_structure_initializer (tree type, tree isa, tree super,
1499 tree name, tree size, int status,
1500 tree dispatch_table, tree ivar_list,
1501 tree protocol_list)
1502 {
1503 tree expr, ltyp;
1504 vec<constructor_elt, va_gc> *v = NULL;
1505
1506 /* isa = */
1507 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1508
1509 /* super_class = */
1510 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1511
1512 /* name = */
1513 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1514
1515 /* version = */
1516 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1517 build_int_cst (long_integer_type_node, 0));
1518
1519 /* info = */
1520 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1521 build_int_cst (long_integer_type_node, status));
1522
1523 /* instance_size = */
1524 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1525 convert (long_integer_type_node, size));
1526
1527 /* objc_ivar_list = */
1528 if (!ivar_list)
1529 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1530 build_int_cst (objc_ivar_list_ptr, 0));
1531 else
1532 {
1533 expr = convert (objc_ivar_list_ptr,
1534 build_unary_op (input_location, ADDR_EXPR,
1535 ivar_list, 0));
1536 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1537 }
1538
1539 /* objc_method_list = */
1540 if (!dispatch_table)
1541 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1542 convert (objc_method_list_ptr, null_pointer_node));
1543 else
1544 {
1545 expr = convert (objc_method_list_ptr,
1546 build_unary_op (input_location, ADDR_EXPR,
1547 dispatch_table, 0));
1548 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1549 }
1550
1551 /* dtable = */
1552 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1553
1554 /* subclass_list = */
1555 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1556
1557 /* sibling_class = */
1558 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1559
1560 /* protocol_list = */
1561 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1562 if (! protocol_list)
1563 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (ltyp, 0));
1564 else
1565 {
1566 expr = convert (ltyp,
1567 build_unary_op (input_location, ADDR_EXPR,
1568 protocol_list, 0));
1569 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1570 }
1571
1572 /* gc_object_type = NULL */
1573 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1574
1575 return objc_build_constructor (type, v);
1576 }
1577
1578
1579 static tree
generate_ivars_list(tree chain,const char * name)1580 generate_ivars_list (tree chain, const char *name)
1581 {
1582 tree initlist, ivar_list_template, decl;
1583 int size;
1584 vec<constructor_elt, va_gc> *inits = NULL;
1585
1586 if (!chain)
1587 return NULL_TREE;
1588
1589 if (!objc_ivar_template)
1590 objc_ivar_template = build_ivar_template ();
1591
1592 size = ivar_list_length (chain);
1593
1594 generating_instance_variables = 1;
1595 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1596 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1597 generating_instance_variables = 0;
1598
1599 decl = start_var_decl (ivar_list_template, name);
1600
1601 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1602 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1603
1604 OBJCMETA (decl, objc_meta, meta_base);
1605 finish_var_decl (decl,
1606 objc_build_constructor (TREE_TYPE (decl), inits));
1607
1608 return decl;
1609 }
1610
1611 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1612 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1613
1614 static void
generate_class_structures(struct imp_entry * impent)1615 generate_class_structures (struct imp_entry *impent)
1616 {
1617 tree name_expr, super_expr, root_expr, class_decl, meta_decl;
1618 tree my_root_id, my_super_id;
1619 tree cast_type, initlist, protocol_decl;
1620 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1621 tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
1622 location_t loc;
1623 char buf[BUFSIZE];
1624 int cls_flags = 0 ;
1625
1626 /* objc_implementation_context = impent->imp_context;
1627 implementation_template = impent->imp_template;*/
1628 class_decl = impent->class_decl;
1629 meta_decl = impent->meta_decl;
1630 /* UOBJC_CLASS_decl = impent->class_decl;
1631 UOBJC_METACLASS_decl = impent->meta_decl;*/
1632
1633 loc = DECL_SOURCE_LOCATION (impent->class_decl);
1634
1635 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
1636 if (my_super_id)
1637 {
1638 add_class_reference (my_super_id);
1639
1640 /* Compute "my_root_id" - this is required for code generation.
1641 the "isa" for all meta class structures points to the root of
1642 the inheritance hierarchy (e.g. "__Object")... */
1643 my_root_id = my_super_id;
1644 do
1645 {
1646 tree my_root_int = lookup_interface (my_root_id);
1647
1648 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
1649 my_root_id = CLASS_SUPER_NAME (my_root_int);
1650 else
1651 break;
1652 }
1653 while (1);
1654 }
1655 else
1656 /* No super class. */
1657 my_root_id = CLASS_NAME (impent->imp_template);
1658
1659 cast_type = build_pointer_type (objc_class_template);
1660 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
1661 class_names);
1662
1663 /* Install class `isa' and `super' pointers at runtime. */
1664 if (my_super_id)
1665 super_expr = add_objc_string (my_super_id, class_names);
1666 else
1667 super_expr = null_pointer_node;
1668
1669 super_expr = build_c_cast (loc, cast_type, super_expr);
1670
1671 root_expr = add_objc_string (my_root_id, class_names);
1672 root_expr = build_c_cast (loc, cast_type, root_expr);
1673
1674 if (CLASS_PROTOCOL_LIST (impent->imp_template))
1675 {
1676 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
1677 protocol_decl = generate_protocol_list (impent->imp_template,
1678 impent->imp_context);
1679 }
1680 else
1681 protocol_decl = NULL_TREE;
1682
1683 if (CLASS_CLS_METHODS (impent->imp_context))
1684 {
1685 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
1686 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1687 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
1688 buf);
1689 }
1690
1691 if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
1692 && (chain = TYPE_FIELDS (objc_class_template)))
1693 {
1694 snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
1695 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1696 class_ivars = generate_ivars_list (chain, buf);
1697 }
1698
1699 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
1700
1701 initlist =
1702 build_shared_structure_initializer
1703 (TREE_TYPE (meta_decl),
1704 root_expr, super_expr, name_expr,
1705 convert (integer_type_node,
1706 TYPE_SIZE_UNIT (objc_class_template)),
1707 CLS_META, class_methods, class_ivars,
1708 protocol_decl);
1709
1710 finish_var_decl (meta_decl, initlist);
1711 impent->meta_decl = meta_decl;
1712
1713 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1714 if (CLASS_NST_METHODS (impent->imp_context))
1715 {
1716 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
1717 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1718 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
1719 buf);
1720 }
1721
1722 if ((chain = CLASS_IVARS (impent->imp_template)))
1723 {
1724 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
1725 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1726 inst_ivars = generate_ivars_list (chain, buf);
1727 }
1728
1729 initlist =
1730 build_shared_structure_initializer
1731 (TREE_TYPE (class_decl),
1732 build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
1733 super_expr, name_expr,
1734 convert (integer_type_node,
1735 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
1736 (impent->imp_template))),
1737 CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
1738 protocol_decl);
1739
1740 finish_var_decl (class_decl, initlist);
1741 impent->class_decl = class_decl;
1742 }
1743
1744 /* --- Output GNU Metadata --- */
1745
1746 /* TODO: Make this into an array of refs. */
1747 static void
handle_class_ref(tree chain)1748 handle_class_ref (tree chain)
1749 {
1750 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
1751 char *string = (char *) alloca (strlen (name) + 30);
1752 tree decl;
1753 tree exp;
1754
1755 sprintf (string, "__objc_class_name_%s", name);
1756
1757 /* Make a decl for this name, so we can use its address in a tree. */
1758 decl = build_decl (input_location,
1759 VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
1760 DECL_EXTERNAL (decl) = 1;
1761 TREE_PUBLIC (decl) = 1;
1762 DECL_CONTEXT (decl) = NULL_TREE;
1763 finish_var_decl (decl, 0);
1764
1765 /* Make a decl for the address. */
1766 sprintf (string, "__objc_class_ref_%s", name);
1767 exp = build1 (ADDR_EXPR, string_type_node, decl);
1768 decl = build_decl (input_location,
1769 VAR_DECL, get_identifier (string), string_type_node);
1770 TREE_STATIC (decl) = 1;
1771 TREE_USED (decl) = 1;
1772 DECL_READ_P (decl) = 1;
1773 DECL_ARTIFICIAL (decl) = 1;
1774 DECL_INITIAL (decl) = error_mark_node;
1775
1776 /* We must force the reference. */
1777 DECL_PRESERVE_P (decl) = 1;
1778
1779 DECL_CONTEXT (decl) = NULL_TREE;
1780 finish_var_decl (decl, exp);
1781 }
1782
1783 static tree
get_proto_encoding(tree proto)1784 get_proto_encoding (tree proto)
1785 {
1786 tree encoding;
1787 if (proto)
1788 {
1789 if (! METHOD_ENCODING (proto))
1790 {
1791 encoding = encode_method_prototype (proto);
1792 METHOD_ENCODING (proto) = encoding;
1793 }
1794 else
1795 encoding = METHOD_ENCODING (proto);
1796
1797 return add_objc_string (encoding, meth_var_types);
1798 }
1799 else
1800 return build_int_cst (NULL_TREE, 0);
1801 }
1802
1803 static void
build_gnu_selector_translation_table(void)1804 build_gnu_selector_translation_table (void)
1805 {
1806 tree chain, expr;
1807 vec<constructor_elt, va_gc> *inits = NULL;
1808 vec<constructor_elt, va_gc> *v ;
1809
1810 /* Cause the selector table (previously forward-declared)
1811 to be actually output. */
1812
1813 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1814 {
1815 tree encoding;
1816 if (warn_selector)
1817 {
1818 /* TODO: improve on the location for the diagnostic. */
1819 location_t loc = input_location;
1820 diagnose_missing_method (TREE_VALUE (chain), loc);
1821 }
1822
1823 v = NULL;
1824 expr = build_selector (TREE_VALUE (chain));
1825 encoding = get_proto_encoding (TREE_PURPOSE (chain));
1826 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1827 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, encoding);
1828 expr = objc_build_constructor (objc_selector_template, v);
1829
1830 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1831 } /* each element in the chain */
1832
1833 /* List terminator. */
1834 v = NULL;
1835 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1836 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1837 expr = objc_build_constructor (objc_selector_template, v);
1838
1839 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1840 expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
1841 inits);
1842 finish_var_decl (UOBJC_SELECTOR_TABLE_decl, expr);
1843 }
1844
1845 /* Output references to all statically allocated objects. Return the DECL
1846 for the array built. */
1847
1848 static void
generate_static_references(void)1849 generate_static_references (void)
1850 {
1851 tree expr = NULL_TREE;
1852 tree class_name, klass, decl;
1853 tree cl_chain, in_chain, type
1854 = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
1855 int num_inst, num_class;
1856 char buf[BUFSIZE];
1857 vec<constructor_elt, va_gc> *decls = NULL;
1858
1859 for (cl_chain = objc_static_instances, num_class = 0;
1860 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1861 {
1862 vec<constructor_elt, va_gc> *v = NULL;
1863
1864 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1865 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1866
1867 snprintf (buf, BUFSIZE, "_OBJC_STATIC_INSTANCES_%d", num_class);
1868 decl = start_var_decl (type, buf);
1869
1870 /* Output {class_name, ...}. */
1871 klass = TREE_VALUE (cl_chain);
1872 class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
1873 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1874 build_unary_op (input_location,
1875 ADDR_EXPR, class_name, 1));
1876
1877 /* Output {..., instance, ...}. */
1878 for (in_chain = TREE_PURPOSE (cl_chain);
1879 in_chain; in_chain = TREE_CHAIN (in_chain))
1880 {
1881 expr = build_unary_op (input_location,
1882 ADDR_EXPR, TREE_VALUE (in_chain), 1);
1883 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1884 }
1885
1886 /* Output {..., NULL}. */
1887 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1888
1889 expr = objc_build_constructor (TREE_TYPE (decl), v);
1890 OBJCMETA (decl, objc_meta, meta_base);
1891 finish_var_decl (decl, expr);
1892 CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
1893 build_unary_op (input_location,
1894 ADDR_EXPR, decl, 1));
1895 }
1896
1897 CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
1898 expr = objc_build_constructor (type, decls);
1899 static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
1900 OBJCMETA (static_instances_decl, objc_meta, meta_base);
1901 finish_var_decl (static_instances_decl, expr);
1902 }
1903
1904 /* Create the initial value for the `defs' field of _objc_symtab.
1905 This is a CONSTRUCTOR. */
1906
1907 static tree
init_def_list(tree type)1908 init_def_list (tree type)
1909 {
1910 tree expr;
1911 struct imp_entry *impent;
1912 location_t loc;
1913 vec<constructor_elt, va_gc> *v = NULL;
1914
1915 if (imp_count)
1916 for (impent = imp_list; impent; impent = impent->next)
1917 {
1918 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1919 {
1920 loc = DECL_SOURCE_LOCATION (impent->class_decl);
1921 expr = build_unary_op (loc,
1922 ADDR_EXPR, impent->class_decl, 0);
1923 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1924 }
1925 }
1926
1927 if (cat_count)
1928 for (impent = imp_list; impent; impent = impent->next)
1929 {
1930 if (TREE_CODE (impent->imp_context) == CATEGORY_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 loc = UNKNOWN_LOCATION;
1940 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1941 if (static_instances_decl)
1942 expr = build_unary_op (loc, ADDR_EXPR, static_instances_decl, 0);
1943 else
1944 expr = integer_zero_node;
1945 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1946
1947 return objc_build_constructor (type, v);
1948 }
1949
1950 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1951
1952 /* Predefine the following data type:
1953
1954 struct _objc_symtab
1955 {
1956 long sel_ref_cnt;
1957 SEL *refs;
1958 short cls_def_cnt;
1959 short cat_def_cnt;
1960 void *defs[cls_def_cnt + cat_def_cnt];
1961 }; */
1962
1963 static void
build_objc_symtab_template(void)1964 build_objc_symtab_template (void)
1965 {
1966 tree fields, array_type, *chain = NULL;
1967 int index;
1968
1969 objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
1970
1971 /* long sel_ref_cnt; */
1972 fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
1973
1974 /* SEL *refs; */
1975 add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
1976
1977 /* short cls_def_cnt; */
1978 add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
1979
1980 /* short cat_def_cnt; */
1981 add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
1982
1983 /* Note that padding will be added here on LP64. */
1984
1985 /* void *defs[imp_count + cat_count (+ 1)]; */
1986 /* NB: The index is one less than the size of the array. */
1987 index = imp_count + cat_count;
1988 array_type = build_sized_array_type (ptr_type_node, index + 1);
1989 add_field_decl (array_type, "defs", &chain);
1990
1991 objc_finish_struct (objc_symtab_template, fields);
1992 }
1993 /* Construct the initial value for all of _objc_symtab. */
1994
1995 static tree
init_objc_symtab(tree type)1996 init_objc_symtab (tree type)
1997 {
1998 tree field, expr, ltyp;
1999 location_t loc;
2000 vec<constructor_elt, va_gc> *v = NULL;
2001
2002 loc = UNKNOWN_LOCATION;
2003
2004 /* sel_ref_cnt = { ..., 5, ... } */
2005
2006 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2007 build_int_cst (long_integer_type_node, 0));
2008
2009 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2010
2011 ltyp = build_pointer_type (objc_selector_type);
2012 if (sel_ref_chain)
2013 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR,
2014 UOBJC_SELECTOR_TABLE_decl, 1));
2015 else
2016 expr = convert (ltyp, null_pointer_node);
2017 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2018
2019 /* cls_def_cnt = { ..., 5, ... } */
2020
2021 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2022 build_int_cst (short_integer_type_node, imp_count));
2023
2024 /* cat_def_cnt = { ..., 5, ... } */
2025
2026 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2027 build_int_cst (short_integer_type_node, cat_count));
2028
2029 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2030
2031 field = TYPE_FIELDS (type);
2032 field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2033
2034 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2035
2036 return objc_build_constructor (type, v);
2037 }
2038
2039 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2040 and initialized appropriately. */
2041
2042 static void
generate_objc_symtab_decl(void)2043 generate_objc_symtab_decl (void)
2044 {
2045 build_objc_symtab_template ();
2046 UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2047 OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_base);
2048 finish_var_decl (UOBJC_SYMBOLS_decl,
2049 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2050 }
2051
2052 static void
objc_generate_v1_gnu_metadata(void)2053 objc_generate_v1_gnu_metadata (void)
2054 {
2055 struct imp_entry *impent;
2056 tree chain;
2057
2058 /* Process the static instances here because initialization of objc_symtab
2059 depends on them. */
2060 if (objc_static_instances)
2061 generate_static_references ();
2062
2063 objc_implementation_context =
2064 implementation_template =
2065 UOBJC_CLASS_decl =
2066 UOBJC_METACLASS_decl = NULL_TREE;
2067
2068 for (impent = imp_list; impent; impent = impent->next)
2069 {
2070 /* If -gen-decls is present, Dump the @interface of each class.
2071 TODO: Dump the classes in the order they were found, rather than in
2072 reverse order as we are doing now. */
2073 if (flag_gen_declaration)
2074 dump_interface (gen_declaration_file, impent->imp_context);
2075
2076 /* all of the following reference the string pool... */
2077 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2078 generate_class_structures (impent);
2079 else
2080 generate_category (impent);
2081 }
2082
2083 /* If we are using an array of selectors, we must always
2084 finish up the array decl even if no selectors were used. */
2085 build_gnu_selector_translation_table ();
2086
2087 if (protocol_chain)
2088 generate_protocols ();
2089
2090 /* Arrange for ObjC data structures to be initialized at run time. */
2091 /* FIXME: Have some more elegant way to determine if we need to
2092 generate objc_symtab_decl or not, instead of checking these
2093 global symbols. */
2094 if (imp_list || class_names_chain
2095 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain
2096 || prop_names_attr_chain)
2097 generate_objc_symtab_decl ();
2098
2099 if (imp_list || class_names_chain || objc_static_instances
2100 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
2101 {
2102 /* Make sure that the meta-data are identified as being
2103 GNU-runtime. */
2104 build_module_descriptor (OBJC_VERSION,
2105 build_tree_list (objc_meta, meta_base));
2106 build_module_initializer_routine ();
2107 }
2108
2109 /* Dump the class references. This forces the appropriate classes
2110 to be linked into the executable image, preserving unix archive
2111 semantics. This can be removed when we move to a more dynamically
2112 linked environment. */
2113
2114 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2115 {
2116 handle_class_ref (chain);
2117 if (TREE_PURPOSE (chain))
2118 generate_classref_translation_entry (chain);
2119 }
2120
2121 for (impent = imp_list; impent; impent = impent->next)
2122 handle_impent (impent);
2123
2124 generate_strings ();
2125 }
2126
2127 /* --- exceptions --- */
2128
2129 static GTY(()) tree objc_eh_personality_decl;
2130
2131 static tree
objc_eh_runtime_type(tree type)2132 objc_eh_runtime_type (tree type)
2133 {
2134 tree ident, eh_id, decl, str;
2135
2136 if (type == error_mark_node
2137 || errorcount || sorrycount)
2138 {
2139 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2140 to prevent an ICE. Note that we know that the compiler will
2141 terminate with an error and this 'ErrorMarkNode' class name will
2142 never be actually used. */
2143 ident = get_identifier ("ErrorMarkNode");
2144 goto make_err_class;
2145 }
2146
2147 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2148 /* We don't want to identify 'id' for GNU. Instead, build a 0
2149 entry in the exceptions table. */
2150 return null_pointer_node;
2151
2152 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2153 {
2154 #ifdef OBJCPLUS
2155 /* This routine is also called for c++ catch clauses; in which case,
2156 we use the c++ typeinfo decl. */
2157 return build_eh_type_type (type);
2158 #else
2159 error ("non-objective-c type %qT cannot be caught", type);
2160 ident = get_identifier ("ErrorMarkNode");
2161 goto make_err_class;
2162 #endif
2163 }
2164 else
2165 ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2166
2167 make_err_class:
2168 /* If this class was already referenced, then it will be output during
2169 meta-data emission, so we don't need to do it here. */
2170 decl = get_objc_string_decl (ident, class_names);
2171 eh_id = add_objc_string (ident, class_names);
2172 if (!decl)
2173 {
2174 /* Not found ... so we need to build it - from the freshly-entered id. */
2175 decl = get_objc_string_decl (ident, class_names);
2176 str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2177 IDENTIFIER_POINTER (ident));
2178 /* We have to finalize this var here, because this might be called after
2179 all the other metadata strings have been emitted. */
2180 finish_var_decl (decl, str);
2181 }
2182 return eh_id;
2183 }
2184
2185 static tree
objc_eh_personality(void)2186 objc_eh_personality (void)
2187 {
2188 if (!objc_eh_personality_decl)
2189 #ifndef OBJCPLUS
2190 objc_eh_personality_decl = build_personality_function ("gnu_objc");
2191 #else
2192 objc_eh_personality_decl = build_personality_function ("gxx");
2193 #endif
2194 return objc_eh_personality_decl;
2195 }
2196
2197 /* -- interfaces --- */
2198
2199 static tree
build_throw_stmt(location_t loc,tree throw_expr,bool rethrown ATTRIBUTE_UNUSED)2200 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2201 {
2202 tree t;
2203 vec<tree, va_gc> *parms;
2204 vec_alloc (parms, 1);
2205 /* A throw is just a call to the runtime throw function with the
2206 object as a parameter. */
2207 parms->quick_push (throw_expr);
2208 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms,
2209 NULL);
2210 vec_free (parms);
2211 return add_stmt (t);
2212 }
2213
2214 /* Build __builtin_eh_pointer. */
2215
2216 static tree
objc_build_exc_ptr(struct objc_try_context ** x ATTRIBUTE_UNUSED)2217 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
2218 {
2219 tree t;
2220 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2221 t = build_call_expr (t, 1, integer_zero_node);
2222 return fold_convert (objc_object_type, t);
2223 }
2224
2225 static tree
begin_catch(struct objc_try_context ** cur_try_context,tree type,tree decl,tree compound,bool ellipsis ATTRIBUTE_UNUSED)2226 begin_catch (struct objc_try_context **cur_try_context, tree type,
2227 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2228 {
2229 tree t;
2230 /* Record the data for the catch in the try context so that we can
2231 finalize it later. */
2232 if (ellipsis)
2233 t = build_stmt (input_location, CATCH_EXPR, NULL, compound);
2234 else
2235 t = build_stmt (input_location, CATCH_EXPR, type, compound);
2236 (*cur_try_context)->current_catch = t;
2237
2238 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
2239 t = objc_build_exc_ptr (cur_try_context);
2240 t = convert (TREE_TYPE (decl), t);
2241 return build2 (MODIFY_EXPR, void_type_node, decl, t);
2242 }
2243
2244 static void
finish_catch(struct objc_try_context ** cur_try_context,tree current_catch)2245 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2246 {
2247 append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2248 }
2249
2250 static tree
finish_try_stmt(struct objc_try_context ** cur_try_context)2251 finish_try_stmt (struct objc_try_context **cur_try_context)
2252 {
2253 struct objc_try_context *c = *cur_try_context;
2254 tree stmt = c->try_body;
2255 if (c->catch_list)
2256 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2257 if (c->finally_body)
2258 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2259 return stmt;
2260 }
2261
2262 #include "gt-objc-objc-gnu-runtime-abi-01.h"
2263