1 /* Next Runtime (ABI-2) private.
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 Contributed by Iain Sandoe and based, in part, on an implementation in
5 'branches/apple/trunk' contributed by Apple Computer Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23 /* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
24
25 This version is intended to match (logically) the output of Apple's
26 4.2.1 compiler. */
27
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "tree.h"
33
34 #ifdef OBJCPLUS
35 #include "cp-tree.h"
36 #else
37 #include "c-tree.h"
38 #include "c-lang.h"
39 #endif
40 #include "langhooks.h"
41 #include "c-family/c-objc.h"
42 #include "objc-act.h"
43
44 /* When building Objective-C++, we are not linking against the C front-end
45 and so need to replicate the C tree-construction functions in some way. */
46 #ifdef OBJCPLUS
47 #define OBJCP_REMAP_FUNCTIONS
48 #include "objcp-decl.h"
49 #endif /* OBJCPLUS */
50
51 #include "ggc.h"
52 #include "target.h"
53 #include "tree-iterator.h"
54
55 #include "objc-runtime-hooks.h"
56 #include "objc-runtime-shared-support.h"
57 #include "objc-encoding.h"
58
59 /* ABI 2 Private definitions. */
60 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
61
62 #define TAG_GETCLASS "objc_getClass"
63 #define TAG_GETMETACLASS "objc_getMetaClass"
64
65 #define TAG_MSGSEND "objc_msgSend"
66 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
67 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
68 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
69
70 #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
71 #define TAG_V2_EH_TYPE "objc_ehtype_t"
72
73 #define UTAG_V2_CLASS "_class_t"
74 #define UTAG_V2_CLASS_RO "_class_ro_t"
75 #define UTAG_V2_PROTOCOL "_protocol_t"
76 #define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
77
78 #define UTAG_V2_EH_TYPE "_objc_ehtype_t"
79
80 #define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
81
82 enum objc_v2_tree_index
83 {
84 /* Templates. */
85 OCTI_V2_CLS_TEMPL,
86 OCTI_V2_CAT_TEMPL,
87 OCTI_V2_CLS_RO_TEMPL,
88 OCTI_V2_PROTO_TEMPL,
89 OCTI_V2_IVAR_TEMPL,
90 OCTI_V2_IVAR_LIST_TEMPL,
91 OCTI_V2_MESSAGE_REF_TEMPL,
92 OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
93
94 OCTI_V2_MESSAGE_SELECTOR_TYPE,
95 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
96 OCTI_V2_IMP_TYPE,
97 OCTI_V2_SUPER_IMP_TYPE,
98
99 OCTI_V2_CACHE_DECL,
100 OCTI_V2_VTABLE_DECL,
101
102 OCTI_V2_PROPERTY_TEMPL,
103
104 /* V2 messaging. */
105 OCTI_V2_UMSG_FIXUP_DECL,
106 OCTI_V2_UMSG_STRET_FIXUP_DECL,
107 OCTI_V2_UMSG_ID_FIXUP_DECL,
108 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
109 OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
110 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
111
112 /* Exceptions - related. */
113 OCTI_V2_BEGIN_CATCH_DECL,
114 OCTI_V2_END_CATCH_DECL,
115 OCTI_V2_RETHROW_DECL,
116
117 OCTI_V2_MAX
118 };
119
120 #define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
121 #define objc_v2_class_ro_template \
122 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
123 #define objc_v2_category_template \
124 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
125 #define objc_v2_protocol_template \
126 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
127
128 /* struct message_ref_t */
129 #define objc_v2_message_ref_template \
130 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
131
132 #define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
133
134 /* struct super_message_ref_t */
135 #define objc_v2_super_message_ref_template \
136 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
137
138 /* struct message_ref_t* */
139 #define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
140 /* struct super_super_message_ref_t */
141 #define objc_v2_super_selector_type \
142 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
143 #define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
144 #define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
145
146 #define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
147 #define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
148
149 #define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
150 #define objc_v2_property_template \
151 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
152
153 /* V2 Messaging */
154
155 /* objc_msgSend_fixup_rtp */
156 #define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
157 /* objc_msgSend_stret_fixup_rtp */
158 #define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
159 /* objc_msgSendId_fixup_rtp */
160 #define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
161 /* objc_msgSendId_stret_fixup_rtp */
162 #define umsg_id_stret_fixup_decl \
163 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
164 /* objc_msgSendSuper2_fixup_rtp */
165 #define umsg_id_super2_fixup_decl \
166 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
167 /* objc_msgSendSuper2_stret_fixup_rtp */
168 #define umsg_id_super2_stret_fixup_decl \
169 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
170
171 #define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
172 #define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
173 #define objc_rethrow_exception_decl \
174 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
175
176 /* rt_trees identifiers - shared between NeXT implementations. These allow
177 the FE to tag meta-data in a manner that survives LTO and can be used when
178 the runtime requires that certain meta-data items appear in particular
179 named sections. */
180
181 #include "objc-next-metadata-tags.h"
182 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
183
184 /* The OCTI_V2_... enumeration itself is in above. */
185 static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
186
187 static void next_runtime_02_initialize (void);
188
189 static void build_v2_message_ref_templates (void);
190 static void build_v2_class_templates (void);
191 static void build_v2_super_template (void);
192 static void build_v2_category_template (void);
193 static void build_v2_protocol_template (void);
194
195 static tree next_runtime_abi_02_super_superclassfield_id (void);
196
197 static tree next_runtime_abi_02_class_decl (tree);
198 static tree next_runtime_abi_02_metaclass_decl (tree);
199 static tree next_runtime_abi_02_category_decl (tree);
200 static tree next_runtime_abi_02_protocol_decl (tree);
201 static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
202
203 static tree next_runtime_abi_02_get_class_reference (tree);
204 static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
205 static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
206 static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
207 static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
208 static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
209
210 static tree next_runtime_abi_02_receiver_is_class_object (tree);
211 static void next_runtime_abi_02_get_arg_type_list_base (VEC(tree,gc) **, tree,
212 int, int);
213 static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
214 tree, tree, tree, int);
215 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
216 static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
217
218 static tree create_extern_decl (tree, const char *);
219
220 static void objc_generate_v2_next_metadata (void);
221 static bool objc2_objc_exception_attr (tree);
222
223 /* void build_v2_protocol_reference (tree);*/
224 static void build_v2_ehtype_template (void);
225 static void build_v2_eh_catch_objects (void);
226 static tree next_runtime_02_eh_type (tree);
227 static tree objc_eh_personality (void);
228 static tree build_throw_stmt (location_t, tree, bool);
229 static tree objc_build_exc_ptr (struct objc_try_context **);
230 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
231 static void finish_catch (struct objc_try_context **, tree);
232 static tree finish_try_stmt (struct objc_try_context **);
233
234 /* TODO: Use an objc-map. */
235 static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
236
237 bool
objc_next_runtime_abi_02_init(objc_runtime_hooks * rthooks)238 objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
239 {
240 extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
241
242 if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
243 {
244 inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for "
245 "%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
246 flag_objc_sjlj_exceptions = 0;
247 }
248
249 rthooks->initialize = next_runtime_02_initialize;
250 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
251 rthooks->tag_getclass = TAG_GETCLASS;
252 rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
253
254 rthooks->class_decl = next_runtime_abi_02_class_decl;
255 rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
256 rthooks->category_decl = next_runtime_abi_02_category_decl;
257 rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
258 rthooks->string_decl = next_runtime_abi_02_string_decl;
259
260 rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
261 rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
262 rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
263 rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
264 rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
265 rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
266
267 rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
268 rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
269 rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
270
271 rthooks->setup_const_string_class_decl =
272 next_runtime_abi_02_setup_const_string_class_decl;
273 rthooks->build_const_string_constructor =
274 next_runtime_abi_02_build_const_string_constructor;
275
276 rthooks->build_throw_stmt = build_throw_stmt;
277 rthooks->build_exc_ptr = objc_build_exc_ptr;
278 rthooks->begin_catch = begin_catch;
279 rthooks->finish_catch = finish_catch;
280 rthooks->finish_try_stmt = finish_try_stmt;
281
282 rthooks->generate_metadata = objc_generate_v2_next_metadata;
283 return true;
284 }
285
286 /* We need a way to convey what kind of meta-data are represented by a given
287 variable, since each type is expected (by the runtime) to be found in a
288 specific named section. The solution must be usable with LTO.
289
290 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
291 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
292 identification attributes in the front end. The back-end may choose to act
293 on these as it requires. */
294
295 static void
next_runtime_abi_02_init_metadata_attributes(void)296 next_runtime_abi_02_init_metadata_attributes (void)
297 {
298 if (!objc_meta)
299 objc_meta = get_identifier ("OBJC2META");
300
301 if (!meta_base)
302 meta_base = get_identifier ("V2_BASE");
303
304 meta_class = get_identifier ("G2_CLAS");
305 meta_metaclass = get_identifier ("G2_META");
306 meta_category =
307 meta_protocol = meta_base;
308
309 meta_clac_vars =
310 meta_clai_vars = meta_base;
311
312 meta_clac_meth =
313 meta_clai_meth =
314 meta_catc_meth =
315 meta_cati_meth =
316 meta_proto_cls_meth =
317 meta_proto_nst_meth = meta_base;
318
319 meta_clas_prot =
320 meta_catg_prot = meta_base;
321
322 meta_sel_refs = get_identifier ("V2_SRFS");
323
324 meta_class_name =
325 meta_meth_name =
326 meta_meth_type =
327 meta_prop_name_attr = get_identifier ("V2_STRG");
328
329 meta_mref = get_identifier ("V2_MREF");
330 meta_class_ref = get_identifier ("V2_CLRF");
331 meta_superclass_ref = get_identifier ("V2_SURF");
332
333 meta_label_classlist = get_identifier ("V2_CLAB");
334 meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
335 meta_label_categorylist = get_identifier ("V2_CALA");
336 meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
337
338 meta_label_protocollist = get_identifier ("V2_PLST");
339 meta_proto_ref = get_identifier ("V2_PRFS");
340
341 meta_info = get_identifier ("V2_INFO");
342
343 meta_ehtype = get_identifier ("V2_EHTY");
344
345 meta_const_str = get_identifier ("V2_CSTR");
346 }
347
next_runtime_02_initialize(void)348 static void next_runtime_02_initialize (void)
349 {
350 tree type;
351 #ifdef OBJCPLUS
352 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
353 default. */
354 if (!global_options_set.x_flag_objc_call_cxx_cdtors)
355 global_options.x_flag_objc_call_cxx_cdtors = 1;
356 #endif
357
358 /* Set up attributes to be attached to the meta-data so that they
359 will be placed in the correct sections. */
360 next_runtime_abi_02_init_metadata_attributes ();
361
362 /* `struct objc_selector *' */
363 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
364 get_identifier (TAG_SELECTOR)));
365
366 /* IMP : id (*) (id, _message_ref_t*, ...)
367 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
368 objc_v2_selector_type. */
369 build_v2_message_ref_templates ();
370
371 objc_v2_ivar_list_ptr =
372 build_pointer_type (xref_tag (RECORD_TYPE,
373 get_identifier ("_ivar_list_t")));
374
375 objc_prop_list_ptr =
376 build_pointer_type (xref_tag (RECORD_TYPE,
377 get_identifier ("_prop_list_t")));
378
379 build_v2_class_templates ();
380 build_v2_super_template ();
381 build_v2_protocol_template ();
382 build_v2_category_template ();
383
384 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
385 type = build_varargs_function_type_list (objc_object_type,
386 objc_object_type,
387 objc_v2_selector_type,
388 NULL_TREE);
389 umsg_fixup_decl = add_builtin_function ("objc_msgSend_fixup",
390 type, 0, NOT_BUILT_IN,
391 NULL, NULL_TREE);
392 TREE_NOTHROW (umsg_fixup_decl) = 0;
393
394 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
395 umsg_stret_fixup_decl = add_builtin_function ("objc_msgSend_stret_fixup",
396 type, 0, NOT_BUILT_IN,
397 NULL, NULL_TREE);
398 TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
399
400 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
401 umsg_id_fixup_decl = add_builtin_function ("objc_msgSendId_fixup",
402 type, 0, NOT_BUILT_IN,
403 NULL, NULL_TREE);
404 TREE_NOTHROW (umsg_id_fixup_decl) = 0;
405
406 /* id objc_msgSendId_stret_fixup_rtp
407 (id, struct message_ref_t*, ...); */
408 umsg_id_stret_fixup_decl = add_builtin_function ("objc_msgSendId_stret_fixup",
409 type, 0, NOT_BUILT_IN,
410 NULL, NULL_TREE);
411 TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
412
413 /* id objc_msgSendSuper2_fixup_rtp
414 (struct objc_super *, struct message_ref_t*, ...); */
415 type = build_varargs_function_type_list (objc_object_type,
416 objc_super_type,
417 objc_v2_super_selector_type,
418 NULL_TREE);
419 umsg_id_super2_fixup_decl = add_builtin_function ("objc_msgSendSuper2_fixup",
420 type, 0, NOT_BUILT_IN,
421 NULL, NULL_TREE);
422 TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
423
424 /* id objc_msgSendSuper2_stret_fixup_rtp
425 (struct objc_super *, struct message_ref_t*, ...); */
426 umsg_id_super2_stret_fixup_decl =
427 add_builtin_function ("objc_msgSendSuper2_stret_fixup",
428 type, 0, NOT_BUILT_IN,
429 NULL, NULL_TREE);
430 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
431
432 /* Present in the library, but unused by the FE. */
433 /* Protocol *objc_getProtocol (const char *)
434 type = build_function_type_list (objc_protocol_type,
435 const_string_type_node,
436 NULL_TREE);
437 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
438 type, 0, NOT_BUILT_IN,
439 NULL, NULL_TREE);
440 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
441
442 UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
443 "_objc_empty_cache");
444
445 UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
446 "_objc_empty_vtable");
447
448 /* id objc_getClass (const char *); */
449 type = build_function_type_list (objc_object_type,
450 const_string_type_node,
451 NULL_TREE);
452 objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
453 type, 0, NOT_BUILT_IN,
454 NULL, NULL_TREE);
455
456 /* id objc_getMetaClass (const char *); */
457 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
458 type, 0, NOT_BUILT_IN,
459 NULL, NULL_TREE);
460
461 /* This is the type of all of the following functions
462 objc_copyStruct(). */
463 type = build_function_type_list (void_type_node,
464 ptr_type_node,
465 const_ptr_type_node,
466 ptrdiff_type_node,
467 boolean_type_node,
468 boolean_type_node,
469 NULL_TREE);
470 /* Declare the following function:
471 void
472 objc_copyStruct (void *destination, const void *source,
473 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
474 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
475 type, 0, NOT_BUILT_IN,
476 NULL, NULL_TREE);
477 TREE_NOTHROW (objc_copyStruct_decl) = 0;
478 objc_getPropertyStruct_decl = NULL_TREE;
479 objc_setPropertyStruct_decl = NULL_TREE;
480
481 gcc_assert (!flag_objc_sjlj_exceptions);
482
483 /* Although we warn that fobjc-exceptions is required for exceptions
484 code, we carry on and create it anyway. */
485
486 /* This can be required, even when exceptions code is not present,
487 when an __attribute__((objc_exception)) is applied to a
488 class. */
489 build_v2_ehtype_template ();
490
491 /* void * objc_begin_catch (void *) */
492 type = build_function_type_list (ptr_type_node,
493 ptr_type_node, NULL_TREE);
494
495 objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
496 type, 0, NOT_BUILT_IN,
497 NULL, NULL_TREE);
498 TREE_NOTHROW (objc2_begin_catch_decl) = 0;
499
500 /* void objc_end_catch () */
501 type = build_function_type_list (void_type_node, NULL_TREE);
502 objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
503 type, 0, NOT_BUILT_IN,
504 NULL, NULL_TREE);
505 TREE_NOTHROW (objc2_end_catch_decl) = 0;
506
507 /* void objc_exception_rethrow (void) */
508 objc_rethrow_exception_decl =
509 add_builtin_function ("objc_exception_rethrow",
510 type, 0, NOT_BUILT_IN,
511 NULL, NULL_TREE);
512 TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
513 using_eh_for_cleanups ();
514 lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
515 lang_hooks.eh_personality = objc_eh_personality;
516 }
517
518 /* NOTE --- templates --- */
519
520 /* Set 'objc_v2_message_ref_template' to the data type node for
521 'struct _message_ref_t'. This needs to be done just once per
522 compilation. Also Set 'objc_v2_super_message_ref_template' to data
523 type node for 'struct _super_message_ref_t'. */
524
525 /* struct _message_ref_t
526 {
527 IMP messenger;
528 SEL name;
529 };
530 where IMP is: id (*) (id, _message_ref_t*, ...)
531 */
532
533 /* struct _super_message_ref_t
534 {
535 SUPER_IMP messenger;
536 SEL name;
537 };
538 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
539 */
540
541 static void
build_v2_message_ref_templates(void)542 build_v2_message_ref_templates (void)
543 {
544 tree ptr_message_ref_t;
545 tree decls, *chain = NULL;
546
547 /* struct _message_ref_t {...} */
548 objc_v2_message_ref_template =
549 objc_start_struct (get_identifier ("_message_ref_t"));
550
551 /* IMP messenger; */
552 ptr_message_ref_t =
553 build_pointer_type (xref_tag (RECORD_TYPE,
554 get_identifier ("_message_ref_t")));
555
556 objc_v2_imp_type =
557 build_pointer_type (build_function_type_list
558 (objc_object_type,
559 objc_object_type,
560 ptr_message_ref_t,
561 NULL_TREE));
562
563 decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
564
565 /* SEL name; */
566 add_field_decl (objc_selector_type, "name", &chain);
567
568 objc_finish_struct (objc_v2_message_ref_template, decls);
569
570 objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
571
572 chain = NULL;
573 /* struct _super_message_ref_t {...} */
574 objc_v2_super_message_ref_template =
575 objc_start_struct (get_identifier ("_super_message_ref_t"));
576
577 /* SUPER_IMP messenger; */
578 ptr_message_ref_t = build_pointer_type
579 (xref_tag (RECORD_TYPE,
580 get_identifier ("_super_message_ref_t")));
581
582 objc_v2_super_imp_type =
583 build_pointer_type (build_function_type_list
584 (objc_object_type,
585 objc_super_type,
586 ptr_message_ref_t,
587 NULL_TREE));
588
589 add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
590
591 /* SEL name; */
592 add_field_decl (objc_selector_type, "name", &chain);
593
594 objc_finish_struct (objc_v2_super_message_ref_template, decls);
595 objc_v2_super_selector_type =
596 build_pointer_type (objc_v2_super_message_ref_template);
597 }
598
599 /* Build following types which represent each class implementation.
600
601 struct class_ro_t
602 {
603 uint32_t const flags;
604 uint32_t const instanceStart;
605 uint32_t const instanceSize;
606 #ifdef __LP64__
607 uint32_t const reserved;
608 #endif
609 const uint8_t * const ivarLayout;
610 const char *const name;
611 const struct method_list_t * const baseMethods;
612 const struct objc_protocol_list *const baseProtocols;
613 const struct ivar_list_t *const ivars;
614 const uint8_t * const weakIvarLayout;
615 const struct _prop_list_t * const properties;
616 };
617
618 struct class_t
619 {
620 struct class_t *isa;
621 struct class_t *superclass;
622 void *cache;
623 IMP *vtable;
624
625 ...When this is active - it will point to a rw version, but
626 when we build the meta-data we point it to the ro...
627 struct class_ro_t *data;
628 };
629
630 */
631
632 static void
build_v2_class_templates(void)633 build_v2_class_templates (void)
634 {
635 tree cnst_strg_type;
636 tree decls, *chain = NULL;
637
638 /* struct class_ro_t {...} */
639 objc_v2_class_ro_template =
640 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
641
642 /* uint32_t const flags; */
643 decls = add_field_decl (integer_type_node, "flags", &chain);
644
645 /* uint32_t const instanceStart; */
646 add_field_decl (integer_type_node, "instanceStart", &chain);
647
648 /* uint32_t const instanceSize; */
649 add_field_decl (integer_type_node, "instanceSize", &chain);
650
651 /* This ABI is currently only used on m64 NeXT. We always
652 explicitly declare the alignment padding. */
653 /* uint32_t const reserved; */
654 add_field_decl (integer_type_node, "reserved", &chain);
655
656 /* const uint8_t * const ivarLayout; */
657 cnst_strg_type = build_pointer_type (unsigned_char_type_node);
658 add_field_decl (cnst_strg_type, "ivarLayout", &chain);
659
660 /* const char *const name; */
661 add_field_decl (string_type_node, "name", &chain);
662
663 /* const struct method_list_t * const baseMethods; */
664 add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
665
666 /* const struct objc_protocol_list *const baseProtocols; */
667 add_field_decl (build_pointer_type
668 (xref_tag (RECORD_TYPE,
669 get_identifier (UTAG_V2_PROTOCOL_LIST))),
670 "baseProtocols", &chain);
671
672 /* const struct ivar_list_t *const ivars; */
673 add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
674
675 /* const uint8_t * const weakIvarLayout; */
676 add_field_decl (cnst_strg_type, "weakIvarLayout", &chain);
677
678 /* struct _prop_list_t * baseProperties; */
679 add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
680
681 objc_finish_struct (objc_v2_class_ro_template, decls);
682
683 chain = NULL;
684 /* struct class_t {...} */
685 objc_v2_class_template =
686 objc_start_struct (get_identifier (UTAG_V2_CLASS));
687
688 /* struct class_t *isa; */
689 decls = add_field_decl (build_pointer_type (objc_v2_class_template),
690 "isa", &chain);
691
692 /* struct class_t * const superclass; */
693 add_field_decl (build_pointer_type (objc_v2_class_template),
694 "superclass", &chain);
695
696 /* void *cache; */
697 add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
698
699 /* IMP *vtable; */
700 add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
701
702 /* struct class_ro_t *ro; */
703 add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
704
705 objc_finish_struct (objc_v2_class_template, decls);
706 }
707
708 /* struct _objc_super
709 {
710 struct _objc_object *self;
711 Class cls;
712 }; */
713 void
build_v2_super_template(void)714 build_v2_super_template (void)
715 {
716 tree decls, *chain = NULL;
717
718 objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
719
720 /* struct _objc_object *self; */
721 decls = add_field_decl (objc_object_type, "self", &chain);
722
723 /* Class cls; */
724 add_field_decl (objc_class_type, "cls", &chain);
725
726 objc_finish_struct (objc_super_template, decls);
727 }
728
729 /* struct protocol_t
730 {
731 Class isa;
732 const char * const protocol_name;
733 const struct protocol_list_t * const protocol_list;
734 const struct method_list_t * const instance_methods;
735 const struct method_list_t * const class_methods;
736 const struct method_list_t * optionalInstanceMethods;
737 const struct method_list_t * optionalClassMethod
738 const struct _prop_list_t * const properties;
739 const uint32_t size;
740 const uint32_t flags;
741 }
742 */
743 static void
build_v2_protocol_template(void)744 build_v2_protocol_template (void)
745 {
746 tree decls, *chain = NULL;
747
748 objc_v2_protocol_template =
749 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
750
751 /* Class isa; */
752 decls = add_field_decl (objc_object_type, "isa", &chain);
753
754 /* char *protocol_name; */
755 add_field_decl (string_type_node, "protocol_name", &chain);
756
757 /* const struct protocol_list_t * const protocol_list; */
758 add_field_decl (build_pointer_type (objc_v2_protocol_template),
759 "protocol_list", &chain);
760
761 /* const struct method_list_t * const instance_methods; */
762 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
763
764 /* const struct method_list_t * const class_methods; */
765 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
766
767 /* const struct method_list_t * optionalInstanceMethods; */
768 add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
769
770 /* const struct method_list_t * optionalClassMethods; */
771 add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
772
773 /* struct _prop_list_t * properties; */
774 add_field_decl (objc_prop_list_ptr, "properties", &chain);
775
776 /* const uint32_t size; */
777 add_field_decl (integer_type_node, "size", &chain);
778
779 /* const uint32_t flags; */
780 add_field_decl (integer_type_node, "flags", &chain);
781
782 objc_finish_struct (objc_v2_protocol_template, decls);
783 }
784
785 /* Build type for a category:
786 struct category_t
787 {
788 const char * const name;
789 struct class_t *const cls;
790 const struct method_list_t * const instance_methods;
791 const struct method_list_t * const class_methods;
792 const struct protocol_list_t * const protocols;
793 const struct _prop_list_t * const properties;
794 }
795 */
796
797 static void
build_v2_category_template(void)798 build_v2_category_template (void)
799 {
800 tree decls, *chain = NULL;
801
802 objc_v2_category_template =
803 objc_start_struct (get_identifier ("_category_t"));
804
805 /* char *name; */
806 decls = add_field_decl (string_type_node, "name", &chain);
807
808 /* struct class_t *const cls; */
809 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
810
811 /* struct method_list_t *instance_methods; */
812 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
813
814 /* struct method_list_t *class_methods; */
815 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
816
817 /* struct protocol_list_t *protocol_list; */
818 add_field_decl (build_pointer_type (objc_v2_protocol_template),
819 "protocol_list", &chain );
820
821 /* struct _prop_list_t * properties; */
822 add_field_decl (objc_prop_list_ptr, "properties", &chain);
823
824 objc_finish_struct (objc_v2_category_template, decls);
825 }
826
827 /* NOTE --- Decls, Identifiers, Names etc. --- */
828
829 /* This routine is given a name and returns a matching extern variable
830 if one is found. */
831
832 static tree
hash_name_lookup(hash * hashlist,tree name)833 hash_name_lookup (hash *hashlist, tree name)
834 {
835 hash target;
836
837 target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
838
839 while (target)
840 {
841 if (name == DECL_NAME (target->key))
842 return target->key;
843
844 target = target->next;
845 }
846 return 0;
847 }
848
849 /* This routine is given an extern variable and enters it in its hash
850 table. Note that hashing is done on its inner IDENTIFIER_NODE
851 node. */
852
853 static void
hash_name_enter(hash * hashlist,tree id)854 hash_name_enter (hash *hashlist, tree id)
855 {
856 hash obj;
857 int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
858
859 obj = ggc_alloc_hashed_entry ();
860 obj->list = 0;
861 obj->next = hashlist[slot];
862 obj->key = id;
863
864 hashlist[slot] = obj; /* append to front */
865 }
866
867 /* Create a declaration "extern <type> <name>;"
868 The var will need to be finalized (e.g. by calling finish_var_decl()). */
869
870 static tree
create_extern_decl(tree type,const char * name)871 create_extern_decl (tree type, const char *name)
872 {
873 tree id = get_identifier (name);
874 tree var = hash_name_lookup (extern_names, id);
875 if (var)
876 return var;
877 /* New name. */
878 var = start_var_decl (type, name);
879 TREE_STATIC (var) = 0;
880 DECL_EXTERNAL (var) = 1;
881 TREE_PUBLIC (var) = 1;
882 hash_name_enter (extern_names, var);
883 return var;
884 }
885
886 /* Create a globally visible definition for variable NAME of a given TYPE. The
887 finish_var_decl() routine will need to be called on it afterwards. */
888
889 static tree
create_global_decl(tree type,const char * name)890 create_global_decl (tree type, const char *name)
891 {
892 tree id = get_identifier (name);
893 tree var = hash_name_lookup (extern_names, id);
894 if (var)
895 {
896 DECL_EXTERNAL (var) = 0;
897 TREE_STATIC (var) = 1;
898 }
899 else
900 {
901 var = start_var_decl (type, name);
902 hash_name_enter (extern_names, var);
903 }
904 TREE_PUBLIC (var) = 1;
905 return var;
906 }
907
908 /* Create a symbol with __attribute__ ((visibility ("hidden")))
909 attribute (private extern). */
910
911 static tree
create_hidden_decl(tree type,const char * name)912 create_hidden_decl (tree type, const char *name)
913 {
914 tree decl = create_global_decl (type, name);
915 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
916 DECL_VISIBILITY_SPECIFIED (decl) = 1;
917 return decl;
918 }
919
920 /* Irritatingly, we have a different superclass field name for ABI=2. */
921 /* PS/TODO: The field name does not matter, it is only used internally
922 by the compiler. We can rename it to whatever we want. ;-) */
923
924 static tree
next_runtime_abi_02_super_superclassfield_id(void)925 next_runtime_abi_02_super_superclassfield_id (void)
926 {
927 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
928 most look it once at startup then always return it. */
929 if (!super_superclassfield_id)
930 super_superclassfield_id = get_identifier ("cls");
931 return super_superclassfield_id;
932 }
933
934 static tree
next_runtime_abi_02_class_decl(tree klass)935 next_runtime_abi_02_class_decl (tree klass)
936 {
937 tree decl;
938 char buf[BUFSIZE];
939 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
940 IDENTIFIER_POINTER (CLASS_NAME (klass)));
941 /* ObjC2 classes are extern visible. */
942 decl = create_global_decl (objc_v2_class_template, buf);
943 OBJCMETA (decl, objc_meta, meta_class);
944 return decl;
945 }
946
947 static tree
next_runtime_abi_02_metaclass_decl(tree klass)948 next_runtime_abi_02_metaclass_decl (tree klass)
949 {
950 tree decl;
951 char buf[BUFSIZE];
952 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
953 IDENTIFIER_POINTER (CLASS_NAME (klass)));
954 /* ObjC2 classes are extern visible. */
955 decl = create_global_decl (objc_v2_class_template, buf);
956 OBJCMETA (decl, objc_meta, meta_metaclass);
957 return decl;
958 }
959
960 static tree
next_runtime_abi_02_category_decl(tree klass)961 next_runtime_abi_02_category_decl (tree klass)
962 {
963 tree decl;
964 char buf[BUFSIZE];
965 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
966 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
967 IDENTIFIER_POINTER (CLASS_NAME (klass)));
968 decl = start_var_decl (objc_v2_category_template, buf);
969 OBJCMETA (decl, objc_meta, meta_category);
970 return decl;
971 }
972
973 static tree
next_runtime_abi_02_protocol_decl(tree p)974 next_runtime_abi_02_protocol_decl (tree p)
975 {
976 tree decl;
977 char buf[BUFSIZE];
978
979 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
980 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
981 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
982 decl = start_var_decl (objc_v2_protocol_template, buf);
983 OBJCMETA (decl, objc_meta, meta_protocol);
984 return decl;
985 }
986
987 static tree
next_runtime_abi_02_string_decl(tree type,const char * name,string_section where)988 next_runtime_abi_02_string_decl (tree type, const char *name, string_section where)
989 {
990 tree var = start_var_decl (type, name);
991 switch (where)
992 {
993 case class_names:
994 OBJCMETA (var, objc_meta, meta_class_name);
995 break;
996 case meth_var_names:
997 OBJCMETA (var, objc_meta, meta_meth_name);
998 break;
999 case meth_var_types:
1000 OBJCMETA (var, objc_meta, meta_meth_type);
1001 break;
1002 case prop_names_attr:
1003 OBJCMETA (var, objc_meta, meta_prop_name_attr);
1004 break;
1005 default:
1006 OBJCMETA (var, objc_meta, meta_base);
1007 break;
1008 }
1009 return var;
1010 }
1011
1012 /* NOTE --- entry --- */
1013
1014 typedef struct GTY(()) ident_data_tuple {
1015 tree ident;
1016 tree data;
1017 } ident_data_tuple ;
1018 DEF_VEC_O(ident_data_tuple);
1019 DEF_VEC_ALLOC_O(ident_data_tuple, gc);
1020
1021 /* This routine creates a file scope static variable of type 'Class'
1022 to hold the address of a class. */
1023
1024 static tree
build_v2_class_reference_decl(tree ident)1025 build_v2_class_reference_decl (tree ident)
1026 {
1027 tree decl;
1028 char buf[BUFSIZE];
1029
1030 snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1031 decl = start_var_decl (objc_class_type, buf);
1032 OBJCMETA (decl, objc_meta, meta_class_ref);
1033 return decl;
1034 }
1035
1036 /* This routine builds a class refs entry for each class name used.
1037 Initially, a (static-ref, IDENT) tuple is added to the list. The
1038 ident is replaced with address of the class metadata (of type
1039 'Class') in the output routine. */
1040
1041 static GTY (()) VEC (ident_data_tuple, gc) * classrefs;
1042
1043 static tree
objc_v2_get_class_reference(tree ident)1044 objc_v2_get_class_reference (tree ident)
1045 {
1046 tree decl;
1047 ident_data_tuple e;
1048 if (classrefs)
1049 {
1050 int count;
1051 ident_data_tuple *ref;
1052 FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
1053 {
1054 if (ref->ident == ident)
1055 {
1056 if (!ref->data)
1057 ref->data = build_v2_class_reference_decl (ident);
1058 return ref->data;
1059 }
1060 }
1061 }
1062 else
1063 /* Somewhat arbitrary initial provision. */
1064 classrefs = VEC_alloc (ident_data_tuple, gc, 16);
1065
1066 /* We come here if we don't find the entry - or if the table was yet
1067 to be created. */
1068 decl = build_v2_class_reference_decl (ident);
1069 e.ident = ident;
1070 e.data = decl;
1071 VEC_safe_push (ident_data_tuple, gc, classrefs, &e);
1072 return decl;
1073 }
1074
1075 static tree
next_runtime_abi_02_get_class_reference(tree ident)1076 next_runtime_abi_02_get_class_reference (tree ident)
1077 {
1078 if (!flag_zero_link)
1079 return objc_v2_get_class_reference (ident);
1080 else
1081 {
1082 /* We fall back to using objc_getClass (). */
1083 VEC(tree,gc) *vec = VEC_alloc (tree, gc, 1);
1084 tree t;
1085 /* ??? add_class_reference (ident); - is pointless, since the
1086 system lib does not export the equivalent symbols. Maybe we
1087 need to build a class ref anyway. */
1088 t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1089 IDENTIFIER_POINTER (ident));
1090 VEC_quick_push (tree, vec, t);
1091 t = build_function_call_vec (input_location, objc_get_class_decl,
1092 vec, NULL);
1093 VEC_free (tree, gc, vec);
1094 return t;
1095 }
1096 }
1097
1098 /* Used by build_function_type_for_method. Append the types for
1099 receiver & _cmd at the start of a method argument list to ARGTYPES.
1100 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1101 trying to define a method or call one. SUPERFLAG says this is for a
1102 send to super. METH may be NULL, in the case that there is no
1103 prototype. */
1104
1105 static void
next_runtime_abi_02_get_arg_type_list_base(VEC (tree,gc)** argtypes,tree meth,int context,int superflag)1106 next_runtime_abi_02_get_arg_type_list_base (VEC(tree,gc) **argtypes, tree meth,
1107 int context, int superflag)
1108 {
1109 tree receiver_type;
1110
1111 if (superflag)
1112 receiver_type = objc_super_type;
1113 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1114 receiver_type = objc_instance_type;
1115 else
1116 receiver_type = objc_object_type;
1117
1118 VEC_safe_push (tree, gc, *argtypes, receiver_type);
1119 /* Selector type - will eventually change to `int'. */
1120 VEC_safe_push (tree, gc, *argtypes,
1121 (superflag
1122 ? objc_v2_super_selector_type
1123 : objc_v2_selector_type));
1124 }
1125
1126 /* TODO: Merge this with the message refs. */
1127 static tree
build_selector_reference_decl(tree ident)1128 build_selector_reference_decl (tree ident)
1129 {
1130 tree decl;
1131 char *t, buf[BUFSIZE];
1132
1133 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1134 t = buf;
1135 while (*t)
1136 {
1137 if (*t==':')
1138 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1139 t++;
1140 }
1141 decl = start_var_decl (objc_selector_type, buf);
1142 OBJCMETA (decl, objc_meta, meta_sel_refs);
1143 return decl;
1144 }
1145
1146 static tree
next_runtime_abi_02_build_selector_reference(location_t loc ATTRIBUTE_UNUSED,tree ident,tree proto ATTRIBUTE_UNUSED)1147 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1148 tree ident,
1149 tree proto ATTRIBUTE_UNUSED)
1150 {
1151 tree *chain = &sel_ref_chain;
1152 tree expr;
1153
1154 while (*chain)
1155 {
1156 if (TREE_VALUE (*chain) == ident)
1157 return TREE_PURPOSE (*chain);
1158
1159 chain = &TREE_CHAIN (*chain);
1160 }
1161
1162 expr = build_selector_reference_decl (ident);
1163 *chain = tree_cons (expr, ident, NULL_TREE);
1164
1165 return expr;
1166 }
1167
1168 /* Declare a variable of type 'struct message_ref_t'. */
1169 /* This will be finished in build_v2_message_ref_translation_table ().
1170 We take an idea from LLVM in making the names a bit more connected
1171 and thus the asm more readable. */
1172
1173 static tree
build_v2_message_reference_decl(tree sel_name,tree message_func_ident)1174 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1175 {
1176 tree decl;
1177 char buf[BUFSIZE], *t;
1178 int offset = 12;
1179
1180 /* Skip past the objc_msgSend it's the same for all... */
1181 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1182 offset++;
1183
1184 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1185 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1186 IDENTIFIER_POINTER (sel_name));
1187 t = buf;
1188 while (*t)
1189 {
1190 if (*t==':')
1191 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1192 t++;
1193 }
1194 decl = start_var_decl (objc_v2_message_ref_template, buf);
1195 OBJCMETA (decl, objc_meta, meta_mref);
1196 return decl;
1197 }
1198
1199 typedef struct GTY(()) msgref_entry {
1200 tree func;
1201 tree selname;
1202 tree refdecl;
1203 } msgref_entry;
1204 DEF_VEC_O(msgref_entry);
1205 DEF_VEC_ALLOC_O(msgref_entry, gc);
1206
1207 static GTY (()) VEC (msgref_entry, gc) * msgrefs;
1208
1209 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1210 later on to initialize the table of 'struct message_ref_t'
1211 elements. */
1212
1213 static tree
build_v2_selector_messenger_reference(tree sel_name,tree message_func_decl)1214 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1215 {
1216 tree decl;
1217 msgref_entry e;
1218 if (msgrefs)
1219 {
1220 int count;
1221 msgref_entry *ref;
1222 FOR_EACH_VEC_ELT (msgref_entry, msgrefs, count, ref)
1223 if (ref->func == message_func_decl && ref->selname == sel_name)
1224 return ref->refdecl;
1225 }
1226 else
1227 /* Somewhat arbitrary initial provision. */
1228 msgrefs = VEC_alloc (msgref_entry, gc, 32);
1229
1230 /* We come here if we don't find a match or at the start. */
1231 decl = build_v2_message_reference_decl (sel_name,
1232 DECL_NAME (message_func_decl));
1233 e.func = message_func_decl;
1234 e.selname = sel_name;
1235 e.refdecl = decl;
1236 VEC_safe_push (msgref_entry, gc, msgrefs, &e);
1237 return decl;
1238 }
1239
1240 static tree
build_v2_protocollist_ref_decl(tree protocol)1241 build_v2_protocollist_ref_decl (tree protocol)
1242 {
1243 tree decl;
1244 tree protocol_ident = PROTOCOL_NAME (protocol);
1245 char buf[BUFSIZE];
1246
1247 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1248 IDENTIFIER_POINTER (protocol_ident));
1249 /* TODO: other compiler versions make these hidden & weak. */
1250 decl = create_global_decl (objc_protocol_type, buf);
1251 /* Let optimizer know that this decl is not removable. */
1252 DECL_PRESERVE_P (decl) = 1;
1253 OBJCMETA (decl, objc_meta, meta_proto_ref);
1254 return decl;
1255 }
1256
1257 typedef struct GTY(()) prot_list_entry {
1258 tree id;
1259 tree refdecl;
1260 } prot_list_entry;
1261 DEF_VEC_O(prot_list_entry);
1262 DEF_VEC_ALLOC_O(prot_list_entry, gc);
1263 static GTY (()) VEC (prot_list_entry, gc) * protrefs;
1264
1265 static tree
objc_v2_get_protocol_reference(tree ident)1266 objc_v2_get_protocol_reference (tree ident)
1267 {
1268 tree decl;
1269 prot_list_entry e;
1270 if (protrefs)
1271 {
1272 int count;
1273 prot_list_entry *ref;
1274 FOR_EACH_VEC_ELT (prot_list_entry, protrefs, count, ref)
1275 {
1276 if (ref->id == ident)
1277 {
1278 if (!ref->refdecl)
1279 ref->refdecl = build_v2_protocollist_ref_decl (ident);
1280 return ref->refdecl;
1281 }
1282 }
1283 }
1284 else
1285 /* Somewhat arbitrary initial provision. */
1286 protrefs = VEC_alloc (prot_list_entry, gc, 32);
1287
1288 /* We come here if we don't find the entry - or if the table was yet
1289 to be created. */
1290 decl = build_v2_protocollist_ref_decl (ident);
1291 e.id = ident;
1292 e.refdecl = decl;
1293 VEC_safe_push (prot_list_entry, gc, protrefs, &e);
1294 return decl;
1295 }
1296
1297 static tree
next_runtime_abi_02_get_protocol_reference(location_t loc ATTRIBUTE_UNUSED,tree p)1298 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1299 tree p)
1300 {
1301 if (!PROTOCOL_FORWARD_DECL (p))
1302 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1303
1304 return objc_v2_get_protocol_reference (p);
1305 }
1306
1307 /* This routine returns the ivar declaration, if component is a valid
1308 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1309 returns the class name in CLASS. */
1310
1311 static tree
objc_is_ivar(tree expr,tree component,tree * klass)1312 objc_is_ivar (tree expr, tree component, tree *klass)
1313 {
1314 tree field = NULL_TREE;
1315 tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1316
1317 if (TREE_CODE (basetype) == RECORD_TYPE
1318 && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1319 {
1320 *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1321 if (*klass)
1322 {
1323 do
1324 {
1325 tree ivar_chain = CLASS_RAW_IVARS (*klass);
1326 if (ivar_chain)
1327 {
1328 field = is_ivar (ivar_chain, component);
1329 if (field != NULL_TREE)
1330 break;
1331 }
1332 *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1333 }
1334 while (*klass);
1335 }
1336 }
1337 return field;
1338 }
1339
1340 static void
create_ivar_offset_name(char * buf,tree class_name,tree field_decl)1341 create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1342 {
1343 tree fname = DECL_NAME (field_decl);
1344
1345 sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1346 IDENTIFIER_POINTER (fname));
1347 return;
1348 }
1349
1350 /* This routine generates new abi's ivar reference tree. It amounts
1351 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1352 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1353 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1354
1355 static tree
objc_v2_build_ivar_ref(tree datum,tree component)1356 objc_v2_build_ivar_ref (tree datum, tree component)
1357 {
1358 tree field, ref, class_name, offset, ftype, expr;
1359 char var_offset_name[512];
1360
1361 field = objc_is_ivar (datum, component, &class_name);
1362 if (!field)
1363 return NULL_TREE;
1364
1365 /* This routine only handles non-bitfield fields */
1366 /* DECL_INITIAL macro is set to width of bitfield and can be relied
1367 on to check for bitfield ivars. Note that I cannot rely on
1368 DECL_BIT_FIELD macro because it is only set when the whole struct
1369 is seen (at finish_struct) and not when the ivar chain is
1370 built. */
1371 if (DECL_INITIAL (field))
1372 return NULL_TREE;
1373
1374 create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field);
1375
1376 offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1377
1378 ftype = TREE_TYPE (field);
1379
1380 /* (char*)datum */
1381 expr = build_c_cast (input_location,
1382 string_type_node, build_fold_addr_expr (datum));
1383
1384 /* (char*)datum + offset */
1385 expr = fold_build_pointer_plus_loc (input_location, expr, offset);
1386
1387 /* (ftype*)((char*)datum + offset) */
1388 expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1389
1390 /* Finally: *(ftype*)((char*)datum + offset) */
1391 ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1392
1393 /* We must set type of the resulting expression to be the same as
1394 the field type. This is because, build_indirect_ref (...)
1395 rebuilds the type which may result in lost information; as in the
1396 case of protocol-qualified types (id <protocol> ). */
1397 TREE_TYPE (ref) = ftype;
1398
1399 if (TREE_READONLY (datum) || TREE_READONLY (field))
1400 TREE_READONLY (ref) = 1;
1401
1402 if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1403 TREE_THIS_VOLATILE (ref) = 1;
1404
1405 if (TREE_DEPRECATED (field))
1406 warn_deprecated_use (field, NULL_TREE);
1407
1408 return ref;
1409 }
1410
1411 /* IVAR refs are made via an externally referenceable offset and built
1412 on the fly. That is, unless they refer to (private) fields in the
1413 class stucture. */
1414 static tree
next_runtime_abi_02_build_ivar_ref(location_t loc ATTRIBUTE_UNUSED,tree base,tree id)1415 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1416 tree base, tree id)
1417 {
1418 tree ivar;
1419 if ((ivar = objc_v2_build_ivar_ref (base, id)))
1420 return ivar;
1421 return objc_build_component_ref (base, id);
1422 }
1423
1424 /* [super ...] references are listed here (and built into a table at
1425 meta -data emit time). */
1426 static tree
build_v2_superclass_ref_decl(tree ident,bool inst)1427 build_v2_superclass_ref_decl (tree ident, bool inst)
1428 {
1429 tree decl;
1430 char buf[BUFSIZE];
1431
1432 snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1433 IDENTIFIER_POINTER (ident));
1434 decl = start_var_decl (objc_class_type, buf);
1435 OBJCMETA (decl, objc_meta, meta_superclass_ref);
1436 return decl;
1437 }
1438
1439 static GTY (()) VEC (ident_data_tuple, gc) * class_super_refs;
1440 static GTY (()) VEC (ident_data_tuple, gc) * metaclass_super_refs;
1441
1442 static tree
next_runtime_abi_02_get_class_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)1443 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1444 struct imp_entry *imp, bool inst_meth)
1445 {
1446 tree decl;
1447 ident_data_tuple e;
1448 tree id = CLASS_NAME (imp->imp_context);
1449 VEC (ident_data_tuple, gc) *list = inst_meth ? class_super_refs
1450 : metaclass_super_refs;
1451
1452 if (list)
1453 {
1454 int count;
1455 ident_data_tuple *ref;
1456 FOR_EACH_VEC_ELT (ident_data_tuple, list, count, ref)
1457 {
1458 if (ref->ident == id)
1459 {
1460 if (!ref->data)
1461 ref->data = build_v2_superclass_ref_decl (id, inst_meth);
1462 return ref->data;
1463 }
1464 }
1465 }
1466 else
1467 {
1468 /* Somewhat arbitrary initial provision. */
1469 if (inst_meth)
1470 list = class_super_refs = VEC_alloc (ident_data_tuple, gc, 16);
1471 else
1472 list = metaclass_super_refs = VEC_alloc (ident_data_tuple, gc, 16);
1473 }
1474 /* We come here if we don't find the entry - or if the table was yet
1475 to be created. */
1476 decl = build_v2_superclass_ref_decl (id, inst_meth);
1477 e.ident = id;
1478 e.data = decl;
1479 VEC_safe_push (ident_data_tuple, gc, list, &e);
1480 return decl;
1481 }
1482
1483 static tree
next_runtime_abi_02_get_category_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)1484 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1485 struct imp_entry *imp, bool inst_meth)
1486 {
1487 /* ??? is this OK when zero-link = true? */
1488 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1489 tree super_class;
1490
1491 if (!flag_zero_link)
1492 {
1493 super_class = objc_get_class_reference (CLASS_NAME (imp->imp_template));
1494
1495 if (!inst_meth)
1496
1497 /* If we are in a class method, we must retrieve the
1498 _metaclass_ for the current class, pointed at by the
1499 class's "isa" pointer. The following assumes that "isa" is
1500 the first ivar in a class (which it must be). */
1501 super_class =
1502 build_indirect_ref (input_location,
1503 build_c_cast (input_location,
1504 build_pointer_type (objc_class_type),
1505 super_class),
1506 RO_UNARY_STAR);
1507 return super_class;
1508 }
1509 /* ??? Do we need to add the class ref anway for zero-link? */
1510 /* else do it the slow way. */
1511 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
1512 /* assemble_external (super_class); */
1513 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1514 IDENTIFIER_POINTER (super_name));
1515 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1516 return build_function_call (input_location,
1517 super_class,
1518 build_tree_list (NULL_TREE, super_name));
1519 }
1520
1521 static tree
next_runtime_abi_02_receiver_is_class_object(tree receiver)1522 next_runtime_abi_02_receiver_is_class_object (tree receiver)
1523 {
1524 if (TREE_CODE (receiver) == VAR_DECL
1525 && IS_CLASS (TREE_TYPE (receiver))
1526 && classrefs
1527 && VEC_length (ident_data_tuple, classrefs))
1528 {
1529 int count;
1530 ident_data_tuple *ref;
1531 /* The receiver is a variable created by build_class_reference_decl. */
1532 FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
1533 if (ref->data == receiver)
1534 return ref->ident;
1535 }
1536 return NULL_TREE;
1537 }
1538
1539 /* Assign all arguments in VALUES which have side-effect to a temporary
1540 and replaced that argument in VALUES list with the temporary. The
1541 arguments will be passed to a function with FNTYPE. */
1542
1543 static tree
objc_copy_to_temp_side_effect_params(tree fntype,tree values)1544 objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1545 {
1546 tree valtail;
1547 function_args_iterator iter;
1548
1549 /* Skip over receiver and the &_msf_ref types. */
1550 function_args_iter_init (&iter, fntype);
1551 function_args_iter_next (&iter);
1552 function_args_iter_next (&iter);
1553
1554 for (valtail = values; valtail;
1555 valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
1556 {
1557 tree value = TREE_VALUE (valtail);
1558 tree type = function_args_iter_cond (&iter);
1559 if (type == NULL_TREE)
1560 break;
1561 if (!TREE_SIDE_EFFECTS (value))
1562 continue;
1563 /* To prevent re-evaluation. */
1564 value = save_expr (value);
1565 add_stmt (value);
1566 TREE_VALUE (valtail) = value;
1567 }
1568 return values;
1569 }
1570
1571 /* Build the new abi's messaging library call. It looks like:
1572 (*_msg.messenger) (receiver, &_msg, ...) */
1573
1574 static tree
build_v2_build_objc_method_call(int super_flag,tree method_prototype,tree lookup_object,tree selector,tree method_params,bool check_for_nil)1575 build_v2_build_objc_method_call (int super_flag, tree method_prototype,
1576 tree lookup_object, tree selector,
1577 tree method_params,
1578 bool check_for_nil)
1579 {
1580 tree ret_val;
1581 tree sender, rcv_p, t;
1582 tree ret_type
1583 = (method_prototype
1584 ? TREE_VALUE (TREE_TYPE (method_prototype))
1585 : objc_object_type);
1586 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1587 METHOD_REF, super_flag);
1588 tree sender_cast;
1589
1590 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1591 ftype = build_type_attribute_variant (
1592 ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1593
1594 sender_cast = build_pointer_type (ftype);
1595
1596 if (check_for_nil)
1597 method_params = objc_copy_to_temp_side_effect_params (ftype,
1598 method_params);
1599
1600 /* Get &message_ref_t.messenger. */
1601 sender = build_c_cast (input_location,
1602 build_pointer_type (super_flag
1603 ? objc_v2_super_imp_type
1604 : objc_v2_imp_type),
1605 selector);
1606
1607 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1608
1609 rcv_p = (super_flag ? objc_super_type : objc_object_type);
1610
1611 lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1612
1613 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1614 lookup_object = save_expr (lookup_object);
1615
1616 method_params = tree_cons (NULL_TREE, lookup_object,
1617 tree_cons (NULL_TREE, selector,
1618 method_params));
1619 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
1620 ret_val = build_function_call (input_location, t, method_params);
1621 if (check_for_nil)
1622 {
1623 /* receiver != nil ? ret_val : 0 */
1624 tree ftree;
1625 tree ifexp;
1626
1627 if (TREE_CODE (ret_type) == RECORD_TYPE
1628 || TREE_CODE (ret_type) == UNION_TYPE)
1629 {
1630 VEC(constructor_elt,gc) *rtt = NULL;
1631 /* ??? CHECKME. hmmm..... think we need something more
1632 here. */
1633 CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE);
1634 ftree = objc_build_constructor (ret_type, rtt);
1635 }
1636 else
1637 ftree = fold_convert (ret_type, integer_zero_node);
1638
1639 ifexp = build_binary_op (input_location, NE_EXPR,
1640 lookup_object,
1641 fold_convert (rcv_p, integer_zero_node), 1);
1642
1643 #ifdef OBJCPLUS
1644 ret_val = build_conditional_expr (ifexp, ret_val, ftree, tf_warning_or_error);
1645 #else
1646 /* ??? CHECKME. */
1647 ret_val = build_conditional_expr (input_location,
1648 ifexp, 1,
1649 ret_val, NULL_TREE,
1650 ftree, NULL_TREE);
1651 #endif
1652 }
1653 return ret_val;
1654 }
1655
1656 static tree
next_runtime_abi_02_build_objc_method_call(location_t loc,tree method_prototype,tree receiver,tree rtype,tree sel_name,tree method_params,int super)1657 next_runtime_abi_02_build_objc_method_call (location_t loc,
1658 tree method_prototype,
1659 tree receiver,
1660 tree rtype,
1661 tree sel_name,
1662 tree method_params,
1663 int super)
1664 {
1665 tree ret_type, selector;
1666 tree message_func_decl;
1667 bool check_for_nil = flag_objc_nilcheck;
1668
1669 ret_type = method_prototype
1670 ? TREE_VALUE (TREE_TYPE (method_prototype))
1671 : objc_object_type;
1672
1673 /* Do we need to check for nil receivers ? */
1674 /* For now, message sent to classes need no nil check. In the
1675 future, class declaration marked as weak_import must be nil
1676 checked. */
1677 if (super
1678 || (TREE_CODE (receiver) == VAR_DECL
1679 && TREE_TYPE (receiver) == objc_class_type))
1680 check_for_nil = false;
1681
1682 if (!targetm.calls.struct_value_rtx (0, 0)
1683 && (TREE_CODE (ret_type) == RECORD_TYPE
1684 || TREE_CODE (ret_type) == UNION_TYPE)
1685 && targetm.calls.return_in_memory (ret_type, 0))
1686 {
1687 if (super)
1688 message_func_decl = umsg_id_super2_stret_fixup_decl;
1689 else
1690 message_func_decl = objc_is_id (rtype)
1691 ? umsg_id_stret_fixup_decl
1692 : umsg_stret_fixup_decl;
1693 }
1694 else
1695 {
1696 if (super)
1697 message_func_decl = umsg_id_super2_fixup_decl;
1698 else
1699 message_func_decl = objc_is_id (rtype)
1700 ? umsg_id_fixup_decl
1701 : umsg_fixup_decl;
1702 }
1703
1704 selector = build_v2_selector_messenger_reference (sel_name,
1705 message_func_decl);
1706
1707 /* selector = &_msg; */
1708 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1709
1710 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1711 : objc_v2_selector_type),
1712 selector);
1713
1714 /* (*_msg.messenger) (receiver, &_msg, ...); */
1715 return build_v2_build_objc_method_call (super, method_prototype,
1716 receiver, selector,
1717 method_params, check_for_nil);
1718 }
1719
1720 /* NOTE --- Constant String Class Stuff --- */
1721
1722 static bool
next_runtime_abi_02_setup_const_string_class_decl(void)1723 next_runtime_abi_02_setup_const_string_class_decl (void)
1724 {
1725 if (!constant_string_global_id)
1726 {
1727 /* Hopefully, this should not represent a serious limitation. */
1728 char buf[BUFSIZE];
1729 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1730 constant_string_global_id = get_identifier (buf);
1731 }
1732
1733 string_class_decl = lookup_name (constant_string_global_id);
1734
1735 /* In OBJC2 abi, constant string class reference refers to class
1736 name for NSConstantString class. This declaration may not be
1737 available yet (in fact it is not in most cases). So, declare an
1738 extern OBJC_CLASS_$_NSConstantString in its place. */
1739 if (!string_class_decl)
1740 string_class_decl =
1741 create_extern_decl (objc_v2_class_template,
1742 IDENTIFIER_POINTER (constant_string_global_id));
1743
1744 return (string_class_decl != NULL_TREE);
1745 }
1746
1747 static tree
next_runtime_abi_02_build_const_string_constructor(location_t loc,tree string,int length)1748 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1749 int length)
1750 {
1751 tree constructor, fields, var;
1752 VEC(constructor_elt,gc) *v = NULL;
1753
1754 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1755 fields = TYPE_FIELDS (internal_const_str_type);
1756 CONSTRUCTOR_APPEND_ELT (v, fields,
1757 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1758
1759 fields = DECL_CHAIN (fields);
1760 CONSTRUCTOR_APPEND_ELT (v, fields,
1761 build_unary_op (loc, ADDR_EXPR, string, 1));
1762
1763 /* ??? check if this should be long. */
1764 fields = DECL_CHAIN (fields);
1765 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1766 constructor = objc_build_constructor (internal_const_str_type, v);
1767
1768 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1769 DECL_INITIAL (var) = constructor;
1770 TREE_STATIC (var) = 1;
1771 DECL_CONTEXT (var) = NULL;
1772 OBJCMETA (var, objc_meta, meta_const_str);
1773 return var;
1774 }
1775
1776 /* NOTE --- NeXT V2 Metadata templates --- */
1777
1778 /* This routine builds the following type:
1779 struct _prop_t
1780 {
1781 const char * const name; // property name
1782 const char * const attributes; // comma-delimited, encoded,
1783 // property attributes
1784 };
1785 */
1786
1787 static tree
build_v2_property_template(void)1788 build_v2_property_template (void)
1789 {
1790 tree prop_record;
1791 tree decls, *chain = NULL;
1792
1793 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1794 /* const char * name */
1795 decls = add_field_decl (string_type_node, "name", &chain);
1796
1797 /* const char * attribute */
1798 add_field_decl (string_type_node, "attribute", &chain);
1799
1800 objc_finish_struct (prop_record, decls);
1801 return prop_record;
1802 }
1803
1804 /* struct ivar_t
1805 {
1806 unsigned long int *offset;
1807 char *name;
1808 char *type;
1809 uint32_t alignment;
1810 uint32_t size;
1811 };
1812 */
1813
1814 static tree
build_v2_ivar_t_template(void)1815 build_v2_ivar_t_template (void)
1816 {
1817 tree objc_ivar_id, objc_ivar_record;
1818 tree decls, *chain = NULL;
1819
1820 objc_ivar_id = get_identifier ("_ivar_t");
1821 objc_ivar_record = objc_start_struct (objc_ivar_id);
1822
1823 /* unsigned long int *offset; */
1824 decls = add_field_decl (build_pointer_type
1825 (TREE_TYPE (size_zero_node)), "offset", &chain);
1826
1827 /* char *name; */
1828 add_field_decl (string_type_node, "name", &chain);
1829
1830 /* char *type; */
1831 add_field_decl (string_type_node, "type", &chain);
1832
1833 /* uint32_t alignment; */
1834 add_field_decl (integer_type_node, "alignment", &chain);
1835
1836 /* uint32_t size; */
1837 add_field_decl (integer_type_node, "size", &chain);
1838
1839 objc_finish_struct (objc_ivar_record, decls);
1840 return objc_ivar_record;
1841 }
1842
1843 static void
build_metadata_templates(void)1844 build_metadata_templates (void)
1845 {
1846
1847 if (!objc_method_template)
1848 objc_method_template = build_method_template ();
1849
1850 if (!objc_v2_property_template)
1851 objc_v2_property_template = build_v2_property_template ();
1852
1853 if (!objc_v2_ivar_template)
1854 objc_v2_ivar_template = build_v2_ivar_t_template ();
1855
1856 }
1857
1858 /* NOTE --- Output NeXT V2 Metadata --- */
1859
1860 /* Routine builds name of Interface's main meta-data of type class_t. */
1861
1862 static char *
objc_build_internal_classname(tree ident,bool metaclass)1863 objc_build_internal_classname (tree ident, bool metaclass)
1864 {
1865 static char string[512];
1866 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
1867 : "OBJC_CLASS_$",
1868 IDENTIFIER_POINTER (ident));
1869 return string;
1870 }
1871
1872 /* Build the name for object of type struct class_ro_t */
1873
1874 static const char *
newabi_append_ro(const char * name)1875 newabi_append_ro (const char *name)
1876 {
1877 const char *dollar;
1878 char *p;
1879 static char string[BUFSIZE];
1880 dollar = strchr (name, '$');
1881 gcc_assert (dollar);
1882 p = string;
1883 *p = '_'; p++;
1884 strncpy (p, name, (int)(dollar - name));
1885 p += (int)(dollar - name);
1886 sprintf (p, "RO_%s", dollar);
1887 return string;
1888 }
1889
1890 /* Build the struct message_ref_t msg =
1891 {objc_msgSend_fixup_xxx, @selector(func)}
1892 table. */
1893
1894 static
build_v2_message_ref_translation_table(void)1895 void build_v2_message_ref_translation_table (void)
1896 {
1897 int count;
1898 msgref_entry *ref;
1899
1900 if (!msgrefs || !VEC_length (msgref_entry,msgrefs))
1901 return;
1902
1903 FOR_EACH_VEC_ELT (msgref_entry, msgrefs, count, ref)
1904 {
1905 VEC(constructor_elt,gc) *initializer;
1906 tree expr, constructor;
1907 tree struct_type = TREE_TYPE (ref->refdecl);
1908 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
1909
1910 initializer = NULL;
1911 /* First 'IMP messenger' field... */
1912 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
1913 expr = convert (objc_v2_imp_type, expr);
1914 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1915
1916 /* ... then 'SEL name' field. */
1917 expr = build_selector (ref->selname);
1918 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1919 constructor = objc_build_constructor (struct_type, initializer);
1920 finish_var_decl (ref->refdecl, constructor);
1921 }
1922 }
1923
1924 /* Build decl = initializer; for each externally visible class
1925 reference. */
1926
1927 static void
build_v2_classrefs_table(void)1928 build_v2_classrefs_table (void)
1929 {
1930 int count;
1931 ident_data_tuple *ref;
1932
1933 if (!classrefs || !VEC_length (ident_data_tuple, classrefs))
1934 return;
1935
1936 FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
1937 {
1938 tree expr = ref->ident;
1939 tree decl = ref->data;
1940 /* Interface with no implementation and yet one of its messages
1941 has been used. Need to generate a full address-of tree for it
1942 here. */
1943 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1944 {
1945 const char *name = objc_build_internal_classname (expr, false);
1946 expr = create_extern_decl (objc_v2_class_template, name);
1947 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1948 }
1949 /* The runtime wants this, even if it appears unused, so we must force the
1950 output.
1951 DECL_PRESERVE_P (decl) = 1; */
1952 finish_var_decl (decl, expr);
1953 }
1954 }
1955
1956 /* Build decl = initializer; for each externally visible super class
1957 reference. */
1958
1959 static void
build_v2_super_classrefs_table(bool metaclass)1960 build_v2_super_classrefs_table (bool metaclass)
1961 {
1962 int count;
1963 ident_data_tuple *ref;
1964 VEC (ident_data_tuple, gc) *list = metaclass ? metaclass_super_refs
1965 : class_super_refs;
1966
1967 if (!list || !VEC_length (ident_data_tuple, list))
1968 return;
1969
1970 FOR_EACH_VEC_ELT (ident_data_tuple, list, count, ref)
1971 {
1972 tree expr = ref->ident;
1973 tree decl = ref->data;
1974 /* Interface with no implementation and yet one of its messages
1975 has been used. Need to generate a full address-of tree for it
1976 here. */
1977 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1978 {
1979 const char * name = objc_build_internal_classname (expr, metaclass);
1980 expr = create_extern_decl (objc_v2_class_template, name);
1981 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1982 }
1983 finish_var_decl (decl, expr);
1984 }
1985 }
1986
1987 /* Add the global class meta-data declaration to the list which later
1988 on ends up in the __class_list section. */
1989
1990 static GTY(()) VEC(tree,gc) *class_list;
1991
1992 static void
objc_v2_add_to_class_list(tree global_class_decl)1993 objc_v2_add_to_class_list (tree global_class_decl)
1994 {
1995 if (!class_list)
1996 class_list = VEC_alloc (tree, gc, imp_count?imp_count:1);
1997 VEC_safe_push (tree, gc, class_list, global_class_decl);
1998 }
1999
2000 static GTY(()) VEC(tree,gc) *nonlazy_class_list;
2001
2002 /* Add the global class meta-data declaration to the list which later
2003 on ends up in the __nonlazy_class section. */
2004
2005 static void
objc_v2_add_to_nonlazy_class_list(tree global_class_decl)2006 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2007 {
2008 if (!nonlazy_class_list)
2009 nonlazy_class_list = VEC_alloc (tree, gc, imp_count?imp_count:1);
2010 VEC_safe_push (tree, gc, nonlazy_class_list, global_class_decl);
2011 }
2012
2013 static GTY(()) VEC(tree,gc) *category_list;
2014
2015 /* Add the category meta-data declaration to the list which later on
2016 ends up in the __nonlazy_category section. */
2017
2018 static void
objc_v2_add_to_category_list(tree decl)2019 objc_v2_add_to_category_list (tree decl)
2020 {
2021 if (!category_list)
2022 category_list = VEC_alloc (tree, gc, cat_count?cat_count:1);
2023 VEC_safe_push (tree, gc, category_list, decl);
2024 }
2025
2026 static GTY(()) VEC(tree,gc) *nonlazy_category_list;
2027
2028 /* Add the category meta-data declaration to the list which later on
2029 ends up in the __category_list section. */
2030
2031 static void
objc_v2_add_to_nonlazy_category_list(tree decl)2032 objc_v2_add_to_nonlazy_category_list (tree decl)
2033 {
2034 if (!nonlazy_category_list)
2035 nonlazy_category_list = VEC_alloc (tree, gc, cat_count?cat_count:1);
2036 VEC_safe_push (tree, gc, nonlazy_category_list, decl);
2037 }
2038
2039 static bool
has_load_impl(tree clsmeth)2040 has_load_impl (tree clsmeth)
2041 {
2042 while (clsmeth)
2043 {
2044 tree id = METHOD_SEL_NAME (clsmeth);
2045 if (IDENTIFIER_LENGTH (id) == 4
2046 && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
2047 return true;
2048 clsmeth = DECL_CHAIN (clsmeth);
2049 }
2050
2051 return false;
2052 }
2053
2054 /* Build a __{class,category}_list section table containing address of
2055 all @implemented {class,category} meta-data. */
2056
2057 static void
build_v2_address_table(VEC (tree,gc)* src,const char * nam,tree attr)2058 build_v2_address_table (VEC(tree,gc) *src, const char *nam, tree attr)
2059 {
2060 int count=0;
2061 tree type, decl, expr;
2062 VEC(constructor_elt,gc) *initlist = NULL;
2063
2064 if (!src || !VEC_length(tree,src))
2065 return;
2066
2067 FOR_EACH_VEC_ELT (tree, src, count, decl)
2068 {
2069 #ifndef OBJCPLUS
2070 tree purpose = build_int_cst (NULL_TREE, count);
2071 #else
2072 tree purpose = NULL_TREE;
2073 #endif
2074 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2075 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2076 }
2077 gcc_assert (count > 0);
2078 type = build_array_type (objc_class_type,
2079 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2080 decl = start_var_decl (type, nam);
2081 /* The runtime wants this, even if it appears unused, so we must
2082 force the output. */
2083 DECL_PRESERVE_P (decl) = 1;
2084 expr = objc_build_constructor (type, initlist);
2085 OBJCMETA (decl, objc_meta, attr);
2086 finish_var_decl (decl, expr);
2087 }
2088
2089 /* Build decl = initializer; for each protocol referenced in
2090 @protocol(MyProt) expression. Refs as built in the entry section
2091 above. */
2092
2093 static void
build_v2_protocol_list_translation_table(void)2094 build_v2_protocol_list_translation_table (void)
2095 {
2096 int count;
2097 prot_list_entry *ref;
2098
2099 if (!protrefs)
2100 return;
2101
2102 FOR_EACH_VEC_ELT (prot_list_entry, protrefs, count, ref)
2103 {
2104 char buf[BUFSIZE];
2105 tree expr;
2106 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2107 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2108 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2109 expr = start_var_decl (objc_v2_protocol_template, buf);
2110 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2111 finish_var_decl (ref->refdecl, expr);
2112 }
2113 /* TODO: Maybe we could explicitly delete the vec. now? */
2114 }
2115
2116 static GTY (()) VEC (prot_list_entry, gc) * protlist;
2117
2118 /* Add the local protocol meta-data declaration to the list which
2119 later on ends up in the __protocol_list section. */
2120
2121 static void
objc_add_to_protocol_list(tree protocol_interface_decl,tree protocol_decl)2122 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2123 {
2124 prot_list_entry e;
2125 if (!protlist)
2126 /* Arbitrary init count. */
2127 protlist = VEC_alloc (prot_list_entry, gc, 32);
2128 e.id = protocol_interface_decl;
2129 e.refdecl = protocol_decl;
2130 VEC_safe_push (prot_list_entry, gc, protlist, &e);
2131 }
2132
2133 /* Build the __protocol_list section table containing address of all
2134 generate protocol_t meta-data. */
2135
2136 static void
build_v2_protocol_list_address_table(void)2137 build_v2_protocol_list_address_table (void)
2138 {
2139 int count;
2140 prot_list_entry *ref;
2141 if (!protlist || !VEC_length (prot_list_entry, protlist))
2142 return;
2143
2144 FOR_EACH_VEC_ELT (prot_list_entry, protlist, count, ref)
2145 {
2146 tree decl, expr;
2147 char buf[BUFSIZE];
2148 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2149 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2150 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2151 decl = create_global_decl (objc_protocol_type, buf);
2152 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2153 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2154 finish_var_decl (decl, expr);
2155 }
2156
2157 /* TODO: delete the vec. */
2158 /* TODO: upgrade to the clang/llvm hidden version. */
2159 }
2160
2161 /* This routine declares a variable to hold meta data for 'struct
2162 protocol_list_t'. */
2163
2164 static tree
generate_v2_protocol_list(tree i_or_p,tree klass_ctxt)2165 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2166 {
2167 tree refs_decl, lproto, e, plist, ptempl_p_t;
2168 int size = 0;
2169 VEC(constructor_elt,gc) *initlist = NULL;
2170 char buf[BUFSIZE];
2171
2172 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2173 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2174 plist = CLASS_PROTOCOL_LIST (i_or_p);
2175 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2176 plist = PROTOCOL_LIST (i_or_p);
2177 else
2178 gcc_unreachable ();
2179
2180 /* Compute size. */
2181 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2182 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2183 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2184 size++;
2185
2186 /* Build initializer. */
2187
2188 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2189 e = build_int_cst (ptempl_p_t, size);
2190 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2191
2192 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2193 {
2194 tree pval = TREE_VALUE (lproto);
2195
2196 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2197 && PROTOCOL_FORWARD_DECL (pval))
2198 {
2199 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2200 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2201 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2202 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2203 }
2204 }
2205
2206 /* static struct protocol_list_t *list[size]; */
2207
2208 switch (TREE_CODE (i_or_p))
2209 {
2210 case PROTOCOL_INTERFACE_TYPE:
2211 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2212 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2213 break;
2214 case CLASS_INTERFACE_TYPE:
2215 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2216 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2217 break;
2218 case CATEGORY_INTERFACE_TYPE:
2219 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2220 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2221 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2222 break;
2223 default:
2224 gcc_unreachable ();
2225 }
2226
2227 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2228 buf);
2229 /* ObjC2 puts all these in the base section. */
2230 OBJCMETA (refs_decl, objc_meta, meta_base);
2231 DECL_PRESERVE_P (refs_decl) = 1;
2232 finish_var_decl (refs_decl,
2233 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2234 return refs_decl;
2235 }
2236
2237 /* This routine builds one 'struct method_t' initializer list. Note
2238 that the old ABI is supposed to build 'struct objc_method' which
2239 has 3 fields, but it does not build the initialization expression
2240 for 'method_imp' which for protocols is NULL any way. To be
2241 consistant with declaration of 'struct method_t', in the new ABI we
2242 set the method_t.imp to NULL. */
2243
2244 static tree
build_v2_descriptor_table_initializer(tree type,tree entries)2245 build_v2_descriptor_table_initializer (tree type, tree entries)
2246 {
2247 VEC(constructor_elt,gc) *initlist = NULL;
2248 do
2249 {
2250 VEC(constructor_elt,gc) *eltlist = NULL;
2251 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2252 build_selector (METHOD_SEL_NAME (entries)));
2253 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2254 add_objc_string (METHOD_ENCODING (entries),
2255 meth_var_types));
2256 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2257
2258 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2259 objc_build_constructor (type, eltlist));
2260 entries = TREE_CHAIN (entries);
2261 }
2262 while (entries);
2263
2264 return objc_build_constructor (build_array_type (type, 0), initlist);
2265 }
2266
2267 /* struct method_list_t
2268 {
2269 uint32_t entsize;
2270 uint32_t method_count;
2271 struct objc_method method_list[method_count];
2272 }; */
2273
2274 static tree
build_v2_method_list_template(tree list_type,int size)2275 build_v2_method_list_template (tree list_type, int size)
2276 {
2277 tree method_list_t_record;
2278 tree array_type, decls, *chain = NULL;
2279
2280 method_list_t_record = objc_start_struct (NULL_TREE);
2281
2282 /* uint32_t const entsize; */
2283 decls = add_field_decl (integer_type_node, "entsize", &chain);
2284
2285 /* int method_count; */
2286 add_field_decl (integer_type_node, "method_count", &chain);
2287
2288 /* struct objc_method method_list[]; */
2289 array_type = build_sized_array_type (list_type, size);
2290 add_field_decl (array_type, "method_list", &chain);
2291
2292 objc_finish_struct (method_list_t_record, decls);
2293 return method_list_t_record;
2294 }
2295
2296 /* Note, as above that we are building to the objc_method_template
2297 which has the *imp field. ABI0/1 build with
2298 objc_method_prototype_template which is missing this field. */
2299 static tree
generate_v2_meth_descriptor_table(tree chain,tree protocol,const char * prefix,tree attr)2300 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2301 const char *prefix, tree attr)
2302 {
2303 tree method_list_template, initlist, decl, methods;
2304 int size, entsize;
2305 VEC(constructor_elt,gc) *v = NULL;
2306 char buf[BUFSIZE];
2307
2308 if (!chain || !prefix)
2309 return NULL_TREE;
2310
2311 methods = chain;
2312 size = 0;
2313 while (methods)
2314 {
2315 if (! METHOD_ENCODING (methods))
2316 METHOD_ENCODING (methods) = encode_method_prototype (methods);
2317 methods = TREE_CHAIN (methods);
2318 size++;
2319 }
2320
2321 gcc_assert (size);
2322 method_list_template = build_v2_method_list_template (objc_method_template,
2323 size);
2324 snprintf (buf, BUFSIZE, "%s_%s", prefix,
2325 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2326
2327 decl = start_var_decl (method_list_template, buf);
2328
2329 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2330 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2331 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2332 initlist =
2333 build_v2_descriptor_table_initializer (objc_method_template,
2334 chain);
2335 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2336 /* Get into the right section. */
2337 OBJCMETA (decl, objc_meta, attr);
2338 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2339 return decl;
2340 }
2341
2342 /* This routine builds the initializer list to initialize the 'struct
2343 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2344
2345 static tree
build_v2_property_table_initializer(tree type,tree context)2346 build_v2_property_table_initializer (tree type, tree context)
2347 {
2348 tree x;
2349 VEC(constructor_elt,gc) *inits = NULL;
2350 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2351 x = CLASS_PROPERTY_DECL (context);
2352 else
2353 x = IMPL_PROPERTY_DECL (context);
2354
2355 for (; x; x = TREE_CHAIN (x))
2356 {
2357 VEC(constructor_elt,gc) *elemlist = NULL;
2358 /* NOTE! sections where property name/attribute go MUST change
2359 later. */
2360 tree attribute, name_ident = PROPERTY_NAME (x);
2361
2362 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2363 add_objc_string (name_ident, prop_names_attr));
2364
2365 attribute = objc_v2_encode_prop_attr (x);
2366 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2367 add_objc_string (attribute, prop_names_attr));
2368
2369 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2370 objc_build_constructor (type, elemlist));
2371 }
2372
2373 return objc_build_constructor (build_array_type (type, 0),inits);
2374 }
2375
2376 /* This routine builds the following type:
2377 struct _prop_list_t
2378 {
2379 uint32_t entsize; // sizeof (struct _prop_t)
2380 uint32_t prop_count;
2381 struct _prop_t prop_list [prop_count];
2382 }
2383 */
2384
2385 static tree
build_v2_property_list_template(tree list_type,int size)2386 build_v2_property_list_template (tree list_type, int size)
2387 {
2388 tree property_list_t_record;
2389 tree array_type, decls, *chain = NULL;
2390
2391 /* anonymous. */
2392 property_list_t_record = objc_start_struct (NULL_TREE);
2393
2394 /* uint32_t const entsize; */
2395 decls = add_field_decl (integer_type_node, "entsize", &chain);
2396
2397 /* int prop_count; */
2398 add_field_decl (integer_type_node, "prop_count", &chain);
2399
2400 /* struct _prop_t prop_list[]; */
2401 array_type = build_sized_array_type (list_type, size);
2402 add_field_decl (array_type, "prop_list", &chain);
2403
2404 objc_finish_struct (property_list_t_record, decls);
2405 return property_list_t_record;
2406 }
2407
2408 /* Top-level routine to generate property tables for each
2409 implementation. */
2410
2411 static tree
generate_v2_property_table(tree context,tree klass_ctxt)2412 generate_v2_property_table (tree context, tree klass_ctxt)
2413 {
2414 tree x, decl, initlist, property_list_template;
2415 bool is_proto = false;
2416 VEC(constructor_elt,gc) *inits = NULL;
2417 int init_val, size = 0;
2418 char buf[BUFSIZE];
2419
2420 if (context)
2421 {
2422 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2423 x = CLASS_PROPERTY_DECL (context);
2424 is_proto = true;
2425 }
2426 else
2427 x = IMPL_PROPERTY_DECL (klass_ctxt);
2428
2429 for (; x; x = TREE_CHAIN (x))
2430 size++;
2431
2432 if (size == 0)
2433 return NULL_TREE;
2434
2435 property_list_template =
2436 build_v2_property_list_template (objc_v2_property_template,
2437 size);
2438
2439 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2440 is_proto ? context
2441 : klass_ctxt);
2442
2443 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2444 if (is_proto)
2445 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2446 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2447 else
2448 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2449 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2450
2451 decl = start_var_decl (property_list_template, buf);
2452
2453 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2454 build_int_cst (NULL_TREE, init_val));
2455 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2456 build_int_cst (NULL_TREE, size));
2457 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2458
2459 OBJCMETA (decl, objc_meta, meta_base);
2460 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2461 return decl;
2462 }
2463
2464 static tree
build_v2_protocol_initializer(tree type,tree protocol_name,tree protocol_list,tree inst_methods,tree class_methods,tree opt_ins_meth,tree opt_cls_meth,tree property_list)2465 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2466 tree inst_methods, tree class_methods,
2467 tree opt_ins_meth, tree opt_cls_meth,
2468 tree property_list)
2469 {
2470 tree expr, ttyp;
2471 location_t loc;
2472 VEC(constructor_elt,gc) *inits = NULL;
2473
2474 /* TODO: find a better representation of location from the inputs. */
2475 loc = UNKNOWN_LOCATION;
2476
2477 /* This is NULL for the new ABI. */
2478 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2479 convert (objc_object_type, null_pointer_node));
2480
2481 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2482 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2483
2484 ttyp = objc_method_proto_list_ptr;
2485 if (inst_methods)
2486 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2487 else
2488 expr = convert (ttyp, null_pointer_node);
2489 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2490
2491 if (class_methods)
2492 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2493 else
2494 expr = convert (ttyp, null_pointer_node);
2495 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2496
2497 if (opt_ins_meth)
2498 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2499 else
2500 expr = convert (ttyp, null_pointer_node);
2501 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2502
2503 if (opt_cls_meth)
2504 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2505 else
2506 expr = convert (ttyp, null_pointer_node);
2507 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2508
2509 ttyp = objc_prop_list_ptr;
2510 if (property_list)
2511 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2512 else
2513 expr = convert (ttyp, null_pointer_node);
2514 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2515
2516 /* const uint32_t size; = sizeof(struct protocol_t) */
2517 expr = build_int_cst (integer_type_node,
2518 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2519 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2520 /* const uint32_t flags; = 0 */
2521 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2522
2523 return objc_build_constructor (type, inits);
2524 }
2525
2526 /* Main routine to build all meta data for all protocols used in a
2527 translation unit. */
2528
2529 static void
generate_v2_protocols(void)2530 generate_v2_protocols (void)
2531 {
2532 tree p ;
2533 bool some = false;
2534
2535 if (!protocol_chain)
2536 return ;
2537
2538 /* If a protocol was directly referenced, pull in indirect
2539 references. */
2540 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2541 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2542 generate_protocol_references (PROTOCOL_LIST (p));
2543
2544 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2545 {
2546 location_t loc;
2547 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2548 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2549
2550 /* If protocol wasn't referenced, don't generate any code. */
2551 decl = PROTOCOL_FORWARD_DECL (p);
2552
2553 if (!decl)
2554 continue;
2555
2556 loc = DECL_SOURCE_LOCATION (decl);
2557 some = true;
2558
2559 inst_meth =
2560 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2561 "_OBJC_ProtocolInstanceMethods",
2562 meta_proto_nst_meth);
2563
2564 class_meth =
2565 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2566 "_OBJC_ProtocolClassMethods",
2567 meta_proto_cls_meth);
2568
2569 opt_inst_meth =
2570 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2571 "_OBJC_OptProtocolInstMethods",
2572 meta_proto_nst_meth);
2573
2574 opt_class_meth =
2575 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2576 "_OBJC_OptProtocolClassMethods",
2577 meta_proto_cls_meth);
2578
2579 if (PROTOCOL_LIST (p))
2580 refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2581 else
2582 refs_decl = 0;
2583
2584 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2585 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2586
2587 if (refs_decl)
2588 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2589 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2590 else
2591 refs_expr = build_int_cst (NULL_TREE, 0);
2592
2593 props = generate_v2_property_table (p, NULL_TREE);
2594
2595 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2596 protocol_name_expr, refs_expr,
2597 inst_meth, class_meth,
2598 opt_inst_meth, opt_class_meth,
2599 props);
2600 finish_var_decl (decl, initlist);
2601 objc_add_to_protocol_list (p, decl);
2602 }
2603
2604 if (some)
2605 {
2606 /* Make sure we get the Protocol class linked in - reference
2607 it... */
2608 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2609 /* ... but since we don't specifically use the reference... we
2610 need to force it. */
2611 DECL_PRESERVE_P (p) = 1;
2612 }
2613 }
2614
2615 static tree
generate_v2_dispatch_table(tree chain,const char * name,tree attr)2616 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2617 {
2618 tree decl, method_list_template, initlist;
2619 VEC(constructor_elt,gc) *v = NULL;
2620 int size, init_val;
2621
2622 if (!chain || !name || !(size = list_length (chain)))
2623 return NULL_TREE;
2624
2625 method_list_template
2626 = build_v2_method_list_template (objc_method_template, size);
2627 initlist
2628 = build_dispatch_table_initializer (objc_method_template, chain);
2629
2630 decl = start_var_decl (method_list_template, name);
2631
2632 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2633 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2634 build_int_cst (integer_type_node, init_val));
2635 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2636 build_int_cst (integer_type_node, size));
2637 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2638
2639 OBJCMETA (decl, objc_meta, attr);
2640 finish_var_decl (decl,
2641 objc_build_constructor (TREE_TYPE (decl), v));
2642 return decl;
2643 }
2644
2645 /* Init a category. */
2646 static tree
build_v2_category_initializer(tree type,tree cat_name,tree class_name,tree inst_methods,tree class_methods,tree protocol_list,tree property_list,location_t loc)2647 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2648 tree inst_methods, tree class_methods,
2649 tree protocol_list, tree property_list,
2650 location_t loc)
2651 {
2652 tree expr, ltyp;
2653 VEC(constructor_elt,gc) *v = NULL;
2654
2655 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2656 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2657
2658 ltyp = objc_method_list_ptr;
2659 if (inst_methods)
2660 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2661 else
2662 expr = convert (ltyp, null_pointer_node);
2663 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2664
2665 if (class_methods)
2666 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2667 else
2668 expr = convert (ltyp, null_pointer_node);
2669 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2670
2671 /* protocol_list = */
2672 ltyp = build_pointer_type (objc_v2_protocol_template);
2673 if (protocol_list)
2674 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2675 else
2676 expr = convert (ltyp, null_pointer_node);
2677 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2678
2679 ltyp = objc_prop_list_ptr;
2680 if (property_list)
2681 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2682 else
2683 expr = convert (ltyp, null_pointer_node);
2684 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2685
2686 return objc_build_constructor (type, v);
2687 }
2688
2689 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2690
2691 static void
generate_v2_category(struct imp_entry * impent)2692 generate_v2_category (struct imp_entry *impent)
2693 {
2694 tree initlist, cat_name_expr, class_name_expr;
2695 tree protocol_decl, category, props, t;
2696 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2697 tree cat = impent->imp_context;
2698 tree cat_decl = impent->class_decl;
2699 location_t loc;
2700 char buf[BUFSIZE];
2701
2702 loc = DECL_SOURCE_LOCATION (cat_decl);
2703
2704 /* ??? not sure this is really necessary, the following references should
2705 force appropriate linkage linkage...
2706 -- but ... ensure a reference to the class... */
2707 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2708 /* ... which we ignore so force it out.. */
2709 DECL_PRESERVE_P (t) = 1;
2710
2711 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2712 class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2713 class_name_expr = build_fold_addr_expr (class_name_expr);
2714
2715 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2716 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2717
2718 if (category && CLASS_PROTOCOL_LIST (category))
2719 {
2720 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2721 protocol_decl = generate_v2_protocol_list (category, cat);
2722 }
2723 else
2724 protocol_decl = NULL_TREE;
2725
2726 /* decl = update_var_decl(impent->class_decl); */
2727
2728 props = generate_v2_property_table (NULL_TREE, cat);
2729
2730 if (CLASS_NST_METHODS (cat))
2731 {
2732 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2733 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2734 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2735 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2736 meta_cati_meth);
2737 }
2738
2739 if (CLASS_CLS_METHODS (cat))
2740 {
2741 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2742 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2743 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2744 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2745 meta_catc_meth);
2746 }
2747
2748 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2749 cat_name_expr, class_name_expr,
2750 inst_methods, class_methods,
2751 protocol_decl, props, loc);
2752
2753 finish_var_decl (cat_decl, initlist);
2754 impent->class_decl = cat_decl;
2755
2756 /* Add to list of pointers in __category_list section. */
2757 objc_v2_add_to_category_list (cat_decl);
2758 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2759 objc_v2_add_to_nonlazy_category_list (cat_decl);
2760 }
2761
2762 /* This routine declares a variable to hold the offset for ivar
2763 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
2764
2765 typedef struct GTY(()) ivarref_entry
2766 {
2767 tree decl;
2768 tree offset;
2769 } ivarref_entry;
2770 DEF_VEC_O(ivarref_entry);
2771 DEF_VEC_ALLOC_O(ivarref_entry, gc);
2772
2773 static GTY (()) VEC (ivarref_entry, gc) * ivar_offset_refs;
2774
2775 static tree
ivar_offset_ref(tree class_name,tree field_decl)2776 ivar_offset_ref (tree class_name, tree field_decl)
2777 {
2778 tree decl, field_decl_id;
2779 ivarref_entry e;
2780 bool global_var;
2781 char buf[512];
2782
2783 create_ivar_offset_name (buf, class_name, field_decl);
2784 field_decl_id = get_identifier (buf);
2785
2786 if (ivar_offset_refs)
2787 {
2788 int count;
2789 ivarref_entry *ref;
2790 FOR_EACH_VEC_ELT (ivarref_entry, ivar_offset_refs, count, ref)
2791 if (DECL_NAME (ref->decl) == field_decl_id)
2792 return ref->decl;
2793 }
2794 else
2795 /* Somewhat arbitrary initial provision. */
2796 ivar_offset_refs = VEC_alloc (ivarref_entry, gc, 32);
2797
2798 /* We come here if we don't find a match or at the start. */
2799 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
2800 if (global_var)
2801 decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
2802 else
2803 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
2804
2805 /* Make sure it ends up in an ObjC section. */
2806 OBJCMETA (decl, objc_meta, meta_base);
2807
2808 e.decl = decl;
2809 e.offset = byte_position (field_decl);
2810 VEC_safe_push (ivarref_entry, gc, ivar_offset_refs, &e);
2811 return decl;
2812 }
2813
2814 /* This routine builds initializer-list needed to initialize 'struct
2815 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
2816 'struct ivar_t' and FIELD_DECL is list of ivars for the target
2817 class. */
2818
2819 static tree
build_v2_ivar_list_initializer(tree class_name,tree type,tree field_decl)2820 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
2821 {
2822 VEC(constructor_elt,gc) *inits = NULL;
2823
2824 do
2825 {
2826 VEC(constructor_elt,gc) *ivar = NULL;
2827 int val;
2828 tree id;
2829
2830 /* Unnamed bitfields are ignored. */
2831 if (!DECL_NAME (field_decl))
2832 {
2833 field_decl = DECL_CHAIN (field_decl);
2834 continue;
2835 }
2836
2837 /* Set offset. */
2838 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2839 build_unary_op (input_location,
2840 ADDR_EXPR,
2841 ivar_offset_ref (class_name,
2842 field_decl), 0));
2843
2844 /* Set name. */
2845 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2846 add_objc_string (DECL_NAME (field_decl),
2847 meth_var_names));
2848
2849 /* Set type. */
2850 id = add_objc_string (encode_field_decl (field_decl),
2851 meth_var_types);
2852 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
2853
2854 /* Set alignment. */
2855 val = DECL_ALIGN_UNIT (field_decl);
2856 val = exact_log2 (val);
2857 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2858 build_int_cst (integer_type_node, val));
2859
2860 /* Set size. */
2861 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
2862 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2863 build_int_cst (integer_type_node, val));
2864
2865 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2866 objc_build_constructor (type, ivar));
2867
2868 do
2869 field_decl = DECL_CHAIN (field_decl);
2870 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
2871 }
2872 while (field_decl);
2873
2874 return objc_build_constructor (build_array_type (type, 0), inits);
2875 }
2876
2877 /*
2878 struct ivar_list_t
2879 {
2880 uint32 entsize;
2881 uint32 count;
2882 struct iver_t list[count];
2883 };
2884 */
2885
2886 static tree
build_v2_ivar_list_t_template(tree list_type,int size)2887 build_v2_ivar_list_t_template (tree list_type, int size)
2888 {
2889 tree objc_ivar_list_record;
2890 tree decls, *chain = NULL;
2891
2892 /* Anonymous. */
2893 objc_ivar_list_record = objc_start_struct (NULL_TREE);
2894
2895 /* uint32 entsize; */
2896 decls = add_field_decl (integer_type_node, "entsize", &chain);
2897
2898 /* uint32 count; */
2899 add_field_decl (integer_type_node, "count", &chain);
2900
2901 /* struct objc_ivar ivar_list[]; */
2902 add_field_decl (build_sized_array_type (list_type, size),
2903 "list", &chain);
2904
2905 objc_finish_struct (objc_ivar_list_record, decls);
2906 return objc_ivar_list_record;
2907 }
2908
2909 /* This routine declares a static variable of type 'struct
2910 ivar_list_t' and initializes it. chain is the source of the data,
2911 name is the name for the var. attr is the meta-data section tag
2912 attribute. templ is the implementation template for the class. */
2913
2914 static tree
generate_v2_ivars_list(tree chain,const char * name,tree attr,tree templ)2915 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
2916 {
2917 tree decl, initlist, ivar_list_template;
2918 VEC(constructor_elt,gc) *inits = NULL;
2919 int size, ivar_t_size;
2920
2921 if (!chain || !name || !(size = ivar_list_length (chain)))
2922 return NULL_TREE;
2923
2924 generating_instance_variables = 1;
2925 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
2926 size);
2927
2928 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
2929 objc_v2_ivar_template, chain);
2930 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
2931
2932 decl = start_var_decl (ivar_list_template, name);
2933 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2934 build_int_cst (integer_type_node, ivar_t_size));
2935 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2936 build_int_cst (integer_type_node, size));
2937 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2938 OBJCMETA (decl, objc_meta, attr);
2939 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2940 generating_instance_variables = 0;
2941 return decl;
2942 }
2943
2944 /* Routine to build initializer list to initialize objects of type
2945 struct class_t; */
2946
2947 static tree
build_v2_class_t_initializer(tree type,tree isa,tree superclass,tree ro,tree cache,tree vtable)2948 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
2949 tree ro, tree cache, tree vtable)
2950 {
2951 VEC(constructor_elt,gc) *initlist = NULL;
2952
2953 /* isa */
2954 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
2955
2956 /* superclass */
2957 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
2958
2959 /* cache */
2960 if (cache)
2961 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
2962 else
2963 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2964
2965 /* vtable */
2966 if (vtable)
2967 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
2968 else
2969 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2970
2971 /* ro */
2972 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
2973
2974 return objc_build_constructor (type, initlist);
2975 }
2976
2977 /* Routine to build object of struct class_ro_t { ... }; */
2978
2979 static tree
build_v2_class_ro_t_initializer(tree type,tree name,unsigned int flags,unsigned int instanceStart,unsigned int instanceSize,tree ivarLayout,tree baseMethods,tree baseProtocols,tree ivars,tree property_list)2980 build_v2_class_ro_t_initializer (tree type, tree name,
2981 unsigned int flags, unsigned int instanceStart,
2982 unsigned int instanceSize,
2983 tree ivarLayout,
2984 tree baseMethods, tree baseProtocols,
2985 tree ivars, tree property_list)
2986 {
2987 tree expr, unsigned_char_star, ltyp;
2988 location_t loc;
2989 VEC(constructor_elt,gc) *initlist = NULL;
2990
2991 /* TODO: fish out the real location from somewhere. */
2992 loc = UNKNOWN_LOCATION;
2993
2994 /* flags */
2995 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2996 build_int_cst (integer_type_node, flags));
2997
2998 /* instanceStart */
2999 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3000 build_int_cst (integer_type_node, instanceStart));
3001
3002 /* instanceSize */
3003 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3004 build_int_cst (integer_type_node, instanceSize));
3005
3006 /* This ABI is currently only used on m64 NeXT. We always
3007 explicitly declare the alignment padding. */
3008 /* reserved, pads alignment. */
3009 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3010 build_int_cst (integer_type_node, 0));
3011
3012 /* ivarLayout */
3013 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3014 if (ivarLayout)
3015 expr = ivarLayout;
3016 else
3017 expr = convert (unsigned_char_star, null_pointer_node);
3018 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3019
3020 /* name */
3021 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3022
3023 /* baseMethods */
3024 ltyp = objc_method_list_ptr;
3025 if (baseMethods)
3026 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3027 else
3028 expr = convert (ltyp, null_pointer_node);
3029 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3030
3031 /* baseProtocols */
3032 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3033 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3034 if (baseProtocols)
3035 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3036 else
3037 expr = convert (ltyp, null_pointer_node);
3038 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3039
3040 /* ivars */
3041 ltyp = objc_v2_ivar_list_ptr;
3042 if (ivars)
3043 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3044 else
3045 expr = convert (ltyp, null_pointer_node);
3046 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3047
3048 /* TODO: We don't yet have the weak/strong stuff... */
3049 /* weakIvarLayout */
3050 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3051 convert (unsigned_char_star, null_pointer_node));
3052
3053 /* property list */
3054 ltyp = objc_prop_list_ptr;
3055 if (property_list)
3056 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3057 else
3058 expr = convert (ltyp, null_pointer_node);
3059 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3060 return objc_build_constructor (type, initlist);
3061 }
3062
3063 static GTY (()) VEC (ident_data_tuple, gc) * ehtype_list;
3064
3065 /* Record a name as needing a catcher. */
3066 static void
objc_v2_add_to_ehtype_list(tree name)3067 objc_v2_add_to_ehtype_list (tree name)
3068 {
3069 ident_data_tuple e;
3070 if (ehtype_list)
3071 {
3072 int count = 0;
3073 ident_data_tuple *ref;
3074
3075 FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3076 if (ref->ident == name)
3077 return; /* Already entered. */
3078 }
3079 else
3080 /* Arbitrary initial count. */
3081 ehtype_list = VEC_alloc (ident_data_tuple, gc, 8);
3082
3083 /* Not found, or new list. */
3084 e.ident = name;
3085 e.data = NULL_TREE;
3086 VEC_safe_push (ident_data_tuple, gc, ehtype_list, &e);
3087 }
3088
3089 static void
generate_v2_class_structs(struct imp_entry * impent)3090 generate_v2_class_structs (struct imp_entry *impent)
3091 {
3092 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3093 tree field, firstIvar, chain;
3094 tree class_superclass_expr, metaclass_superclass_expr, props;
3095 /* TODO: figure out how to compute this. */
3096 tree ivarLayout = NULL_TREE;
3097 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3098 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3099 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3100 location_t loc;
3101 char buf[BUFSIZE];
3102 unsigned int instanceStart, instanceSize;
3103 unsigned int flags = 0x01; /* RO_META */
3104 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3105 : 0 ;
3106
3107 class_decl = impent->class_decl;
3108 metaclass_decl = impent->meta_decl;
3109 loc = DECL_SOURCE_LOCATION (class_decl);
3110
3111 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3112 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3113 #ifdef OBJCPLUS
3114 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3115 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3116 #endif
3117
3118 /* Generation of data for meta class. */
3119 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3120 if (my_super_id)
3121 {
3122 /* Compute reference to root's name. For a meta class, "isa" is
3123 a reference to the root class name. */
3124 tree my_root_id = my_super_id;
3125 tree my_root_int, interface;
3126 do
3127 {
3128 my_root_int = lookup_interface (my_root_id);
3129
3130 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3131 my_root_id = CLASS_SUPER_NAME (my_root_int);
3132 else
3133 break;
3134 }
3135 while (1);
3136
3137 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3138 create extern if not already declared. */
3139 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3140 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3141 root_expr = create_extern_decl (objc_v2_class_template, buf);
3142 root_expr = build_fold_addr_expr (root_expr);
3143
3144 /* Install class `isa' and `super' pointers at runtime. */
3145 interface = lookup_interface (my_super_id);
3146 gcc_assert (interface);
3147 /* Similarly, for OBJC_CLASS_$_<interface>... */
3148 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3149 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3150 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3151 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3152 /* ... and for OBJC_METACLASS_$_<interface>. */
3153 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3154 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3155 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3156 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3157 }
3158 else
3159 {
3160 /* Root class. */
3161 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3162 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3163 class_superclass_expr = build_int_cst (NULL_TREE, 0);
3164 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */
3165 }
3166
3167 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3168 {
3169 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3170 protocol_decl = generate_v2_protocol_list (impent->imp_template,
3171 impent->imp_context);
3172 }
3173 else
3174 protocol_decl = 0;
3175
3176 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3177 class_names);
3178
3179 if (CLASS_CLS_METHODS (impent->imp_context))
3180 {
3181 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3182 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3183 class_methods =
3184 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3185 buf, meta_clac_meth);
3186 }
3187
3188 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3189
3190 /* Currently there are no class ivars and generation of class
3191 variables for the root of the inheritance has been removed. It
3192 causes multiple defines if there are two root classes in the
3193 link, because each will define its own identically-named offset
3194 variable. */
3195
3196 class_ivars = NULL_TREE;
3197 /* TODO: Add total size of class variables when implemented. */
3198 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3199
3200 /* So now build the META CLASS structs. */
3201 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3202
3203 decl = start_var_decl (objc_v2_class_ro_template,
3204 newabi_append_ro (IDENTIFIER_POINTER
3205 (DECL_NAME (metaclass_decl))));
3206
3207 /* TODO: ivarLayout needs t be built. */
3208 initlist =
3209 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3210 (flags | cls_flags), instanceStart,
3211 instanceSize, ivarLayout,
3212 class_methods, protocol_decl,
3213 class_ivars, NULL_TREE);
3214 /* The ROs sit in the default const section. */
3215 OBJCMETA (decl, objc_meta, meta_base);
3216 finish_var_decl (decl, initlist);
3217
3218 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3219 initlist =
3220 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3221 root_expr,
3222 metaclass_superclass_expr,
3223 build_fold_addr_expr (decl),
3224 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3225 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3226 /* The class section attributes are set when they are created. */
3227 finish_var_decl (metaclass_decl, initlist);
3228 impent->meta_decl = metaclass_decl;
3229
3230 /* So now build the CLASS structs. */
3231
3232 flags = 0x0; /* ... */
3233 if (!my_super_id)
3234 flags |= 0x02; /* RO_ROOT: this is a root class */
3235
3236 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3237 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3238
3239 if (objc2_objc_exception_attr (impent->imp_template))
3240 flags |= 0x20; /* RO_EXCEPTION */
3241
3242 if (CLASS_NST_METHODS (impent->imp_context))
3243 {
3244 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3245 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3246 inst_methods =
3247 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3248 buf, meta_clai_meth);
3249 }
3250
3251 /* Sort out the ivars before we try to compute the class sizes. */
3252 if ((chain = CLASS_IVARS (impent->imp_template)))
3253 {
3254 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3255 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3256 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3257 impent->imp_template);
3258 }
3259
3260 /* Compute instanceStart. */
3261 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3262 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3263 if (my_super_id && field && TREE_CHAIN (field))
3264 field = TREE_CHAIN (field);
3265
3266 firstIvar = field;
3267
3268 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3269 firstIvar = TREE_CHAIN (firstIvar);
3270
3271 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3272
3273 /* Compute instanceSize. */
3274 while (field && TREE_CHAIN (field)
3275 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3276 field = TREE_CHAIN (field);
3277
3278 if (field && TREE_CODE (field) == FIELD_DECL)
3279 instanceSize = int_byte_position (field) * BITS_PER_UNIT
3280 + tree_low_cst (DECL_SIZE (field), 0);
3281 else
3282 instanceSize = 0;
3283 instanceSize /= BITS_PER_UNIT;
3284
3285 props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3286
3287 /* If the class has no ivars, instanceStart should be set to the
3288 superclass's instanceSize. */
3289 instanceStart =
3290 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3291 : instanceSize;
3292
3293 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3294 decl = start_var_decl (objc_v2_class_ro_template,
3295 newabi_append_ro (IDENTIFIER_POINTER
3296 (DECL_NAME (class_decl))));
3297
3298 initlist =
3299 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3300 (flags | cls_flags), instanceStart,
3301 instanceSize, ivarLayout,
3302 inst_methods, protocol_decl,
3303 inst_ivars, props);
3304 /* The ROs sit in the default const section. */
3305 OBJCMETA (decl, objc_meta, meta_base);
3306 finish_var_decl (decl, initlist);
3307
3308 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3309 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3310 build_fold_addr_expr (metaclass_decl),
3311 class_superclass_expr,
3312 build_fold_addr_expr (decl),
3313 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3314 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3315
3316 /* The class section attributes are set when they are created. */
3317 finish_var_decl (class_decl, initlist);
3318 impent->class_decl = class_decl;
3319
3320 objc_v2_add_to_class_list (class_decl);
3321 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3322 objc_v2_add_to_nonlazy_class_list (class_decl);
3323
3324 if (flags & 0x20) /* RO_EXCEPTION */
3325 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3326 }
3327
3328 /* This routine outputs the (ivar_reference_offset, offset)
3329 tuples. */
3330
3331 static void
build_v2_ivar_offset_ref_table(void)3332 build_v2_ivar_offset_ref_table (void)
3333 {
3334 int count;
3335 ivarref_entry *ref;
3336
3337 if (!ivar_offset_refs || !VEC_length (ivarref_entry, ivar_offset_refs))
3338 return;
3339
3340 FOR_EACH_VEC_ELT (ivarref_entry, ivar_offset_refs, count, ref)
3341 finish_var_decl (ref->decl, ref->offset);
3342 }
3343
3344 static void
objc_generate_v2_next_metadata(void)3345 objc_generate_v2_next_metadata (void)
3346 {
3347 struct imp_entry *impent;
3348
3349 /* FIXME: Make sure that we generate no metadata if there is nothing
3350 to put into it. */
3351
3352 gcc_assert (!objc_static_instances); /* Not for NeXT */
3353
3354 build_metadata_templates ();
3355
3356 for (impent = imp_list; impent; impent = impent->next)
3357 {
3358 /* If -gen-decls is present, Dump the @interface of each class.
3359 TODO: Dump the classes in the order they were found, rather
3360 than in reverse order as we are doing now. */
3361 if (flag_gen_declaration)
3362 dump_interface (gen_declaration_file, impent->imp_context);
3363
3364 /* all of the following reference the string pool... */
3365 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3366 generate_v2_class_structs (impent);
3367 else
3368 generate_v2_category (impent);
3369 }
3370
3371 build_next_selector_translation_table ();
3372 build_v2_message_ref_translation_table ();
3373
3374 /* This will add "Protocol" to the class refs. */
3375 generate_v2_protocols ();
3376
3377 build_v2_classrefs_table ();
3378 build_v2_super_classrefs_table (/*metaclass= */false);
3379 build_v2_super_classrefs_table (/*metaclass= */true);
3380
3381 build_v2_ivar_offset_ref_table ();
3382
3383 build_v2_protocol_list_translation_table ();
3384 build_v2_protocol_list_address_table ();
3385
3386 build_v2_address_table (class_list, "_OBJC_ClassList$",
3387 meta_label_classlist);
3388 build_v2_address_table (category_list, "_OBJC_CategoryList$",
3389 meta_label_categorylist);
3390 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3391 meta_label_nonlazy_classlist);
3392 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3393 meta_label_nonlazy_categorylist);
3394
3395 /* Generate catch objects for eh, if any are needed. */
3396 build_v2_eh_catch_objects ();
3397
3398 /* Emit the string table last. */
3399 generate_strings ();
3400 }
3401
3402 /* NOTE --- Output NeXT V2 Exceptions --- */
3403
3404 static GTY(()) tree objc_v2_ehtype_template;
3405 static GTY(()) tree next_v2_ehvtable_decl;
3406 static GTY(()) tree next_v2_EHTYPE_id_decl;
3407
3408 static void
build_v2_ehtype_template(void)3409 build_v2_ehtype_template (void)
3410 {
3411 tree decls, *chain = NULL;
3412 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3413
3414 /* void *_objc_ehtype_vtable; */
3415 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3416
3417 /* const char *className; */
3418 add_field_decl (string_type_node, "className", &chain);
3419
3420 /* struct class_t *const cls; */
3421 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3422
3423 objc_finish_struct (objc_v2_ehtype_template, decls);
3424 }
3425
3426 /* Template for the Objective-C family typeinfo type for ABI=2. This
3427 starts off the same as the gxx/cxx eh typeinfo.
3428
3429 struct _objc_ehtype_t
3430 {
3431 void *_objc_ehtype_vtable_ptr; - as per c++
3432 const char *className; - as per c++
3433 struct class_t *const cls;
3434 }
3435 */
3436
3437 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3438 */
3439
3440 static tree
objc2_build_ehtype_initializer(tree name,tree cls)3441 objc2_build_ehtype_initializer (tree name, tree cls)
3442 {
3443 VEC(constructor_elt,gc) *initlist = NULL;
3444 tree addr, offs;
3445
3446 /* This is done the same way as c++, missing the two first entries
3447 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3448 runtime source about this so, perhaps, this will change at some
3449 point. */
3450 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3451 if (!next_v2_ehvtable_decl)
3452 {
3453 next_v2_ehvtable_decl =
3454 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3455 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3456 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3457 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3458 }
3459 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3460 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3461 addr = fold_build_pointer_plus (addr, offs);
3462
3463 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3464
3465 /* className */
3466 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3467
3468 /* cls */
3469 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3470
3471 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3472 }
3473
3474 static tree
build_ehtype(tree name,const char * eh_name,bool weak)3475 build_ehtype (tree name, const char *eh_name, bool weak)
3476 {
3477 tree name_expr, class_name_expr, ehtype_decl, inits;
3478
3479 name_expr = add_objc_string (name, class_names);
3480 /* Extern ref. for the class. ??? Maybe we can look this up
3481 somewhere. */
3482 class_name_expr =
3483 create_extern_decl (objc_v2_class_template,
3484 objc_build_internal_classname (name, false));
3485 class_name_expr = build_fold_addr_expr (class_name_expr);
3486 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3487 if (weak)
3488 DECL_WEAK (ehtype_decl) = 1;
3489 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3490 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3491 finish_var_decl (ehtype_decl, inits);
3492 return ehtype_decl;
3493 }
3494
3495 /* This routine returns TRUE if CLS or any of its super classes has
3496 __attribute__ ((objc_exception)). */
3497
3498 static bool
objc2_objc_exception_attr(tree cls)3499 objc2_objc_exception_attr (tree cls)
3500 {
3501 while (cls)
3502 {
3503 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3504 return true;
3505 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3506 }
3507
3508 return false;
3509 }
3510
3511 static bool
is_implemented(tree name)3512 is_implemented (tree name)
3513 {
3514 struct imp_entry *t;
3515 for (t = imp_list; t; t = t->next)
3516 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3517 && CLASS_NAME (t->imp_template) == name)
3518 return true;
3519
3520 return false;
3521 }
3522
3523 /* We will build catch objects:
3524 for any type implemented here.
3525 for any type used in a catch that has no exception attribute. */
build_v2_eh_catch_objects(void)3526 static void build_v2_eh_catch_objects (void)
3527 {
3528 int count=0;
3529 ident_data_tuple *ref;
3530
3531 if (!ehtype_list || !VEC_length (ident_data_tuple, ehtype_list))
3532 return;
3533
3534 FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3535 {
3536 char buf[BUFSIZE];
3537 bool impl = is_implemented (ref->ident);
3538 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3539 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3540 if (!impl && excpt)
3541 /* The User says this class has a catcher already. */
3542 ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3543 else
3544 /* Create a catcher, weak if it wasn't marked. */
3545 ref->data = build_ehtype (ref->ident, buf, !excpt);
3546 }
3547 }
3548
3549 static tree
lookup_ehtype_ref(tree id)3550 lookup_ehtype_ref (tree id)
3551 {
3552 int count=0;
3553 ident_data_tuple *ref;
3554
3555 if (!ehtype_list || !VEC_length (ident_data_tuple, ehtype_list))
3556 return NULL_TREE;
3557
3558 FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3559 if (ref->ident == id)
3560 return ref->data;
3561 return NULL_TREE;
3562 }
3563
3564 /* This hook, called via lang_eh_runtime_type, generates a runtime
3565 object which is either the address of the 'OBJC_EHTYPE_$_class'
3566 object or address of external OBJC_EHTYPE_id object. */
3567 static tree
next_runtime_02_eh_type(tree type)3568 next_runtime_02_eh_type (tree type)
3569 {
3570 tree t;
3571
3572 if (type == error_mark_node
3573 /*|| errorcount || sorrycount*/)
3574 goto err_mark_in;
3575
3576 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3577 {
3578 if (!next_v2_EHTYPE_id_decl)
3579 {
3580 /* This is provided by the Apple/NeXT libobjc.dylib so we
3581 need only to reference it. */
3582 next_v2_EHTYPE_id_decl =
3583 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3584 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3585 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3586 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3587 }
3588 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3589 }
3590
3591 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3592 {
3593 #ifdef OBJCPLUS
3594 /* This routine is also called for c++'s catch clause; in which
3595 case, we use c++'s typeinfo decl. */
3596 return build_eh_type_type (type);
3597 #else
3598 error ("non-objective-c type '%T' cannot be caught", type);
3599 goto err_mark_in;
3600 #endif
3601 }
3602 else
3603 t = OBJC_TYPE_NAME (TREE_TYPE (type));
3604
3605 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3606 t = lookup_ehtype_ref (t);
3607 if (!t)
3608 goto err_mark_in;
3609
3610 return build_fold_addr_expr (t);
3611
3612 err_mark_in:
3613 return error_mark_node;
3614 }
3615
3616 static GTY(()) tree objc_eh_personality_decl;
3617
3618 static tree
objc_eh_personality(void)3619 objc_eh_personality (void)
3620 {
3621 if (!objc_eh_personality_decl)
3622 objc_eh_personality_decl = build_personality_function ("objc");
3623 return objc_eh_personality_decl;
3624 }
3625
3626 /* NOTE --- interfaces --- */
3627
3628 static tree
build_throw_stmt(location_t loc,tree throw_expr,bool rethrown)3629 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3630 {
3631 tree t;
3632 if (rethrown)
3633 /* We have a separate re-throw entry. */
3634 t = build_function_call_vec (loc, objc_rethrow_exception_decl, NULL, NULL);
3635 else
3636 {
3637 /* Throw like the others... */
3638 VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
3639 VEC_quick_push (tree, parms, throw_expr);
3640 t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
3641 VEC_free (tree, gc, parms);
3642 }
3643 return add_stmt (t);
3644 }
3645
3646 /* Build __builtin_eh_pointer. */
3647
3648 static tree
objc_build_exc_ptr(struct objc_try_context ** x ATTRIBUTE_UNUSED)3649 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3650 {
3651 tree t;
3652 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3653 t = build_call_expr (t, 1, integer_zero_node);
3654 return fold_convert (objc_object_type, t);
3655 }
3656
begin_catch(struct objc_try_context ** cur_try_context,tree type,tree decl,tree compound,bool ellipsis ATTRIBUTE_UNUSED)3657 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3658 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3659 {
3660 tree t;
3661
3662 /* Record the data for the catch in the try context so that we can
3663 finalize it later. Ellipsis is signalled by a NULL entry. */
3664 if (ellipsis)
3665 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3666 else
3667 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3668 (*cur_try_context)->current_catch = t;
3669
3670 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3671 t = objc_build_exc_ptr (cur_try_context);
3672 t = convert (TREE_TYPE (decl), t);
3673 /* FIXME: location. */
3674 if (type && type != error_mark_node)
3675 {
3676 t = build1(NOP_EXPR, ptr_type_node, t);
3677 t = build_function_call (input_location, objc2_begin_catch_decl,
3678 tree_cons (NULL_TREE, t, NULL_TREE));
3679
3680 /* We might want to build a catch object for this (if it's not
3681 id). */
3682 if (POINTER_TYPE_P (type)
3683 && !objc_is_object_id (TREE_TYPE (type))
3684 && TYPED_OBJECT (TREE_TYPE (type)))
3685 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3686 }
3687 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3688 }
3689
3690 /* try { catch-body } finally { objc_end_catch (); } */
3691 static void
finish_catch(struct objc_try_context ** cur_try_context,tree curr_catch)3692 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3693 {
3694 struct objc_try_context *ct;
3695 tree try_exp, func, *l, t ;
3696 location_t loc = (*cur_try_context)->try_locus;
3697
3698 if (!curr_catch || curr_catch == error_mark_node)
3699 return;
3700
3701 t = CATCH_BODY (curr_catch);
3702 if (TREE_CODE (t) == BIND_EXPR)
3703 {
3704 /* Usual case of @catch (objc-expr). */
3705 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3706 BIND_EXPR_BODY (t) = NULL_TREE;
3707 l = &BIND_EXPR_BODY (t);
3708 }
3709 else
3710 {
3711 /* NULL entry, meaning @catch (...). */
3712 objc_begin_try_stmt (loc, t);
3713 CATCH_BODY (curr_catch) = NULL_TREE;
3714 l = &CATCH_BODY (curr_catch);
3715 }
3716
3717 /* Pick up the new context we made in begin_try above... */
3718 ct = *cur_try_context;
3719 func = build_function_call_vec (loc, objc2_end_catch_decl, NULL, NULL);
3720 append_to_statement_list (func, &ct->finally_body);
3721 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3722 *cur_try_context = ct->outer;
3723 free (ct);
3724 append_to_statement_list (try_exp, l);
3725 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3726 }
3727
3728 static tree
finish_try_stmt(struct objc_try_context ** cur_try_context)3729 finish_try_stmt (struct objc_try_context **cur_try_context)
3730 {
3731 struct objc_try_context *c = *cur_try_context;
3732 tree stmt = c->try_body;
3733 if (c->catch_list)
3734 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3735 if (c->finally_body)
3736 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3737 return stmt;
3738 }
3739
3740 #include "gt-objc-objc-next-runtime-abi-02.h"
3741