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