Add C++11 header <cuchar>.
[official-gcc.git] / gcc / objc / objc-next-runtime-abi-02.c
blob73b591e830c34327e0469b994e82750873a9bb41
1 /* Next Runtime (ABI-2) private.
2 Copyright (C) 2011-2015 Free Software Foundation, Inc.
4 Contributed by Iain Sandoe and based, in part, on an implementation in
5 'branches/apple/trunk' contributed by Apple Computer Inc.
7 This file is part of GCC.
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.
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.
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/>. */
23 /* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
25 This version is intended to match (logically) the output of Apple's
26 4.2.1 compiler. */
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "alias.h"
33 #include "tree.h"
34 #include "options.h"
35 #include "fold-const.h"
36 #include "stringpool.h"
38 #ifdef OBJCPLUS
39 #include "cp/cp-tree.h"
40 #else
41 #include "c/c-tree.h"
42 #include "c/c-lang.h"
43 #endif
44 #include "langhooks.h"
45 #include "c-family/c-objc.h"
46 #include "objc-act.h"
48 /* When building Objective-C++, we are not linking against the C front-end
49 and so need to replicate the C tree-construction functions in some way. */
50 #ifdef OBJCPLUS
51 #define OBJCP_REMAP_FUNCTIONS
52 #include "objcp-decl.h"
53 #endif /* OBJCPLUS */
55 #include "target.h"
56 #include "tree-iterator.h"
58 #include "objc-runtime-hooks.h"
59 #include "objc-runtime-shared-support.h"
60 #include "objc-encoding.h"
62 /* ABI 2 Private definitions. */
63 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
65 #define TAG_GETCLASS "objc_getClass"
66 #define TAG_GETMETACLASS "objc_getMetaClass"
68 #define TAG_MSGSEND "objc_msgSend"
69 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
70 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
71 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
73 #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
74 #define TAG_V2_EH_TYPE "objc_ehtype_t"
76 #define UTAG_V2_CLASS "_class_t"
77 #define UTAG_V2_CLASS_RO "_class_ro_t"
78 #define UTAG_V2_PROTOCOL "_protocol_t"
79 #define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
81 #define UTAG_V2_EH_TYPE "_objc_ehtype_t"
83 #define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
85 enum objc_v2_tree_index
87 /* Templates. */
88 OCTI_V2_CLS_TEMPL,
89 OCTI_V2_CAT_TEMPL,
90 OCTI_V2_CLS_RO_TEMPL,
91 OCTI_V2_PROTO_TEMPL,
92 OCTI_V2_IVAR_TEMPL,
93 OCTI_V2_IVAR_LIST_TEMPL,
94 OCTI_V2_MESSAGE_REF_TEMPL,
95 OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
97 OCTI_V2_MESSAGE_SELECTOR_TYPE,
98 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
99 OCTI_V2_IMP_TYPE,
100 OCTI_V2_SUPER_IMP_TYPE,
102 OCTI_V2_CACHE_DECL,
103 OCTI_V2_VTABLE_DECL,
105 OCTI_V2_PROPERTY_TEMPL,
107 /* V2 messaging. */
108 OCTI_V2_UMSG_FIXUP_DECL,
109 OCTI_V2_UMSG_STRET_FIXUP_DECL,
110 OCTI_V2_UMSG_ID_FIXUP_DECL,
111 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
112 OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
113 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
115 /* Exceptions - related. */
116 OCTI_V2_BEGIN_CATCH_DECL,
117 OCTI_V2_END_CATCH_DECL,
118 OCTI_V2_RETHROW_DECL,
120 OCTI_V2_MAX
123 #define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
124 #define objc_v2_class_ro_template \
125 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
126 #define objc_v2_category_template \
127 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
128 #define objc_v2_protocol_template \
129 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
131 /* struct message_ref_t */
132 #define objc_v2_message_ref_template \
133 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
135 #define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
137 /* struct super_message_ref_t */
138 #define objc_v2_super_message_ref_template \
139 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
141 /* struct message_ref_t* */
142 #define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
143 /* struct super_super_message_ref_t */
144 #define objc_v2_super_selector_type \
145 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
146 #define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
147 #define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
149 #define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
150 #define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
152 #define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
153 #define objc_v2_property_template \
154 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
156 /* V2 Messaging */
158 /* objc_msgSend_fixup_rtp */
159 #define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
160 /* objc_msgSend_stret_fixup_rtp */
161 #define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
162 /* objc_msgSendId_fixup_rtp */
163 #define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
164 /* objc_msgSendId_stret_fixup_rtp */
165 #define umsg_id_stret_fixup_decl \
166 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
167 /* objc_msgSendSuper2_fixup_rtp */
168 #define umsg_id_super2_fixup_decl \
169 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
170 /* objc_msgSendSuper2_stret_fixup_rtp */
171 #define umsg_id_super2_stret_fixup_decl \
172 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
174 #define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
175 #define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
176 #define objc_rethrow_exception_decl \
177 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
179 /* rt_trees identifiers - shared between NeXT implementations. These allow
180 the FE to tag meta-data in a manner that survives LTO and can be used when
181 the runtime requires that certain meta-data items appear in particular
182 named sections. */
184 #include "objc-next-metadata-tags.h"
185 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
187 /* The OCTI_V2_... enumeration itself is in above. */
188 static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
190 static void next_runtime_02_initialize (void);
192 static void build_v2_message_ref_templates (void);
193 static void build_v2_class_templates (void);
194 static void build_v2_super_template (void);
195 static void build_v2_category_template (void);
196 static void build_v2_protocol_template (void);
198 static tree next_runtime_abi_02_super_superclassfield_id (void);
200 static tree next_runtime_abi_02_class_decl (tree);
201 static tree next_runtime_abi_02_metaclass_decl (tree);
202 static tree next_runtime_abi_02_category_decl (tree);
203 static tree next_runtime_abi_02_protocol_decl (tree);
204 static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
206 static tree next_runtime_abi_02_get_class_reference (tree);
207 static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
208 static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
209 static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
210 static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
211 static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
213 static tree next_runtime_abi_02_receiver_is_class_object (tree);
214 static void next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **,
215 tree, int, int);
216 static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
217 tree, tree, tree, int);
218 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
219 static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
221 static tree create_extern_decl (tree, const char *);
223 static void objc_generate_v2_next_metadata (void);
224 static bool objc2_objc_exception_attr (tree);
226 /* void build_v2_protocol_reference (tree);*/
227 static void build_v2_ehtype_template (void);
228 static void build_v2_eh_catch_objects (void);
229 static tree next_runtime_02_eh_type (tree);
230 static tree objc_eh_personality (void);
231 static tree build_throw_stmt (location_t, tree, bool);
232 static tree objc_build_exc_ptr (struct objc_try_context **);
233 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
234 static void finish_catch (struct objc_try_context **, tree);
235 static tree finish_try_stmt (struct objc_try_context **);
237 /* TODO: Use an objc-map. */
238 static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
240 bool
241 objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
243 extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
245 if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
247 inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for "
248 "%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
249 flag_objc_sjlj_exceptions = 0;
252 rthooks->initialize = next_runtime_02_initialize;
253 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
254 rthooks->tag_getclass = TAG_GETCLASS;
255 rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
257 rthooks->class_decl = next_runtime_abi_02_class_decl;
258 rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
259 rthooks->category_decl = next_runtime_abi_02_category_decl;
260 rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
261 rthooks->string_decl = next_runtime_abi_02_string_decl;
263 rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
264 rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
265 rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
266 rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
267 rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
268 rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
270 rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
271 rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
272 rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
274 rthooks->setup_const_string_class_decl =
275 next_runtime_abi_02_setup_const_string_class_decl;
276 rthooks->build_const_string_constructor =
277 next_runtime_abi_02_build_const_string_constructor;
279 rthooks->build_throw_stmt = build_throw_stmt;
280 rthooks->build_exc_ptr = objc_build_exc_ptr;
281 rthooks->begin_catch = begin_catch;
282 rthooks->finish_catch = finish_catch;
283 rthooks->finish_try_stmt = finish_try_stmt;
285 rthooks->generate_metadata = objc_generate_v2_next_metadata;
286 return true;
289 /* We need a way to convey what kind of meta-data are represented by a given
290 variable, since each type is expected (by the runtime) to be found in a
291 specific named section. The solution must be usable with LTO.
293 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
294 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
295 identification attributes in the front end. The back-end may choose to act
296 on these as it requires. */
298 static void
299 next_runtime_abi_02_init_metadata_attributes (void)
301 if (!objc_meta)
302 objc_meta = get_identifier ("OBJC2META");
304 if (!meta_base)
305 meta_base = get_identifier ("V2_BASE");
307 meta_class = get_identifier ("G2_CLAS");
308 meta_metaclass = get_identifier ("G2_META");
309 meta_category =
310 meta_protocol = meta_base;
312 meta_clac_vars =
313 meta_clai_vars = meta_base;
315 meta_clac_meth =
316 meta_clai_meth =
317 meta_catc_meth =
318 meta_cati_meth =
319 meta_proto_cls_meth =
320 meta_proto_nst_meth = meta_base;
322 meta_clas_prot =
323 meta_catg_prot = meta_base;
325 meta_sel_refs = get_identifier ("V2_SRFS");
327 meta_class_name =
328 meta_meth_name =
329 meta_meth_type =
330 meta_prop_name_attr = get_identifier ("V2_STRG");
332 meta_mref = get_identifier ("V2_MREF");
333 meta_class_ref = get_identifier ("V2_CLRF");
334 meta_superclass_ref = get_identifier ("V2_SURF");
336 meta_label_classlist = get_identifier ("V2_CLAB");
337 meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
338 meta_label_categorylist = get_identifier ("V2_CALA");
339 meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
341 meta_label_protocollist = get_identifier ("V2_PLST");
342 meta_proto_ref = get_identifier ("V2_PRFS");
344 meta_info = get_identifier ("V2_INFO");
346 meta_ehtype = get_identifier ("V2_EHTY");
348 meta_const_str = get_identifier ("V2_CSTR");
351 static void next_runtime_02_initialize (void)
353 tree type;
354 #ifdef OBJCPLUS
355 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
356 default. */
357 if (!global_options_set.x_flag_objc_call_cxx_cdtors)
358 global_options.x_flag_objc_call_cxx_cdtors = 1;
359 #endif
361 /* Set up attributes to be attached to the meta-data so that they
362 will be placed in the correct sections. */
363 next_runtime_abi_02_init_metadata_attributes ();
365 /* `struct objc_selector *' */
366 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
367 get_identifier (TAG_SELECTOR)));
369 /* IMP : id (*) (id, _message_ref_t*, ...)
370 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
371 objc_v2_selector_type. */
372 build_v2_message_ref_templates ();
374 objc_v2_ivar_list_ptr =
375 build_pointer_type (xref_tag (RECORD_TYPE,
376 get_identifier ("_ivar_list_t")));
378 objc_prop_list_ptr =
379 build_pointer_type (xref_tag (RECORD_TYPE,
380 get_identifier ("_prop_list_t")));
382 build_v2_class_templates ();
383 build_v2_super_template ();
384 build_v2_protocol_template ();
385 build_v2_category_template ();
387 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
388 type = build_varargs_function_type_list (objc_object_type,
389 objc_object_type,
390 objc_v2_selector_type,
391 NULL_TREE);
392 umsg_fixup_decl = add_builtin_function ("objc_msgSend_fixup",
393 type, 0, NOT_BUILT_IN,
394 NULL, NULL_TREE);
395 TREE_NOTHROW (umsg_fixup_decl) = 0;
397 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
398 umsg_stret_fixup_decl = add_builtin_function ("objc_msgSend_stret_fixup",
399 type, 0, NOT_BUILT_IN,
400 NULL, NULL_TREE);
401 TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
403 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
404 umsg_id_fixup_decl = add_builtin_function ("objc_msgSendId_fixup",
405 type, 0, NOT_BUILT_IN,
406 NULL, NULL_TREE);
407 TREE_NOTHROW (umsg_id_fixup_decl) = 0;
409 /* id objc_msgSendId_stret_fixup_rtp
410 (id, struct message_ref_t*, ...); */
411 umsg_id_stret_fixup_decl = add_builtin_function ("objc_msgSendId_stret_fixup",
412 type, 0, NOT_BUILT_IN,
413 NULL, NULL_TREE);
414 TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
416 /* id objc_msgSendSuper2_fixup_rtp
417 (struct objc_super *, struct message_ref_t*, ...); */
418 type = build_varargs_function_type_list (objc_object_type,
419 objc_super_type,
420 objc_v2_super_selector_type,
421 NULL_TREE);
422 umsg_id_super2_fixup_decl = add_builtin_function ("objc_msgSendSuper2_fixup",
423 type, 0, NOT_BUILT_IN,
424 NULL, NULL_TREE);
425 TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
427 /* id objc_msgSendSuper2_stret_fixup_rtp
428 (struct objc_super *, struct message_ref_t*, ...); */
429 umsg_id_super2_stret_fixup_decl =
430 add_builtin_function ("objc_msgSendSuper2_stret_fixup",
431 type, 0, NOT_BUILT_IN,
432 NULL, NULL_TREE);
433 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
435 /* Present in the library, but unused by the FE. */
436 /* Protocol *objc_getProtocol (const char *)
437 type = build_function_type_list (objc_protocol_type,
438 const_string_type_node,
439 NULL_TREE);
440 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
441 type, 0, NOT_BUILT_IN,
442 NULL, NULL_TREE);
443 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
445 UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
446 "_objc_empty_cache");
448 UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
449 "_objc_empty_vtable");
451 /* id objc_getClass (const char *); */
452 type = build_function_type_list (objc_object_type,
453 const_string_type_node,
454 NULL_TREE);
455 objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
456 type, 0, NOT_BUILT_IN,
457 NULL, NULL_TREE);
459 /* id objc_getMetaClass (const char *); */
460 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
461 type, 0, NOT_BUILT_IN,
462 NULL, NULL_TREE);
464 /* This is the type of all of the following functions
465 objc_copyStruct(). */
466 type = build_function_type_list (void_type_node,
467 ptr_type_node,
468 const_ptr_type_node,
469 ptrdiff_type_node,
470 boolean_type_node,
471 boolean_type_node,
472 NULL_TREE);
473 /* Declare the following function:
474 void
475 objc_copyStruct (void *destination, const void *source,
476 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
477 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
478 type, 0, NOT_BUILT_IN,
479 NULL, NULL_TREE);
480 TREE_NOTHROW (objc_copyStruct_decl) = 0;
481 objc_getPropertyStruct_decl = NULL_TREE;
482 objc_setPropertyStruct_decl = NULL_TREE;
484 gcc_assert (!flag_objc_sjlj_exceptions);
486 /* Although we warn that fobjc-exceptions is required for exceptions
487 code, we carry on and create it anyway. */
489 /* This can be required, even when exceptions code is not present,
490 when an __attribute__((objc_exception)) is applied to a
491 class. */
492 build_v2_ehtype_template ();
494 /* void * objc_begin_catch (void *) */
495 type = build_function_type_list (ptr_type_node,
496 ptr_type_node, NULL_TREE);
498 objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
499 type, 0, NOT_BUILT_IN,
500 NULL, NULL_TREE);
501 TREE_NOTHROW (objc2_begin_catch_decl) = 0;
503 /* void objc_end_catch () */
504 type = build_function_type_list (void_type_node, NULL_TREE);
505 objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
506 type, 0, NOT_BUILT_IN,
507 NULL, NULL_TREE);
508 TREE_NOTHROW (objc2_end_catch_decl) = 0;
510 /* void objc_exception_rethrow (void) */
511 objc_rethrow_exception_decl =
512 add_builtin_function ("objc_exception_rethrow",
513 type, 0, NOT_BUILT_IN,
514 NULL, NULL_TREE);
515 TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
516 using_eh_for_cleanups ();
517 lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
518 lang_hooks.eh_personality = objc_eh_personality;
521 /* NOTE --- templates --- */
523 /* Set 'objc_v2_message_ref_template' to the data type node for
524 'struct _message_ref_t'. This needs to be done just once per
525 compilation. Also Set 'objc_v2_super_message_ref_template' to data
526 type node for 'struct _super_message_ref_t'. */
528 /* struct _message_ref_t
530 IMP messenger;
531 SEL name;
533 where IMP is: id (*) (id, _message_ref_t*, ...)
536 /* struct _super_message_ref_t
538 SUPER_IMP messenger;
539 SEL name;
541 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
544 static void
545 build_v2_message_ref_templates (void)
547 tree ptr_message_ref_t;
548 tree decls, *chain = NULL;
550 /* struct _message_ref_t {...} */
551 objc_v2_message_ref_template =
552 objc_start_struct (get_identifier ("_message_ref_t"));
554 /* IMP messenger; */
555 ptr_message_ref_t =
556 build_pointer_type (xref_tag (RECORD_TYPE,
557 get_identifier ("_message_ref_t")));
559 objc_v2_imp_type =
560 build_pointer_type (build_function_type_list
561 (objc_object_type,
562 objc_object_type,
563 ptr_message_ref_t,
564 NULL_TREE));
566 decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
568 /* SEL name; */
569 add_field_decl (objc_selector_type, "name", &chain);
571 objc_finish_struct (objc_v2_message_ref_template, decls);
573 objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
575 chain = NULL;
576 /* struct _super_message_ref_t {...} */
577 objc_v2_super_message_ref_template =
578 objc_start_struct (get_identifier ("_super_message_ref_t"));
580 /* SUPER_IMP messenger; */
581 ptr_message_ref_t = build_pointer_type
582 (xref_tag (RECORD_TYPE,
583 get_identifier ("_super_message_ref_t")));
585 objc_v2_super_imp_type =
586 build_pointer_type (build_function_type_list
587 (objc_object_type,
588 objc_super_type,
589 ptr_message_ref_t,
590 NULL_TREE));
592 add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
594 /* SEL name; */
595 add_field_decl (objc_selector_type, "name", &chain);
597 objc_finish_struct (objc_v2_super_message_ref_template, decls);
598 objc_v2_super_selector_type =
599 build_pointer_type (objc_v2_super_message_ref_template);
602 /* Build following types which represent each class implementation.
604 struct class_ro_t
606 uint32_t const flags;
607 uint32_t const instanceStart;
608 uint32_t const instanceSize;
609 #ifdef __LP64__
610 uint32_t const reserved;
611 #endif
612 const uint8_t * const ivarLayout;
613 const char *const name;
614 const struct method_list_t * const baseMethods;
615 const struct objc_protocol_list *const baseProtocols;
616 const struct ivar_list_t *const ivars;
617 const uint8_t * const weakIvarLayout;
618 const struct _prop_list_t * const properties;
621 struct class_t
623 struct class_t *isa;
624 struct class_t *superclass;
625 void *cache;
626 IMP *vtable;
628 ...When this is active - it will point to a rw version, but
629 when we build the meta-data we point it to the ro...
630 struct class_ro_t *data;
635 static void
636 build_v2_class_templates (void)
638 tree cnst_strg_type;
639 tree decls, *chain = NULL;
641 /* struct class_ro_t {...} */
642 objc_v2_class_ro_template =
643 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
645 /* uint32_t const flags; */
646 decls = add_field_decl (integer_type_node, "flags", &chain);
648 /* uint32_t const instanceStart; */
649 add_field_decl (integer_type_node, "instanceStart", &chain);
651 /* uint32_t const instanceSize; */
652 add_field_decl (integer_type_node, "instanceSize", &chain);
654 /* This ABI is currently only used on m64 NeXT. We always
655 explicitly declare the alignment padding. */
656 /* uint32_t const reserved; */
657 add_field_decl (integer_type_node, "reserved", &chain);
659 /* const uint8_t * const ivarLayout; */
660 cnst_strg_type = build_pointer_type (unsigned_char_type_node);
661 add_field_decl (cnst_strg_type, "ivarLayout", &chain);
663 /* const char *const name; */
664 add_field_decl (string_type_node, "name", &chain);
666 /* const struct method_list_t * const baseMethods; */
667 add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
669 /* const struct objc_protocol_list *const baseProtocols; */
670 add_field_decl (build_pointer_type
671 (xref_tag (RECORD_TYPE,
672 get_identifier (UTAG_V2_PROTOCOL_LIST))),
673 "baseProtocols", &chain);
675 /* const struct ivar_list_t *const ivars; */
676 add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
678 /* const uint8_t * const weakIvarLayout; */
679 add_field_decl (cnst_strg_type, "weakIvarLayout", &chain);
681 /* struct _prop_list_t * baseProperties; */
682 add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
684 objc_finish_struct (objc_v2_class_ro_template, decls);
686 chain = NULL;
687 /* struct class_t {...} */
688 objc_v2_class_template =
689 objc_start_struct (get_identifier (UTAG_V2_CLASS));
691 /* struct class_t *isa; */
692 decls = add_field_decl (build_pointer_type (objc_v2_class_template),
693 "isa", &chain);
695 /* struct class_t * const superclass; */
696 add_field_decl (build_pointer_type (objc_v2_class_template),
697 "superclass", &chain);
699 /* void *cache; */
700 add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
702 /* IMP *vtable; */
703 add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
705 /* struct class_ro_t *ro; */
706 add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
708 objc_finish_struct (objc_v2_class_template, decls);
711 /* struct _objc_super
713 struct _objc_object *self;
714 Class cls;
715 }; */
716 void
717 build_v2_super_template (void)
719 tree decls, *chain = NULL;
721 objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
723 /* struct _objc_object *self; */
724 decls = add_field_decl (objc_object_type, "self", &chain);
726 /* Class cls; */
727 add_field_decl (objc_class_type, "cls", &chain);
729 objc_finish_struct (objc_super_template, decls);
732 /* struct protocol_t
734 Class isa;
735 const char * const protocol_name;
736 const struct protocol_list_t * const protocol_list;
737 const struct method_list_t * const instance_methods;
738 const struct method_list_t * const class_methods;
739 const struct method_list_t * optionalInstanceMethods;
740 const struct method_list_t * optionalClassMethod
741 const struct _prop_list_t * const properties;
742 const uint32_t size;
743 const uint32_t flags;
746 static void
747 build_v2_protocol_template (void)
749 tree decls, *chain = NULL;
751 objc_v2_protocol_template =
752 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
754 /* Class isa; */
755 decls = add_field_decl (objc_object_type, "isa", &chain);
757 /* char *protocol_name; */
758 add_field_decl (string_type_node, "protocol_name", &chain);
760 /* const struct protocol_list_t * const protocol_list; */
761 add_field_decl (build_pointer_type (objc_v2_protocol_template),
762 "protocol_list", &chain);
764 /* const struct method_list_t * const instance_methods; */
765 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
767 /* const struct method_list_t * const class_methods; */
768 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
770 /* const struct method_list_t * optionalInstanceMethods; */
771 add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
773 /* const struct method_list_t * optionalClassMethods; */
774 add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
776 /* struct _prop_list_t * properties; */
777 add_field_decl (objc_prop_list_ptr, "properties", &chain);
779 /* const uint32_t size; */
780 add_field_decl (integer_type_node, "size", &chain);
782 /* const uint32_t flags; */
783 add_field_decl (integer_type_node, "flags", &chain);
785 objc_finish_struct (objc_v2_protocol_template, decls);
788 /* Build type for a category:
789 struct category_t
791 const char * const name;
792 struct class_t *const cls;
793 const struct method_list_t * const instance_methods;
794 const struct method_list_t * const class_methods;
795 const struct protocol_list_t * const protocols;
796 const struct _prop_list_t * const properties;
800 static void
801 build_v2_category_template (void)
803 tree decls, *chain = NULL;
805 objc_v2_category_template =
806 objc_start_struct (get_identifier ("_category_t"));
808 /* char *name; */
809 decls = add_field_decl (string_type_node, "name", &chain);
811 /* struct class_t *const cls; */
812 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
814 /* struct method_list_t *instance_methods; */
815 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
817 /* struct method_list_t *class_methods; */
818 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
820 /* struct protocol_list_t *protocol_list; */
821 add_field_decl (build_pointer_type (objc_v2_protocol_template),
822 "protocol_list", &chain );
824 /* struct _prop_list_t * properties; */
825 add_field_decl (objc_prop_list_ptr, "properties", &chain);
827 objc_finish_struct (objc_v2_category_template, decls);
830 /* NOTE --- Decls, Identifiers, Names etc. --- */
832 /* This routine is given a name and returns a matching extern variable
833 if one is found. */
835 static tree
836 hash_name_lookup (hash *hashlist, tree name)
838 hash target;
840 target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
842 while (target)
844 if (name == DECL_NAME (target->key))
845 return target->key;
847 target = target->next;
849 return 0;
852 /* This routine is given an extern variable and enters it in its hash
853 table. Note that hashing is done on its inner IDENTIFIER_NODE
854 node. */
856 static void
857 hash_name_enter (hash *hashlist, tree id)
859 hash obj;
860 int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
862 obj = ggc_alloc<hashed_entry> ();
863 obj->list = 0;
864 obj->next = hashlist[slot];
865 obj->key = id;
867 hashlist[slot] = obj; /* append to front */
870 /* Create a declaration "extern <type> <name>;"
871 The var will need to be finalized (e.g. by calling finish_var_decl()). */
873 static tree
874 create_extern_decl (tree type, const char *name)
876 tree id = get_identifier (name);
877 tree var = hash_name_lookup (extern_names, id);
878 if (var)
879 return var;
880 /* New name. */
881 var = start_var_decl (type, name);
882 TREE_STATIC (var) = 0;
883 DECL_EXTERNAL (var) = 1;
884 TREE_PUBLIC (var) = 1;
885 hash_name_enter (extern_names, var);
886 return var;
889 /* Create a globally visible definition for variable NAME of a given TYPE. The
890 finish_var_decl() routine will need to be called on it afterwards. */
892 static tree
893 create_global_decl (tree type, const char *name)
895 tree id = get_identifier (name);
896 tree var = hash_name_lookup (extern_names, id);
897 if (var)
899 DECL_EXTERNAL (var) = 0;
900 TREE_STATIC (var) = 1;
902 else
904 var = start_var_decl (type, name);
905 hash_name_enter (extern_names, var);
907 TREE_PUBLIC (var) = 1;
908 return var;
911 /* Create a symbol with __attribute__ ((visibility ("hidden")))
912 attribute (private extern). */
914 static tree
915 create_hidden_decl (tree type, const char *name)
917 tree decl = create_global_decl (type, name);
918 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
919 DECL_VISIBILITY_SPECIFIED (decl) = 1;
920 return decl;
923 /* Irritatingly, we have a different superclass field name for ABI=2. */
924 /* PS/TODO: The field name does not matter, it is only used internally
925 by the compiler. We can rename it to whatever we want. ;-) */
927 static tree
928 next_runtime_abi_02_super_superclassfield_id (void)
930 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
931 most look it once at startup then always return it. */
932 if (!super_superclassfield_id)
933 super_superclassfield_id = get_identifier ("cls");
934 return super_superclassfield_id;
937 static tree
938 next_runtime_abi_02_class_decl (tree klass)
940 tree decl;
941 char buf[BUFSIZE];
942 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
943 IDENTIFIER_POINTER (CLASS_NAME (klass)));
944 /* ObjC2 classes are extern visible. */
945 decl = create_global_decl (objc_v2_class_template, buf);
946 OBJCMETA (decl, objc_meta, meta_class);
947 return decl;
950 static tree
951 next_runtime_abi_02_metaclass_decl (tree klass)
953 tree decl;
954 char buf[BUFSIZE];
955 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
956 IDENTIFIER_POINTER (CLASS_NAME (klass)));
957 /* ObjC2 classes are extern visible. */
958 decl = create_global_decl (objc_v2_class_template, buf);
959 OBJCMETA (decl, objc_meta, meta_metaclass);
960 return decl;
963 static tree
964 next_runtime_abi_02_category_decl (tree klass)
966 tree decl;
967 char buf[BUFSIZE];
968 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
969 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
970 IDENTIFIER_POINTER (CLASS_NAME (klass)));
971 decl = start_var_decl (objc_v2_category_template, buf);
972 OBJCMETA (decl, objc_meta, meta_category);
973 return decl;
976 static tree
977 next_runtime_abi_02_protocol_decl (tree p)
979 tree decl;
980 char buf[BUFSIZE];
982 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
983 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
984 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
985 decl = start_var_decl (objc_v2_protocol_template, buf);
986 OBJCMETA (decl, objc_meta, meta_protocol);
987 return decl;
990 static tree
991 next_runtime_abi_02_string_decl (tree type, const char *name, string_section where)
993 tree var = start_var_decl (type, name);
994 switch (where)
996 case class_names:
997 OBJCMETA (var, objc_meta, meta_class_name);
998 break;
999 case meth_var_names:
1000 OBJCMETA (var, objc_meta, meta_meth_name);
1001 break;
1002 case meth_var_types:
1003 OBJCMETA (var, objc_meta, meta_meth_type);
1004 break;
1005 case prop_names_attr:
1006 OBJCMETA (var, objc_meta, meta_prop_name_attr);
1007 break;
1008 default:
1009 OBJCMETA (var, objc_meta, meta_base);
1010 break;
1012 return var;
1015 /* NOTE --- entry --- */
1017 struct GTY(()) ident_data_tuple {
1018 tree ident;
1019 tree data;
1022 /* This routine creates a file scope static variable of type 'Class'
1023 to hold the address of a class. */
1025 static tree
1026 build_v2_class_reference_decl (tree ident)
1028 tree decl;
1029 char buf[BUFSIZE];
1031 snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1032 decl = start_var_decl (objc_class_type, buf);
1033 OBJCMETA (decl, objc_meta, meta_class_ref);
1034 return decl;
1037 /* This routine builds a class refs entry for each class name used.
1038 Initially, a (static-ref, IDENT) tuple is added to the list. The
1039 ident is replaced with address of the class metadata (of type
1040 'Class') in the output routine. */
1042 static GTY (()) vec<ident_data_tuple, va_gc> *classrefs;
1044 static tree
1045 objc_v2_get_class_reference (tree ident)
1047 tree decl;
1048 ident_data_tuple e;
1049 if (classrefs)
1051 int count;
1052 ident_data_tuple *ref;
1053 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1055 if (ref->ident == ident)
1057 if (!ref->data)
1058 ref->data = build_v2_class_reference_decl (ident);
1059 return ref->data;
1063 else
1064 /* Somewhat arbitrary initial provision. */
1065 vec_alloc (classrefs, 16);
1067 /* We come here if we don't find the entry - or if the table was yet
1068 to be created. */
1069 decl = build_v2_class_reference_decl (ident);
1070 e.ident = ident;
1071 e.data = decl;
1072 vec_safe_push (classrefs, e);
1073 return decl;
1076 static tree
1077 next_runtime_abi_02_get_class_reference (tree ident)
1079 if (!flag_zero_link)
1080 return objc_v2_get_class_reference (ident);
1081 else
1083 /* We fall back to using objc_getClass (). */
1084 vec<tree, va_gc> *v;
1085 vec_alloc (v, 1);
1086 tree t;
1087 /* ??? add_class_reference (ident); - is pointless, since the
1088 system lib does not export the equivalent symbols. Maybe we
1089 need to build a class ref anyway. */
1090 t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1091 IDENTIFIER_POINTER (ident));
1092 v->quick_push (t);
1093 t = build_function_call_vec (input_location, vNULL, objc_get_class_decl,
1094 v, 0);
1095 vec_free (v);
1096 return t;
1100 /* Used by build_function_type_for_method. Append the types for
1101 receiver & _cmd at the start of a method argument list to ARGTYPES.
1102 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1103 trying to define a method or call one. SUPERFLAG says this is for a
1104 send to super. METH may be NULL, in the case that there is no
1105 prototype. */
1107 static void
1108 next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1109 tree meth, int context,
1110 int superflag)
1112 tree receiver_type;
1114 if (superflag)
1115 receiver_type = objc_super_type;
1116 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1117 receiver_type = objc_instance_type;
1118 else
1119 receiver_type = objc_object_type;
1121 vec_safe_push (*argtypes, receiver_type);
1122 /* Selector type - will eventually change to `int'. */
1123 vec_safe_push (*argtypes,
1124 superflag ? objc_v2_super_selector_type
1125 : objc_v2_selector_type);
1128 /* TODO: Merge this with the message refs. */
1129 static tree
1130 build_selector_reference_decl (tree ident)
1132 tree decl;
1133 char *t, buf[BUFSIZE];
1135 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1136 t = buf;
1137 while (*t)
1139 if (*t==':')
1140 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1141 t++;
1143 decl = start_var_decl (objc_selector_type, buf);
1144 OBJCMETA (decl, objc_meta, meta_sel_refs);
1145 return decl;
1148 static tree
1149 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1150 tree ident,
1151 tree proto ATTRIBUTE_UNUSED)
1153 tree *chain = &sel_ref_chain;
1154 tree expr;
1156 while (*chain)
1158 if (TREE_VALUE (*chain) == ident)
1159 return TREE_PURPOSE (*chain);
1161 chain = &TREE_CHAIN (*chain);
1164 expr = build_selector_reference_decl (ident);
1165 *chain = tree_cons (expr, ident, NULL_TREE);
1167 return expr;
1170 /* Declare a variable of type 'struct message_ref_t'. */
1171 /* This will be finished in build_v2_message_ref_translation_table ().
1172 We take an idea from LLVM in making the names a bit more connected
1173 and thus the asm more readable. */
1175 static tree
1176 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1178 tree decl;
1179 char buf[BUFSIZE], *t;
1180 int offset = 12;
1182 /* Skip past the objc_msgSend it's the same for all... */
1183 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1184 offset++;
1186 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1187 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1188 IDENTIFIER_POINTER (sel_name));
1189 t = buf;
1190 while (*t)
1192 if (*t==':')
1193 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1194 t++;
1196 decl = start_var_decl (objc_v2_message_ref_template, buf);
1197 OBJCMETA (decl, objc_meta, meta_mref);
1198 return decl;
1201 struct GTY(()) msgref_entry {
1202 tree func;
1203 tree selname;
1204 tree refdecl;
1207 static GTY (()) vec<msgref_entry, va_gc> *msgrefs;
1209 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1210 later on to initialize the table of 'struct message_ref_t'
1211 elements. */
1213 static tree
1214 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1216 tree decl;
1217 msgref_entry e;
1218 if (msgrefs)
1220 int count;
1221 msgref_entry *ref;
1222 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1223 if (ref->func == message_func_decl && ref->selname == sel_name)
1224 return ref->refdecl;
1226 else
1227 /* Somewhat arbitrary initial provision. */
1228 vec_alloc (msgrefs, 32);
1230 /* We come here if we don't find a match or at the start. */
1231 decl = build_v2_message_reference_decl (sel_name,
1232 DECL_NAME (message_func_decl));
1233 e.func = message_func_decl;
1234 e.selname = sel_name;
1235 e.refdecl = decl;
1236 vec_safe_push (msgrefs, e);
1237 return decl;
1240 static tree
1241 build_v2_protocollist_ref_decl (tree protocol)
1243 tree decl;
1244 tree protocol_ident = PROTOCOL_NAME (protocol);
1245 char buf[BUFSIZE];
1247 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1248 IDENTIFIER_POINTER (protocol_ident));
1249 /* TODO: other compiler versions make these hidden & weak. */
1250 decl = create_global_decl (objc_protocol_type, buf);
1251 /* Let optimizer know that this decl is not removable. */
1252 DECL_PRESERVE_P (decl) = 1;
1253 OBJCMETA (decl, objc_meta, meta_proto_ref);
1254 return decl;
1257 struct GTY(()) prot_list_entry {
1258 tree id;
1259 tree refdecl;
1261 static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
1263 static tree
1264 objc_v2_get_protocol_reference (tree ident)
1266 tree decl;
1267 prot_list_entry e;
1268 if (protrefs)
1270 int count;
1271 prot_list_entry *ref;
1272 FOR_EACH_VEC_ELT (*protrefs, count, ref)
1274 if (ref->id == ident)
1276 if (!ref->refdecl)
1277 ref->refdecl = build_v2_protocollist_ref_decl (ident);
1278 return ref->refdecl;
1282 else
1283 /* Somewhat arbitrary initial provision. */
1284 vec_alloc (protrefs, 32);
1286 /* We come here if we don't find the entry - or if the table was yet
1287 to be created. */
1288 decl = build_v2_protocollist_ref_decl (ident);
1289 e.id = ident;
1290 e.refdecl = decl;
1291 vec_safe_push (protrefs, e);
1292 return decl;
1295 static tree
1296 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1297 tree p)
1299 if (!PROTOCOL_FORWARD_DECL (p))
1300 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1302 return objc_v2_get_protocol_reference (p);
1305 /* This routine returns the ivar declaration, if component is a valid
1306 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1307 returns the class name in CLASS. */
1309 static tree
1310 objc_is_ivar (tree expr, tree component, tree *klass)
1312 tree field = NULL_TREE;
1313 tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1315 if (TREE_CODE (basetype) == RECORD_TYPE
1316 && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1318 *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1319 if (*klass)
1323 tree ivar_chain = CLASS_RAW_IVARS (*klass);
1324 if (ivar_chain)
1326 field = is_ivar (ivar_chain, component);
1327 if (field != NULL_TREE)
1328 break;
1330 *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1332 while (*klass);
1335 return field;
1338 static void
1339 create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1341 tree fname = DECL_NAME (field_decl);
1343 sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1344 IDENTIFIER_POINTER (fname));
1345 return;
1348 /* This routine generates new abi's ivar reference tree. It amounts
1349 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1350 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1351 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1353 static tree
1354 objc_v2_build_ivar_ref (tree datum, tree component)
1356 tree field, ref, class_name, offset, ftype, expr;
1357 char var_offset_name[512];
1359 field = objc_is_ivar (datum, component, &class_name);
1360 if (!field)
1361 return NULL_TREE;
1363 /* This routine only handles non-bitfield fields */
1364 /* DECL_INITIAL macro is set to width of bitfield and can be relied
1365 on to check for bitfield ivars. Note that I cannot rely on
1366 DECL_BIT_FIELD macro because it is only set when the whole struct
1367 is seen (at finish_struct) and not when the ivar chain is
1368 built. */
1369 if (DECL_INITIAL (field))
1370 return NULL_TREE;
1372 create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field);
1374 offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1376 ftype = TREE_TYPE (field);
1378 /* (char*)datum */
1379 expr = build_c_cast (input_location,
1380 string_type_node, build_fold_addr_expr (datum));
1382 /* (char*)datum + offset */
1383 expr = fold_build_pointer_plus_loc (input_location, expr, offset);
1385 /* (ftype*)((char*)datum + offset) */
1386 expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1388 /* Finally: *(ftype*)((char*)datum + offset) */
1389 ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1391 /* We must set type of the resulting expression to be the same as
1392 the field type. This is because, build_indirect_ref (...)
1393 rebuilds the type which may result in lost information; as in the
1394 case of protocol-qualified types (id <protocol> ). */
1395 TREE_TYPE (ref) = ftype;
1397 if (TREE_READONLY (datum) || TREE_READONLY (field))
1398 TREE_READONLY (ref) = 1;
1400 if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1401 TREE_THIS_VOLATILE (ref) = 1;
1403 if (TREE_DEPRECATED (field))
1404 warn_deprecated_use (field, NULL_TREE);
1406 return ref;
1409 /* IVAR refs are made via an externally referenceable offset and built
1410 on the fly. That is, unless they refer to (private) fields in the
1411 class structure. */
1412 static tree
1413 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1414 tree base, tree id)
1416 tree ivar;
1417 if ((ivar = objc_v2_build_ivar_ref (base, id)))
1418 return ivar;
1419 return objc_build_component_ref (base, id);
1422 /* [super ...] references are listed here (and built into a table at
1423 meta -data emit time). */
1424 static tree
1425 build_v2_superclass_ref_decl (tree ident, bool inst)
1427 tree decl;
1428 char buf[BUFSIZE];
1430 snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1431 IDENTIFIER_POINTER (ident));
1432 decl = start_var_decl (objc_class_type, buf);
1433 OBJCMETA (decl, objc_meta, meta_superclass_ref);
1434 return decl;
1437 static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs;
1438 static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs;
1440 static tree
1441 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1442 struct imp_entry *imp, bool inst_meth)
1444 tree decl;
1445 ident_data_tuple e;
1446 tree id = CLASS_NAME (imp->imp_context);
1447 vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs
1448 : metaclass_super_refs;
1450 if (list)
1452 int count;
1453 ident_data_tuple *ref;
1454 FOR_EACH_VEC_ELT (*list, count, ref)
1456 if (ref->ident == id)
1458 if (!ref->data)
1459 ref->data = build_v2_superclass_ref_decl (id, inst_meth);
1460 return ref->data;
1464 else
1466 /* Somewhat arbitrary initial provision. */
1467 if (inst_meth)
1469 vec_alloc (class_super_refs, 16);
1470 list = class_super_refs;
1472 else
1474 vec_alloc (metaclass_super_refs, 16);
1475 list = metaclass_super_refs;
1478 /* We come here if we don't find the entry - or if the table was yet
1479 to be created. */
1480 decl = build_v2_superclass_ref_decl (id, inst_meth);
1481 e.ident = id;
1482 e.data = decl;
1483 vec_safe_push (list, e);
1484 return decl;
1487 static tree
1488 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1489 struct imp_entry *imp, bool inst_meth)
1491 /* ??? is this OK when zero-link = true? */
1492 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1493 tree super_class;
1495 if (!flag_zero_link)
1497 super_class = objc_get_class_reference (CLASS_NAME (imp->imp_template));
1499 if (!inst_meth)
1501 /* If we are in a class method, we must retrieve the
1502 _metaclass_ for the current class, pointed at by the
1503 class's "isa" pointer. The following assumes that "isa" is
1504 the first ivar in a class (which it must be). */
1505 super_class =
1506 build_indirect_ref (input_location,
1507 build_c_cast (input_location,
1508 build_pointer_type (objc_class_type),
1509 super_class),
1510 RO_UNARY_STAR);
1511 return super_class;
1513 /* ??? Do we need to add the class ref anway for zero-link? */
1514 /* else do it the slow way. */
1515 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
1516 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1517 IDENTIFIER_POINTER (super_name));
1518 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1519 return build_function_call (input_location,
1520 super_class,
1521 build_tree_list (NULL_TREE, super_name));
1524 static tree
1525 next_runtime_abi_02_receiver_is_class_object (tree receiver)
1527 if (TREE_CODE (receiver) == VAR_DECL
1528 && IS_CLASS (TREE_TYPE (receiver))
1529 && vec_safe_length (classrefs))
1531 int count;
1532 ident_data_tuple *ref;
1533 /* The receiver is a variable created by build_class_reference_decl. */
1534 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1535 if (ref->data == receiver)
1536 return ref->ident;
1538 return NULL_TREE;
1541 /* Assign all arguments in VALUES which have side-effect to a temporary
1542 and replaced that argument in VALUES list with the temporary. The
1543 arguments will be passed to a function with FNTYPE. */
1545 static tree
1546 objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1548 tree valtail;
1549 function_args_iterator iter;
1551 /* Skip over receiver and the &_msf_ref types. */
1552 function_args_iter_init (&iter, fntype);
1553 function_args_iter_next (&iter);
1554 function_args_iter_next (&iter);
1556 for (valtail = values; valtail;
1557 valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
1559 tree value = TREE_VALUE (valtail);
1560 tree type = function_args_iter_cond (&iter);
1561 if (type == NULL_TREE)
1562 break;
1563 if (!TREE_SIDE_EFFECTS (value))
1564 continue;
1565 /* To prevent re-evaluation. */
1566 value = save_expr (value);
1567 add_stmt (value);
1568 TREE_VALUE (valtail) = value;
1570 return values;
1573 /* Build the new abi's messaging library call. It looks like:
1574 (*_msg.messenger) (receiver, &_msg, ...) */
1576 static tree
1577 build_v2_build_objc_method_call (int super_flag, tree method_prototype,
1578 tree lookup_object, tree selector,
1579 tree method_params,
1580 bool check_for_nil)
1582 tree ret_val;
1583 tree sender, rcv_p, t;
1584 tree ret_type
1585 = (method_prototype
1586 ? TREE_VALUE (TREE_TYPE (method_prototype))
1587 : objc_object_type);
1588 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1589 METHOD_REF, super_flag);
1590 tree sender_cast;
1592 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1593 ftype = build_type_attribute_variant (
1594 ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1596 sender_cast = build_pointer_type (ftype);
1598 if (check_for_nil)
1599 method_params = objc_copy_to_temp_side_effect_params (ftype,
1600 method_params);
1602 /* Get &message_ref_t.messenger. */
1603 sender = build_c_cast (input_location,
1604 build_pointer_type (super_flag
1605 ? objc_v2_super_imp_type
1606 : objc_v2_imp_type),
1607 selector);
1609 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1611 rcv_p = (super_flag ? objc_super_type : objc_object_type);
1613 lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1615 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1616 lookup_object = save_expr (lookup_object);
1618 method_params = tree_cons (NULL_TREE, lookup_object,
1619 tree_cons (NULL_TREE, selector,
1620 method_params));
1621 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
1622 ret_val = build_function_call (input_location, t, method_params);
1623 if (check_for_nil)
1625 /* receiver != nil ? ret_val : 0 */
1626 tree ftree;
1627 tree ifexp;
1629 if (TREE_CODE (ret_type) == RECORD_TYPE
1630 || TREE_CODE (ret_type) == UNION_TYPE)
1632 vec<constructor_elt, va_gc> *rtt = NULL;
1633 /* ??? CHECKME. hmmm..... think we need something more
1634 here. */
1635 CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE);
1636 ftree = objc_build_constructor (ret_type, rtt);
1638 else
1639 ftree = fold_convert (ret_type, integer_zero_node);
1641 ifexp = build_binary_op (input_location, NE_EXPR,
1642 lookup_object,
1643 fold_convert (rcv_p, integer_zero_node), 1);
1645 #ifdef OBJCPLUS
1646 ret_val = build_conditional_expr (input_location,
1647 ifexp, ret_val, ftree,
1648 tf_warning_or_error);
1649 #else
1650 /* ??? CHECKME. */
1651 ret_val = build_conditional_expr (input_location,
1652 ifexp, 1,
1653 ret_val, NULL_TREE,
1654 ftree, NULL_TREE);
1655 #endif
1657 return ret_val;
1660 static tree
1661 next_runtime_abi_02_build_objc_method_call (location_t loc,
1662 tree method_prototype,
1663 tree receiver,
1664 tree rtype,
1665 tree sel_name,
1666 tree method_params,
1667 int super)
1669 tree ret_type, selector;
1670 tree message_func_decl;
1671 bool check_for_nil = flag_objc_nilcheck;
1673 ret_type = method_prototype
1674 ? TREE_VALUE (TREE_TYPE (method_prototype))
1675 : objc_object_type;
1677 /* Do we need to check for nil receivers ? */
1678 /* For now, message sent to classes need no nil check. In the
1679 future, class declaration marked as weak_import must be nil
1680 checked. */
1681 if (super
1682 || (TREE_CODE (receiver) == VAR_DECL
1683 && TREE_TYPE (receiver) == objc_class_type))
1684 check_for_nil = false;
1686 if (!targetm.calls.struct_value_rtx (0, 0)
1687 && (TREE_CODE (ret_type) == RECORD_TYPE
1688 || TREE_CODE (ret_type) == UNION_TYPE)
1689 && targetm.calls.return_in_memory (ret_type, 0))
1691 if (super)
1692 message_func_decl = umsg_id_super2_stret_fixup_decl;
1693 else
1694 message_func_decl = objc_is_id (rtype)
1695 ? umsg_id_stret_fixup_decl
1696 : umsg_stret_fixup_decl;
1698 else
1700 if (super)
1701 message_func_decl = umsg_id_super2_fixup_decl;
1702 else
1703 message_func_decl = objc_is_id (rtype)
1704 ? umsg_id_fixup_decl
1705 : umsg_fixup_decl;
1708 selector = build_v2_selector_messenger_reference (sel_name,
1709 message_func_decl);
1711 /* selector = &_msg; */
1712 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1714 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1715 : objc_v2_selector_type),
1716 selector);
1718 /* (*_msg.messenger) (receiver, &_msg, ...); */
1719 return build_v2_build_objc_method_call (super, method_prototype,
1720 receiver, selector,
1721 method_params, check_for_nil);
1724 /* NOTE --- Constant String Class Stuff --- */
1726 static bool
1727 next_runtime_abi_02_setup_const_string_class_decl (void)
1729 if (!constant_string_global_id)
1731 /* Hopefully, this should not represent a serious limitation. */
1732 char buf[BUFSIZE];
1733 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1734 constant_string_global_id = get_identifier (buf);
1737 string_class_decl = lookup_name (constant_string_global_id);
1739 /* In OBJC2 abi, constant string class reference refers to class
1740 name for NSConstantString class. This declaration may not be
1741 available yet (in fact it is not in most cases). So, declare an
1742 extern OBJC_CLASS_$_NSConstantString in its place. */
1743 if (!string_class_decl)
1744 string_class_decl =
1745 create_extern_decl (objc_v2_class_template,
1746 IDENTIFIER_POINTER (constant_string_global_id));
1748 return (string_class_decl != NULL_TREE);
1751 static tree
1752 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1753 int length)
1755 tree constructor, fields, var;
1756 vec<constructor_elt, va_gc> *v = NULL;
1758 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1759 fields = TYPE_FIELDS (internal_const_str_type);
1760 CONSTRUCTOR_APPEND_ELT (v, fields,
1761 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1763 fields = DECL_CHAIN (fields);
1764 CONSTRUCTOR_APPEND_ELT (v, fields,
1765 build_unary_op (loc, ADDR_EXPR, string, 1));
1767 /* ??? check if this should be long. */
1768 fields = DECL_CHAIN (fields);
1769 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1770 constructor = objc_build_constructor (internal_const_str_type, v);
1772 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1773 DECL_INITIAL (var) = constructor;
1774 TREE_STATIC (var) = 1;
1775 DECL_CONTEXT (var) = NULL;
1776 OBJCMETA (var, objc_meta, meta_const_str);
1777 return var;
1780 /* NOTE --- NeXT V2 Metadata templates --- */
1782 /* This routine builds the following type:
1783 struct _prop_t
1785 const char * const name; // property name
1786 const char * const attributes; // comma-delimited, encoded,
1787 // property attributes
1791 static tree
1792 build_v2_property_template (void)
1794 tree prop_record;
1795 tree decls, *chain = NULL;
1797 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1798 /* const char * name */
1799 decls = add_field_decl (string_type_node, "name", &chain);
1801 /* const char * attribute */
1802 add_field_decl (string_type_node, "attribute", &chain);
1804 objc_finish_struct (prop_record, decls);
1805 return prop_record;
1808 /* struct ivar_t
1810 unsigned long int *offset;
1811 char *name;
1812 char *type;
1813 uint32_t alignment;
1814 uint32_t size;
1818 static tree
1819 build_v2_ivar_t_template (void)
1821 tree objc_ivar_id, objc_ivar_record;
1822 tree decls, *chain = NULL;
1824 objc_ivar_id = get_identifier ("_ivar_t");
1825 objc_ivar_record = objc_start_struct (objc_ivar_id);
1827 /* unsigned long int *offset; */
1828 decls = add_field_decl (build_pointer_type
1829 (TREE_TYPE (size_zero_node)), "offset", &chain);
1831 /* char *name; */
1832 add_field_decl (string_type_node, "name", &chain);
1834 /* char *type; */
1835 add_field_decl (string_type_node, "type", &chain);
1837 /* uint32_t alignment; */
1838 add_field_decl (integer_type_node, "alignment", &chain);
1840 /* uint32_t size; */
1841 add_field_decl (integer_type_node, "size", &chain);
1843 objc_finish_struct (objc_ivar_record, decls);
1844 return objc_ivar_record;
1847 static void
1848 build_metadata_templates (void)
1851 if (!objc_method_template)
1852 objc_method_template = build_method_template ();
1854 if (!objc_v2_property_template)
1855 objc_v2_property_template = build_v2_property_template ();
1857 if (!objc_v2_ivar_template)
1858 objc_v2_ivar_template = build_v2_ivar_t_template ();
1862 /* NOTE --- Output NeXT V2 Metadata --- */
1864 /* Routine builds name of Interface's main meta-data of type class_t. */
1866 static char *
1867 objc_build_internal_classname (tree ident, bool metaclass)
1869 static char string[512];
1870 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
1871 : "OBJC_CLASS_$",
1872 IDENTIFIER_POINTER (ident));
1873 return string;
1876 /* Build the name for object of type struct class_ro_t */
1878 static const char *
1879 newabi_append_ro (const char *name)
1881 const char *dollar;
1882 char *p;
1883 static char string[BUFSIZE];
1884 dollar = strchr (name, '$');
1885 gcc_assert (dollar);
1886 p = string;
1887 *p = '_'; p++;
1888 strncpy (p, name, (int)(dollar - name));
1889 p += (int)(dollar - name);
1890 sprintf (p, "RO_%s", dollar);
1891 return string;
1894 /* Build the struct message_ref_t msg =
1895 {objc_msgSend_fixup_xxx, @selector(func)}
1896 table. */
1898 static
1899 void build_v2_message_ref_translation_table (void)
1901 int count;
1902 msgref_entry *ref;
1904 if (!vec_safe_length (msgrefs))
1905 return;
1907 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1909 vec<constructor_elt, va_gc> *initializer;
1910 tree expr, constructor;
1911 tree struct_type = TREE_TYPE (ref->refdecl);
1912 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
1914 initializer = NULL;
1915 /* First 'IMP messenger' field... */
1916 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
1917 expr = convert (objc_v2_imp_type, expr);
1918 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1920 /* ... then 'SEL name' field. */
1921 expr = build_selector (ref->selname);
1922 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1923 constructor = objc_build_constructor (struct_type, initializer);
1924 finish_var_decl (ref->refdecl, constructor);
1928 /* Build decl = initializer; for each externally visible class
1929 reference. */
1931 static void
1932 build_v2_classrefs_table (void)
1934 int count;
1935 ident_data_tuple *ref;
1937 if (!vec_safe_length (classrefs))
1938 return;
1940 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1942 tree expr = ref->ident;
1943 tree decl = ref->data;
1944 /* Interface with no implementation and yet one of its messages
1945 has been used. Need to generate a full address-of tree for it
1946 here. */
1947 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1949 const char *name = objc_build_internal_classname (expr, false);
1950 expr = create_extern_decl (objc_v2_class_template, name);
1951 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1953 /* The runtime wants this, even if it appears unused, so we must force the
1954 output.
1955 DECL_PRESERVE_P (decl) = 1; */
1956 finish_var_decl (decl, expr);
1960 /* Build decl = initializer; for each externally visible super class
1961 reference. */
1963 static void
1964 build_v2_super_classrefs_table (bool metaclass)
1966 int count;
1967 ident_data_tuple *ref;
1968 vec<ident_data_tuple, va_gc> *list = metaclass ? metaclass_super_refs
1969 : class_super_refs;
1971 if (!vec_safe_length (list))
1972 return;
1974 FOR_EACH_VEC_ELT (*list, count, ref)
1976 tree expr = ref->ident;
1977 tree decl = ref->data;
1978 /* Interface with no implementation and yet one of its messages
1979 has been used. Need to generate a full address-of tree for it
1980 here. */
1981 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1983 const char * name = objc_build_internal_classname (expr, metaclass);
1984 expr = create_extern_decl (objc_v2_class_template, name);
1985 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1987 finish_var_decl (decl, expr);
1991 /* Add the global class meta-data declaration to the list which later
1992 on ends up in the __class_list section. */
1994 static GTY(()) vec<tree, va_gc> *class_list;
1996 static void
1997 objc_v2_add_to_class_list (tree global_class_decl)
1999 vec_safe_push (class_list, global_class_decl);
2002 static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
2004 /* Add the global class meta-data declaration to the list which later
2005 on ends up in the __nonlazy_class section. */
2007 static void
2008 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2010 vec_safe_push (nonlazy_class_list, global_class_decl);
2013 static GTY(()) vec<tree, va_gc> *category_list;
2015 /* Add the category meta-data declaration to the list which later on
2016 ends up in the __nonlazy_category section. */
2018 static void
2019 objc_v2_add_to_category_list (tree decl)
2021 vec_safe_push (category_list, decl);
2024 static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
2026 /* Add the category meta-data declaration to the list which later on
2027 ends up in the __category_list section. */
2029 static void
2030 objc_v2_add_to_nonlazy_category_list (tree decl)
2032 vec_safe_push (nonlazy_category_list, decl);
2035 static bool
2036 has_load_impl (tree clsmeth)
2038 while (clsmeth)
2040 tree id = METHOD_SEL_NAME (clsmeth);
2041 if (IDENTIFIER_LENGTH (id) == 4
2042 && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
2043 return true;
2044 clsmeth = DECL_CHAIN (clsmeth);
2047 return false;
2050 /* Build a __{class,category}_list section table containing address of
2051 all @implemented {class,category} meta-data. */
2053 static void
2054 build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
2056 int count=0;
2057 tree type, decl, expr;
2058 vec<constructor_elt, va_gc> *initlist = NULL;
2060 if (!vec_safe_length (src))
2061 return;
2063 FOR_EACH_VEC_ELT (*src, count, decl)
2065 #ifndef OBJCPLUS
2066 tree purpose = build_int_cst (NULL_TREE, count);
2067 #else
2068 tree purpose = NULL_TREE;
2069 #endif
2070 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2071 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2073 gcc_assert (count > 0);
2074 type = build_array_type (objc_class_type,
2075 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2076 decl = start_var_decl (type, nam);
2077 /* The runtime wants this, even if it appears unused, so we must
2078 force the output. */
2079 DECL_PRESERVE_P (decl) = 1;
2080 expr = objc_build_constructor (type, initlist);
2081 OBJCMETA (decl, objc_meta, attr);
2082 finish_var_decl (decl, expr);
2085 /* Build decl = initializer; for each protocol referenced in
2086 @protocol(MyProt) expression. Refs as built in the entry section
2087 above. */
2089 static void
2090 build_v2_protocol_list_translation_table (void)
2092 int count;
2093 prot_list_entry *ref;
2095 if (!protrefs)
2096 return;
2098 FOR_EACH_VEC_ELT (*protrefs, count, ref)
2100 char buf[BUFSIZE];
2101 tree expr;
2102 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2103 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2104 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2105 expr = start_var_decl (objc_v2_protocol_template, buf);
2106 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2107 finish_var_decl (ref->refdecl, expr);
2109 /* TODO: Maybe we could explicitly delete the vec. now? */
2112 static GTY (()) vec<prot_list_entry, va_gc> *protlist;
2114 /* Add the local protocol meta-data declaration to the list which
2115 later on ends up in the __protocol_list section. */
2117 static void
2118 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2120 prot_list_entry e;
2121 if (!protlist)
2122 /* Arbitrary init count. */
2123 vec_alloc (protlist, 32);
2124 e.id = protocol_interface_decl;
2125 e.refdecl = protocol_decl;
2126 vec_safe_push (protlist, e);
2129 /* Build the __protocol_list section table containing address of all
2130 generate protocol_t meta-data. */
2132 static void
2133 build_v2_protocol_list_address_table (void)
2135 int count;
2136 prot_list_entry *ref;
2137 if (!vec_safe_length (protlist))
2138 return;
2140 FOR_EACH_VEC_ELT (*protlist, count, ref)
2142 tree decl, expr;
2143 char buf[BUFSIZE];
2144 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2145 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2146 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2147 decl = create_global_decl (objc_protocol_type, buf);
2148 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2149 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2150 finish_var_decl (decl, expr);
2153 /* TODO: delete the vec. */
2154 /* TODO: upgrade to the clang/llvm hidden version. */
2157 /* This routine declares a variable to hold meta data for 'struct
2158 protocol_list_t'. */
2160 static tree
2161 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2163 tree refs_decl, lproto, e, plist, ptempl_p_t;
2164 int size = 0;
2165 vec<constructor_elt, va_gc> *initlist = NULL;
2166 char buf[BUFSIZE];
2168 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2169 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2170 plist = CLASS_PROTOCOL_LIST (i_or_p);
2171 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2172 plist = PROTOCOL_LIST (i_or_p);
2173 else
2174 gcc_unreachable ();
2176 /* Compute size. */
2177 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2178 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2179 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2180 size++;
2182 /* Build initializer. */
2184 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2185 e = build_int_cst (ptempl_p_t, size);
2186 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2188 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2190 tree pval = TREE_VALUE (lproto);
2192 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2193 && PROTOCOL_FORWARD_DECL (pval))
2195 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2196 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2197 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2198 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2202 /* static struct protocol_list_t *list[size]; */
2204 switch (TREE_CODE (i_or_p))
2206 case PROTOCOL_INTERFACE_TYPE:
2207 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2208 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2209 break;
2210 case CLASS_INTERFACE_TYPE:
2211 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2212 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2213 break;
2214 case CATEGORY_INTERFACE_TYPE:
2215 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2216 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2217 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2218 break;
2219 default:
2220 gcc_unreachable ();
2223 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2224 buf);
2225 /* ObjC2 puts all these in the base section. */
2226 OBJCMETA (refs_decl, objc_meta, meta_base);
2227 DECL_PRESERVE_P (refs_decl) = 1;
2228 finish_var_decl (refs_decl,
2229 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2230 return refs_decl;
2233 /* This routine builds one 'struct method_t' initializer list. Note
2234 that the old ABI is supposed to build 'struct objc_method' which
2235 has 3 fields, but it does not build the initialization expression
2236 for 'method_imp' which for protocols is NULL any way. To be
2237 consistent with declaration of 'struct method_t', in the new ABI we
2238 set the method_t.imp to NULL. */
2240 static tree
2241 build_v2_descriptor_table_initializer (tree type, tree entries)
2243 vec<constructor_elt, va_gc> *initlist = NULL;
2246 vec<constructor_elt, va_gc> *eltlist = NULL;
2247 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2248 build_selector (METHOD_SEL_NAME (entries)));
2249 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2250 add_objc_string (METHOD_ENCODING (entries),
2251 meth_var_types));
2252 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2254 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2255 objc_build_constructor (type, eltlist));
2256 entries = TREE_CHAIN (entries);
2258 while (entries);
2260 return objc_build_constructor (build_array_type (type, 0), initlist);
2263 /* struct method_list_t
2265 uint32_t entsize;
2266 uint32_t method_count;
2267 struct objc_method method_list[method_count];
2268 }; */
2270 static tree
2271 build_v2_method_list_template (tree list_type, int size)
2273 tree method_list_t_record;
2274 tree array_type, decls, *chain = NULL;
2276 method_list_t_record = objc_start_struct (NULL_TREE);
2278 /* uint32_t const entsize; */
2279 decls = add_field_decl (integer_type_node, "entsize", &chain);
2281 /* int method_count; */
2282 add_field_decl (integer_type_node, "method_count", &chain);
2284 /* struct objc_method method_list[]; */
2285 array_type = build_sized_array_type (list_type, size);
2286 add_field_decl (array_type, "method_list", &chain);
2288 objc_finish_struct (method_list_t_record, decls);
2289 return method_list_t_record;
2292 /* Note, as above that we are building to the objc_method_template
2293 which has the *imp field. ABI0/1 build with
2294 objc_method_prototype_template which is missing this field. */
2295 static tree
2296 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2297 const char *prefix, tree attr)
2299 tree method_list_template, initlist, decl, methods;
2300 int size, entsize;
2301 vec<constructor_elt, va_gc> *v = NULL;
2302 char buf[BUFSIZE];
2304 if (!chain || !prefix)
2305 return NULL_TREE;
2307 methods = chain;
2308 size = 0;
2309 while (methods)
2311 if (! METHOD_ENCODING (methods))
2312 METHOD_ENCODING (methods) = encode_method_prototype (methods);
2313 methods = TREE_CHAIN (methods);
2314 size++;
2317 gcc_assert (size);
2318 method_list_template = build_v2_method_list_template (objc_method_template,
2319 size);
2320 snprintf (buf, BUFSIZE, "%s_%s", prefix,
2321 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2323 decl = start_var_decl (method_list_template, buf);
2325 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2326 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2327 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2328 initlist =
2329 build_v2_descriptor_table_initializer (objc_method_template,
2330 chain);
2331 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2332 /* Get into the right section. */
2333 OBJCMETA (decl, objc_meta, attr);
2334 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2335 return decl;
2338 /* This routine builds the initializer list to initialize the 'struct
2339 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2341 static tree
2342 build_v2_property_table_initializer (tree type, tree context)
2344 tree x;
2345 vec<constructor_elt, va_gc> *inits = NULL;
2346 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2347 x = CLASS_PROPERTY_DECL (context);
2348 else
2349 x = IMPL_PROPERTY_DECL (context);
2351 for (; x; x = TREE_CHAIN (x))
2353 vec<constructor_elt, va_gc> *elemlist = NULL;
2354 /* NOTE! sections where property name/attribute go MUST change
2355 later. */
2356 tree attribute, name_ident = PROPERTY_NAME (x);
2358 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2359 add_objc_string (name_ident, prop_names_attr));
2361 attribute = objc_v2_encode_prop_attr (x);
2362 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2363 add_objc_string (attribute, prop_names_attr));
2365 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2366 objc_build_constructor (type, elemlist));
2369 return objc_build_constructor (build_array_type (type, 0),inits);
2372 /* This routine builds the following type:
2373 struct _prop_list_t
2375 uint32_t entsize; // sizeof (struct _prop_t)
2376 uint32_t prop_count;
2377 struct _prop_t prop_list [prop_count];
2381 static tree
2382 build_v2_property_list_template (tree list_type, int size)
2384 tree property_list_t_record;
2385 tree array_type, decls, *chain = NULL;
2387 /* anonymous. */
2388 property_list_t_record = objc_start_struct (NULL_TREE);
2390 /* uint32_t const entsize; */
2391 decls = add_field_decl (integer_type_node, "entsize", &chain);
2393 /* int prop_count; */
2394 add_field_decl (integer_type_node, "prop_count", &chain);
2396 /* struct _prop_t prop_list[]; */
2397 array_type = build_sized_array_type (list_type, size);
2398 add_field_decl (array_type, "prop_list", &chain);
2400 objc_finish_struct (property_list_t_record, decls);
2401 return property_list_t_record;
2404 /* Top-level routine to generate property tables for each
2405 implementation. */
2407 static tree
2408 generate_v2_property_table (tree context, tree klass_ctxt)
2410 tree x, decl, initlist, property_list_template;
2411 bool is_proto = false;
2412 vec<constructor_elt, va_gc> *inits = NULL;
2413 int init_val, size = 0;
2414 char buf[BUFSIZE];
2416 if (context)
2418 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2419 x = CLASS_PROPERTY_DECL (context);
2420 is_proto = true;
2422 else
2423 x = IMPL_PROPERTY_DECL (klass_ctxt);
2425 for (; x; x = TREE_CHAIN (x))
2426 size++;
2428 if (size == 0)
2429 return NULL_TREE;
2431 property_list_template =
2432 build_v2_property_list_template (objc_v2_property_template,
2433 size);
2435 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2436 is_proto ? context
2437 : klass_ctxt);
2439 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2440 if (is_proto)
2441 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2442 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2443 else
2444 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2445 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2447 decl = start_var_decl (property_list_template, buf);
2449 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2450 build_int_cst (NULL_TREE, init_val));
2451 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2452 build_int_cst (NULL_TREE, size));
2453 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2455 OBJCMETA (decl, objc_meta, meta_base);
2456 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2457 return decl;
2460 static tree
2461 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2462 tree inst_methods, tree class_methods,
2463 tree opt_ins_meth, tree opt_cls_meth,
2464 tree property_list)
2466 tree expr, ttyp;
2467 location_t loc;
2468 vec<constructor_elt, va_gc> *inits = NULL;
2470 /* TODO: find a better representation of location from the inputs. */
2471 loc = UNKNOWN_LOCATION;
2473 /* This is NULL for the new ABI. */
2474 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2475 convert (objc_object_type, null_pointer_node));
2477 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2478 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2480 ttyp = objc_method_proto_list_ptr;
2481 if (inst_methods)
2482 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2483 else
2484 expr = convert (ttyp, null_pointer_node);
2485 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2487 if (class_methods)
2488 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2489 else
2490 expr = convert (ttyp, null_pointer_node);
2491 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2493 if (opt_ins_meth)
2494 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2495 else
2496 expr = convert (ttyp, null_pointer_node);
2497 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2499 if (opt_cls_meth)
2500 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2501 else
2502 expr = convert (ttyp, null_pointer_node);
2503 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2505 ttyp = objc_prop_list_ptr;
2506 if (property_list)
2507 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2508 else
2509 expr = convert (ttyp, null_pointer_node);
2510 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2512 /* const uint32_t size; = sizeof(struct protocol_t) */
2513 expr = build_int_cst (integer_type_node,
2514 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2515 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2516 /* const uint32_t flags; = 0 */
2517 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2519 return objc_build_constructor (type, inits);
2522 /* Main routine to build all meta data for all protocols used in a
2523 translation unit. */
2525 static void
2526 generate_v2_protocols (void)
2528 tree p ;
2529 bool some = false;
2531 if (!protocol_chain)
2532 return ;
2534 /* If a protocol was directly referenced, pull in indirect
2535 references. */
2536 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2537 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2538 generate_protocol_references (PROTOCOL_LIST (p));
2540 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2542 location_t loc;
2543 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2544 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2546 /* If protocol wasn't referenced, don't generate any code. */
2547 decl = PROTOCOL_FORWARD_DECL (p);
2549 if (!decl)
2550 continue;
2552 loc = DECL_SOURCE_LOCATION (decl);
2553 some = true;
2555 inst_meth =
2556 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2557 "_OBJC_ProtocolInstanceMethods",
2558 meta_proto_nst_meth);
2560 class_meth =
2561 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2562 "_OBJC_ProtocolClassMethods",
2563 meta_proto_cls_meth);
2565 opt_inst_meth =
2566 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2567 "_OBJC_OptProtocolInstMethods",
2568 meta_proto_nst_meth);
2570 opt_class_meth =
2571 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2572 "_OBJC_OptProtocolClassMethods",
2573 meta_proto_cls_meth);
2575 if (PROTOCOL_LIST (p))
2576 refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2577 else
2578 refs_decl = 0;
2580 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2581 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2583 if (refs_decl)
2584 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2585 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2586 else
2587 refs_expr = build_int_cst (NULL_TREE, 0);
2589 props = generate_v2_property_table (p, NULL_TREE);
2591 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2592 protocol_name_expr, refs_expr,
2593 inst_meth, class_meth,
2594 opt_inst_meth, opt_class_meth,
2595 props);
2596 finish_var_decl (decl, initlist);
2597 objc_add_to_protocol_list (p, decl);
2600 if (some)
2602 /* Make sure we get the Protocol class linked in - reference
2603 it... */
2604 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2605 /* ... but since we don't specifically use the reference... we
2606 need to force it. */
2607 DECL_PRESERVE_P (p) = 1;
2611 static tree
2612 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2614 tree decl, method_list_template, initlist;
2615 vec<constructor_elt, va_gc> *v = NULL;
2616 int size, init_val;
2618 if (!chain || !name || !(size = list_length (chain)))
2619 return NULL_TREE;
2621 method_list_template
2622 = build_v2_method_list_template (objc_method_template, size);
2623 initlist
2624 = build_dispatch_table_initializer (objc_method_template, chain);
2626 decl = start_var_decl (method_list_template, name);
2628 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2629 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2630 build_int_cst (integer_type_node, init_val));
2631 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2632 build_int_cst (integer_type_node, size));
2633 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2635 OBJCMETA (decl, objc_meta, attr);
2636 finish_var_decl (decl,
2637 objc_build_constructor (TREE_TYPE (decl), v));
2638 return decl;
2641 /* Init a category. */
2642 static tree
2643 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2644 tree inst_methods, tree class_methods,
2645 tree protocol_list, tree property_list,
2646 location_t loc)
2648 tree expr, ltyp;
2649 vec<constructor_elt, va_gc> *v = NULL;
2651 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2652 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2654 ltyp = objc_method_list_ptr;
2655 if (inst_methods)
2656 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2657 else
2658 expr = convert (ltyp, null_pointer_node);
2659 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2661 if (class_methods)
2662 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2663 else
2664 expr = convert (ltyp, null_pointer_node);
2665 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2667 /* protocol_list = */
2668 ltyp = build_pointer_type (objc_v2_protocol_template);
2669 if (protocol_list)
2670 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2671 else
2672 expr = convert (ltyp, null_pointer_node);
2673 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2675 ltyp = objc_prop_list_ptr;
2676 if (property_list)
2677 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2678 else
2679 expr = convert (ltyp, null_pointer_node);
2680 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2682 return objc_build_constructor (type, v);
2685 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2687 static void
2688 generate_v2_category (struct imp_entry *impent)
2690 tree initlist, cat_name_expr, class_name_expr;
2691 tree protocol_decl, category, props, t;
2692 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2693 tree cat = impent->imp_context;
2694 tree cat_decl = impent->class_decl;
2695 location_t loc;
2696 char buf[BUFSIZE];
2698 loc = DECL_SOURCE_LOCATION (cat_decl);
2700 /* ??? not sure this is really necessary, the following references should
2701 force appropriate linkage linkage...
2702 -- but ... ensure a reference to the class... */
2703 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2704 /* ... which we ignore so force it out.. */
2705 DECL_PRESERVE_P (t) = 1;
2707 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2708 class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2709 class_name_expr = build_fold_addr_expr (class_name_expr);
2711 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2712 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2714 if (category && CLASS_PROTOCOL_LIST (category))
2716 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2717 protocol_decl = generate_v2_protocol_list (category, cat);
2719 else
2720 protocol_decl = NULL_TREE;
2722 /* decl = update_var_decl(impent->class_decl); */
2724 props = generate_v2_property_table (NULL_TREE, cat);
2726 if (CLASS_NST_METHODS (cat))
2728 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2729 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2730 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2731 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2732 meta_cati_meth);
2735 if (CLASS_CLS_METHODS (cat))
2737 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2738 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2739 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2740 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2741 meta_catc_meth);
2744 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2745 cat_name_expr, class_name_expr,
2746 inst_methods, class_methods,
2747 protocol_decl, props, loc);
2749 finish_var_decl (cat_decl, initlist);
2750 impent->class_decl = cat_decl;
2752 /* Add to list of pointers in __category_list section. */
2753 objc_v2_add_to_category_list (cat_decl);
2754 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2755 objc_v2_add_to_nonlazy_category_list (cat_decl);
2758 /* This routine declares a variable to hold the offset for ivar
2759 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
2761 struct GTY(()) ivarref_entry
2763 tree decl;
2764 tree offset;
2767 static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
2769 static tree
2770 ivar_offset_ref (tree class_name, tree field_decl)
2772 tree decl, field_decl_id;
2773 ivarref_entry e;
2774 bool global_var;
2775 char buf[512];
2777 create_ivar_offset_name (buf, class_name, field_decl);
2778 field_decl_id = get_identifier (buf);
2780 if (ivar_offset_refs)
2782 int count;
2783 ivarref_entry *ref;
2784 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
2785 if (DECL_NAME (ref->decl) == field_decl_id)
2786 return ref->decl;
2788 else
2789 /* Somewhat arbitrary initial provision. */
2790 vec_alloc (ivar_offset_refs, 32);
2792 /* We come here if we don't find a match or at the start. */
2793 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
2794 if (global_var)
2795 decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
2796 else
2797 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
2799 /* Make sure it ends up in an ObjC section. */
2800 OBJCMETA (decl, objc_meta, meta_base);
2802 e.decl = decl;
2803 e.offset = byte_position (field_decl);
2804 vec_safe_push (ivar_offset_refs, e);
2805 return decl;
2808 /* This routine builds initializer-list needed to initialize 'struct
2809 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
2810 'struct ivar_t' and FIELD_DECL is list of ivars for the target
2811 class. */
2813 static tree
2814 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
2816 vec<constructor_elt, va_gc> *inits = NULL;
2820 vec<constructor_elt, va_gc> *ivar = NULL;
2821 int val;
2822 tree id;
2824 /* Unnamed bitfields are ignored. */
2825 if (!DECL_NAME (field_decl))
2827 field_decl = DECL_CHAIN (field_decl);
2828 continue;
2831 /* Set offset. */
2832 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2833 build_unary_op (input_location,
2834 ADDR_EXPR,
2835 ivar_offset_ref (class_name,
2836 field_decl), 0));
2838 /* Set name. */
2839 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2840 add_objc_string (DECL_NAME (field_decl),
2841 meth_var_names));
2843 /* Set type. */
2844 id = add_objc_string (encode_field_decl (field_decl),
2845 meth_var_types);
2846 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
2848 /* Set alignment. */
2849 val = DECL_ALIGN_UNIT (field_decl);
2850 val = exact_log2 (val);
2851 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2852 build_int_cst (integer_type_node, val));
2854 /* Set size. */
2855 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
2856 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2857 build_int_cst (integer_type_node, val));
2859 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2860 objc_build_constructor (type, ivar));
2863 field_decl = DECL_CHAIN (field_decl);
2864 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
2866 while (field_decl);
2868 return objc_build_constructor (build_array_type (type, 0), inits);
2872 struct ivar_list_t
2874 uint32 entsize;
2875 uint32 count;
2876 struct iver_t list[count];
2880 static tree
2881 build_v2_ivar_list_t_template (tree list_type, int size)
2883 tree objc_ivar_list_record;
2884 tree decls, *chain = NULL;
2886 /* Anonymous. */
2887 objc_ivar_list_record = objc_start_struct (NULL_TREE);
2889 /* uint32 entsize; */
2890 decls = add_field_decl (integer_type_node, "entsize", &chain);
2892 /* uint32 count; */
2893 add_field_decl (integer_type_node, "count", &chain);
2895 /* struct objc_ivar ivar_list[]; */
2896 add_field_decl (build_sized_array_type (list_type, size),
2897 "list", &chain);
2899 objc_finish_struct (objc_ivar_list_record, decls);
2900 return objc_ivar_list_record;
2903 /* This routine declares a static variable of type 'struct
2904 ivar_list_t' and initializes it. chain is the source of the data,
2905 name is the name for the var. attr is the meta-data section tag
2906 attribute. templ is the implementation template for the class. */
2908 static tree
2909 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
2911 tree decl, initlist, ivar_list_template;
2912 vec<constructor_elt, va_gc> *inits = NULL;
2913 int size, ivar_t_size;
2915 if (!chain || !name || !(size = ivar_list_length (chain)))
2916 return NULL_TREE;
2918 generating_instance_variables = 1;
2919 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
2920 size);
2922 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
2923 objc_v2_ivar_template, chain);
2924 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
2926 decl = start_var_decl (ivar_list_template, name);
2927 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2928 build_int_cst (integer_type_node, ivar_t_size));
2929 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2930 build_int_cst (integer_type_node, size));
2931 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2932 OBJCMETA (decl, objc_meta, attr);
2933 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2934 generating_instance_variables = 0;
2935 return decl;
2938 /* Routine to build initializer list to initialize objects of type
2939 struct class_t; */
2941 static tree
2942 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
2943 tree ro, tree cache, tree vtable)
2945 vec<constructor_elt, va_gc> *initlist = NULL;
2947 /* isa */
2948 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
2950 /* superclass */
2951 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
2953 /* cache */
2954 if (cache)
2955 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
2956 else
2957 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2959 /* vtable */
2960 if (vtable)
2961 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
2962 else
2963 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2965 /* ro */
2966 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
2968 return objc_build_constructor (type, initlist);
2971 /* Routine to build object of struct class_ro_t { ... }; */
2973 static tree
2974 build_v2_class_ro_t_initializer (tree type, tree name,
2975 unsigned int flags, unsigned int instanceStart,
2976 unsigned int instanceSize,
2977 tree ivarLayout,
2978 tree baseMethods, tree baseProtocols,
2979 tree ivars, tree property_list)
2981 tree expr, unsigned_char_star, ltyp;
2982 location_t loc;
2983 vec<constructor_elt, va_gc> *initlist = NULL;
2985 /* TODO: fish out the real location from somewhere. */
2986 loc = UNKNOWN_LOCATION;
2988 /* flags */
2989 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2990 build_int_cst (integer_type_node, flags));
2992 /* instanceStart */
2993 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2994 build_int_cst (integer_type_node, instanceStart));
2996 /* instanceSize */
2997 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2998 build_int_cst (integer_type_node, instanceSize));
3000 /* This ABI is currently only used on m64 NeXT. We always
3001 explicitly declare the alignment padding. */
3002 /* reserved, pads alignment. */
3003 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3004 build_int_cst (integer_type_node, 0));
3006 /* ivarLayout */
3007 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3008 if (ivarLayout)
3009 expr = ivarLayout;
3010 else
3011 expr = convert (unsigned_char_star, null_pointer_node);
3012 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3014 /* name */
3015 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3017 /* baseMethods */
3018 ltyp = objc_method_list_ptr;
3019 if (baseMethods)
3020 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3021 else
3022 expr = convert (ltyp, null_pointer_node);
3023 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3025 /* baseProtocols */
3026 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3027 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3028 if (baseProtocols)
3029 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3030 else
3031 expr = convert (ltyp, null_pointer_node);
3032 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3034 /* ivars */
3035 ltyp = objc_v2_ivar_list_ptr;
3036 if (ivars)
3037 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3038 else
3039 expr = convert (ltyp, null_pointer_node);
3040 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3042 /* TODO: We don't yet have the weak/strong stuff... */
3043 /* weakIvarLayout */
3044 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3045 convert (unsigned_char_star, null_pointer_node));
3047 /* property list */
3048 ltyp = objc_prop_list_ptr;
3049 if (property_list)
3050 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3051 else
3052 expr = convert (ltyp, null_pointer_node);
3053 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3054 return objc_build_constructor (type, initlist);
3057 static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
3059 /* Record a name as needing a catcher. */
3060 static void
3061 objc_v2_add_to_ehtype_list (tree name)
3063 ident_data_tuple e;
3064 if (ehtype_list)
3066 int count = 0;
3067 ident_data_tuple *ref;
3069 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3070 if (ref->ident == name)
3071 return; /* Already entered. */
3073 else
3074 /* Arbitrary initial count. */
3075 vec_alloc (ehtype_list, 8);
3077 /* Not found, or new list. */
3078 e.ident = name;
3079 e.data = NULL_TREE;
3080 vec_safe_push (ehtype_list, e);
3083 static void
3084 generate_v2_class_structs (struct imp_entry *impent)
3086 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3087 tree field, firstIvar, chain;
3088 tree class_superclass_expr, metaclass_superclass_expr, props;
3089 /* TODO: figure out how to compute this. */
3090 tree ivarLayout = NULL_TREE;
3091 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3092 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3093 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3094 location_t loc;
3095 char buf[BUFSIZE];
3096 unsigned int instanceStart, instanceSize;
3097 unsigned int flags = 0x01; /* RO_META */
3098 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3099 : 0 ;
3101 class_decl = impent->class_decl;
3102 metaclass_decl = impent->meta_decl;
3103 loc = DECL_SOURCE_LOCATION (class_decl);
3105 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3106 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3107 #ifdef OBJCPLUS
3108 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3109 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3110 #endif
3112 /* Generation of data for meta class. */
3113 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3114 if (my_super_id)
3116 /* Compute reference to root's name. For a meta class, "isa" is
3117 a reference to the root class name. */
3118 tree my_root_id = my_super_id;
3119 tree my_root_int, interface;
3122 my_root_int = lookup_interface (my_root_id);
3124 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3125 my_root_id = CLASS_SUPER_NAME (my_root_int);
3126 else
3127 break;
3129 while (1);
3131 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3132 create extern if not already declared. */
3133 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3134 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3135 root_expr = create_extern_decl (objc_v2_class_template, buf);
3136 root_expr = build_fold_addr_expr (root_expr);
3138 /* Install class `isa' and `super' pointers at runtime. */
3139 interface = lookup_interface (my_super_id);
3140 gcc_assert (interface);
3141 /* Similarly, for OBJC_CLASS_$_<interface>... */
3142 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3143 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3144 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3145 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3146 /* ... and for OBJC_METACLASS_$_<interface>. */
3147 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3148 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3149 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3150 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3152 else
3154 /* Root class. */
3155 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3156 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3157 class_superclass_expr = build_int_cst (NULL_TREE, 0);
3158 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */
3161 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3163 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3164 protocol_decl = generate_v2_protocol_list (impent->imp_template,
3165 impent->imp_context);
3167 else
3168 protocol_decl = 0;
3170 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3171 class_names);
3173 if (CLASS_CLS_METHODS (impent->imp_context))
3175 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3176 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3177 class_methods =
3178 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3179 buf, meta_clac_meth);
3182 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3184 /* Currently there are no class ivars and generation of class
3185 variables for the root of the inheritance has been removed. It
3186 causes multiple defines if there are two root classes in the
3187 link, because each will define its own identically-named offset
3188 variable. */
3190 class_ivars = NULL_TREE;
3191 /* TODO: Add total size of class variables when implemented. */
3192 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3194 /* So now build the META CLASS structs. */
3195 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3197 decl = start_var_decl (objc_v2_class_ro_template,
3198 newabi_append_ro (IDENTIFIER_POINTER
3199 (DECL_NAME (metaclass_decl))));
3201 /* TODO: ivarLayout needs t be built. */
3202 initlist =
3203 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3204 (flags | cls_flags), instanceStart,
3205 instanceSize, ivarLayout,
3206 class_methods, protocol_decl,
3207 class_ivars, NULL_TREE);
3208 /* The ROs sit in the default const section. */
3209 OBJCMETA (decl, objc_meta, meta_base);
3210 finish_var_decl (decl, initlist);
3212 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3213 initlist =
3214 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3215 root_expr,
3216 metaclass_superclass_expr,
3217 build_fold_addr_expr (decl),
3218 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3219 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3220 /* The class section attributes are set when they are created. */
3221 finish_var_decl (metaclass_decl, initlist);
3222 impent->meta_decl = metaclass_decl;
3224 /* So now build the CLASS structs. */
3226 flags = 0x0; /* ... */
3227 if (!my_super_id)
3228 flags |= 0x02; /* RO_ROOT: this is a root class */
3230 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3231 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3233 if (objc2_objc_exception_attr (impent->imp_template))
3234 flags |= 0x20; /* RO_EXCEPTION */
3236 if (CLASS_NST_METHODS (impent->imp_context))
3238 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3239 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3240 inst_methods =
3241 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3242 buf, meta_clai_meth);
3245 /* Sort out the ivars before we try to compute the class sizes. */
3246 if ((chain = CLASS_IVARS (impent->imp_template)))
3248 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3249 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3250 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3251 impent->imp_template);
3254 /* Compute instanceStart. */
3255 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3256 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3257 if (my_super_id && field && TREE_CHAIN (field))
3258 field = TREE_CHAIN (field);
3260 firstIvar = field;
3262 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3263 firstIvar = TREE_CHAIN (firstIvar);
3265 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3267 /* Compute instanceSize. */
3268 while (field && TREE_CHAIN (field)
3269 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3270 field = TREE_CHAIN (field);
3272 if (field && TREE_CODE (field) == FIELD_DECL)
3273 instanceSize = int_byte_position (field) * BITS_PER_UNIT
3274 + tree_to_shwi (DECL_SIZE (field));
3275 else
3276 instanceSize = 0;
3277 instanceSize /= BITS_PER_UNIT;
3279 props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3281 /* If the class has no ivars, instanceStart should be set to the
3282 superclass's instanceSize. */
3283 instanceStart =
3284 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3285 : instanceSize;
3287 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3288 decl = start_var_decl (objc_v2_class_ro_template,
3289 newabi_append_ro (IDENTIFIER_POINTER
3290 (DECL_NAME (class_decl))));
3292 initlist =
3293 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3294 (flags | cls_flags), instanceStart,
3295 instanceSize, ivarLayout,
3296 inst_methods, protocol_decl,
3297 inst_ivars, props);
3298 /* The ROs sit in the default const section. */
3299 OBJCMETA (decl, objc_meta, meta_base);
3300 finish_var_decl (decl, initlist);
3302 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3303 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3304 build_fold_addr_expr (metaclass_decl),
3305 class_superclass_expr,
3306 build_fold_addr_expr (decl),
3307 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3308 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3310 /* The class section attributes are set when they are created. */
3311 finish_var_decl (class_decl, initlist);
3312 impent->class_decl = class_decl;
3314 objc_v2_add_to_class_list (class_decl);
3315 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3316 objc_v2_add_to_nonlazy_class_list (class_decl);
3318 if (flags & 0x20) /* RO_EXCEPTION */
3319 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3322 /* This routine outputs the (ivar_reference_offset, offset)
3323 tuples. */
3325 static void
3326 build_v2_ivar_offset_ref_table (void)
3328 int count;
3329 ivarref_entry *ref;
3331 if (!vec_safe_length (ivar_offset_refs))
3332 return;
3334 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3335 finish_var_decl (ref->decl, ref->offset);
3338 static void
3339 objc_generate_v2_next_metadata (void)
3341 struct imp_entry *impent;
3343 /* FIXME: Make sure that we generate no metadata if there is nothing
3344 to put into it. */
3346 gcc_assert (!objc_static_instances); /* Not for NeXT */
3348 build_metadata_templates ();
3350 for (impent = imp_list; impent; impent = impent->next)
3352 /* If -gen-decls is present, Dump the @interface of each class.
3353 TODO: Dump the classes in the order they were found, rather
3354 than in reverse order as we are doing now. */
3355 if (flag_gen_declaration)
3356 dump_interface (gen_declaration_file, impent->imp_context);
3358 /* all of the following reference the string pool... */
3359 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3360 generate_v2_class_structs (impent);
3361 else
3362 generate_v2_category (impent);
3365 build_next_selector_translation_table ();
3366 build_v2_message_ref_translation_table ();
3368 /* This will add "Protocol" to the class refs. */
3369 generate_v2_protocols ();
3371 build_v2_classrefs_table ();
3372 build_v2_super_classrefs_table (/*metaclass= */false);
3373 build_v2_super_classrefs_table (/*metaclass= */true);
3375 build_v2_ivar_offset_ref_table ();
3377 build_v2_protocol_list_translation_table ();
3378 build_v2_protocol_list_address_table ();
3380 build_v2_address_table (class_list, "_OBJC_ClassList$",
3381 meta_label_classlist);
3382 build_v2_address_table (category_list, "_OBJC_CategoryList$",
3383 meta_label_categorylist);
3384 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3385 meta_label_nonlazy_classlist);
3386 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3387 meta_label_nonlazy_categorylist);
3389 /* Generate catch objects for eh, if any are needed. */
3390 build_v2_eh_catch_objects ();
3392 /* Emit the string table last. */
3393 generate_strings ();
3396 /* NOTE --- Output NeXT V2 Exceptions --- */
3398 static GTY(()) tree objc_v2_ehtype_template;
3399 static GTY(()) tree next_v2_ehvtable_decl;
3400 static GTY(()) tree next_v2_EHTYPE_id_decl;
3402 static void
3403 build_v2_ehtype_template (void)
3405 tree decls, *chain = NULL;
3406 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3408 /* void *_objc_ehtype_vtable; */
3409 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3411 /* const char *className; */
3412 add_field_decl (string_type_node, "className", &chain);
3414 /* struct class_t *const cls; */
3415 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3417 objc_finish_struct (objc_v2_ehtype_template, decls);
3420 /* Template for the Objective-C family typeinfo type for ABI=2. This
3421 starts off the same as the gxx/cxx eh typeinfo.
3423 struct _objc_ehtype_t
3425 void *_objc_ehtype_vtable_ptr; - as per c++
3426 const char *className; - as per c++
3427 struct class_t *const cls;
3431 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3434 static tree
3435 objc2_build_ehtype_initializer (tree name, tree cls)
3437 vec<constructor_elt, va_gc> *initlist = NULL;
3438 tree addr, offs;
3440 /* This is done the same way as c++, missing the two first entries
3441 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3442 runtime source about this so, perhaps, this will change at some
3443 point. */
3444 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3445 if (!next_v2_ehvtable_decl)
3447 next_v2_ehvtable_decl =
3448 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3449 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3450 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3451 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3453 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3454 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3455 addr = fold_build_pointer_plus (addr, offs);
3457 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3459 /* className */
3460 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3462 /* cls */
3463 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3465 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3468 static tree
3469 build_ehtype (tree name, const char *eh_name, bool weak)
3471 tree name_expr, class_name_expr, ehtype_decl, inits;
3473 name_expr = add_objc_string (name, class_names);
3474 /* Extern ref. for the class. ??? Maybe we can look this up
3475 somewhere. */
3476 class_name_expr =
3477 create_extern_decl (objc_v2_class_template,
3478 objc_build_internal_classname (name, false));
3479 class_name_expr = build_fold_addr_expr (class_name_expr);
3480 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3481 if (weak)
3482 DECL_WEAK (ehtype_decl) = 1;
3483 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3484 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3485 finish_var_decl (ehtype_decl, inits);
3486 return ehtype_decl;
3489 /* This routine returns TRUE if CLS or any of its super classes has
3490 __attribute__ ((objc_exception)). */
3492 static bool
3493 objc2_objc_exception_attr (tree cls)
3495 while (cls)
3497 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3498 return true;
3499 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3502 return false;
3505 static bool
3506 is_implemented (tree name)
3508 struct imp_entry *t;
3509 for (t = imp_list; t; t = t->next)
3510 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3511 && CLASS_NAME (t->imp_template) == name)
3512 return true;
3514 return false;
3517 /* We will build catch objects:
3518 for any type implemented here.
3519 for any type used in a catch that has no exception attribute. */
3520 static void build_v2_eh_catch_objects (void)
3522 int count=0;
3523 ident_data_tuple *ref;
3525 if (!vec_safe_length (ehtype_list))
3526 return;
3528 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3530 char buf[BUFSIZE];
3531 bool impl = is_implemented (ref->ident);
3532 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3533 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3534 if (!impl && excpt)
3535 /* The User says this class has a catcher already. */
3536 ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3537 else
3538 /* Create a catcher, weak if it wasn't marked. */
3539 ref->data = build_ehtype (ref->ident, buf, !excpt);
3543 static tree
3544 lookup_ehtype_ref (tree id)
3546 int count=0;
3547 ident_data_tuple *ref;
3549 if (!vec_safe_length (ehtype_list))
3550 return NULL_TREE;
3552 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3553 if (ref->ident == id)
3554 return ref->data;
3555 return NULL_TREE;
3558 /* This hook, called via lang_eh_runtime_type, generates a runtime
3559 object which is either the address of the 'OBJC_EHTYPE_$_class'
3560 object or address of external OBJC_EHTYPE_id object. */
3561 static tree
3562 next_runtime_02_eh_type (tree type)
3564 tree t;
3566 if (type == error_mark_node
3567 /*|| errorcount || sorrycount*/)
3568 goto err_mark_in;
3570 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3572 if (!next_v2_EHTYPE_id_decl)
3574 /* This is provided by the Apple/NeXT libobjc.dylib so we
3575 need only to reference it. */
3576 next_v2_EHTYPE_id_decl =
3577 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3578 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3579 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3580 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3582 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3585 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3587 #ifdef OBJCPLUS
3588 /* This routine is also called for c++'s catch clause; in which
3589 case, we use c++'s typeinfo decl. */
3590 return build_eh_type_type (type);
3591 #else
3592 error ("non-objective-c type '%T' cannot be caught", type);
3593 goto err_mark_in;
3594 #endif
3596 else
3597 t = OBJC_TYPE_NAME (TREE_TYPE (type));
3599 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3600 t = lookup_ehtype_ref (t);
3601 if (!t)
3602 goto err_mark_in;
3604 return build_fold_addr_expr (t);
3606 err_mark_in:
3607 return error_mark_node;
3610 static GTY(()) tree objc_eh_personality_decl;
3612 static tree
3613 objc_eh_personality (void)
3615 if (!objc_eh_personality_decl)
3616 objc_eh_personality_decl = build_personality_function ("objc");
3617 return objc_eh_personality_decl;
3620 /* NOTE --- interfaces --- */
3622 static tree
3623 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3625 tree t;
3626 if (rethrown)
3627 /* We have a separate re-throw entry. */
3628 t = build_function_call_vec (loc, vNULL, objc_rethrow_exception_decl,
3629 NULL, NULL);
3630 else
3632 /* Throw like the others... */
3633 vec<tree, va_gc> *parms;
3634 vec_alloc (parms, 1);
3635 parms->quick_push (throw_expr);
3636 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl,
3637 parms, 0);
3638 vec_free (parms);
3640 return add_stmt (t);
3643 /* Build __builtin_eh_pointer. */
3645 static tree
3646 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3648 tree t;
3649 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3650 t = build_call_expr (t, 1, integer_zero_node);
3651 return fold_convert (objc_object_type, t);
3654 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3655 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3657 tree t;
3659 /* Record the data for the catch in the try context so that we can
3660 finalize it later. Ellipsis is signalled by a NULL entry. */
3661 if (ellipsis)
3662 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3663 else
3664 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3665 (*cur_try_context)->current_catch = t;
3667 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3668 t = objc_build_exc_ptr (cur_try_context);
3669 t = convert (TREE_TYPE (decl), t);
3670 /* FIXME: location. */
3671 if (type && type != error_mark_node)
3673 t = build1(NOP_EXPR, ptr_type_node, t);
3674 t = build_function_call (input_location, objc2_begin_catch_decl,
3675 tree_cons (NULL_TREE, t, NULL_TREE));
3677 /* We might want to build a catch object for this (if it's not
3678 id). */
3679 if (POINTER_TYPE_P (type)
3680 && !objc_is_object_id (TREE_TYPE (type))
3681 && TYPED_OBJECT (TREE_TYPE (type)))
3682 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3684 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3687 /* try { catch-body } finally { objc_end_catch (); } */
3688 static void
3689 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3691 struct objc_try_context *ct;
3692 tree try_exp, func, *l, t ;
3693 location_t loc = (*cur_try_context)->try_locus;
3695 if (!curr_catch || curr_catch == error_mark_node)
3696 return;
3698 t = CATCH_BODY (curr_catch);
3699 if (TREE_CODE (t) == BIND_EXPR)
3701 /* Usual case of @catch (objc-expr). */
3702 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3703 BIND_EXPR_BODY (t) = NULL_TREE;
3704 l = &BIND_EXPR_BODY (t);
3706 else
3708 /* NULL entry, meaning @catch (...). */
3709 objc_begin_try_stmt (loc, t);
3710 CATCH_BODY (curr_catch) = NULL_TREE;
3711 l = &CATCH_BODY (curr_catch);
3714 /* Pick up the new context we made in begin_try above... */
3715 ct = *cur_try_context;
3716 func = build_function_call_vec (loc, vNULL, objc2_end_catch_decl, NULL,
3717 NULL);
3718 append_to_statement_list (func, &ct->finally_body);
3719 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3720 *cur_try_context = ct->outer;
3721 free (ct);
3722 append_to_statement_list (try_exp, l);
3723 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3726 static tree
3727 finish_try_stmt (struct objc_try_context **cur_try_context)
3729 struct objc_try_context *c = *cur_try_context;
3730 tree stmt = c->try_body;
3731 if (c->catch_list)
3732 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3733 if (c->finally_body)
3734 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3735 return stmt;
3738 #include "gt-objc-objc-next-runtime-abi-02.h"