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