* config/i386/gnu-user.h (TARGET_CAN_SPLIT_STACK): Move from here ...
[official-gcc.git] / gcc / objc / objc-next-runtime-abi-02.c
blob85033a3074c5a042f0b684e6cdc94b40f617df8d
1 /* Next Runtime (ABI-2) private.
2 Copyright (C) 2011-2014 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 "tree.h"
33 #include "stringpool.h"
35 #ifdef OBJCPLUS
36 #include "cp/cp-tree.h"
37 #else
38 #include "c/c-tree.h"
39 #include "c/c-lang.h"
40 #endif
41 #include "langhooks.h"
42 #include "c-family/c-objc.h"
43 #include "objc-act.h"
45 /* When building Objective-C++, we are not linking against the C front-end
46 and so need to replicate the C tree-construction functions in some way. */
47 #ifdef OBJCPLUS
48 #define OBJCP_REMAP_FUNCTIONS
49 #include "objcp-decl.h"
50 #endif /* OBJCPLUS */
52 #include "ggc.h"
53 #include "target.h"
54 #include "tree-iterator.h"
56 #include "objc-runtime-hooks.h"
57 #include "objc-runtime-shared-support.h"
58 #include "objc-encoding.h"
60 /* ABI 2 Private definitions. */
61 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
63 #define TAG_GETCLASS "objc_getClass"
64 #define TAG_GETMETACLASS "objc_getMetaClass"
66 #define TAG_MSGSEND "objc_msgSend"
67 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
68 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
69 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
71 #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
72 #define TAG_V2_EH_TYPE "objc_ehtype_t"
74 #define UTAG_V2_CLASS "_class_t"
75 #define UTAG_V2_CLASS_RO "_class_ro_t"
76 #define UTAG_V2_PROTOCOL "_protocol_t"
77 #define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
79 #define UTAG_V2_EH_TYPE "_objc_ehtype_t"
81 #define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
83 enum objc_v2_tree_index
85 /* Templates. */
86 OCTI_V2_CLS_TEMPL,
87 OCTI_V2_CAT_TEMPL,
88 OCTI_V2_CLS_RO_TEMPL,
89 OCTI_V2_PROTO_TEMPL,
90 OCTI_V2_IVAR_TEMPL,
91 OCTI_V2_IVAR_LIST_TEMPL,
92 OCTI_V2_MESSAGE_REF_TEMPL,
93 OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
95 OCTI_V2_MESSAGE_SELECTOR_TYPE,
96 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
97 OCTI_V2_IMP_TYPE,
98 OCTI_V2_SUPER_IMP_TYPE,
100 OCTI_V2_CACHE_DECL,
101 OCTI_V2_VTABLE_DECL,
103 OCTI_V2_PROPERTY_TEMPL,
105 /* V2 messaging. */
106 OCTI_V2_UMSG_FIXUP_DECL,
107 OCTI_V2_UMSG_STRET_FIXUP_DECL,
108 OCTI_V2_UMSG_ID_FIXUP_DECL,
109 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
110 OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
111 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
113 /* Exceptions - related. */
114 OCTI_V2_BEGIN_CATCH_DECL,
115 OCTI_V2_END_CATCH_DECL,
116 OCTI_V2_RETHROW_DECL,
118 OCTI_V2_MAX
121 #define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
122 #define objc_v2_class_ro_template \
123 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
124 #define objc_v2_category_template \
125 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
126 #define objc_v2_protocol_template \
127 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
129 /* struct message_ref_t */
130 #define objc_v2_message_ref_template \
131 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
133 #define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
135 /* struct super_message_ref_t */
136 #define objc_v2_super_message_ref_template \
137 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
139 /* struct message_ref_t* */
140 #define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
141 /* struct super_super_message_ref_t */
142 #define objc_v2_super_selector_type \
143 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
144 #define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
145 #define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
147 #define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
148 #define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
150 #define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
151 #define objc_v2_property_template \
152 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
154 /* V2 Messaging */
156 /* objc_msgSend_fixup_rtp */
157 #define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
158 /* objc_msgSend_stret_fixup_rtp */
159 #define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
160 /* objc_msgSendId_fixup_rtp */
161 #define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
162 /* objc_msgSendId_stret_fixup_rtp */
163 #define umsg_id_stret_fixup_decl \
164 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
165 /* objc_msgSendSuper2_fixup_rtp */
166 #define umsg_id_super2_fixup_decl \
167 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
168 /* objc_msgSendSuper2_stret_fixup_rtp */
169 #define umsg_id_super2_stret_fixup_decl \
170 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
172 #define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
173 #define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
174 #define objc_rethrow_exception_decl \
175 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
177 /* rt_trees identifiers - shared between NeXT implementations. These allow
178 the FE to tag meta-data in a manner that survives LTO and can be used when
179 the runtime requires that certain meta-data items appear in particular
180 named sections. */
182 #include "objc-next-metadata-tags.h"
183 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
185 /* The OCTI_V2_... enumeration itself is in above. */
186 static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
188 static void next_runtime_02_initialize (void);
190 static void build_v2_message_ref_templates (void);
191 static void build_v2_class_templates (void);
192 static void build_v2_super_template (void);
193 static void build_v2_category_template (void);
194 static void build_v2_protocol_template (void);
196 static tree next_runtime_abi_02_super_superclassfield_id (void);
198 static tree next_runtime_abi_02_class_decl (tree);
199 static tree next_runtime_abi_02_metaclass_decl (tree);
200 static tree next_runtime_abi_02_category_decl (tree);
201 static tree next_runtime_abi_02_protocol_decl (tree);
202 static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
204 static tree next_runtime_abi_02_get_class_reference (tree);
205 static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
206 static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
207 static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
208 static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
209 static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
211 static tree next_runtime_abi_02_receiver_is_class_object (tree);
212 static void next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **,
213 tree, int, int);
214 static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
215 tree, tree, tree, int);
216 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
217 static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
219 static tree create_extern_decl (tree, const char *);
221 static void objc_generate_v2_next_metadata (void);
222 static bool objc2_objc_exception_attr (tree);
224 /* void build_v2_protocol_reference (tree);*/
225 static void build_v2_ehtype_template (void);
226 static void build_v2_eh_catch_objects (void);
227 static tree next_runtime_02_eh_type (tree);
228 static tree objc_eh_personality (void);
229 static tree build_throw_stmt (location_t, tree, bool);
230 static tree objc_build_exc_ptr (struct objc_try_context **);
231 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
232 static void finish_catch (struct objc_try_context **, tree);
233 static tree finish_try_stmt (struct objc_try_context **);
235 /* TODO: Use an objc-map. */
236 static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
238 bool
239 objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
241 extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
243 if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
245 inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for "
246 "%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
247 flag_objc_sjlj_exceptions = 0;
250 rthooks->initialize = next_runtime_02_initialize;
251 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
252 rthooks->tag_getclass = TAG_GETCLASS;
253 rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
255 rthooks->class_decl = next_runtime_abi_02_class_decl;
256 rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
257 rthooks->category_decl = next_runtime_abi_02_category_decl;
258 rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
259 rthooks->string_decl = next_runtime_abi_02_string_decl;
261 rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
262 rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
263 rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
264 rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
265 rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
266 rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
268 rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
269 rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
270 rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
272 rthooks->setup_const_string_class_decl =
273 next_runtime_abi_02_setup_const_string_class_decl;
274 rthooks->build_const_string_constructor =
275 next_runtime_abi_02_build_const_string_constructor;
277 rthooks->build_throw_stmt = build_throw_stmt;
278 rthooks->build_exc_ptr = objc_build_exc_ptr;
279 rthooks->begin_catch = begin_catch;
280 rthooks->finish_catch = finish_catch;
281 rthooks->finish_try_stmt = finish_try_stmt;
283 rthooks->generate_metadata = objc_generate_v2_next_metadata;
284 return true;
287 /* We need a way to convey what kind of meta-data are represented by a given
288 variable, since each type is expected (by the runtime) to be found in a
289 specific named section. The solution must be usable with LTO.
291 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
292 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
293 identification attributes in the front end. The back-end may choose to act
294 on these as it requires. */
296 static void
297 next_runtime_abi_02_init_metadata_attributes (void)
299 if (!objc_meta)
300 objc_meta = get_identifier ("OBJC2META");
302 if (!meta_base)
303 meta_base = get_identifier ("V2_BASE");
305 meta_class = get_identifier ("G2_CLAS");
306 meta_metaclass = get_identifier ("G2_META");
307 meta_category =
308 meta_protocol = meta_base;
310 meta_clac_vars =
311 meta_clai_vars = meta_base;
313 meta_clac_meth =
314 meta_clai_meth =
315 meta_catc_meth =
316 meta_cati_meth =
317 meta_proto_cls_meth =
318 meta_proto_nst_meth = meta_base;
320 meta_clas_prot =
321 meta_catg_prot = meta_base;
323 meta_sel_refs = get_identifier ("V2_SRFS");
325 meta_class_name =
326 meta_meth_name =
327 meta_meth_type =
328 meta_prop_name_attr = get_identifier ("V2_STRG");
330 meta_mref = get_identifier ("V2_MREF");
331 meta_class_ref = get_identifier ("V2_CLRF");
332 meta_superclass_ref = get_identifier ("V2_SURF");
334 meta_label_classlist = get_identifier ("V2_CLAB");
335 meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
336 meta_label_categorylist = get_identifier ("V2_CALA");
337 meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
339 meta_label_protocollist = get_identifier ("V2_PLST");
340 meta_proto_ref = get_identifier ("V2_PRFS");
342 meta_info = get_identifier ("V2_INFO");
344 meta_ehtype = get_identifier ("V2_EHTY");
346 meta_const_str = get_identifier ("V2_CSTR");
349 static void next_runtime_02_initialize (void)
351 tree type;
352 #ifdef OBJCPLUS
353 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
354 default. */
355 if (!global_options_set.x_flag_objc_call_cxx_cdtors)
356 global_options.x_flag_objc_call_cxx_cdtors = 1;
357 #endif
359 /* Set up attributes to be attached to the meta-data so that they
360 will be placed in the correct sections. */
361 next_runtime_abi_02_init_metadata_attributes ();
363 /* `struct objc_selector *' */
364 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
365 get_identifier (TAG_SELECTOR)));
367 /* IMP : id (*) (id, _message_ref_t*, ...)
368 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
369 objc_v2_selector_type. */
370 build_v2_message_ref_templates ();
372 objc_v2_ivar_list_ptr =
373 build_pointer_type (xref_tag (RECORD_TYPE,
374 get_identifier ("_ivar_list_t")));
376 objc_prop_list_ptr =
377 build_pointer_type (xref_tag (RECORD_TYPE,
378 get_identifier ("_prop_list_t")));
380 build_v2_class_templates ();
381 build_v2_super_template ();
382 build_v2_protocol_template ();
383 build_v2_category_template ();
385 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
386 type = build_varargs_function_type_list (objc_object_type,
387 objc_object_type,
388 objc_v2_selector_type,
389 NULL_TREE);
390 umsg_fixup_decl = add_builtin_function ("objc_msgSend_fixup",
391 type, 0, NOT_BUILT_IN,
392 NULL, NULL_TREE);
393 TREE_NOTHROW (umsg_fixup_decl) = 0;
395 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
396 umsg_stret_fixup_decl = add_builtin_function ("objc_msgSend_stret_fixup",
397 type, 0, NOT_BUILT_IN,
398 NULL, NULL_TREE);
399 TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
401 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
402 umsg_id_fixup_decl = add_builtin_function ("objc_msgSendId_fixup",
403 type, 0, NOT_BUILT_IN,
404 NULL, NULL_TREE);
405 TREE_NOTHROW (umsg_id_fixup_decl) = 0;
407 /* id objc_msgSendId_stret_fixup_rtp
408 (id, struct message_ref_t*, ...); */
409 umsg_id_stret_fixup_decl = add_builtin_function ("objc_msgSendId_stret_fixup",
410 type, 0, NOT_BUILT_IN,
411 NULL, NULL_TREE);
412 TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
414 /* id objc_msgSendSuper2_fixup_rtp
415 (struct objc_super *, struct message_ref_t*, ...); */
416 type = build_varargs_function_type_list (objc_object_type,
417 objc_super_type,
418 objc_v2_super_selector_type,
419 NULL_TREE);
420 umsg_id_super2_fixup_decl = add_builtin_function ("objc_msgSendSuper2_fixup",
421 type, 0, NOT_BUILT_IN,
422 NULL, NULL_TREE);
423 TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
425 /* id objc_msgSendSuper2_stret_fixup_rtp
426 (struct objc_super *, struct message_ref_t*, ...); */
427 umsg_id_super2_stret_fixup_decl =
428 add_builtin_function ("objc_msgSendSuper2_stret_fixup",
429 type, 0, NOT_BUILT_IN,
430 NULL, NULL_TREE);
431 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
433 /* Present in the library, but unused by the FE. */
434 /* Protocol *objc_getProtocol (const char *)
435 type = build_function_type_list (objc_protocol_type,
436 const_string_type_node,
437 NULL_TREE);
438 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
439 type, 0, NOT_BUILT_IN,
440 NULL, NULL_TREE);
441 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
443 UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
444 "_objc_empty_cache");
446 UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
447 "_objc_empty_vtable");
449 /* id objc_getClass (const char *); */
450 type = build_function_type_list (objc_object_type,
451 const_string_type_node,
452 NULL_TREE);
453 objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
454 type, 0, NOT_BUILT_IN,
455 NULL, NULL_TREE);
457 /* id objc_getMetaClass (const char *); */
458 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
459 type, 0, NOT_BUILT_IN,
460 NULL, NULL_TREE);
462 /* This is the type of all of the following functions
463 objc_copyStruct(). */
464 type = build_function_type_list (void_type_node,
465 ptr_type_node,
466 const_ptr_type_node,
467 ptrdiff_type_node,
468 boolean_type_node,
469 boolean_type_node,
470 NULL_TREE);
471 /* Declare the following function:
472 void
473 objc_copyStruct (void *destination, const void *source,
474 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
475 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
476 type, 0, NOT_BUILT_IN,
477 NULL, NULL_TREE);
478 TREE_NOTHROW (objc_copyStruct_decl) = 0;
479 objc_getPropertyStruct_decl = NULL_TREE;
480 objc_setPropertyStruct_decl = NULL_TREE;
482 gcc_assert (!flag_objc_sjlj_exceptions);
484 /* Although we warn that fobjc-exceptions is required for exceptions
485 code, we carry on and create it anyway. */
487 /* This can be required, even when exceptions code is not present,
488 when an __attribute__((objc_exception)) is applied to a
489 class. */
490 build_v2_ehtype_template ();
492 /* void * objc_begin_catch (void *) */
493 type = build_function_type_list (ptr_type_node,
494 ptr_type_node, NULL_TREE);
496 objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
497 type, 0, NOT_BUILT_IN,
498 NULL, NULL_TREE);
499 TREE_NOTHROW (objc2_begin_catch_decl) = 0;
501 /* void objc_end_catch () */
502 type = build_function_type_list (void_type_node, NULL_TREE);
503 objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
504 type, 0, NOT_BUILT_IN,
505 NULL, NULL_TREE);
506 TREE_NOTHROW (objc2_end_catch_decl) = 0;
508 /* void objc_exception_rethrow (void) */
509 objc_rethrow_exception_decl =
510 add_builtin_function ("objc_exception_rethrow",
511 type, 0, NOT_BUILT_IN,
512 NULL, NULL_TREE);
513 TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
514 using_eh_for_cleanups ();
515 lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
516 lang_hooks.eh_personality = objc_eh_personality;
519 /* NOTE --- templates --- */
521 /* Set 'objc_v2_message_ref_template' to the data type node for
522 'struct _message_ref_t'. This needs to be done just once per
523 compilation. Also Set 'objc_v2_super_message_ref_template' to data
524 type node for 'struct _super_message_ref_t'. */
526 /* struct _message_ref_t
528 IMP messenger;
529 SEL name;
531 where IMP is: id (*) (id, _message_ref_t*, ...)
534 /* struct _super_message_ref_t
536 SUPER_IMP messenger;
537 SEL name;
539 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
542 static void
543 build_v2_message_ref_templates (void)
545 tree ptr_message_ref_t;
546 tree decls, *chain = NULL;
548 /* struct _message_ref_t {...} */
549 objc_v2_message_ref_template =
550 objc_start_struct (get_identifier ("_message_ref_t"));
552 /* IMP messenger; */
553 ptr_message_ref_t =
554 build_pointer_type (xref_tag (RECORD_TYPE,
555 get_identifier ("_message_ref_t")));
557 objc_v2_imp_type =
558 build_pointer_type (build_function_type_list
559 (objc_object_type,
560 objc_object_type,
561 ptr_message_ref_t,
562 NULL_TREE));
564 decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
566 /* SEL name; */
567 add_field_decl (objc_selector_type, "name", &chain);
569 objc_finish_struct (objc_v2_message_ref_template, decls);
571 objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
573 chain = NULL;
574 /* struct _super_message_ref_t {...} */
575 objc_v2_super_message_ref_template =
576 objc_start_struct (get_identifier ("_super_message_ref_t"));
578 /* SUPER_IMP messenger; */
579 ptr_message_ref_t = build_pointer_type
580 (xref_tag (RECORD_TYPE,
581 get_identifier ("_super_message_ref_t")));
583 objc_v2_super_imp_type =
584 build_pointer_type (build_function_type_list
585 (objc_object_type,
586 objc_super_type,
587 ptr_message_ref_t,
588 NULL_TREE));
590 add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
592 /* SEL name; */
593 add_field_decl (objc_selector_type, "name", &chain);
595 objc_finish_struct (objc_v2_super_message_ref_template, decls);
596 objc_v2_super_selector_type =
597 build_pointer_type (objc_v2_super_message_ref_template);
600 /* Build following types which represent each class implementation.
602 struct class_ro_t
604 uint32_t const flags;
605 uint32_t const instanceStart;
606 uint32_t const instanceSize;
607 #ifdef __LP64__
608 uint32_t const reserved;
609 #endif
610 const uint8_t * const ivarLayout;
611 const char *const name;
612 const struct method_list_t * const baseMethods;
613 const struct objc_protocol_list *const baseProtocols;
614 const struct ivar_list_t *const ivars;
615 const uint8_t * const weakIvarLayout;
616 const struct _prop_list_t * const properties;
619 struct class_t
621 struct class_t *isa;
622 struct class_t *superclass;
623 void *cache;
624 IMP *vtable;
626 ...When this is active - it will point to a rw version, but
627 when we build the meta-data we point it to the ro...
628 struct class_ro_t *data;
633 static void
634 build_v2_class_templates (void)
636 tree cnst_strg_type;
637 tree decls, *chain = NULL;
639 /* struct class_ro_t {...} */
640 objc_v2_class_ro_template =
641 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
643 /* uint32_t const flags; */
644 decls = add_field_decl (integer_type_node, "flags", &chain);
646 /* uint32_t const instanceStart; */
647 add_field_decl (integer_type_node, "instanceStart", &chain);
649 /* uint32_t const instanceSize; */
650 add_field_decl (integer_type_node, "instanceSize", &chain);
652 /* This ABI is currently only used on m64 NeXT. We always
653 explicitly declare the alignment padding. */
654 /* uint32_t const reserved; */
655 add_field_decl (integer_type_node, "reserved", &chain);
657 /* const uint8_t * const ivarLayout; */
658 cnst_strg_type = build_pointer_type (unsigned_char_type_node);
659 add_field_decl (cnst_strg_type, "ivarLayout", &chain);
661 /* const char *const name; */
662 add_field_decl (string_type_node, "name", &chain);
664 /* const struct method_list_t * const baseMethods; */
665 add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
667 /* const struct objc_protocol_list *const baseProtocols; */
668 add_field_decl (build_pointer_type
669 (xref_tag (RECORD_TYPE,
670 get_identifier (UTAG_V2_PROTOCOL_LIST))),
671 "baseProtocols", &chain);
673 /* const struct ivar_list_t *const ivars; */
674 add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
676 /* const uint8_t * const weakIvarLayout; */
677 add_field_decl (cnst_strg_type, "weakIvarLayout", &chain);
679 /* struct _prop_list_t * baseProperties; */
680 add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
682 objc_finish_struct (objc_v2_class_ro_template, decls);
684 chain = NULL;
685 /* struct class_t {...} */
686 objc_v2_class_template =
687 objc_start_struct (get_identifier (UTAG_V2_CLASS));
689 /* struct class_t *isa; */
690 decls = add_field_decl (build_pointer_type (objc_v2_class_template),
691 "isa", &chain);
693 /* struct class_t * const superclass; */
694 add_field_decl (build_pointer_type (objc_v2_class_template),
695 "superclass", &chain);
697 /* void *cache; */
698 add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
700 /* IMP *vtable; */
701 add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
703 /* struct class_ro_t *ro; */
704 add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
706 objc_finish_struct (objc_v2_class_template, decls);
709 /* struct _objc_super
711 struct _objc_object *self;
712 Class cls;
713 }; */
714 void
715 build_v2_super_template (void)
717 tree decls, *chain = NULL;
719 objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
721 /* struct _objc_object *self; */
722 decls = add_field_decl (objc_object_type, "self", &chain);
724 /* Class cls; */
725 add_field_decl (objc_class_type, "cls", &chain);
727 objc_finish_struct (objc_super_template, decls);
730 /* struct protocol_t
732 Class isa;
733 const char * const protocol_name;
734 const struct protocol_list_t * const protocol_list;
735 const struct method_list_t * const instance_methods;
736 const struct method_list_t * const class_methods;
737 const struct method_list_t * optionalInstanceMethods;
738 const struct method_list_t * optionalClassMethod
739 const struct _prop_list_t * const properties;
740 const uint32_t size;
741 const uint32_t flags;
744 static void
745 build_v2_protocol_template (void)
747 tree decls, *chain = NULL;
749 objc_v2_protocol_template =
750 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
752 /* Class isa; */
753 decls = add_field_decl (objc_object_type, "isa", &chain);
755 /* char *protocol_name; */
756 add_field_decl (string_type_node, "protocol_name", &chain);
758 /* const struct protocol_list_t * const protocol_list; */
759 add_field_decl (build_pointer_type (objc_v2_protocol_template),
760 "protocol_list", &chain);
762 /* const struct method_list_t * const instance_methods; */
763 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
765 /* const struct method_list_t * const class_methods; */
766 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
768 /* const struct method_list_t * optionalInstanceMethods; */
769 add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
771 /* const struct method_list_t * optionalClassMethods; */
772 add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
774 /* struct _prop_list_t * properties; */
775 add_field_decl (objc_prop_list_ptr, "properties", &chain);
777 /* const uint32_t size; */
778 add_field_decl (integer_type_node, "size", &chain);
780 /* const uint32_t flags; */
781 add_field_decl (integer_type_node, "flags", &chain);
783 objc_finish_struct (objc_v2_protocol_template, decls);
786 /* Build type for a category:
787 struct category_t
789 const char * const name;
790 struct class_t *const cls;
791 const struct method_list_t * const instance_methods;
792 const struct method_list_t * const class_methods;
793 const struct protocol_list_t * const protocols;
794 const struct _prop_list_t * const properties;
798 static void
799 build_v2_category_template (void)
801 tree decls, *chain = NULL;
803 objc_v2_category_template =
804 objc_start_struct (get_identifier ("_category_t"));
806 /* char *name; */
807 decls = add_field_decl (string_type_node, "name", &chain);
809 /* struct class_t *const cls; */
810 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
812 /* struct method_list_t *instance_methods; */
813 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
815 /* struct method_list_t *class_methods; */
816 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
818 /* struct protocol_list_t *protocol_list; */
819 add_field_decl (build_pointer_type (objc_v2_protocol_template),
820 "protocol_list", &chain );
822 /* struct _prop_list_t * properties; */
823 add_field_decl (objc_prop_list_ptr, "properties", &chain);
825 objc_finish_struct (objc_v2_category_template, decls);
828 /* NOTE --- Decls, Identifiers, Names etc. --- */
830 /* This routine is given a name and returns a matching extern variable
831 if one is found. */
833 static tree
834 hash_name_lookup (hash *hashlist, tree name)
836 hash target;
838 target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
840 while (target)
842 if (name == DECL_NAME (target->key))
843 return target->key;
845 target = target->next;
847 return 0;
850 /* This routine is given an extern variable and enters it in its hash
851 table. Note that hashing is done on its inner IDENTIFIER_NODE
852 node. */
854 static void
855 hash_name_enter (hash *hashlist, tree id)
857 hash obj;
858 int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
860 obj = ggc_alloc<hashed_entry> ();
861 obj->list = 0;
862 obj->next = hashlist[slot];
863 obj->key = id;
865 hashlist[slot] = obj; /* append to front */
868 /* Create a declaration "extern <type> <name>;"
869 The var will need to be finalized (e.g. by calling finish_var_decl()). */
871 static tree
872 create_extern_decl (tree type, const char *name)
874 tree id = get_identifier (name);
875 tree var = hash_name_lookup (extern_names, id);
876 if (var)
877 return var;
878 /* New name. */
879 var = start_var_decl (type, name);
880 TREE_STATIC (var) = 0;
881 DECL_EXTERNAL (var) = 1;
882 TREE_PUBLIC (var) = 1;
883 hash_name_enter (extern_names, var);
884 return var;
887 /* Create a globally visible definition for variable NAME of a given TYPE. The
888 finish_var_decl() routine will need to be called on it afterwards. */
890 static tree
891 create_global_decl (tree type, const char *name)
893 tree id = get_identifier (name);
894 tree var = hash_name_lookup (extern_names, id);
895 if (var)
897 DECL_EXTERNAL (var) = 0;
898 TREE_STATIC (var) = 1;
900 else
902 var = start_var_decl (type, name);
903 hash_name_enter (extern_names, var);
905 TREE_PUBLIC (var) = 1;
906 return var;
909 /* Create a symbol with __attribute__ ((visibility ("hidden")))
910 attribute (private extern). */
912 static tree
913 create_hidden_decl (tree type, const char *name)
915 tree decl = create_global_decl (type, name);
916 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
917 DECL_VISIBILITY_SPECIFIED (decl) = 1;
918 return decl;
921 /* Irritatingly, we have a different superclass field name for ABI=2. */
922 /* PS/TODO: The field name does not matter, it is only used internally
923 by the compiler. We can rename it to whatever we want. ;-) */
925 static tree
926 next_runtime_abi_02_super_superclassfield_id (void)
928 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
929 most look it once at startup then always return it. */
930 if (!super_superclassfield_id)
931 super_superclassfield_id = get_identifier ("cls");
932 return super_superclassfield_id;
935 static tree
936 next_runtime_abi_02_class_decl (tree klass)
938 tree decl;
939 char buf[BUFSIZE];
940 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
941 IDENTIFIER_POINTER (CLASS_NAME (klass)));
942 /* ObjC2 classes are extern visible. */
943 decl = create_global_decl (objc_v2_class_template, buf);
944 OBJCMETA (decl, objc_meta, meta_class);
945 return decl;
948 static tree
949 next_runtime_abi_02_metaclass_decl (tree klass)
951 tree decl;
952 char buf[BUFSIZE];
953 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
954 IDENTIFIER_POINTER (CLASS_NAME (klass)));
955 /* ObjC2 classes are extern visible. */
956 decl = create_global_decl (objc_v2_class_template, buf);
957 OBJCMETA (decl, objc_meta, meta_metaclass);
958 return decl;
961 static tree
962 next_runtime_abi_02_category_decl (tree klass)
964 tree decl;
965 char buf[BUFSIZE];
966 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
967 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
968 IDENTIFIER_POINTER (CLASS_NAME (klass)));
969 decl = start_var_decl (objc_v2_category_template, buf);
970 OBJCMETA (decl, objc_meta, meta_category);
971 return decl;
974 static tree
975 next_runtime_abi_02_protocol_decl (tree p)
977 tree decl;
978 char buf[BUFSIZE];
980 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
981 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
982 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
983 decl = start_var_decl (objc_v2_protocol_template, buf);
984 OBJCMETA (decl, objc_meta, meta_protocol);
985 return decl;
988 static tree
989 next_runtime_abi_02_string_decl (tree type, const char *name, string_section where)
991 tree var = start_var_decl (type, name);
992 switch (where)
994 case class_names:
995 OBJCMETA (var, objc_meta, meta_class_name);
996 break;
997 case meth_var_names:
998 OBJCMETA (var, objc_meta, meta_meth_name);
999 break;
1000 case meth_var_types:
1001 OBJCMETA (var, objc_meta, meta_meth_type);
1002 break;
1003 case prop_names_attr:
1004 OBJCMETA (var, objc_meta, meta_prop_name_attr);
1005 break;
1006 default:
1007 OBJCMETA (var, objc_meta, meta_base);
1008 break;
1010 return var;
1013 /* NOTE --- entry --- */
1015 typedef struct GTY(()) ident_data_tuple {
1016 tree ident;
1017 tree data;
1018 } ident_data_tuple ;
1020 /* This routine creates a file scope static variable of type 'Class'
1021 to hold the address of a class. */
1023 static tree
1024 build_v2_class_reference_decl (tree ident)
1026 tree decl;
1027 char buf[BUFSIZE];
1029 snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1030 decl = start_var_decl (objc_class_type, buf);
1031 OBJCMETA (decl, objc_meta, meta_class_ref);
1032 return decl;
1035 /* This routine builds a class refs entry for each class name used.
1036 Initially, a (static-ref, IDENT) tuple is added to the list. The
1037 ident is replaced with address of the class metadata (of type
1038 'Class') in the output routine. */
1040 static GTY (()) vec<ident_data_tuple, va_gc> *classrefs;
1042 static tree
1043 objc_v2_get_class_reference (tree ident)
1045 tree decl;
1046 ident_data_tuple e;
1047 if (classrefs)
1049 int count;
1050 ident_data_tuple *ref;
1051 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1053 if (ref->ident == ident)
1055 if (!ref->data)
1056 ref->data = build_v2_class_reference_decl (ident);
1057 return ref->data;
1061 else
1062 /* Somewhat arbitrary initial provision. */
1063 vec_alloc (classrefs, 16);
1065 /* We come here if we don't find the entry - or if the table was yet
1066 to be created. */
1067 decl = build_v2_class_reference_decl (ident);
1068 e.ident = ident;
1069 e.data = decl;
1070 vec_safe_push (classrefs, e);
1071 return decl;
1074 static tree
1075 next_runtime_abi_02_get_class_reference (tree ident)
1077 if (!flag_zero_link)
1078 return objc_v2_get_class_reference (ident);
1079 else
1081 /* We fall back to using objc_getClass (). */
1082 vec<tree, va_gc> *v;
1083 vec_alloc (v, 1);
1084 tree t;
1085 /* ??? add_class_reference (ident); - is pointless, since the
1086 system lib does not export the equivalent symbols. Maybe we
1087 need to build a class ref anyway. */
1088 t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1089 IDENTIFIER_POINTER (ident));
1090 v->quick_push (t);
1091 t = build_function_call_vec (input_location, vNULL, objc_get_class_decl,
1092 v, 0);
1093 vec_free (v);
1094 return t;
1098 /* Used by build_function_type_for_method. Append the types for
1099 receiver & _cmd at the start of a method argument list to ARGTYPES.
1100 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1101 trying to define a method or call one. SUPERFLAG says this is for a
1102 send to super. METH may be NULL, in the case that there is no
1103 prototype. */
1105 static void
1106 next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1107 tree meth, int context,
1108 int superflag)
1110 tree receiver_type;
1112 if (superflag)
1113 receiver_type = objc_super_type;
1114 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1115 receiver_type = objc_instance_type;
1116 else
1117 receiver_type = objc_object_type;
1119 vec_safe_push (*argtypes, receiver_type);
1120 /* Selector type - will eventually change to `int'. */
1121 vec_safe_push (*argtypes,
1122 superflag ? objc_v2_super_selector_type
1123 : objc_v2_selector_type);
1126 /* TODO: Merge this with the message refs. */
1127 static tree
1128 build_selector_reference_decl (tree ident)
1130 tree decl;
1131 char *t, buf[BUFSIZE];
1133 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1134 t = buf;
1135 while (*t)
1137 if (*t==':')
1138 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1139 t++;
1141 decl = start_var_decl (objc_selector_type, buf);
1142 OBJCMETA (decl, objc_meta, meta_sel_refs);
1143 return decl;
1146 static tree
1147 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1148 tree ident,
1149 tree proto ATTRIBUTE_UNUSED)
1151 tree *chain = &sel_ref_chain;
1152 tree expr;
1154 while (*chain)
1156 if (TREE_VALUE (*chain) == ident)
1157 return TREE_PURPOSE (*chain);
1159 chain = &TREE_CHAIN (*chain);
1162 expr = build_selector_reference_decl (ident);
1163 *chain = tree_cons (expr, ident, NULL_TREE);
1165 return expr;
1168 /* Declare a variable of type 'struct message_ref_t'. */
1169 /* This will be finished in build_v2_message_ref_translation_table ().
1170 We take an idea from LLVM in making the names a bit more connected
1171 and thus the asm more readable. */
1173 static tree
1174 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1176 tree decl;
1177 char buf[BUFSIZE], *t;
1178 int offset = 12;
1180 /* Skip past the objc_msgSend it's the same for all... */
1181 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1182 offset++;
1184 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1185 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1186 IDENTIFIER_POINTER (sel_name));
1187 t = buf;
1188 while (*t)
1190 if (*t==':')
1191 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1192 t++;
1194 decl = start_var_decl (objc_v2_message_ref_template, buf);
1195 OBJCMETA (decl, objc_meta, meta_mref);
1196 return decl;
1199 typedef struct GTY(()) msgref_entry {
1200 tree func;
1201 tree selname;
1202 tree refdecl;
1203 } msgref_entry;
1205 static GTY (()) vec<msgref_entry, va_gc> *msgrefs;
1207 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1208 later on to initialize the table of 'struct message_ref_t'
1209 elements. */
1211 static tree
1212 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1214 tree decl;
1215 msgref_entry e;
1216 if (msgrefs)
1218 int count;
1219 msgref_entry *ref;
1220 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1221 if (ref->func == message_func_decl && ref->selname == sel_name)
1222 return ref->refdecl;
1224 else
1225 /* Somewhat arbitrary initial provision. */
1226 vec_alloc (msgrefs, 32);
1228 /* We come here if we don't find a match or at the start. */
1229 decl = build_v2_message_reference_decl (sel_name,
1230 DECL_NAME (message_func_decl));
1231 e.func = message_func_decl;
1232 e.selname = sel_name;
1233 e.refdecl = decl;
1234 vec_safe_push (msgrefs, e);
1235 return decl;
1238 static tree
1239 build_v2_protocollist_ref_decl (tree protocol)
1241 tree decl;
1242 tree protocol_ident = PROTOCOL_NAME (protocol);
1243 char buf[BUFSIZE];
1245 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1246 IDENTIFIER_POINTER (protocol_ident));
1247 /* TODO: other compiler versions make these hidden & weak. */
1248 decl = create_global_decl (objc_protocol_type, buf);
1249 /* Let optimizer know that this decl is not removable. */
1250 DECL_PRESERVE_P (decl) = 1;
1251 OBJCMETA (decl, objc_meta, meta_proto_ref);
1252 return decl;
1255 typedef struct GTY(()) prot_list_entry {
1256 tree id;
1257 tree refdecl;
1258 } prot_list_entry;
1259 static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
1261 static tree
1262 objc_v2_get_protocol_reference (tree ident)
1264 tree decl;
1265 prot_list_entry e;
1266 if (protrefs)
1268 int count;
1269 prot_list_entry *ref;
1270 FOR_EACH_VEC_ELT (*protrefs, count, ref)
1272 if (ref->id == ident)
1274 if (!ref->refdecl)
1275 ref->refdecl = build_v2_protocollist_ref_decl (ident);
1276 return ref->refdecl;
1280 else
1281 /* Somewhat arbitrary initial provision. */
1282 vec_alloc (protrefs, 32);
1284 /* We come here if we don't find the entry - or if the table was yet
1285 to be created. */
1286 decl = build_v2_protocollist_ref_decl (ident);
1287 e.id = ident;
1288 e.refdecl = decl;
1289 vec_safe_push (protrefs, e);
1290 return decl;
1293 static tree
1294 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1295 tree p)
1297 if (!PROTOCOL_FORWARD_DECL (p))
1298 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1300 return objc_v2_get_protocol_reference (p);
1303 /* This routine returns the ivar declaration, if component is a valid
1304 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1305 returns the class name in CLASS. */
1307 static tree
1308 objc_is_ivar (tree expr, tree component, tree *klass)
1310 tree field = NULL_TREE;
1311 tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1313 if (TREE_CODE (basetype) == RECORD_TYPE
1314 && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1316 *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1317 if (*klass)
1321 tree ivar_chain = CLASS_RAW_IVARS (*klass);
1322 if (ivar_chain)
1324 field = is_ivar (ivar_chain, component);
1325 if (field != NULL_TREE)
1326 break;
1328 *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1330 while (*klass);
1333 return field;
1336 static void
1337 create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1339 tree fname = DECL_NAME (field_decl);
1341 sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1342 IDENTIFIER_POINTER (fname));
1343 return;
1346 /* This routine generates new abi's ivar reference tree. It amounts
1347 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1348 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1349 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1351 static tree
1352 objc_v2_build_ivar_ref (tree datum, tree component)
1354 tree field, ref, class_name, offset, ftype, expr;
1355 char var_offset_name[512];
1357 field = objc_is_ivar (datum, component, &class_name);
1358 if (!field)
1359 return NULL_TREE;
1361 /* This routine only handles non-bitfield fields */
1362 /* DECL_INITIAL macro is set to width of bitfield and can be relied
1363 on to check for bitfield ivars. Note that I cannot rely on
1364 DECL_BIT_FIELD macro because it is only set when the whole struct
1365 is seen (at finish_struct) and not when the ivar chain is
1366 built. */
1367 if (DECL_INITIAL (field))
1368 return NULL_TREE;
1370 create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field);
1372 offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1374 ftype = TREE_TYPE (field);
1376 /* (char*)datum */
1377 expr = build_c_cast (input_location,
1378 string_type_node, build_fold_addr_expr (datum));
1380 /* (char*)datum + offset */
1381 expr = fold_build_pointer_plus_loc (input_location, expr, offset);
1383 /* (ftype*)((char*)datum + offset) */
1384 expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1386 /* Finally: *(ftype*)((char*)datum + offset) */
1387 ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1389 /* We must set type of the resulting expression to be the same as
1390 the field type. This is because, build_indirect_ref (...)
1391 rebuilds the type which may result in lost information; as in the
1392 case of protocol-qualified types (id <protocol> ). */
1393 TREE_TYPE (ref) = ftype;
1395 if (TREE_READONLY (datum) || TREE_READONLY (field))
1396 TREE_READONLY (ref) = 1;
1398 if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1399 TREE_THIS_VOLATILE (ref) = 1;
1401 if (TREE_DEPRECATED (field))
1402 warn_deprecated_use (field, NULL_TREE);
1404 return ref;
1407 /* IVAR refs are made via an externally referenceable offset and built
1408 on the fly. That is, unless they refer to (private) fields in the
1409 class structure. */
1410 static tree
1411 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1412 tree base, tree id)
1414 tree ivar;
1415 if ((ivar = objc_v2_build_ivar_ref (base, id)))
1416 return ivar;
1417 return objc_build_component_ref (base, id);
1420 /* [super ...] references are listed here (and built into a table at
1421 meta -data emit time). */
1422 static tree
1423 build_v2_superclass_ref_decl (tree ident, bool inst)
1425 tree decl;
1426 char buf[BUFSIZE];
1428 snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1429 IDENTIFIER_POINTER (ident));
1430 decl = start_var_decl (objc_class_type, buf);
1431 OBJCMETA (decl, objc_meta, meta_superclass_ref);
1432 return decl;
1435 static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs;
1436 static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs;
1438 static tree
1439 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1440 struct imp_entry *imp, bool inst_meth)
1442 tree decl;
1443 ident_data_tuple e;
1444 tree id = CLASS_NAME (imp->imp_context);
1445 vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs
1446 : metaclass_super_refs;
1448 if (list)
1450 int count;
1451 ident_data_tuple *ref;
1452 FOR_EACH_VEC_ELT (*list, count, ref)
1454 if (ref->ident == id)
1456 if (!ref->data)
1457 ref->data = build_v2_superclass_ref_decl (id, inst_meth);
1458 return ref->data;
1462 else
1464 /* Somewhat arbitrary initial provision. */
1465 if (inst_meth)
1467 vec_alloc (class_super_refs, 16);
1468 list = class_super_refs;
1470 else
1472 vec_alloc (metaclass_super_refs, 16);
1473 list = metaclass_super_refs;
1476 /* We come here if we don't find the entry - or if the table was yet
1477 to be created. */
1478 decl = build_v2_superclass_ref_decl (id, inst_meth);
1479 e.ident = id;
1480 e.data = decl;
1481 vec_safe_push (list, e);
1482 return decl;
1485 static tree
1486 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1487 struct imp_entry *imp, bool inst_meth)
1489 /* ??? is this OK when zero-link = true? */
1490 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1491 tree super_class;
1493 if (!flag_zero_link)
1495 super_class = objc_get_class_reference (CLASS_NAME (imp->imp_template));
1497 if (!inst_meth)
1499 /* If we are in a class method, we must retrieve the
1500 _metaclass_ for the current class, pointed at by the
1501 class's "isa" pointer. The following assumes that "isa" is
1502 the first ivar in a class (which it must be). */
1503 super_class =
1504 build_indirect_ref (input_location,
1505 build_c_cast (input_location,
1506 build_pointer_type (objc_class_type),
1507 super_class),
1508 RO_UNARY_STAR);
1509 return super_class;
1511 /* ??? Do we need to add the class ref anway for zero-link? */
1512 /* else do it the slow way. */
1513 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
1514 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1515 IDENTIFIER_POINTER (super_name));
1516 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1517 return build_function_call (input_location,
1518 super_class,
1519 build_tree_list (NULL_TREE, super_name));
1522 static tree
1523 next_runtime_abi_02_receiver_is_class_object (tree receiver)
1525 if (TREE_CODE (receiver) == VAR_DECL
1526 && IS_CLASS (TREE_TYPE (receiver))
1527 && vec_safe_length (classrefs))
1529 int count;
1530 ident_data_tuple *ref;
1531 /* The receiver is a variable created by build_class_reference_decl. */
1532 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1533 if (ref->data == receiver)
1534 return ref->ident;
1536 return NULL_TREE;
1539 /* Assign all arguments in VALUES which have side-effect to a temporary
1540 and replaced that argument in VALUES list with the temporary. The
1541 arguments will be passed to a function with FNTYPE. */
1543 static tree
1544 objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1546 tree valtail;
1547 function_args_iterator iter;
1549 /* Skip over receiver and the &_msf_ref types. */
1550 function_args_iter_init (&iter, fntype);
1551 function_args_iter_next (&iter);
1552 function_args_iter_next (&iter);
1554 for (valtail = values; valtail;
1555 valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
1557 tree value = TREE_VALUE (valtail);
1558 tree type = function_args_iter_cond (&iter);
1559 if (type == NULL_TREE)
1560 break;
1561 if (!TREE_SIDE_EFFECTS (value))
1562 continue;
1563 /* To prevent re-evaluation. */
1564 value = save_expr (value);
1565 add_stmt (value);
1566 TREE_VALUE (valtail) = value;
1568 return values;
1571 /* Build the new abi's messaging library call. It looks like:
1572 (*_msg.messenger) (receiver, &_msg, ...) */
1574 static tree
1575 build_v2_build_objc_method_call (int super_flag, tree method_prototype,
1576 tree lookup_object, tree selector,
1577 tree method_params,
1578 bool check_for_nil)
1580 tree ret_val;
1581 tree sender, rcv_p, t;
1582 tree ret_type
1583 = (method_prototype
1584 ? TREE_VALUE (TREE_TYPE (method_prototype))
1585 : objc_object_type);
1586 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1587 METHOD_REF, super_flag);
1588 tree sender_cast;
1590 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1591 ftype = build_type_attribute_variant (
1592 ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1594 sender_cast = build_pointer_type (ftype);
1596 if (check_for_nil)
1597 method_params = objc_copy_to_temp_side_effect_params (ftype,
1598 method_params);
1600 /* Get &message_ref_t.messenger. */
1601 sender = build_c_cast (input_location,
1602 build_pointer_type (super_flag
1603 ? objc_v2_super_imp_type
1604 : objc_v2_imp_type),
1605 selector);
1607 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1609 rcv_p = (super_flag ? objc_super_type : objc_object_type);
1611 lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1613 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1614 lookup_object = save_expr (lookup_object);
1616 method_params = tree_cons (NULL_TREE, lookup_object,
1617 tree_cons (NULL_TREE, selector,
1618 method_params));
1619 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
1620 ret_val = build_function_call (input_location, t, method_params);
1621 if (check_for_nil)
1623 /* receiver != nil ? ret_val : 0 */
1624 tree ftree;
1625 tree ifexp;
1627 if (TREE_CODE (ret_type) == RECORD_TYPE
1628 || TREE_CODE (ret_type) == UNION_TYPE)
1630 vec<constructor_elt, va_gc> *rtt = NULL;
1631 /* ??? CHECKME. hmmm..... think we need something more
1632 here. */
1633 CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE);
1634 ftree = objc_build_constructor (ret_type, rtt);
1636 else
1637 ftree = fold_convert (ret_type, integer_zero_node);
1639 ifexp = build_binary_op (input_location, NE_EXPR,
1640 lookup_object,
1641 fold_convert (rcv_p, integer_zero_node), 1);
1643 #ifdef OBJCPLUS
1644 ret_val = build_conditional_expr (input_location,
1645 ifexp, ret_val, ftree,
1646 tf_warning_or_error);
1647 #else
1648 /* ??? CHECKME. */
1649 ret_val = build_conditional_expr (input_location,
1650 ifexp, 1,
1651 ret_val, NULL_TREE,
1652 ftree, NULL_TREE);
1653 #endif
1655 return ret_val;
1658 static tree
1659 next_runtime_abi_02_build_objc_method_call (location_t loc,
1660 tree method_prototype,
1661 tree receiver,
1662 tree rtype,
1663 tree sel_name,
1664 tree method_params,
1665 int super)
1667 tree ret_type, selector;
1668 tree message_func_decl;
1669 bool check_for_nil = flag_objc_nilcheck;
1671 ret_type = method_prototype
1672 ? TREE_VALUE (TREE_TYPE (method_prototype))
1673 : objc_object_type;
1675 /* Do we need to check for nil receivers ? */
1676 /* For now, message sent to classes need no nil check. In the
1677 future, class declaration marked as weak_import must be nil
1678 checked. */
1679 if (super
1680 || (TREE_CODE (receiver) == VAR_DECL
1681 && TREE_TYPE (receiver) == objc_class_type))
1682 check_for_nil = false;
1684 if (!targetm.calls.struct_value_rtx (0, 0)
1685 && (TREE_CODE (ret_type) == RECORD_TYPE
1686 || TREE_CODE (ret_type) == UNION_TYPE)
1687 && targetm.calls.return_in_memory (ret_type, 0))
1689 if (super)
1690 message_func_decl = umsg_id_super2_stret_fixup_decl;
1691 else
1692 message_func_decl = objc_is_id (rtype)
1693 ? umsg_id_stret_fixup_decl
1694 : umsg_stret_fixup_decl;
1696 else
1698 if (super)
1699 message_func_decl = umsg_id_super2_fixup_decl;
1700 else
1701 message_func_decl = objc_is_id (rtype)
1702 ? umsg_id_fixup_decl
1703 : umsg_fixup_decl;
1706 selector = build_v2_selector_messenger_reference (sel_name,
1707 message_func_decl);
1709 /* selector = &_msg; */
1710 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1712 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1713 : objc_v2_selector_type),
1714 selector);
1716 /* (*_msg.messenger) (receiver, &_msg, ...); */
1717 return build_v2_build_objc_method_call (super, method_prototype,
1718 receiver, selector,
1719 method_params, check_for_nil);
1722 /* NOTE --- Constant String Class Stuff --- */
1724 static bool
1725 next_runtime_abi_02_setup_const_string_class_decl (void)
1727 if (!constant_string_global_id)
1729 /* Hopefully, this should not represent a serious limitation. */
1730 char buf[BUFSIZE];
1731 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1732 constant_string_global_id = get_identifier (buf);
1735 string_class_decl = lookup_name (constant_string_global_id);
1737 /* In OBJC2 abi, constant string class reference refers to class
1738 name for NSConstantString class. This declaration may not be
1739 available yet (in fact it is not in most cases). So, declare an
1740 extern OBJC_CLASS_$_NSConstantString in its place. */
1741 if (!string_class_decl)
1742 string_class_decl =
1743 create_extern_decl (objc_v2_class_template,
1744 IDENTIFIER_POINTER (constant_string_global_id));
1746 return (string_class_decl != NULL_TREE);
1749 static tree
1750 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1751 int length)
1753 tree constructor, fields, var;
1754 vec<constructor_elt, va_gc> *v = NULL;
1756 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1757 fields = TYPE_FIELDS (internal_const_str_type);
1758 CONSTRUCTOR_APPEND_ELT (v, fields,
1759 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1761 fields = DECL_CHAIN (fields);
1762 CONSTRUCTOR_APPEND_ELT (v, fields,
1763 build_unary_op (loc, ADDR_EXPR, string, 1));
1765 /* ??? check if this should be long. */
1766 fields = DECL_CHAIN (fields);
1767 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1768 constructor = objc_build_constructor (internal_const_str_type, v);
1770 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1771 DECL_INITIAL (var) = constructor;
1772 TREE_STATIC (var) = 1;
1773 DECL_CONTEXT (var) = NULL;
1774 OBJCMETA (var, objc_meta, meta_const_str);
1775 return var;
1778 /* NOTE --- NeXT V2 Metadata templates --- */
1780 /* This routine builds the following type:
1781 struct _prop_t
1783 const char * const name; // property name
1784 const char * const attributes; // comma-delimited, encoded,
1785 // property attributes
1789 static tree
1790 build_v2_property_template (void)
1792 tree prop_record;
1793 tree decls, *chain = NULL;
1795 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1796 /* const char * name */
1797 decls = add_field_decl (string_type_node, "name", &chain);
1799 /* const char * attribute */
1800 add_field_decl (string_type_node, "attribute", &chain);
1802 objc_finish_struct (prop_record, decls);
1803 return prop_record;
1806 /* struct ivar_t
1808 unsigned long int *offset;
1809 char *name;
1810 char *type;
1811 uint32_t alignment;
1812 uint32_t size;
1816 static tree
1817 build_v2_ivar_t_template (void)
1819 tree objc_ivar_id, objc_ivar_record;
1820 tree decls, *chain = NULL;
1822 objc_ivar_id = get_identifier ("_ivar_t");
1823 objc_ivar_record = objc_start_struct (objc_ivar_id);
1825 /* unsigned long int *offset; */
1826 decls = add_field_decl (build_pointer_type
1827 (TREE_TYPE (size_zero_node)), "offset", &chain);
1829 /* char *name; */
1830 add_field_decl (string_type_node, "name", &chain);
1832 /* char *type; */
1833 add_field_decl (string_type_node, "type", &chain);
1835 /* uint32_t alignment; */
1836 add_field_decl (integer_type_node, "alignment", &chain);
1838 /* uint32_t size; */
1839 add_field_decl (integer_type_node, "size", &chain);
1841 objc_finish_struct (objc_ivar_record, decls);
1842 return objc_ivar_record;
1845 static void
1846 build_metadata_templates (void)
1849 if (!objc_method_template)
1850 objc_method_template = build_method_template ();
1852 if (!objc_v2_property_template)
1853 objc_v2_property_template = build_v2_property_template ();
1855 if (!objc_v2_ivar_template)
1856 objc_v2_ivar_template = build_v2_ivar_t_template ();
1860 /* NOTE --- Output NeXT V2 Metadata --- */
1862 /* Routine builds name of Interface's main meta-data of type class_t. */
1864 static char *
1865 objc_build_internal_classname (tree ident, bool metaclass)
1867 static char string[512];
1868 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
1869 : "OBJC_CLASS_$",
1870 IDENTIFIER_POINTER (ident));
1871 return string;
1874 /* Build the name for object of type struct class_ro_t */
1876 static const char *
1877 newabi_append_ro (const char *name)
1879 const char *dollar;
1880 char *p;
1881 static char string[BUFSIZE];
1882 dollar = strchr (name, '$');
1883 gcc_assert (dollar);
1884 p = string;
1885 *p = '_'; p++;
1886 strncpy (p, name, (int)(dollar - name));
1887 p += (int)(dollar - name);
1888 sprintf (p, "RO_%s", dollar);
1889 return string;
1892 /* Build the struct message_ref_t msg =
1893 {objc_msgSend_fixup_xxx, @selector(func)}
1894 table. */
1896 static
1897 void build_v2_message_ref_translation_table (void)
1899 int count;
1900 msgref_entry *ref;
1902 if (!vec_safe_length (msgrefs))
1903 return;
1905 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1907 vec<constructor_elt, va_gc> *initializer;
1908 tree expr, constructor;
1909 tree struct_type = TREE_TYPE (ref->refdecl);
1910 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
1912 initializer = NULL;
1913 /* First 'IMP messenger' field... */
1914 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
1915 expr = convert (objc_v2_imp_type, expr);
1916 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1918 /* ... then 'SEL name' field. */
1919 expr = build_selector (ref->selname);
1920 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1921 constructor = objc_build_constructor (struct_type, initializer);
1922 finish_var_decl (ref->refdecl, constructor);
1926 /* Build decl = initializer; for each externally visible class
1927 reference. */
1929 static void
1930 build_v2_classrefs_table (void)
1932 int count;
1933 ident_data_tuple *ref;
1935 if (!vec_safe_length (classrefs))
1936 return;
1938 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1940 tree expr = ref->ident;
1941 tree decl = ref->data;
1942 /* Interface with no implementation and yet one of its messages
1943 has been used. Need to generate a full address-of tree for it
1944 here. */
1945 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1947 const char *name = objc_build_internal_classname (expr, false);
1948 expr = create_extern_decl (objc_v2_class_template, name);
1949 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1951 /* The runtime wants this, even if it appears unused, so we must force the
1952 output.
1953 DECL_PRESERVE_P (decl) = 1; */
1954 finish_var_decl (decl, expr);
1958 /* Build decl = initializer; for each externally visible super class
1959 reference. */
1961 static void
1962 build_v2_super_classrefs_table (bool metaclass)
1964 int count;
1965 ident_data_tuple *ref;
1966 vec<ident_data_tuple, va_gc> *list = metaclass ? metaclass_super_refs
1967 : class_super_refs;
1969 if (!vec_safe_length (list))
1970 return;
1972 FOR_EACH_VEC_ELT (*list, count, ref)
1974 tree expr = ref->ident;
1975 tree decl = ref->data;
1976 /* Interface with no implementation and yet one of its messages
1977 has been used. Need to generate a full address-of tree for it
1978 here. */
1979 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1981 const char * name = objc_build_internal_classname (expr, metaclass);
1982 expr = create_extern_decl (objc_v2_class_template, name);
1983 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1985 finish_var_decl (decl, expr);
1989 /* Add the global class meta-data declaration to the list which later
1990 on ends up in the __class_list section. */
1992 static GTY(()) vec<tree, va_gc> *class_list;
1994 static void
1995 objc_v2_add_to_class_list (tree global_class_decl)
1997 vec_safe_push (class_list, global_class_decl);
2000 static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
2002 /* Add the global class meta-data declaration to the list which later
2003 on ends up in the __nonlazy_class section. */
2005 static void
2006 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2008 vec_safe_push (nonlazy_class_list, global_class_decl);
2011 static GTY(()) vec<tree, va_gc> *category_list;
2013 /* Add the category meta-data declaration to the list which later on
2014 ends up in the __nonlazy_category section. */
2016 static void
2017 objc_v2_add_to_category_list (tree decl)
2019 vec_safe_push (category_list, decl);
2022 static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
2024 /* Add the category meta-data declaration to the list which later on
2025 ends up in the __category_list section. */
2027 static void
2028 objc_v2_add_to_nonlazy_category_list (tree decl)
2030 vec_safe_push (nonlazy_category_list, decl);
2033 static bool
2034 has_load_impl (tree clsmeth)
2036 while (clsmeth)
2038 tree id = METHOD_SEL_NAME (clsmeth);
2039 if (IDENTIFIER_LENGTH (id) == 4
2040 && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
2041 return true;
2042 clsmeth = DECL_CHAIN (clsmeth);
2045 return false;
2048 /* Build a __{class,category}_list section table containing address of
2049 all @implemented {class,category} meta-data. */
2051 static void
2052 build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
2054 int count=0;
2055 tree type, decl, expr;
2056 vec<constructor_elt, va_gc> *initlist = NULL;
2058 if (!vec_safe_length (src))
2059 return;
2061 FOR_EACH_VEC_ELT (*src, count, decl)
2063 #ifndef OBJCPLUS
2064 tree purpose = build_int_cst (NULL_TREE, count);
2065 #else
2066 tree purpose = NULL_TREE;
2067 #endif
2068 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2069 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2071 gcc_assert (count > 0);
2072 type = build_array_type (objc_class_type,
2073 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2074 decl = start_var_decl (type, nam);
2075 /* The runtime wants this, even if it appears unused, so we must
2076 force the output. */
2077 DECL_PRESERVE_P (decl) = 1;
2078 expr = objc_build_constructor (type, initlist);
2079 OBJCMETA (decl, objc_meta, attr);
2080 finish_var_decl (decl, expr);
2083 /* Build decl = initializer; for each protocol referenced in
2084 @protocol(MyProt) expression. Refs as built in the entry section
2085 above. */
2087 static void
2088 build_v2_protocol_list_translation_table (void)
2090 int count;
2091 prot_list_entry *ref;
2093 if (!protrefs)
2094 return;
2096 FOR_EACH_VEC_ELT (*protrefs, count, ref)
2098 char buf[BUFSIZE];
2099 tree expr;
2100 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2101 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2102 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2103 expr = start_var_decl (objc_v2_protocol_template, buf);
2104 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2105 finish_var_decl (ref->refdecl, expr);
2107 /* TODO: Maybe we could explicitly delete the vec. now? */
2110 static GTY (()) vec<prot_list_entry, va_gc> *protlist;
2112 /* Add the local protocol meta-data declaration to the list which
2113 later on ends up in the __protocol_list section. */
2115 static void
2116 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2118 prot_list_entry e;
2119 if (!protlist)
2120 /* Arbitrary init count. */
2121 vec_alloc (protlist, 32);
2122 e.id = protocol_interface_decl;
2123 e.refdecl = protocol_decl;
2124 vec_safe_push (protlist, e);
2127 /* Build the __protocol_list section table containing address of all
2128 generate protocol_t meta-data. */
2130 static void
2131 build_v2_protocol_list_address_table (void)
2133 int count;
2134 prot_list_entry *ref;
2135 if (!vec_safe_length (protlist))
2136 return;
2138 FOR_EACH_VEC_ELT (*protlist, count, ref)
2140 tree decl, expr;
2141 char buf[BUFSIZE];
2142 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2143 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2144 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2145 decl = create_global_decl (objc_protocol_type, buf);
2146 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2147 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2148 finish_var_decl (decl, expr);
2151 /* TODO: delete the vec. */
2152 /* TODO: upgrade to the clang/llvm hidden version. */
2155 /* This routine declares a variable to hold meta data for 'struct
2156 protocol_list_t'. */
2158 static tree
2159 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2161 tree refs_decl, lproto, e, plist, ptempl_p_t;
2162 int size = 0;
2163 vec<constructor_elt, va_gc> *initlist = NULL;
2164 char buf[BUFSIZE];
2166 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2167 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2168 plist = CLASS_PROTOCOL_LIST (i_or_p);
2169 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2170 plist = PROTOCOL_LIST (i_or_p);
2171 else
2172 gcc_unreachable ();
2174 /* Compute size. */
2175 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2176 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2177 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2178 size++;
2180 /* Build initializer. */
2182 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2183 e = build_int_cst (ptempl_p_t, size);
2184 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2186 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2188 tree pval = TREE_VALUE (lproto);
2190 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2191 && PROTOCOL_FORWARD_DECL (pval))
2193 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2194 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2195 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2196 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2200 /* static struct protocol_list_t *list[size]; */
2202 switch (TREE_CODE (i_or_p))
2204 case PROTOCOL_INTERFACE_TYPE:
2205 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2206 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2207 break;
2208 case CLASS_INTERFACE_TYPE:
2209 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2210 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2211 break;
2212 case CATEGORY_INTERFACE_TYPE:
2213 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2214 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2215 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2216 break;
2217 default:
2218 gcc_unreachable ();
2221 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2222 buf);
2223 /* ObjC2 puts all these in the base section. */
2224 OBJCMETA (refs_decl, objc_meta, meta_base);
2225 DECL_PRESERVE_P (refs_decl) = 1;
2226 finish_var_decl (refs_decl,
2227 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2228 return refs_decl;
2231 /* This routine builds one 'struct method_t' initializer list. Note
2232 that the old ABI is supposed to build 'struct objc_method' which
2233 has 3 fields, but it does not build the initialization expression
2234 for 'method_imp' which for protocols is NULL any way. To be
2235 consistent with declaration of 'struct method_t', in the new ABI we
2236 set the method_t.imp to NULL. */
2238 static tree
2239 build_v2_descriptor_table_initializer (tree type, tree entries)
2241 vec<constructor_elt, va_gc> *initlist = NULL;
2244 vec<constructor_elt, va_gc> *eltlist = NULL;
2245 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2246 build_selector (METHOD_SEL_NAME (entries)));
2247 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2248 add_objc_string (METHOD_ENCODING (entries),
2249 meth_var_types));
2250 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2252 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2253 objc_build_constructor (type, eltlist));
2254 entries = TREE_CHAIN (entries);
2256 while (entries);
2258 return objc_build_constructor (build_array_type (type, 0), initlist);
2261 /* struct method_list_t
2263 uint32_t entsize;
2264 uint32_t method_count;
2265 struct objc_method method_list[method_count];
2266 }; */
2268 static tree
2269 build_v2_method_list_template (tree list_type, int size)
2271 tree method_list_t_record;
2272 tree array_type, decls, *chain = NULL;
2274 method_list_t_record = objc_start_struct (NULL_TREE);
2276 /* uint32_t const entsize; */
2277 decls = add_field_decl (integer_type_node, "entsize", &chain);
2279 /* int method_count; */
2280 add_field_decl (integer_type_node, "method_count", &chain);
2282 /* struct objc_method method_list[]; */
2283 array_type = build_sized_array_type (list_type, size);
2284 add_field_decl (array_type, "method_list", &chain);
2286 objc_finish_struct (method_list_t_record, decls);
2287 return method_list_t_record;
2290 /* Note, as above that we are building to the objc_method_template
2291 which has the *imp field. ABI0/1 build with
2292 objc_method_prototype_template which is missing this field. */
2293 static tree
2294 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2295 const char *prefix, tree attr)
2297 tree method_list_template, initlist, decl, methods;
2298 int size, entsize;
2299 vec<constructor_elt, va_gc> *v = NULL;
2300 char buf[BUFSIZE];
2302 if (!chain || !prefix)
2303 return NULL_TREE;
2305 methods = chain;
2306 size = 0;
2307 while (methods)
2309 if (! METHOD_ENCODING (methods))
2310 METHOD_ENCODING (methods) = encode_method_prototype (methods);
2311 methods = TREE_CHAIN (methods);
2312 size++;
2315 gcc_assert (size);
2316 method_list_template = build_v2_method_list_template (objc_method_template,
2317 size);
2318 snprintf (buf, BUFSIZE, "%s_%s", prefix,
2319 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2321 decl = start_var_decl (method_list_template, buf);
2323 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2324 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2325 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2326 initlist =
2327 build_v2_descriptor_table_initializer (objc_method_template,
2328 chain);
2329 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2330 /* Get into the right section. */
2331 OBJCMETA (decl, objc_meta, attr);
2332 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2333 return decl;
2336 /* This routine builds the initializer list to initialize the 'struct
2337 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2339 static tree
2340 build_v2_property_table_initializer (tree type, tree context)
2342 tree x;
2343 vec<constructor_elt, va_gc> *inits = NULL;
2344 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2345 x = CLASS_PROPERTY_DECL (context);
2346 else
2347 x = IMPL_PROPERTY_DECL (context);
2349 for (; x; x = TREE_CHAIN (x))
2351 vec<constructor_elt, va_gc> *elemlist = NULL;
2352 /* NOTE! sections where property name/attribute go MUST change
2353 later. */
2354 tree attribute, name_ident = PROPERTY_NAME (x);
2356 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2357 add_objc_string (name_ident, prop_names_attr));
2359 attribute = objc_v2_encode_prop_attr (x);
2360 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2361 add_objc_string (attribute, prop_names_attr));
2363 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2364 objc_build_constructor (type, elemlist));
2367 return objc_build_constructor (build_array_type (type, 0),inits);
2370 /* This routine builds the following type:
2371 struct _prop_list_t
2373 uint32_t entsize; // sizeof (struct _prop_t)
2374 uint32_t prop_count;
2375 struct _prop_t prop_list [prop_count];
2379 static tree
2380 build_v2_property_list_template (tree list_type, int size)
2382 tree property_list_t_record;
2383 tree array_type, decls, *chain = NULL;
2385 /* anonymous. */
2386 property_list_t_record = objc_start_struct (NULL_TREE);
2388 /* uint32_t const entsize; */
2389 decls = add_field_decl (integer_type_node, "entsize", &chain);
2391 /* int prop_count; */
2392 add_field_decl (integer_type_node, "prop_count", &chain);
2394 /* struct _prop_t prop_list[]; */
2395 array_type = build_sized_array_type (list_type, size);
2396 add_field_decl (array_type, "prop_list", &chain);
2398 objc_finish_struct (property_list_t_record, decls);
2399 return property_list_t_record;
2402 /* Top-level routine to generate property tables for each
2403 implementation. */
2405 static tree
2406 generate_v2_property_table (tree context, tree klass_ctxt)
2408 tree x, decl, initlist, property_list_template;
2409 bool is_proto = false;
2410 vec<constructor_elt, va_gc> *inits = NULL;
2411 int init_val, size = 0;
2412 char buf[BUFSIZE];
2414 if (context)
2416 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2417 x = CLASS_PROPERTY_DECL (context);
2418 is_proto = true;
2420 else
2421 x = IMPL_PROPERTY_DECL (klass_ctxt);
2423 for (; x; x = TREE_CHAIN (x))
2424 size++;
2426 if (size == 0)
2427 return NULL_TREE;
2429 property_list_template =
2430 build_v2_property_list_template (objc_v2_property_template,
2431 size);
2433 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2434 is_proto ? context
2435 : klass_ctxt);
2437 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2438 if (is_proto)
2439 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2440 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2441 else
2442 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2443 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2445 decl = start_var_decl (property_list_template, buf);
2447 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2448 build_int_cst (NULL_TREE, init_val));
2449 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2450 build_int_cst (NULL_TREE, size));
2451 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2453 OBJCMETA (decl, objc_meta, meta_base);
2454 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2455 return decl;
2458 static tree
2459 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2460 tree inst_methods, tree class_methods,
2461 tree opt_ins_meth, tree opt_cls_meth,
2462 tree property_list)
2464 tree expr, ttyp;
2465 location_t loc;
2466 vec<constructor_elt, va_gc> *inits = NULL;
2468 /* TODO: find a better representation of location from the inputs. */
2469 loc = UNKNOWN_LOCATION;
2471 /* This is NULL for the new ABI. */
2472 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2473 convert (objc_object_type, null_pointer_node));
2475 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2476 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2478 ttyp = objc_method_proto_list_ptr;
2479 if (inst_methods)
2480 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2481 else
2482 expr = convert (ttyp, null_pointer_node);
2483 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2485 if (class_methods)
2486 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2487 else
2488 expr = convert (ttyp, null_pointer_node);
2489 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2491 if (opt_ins_meth)
2492 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2493 else
2494 expr = convert (ttyp, null_pointer_node);
2495 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2497 if (opt_cls_meth)
2498 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2499 else
2500 expr = convert (ttyp, null_pointer_node);
2501 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2503 ttyp = objc_prop_list_ptr;
2504 if (property_list)
2505 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2506 else
2507 expr = convert (ttyp, null_pointer_node);
2508 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2510 /* const uint32_t size; = sizeof(struct protocol_t) */
2511 expr = build_int_cst (integer_type_node,
2512 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2513 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2514 /* const uint32_t flags; = 0 */
2515 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2517 return objc_build_constructor (type, inits);
2520 /* Main routine to build all meta data for all protocols used in a
2521 translation unit. */
2523 static void
2524 generate_v2_protocols (void)
2526 tree p ;
2527 bool some = false;
2529 if (!protocol_chain)
2530 return ;
2532 /* If a protocol was directly referenced, pull in indirect
2533 references. */
2534 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2535 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2536 generate_protocol_references (PROTOCOL_LIST (p));
2538 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2540 location_t loc;
2541 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2542 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2544 /* If protocol wasn't referenced, don't generate any code. */
2545 decl = PROTOCOL_FORWARD_DECL (p);
2547 if (!decl)
2548 continue;
2550 loc = DECL_SOURCE_LOCATION (decl);
2551 some = true;
2553 inst_meth =
2554 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2555 "_OBJC_ProtocolInstanceMethods",
2556 meta_proto_nst_meth);
2558 class_meth =
2559 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2560 "_OBJC_ProtocolClassMethods",
2561 meta_proto_cls_meth);
2563 opt_inst_meth =
2564 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2565 "_OBJC_OptProtocolInstMethods",
2566 meta_proto_nst_meth);
2568 opt_class_meth =
2569 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2570 "_OBJC_OptProtocolClassMethods",
2571 meta_proto_cls_meth);
2573 if (PROTOCOL_LIST (p))
2574 refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2575 else
2576 refs_decl = 0;
2578 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2579 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2581 if (refs_decl)
2582 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2583 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2584 else
2585 refs_expr = build_int_cst (NULL_TREE, 0);
2587 props = generate_v2_property_table (p, NULL_TREE);
2589 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2590 protocol_name_expr, refs_expr,
2591 inst_meth, class_meth,
2592 opt_inst_meth, opt_class_meth,
2593 props);
2594 finish_var_decl (decl, initlist);
2595 objc_add_to_protocol_list (p, decl);
2598 if (some)
2600 /* Make sure we get the Protocol class linked in - reference
2601 it... */
2602 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2603 /* ... but since we don't specifically use the reference... we
2604 need to force it. */
2605 DECL_PRESERVE_P (p) = 1;
2609 static tree
2610 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2612 tree decl, method_list_template, initlist;
2613 vec<constructor_elt, va_gc> *v = NULL;
2614 int size, init_val;
2616 if (!chain || !name || !(size = list_length (chain)))
2617 return NULL_TREE;
2619 method_list_template
2620 = build_v2_method_list_template (objc_method_template, size);
2621 initlist
2622 = build_dispatch_table_initializer (objc_method_template, chain);
2624 decl = start_var_decl (method_list_template, name);
2626 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2627 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2628 build_int_cst (integer_type_node, init_val));
2629 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2630 build_int_cst (integer_type_node, size));
2631 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2633 OBJCMETA (decl, objc_meta, attr);
2634 finish_var_decl (decl,
2635 objc_build_constructor (TREE_TYPE (decl), v));
2636 return decl;
2639 /* Init a category. */
2640 static tree
2641 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2642 tree inst_methods, tree class_methods,
2643 tree protocol_list, tree property_list,
2644 location_t loc)
2646 tree expr, ltyp;
2647 vec<constructor_elt, va_gc> *v = NULL;
2649 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2650 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2652 ltyp = objc_method_list_ptr;
2653 if (inst_methods)
2654 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2655 else
2656 expr = convert (ltyp, null_pointer_node);
2657 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2659 if (class_methods)
2660 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2661 else
2662 expr = convert (ltyp, null_pointer_node);
2663 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2665 /* protocol_list = */
2666 ltyp = build_pointer_type (objc_v2_protocol_template);
2667 if (protocol_list)
2668 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2669 else
2670 expr = convert (ltyp, null_pointer_node);
2671 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2673 ltyp = objc_prop_list_ptr;
2674 if (property_list)
2675 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2676 else
2677 expr = convert (ltyp, null_pointer_node);
2678 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2680 return objc_build_constructor (type, v);
2683 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2685 static void
2686 generate_v2_category (struct imp_entry *impent)
2688 tree initlist, cat_name_expr, class_name_expr;
2689 tree protocol_decl, category, props, t;
2690 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2691 tree cat = impent->imp_context;
2692 tree cat_decl = impent->class_decl;
2693 location_t loc;
2694 char buf[BUFSIZE];
2696 loc = DECL_SOURCE_LOCATION (cat_decl);
2698 /* ??? not sure this is really necessary, the following references should
2699 force appropriate linkage linkage...
2700 -- but ... ensure a reference to the class... */
2701 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2702 /* ... which we ignore so force it out.. */
2703 DECL_PRESERVE_P (t) = 1;
2705 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2706 class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2707 class_name_expr = build_fold_addr_expr (class_name_expr);
2709 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2710 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2712 if (category && CLASS_PROTOCOL_LIST (category))
2714 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2715 protocol_decl = generate_v2_protocol_list (category, cat);
2717 else
2718 protocol_decl = NULL_TREE;
2720 /* decl = update_var_decl(impent->class_decl); */
2722 props = generate_v2_property_table (NULL_TREE, cat);
2724 if (CLASS_NST_METHODS (cat))
2726 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2727 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2728 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2729 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2730 meta_cati_meth);
2733 if (CLASS_CLS_METHODS (cat))
2735 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2736 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2737 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2738 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2739 meta_catc_meth);
2742 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2743 cat_name_expr, class_name_expr,
2744 inst_methods, class_methods,
2745 protocol_decl, props, loc);
2747 finish_var_decl (cat_decl, initlist);
2748 impent->class_decl = cat_decl;
2750 /* Add to list of pointers in __category_list section. */
2751 objc_v2_add_to_category_list (cat_decl);
2752 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2753 objc_v2_add_to_nonlazy_category_list (cat_decl);
2756 /* This routine declares a variable to hold the offset for ivar
2757 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
2759 typedef struct GTY(()) ivarref_entry
2761 tree decl;
2762 tree offset;
2763 } ivarref_entry;
2765 static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
2767 static tree
2768 ivar_offset_ref (tree class_name, tree field_decl)
2770 tree decl, field_decl_id;
2771 ivarref_entry e;
2772 bool global_var;
2773 char buf[512];
2775 create_ivar_offset_name (buf, class_name, field_decl);
2776 field_decl_id = get_identifier (buf);
2778 if (ivar_offset_refs)
2780 int count;
2781 ivarref_entry *ref;
2782 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
2783 if (DECL_NAME (ref->decl) == field_decl_id)
2784 return ref->decl;
2786 else
2787 /* Somewhat arbitrary initial provision. */
2788 vec_alloc (ivar_offset_refs, 32);
2790 /* We come here if we don't find a match or at the start. */
2791 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
2792 if (global_var)
2793 decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
2794 else
2795 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
2797 /* Make sure it ends up in an ObjC section. */
2798 OBJCMETA (decl, objc_meta, meta_base);
2800 e.decl = decl;
2801 e.offset = byte_position (field_decl);
2802 vec_safe_push (ivar_offset_refs, e);
2803 return decl;
2806 /* This routine builds initializer-list needed to initialize 'struct
2807 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
2808 'struct ivar_t' and FIELD_DECL is list of ivars for the target
2809 class. */
2811 static tree
2812 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
2814 vec<constructor_elt, va_gc> *inits = NULL;
2818 vec<constructor_elt, va_gc> *ivar = NULL;
2819 int val;
2820 tree id;
2822 /* Unnamed bitfields are ignored. */
2823 if (!DECL_NAME (field_decl))
2825 field_decl = DECL_CHAIN (field_decl);
2826 continue;
2829 /* Set offset. */
2830 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2831 build_unary_op (input_location,
2832 ADDR_EXPR,
2833 ivar_offset_ref (class_name,
2834 field_decl), 0));
2836 /* Set name. */
2837 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2838 add_objc_string (DECL_NAME (field_decl),
2839 meth_var_names));
2841 /* Set type. */
2842 id = add_objc_string (encode_field_decl (field_decl),
2843 meth_var_types);
2844 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
2846 /* Set alignment. */
2847 val = DECL_ALIGN_UNIT (field_decl);
2848 val = exact_log2 (val);
2849 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2850 build_int_cst (integer_type_node, val));
2852 /* Set size. */
2853 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
2854 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2855 build_int_cst (integer_type_node, val));
2857 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2858 objc_build_constructor (type, ivar));
2861 field_decl = DECL_CHAIN (field_decl);
2862 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
2864 while (field_decl);
2866 return objc_build_constructor (build_array_type (type, 0), inits);
2870 struct ivar_list_t
2872 uint32 entsize;
2873 uint32 count;
2874 struct iver_t list[count];
2878 static tree
2879 build_v2_ivar_list_t_template (tree list_type, int size)
2881 tree objc_ivar_list_record;
2882 tree decls, *chain = NULL;
2884 /* Anonymous. */
2885 objc_ivar_list_record = objc_start_struct (NULL_TREE);
2887 /* uint32 entsize; */
2888 decls = add_field_decl (integer_type_node, "entsize", &chain);
2890 /* uint32 count; */
2891 add_field_decl (integer_type_node, "count", &chain);
2893 /* struct objc_ivar ivar_list[]; */
2894 add_field_decl (build_sized_array_type (list_type, size),
2895 "list", &chain);
2897 objc_finish_struct (objc_ivar_list_record, decls);
2898 return objc_ivar_list_record;
2901 /* This routine declares a static variable of type 'struct
2902 ivar_list_t' and initializes it. chain is the source of the data,
2903 name is the name for the var. attr is the meta-data section tag
2904 attribute. templ is the implementation template for the class. */
2906 static tree
2907 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
2909 tree decl, initlist, ivar_list_template;
2910 vec<constructor_elt, va_gc> *inits = NULL;
2911 int size, ivar_t_size;
2913 if (!chain || !name || !(size = ivar_list_length (chain)))
2914 return NULL_TREE;
2916 generating_instance_variables = 1;
2917 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
2918 size);
2920 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
2921 objc_v2_ivar_template, chain);
2922 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
2924 decl = start_var_decl (ivar_list_template, name);
2925 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2926 build_int_cst (integer_type_node, ivar_t_size));
2927 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2928 build_int_cst (integer_type_node, size));
2929 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2930 OBJCMETA (decl, objc_meta, attr);
2931 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2932 generating_instance_variables = 0;
2933 return decl;
2936 /* Routine to build initializer list to initialize objects of type
2937 struct class_t; */
2939 static tree
2940 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
2941 tree ro, tree cache, tree vtable)
2943 vec<constructor_elt, va_gc> *initlist = NULL;
2945 /* isa */
2946 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
2948 /* superclass */
2949 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
2951 /* cache */
2952 if (cache)
2953 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
2954 else
2955 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2957 /* vtable */
2958 if (vtable)
2959 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
2960 else
2961 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2963 /* ro */
2964 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
2966 return objc_build_constructor (type, initlist);
2969 /* Routine to build object of struct class_ro_t { ... }; */
2971 static tree
2972 build_v2_class_ro_t_initializer (tree type, tree name,
2973 unsigned int flags, unsigned int instanceStart,
2974 unsigned int instanceSize,
2975 tree ivarLayout,
2976 tree baseMethods, tree baseProtocols,
2977 tree ivars, tree property_list)
2979 tree expr, unsigned_char_star, ltyp;
2980 location_t loc;
2981 vec<constructor_elt, va_gc> *initlist = NULL;
2983 /* TODO: fish out the real location from somewhere. */
2984 loc = UNKNOWN_LOCATION;
2986 /* flags */
2987 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2988 build_int_cst (integer_type_node, flags));
2990 /* instanceStart */
2991 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2992 build_int_cst (integer_type_node, instanceStart));
2994 /* instanceSize */
2995 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2996 build_int_cst (integer_type_node, instanceSize));
2998 /* This ABI is currently only used on m64 NeXT. We always
2999 explicitly declare the alignment padding. */
3000 /* reserved, pads alignment. */
3001 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3002 build_int_cst (integer_type_node, 0));
3004 /* ivarLayout */
3005 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3006 if (ivarLayout)
3007 expr = ivarLayout;
3008 else
3009 expr = convert (unsigned_char_star, null_pointer_node);
3010 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3012 /* name */
3013 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3015 /* baseMethods */
3016 ltyp = objc_method_list_ptr;
3017 if (baseMethods)
3018 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3019 else
3020 expr = convert (ltyp, null_pointer_node);
3021 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3023 /* baseProtocols */
3024 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3025 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3026 if (baseProtocols)
3027 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3028 else
3029 expr = convert (ltyp, null_pointer_node);
3030 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3032 /* ivars */
3033 ltyp = objc_v2_ivar_list_ptr;
3034 if (ivars)
3035 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3036 else
3037 expr = convert (ltyp, null_pointer_node);
3038 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3040 /* TODO: We don't yet have the weak/strong stuff... */
3041 /* weakIvarLayout */
3042 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3043 convert (unsigned_char_star, null_pointer_node));
3045 /* property list */
3046 ltyp = objc_prop_list_ptr;
3047 if (property_list)
3048 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3049 else
3050 expr = convert (ltyp, null_pointer_node);
3051 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3052 return objc_build_constructor (type, initlist);
3055 static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
3057 /* Record a name as needing a catcher. */
3058 static void
3059 objc_v2_add_to_ehtype_list (tree name)
3061 ident_data_tuple e;
3062 if (ehtype_list)
3064 int count = 0;
3065 ident_data_tuple *ref;
3067 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3068 if (ref->ident == name)
3069 return; /* Already entered. */
3071 else
3072 /* Arbitrary initial count. */
3073 vec_alloc (ehtype_list, 8);
3075 /* Not found, or new list. */
3076 e.ident = name;
3077 e.data = NULL_TREE;
3078 vec_safe_push (ehtype_list, e);
3081 static void
3082 generate_v2_class_structs (struct imp_entry *impent)
3084 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3085 tree field, firstIvar, chain;
3086 tree class_superclass_expr, metaclass_superclass_expr, props;
3087 /* TODO: figure out how to compute this. */
3088 tree ivarLayout = NULL_TREE;
3089 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3090 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3091 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3092 location_t loc;
3093 char buf[BUFSIZE];
3094 unsigned int instanceStart, instanceSize;
3095 unsigned int flags = 0x01; /* RO_META */
3096 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3097 : 0 ;
3099 class_decl = impent->class_decl;
3100 metaclass_decl = impent->meta_decl;
3101 loc = DECL_SOURCE_LOCATION (class_decl);
3103 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3104 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3105 #ifdef OBJCPLUS
3106 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3107 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3108 #endif
3110 /* Generation of data for meta class. */
3111 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3112 if (my_super_id)
3114 /* Compute reference to root's name. For a meta class, "isa" is
3115 a reference to the root class name. */
3116 tree my_root_id = my_super_id;
3117 tree my_root_int, interface;
3120 my_root_int = lookup_interface (my_root_id);
3122 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3123 my_root_id = CLASS_SUPER_NAME (my_root_int);
3124 else
3125 break;
3127 while (1);
3129 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3130 create extern if not already declared. */
3131 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3132 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3133 root_expr = create_extern_decl (objc_v2_class_template, buf);
3134 root_expr = build_fold_addr_expr (root_expr);
3136 /* Install class `isa' and `super' pointers at runtime. */
3137 interface = lookup_interface (my_super_id);
3138 gcc_assert (interface);
3139 /* Similarly, for OBJC_CLASS_$_<interface>... */
3140 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3141 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3142 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3143 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3144 /* ... and for OBJC_METACLASS_$_<interface>. */
3145 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3146 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3147 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3148 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3150 else
3152 /* Root class. */
3153 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3154 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3155 class_superclass_expr = build_int_cst (NULL_TREE, 0);
3156 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */
3159 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3161 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3162 protocol_decl = generate_v2_protocol_list (impent->imp_template,
3163 impent->imp_context);
3165 else
3166 protocol_decl = 0;
3168 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3169 class_names);
3171 if (CLASS_CLS_METHODS (impent->imp_context))
3173 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3174 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3175 class_methods =
3176 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3177 buf, meta_clac_meth);
3180 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3182 /* Currently there are no class ivars and generation of class
3183 variables for the root of the inheritance has been removed. It
3184 causes multiple defines if there are two root classes in the
3185 link, because each will define its own identically-named offset
3186 variable. */
3188 class_ivars = NULL_TREE;
3189 /* TODO: Add total size of class variables when implemented. */
3190 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3192 /* So now build the META CLASS structs. */
3193 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3195 decl = start_var_decl (objc_v2_class_ro_template,
3196 newabi_append_ro (IDENTIFIER_POINTER
3197 (DECL_NAME (metaclass_decl))));
3199 /* TODO: ivarLayout needs t be built. */
3200 initlist =
3201 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3202 (flags | cls_flags), instanceStart,
3203 instanceSize, ivarLayout,
3204 class_methods, protocol_decl,
3205 class_ivars, NULL_TREE);
3206 /* The ROs sit in the default const section. */
3207 OBJCMETA (decl, objc_meta, meta_base);
3208 finish_var_decl (decl, initlist);
3210 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3211 initlist =
3212 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3213 root_expr,
3214 metaclass_superclass_expr,
3215 build_fold_addr_expr (decl),
3216 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3217 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3218 /* The class section attributes are set when they are created. */
3219 finish_var_decl (metaclass_decl, initlist);
3220 impent->meta_decl = metaclass_decl;
3222 /* So now build the CLASS structs. */
3224 flags = 0x0; /* ... */
3225 if (!my_super_id)
3226 flags |= 0x02; /* RO_ROOT: this is a root class */
3228 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3229 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3231 if (objc2_objc_exception_attr (impent->imp_template))
3232 flags |= 0x20; /* RO_EXCEPTION */
3234 if (CLASS_NST_METHODS (impent->imp_context))
3236 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3237 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3238 inst_methods =
3239 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3240 buf, meta_clai_meth);
3243 /* Sort out the ivars before we try to compute the class sizes. */
3244 if ((chain = CLASS_IVARS (impent->imp_template)))
3246 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3247 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3248 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3249 impent->imp_template);
3252 /* Compute instanceStart. */
3253 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3254 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3255 if (my_super_id && field && TREE_CHAIN (field))
3256 field = TREE_CHAIN (field);
3258 firstIvar = field;
3260 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3261 firstIvar = TREE_CHAIN (firstIvar);
3263 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3265 /* Compute instanceSize. */
3266 while (field && TREE_CHAIN (field)
3267 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3268 field = TREE_CHAIN (field);
3270 if (field && TREE_CODE (field) == FIELD_DECL)
3271 instanceSize = int_byte_position (field) * BITS_PER_UNIT
3272 + tree_to_shwi (DECL_SIZE (field));
3273 else
3274 instanceSize = 0;
3275 instanceSize /= BITS_PER_UNIT;
3277 props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3279 /* If the class has no ivars, instanceStart should be set to the
3280 superclass's instanceSize. */
3281 instanceStart =
3282 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3283 : instanceSize;
3285 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3286 decl = start_var_decl (objc_v2_class_ro_template,
3287 newabi_append_ro (IDENTIFIER_POINTER
3288 (DECL_NAME (class_decl))));
3290 initlist =
3291 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3292 (flags | cls_flags), instanceStart,
3293 instanceSize, ivarLayout,
3294 inst_methods, protocol_decl,
3295 inst_ivars, props);
3296 /* The ROs sit in the default const section. */
3297 OBJCMETA (decl, objc_meta, meta_base);
3298 finish_var_decl (decl, initlist);
3300 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3301 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3302 build_fold_addr_expr (metaclass_decl),
3303 class_superclass_expr,
3304 build_fold_addr_expr (decl),
3305 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3306 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3308 /* The class section attributes are set when they are created. */
3309 finish_var_decl (class_decl, initlist);
3310 impent->class_decl = class_decl;
3312 objc_v2_add_to_class_list (class_decl);
3313 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3314 objc_v2_add_to_nonlazy_class_list (class_decl);
3316 if (flags & 0x20) /* RO_EXCEPTION */
3317 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3320 /* This routine outputs the (ivar_reference_offset, offset)
3321 tuples. */
3323 static void
3324 build_v2_ivar_offset_ref_table (void)
3326 int count;
3327 ivarref_entry *ref;
3329 if (!vec_safe_length (ivar_offset_refs))
3330 return;
3332 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3333 finish_var_decl (ref->decl, ref->offset);
3336 static void
3337 objc_generate_v2_next_metadata (void)
3339 struct imp_entry *impent;
3341 /* FIXME: Make sure that we generate no metadata if there is nothing
3342 to put into it. */
3344 gcc_assert (!objc_static_instances); /* Not for NeXT */
3346 build_metadata_templates ();
3348 for (impent = imp_list; impent; impent = impent->next)
3350 /* If -gen-decls is present, Dump the @interface of each class.
3351 TODO: Dump the classes in the order they were found, rather
3352 than in reverse order as we are doing now. */
3353 if (flag_gen_declaration)
3354 dump_interface (gen_declaration_file, impent->imp_context);
3356 /* all of the following reference the string pool... */
3357 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3358 generate_v2_class_structs (impent);
3359 else
3360 generate_v2_category (impent);
3363 build_next_selector_translation_table ();
3364 build_v2_message_ref_translation_table ();
3366 /* This will add "Protocol" to the class refs. */
3367 generate_v2_protocols ();
3369 build_v2_classrefs_table ();
3370 build_v2_super_classrefs_table (/*metaclass= */false);
3371 build_v2_super_classrefs_table (/*metaclass= */true);
3373 build_v2_ivar_offset_ref_table ();
3375 build_v2_protocol_list_translation_table ();
3376 build_v2_protocol_list_address_table ();
3378 build_v2_address_table (class_list, "_OBJC_ClassList$",
3379 meta_label_classlist);
3380 build_v2_address_table (category_list, "_OBJC_CategoryList$",
3381 meta_label_categorylist);
3382 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3383 meta_label_nonlazy_classlist);
3384 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3385 meta_label_nonlazy_categorylist);
3387 /* Generate catch objects for eh, if any are needed. */
3388 build_v2_eh_catch_objects ();
3390 /* Emit the string table last. */
3391 generate_strings ();
3394 /* NOTE --- Output NeXT V2 Exceptions --- */
3396 static GTY(()) tree objc_v2_ehtype_template;
3397 static GTY(()) tree next_v2_ehvtable_decl;
3398 static GTY(()) tree next_v2_EHTYPE_id_decl;
3400 static void
3401 build_v2_ehtype_template (void)
3403 tree decls, *chain = NULL;
3404 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3406 /* void *_objc_ehtype_vtable; */
3407 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3409 /* const char *className; */
3410 add_field_decl (string_type_node, "className", &chain);
3412 /* struct class_t *const cls; */
3413 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3415 objc_finish_struct (objc_v2_ehtype_template, decls);
3418 /* Template for the Objective-C family typeinfo type for ABI=2. This
3419 starts off the same as the gxx/cxx eh typeinfo.
3421 struct _objc_ehtype_t
3423 void *_objc_ehtype_vtable_ptr; - as per c++
3424 const char *className; - as per c++
3425 struct class_t *const cls;
3429 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3432 static tree
3433 objc2_build_ehtype_initializer (tree name, tree cls)
3435 vec<constructor_elt, va_gc> *initlist = NULL;
3436 tree addr, offs;
3438 /* This is done the same way as c++, missing the two first entries
3439 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3440 runtime source about this so, perhaps, this will change at some
3441 point. */
3442 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3443 if (!next_v2_ehvtable_decl)
3445 next_v2_ehvtable_decl =
3446 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3447 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3448 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3449 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3451 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3452 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3453 addr = fold_build_pointer_plus (addr, offs);
3455 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3457 /* className */
3458 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3460 /* cls */
3461 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3463 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3466 static tree
3467 build_ehtype (tree name, const char *eh_name, bool weak)
3469 tree name_expr, class_name_expr, ehtype_decl, inits;
3471 name_expr = add_objc_string (name, class_names);
3472 /* Extern ref. for the class. ??? Maybe we can look this up
3473 somewhere. */
3474 class_name_expr =
3475 create_extern_decl (objc_v2_class_template,
3476 objc_build_internal_classname (name, false));
3477 class_name_expr = build_fold_addr_expr (class_name_expr);
3478 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3479 if (weak)
3480 DECL_WEAK (ehtype_decl) = 1;
3481 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3482 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3483 finish_var_decl (ehtype_decl, inits);
3484 return ehtype_decl;
3487 /* This routine returns TRUE if CLS or any of its super classes has
3488 __attribute__ ((objc_exception)). */
3490 static bool
3491 objc2_objc_exception_attr (tree cls)
3493 while (cls)
3495 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3496 return true;
3497 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3500 return false;
3503 static bool
3504 is_implemented (tree name)
3506 struct imp_entry *t;
3507 for (t = imp_list; t; t = t->next)
3508 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3509 && CLASS_NAME (t->imp_template) == name)
3510 return true;
3512 return false;
3515 /* We will build catch objects:
3516 for any type implemented here.
3517 for any type used in a catch that has no exception attribute. */
3518 static void build_v2_eh_catch_objects (void)
3520 int count=0;
3521 ident_data_tuple *ref;
3523 if (!vec_safe_length (ehtype_list))
3524 return;
3526 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3528 char buf[BUFSIZE];
3529 bool impl = is_implemented (ref->ident);
3530 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3531 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3532 if (!impl && excpt)
3533 /* The User says this class has a catcher already. */
3534 ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3535 else
3536 /* Create a catcher, weak if it wasn't marked. */
3537 ref->data = build_ehtype (ref->ident, buf, !excpt);
3541 static tree
3542 lookup_ehtype_ref (tree id)
3544 int count=0;
3545 ident_data_tuple *ref;
3547 if (!vec_safe_length (ehtype_list))
3548 return NULL_TREE;
3550 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3551 if (ref->ident == id)
3552 return ref->data;
3553 return NULL_TREE;
3556 /* This hook, called via lang_eh_runtime_type, generates a runtime
3557 object which is either the address of the 'OBJC_EHTYPE_$_class'
3558 object or address of external OBJC_EHTYPE_id object. */
3559 static tree
3560 next_runtime_02_eh_type (tree type)
3562 tree t;
3564 if (type == error_mark_node
3565 /*|| errorcount || sorrycount*/)
3566 goto err_mark_in;
3568 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3570 if (!next_v2_EHTYPE_id_decl)
3572 /* This is provided by the Apple/NeXT libobjc.dylib so we
3573 need only to reference it. */
3574 next_v2_EHTYPE_id_decl =
3575 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3576 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3577 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3578 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3580 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3583 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3585 #ifdef OBJCPLUS
3586 /* This routine is also called for c++'s catch clause; in which
3587 case, we use c++'s typeinfo decl. */
3588 return build_eh_type_type (type);
3589 #else
3590 error ("non-objective-c type '%T' cannot be caught", type);
3591 goto err_mark_in;
3592 #endif
3594 else
3595 t = OBJC_TYPE_NAME (TREE_TYPE (type));
3597 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3598 t = lookup_ehtype_ref (t);
3599 if (!t)
3600 goto err_mark_in;
3602 return build_fold_addr_expr (t);
3604 err_mark_in:
3605 return error_mark_node;
3608 static GTY(()) tree objc_eh_personality_decl;
3610 static tree
3611 objc_eh_personality (void)
3613 if (!objc_eh_personality_decl)
3614 objc_eh_personality_decl = build_personality_function ("objc");
3615 return objc_eh_personality_decl;
3618 /* NOTE --- interfaces --- */
3620 static tree
3621 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3623 tree t;
3624 if (rethrown)
3625 /* We have a separate re-throw entry. */
3626 t = build_function_call_vec (loc, vNULL, objc_rethrow_exception_decl,
3627 NULL, NULL);
3628 else
3630 /* Throw like the others... */
3631 vec<tree, va_gc> *parms;
3632 vec_alloc (parms, 1);
3633 parms->quick_push (throw_expr);
3634 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl,
3635 parms, 0);
3636 vec_free (parms);
3638 return add_stmt (t);
3641 /* Build __builtin_eh_pointer. */
3643 static tree
3644 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3646 tree t;
3647 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3648 t = build_call_expr (t, 1, integer_zero_node);
3649 return fold_convert (objc_object_type, t);
3652 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3653 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3655 tree t;
3657 /* Record the data for the catch in the try context so that we can
3658 finalize it later. Ellipsis is signalled by a NULL entry. */
3659 if (ellipsis)
3660 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3661 else
3662 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3663 (*cur_try_context)->current_catch = t;
3665 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3666 t = objc_build_exc_ptr (cur_try_context);
3667 t = convert (TREE_TYPE (decl), t);
3668 /* FIXME: location. */
3669 if (type && type != error_mark_node)
3671 t = build1(NOP_EXPR, ptr_type_node, t);
3672 t = build_function_call (input_location, objc2_begin_catch_decl,
3673 tree_cons (NULL_TREE, t, NULL_TREE));
3675 /* We might want to build a catch object for this (if it's not
3676 id). */
3677 if (POINTER_TYPE_P (type)
3678 && !objc_is_object_id (TREE_TYPE (type))
3679 && TYPED_OBJECT (TREE_TYPE (type)))
3680 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3682 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3685 /* try { catch-body } finally { objc_end_catch (); } */
3686 static void
3687 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3689 struct objc_try_context *ct;
3690 tree try_exp, func, *l, t ;
3691 location_t loc = (*cur_try_context)->try_locus;
3693 if (!curr_catch || curr_catch == error_mark_node)
3694 return;
3696 t = CATCH_BODY (curr_catch);
3697 if (TREE_CODE (t) == BIND_EXPR)
3699 /* Usual case of @catch (objc-expr). */
3700 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3701 BIND_EXPR_BODY (t) = NULL_TREE;
3702 l = &BIND_EXPR_BODY (t);
3704 else
3706 /* NULL entry, meaning @catch (...). */
3707 objc_begin_try_stmt (loc, t);
3708 CATCH_BODY (curr_catch) = NULL_TREE;
3709 l = &CATCH_BODY (curr_catch);
3712 /* Pick up the new context we made in begin_try above... */
3713 ct = *cur_try_context;
3714 func = build_function_call_vec (loc, vNULL, objc2_end_catch_decl, NULL,
3715 NULL);
3716 append_to_statement_list (func, &ct->finally_body);
3717 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3718 *cur_try_context = ct->outer;
3719 free (ct);
3720 append_to_statement_list (try_exp, l);
3721 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3724 static tree
3725 finish_try_stmt (struct objc_try_context **cur_try_context)
3727 struct objc_try_context *c = *cur_try_context;
3728 tree stmt = c->try_body;
3729 if (c->catch_list)
3730 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3731 if (c->finally_body)
3732 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3733 return stmt;
3736 #include "gt-objc-objc-next-runtime-abi-02.h"