Added support for the 64-bit Apple Objective-C runtime
[official-gcc.git] / gcc / objc / objc-next-runtime-abi-02.c
blob46e56937755dcb036fed872464080ff8096647f0
1 /* Next Runtime (ABI-2) private.
2 Copyright (C) 2011 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) output of Apple's 4.2.1
26 compiler.
28 References:
29 FSF GCC branches/apple/trunk.
30 objc4-371.2 Open Source release (Apple Computer). (objc-runtime-new.h)
31 gcc_42-5664 Apple Local modifications to GCC (Apple Computer).
34 #include "config.h"
35 #include "system.h"
36 #include "coretypes.h"
37 #include "tm.h"
38 #include "tree.h"
40 #ifdef OBJCPLUS
41 #include "cp-tree.h"
42 #else
43 #include "c-tree.h"
44 #include "c-lang.h"
45 #endif
46 #include "langhooks.h"
47 #include "c-family/c-objc.h"
48 #include "objc-act.h"
50 /* When building Objective-C++, we are not linking against the C front-end
51 and so need to replicate the C tree-construction functions in some way. */
52 #ifdef OBJCPLUS
53 #define OBJCP_REMAP_FUNCTIONS
54 #include "objcp-decl.h"
55 #endif /* OBJCPLUS */
57 #include "ggc.h"
58 #include "target.h"
59 #include "obstack.h"
60 #include "tree-iterator.h"
62 /* These are only used for encoding ivars. */
63 extern struct obstack util_obstack;
64 extern char *util_firstobj;
66 #include "objc-runtime-hooks.h"
68 #include "objc-runtime-shared-support.h"
70 /* ABI 2 Private definitions. */
71 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
73 #define TAG_GETCLASS "objc_getClass"
74 #define TAG_GETMETACLASS "objc_getMetaClass"
76 #define TAG_MSGSEND "objc_msgSend"
77 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
78 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
79 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
81 #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
82 #define TAG_V2_EH_TYPE "objc_ehtype_t"
84 #define UTAG_V2_CLASS "_class_t"
85 #define UTAG_V2_CLASS_RO "_class_ro_t"
86 #define UTAG_V2_PROTOCOL "_protocol_t"
87 #define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
89 #define UTAG_V2_EH_TYPE "_objc_ehtype_t"
91 #define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
93 enum objc_v2_tree_index
95 /* Templates. */
96 OCTI_V2_CLS_TEMPL,
97 OCTI_V2_CAT_TEMPL,
98 OCTI_V2_CLS_RO_TEMPL,
99 OCTI_V2_PROTO_TEMPL,
100 OCTI_V2_IVAR_TEMPL,
101 OCTI_V2_IVAR_LIST_TEMPL,
102 OCTI_V2_MESSAGE_REF_TEMPL,
103 OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
105 OCTI_V2_MESSAGE_SELECTOR_TYPE,
106 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
107 OCTI_V2_IMP_TYPE,
108 OCTI_V2_SUPER_IMP_TYPE,
110 OCTI_V2_CACHE_DECL,
111 OCTI_V2_VTABLE_DECL,
113 OCTI_V2_PROPERTY_TEMPL,
115 /* V2 messaging. */
116 OCTI_V2_UMSG_FIXUP_DECL,
117 OCTI_V2_UMSG_STRET_FIXUP_DECL,
118 OCTI_V2_UMSG_ID_FIXUP_DECL,
119 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
120 OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
121 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
123 /* Exceptions - related. */
124 OCTI_V2_BEGIN_CATCH_DECL,
125 OCTI_V2_END_CATCH_DECL,
126 OCTI_V2_RETHROW_DECL,
128 OCTI_V2_MAX
131 #define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
132 #define objc_v2_class_ro_template \
133 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
134 #define objc_v2_category_template \
135 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
136 #define objc_v2_protocol_template \
137 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
139 /* struct message_ref_t */
140 #define objc_v2_message_ref_template \
141 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
143 #define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
145 /* struct super_message_ref_t */
146 #define objc_v2_super_message_ref_template \
147 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
149 /* struct message_ref_t* */
150 #define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
151 /* struct super_super_message_ref_t */
152 #define objc_v2_super_selector_type \
153 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
154 #define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
155 #define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
157 #define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
158 #define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
160 #define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
161 #define objc_v2_property_template \
162 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
164 /* V2 Messaging */
166 /* objc_msgSend_fixup_rtp */
167 #define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
168 /* objc_msgSend_stret_fixup_rtp */
169 #define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
170 /* objc_msgSendId_fixup_rtp */
171 #define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
172 /* objc_msgSendId_stret_fixup_rtp */
173 #define umsg_id_stret_fixup_decl \
174 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
175 /* objc_msgSendSuper2_fixup_rtp */
176 #define umsg_id_super2_fixup_decl \
177 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
178 /* objc_msgSendSuper2_stret_fixup_rtp */
179 #define umsg_id_super2_stret_fixup_decl \
180 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
182 #define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
183 #define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
184 #define objc_rethrow_exception_decl \
185 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
187 /* rt_trees identifiers - shared between NeXT implementations. These allow
188 the FE to tag meta-data in a manner that survives LTO and can be used when
189 the runtime requires that certain meta-data items appear in particular
190 named sections. */
192 #include "objc-next-metadata-tags.h"
193 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
195 /* The OCTI_V2_... enumeration itself is in above. */
196 static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
198 static void next_runtime_02_initialize (void);
200 static void build_v2_message_ref_templates (void);
201 static void build_v2_class_templates (void);
202 static void build_v2_super_template (void);
203 static void build_v2_category_template (void);
204 static void build_v2_protocol_template (void);
206 static tree next_runtime_abi_02_super_superclassfield_id (void);
208 static tree next_runtime_abi_02_class_decl (tree);
209 static tree next_runtime_abi_02_metaclass_decl (tree);
210 static tree next_runtime_abi_02_category_decl (tree);
211 static tree next_runtime_abi_02_protocol_decl (tree);
212 static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
214 static tree next_runtime_abi_02_get_class_reference (tree);
215 static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
216 static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
217 static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
218 static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
219 static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
221 static tree next_runtime_abi_02_receiver_is_class_object (tree);
222 static tree next_runtime_abi_02_get_arg_type_list_base (tree, int, int);
223 static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
224 tree, tree, tree, int);
225 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
226 static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
228 static tree create_extern_decl (tree, const char *);
230 static void objc_generate_v2_next_metadata (void);
231 static bool objc2_objc_exception_attr (tree);
233 /* void build_v2_protocol_reference (tree);*/
234 static void build_v2_ehtype_template (void);
235 static void build_v2_eh_catch_objects (void);
236 static tree next_runtime_02_eh_type (tree);
237 static tree objc_eh_personality (void);
238 static tree build_throw_stmt (location_t, tree, bool);
239 static tree objc_build_exc_ptr (struct objc_try_context **);
240 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
241 static void finish_catch (struct objc_try_context **, tree);
242 static tree finish_try_stmt (struct objc_try_context **);
244 static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
246 bool
247 objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
249 extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
251 if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
253 inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for "
254 "%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
255 flag_objc_sjlj_exceptions = 0;
258 rthooks->initialize = next_runtime_02_initialize;
259 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
260 rthooks->tag_getclass = TAG_GETCLASS;
261 rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
263 rthooks->class_decl = next_runtime_abi_02_class_decl;
264 rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
265 rthooks->category_decl = next_runtime_abi_02_category_decl;
266 rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
267 rthooks->string_decl = next_runtime_abi_02_string_decl;
269 rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
270 rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
271 rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
272 rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
273 rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
274 rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
276 rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
277 rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
278 rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
280 rthooks->setup_const_string_class_decl =
281 next_runtime_abi_02_setup_const_string_class_decl;
282 rthooks->build_const_string_constructor =
283 next_runtime_abi_02_build_const_string_constructor;
285 rthooks->build_throw_stmt = build_throw_stmt;
286 rthooks->build_exc_ptr = objc_build_exc_ptr;
287 rthooks->begin_catch = begin_catch;
288 rthooks->finish_catch = finish_catch;
289 rthooks->finish_try_stmt = finish_try_stmt;
291 rthooks->generate_metadata = objc_generate_v2_next_metadata;
292 return true;
295 /* We need a way to convey what kind of meta-data are represented by a given
296 variable, since each type is expected (by the runtime) to be found in a
297 specific named section. The solution must be usable with LTO.
299 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
300 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
301 identification attributes in the front end. The back-end may choose to act
302 on these as it requires. */
304 static void
305 next_runtime_abi_02_init_metadata_attributes (void)
307 if (!objc_meta)
308 objc_meta = get_identifier ("OBJC2META");
310 if (!meta_base)
311 meta_base = get_identifier ("V2_BASE");
313 meta_class = get_identifier ("G2_CLAS");
314 meta_metaclass = get_identifier ("G2_META");
315 meta_category =
316 meta_protocol = meta_base;
318 meta_clac_vars =
319 meta_clai_vars = meta_base;
321 meta_clac_meth =
322 meta_clai_meth =
323 meta_catc_meth =
324 meta_cati_meth =
325 meta_proto_cls_meth =
326 meta_proto_nst_meth = meta_base;
328 meta_clas_prot =
329 meta_catg_prot = meta_base;
331 meta_sel_refs = get_identifier ("V2_SRFS");
333 meta_class_name =
334 meta_meth_name =
335 meta_meth_type =
336 meta_prop_name_attr = get_identifier ("V2_STRG");
338 meta_mref = get_identifier ("V2_MREF");
339 meta_class_ref = get_identifier ("V2_CLRF");
340 meta_superclass_ref = get_identifier ("V2_SURF");
342 meta_label_classlist = get_identifier ("V2_CLAB");
343 meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
344 meta_label_categorylist = get_identifier ("V2_CALA");
345 meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
347 meta_label_protocollist = get_identifier ("V2_PLST");
348 meta_proto_ref = get_identifier ("V2_PRFS");
350 meta_info = get_identifier ("V2_INFO");
352 meta_ehtype = get_identifier ("V2_EHTY");
354 meta_const_str = get_identifier ("V2_CSTR");
357 static void next_runtime_02_initialize (void)
359 tree type;
360 #ifdef OBJCPLUS
361 /* For all objc ABIs -fobjc-call-cxx-cdtors is on by default. */
362 if (!global_options_set.x_flag_objc_call_cxx_cdtors)
363 global_options.x_flag_objc_call_cxx_cdtors = 1;
364 #endif
366 /* Set up attributes to be attached to the meta-data so that they
367 will be placed in the correct sections. */
368 next_runtime_abi_02_init_metadata_attributes ();
370 /* `struct objc_selector *' */
371 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
372 get_identifier (TAG_SELECTOR)));
374 /* IMP : id (*) (id, _message_ref_t*, ...)
375 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
376 objc_v2_selector_type. */
377 build_v2_message_ref_templates ();
379 objc_v2_ivar_list_ptr =
380 build_pointer_type (xref_tag (RECORD_TYPE,
381 get_identifier ("_ivar_list_t")));
383 objc_prop_list_ptr =
384 build_pointer_type (xref_tag (RECORD_TYPE,
385 get_identifier ("_prop_list_t")));
387 build_v2_class_templates ();
388 build_v2_super_template ();
389 build_v2_protocol_template ();
390 build_v2_category_template ();
392 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
393 type = build_varargs_function_type_list (objc_object_type,
394 objc_object_type,
395 objc_v2_selector_type,
396 NULL_TREE);
397 umsg_fixup_decl = add_builtin_function ("objc_msgSend_fixup",
398 type, 0, NOT_BUILT_IN,
399 NULL, NULL_TREE);
400 TREE_NOTHROW (umsg_fixup_decl) = 0;
402 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
403 umsg_stret_fixup_decl = add_builtin_function ("objc_msgSend_stret_fixup",
404 type, 0, NOT_BUILT_IN,
405 NULL, NULL_TREE);
406 TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
408 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
409 umsg_id_fixup_decl = add_builtin_function ("objc_msgSendId_fixup",
410 type, 0, NOT_BUILT_IN,
411 NULL, NULL_TREE);
412 TREE_NOTHROW (umsg_id_fixup_decl) = 0;
414 /* id objc_msgSendId_stret_fixup_rtp
415 (id, struct message_ref_t*, ...); */
416 umsg_id_stret_fixup_decl = add_builtin_function ("objc_msgSendId_stret_fixup",
417 type, 0, NOT_BUILT_IN,
418 NULL, NULL_TREE);
419 TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
421 /* id objc_msgSendSuper2_fixup_rtp
422 (struct objc_super *, struct message_ref_t*, ...); */
423 type = build_varargs_function_type_list (objc_object_type,
424 objc_super_type,
425 objc_v2_super_selector_type,
426 NULL_TREE);
427 umsg_id_super2_fixup_decl = add_builtin_function ("objc_msgSendSuper2_fixup",
428 type, 0, NOT_BUILT_IN,
429 NULL, NULL_TREE);
430 TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
432 /* id objc_msgSendSuper2_stret_fixup_rtp
433 (struct objc_super *, struct message_ref_t*, ...); */
434 umsg_id_super2_stret_fixup_decl =
435 add_builtin_function ("objc_msgSendSuper2_stret_fixup",
436 type, 0, NOT_BUILT_IN,
437 NULL, NULL_TREE);
438 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
440 /* Present in the library, but unused by the FE. */
441 /* Protocol *objc_getProtocol (const char *)
442 type = build_function_type_list (objc_protocol_type,
443 const_string_type_node,
444 NULL_TREE);
445 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
446 type, 0, NOT_BUILT_IN,
447 NULL, NULL_TREE);
448 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
450 UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
451 "_objc_empty_cache");
453 UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
454 "_objc_empty_vtable");
456 /* id objc_getClass (const char *); */
457 type = build_function_type_list (objc_object_type,
458 const_string_type_node,
459 NULL_TREE);
460 objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
461 type, 0, NOT_BUILT_IN,
462 NULL, NULL_TREE);
464 /* id objc_getMetaClass (const char *); */
465 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
466 type, 0, NOT_BUILT_IN,
467 NULL, NULL_TREE);
469 /* This is the type of all of the following functions objc_copyStruct(). */
470 type = build_function_type_list (void_type_node,
471 ptr_type_node,
472 const_ptr_type_node,
473 ptrdiff_type_node,
474 boolean_type_node,
475 boolean_type_node,
476 NULL_TREE);
477 /* Declare the following function:
478 void
479 objc_copyStruct (void *destination, const void *source,
480 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
481 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
482 type, 0, NOT_BUILT_IN,
483 NULL, NULL_TREE);
484 TREE_NOTHROW (objc_copyStruct_decl) = 0;
485 objc_getPropertyStruct_decl = NULL_TREE;
486 objc_setPropertyStruct_decl = NULL_TREE;
488 gcc_assert (!flag_objc_sjlj_exceptions);
490 /* Although we warn that fobjc-exceptions is required for exceptions
491 code, we carry on an create it anyway. */
493 /* This can be required, even when exceptions code is not present,
494 when an __attribute__((objc_exception)) is applied to a class. */
495 build_v2_ehtype_template ();
497 /* void * objc_begin_catch (void *) */
498 type = build_function_type (ptr_type_node,
499 tree_cons (NULL_TREE, ptr_type_node,
500 OBJC_VOID_AT_END));
502 objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
503 type, 0, NOT_BUILT_IN,
504 NULL, NULL_TREE);
505 TREE_NOTHROW (objc2_begin_catch_decl) = 0;
507 /* void objc_end_catch () */
508 type = build_function_type (void_type_node, OBJC_VOID_AT_END);
509 objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
510 type, 0, NOT_BUILT_IN,
511 NULL, NULL_TREE);
512 TREE_NOTHROW (objc2_end_catch_decl) = 0;
514 /* void objc_exception_rethrow (void) */
515 type = build_function_type (void_type_node, OBJC_VOID_AT_END);
516 objc_rethrow_exception_decl =
517 add_builtin_function ("objc_exception_rethrow",
518 type, 0, NOT_BUILT_IN,
519 NULL, NULL_TREE);
520 TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
521 using_eh_for_cleanups ();
522 lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
523 lang_hooks.eh_personality = objc_eh_personality;
526 /* NOTE --- templates --- */
528 /* Set 'objc_v2_message_ref_template' to the data type node for 'struct _message_ref_t'.
529 This needs to be done just once per compilation. Also Set
530 'objc_v2_super_message_ref_template' to data type node
531 for 'struct _super_message_ref_t'. */
533 /* struct _message_ref_t {
534 IMP messenger;
535 SEL name;
537 where IMP is: id (*) (id, _message_ref_t*, ...)
540 /* struct _super_message_ref_t {
541 SUPER_IMP messenger;
542 SEL name;
544 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
547 static void
548 build_v2_message_ref_templates (void)
550 tree ptr_message_ref_t;
551 tree decls, *chain = NULL;
553 /* struct _message_ref_t {...} */
554 objc_v2_message_ref_template =
555 objc_start_struct (get_identifier ("_message_ref_t"));
557 /* IMP messenger; */
558 ptr_message_ref_t =
559 build_pointer_type (xref_tag (RECORD_TYPE,
560 get_identifier ("_message_ref_t")));
562 objc_v2_imp_type =
563 build_pointer_type (build_function_type_list
564 (objc_object_type,
565 objc_object_type,
566 ptr_message_ref_t,
567 NULL_TREE));
569 decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
571 /* SEL name; */
572 add_field_decl (objc_selector_type, "name", &chain);
574 objc_finish_struct (objc_v2_message_ref_template, decls);
576 objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
578 chain = NULL;
579 /* struct _super_message_ref_t {...} */
580 objc_v2_super_message_ref_template =
581 objc_start_struct (get_identifier ("_super_message_ref_t"));
583 /* SUPER_IMP messenger; */
584 ptr_message_ref_t = build_pointer_type
585 (xref_tag (RECORD_TYPE,
586 get_identifier ("_super_message_ref_t")));
588 objc_v2_super_imp_type =
589 build_pointer_type (build_function_type_list
590 (objc_object_type,
591 objc_super_type,
592 ptr_message_ref_t,
593 NULL_TREE));
595 add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
597 /* SEL name; */
598 add_field_decl (objc_selector_type, "name", &chain);
600 objc_finish_struct (objc_v2_super_message_ref_template, decls);
601 objc_v2_super_selector_type =
602 build_pointer_type (objc_v2_super_message_ref_template);
605 /* Build following types which represent each class implementation.
607 struct class_ro_t {
608 uint32_t const flags;
609 uint32_t const instanceStart;
610 uint32_t const instanceSize;
611 #ifdef __LP64__
612 uint32_t const reserved;
613 #endif
614 const uint8_t * const ivarLayout;
615 const char *const name;
616 const struct method_list_t * const baseMethods;
617 const struct objc_protocol_list *const baseProtocols;
618 const struct ivar_list_t *const ivars;
619 const uint8_t * const weakIvarLayout;
620 const struct _prop_list_t * const properties;
623 struct class_t {
624 struct class_t *isa;
625 struct class_t *superclass;
626 void *cache;
627 IMP *vtable;
629 ...When this is active - it will point to a rw version, but
630 when we build the meta-data we point it to the ro...
631 struct class_ro_t *data;
636 static void
637 build_v2_class_templates (void)
639 tree cnst_strg_type;
640 tree decls, *chain = NULL;
642 /* struct class_ro_t {...} */
643 objc_v2_class_ro_template =
644 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
646 /* uint32_t const flags; */
647 decls = add_field_decl (integer_type_node, "flags", &chain);
649 /* uint32_t const instanceStart */
650 add_field_decl (integer_type_node, "instanceStart", &chain);
652 /* uint32_t const instanceSize */
653 add_field_decl (integer_type_node, "instanceSize", &chain);
655 /* This ABI is currently only used on m64 NeXT, we choose to
656 make the alignment padding explicit. */
657 /* uint32_t const reserved. */
658 add_field_decl (integer_type_node, "reserved", &chain);
660 /* const uint8_t * const ivarLayout */
661 cnst_strg_type = build_pointer_type (unsigned_char_type_node);
662 add_field_decl (cnst_strg_type, "ivarLayout", &chain);
664 /* const char *const name; */
665 add_field_decl (string_type_node, "name", &chain);
667 /* const struct method_list_t * const baseMethods */
668 add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
670 /* const struct objc_protocol_list *const baseProtocols */
671 add_field_decl (build_pointer_type
672 (xref_tag (RECORD_TYPE,
673 get_identifier (UTAG_V2_PROTOCOL_LIST))),
674 "baseProtocols", &chain);
676 /* const struct ivar_list_t *const ivars */
677 add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
679 /* const uint8_t * const weakIvarLayout; */
680 add_field_decl (cnst_strg_type, "weakIvarLayout", &chain);
682 /* struct _prop_list_t * baseProperties */
683 add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
685 objc_finish_struct (objc_v2_class_ro_template, decls);
687 chain = NULL;
688 /* struct class_t {...} */
689 objc_v2_class_template =
690 objc_start_struct (get_identifier (UTAG_V2_CLASS));
692 /* struct class_t *isa; */
693 decls = add_field_decl (build_pointer_type (objc_v2_class_template),
694 "isa", &chain);
696 /* struct class_t * const superclass */
697 add_field_decl (build_pointer_type (objc_v2_class_template),
698 "superclass", &chain);
700 /* void *cache; */
701 add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
703 /* IMP *vtable; */
704 add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
706 /* struct class_ro_t *ro; */
707 add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
709 objc_finish_struct (objc_v2_class_template, decls);
712 /* struct _objc_super {
713 struct _objc_object *self;
714 Class cls;
715 }; */
717 void
718 build_v2_super_template (void)
720 tree decls, *chain = NULL;
722 objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
724 /* struct _objc_object *self; */
725 decls = add_field_decl (objc_object_type, "self", &chain);
727 /* Class cls; */
728 add_field_decl (objc_class_type, "cls", &chain);
730 objc_finish_struct (objc_super_template, decls);
733 /* struct protocol_t {
734 Class isa;
735 const char * const protocol_name;
736 const struct protocol_list_t * const protocol_list;
737 const struct method_list_t * const instance_methods;
738 const struct method_list_t * const class_methods;
739 const struct method_list_t * optionalInstanceMethods;
740 const struct method_list_t * optionalClassMethod
741 const struct _prop_list_t * const properties;
742 const uint32_t size;
743 const uint32_t flags;
746 static void
747 build_v2_protocol_template (void)
749 tree decls, *chain = NULL;
751 objc_v2_protocol_template =
752 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
754 /* Class isa; */
755 decls = add_field_decl (objc_object_type, "isa", &chain);
757 /* char *protocol_name; */
758 add_field_decl (string_type_node, "protocol_name", &chain);
760 /* const struct protocol_list_t * const protocol_list; */
761 add_field_decl (build_pointer_type (objc_v2_protocol_template),
762 "protocol_list", &chain);
764 /* const struct method_list_t * const instance_methods; */
765 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
767 /* const struct method_list_t * const class_methods; */
768 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
770 /* const struct method_list_t * optionalInstanceMethods */
771 add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
773 /* const struct method_list_t * optionalClassMethods */
774 add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
776 /* struct _prop_list_t * properties; */
777 add_field_decl (objc_prop_list_ptr, "properties", &chain);
779 /* const uint32_t size; */
780 add_field_decl (integer_type_node, "size", &chain);
782 /* const uint32_t flags; */
783 add_field_decl (integer_type_node, "flags", &chain);
785 objc_finish_struct (objc_v2_protocol_template, decls);
788 /* Build type for a category:
789 struct category_t {
790 const char * const name;
791 struct class_t *const cls;
792 const struct method_list_t * const instance_methods;
793 const struct method_list_t * const class_methods;
794 const struct protocol_list_t * const protocols;
795 const struct _prop_list_t * const properties;
799 static void
800 build_v2_category_template (void)
802 tree decls, *chain = NULL;
804 objc_v2_category_template =
805 objc_start_struct (get_identifier ("_category_t"));
807 /* char *name; */
808 decls = add_field_decl (string_type_node, "name", &chain);
810 /* struct class_t *const cls; */
811 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
813 /* struct method_list_t *instance_methods; */
814 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
816 /* struct method_list_t *class_methods; */
817 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
819 /* struct protocol_list_t *protocol_list; */
820 add_field_decl (build_pointer_type (objc_v2_protocol_template),
821 "protocol_list", &chain );
823 /* struct _prop_list_t * properties; */
824 add_field_decl (objc_prop_list_ptr, "properties", &chain);
826 objc_finish_struct (objc_v2_category_template, decls);
829 /* NOTE --- Decls, Identifiers, Names etc. --- */
831 /* This routine is given a name and returns a matching extern variable if
832 one is found.
835 static tree
836 hash_name_lookup (hash *hashlist, tree name)
838 hash target;
840 target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
842 while (target)
844 if (name == DECL_NAME (target->key))
845 return target->key;
847 target = target->next;
849 return 0;
852 /* This routine is given an extern variable and enters it in its hash table.
853 Note that hashing is done on its inner IDENTIFIER_NODE node.
856 static void
857 hash_name_enter (hash *hashlist, tree id)
859 hash obj;
860 int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
862 obj = ggc_alloc_hashed_entry ();
863 obj->list = 0;
864 obj->next = hashlist[slot];
865 obj->key = id;
867 hashlist[slot] = obj; /* append to front */
870 /* Create a declaration "extern <type> <name>;"
871 The var will need to be finalized (e.g. by calling finish_var_decl()). */
873 static tree
874 create_extern_decl (tree type, const char *name)
876 tree id = get_identifier (name);
877 tree var = hash_name_lookup (extern_names, id);
878 if (var)
879 return var;
880 /* New name. */
881 var = start_var_decl (type, name);
882 TREE_STATIC (var) = 0;
883 DECL_EXTERNAL (var) = 1;
884 TREE_PUBLIC (var) = 1;
885 hash_name_enter (extern_names, var);
886 return var;
889 /* Create a globally visible definition for variable NAME of a given TYPE. The
890 finish_var_decl() routine will need to be called on it afterwards. */
892 static tree
893 create_global_decl (tree type, const char *name)
895 tree id = get_identifier (name);
896 tree var = hash_name_lookup (extern_names, id);
897 if (var)
899 DECL_EXTERNAL (var) = 0;
900 TREE_STATIC (var) = 1;
902 else
904 var = start_var_decl (type, name);
905 hash_name_enter (extern_names, var);
907 TREE_PUBLIC (var) = 1;
908 return var;
911 /* Create a symbol with __attribute__ ((visibility ("hidden")))
912 attribute (private extern) */
914 static tree
915 create_hidden_decl (tree type, const char *name)
917 tree decl = create_global_decl (type, name);
918 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
919 DECL_VISIBILITY_SPECIFIED (decl) = 1;
920 return decl;
923 /* Irritatingly, we have a different superclass field name for ABI=2. */
925 static tree
926 next_runtime_abi_02_super_superclassfield_id (void)
928 if (!super_superclassfield_id)
929 super_superclassfield_id = get_identifier ("cls");
930 return super_superclassfield_id;
933 static tree
934 next_runtime_abi_02_class_decl (tree klass)
936 tree decl;
937 char buf[BUFSIZE];
938 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
939 IDENTIFIER_POINTER (CLASS_NAME (klass)));
940 /* ObjC2 classes are extern visible. */
941 decl = create_global_decl (objc_v2_class_template, buf);
942 OBJCMETA (decl, objc_meta, meta_class);
943 return decl;
946 static tree
947 next_runtime_abi_02_metaclass_decl (tree klass)
949 tree decl;
950 char buf[BUFSIZE];
951 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
952 IDENTIFIER_POINTER (CLASS_NAME (klass)));
953 /* ObjC2 classes are extern visible. */
954 decl = create_global_decl (objc_v2_class_template, buf);
955 OBJCMETA (decl, objc_meta, meta_metaclass);
956 return decl;
959 static tree
960 next_runtime_abi_02_category_decl (tree klass)
962 tree decl;
963 char buf[BUFSIZE];
964 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
965 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
966 IDENTIFIER_POINTER (CLASS_NAME (klass)));
967 decl = start_var_decl (objc_v2_category_template, buf);
968 OBJCMETA (decl, objc_meta, meta_category);
969 return decl;
972 static tree
973 next_runtime_abi_02_protocol_decl (tree p)
975 tree decl;
976 char buf[BUFSIZE];
978 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
979 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
980 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
981 decl = start_var_decl (objc_v2_protocol_template, buf);
982 OBJCMETA (decl, objc_meta, meta_protocol);
983 return decl;
986 static tree
987 next_runtime_abi_02_string_decl (tree type, const char *name, string_section where)
989 tree var = start_var_decl (type, name);
990 switch (where)
992 case class_names:
993 OBJCMETA (var, objc_meta, meta_class_name);
994 break;
995 case meth_var_names:
996 OBJCMETA (var, objc_meta, meta_meth_name);
997 break;
998 case meth_var_types:
999 OBJCMETA (var, objc_meta, meta_meth_type);
1000 break;
1001 case prop_names_attr:
1002 OBJCMETA (var, objc_meta, meta_prop_name_attr);
1003 break;
1004 default:
1005 OBJCMETA (var, objc_meta, meta_base);
1006 break;
1008 return var;
1011 /* NOTE --- entry --- */
1013 typedef struct GTY(()) ident_data_tuple {
1014 tree ident;
1015 tree data;
1016 } ident_data_tuple ;
1017 DEF_VEC_O(ident_data_tuple);
1018 DEF_VEC_ALLOC_O(ident_data_tuple, gc);
1020 /* This routine creates a file scope static variable of type 'Class' to hold
1021 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.
1037 The ident is replaced with address of the class metadata (of type 'Class')
1038 in the output routine. */
1040 static GTY (()) VEC (ident_data_tuple, 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 (ident_data_tuple, 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 classrefs = VEC_alloc (ident_data_tuple, gc, 16);
1064 /* We come here if we don't find the entry - or if the table was yet
1065 to be created. */
1066 decl = build_v2_class_reference_decl (ident);
1067 e.ident = ident;
1068 e.data = decl;
1069 VEC_safe_push (ident_data_tuple, gc, classrefs, &e);
1070 return decl;
1073 static tree
1074 next_runtime_abi_02_get_class_reference (tree ident)
1076 if (!flag_zero_link)
1077 return objc_v2_get_class_reference (ident);
1078 else
1080 /* We fall back to using objc_getClass (). */
1081 VEC(tree,gc) *vec = VEC_alloc (tree, gc, 1);
1082 tree t;
1083 /* ??? add_class_reference (ident); - is pointless, since the
1084 system lib does not export the equivalent symbols. Maybe we
1085 need to build a class ref anyway. */
1086 t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1087 IDENTIFIER_POINTER (ident));
1088 VEC_quick_push (tree, vec, t);
1089 t = build_function_call_vec (input_location, objc_get_class_decl,
1090 vec, NULL);
1091 VEC_free (tree, gc, vec);
1092 return t;
1096 /* Used by get_arg_type_list.
1097 Return the types for receiver & _cmd at the start of a method argument list.
1098 context is either METHOD_DEF or METHOD_REF, saying whether we are trying
1099 to define a method or call one. superflag says this is for a send to super.
1100 meth may be NULL, in the case that there is no prototype. */
1102 static tree
1103 next_runtime_abi_02_get_arg_type_list_base (tree meth, int context, int superflag)
1105 tree arglist;
1107 /* Receiver type. */
1108 if (superflag)
1109 arglist = build_tree_list (NULL_TREE, objc_super_type);
1110 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1111 arglist = build_tree_list (NULL_TREE, objc_instance_type);
1112 else
1113 arglist = build_tree_list (NULL_TREE, objc_object_type);
1115 /* Selector type - will eventually change to `int'. */
1116 chainon (arglist, build_tree_list (NULL_TREE,
1117 (superflag ? objc_v2_super_selector_type
1118 : objc_v2_selector_type)));
1119 return arglist;
1122 /* TODO: Merge this with the message refs. */
1123 static tree
1124 build_selector_reference_decl (tree ident)
1126 tree decl;
1127 char *t, buf[BUFSIZE];
1129 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1130 t = buf;
1131 while (*t)
1133 if (*t==':')
1134 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1135 t++;
1137 decl = start_var_decl (objc_selector_type, buf);
1138 OBJCMETA (decl, objc_meta, meta_sel_refs);
1139 return decl;
1142 static tree
1143 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1144 tree ident,
1145 tree proto ATTRIBUTE_UNUSED)
1147 tree *chain = &sel_ref_chain;
1148 tree expr;
1150 while (*chain)
1152 if (TREE_VALUE (*chain) == ident)
1153 return TREE_PURPOSE (*chain);
1155 chain = &TREE_CHAIN (*chain);
1158 expr = build_selector_reference_decl (ident);
1159 *chain = tree_cons (expr, ident, NULL_TREE);
1161 return expr;
1164 /* Declare a variable of type 'struct message_ref_t'. */
1165 /* This will be finished in build_v2_message_ref_translation_table ().
1166 We take an idea from LLVM in making the names a bit more connected
1167 and thus the asm more readable. */
1169 static tree
1170 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1172 tree decl;
1173 char buf[BUFSIZE], *t;
1174 int offset = 12;
1176 /* Skip past the objc_msgSend it's the same for all... */
1177 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1178 offset++;
1180 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1181 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1182 IDENTIFIER_POINTER (sel_name));
1183 t = buf;
1184 while (*t)
1186 if (*t==':')
1187 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1188 t++;
1190 decl = start_var_decl (objc_v2_message_ref_template, buf);
1191 OBJCMETA (decl, objc_meta, meta_mref);
1192 return decl;
1195 typedef struct GTY(()) msgref_entry {
1196 tree func;
1197 tree selname;
1198 tree refdecl;
1199 } msgref_entry;
1200 DEF_VEC_O(msgref_entry);
1201 DEF_VEC_ALLOC_O(msgref_entry, gc);
1203 static GTY (()) VEC (msgref_entry, gc) * msgrefs;
1205 /* Build the list of (objc_msgSend_fixup_xxx, selector name) Used later on to
1206 initialize the table of 'struct message_ref_t' elements. */
1208 static tree
1209 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1211 tree decl;
1212 msgref_entry e;
1213 if (msgrefs)
1215 int count;
1216 msgref_entry *ref;
1217 FOR_EACH_VEC_ELT (msgref_entry, msgrefs, count, ref)
1218 if (ref->func == message_func_decl && ref->selname == sel_name)
1219 return ref->refdecl;
1221 else
1222 /* Somewhat arbitrary initial provision. */
1223 msgrefs = VEC_alloc (msgref_entry, gc, 32);
1224 /* We come here if we don't find a match or at the start. */
1225 decl = build_v2_message_reference_decl (sel_name,
1226 DECL_NAME (message_func_decl));
1227 e.func = message_func_decl;
1228 e.selname = sel_name;
1229 e.refdecl = decl;
1230 VEC_safe_push (msgref_entry, gc, msgrefs, &e);
1231 return decl;
1234 static tree
1235 build_v2_protocollist_ref_decl (tree protocol)
1237 tree decl;
1238 tree protocol_ident = PROTOCOL_NAME (protocol);
1239 char buf[BUFSIZE];
1241 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1242 IDENTIFIER_POINTER (protocol_ident));
1243 /* TODO: other compiler versions make these hidden & weak. */
1244 decl = create_global_decl (objc_protocol_type, buf);
1245 /* Let optimizer know that this decl is not removable. */
1246 DECL_PRESERVE_P (decl) = 1;
1247 OBJCMETA (decl, objc_meta, meta_proto_ref);
1248 return decl;
1251 typedef struct GTY(()) prot_list_entry {
1252 tree id;
1253 tree refdecl;
1254 } prot_list_entry;
1255 DEF_VEC_O(prot_list_entry);
1256 DEF_VEC_ALLOC_O(prot_list_entry, gc);
1257 static GTY (()) VEC (prot_list_entry, gc) * protrefs;
1259 static tree
1260 objc_v2_get_protocol_reference (tree ident)
1262 tree decl;
1263 prot_list_entry e;
1264 if (protrefs)
1266 int count;
1267 prot_list_entry *ref;
1268 FOR_EACH_VEC_ELT (prot_list_entry, protrefs, count, ref)
1270 if (ref->id == ident)
1272 if (!ref->refdecl)
1273 ref->refdecl = build_v2_protocollist_ref_decl (ident);
1274 return ref->refdecl;
1278 else
1279 /* Somewhat arbitrary initial provision. */
1280 protrefs = VEC_alloc (prot_list_entry, gc, 32);
1281 /* We come here if we don't find the entry - or if the table was yet
1282 to be created. */
1283 decl = build_v2_protocollist_ref_decl (ident);
1284 e.id = ident;
1285 e.refdecl = decl;
1286 VEC_safe_push (prot_list_entry, gc, protrefs, &e);
1287 return decl;
1290 static tree
1291 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1292 tree p)
1294 if (!PROTOCOL_FORWARD_DECL (p))
1295 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1297 return objc_v2_get_protocol_reference (p);
1300 /* This routine returns the ivar declaration, if component is a valid ivar field;
1301 NULL_TREE otherwise. On finding an ivar, it also returns the class name in CLASS.
1304 static tree
1305 objc_is_ivar (tree expr, tree component, tree *klass)
1307 tree field = NULL_TREE;
1308 tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1310 if (TREE_CODE (basetype) == RECORD_TYPE
1311 && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1313 *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1314 if (*klass)
1318 tree ivar_chain = CLASS_RAW_IVARS (*klass);
1319 if (ivar_chain)
1321 field = is_ivar (ivar_chain, component);
1322 if (field != NULL_TREE)
1323 break;
1325 *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1327 while (*klass);
1330 return field;
1333 static void
1334 create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1336 tree fname = DECL_NAME (field_decl);
1338 sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1339 IDENTIFIER_POINTER (fname));
1340 return;
1343 /* This routine generates new abi's ivar reference tree. It amounts to generating
1344 *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally generate pObj->IVAR
1345 OFFSET_IVAR is an 'extern' variable holding the offset for 'IVAR' field. TYPE
1346 is type of IVAR field.
1349 static tree
1350 objc_v2_build_ivar_ref (tree datum, tree component)
1352 tree field, ref, class_name, offset, ftype, expr;
1353 char var_offset_name[512];
1355 field = objc_is_ivar (datum, component, &class_name);
1356 if (!field)
1357 return NULL_TREE;
1359 /* This routine only handles non-bitfield fields */
1360 /* DECL_INITIAL macro is set to width of bitfield and can be relied on to
1361 check for bitfield ivars. Note that I cannot rely on DECL_BIT_FIELD macro
1362 because it is only set when the whole struct is seen (at finish_struct)
1363 and not when the ivar chain is built. */
1364 if (DECL_INITIAL (field))
1365 return NULL_TREE;
1367 create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field);
1369 offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1371 ftype = TREE_TYPE (field);
1373 /* (char*)datum */
1374 expr = build_c_cast (input_location,
1375 string_type_node, build_fold_addr_expr (datum));
1377 /* (char*)datum + offset */
1378 expr = fold_build2_loc (input_location,
1379 POINTER_PLUS_EXPR, string_type_node, expr, offset);
1381 /* (ftype*)((char*)datum + offset) */
1382 expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1384 /* Finally: *(ftype*)((char*)datum + offset) */
1385 ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1387 /* We must set type of the resulting expression to be the same as the
1388 field type. This is because, build_indirect_ref (...) rebuilds the
1389 type which may result in lost information; as in the case of
1390 protocol-qualified types (id <protocol> ). */
1391 TREE_TYPE (ref) = ftype;
1393 if (TREE_READONLY (datum) || TREE_READONLY (field))
1394 TREE_READONLY (ref) = 1;
1396 if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1397 TREE_THIS_VOLATILE (ref) = 1;
1399 if (TREE_DEPRECATED (field))
1400 warn_deprecated_use (field, NULL_TREE);
1402 return ref;
1405 /* IVAR refs are made via an externally referenceable offset and built
1406 on the fly. That is, unless they refer to (private) fields in the
1407 class stucture. */
1408 static tree
1409 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1410 tree base, tree id)
1412 tree ivar;
1413 if ((ivar = objc_v2_build_ivar_ref (base, id)))
1414 return ivar;
1415 return objc_build_component_ref (base, id);
1418 /* [super ...] references are listed here (and built into a table at meta
1419 -data emit time). */
1421 static tree
1422 build_v2_superclass_ref_decl (tree ident, bool inst)
1424 tree decl;
1425 char buf[BUFSIZE];
1427 snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1428 IDENTIFIER_POINTER (ident));
1429 decl = start_var_decl (objc_class_type, buf);
1430 OBJCMETA (decl, objc_meta, meta_superclass_ref);
1431 return decl;
1434 static GTY (()) VEC (ident_data_tuple, gc) * class_super_refs;
1435 static GTY (()) VEC (ident_data_tuple, gc) * metaclass_super_refs;
1437 static tree
1438 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1439 struct imp_entry *imp, bool inst_meth)
1441 tree decl;
1442 ident_data_tuple e;
1443 tree id = CLASS_NAME (imp->imp_context);
1444 VEC (ident_data_tuple, gc) *list = inst_meth ? class_super_refs
1445 : metaclass_super_refs;
1447 if (list)
1449 int count;
1450 ident_data_tuple *ref;
1451 FOR_EACH_VEC_ELT (ident_data_tuple, list, count, ref)
1453 if (ref->ident == id)
1455 if (!ref->data)
1456 ref->data = build_v2_superclass_ref_decl (id, inst_meth);
1457 return ref->data;
1461 else
1463 /* Somewhat arbitrary initial provision. */
1464 if (inst_meth)
1465 list = class_super_refs = VEC_alloc (ident_data_tuple, gc, 16);
1466 else
1467 list = metaclass_super_refs = VEC_alloc (ident_data_tuple, gc, 16);
1469 /* We come here if we don't find the entry - or if the table was yet
1470 to be created. */
1471 decl = build_v2_superclass_ref_decl (id, inst_meth);
1472 e.ident = id;
1473 e.data = decl;
1474 VEC_safe_push (ident_data_tuple, gc, list, &e);
1475 return decl;
1478 static tree
1479 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1480 struct imp_entry *imp, bool inst_meth)
1482 /* ??? is this OK when zero-link = true? */
1483 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1484 tree super_class;
1486 if (!flag_zero_link)
1488 super_class = objc_get_class_reference (CLASS_NAME (imp->imp_template));
1490 if (!inst_meth)
1492 /* If we are in a class method, we must retrieve the
1493 _metaclass_ for the current class, pointed at by
1494 the class's "isa" pointer. The following assumes that
1495 "isa" is the first ivar in a class (which it must be). */
1496 super_class =
1497 build_indirect_ref (input_location,
1498 build_c_cast (input_location,
1499 build_pointer_type (objc_class_type),
1500 super_class),
1501 RO_UNARY_STAR);
1502 return super_class;
1504 /* ??? Do we need to add the class ref anway for zero-link? */
1505 /* else do it the slow way. */
1506 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
1507 /* assemble_external (super_class);*/
1508 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1509 IDENTIFIER_POINTER (super_name));
1510 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1511 return build_function_call (input_location,
1512 super_class,
1513 build_tree_list (NULL_TREE, super_name));
1516 static tree
1517 next_runtime_abi_02_receiver_is_class_object (tree receiver)
1519 if (TREE_CODE (receiver) == VAR_DECL
1520 && IS_CLASS (TREE_TYPE (receiver))
1521 && classrefs
1522 && VEC_length (ident_data_tuple, classrefs))
1524 int count;
1525 ident_data_tuple *ref;
1526 /* The receiver is a variable created by build_class_reference_decl. */
1527 FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
1528 if (ref->data == receiver)
1529 return ref->ident;
1531 return NULL_TREE;
1534 /* Assign all arguments in VALUES which have side-effect to a temporary and
1535 replaced that argument in VALUES list with the temporary. TYPELIST is the
1536 list of argument types. */
1538 static tree
1539 objc_copy_to_temp_side_effect_params (tree typelist, tree values)
1541 tree valtail, typetail;
1542 /* skip over receiver and the &_msf_ref types */
1543 gcc_assert (TREE_CHAIN (typelist));
1544 typetail = TREE_CHAIN (TREE_CHAIN (typelist));
1546 for (valtail = values; valtail;
1547 valtail = TREE_CHAIN (valtail), typetail = TREE_CHAIN (typetail))
1549 tree value = TREE_VALUE (valtail);
1550 tree type = typetail ? TREE_VALUE (typetail) : NULL_TREE;
1551 if (type == NULL_TREE)
1552 break;
1553 if (!TREE_SIDE_EFFECTS (value))
1554 continue;
1555 /* To prevent re-evaluation */
1556 value = save_expr (value);
1557 add_stmt (value);
1558 TREE_VALUE (valtail) = value;
1560 return values;
1563 /* Build the new abi's messaging library call. It looks like:
1564 (*_msg.messenger) (receiver, &_msg, ...)
1567 static tree
1568 build_v2_build_objc_method_call (int super_flag, tree method_prototype,
1569 tree lookup_object, tree selector,
1570 tree method_params,
1571 bool check_for_nil)
1573 tree ret_val;
1574 tree sender, rcv_p, t;
1575 tree ret_type
1576 = (method_prototype
1577 ? TREE_VALUE (TREE_TYPE (method_prototype))
1578 : objc_object_type);
1579 tree method_param_types = get_arg_type_list (method_prototype,
1580 METHOD_REF, super_flag);
1582 tree ftype = build_function_type (ret_type, method_param_types);
1583 tree sender_cast;
1585 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1586 ftype = build_type_attribute_variant (
1587 ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1589 sender_cast = build_pointer_type (ftype);
1591 if (check_for_nil)
1592 method_params = objc_copy_to_temp_side_effect_params (method_param_types,
1593 method_params);
1595 /* Get &message_ref_t.messenger */
1596 sender = build_c_cast (input_location,
1597 build_pointer_type (super_flag
1598 ? objc_v2_super_imp_type
1599 : objc_v2_imp_type),
1600 selector);
1602 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1604 rcv_p = (super_flag ? objc_super_type : objc_object_type);
1606 lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1608 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1609 lookup_object = save_expr (lookup_object);
1611 method_params = tree_cons (NULL_TREE, lookup_object,
1612 tree_cons (NULL_TREE, selector,
1613 method_params));
1614 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
1615 ret_val = build_function_call (input_location, t, method_params);
1616 if (check_for_nil)
1618 /* receiver != nil ? ret_val : 0 */
1619 tree ftree;
1620 tree ifexp;
1622 if (TREE_CODE (ret_type) == RECORD_TYPE
1623 || TREE_CODE (ret_type) == UNION_TYPE)
1625 VEC(constructor_elt,gc) *rtt = NULL;
1626 /* ??? CHECKME. hmmm..... think we need something more here. */
1627 CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE);
1628 ftree = objc_build_constructor (ret_type, rtt);
1630 else
1631 ftree = fold_convert (ret_type, integer_zero_node);
1633 ifexp = build_binary_op (input_location, NE_EXPR,
1634 lookup_object,
1635 fold_convert (rcv_p, integer_zero_node), 1);
1637 #ifdef OBJCPLUS
1638 ret_val = build_conditional_expr (ifexp, ret_val, ftree, tf_warning_or_error);
1639 #else
1640 /* ??? CHECKME. */
1641 ret_val = build_conditional_expr (input_location,
1642 ifexp, 1,
1643 ret_val, NULL_TREE,
1644 ftree, NULL_TREE);
1645 #endif
1647 return ret_val;
1650 static tree
1651 next_runtime_abi_02_build_objc_method_call (location_t loc,
1652 tree method_prototype,
1653 tree receiver,
1654 tree rtype,
1655 tree sel_name,
1656 tree method_params,
1657 int super)
1659 tree ret_type, selector;
1660 tree message_func_decl;
1661 bool check_for_nil = flag_objc_nilcheck;
1663 ret_type = (method_prototype ?
1664 TREE_VALUE (TREE_TYPE (method_prototype)) :
1665 objc_object_type);
1667 /* Do we need to check for nil receivers ? */
1668 /* For now, message sent to classes need no nil check. In future, class
1669 declaration marked as weak_import must be nil checked. */
1670 if (super
1671 || (TREE_CODE (receiver) == VAR_DECL
1672 && TREE_TYPE (receiver) == objc_class_type))
1673 check_for_nil = false;
1675 if (!targetm.calls.struct_value_rtx (0, 0)
1676 && (TREE_CODE (ret_type) == RECORD_TYPE
1677 || TREE_CODE (ret_type) == UNION_TYPE)
1678 && targetm.calls.return_in_memory (ret_type, 0))
1680 if (super)
1681 message_func_decl = umsg_id_super2_stret_fixup_decl;
1682 else
1683 message_func_decl = objc_is_id (rtype)
1684 ? umsg_id_stret_fixup_decl
1685 : umsg_stret_fixup_decl;
1687 else
1689 if (super)
1690 message_func_decl = umsg_id_super2_fixup_decl;
1691 else
1692 message_func_decl = objc_is_id (rtype)
1693 ? umsg_id_fixup_decl
1694 : umsg_fixup_decl;
1697 selector = build_v2_selector_messenger_reference (sel_name,
1698 message_func_decl);
1700 /* selector = &_msg; */
1701 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1703 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1704 : objc_v2_selector_type),
1705 selector);
1707 /* (*_msg.messenger) (receiver, &_msg, ...); */
1708 return build_v2_build_objc_method_call (super, method_prototype,
1709 receiver, selector,
1710 method_params, check_for_nil);
1713 /* NOTE --- Constant String Class Stuff --- */
1715 static bool
1716 next_runtime_abi_02_setup_const_string_class_decl (void)
1718 if (!constant_string_global_id)
1720 /* Hopefully, this should not represent a serious limitation. */
1721 char buf[BUFSIZE];
1722 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1723 constant_string_global_id = get_identifier (buf);
1726 string_class_decl = lookup_name (constant_string_global_id);
1728 /* In OBJC2 abi constant string class reference refers to
1729 class name for NSConstantString class. This declaration may not be
1730 available yet (in fact it is not in most cases). So, declare an extern
1731 OBJC_CLASS_$_NSConstantString in its place. */
1732 if (!string_class_decl)
1733 string_class_decl =
1734 create_extern_decl (objc_v2_class_template,
1735 IDENTIFIER_POINTER (constant_string_global_id));
1737 return (string_class_decl != NULL_TREE);
1740 static tree
1741 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1742 int length)
1744 tree constructor, fields, var;
1745 VEC(constructor_elt,gc) *v = NULL;
1747 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1748 fields = TYPE_FIELDS (internal_const_str_type);
1749 CONSTRUCTOR_APPEND_ELT (v, fields,
1750 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1752 fields = DECL_CHAIN (fields);
1753 CONSTRUCTOR_APPEND_ELT (v, fields,
1754 build_unary_op (loc, ADDR_EXPR, string, 1));
1756 /* ??? check if this should be long. */
1757 fields = DECL_CHAIN (fields);
1758 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1759 constructor = objc_build_constructor (internal_const_str_type, v);
1761 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1762 DECL_INITIAL (var) = constructor;
1763 TREE_STATIC (var) = 1;
1764 DECL_CONTEXT (var) = NULL;
1765 OBJCMETA (var, objc_meta, meta_const_str);
1766 return var;
1769 /* NOTE --- NeXT V2 Metadata templates --- */
1771 /* This routine builds the following type:
1772 struct _prop_t {
1773 const char * const name; // property name
1774 const char * const attributes; // comma-delimited, encoded,
1775 // property attributes
1779 static tree
1780 build_v2_property_template (void)
1782 tree prop_record;
1783 tree decls, *chain = NULL;
1785 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1786 /* const char * name */
1787 decls = add_field_decl (string_type_node, "name", &chain);
1789 /* const char * attribute */
1790 add_field_decl (string_type_node, "attribute", &chain);
1792 objc_finish_struct (prop_record, decls);
1793 return prop_record;
1796 /* struct ivar_t {
1797 unsigned long int *offset;
1798 char *name;
1799 char *type;
1800 uint32_t alignment;
1801 uint32_t size;
1805 static tree
1806 build_v2_ivar_t_template (void)
1808 tree objc_ivar_id, objc_ivar_record;
1809 tree decls, *chain = NULL;
1811 objc_ivar_id = get_identifier ("_ivar_t");
1812 objc_ivar_record = objc_start_struct (objc_ivar_id);
1814 /* unsigned long int *offset */
1815 decls = add_field_decl (build_pointer_type
1816 (TREE_TYPE (size_zero_node)), "offset", &chain);
1818 /* char *name; */
1819 add_field_decl (string_type_node, "name", &chain);
1821 /* char *type; */
1822 add_field_decl (string_type_node, "type", &chain);
1824 /* uint32_t alignment; */
1825 add_field_decl (integer_type_node, "alignment", &chain);
1827 /* uint32_t size; */
1828 add_field_decl (integer_type_node, "size", &chain);
1830 objc_finish_struct (objc_ivar_record, decls);
1831 return objc_ivar_record;
1834 static void
1835 build_metadata_templates (void)
1838 if (!objc_method_template)
1839 objc_method_template = build_method_template ();
1841 if (!objc_v2_property_template)
1842 objc_v2_property_template = build_v2_property_template ();
1844 if (!objc_v2_ivar_template)
1845 objc_v2_ivar_template = build_v2_ivar_t_template ();
1849 /* NOTE --- Output NeXT V2 Metadata --- */
1851 /* Routine builds name of Interface's main meta-data of type class_t. */
1853 static char *
1854 objc_build_internal_classname (tree ident, bool metaclass)
1856 static char string[512];
1857 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
1858 : "OBJC_CLASS_$",
1859 IDENTIFIER_POINTER (ident));
1860 return string;
1863 /* Build the name for object of type struct class_ro_t */
1865 static const char *
1866 newabi_append_ro (const char *name)
1868 char *dollar;
1869 char *p;
1870 static char string[BUFSIZE];
1871 dollar = strchr (name, '$');
1872 gcc_assert (dollar);
1873 p = string;
1874 *p = '_'; p++;
1875 strncpy (p, name, (int)(dollar - name));
1876 p += (int)(dollar - name);
1877 sprintf (p, "RO_%s", dollar);
1878 return string;
1881 /* Build the struct message_ref_t msg =
1882 {objc_msgSend_fixup_xxx, @selector(func)}
1883 table.
1886 static
1887 void build_v2_message_ref_translation_table (void)
1889 int count;
1890 msgref_entry *ref;
1892 if (!msgrefs || !VEC_length (msgref_entry,msgrefs))
1893 return;
1895 FOR_EACH_VEC_ELT (msgref_entry, msgrefs, count, ref)
1897 VEC(constructor_elt,gc) *initializer;
1898 tree expr, constructor;
1899 tree struct_type = TREE_TYPE (ref->refdecl);
1900 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
1902 initializer = NULL;
1903 /* First 'IMP messenger' field.. */
1904 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
1905 expr = convert (objc_v2_imp_type, expr);
1906 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1908 /* then.. 'SEL name' field */
1909 expr = build_selector (ref->selname);
1910 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1911 constructor = objc_build_constructor (struct_type, initializer);
1912 finish_var_decl (ref->refdecl, constructor);
1916 /* Build decl = initializer; for each externally visible class reference. */
1918 static void
1919 build_v2_classrefs_table (void)
1921 int count;
1922 ident_data_tuple *ref;
1924 if (!classrefs || !VEC_length (ident_data_tuple, classrefs))
1925 return;
1927 FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
1929 tree expr = ref->ident;
1930 tree decl = ref->data;
1931 /* Interface with no implementation and yet one of its messages has been
1932 used. Need to generate a full address-of tree for it here. */
1933 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1935 const char *name = objc_build_internal_classname (expr, false);
1936 expr = create_extern_decl (objc_v2_class_template, name);
1937 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1939 /* The runtime wants this, even if it appears unused, so we must force the
1940 output.
1941 DECL_PRESERVE_P (decl) = 1; */
1942 finish_var_decl (decl, expr);
1946 /* Build decl = initializer; for each externally visible class reference. */
1948 static void
1949 build_v2_super_classrefs_table (bool metaclass)
1951 int count;
1952 ident_data_tuple *ref;
1953 VEC (ident_data_tuple, gc) *list = metaclass ? metaclass_super_refs
1954 : class_super_refs;
1956 if (!list || !VEC_length (ident_data_tuple, list))
1957 return;
1959 FOR_EACH_VEC_ELT (ident_data_tuple, list, count, ref)
1961 tree expr = ref->ident;
1962 tree decl = ref->data;
1963 /* Interface with no implementation and yet one of its messages has been
1964 used. Need to generate a full address-of tree for it here. */
1965 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1967 const char * name = objc_build_internal_classname (expr, metaclass);
1968 expr = create_extern_decl (objc_v2_class_template, name);
1969 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1971 finish_var_decl (decl, expr);
1975 /* Add the global class meta-data declaration to the list which later on
1976 ends up in the __class_list section. */
1978 static GTY(()) VEC(tree,gc) *class_list;
1980 static void
1981 objc_v2_add_to_class_list (tree global_class_decl)
1983 if (!class_list)
1984 class_list = VEC_alloc (tree, gc, imp_count?imp_count:1);
1985 VEC_safe_push (tree, gc, class_list, global_class_decl);
1988 static GTY(()) VEC(tree,gc) *nonlazy_class_list;
1990 /* Add the global class meta-data declaration to the list which later on
1991 ends up in the __nonlazy_class section. */
1993 static void
1994 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
1996 if (!nonlazy_class_list)
1997 nonlazy_class_list = VEC_alloc (tree, gc, imp_count?imp_count:1);
1998 VEC_safe_push (tree, gc, nonlazy_class_list, global_class_decl);
2001 static GTY(()) VEC(tree,gc) *category_list;
2003 /* Add the category meta-data declaration to the list which later on ends up
2004 in the __nonlazy_category section. */
2006 static void
2007 objc_v2_add_to_category_list (tree decl)
2009 if (!category_list)
2010 category_list = VEC_alloc (tree, gc, cat_count?cat_count:1);
2011 VEC_safe_push (tree, gc, category_list, decl);
2014 static GTY(()) VEC(tree,gc) *nonlazy_category_list;
2016 /* Add the category meta-data declaration to the list which later on ends up
2017 in the __category_list section. */
2019 static void
2020 objc_v2_add_to_nonlazy_category_list (tree decl)
2022 if (!nonlazy_category_list)
2023 nonlazy_category_list = VEC_alloc (tree, gc, cat_count?cat_count:1);
2024 VEC_safe_push (tree, gc, nonlazy_category_list, decl);
2027 static bool
2028 has_load_impl (tree clsmeth)
2030 while (clsmeth)
2032 tree id = METHOD_SEL_NAME (clsmeth);
2033 if (IDENTIFIER_LENGTH (id) == 4
2034 && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
2035 return true;
2036 clsmeth = DECL_CHAIN (clsmeth);
2039 return false;
2042 /* Build a __{class,category}_list section table containing address of all
2043 @implemented {class,category} meta-data. */
2045 static void
2046 build_v2_address_table (VEC(tree,gc) *src, const char *nam, tree attr)
2048 int count=0;
2049 tree type, decl, expr;
2050 VEC(constructor_elt,gc) *initlist = NULL;
2052 if (!src || !VEC_length(tree,src))
2053 return;
2055 FOR_EACH_VEC_ELT (tree, src, count, decl)
2057 #ifndef OBJCPLUS
2058 tree purpose = build_int_cst (NULL_TREE, count);
2059 #else
2060 tree purpose = NULL_TREE;
2061 #endif
2062 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2063 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2065 gcc_assert (count > 0);
2066 type = build_array_type (objc_class_type,
2067 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2068 decl = start_var_decl (type, nam);
2069 /* The runtime wants this, even if it appears unused, so we must force the
2070 output. */
2071 DECL_PRESERVE_P (decl) = 1;
2072 expr = objc_build_constructor (type, initlist);
2073 OBJCMETA (decl, objc_meta, attr);
2074 finish_var_decl (decl, expr);
2077 /* Build decl = initializer;
2078 for each protocol referenced in @protocol(MyProt) expression.
2079 Refs as built in the entry section above. */
2081 static void
2082 build_v2_protocol_list_translation_table (void)
2084 int count;
2085 prot_list_entry *ref;
2087 if (!protrefs)
2088 return;
2090 FOR_EACH_VEC_ELT (prot_list_entry, protrefs, count, ref)
2092 char buf[BUFSIZE];
2093 tree expr;
2094 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2095 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2096 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2097 expr = start_var_decl (objc_v2_protocol_template, buf);
2098 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2099 finish_var_decl (ref->refdecl, expr);
2101 /* TODO: Maybe we could explicitly delete the vec. now? */
2104 static GTY (()) VEC (prot_list_entry, gc) * protlist;
2106 /* Add the local protocol meta-data declaration to the list which later on ends up
2107 in the __protocol_list section. */
2109 static void
2110 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2112 prot_list_entry e;
2113 if (!protlist)
2114 /* Arbitrary init count. */
2115 protlist = VEC_alloc (prot_list_entry, gc, 32);
2116 e.id = protocol_interface_decl;
2117 e.refdecl = protocol_decl;
2118 VEC_safe_push (prot_list_entry, gc, protlist, &e);
2121 /* Build the __protocol_list section table containing address of all generate protocol_t
2122 meta-data. */
2124 static void
2125 build_v2_protocol_list_address_table (void)
2127 int count;
2128 prot_list_entry *ref;
2129 if (!protlist || !VEC_length (prot_list_entry, protlist))
2130 return;
2132 FOR_EACH_VEC_ELT (prot_list_entry, protlist, count, ref)
2134 tree decl, expr;
2135 char buf[BUFSIZE];
2136 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2137 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2138 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2139 decl = create_global_decl (objc_protocol_type, buf);
2140 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2141 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2142 finish_var_decl (decl, expr);
2145 /* TODO: delete the vec. */
2146 /* TODO: upgrade to the the clang/llvm hidden version. */
2149 /* This routine declares a variable to hold meta data for
2150 'struct protocol_list_t'. */
2152 static tree
2153 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2155 tree refs_decl, lproto, e, plist, ptempl_p_t;
2156 int size = 0;
2157 VEC(constructor_elt,gc) *initlist = NULL;
2158 char buf[BUFSIZE];
2160 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2161 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2162 plist = CLASS_PROTOCOL_LIST (i_or_p);
2163 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2164 plist = PROTOCOL_LIST (i_or_p);
2165 else
2166 gcc_unreachable ();
2168 /* Compute size. */
2169 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2170 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2171 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2172 size++;
2174 /* Build initializer. */
2176 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2177 e = build_int_cst (ptempl_p_t, size);
2178 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2180 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2182 tree pval = TREE_VALUE (lproto);
2184 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2185 && PROTOCOL_FORWARD_DECL (pval))
2187 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2188 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2189 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2190 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2194 /* static struct protocol_list_t *list[size]; */
2196 switch (TREE_CODE (i_or_p))
2198 case PROTOCOL_INTERFACE_TYPE:
2199 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2200 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2201 break;
2202 case CLASS_INTERFACE_TYPE:
2203 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2204 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2205 break;
2206 case CATEGORY_INTERFACE_TYPE:
2207 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2208 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2209 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2210 break;
2211 default:
2212 gcc_unreachable ();
2215 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2216 buf);
2217 /* ObjC2 puts all these in the base section. */
2218 OBJCMETA (refs_decl, objc_meta, meta_base);
2219 DECL_PRESERVE_P (refs_decl) = 1;
2220 finish_var_decl (refs_decl,
2221 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2222 return refs_decl;
2225 /* This routine builds one 'struct method_t' initializer list. Note that the
2226 old ABI is supposed to build 'struct objc_method' which has 3 fields, but
2227 it does not build the initialization expression for 'method_imp' which for
2228 protocols is NULL any way. To be consistant with declaration of
2229 'struct method_t', in the new ABI we set the method_t.imp to NULL.
2232 static tree
2233 build_v2_descriptor_table_initializer (tree type, tree entries)
2235 VEC(constructor_elt,gc) *initlist = NULL;
2238 VEC(constructor_elt,gc) *eltlist = NULL;
2239 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2240 build_selector (METHOD_SEL_NAME (entries)));
2241 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2242 add_objc_string (METHOD_ENCODING (entries),
2243 meth_var_types));
2244 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2246 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2247 objc_build_constructor (type, eltlist));
2248 entries = TREE_CHAIN (entries);
2250 while (entries);
2252 return objc_build_constructor (build_array_type (type, 0), initlist);
2255 /* struct method_list_t {
2256 uint32_t entsize;
2257 uint32_t method_count;
2258 struct objc_method method_list[method_count];
2259 }; */
2261 static tree
2262 build_v2_method_list_template (tree list_type, int size)
2264 tree method_list_t_record;
2265 tree array_type, decls, *chain = NULL;
2267 method_list_t_record = objc_start_struct (NULL_TREE);
2269 /* uint32_t const entsize */
2270 decls = add_field_decl (integer_type_node, "entsize", &chain);
2272 /* int method_count; */
2273 add_field_decl (integer_type_node, "method_count", &chain);
2275 /* struct objc_method method_list[]; */
2276 array_type = build_sized_array_type (list_type, size);
2277 add_field_decl (array_type, "method_list", &chain);
2279 objc_finish_struct (method_list_t_record, decls);
2280 return method_list_t_record;
2283 /* Note, as above that we are building to the objc_method_template
2284 which has the *imp field. ABI0/1 build with objc_method_prototype_template
2285 which is missing this field. */
2286 static tree
2287 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2288 const char *prefix, tree attr)
2290 tree method_list_template, initlist, decl, methods;
2291 int size, entsize;
2292 VEC(constructor_elt,gc) *v = NULL;
2293 char buf[BUFSIZE];
2295 if (!chain || !prefix)
2296 return NULL_TREE;
2298 methods = chain;
2299 size = 0;
2300 while (methods)
2302 if (! METHOD_ENCODING (methods))
2303 METHOD_ENCODING (methods) = encode_method_prototype (methods);
2304 methods = TREE_CHAIN (methods);
2305 size++;
2308 gcc_assert (size);
2309 method_list_template = build_v2_method_list_template (objc_method_template,
2310 size);
2311 snprintf (buf, BUFSIZE, "%s_%s", prefix,
2312 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2314 decl = start_var_decl (method_list_template, buf);
2316 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2317 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2318 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2319 initlist =
2320 build_v2_descriptor_table_initializer (objc_method_template,
2321 chain);
2322 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2323 /* Get into the right section. */
2324 OBJCMETA (decl, objc_meta, attr);
2325 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2326 return decl;
2329 /* This routine builds the initializer list to initialize the
2330 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2332 static tree
2333 build_v2_property_table_initializer (tree type, tree context)
2335 tree x;
2336 VEC(constructor_elt,gc) *inits = NULL;
2337 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2338 x = CLASS_PROPERTY_DECL (context);
2339 else
2340 x = IMPL_PROPERTY_DECL (context);
2342 for (; x; x = TREE_CHAIN (x))
2344 VEC(constructor_elt,gc) *elemlist = NULL;
2345 /* NOTE! sections where property name/attribute go MUST change later. */
2346 tree attribute, name_ident = PROPERTY_NAME (x);
2348 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2349 add_objc_string (name_ident, prop_names_attr));
2351 attribute = objc_v2_encode_prop_attr (x);
2352 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2353 add_objc_string (attribute, prop_names_attr));
2355 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2356 objc_build_constructor (type, elemlist));
2359 return objc_build_constructor (build_array_type (type, 0),inits);
2362 /* This routine builds the following type:
2363 struct _prop_list_t {
2364 uint32_t entsize; // sizeof (struct _prop_t)
2365 uint32_t prop_count;
2366 struct _prop_t prop_list [prop_count];
2370 static tree
2371 build_v2_property_list_template (tree list_type, int size)
2373 tree property_list_t_record;
2374 tree array_type, decls, *chain = NULL;
2376 /* anonymous. */
2377 property_list_t_record = objc_start_struct (NULL_TREE);
2379 /* uint32_t const entsize */
2380 decls = add_field_decl (integer_type_node, "entsize", &chain);
2382 /* int prop_count */
2383 add_field_decl (integer_type_node, "prop_count", &chain);
2385 /* struct _prop_t prop_list[]; */
2386 array_type = build_sized_array_type (list_type, size);
2387 add_field_decl (array_type, "prop_list", &chain);
2389 objc_finish_struct (property_list_t_record, decls);
2390 return property_list_t_record;
2394 Top-level routine to generate property tables for each implementation.
2397 static tree
2398 generate_v2_property_table (tree context, tree klass_ctxt)
2400 tree x, decl, initlist, property_list_template;
2401 bool is_proto = false;
2402 VEC(constructor_elt,gc) *inits = NULL;
2403 int init_val, size = 0;
2404 char buf[BUFSIZE];
2406 if (context)
2408 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2409 x = CLASS_PROPERTY_DECL (context);
2410 is_proto = true;
2412 else
2413 x = IMPL_PROPERTY_DECL (klass_ctxt);
2415 for (; x; x = TREE_CHAIN (x))
2416 size++;
2418 if (size == 0)
2419 return NULL_TREE;
2421 property_list_template =
2422 build_v2_property_list_template (objc_v2_property_template,
2423 size);
2425 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2426 is_proto ? context
2427 : klass_ctxt);
2429 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2430 if (is_proto)
2431 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2432 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2433 else
2434 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2435 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2437 decl = start_var_decl (property_list_template, buf);
2439 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2440 build_int_cst (NULL_TREE, init_val));
2441 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2442 build_int_cst (NULL_TREE, size));
2443 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2445 OBJCMETA (decl, objc_meta, meta_base);
2446 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2447 return decl;
2450 static tree
2451 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2452 tree inst_methods, tree class_methods,
2453 tree opt_ins_meth, tree opt_cls_meth,
2454 tree property_list)
2456 tree expr, ttyp;
2457 location_t loc;
2458 VEC(constructor_elt,gc) *inits = NULL;
2460 /* TODO: find a better representation of location from the inputs. */
2461 loc = UNKNOWN_LOCATION;
2463 /* This is NULL for the new ABI. */
2464 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2465 convert (objc_object_type, null_pointer_node));
2467 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2468 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2470 ttyp = objc_method_proto_list_ptr;
2471 if (inst_methods)
2472 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2473 else
2474 expr = convert (ttyp, null_pointer_node);
2475 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2477 if (class_methods)
2478 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2479 else
2480 expr = convert (ttyp, null_pointer_node);
2481 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2483 if (opt_ins_meth)
2484 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2485 else
2486 expr = convert (ttyp, null_pointer_node);
2487 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2489 if (opt_cls_meth)
2490 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2491 else
2492 expr = convert (ttyp, null_pointer_node);
2493 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2495 ttyp = objc_prop_list_ptr;
2496 if (property_list)
2497 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2498 else
2499 expr = convert (ttyp, null_pointer_node);
2500 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2502 /* const uint32_t size; = sizeof(struct protocol_t) */
2503 expr = build_int_cst (integer_type_node,
2504 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2505 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2506 /* const uint32_t flags; = 0 */
2507 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2509 return objc_build_constructor (type, inits);
2513 Main routine to build all meta data for all protocols used in a translation unit.
2516 static void
2517 generate_v2_protocols (void)
2519 tree p ;
2520 bool some = false;
2522 if (!protocol_chain)
2523 return ;
2525 /* If a protocol was directly referenced, pull in indirect references. */
2526 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2527 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2528 generate_protocol_references (PROTOCOL_LIST (p));
2530 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2532 location_t loc;
2533 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2534 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2536 /* If protocol wasn't referenced, don't generate any code. */
2537 decl = PROTOCOL_FORWARD_DECL (p);
2539 if (!decl)
2540 continue;
2542 loc = DECL_SOURCE_LOCATION (decl);
2543 some = true;
2545 inst_meth =
2546 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2547 "_OBJC_ProtocolInstanceMethods",
2548 meta_proto_nst_meth);
2550 class_meth =
2551 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2552 "_OBJC_ProtocolClassMethods",
2553 meta_proto_cls_meth);
2555 opt_inst_meth =
2556 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2557 "_OBJC_OptProtocolInstMethods",
2558 meta_proto_nst_meth);
2560 opt_class_meth =
2561 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2562 "_OBJC_OptProtocolClassMethods",
2563 meta_proto_cls_meth);
2565 if (PROTOCOL_LIST (p))
2566 refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2567 else
2568 refs_decl = 0;
2570 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2571 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2573 if (refs_decl)
2574 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2575 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2576 else
2577 refs_expr = build_int_cst (NULL_TREE, 0);
2579 props = generate_v2_property_table (p, NULL_TREE);
2581 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2582 protocol_name_expr, refs_expr,
2583 inst_meth, class_meth,
2584 opt_inst_meth, opt_class_meth,
2585 props);
2586 finish_var_decl (decl, initlist);
2587 objc_add_to_protocol_list (p, decl);
2590 if (some)
2592 /* Make sure we get the Protocol class linked in - reference it... */
2593 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2594 /* .. but since we don't specifically use the ref..
2595 we need to force it. */
2596 DECL_PRESERVE_P (p) = 1;
2600 static tree
2601 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2603 tree decl, method_list_template, initlist;
2604 VEC(constructor_elt,gc) *v = NULL;
2605 int size, init_val;
2607 if (!chain || !name || !(size = list_length (chain)))
2608 return NULL_TREE;
2610 method_list_template
2611 = build_v2_method_list_template (objc_method_template, size);
2612 initlist
2613 = build_dispatch_table_initializer (objc_method_template, chain);
2615 decl = start_var_decl (method_list_template, name);
2617 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2618 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2619 build_int_cst (integer_type_node, init_val));
2620 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2621 build_int_cst (integer_type_node, size));
2622 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2624 OBJCMETA (decl, objc_meta, attr);
2625 finish_var_decl (decl,
2626 objc_build_constructor (TREE_TYPE (decl), v));
2627 return decl;
2630 /* Init a category. */
2631 static tree
2632 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2633 tree inst_methods, tree class_methods,
2634 tree protocol_list, tree property_list,
2635 location_t loc)
2637 tree expr, ltyp;
2638 VEC(constructor_elt,gc) *v = NULL;
2640 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2641 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2643 ltyp = objc_method_list_ptr;
2644 if (inst_methods)
2645 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2646 else
2647 expr = convert (ltyp, null_pointer_node);
2648 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2650 if (class_methods)
2651 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2652 else
2653 expr = convert (ltyp, null_pointer_node);
2654 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2656 /* protocol_list = */
2657 ltyp = build_pointer_type (objc_v2_protocol_template);
2658 if (protocol_list)
2659 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2660 else
2661 expr = convert (ltyp, null_pointer_node);
2662 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2664 ltyp = objc_prop_list_ptr;
2665 if (property_list)
2666 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2667 else
2668 expr = convert (ltyp, null_pointer_node);
2669 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2671 return objc_build_constructor (type, v);
2674 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2676 static void
2677 generate_v2_category (struct imp_entry *impent)
2679 tree initlist, cat_name_expr, class_name_expr;
2680 tree protocol_decl, category, props, t;
2681 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2682 tree cat = impent->imp_context;
2683 tree cat_decl = impent->class_decl;
2684 location_t loc;
2685 char buf[BUFSIZE];
2687 loc = DECL_SOURCE_LOCATION (cat_decl);
2689 /* ??? not sure this is really necessary, the following references should
2690 force appropriate linkage linkage...
2691 -- but ... ensure a reference to the class... */
2692 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2693 /* ... which we ignore so force it out.. */
2694 DECL_PRESERVE_P (t) = 1;
2696 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2697 class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2698 class_name_expr = build_fold_addr_expr (class_name_expr);
2700 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2701 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2703 if (category && CLASS_PROTOCOL_LIST (category))
2705 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2706 protocol_decl = generate_v2_protocol_list (category, cat);
2708 else
2709 protocol_decl = NULL_TREE;
2711 /* decl = update_var_decl(impent->class_decl);*/
2713 props = generate_v2_property_table (NULL_TREE, cat);
2715 if (CLASS_NST_METHODS (cat))
2717 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2718 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2719 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2720 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2721 meta_cati_meth);
2724 if (CLASS_CLS_METHODS (cat))
2726 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2727 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2728 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2729 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2730 meta_catc_meth);
2733 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2734 cat_name_expr, class_name_expr,
2735 inst_methods, class_methods,
2736 protocol_decl, props, loc);
2738 finish_var_decl (cat_decl, initlist);
2739 impent->class_decl = cat_decl;
2741 /* Add to list of pointers in __category_list section */
2742 objc_v2_add_to_category_list (cat_decl);
2743 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2744 objc_v2_add_to_nonlazy_category_list (cat_decl);
2747 /* This routine declares a variable to hold the offset for ivar FIELD_DECL.
2748 Variable name is .objc_ivar.ClassName.IvarName. */
2750 typedef struct GTY(()) ivarref_entry {
2751 tree decl;
2752 tree offset;
2753 } ivarref_entry;
2754 DEF_VEC_O(ivarref_entry);
2755 DEF_VEC_ALLOC_O(ivarref_entry, gc);
2757 static GTY (()) VEC (ivarref_entry, gc) * ivar_offset_refs;
2759 static tree
2760 ivar_offset_ref (tree class_name, tree field_decl)
2762 tree decl, field_decl_id;
2763 ivarref_entry e;
2764 bool global_var;
2765 char buf[512];
2767 create_ivar_offset_name (buf, class_name, field_decl);
2768 field_decl_id = get_identifier (buf);
2770 if (ivar_offset_refs)
2772 int count;
2773 ivarref_entry *ref;
2774 FOR_EACH_VEC_ELT (ivarref_entry, ivar_offset_refs, count, ref)
2775 if (DECL_NAME (ref->decl) == field_decl_id)
2776 return ref->decl;
2778 else
2779 /* Somewhat arbitrary initial provision. */
2780 ivar_offset_refs = VEC_alloc (ivarref_entry, gc, 32);
2782 /* We come here if we don't find a match or at the start. */
2783 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
2784 if (global_var)
2785 decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
2786 else
2787 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
2789 /* Make sure it ends up in an ObjC section. */
2790 OBJCMETA (decl, objc_meta, meta_base);
2792 e.decl = decl;
2793 e.offset = byte_position (field_decl);
2794 VEC_safe_push (ivarref_entry, gc, ivar_offset_refs, &e);
2795 return decl;
2798 /* This routine builds initializer-list needed to initialize
2799 'struct ivar_t list[count]
2800 of 'struct ivar_list_t' meta data. TYPE is 'struct ivar_t' and
2801 FIELD_DECL is list of ivars for the target class.
2804 static tree
2805 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
2807 VEC(constructor_elt,gc) *inits = NULL;
2811 VEC(constructor_elt,gc) *ivar = NULL;
2812 int val;
2813 tree id;
2815 /* Unnamed bitfields are ignored. */
2816 if (!DECL_NAME (field_decl))
2818 field_decl = DECL_CHAIN (field_decl);
2819 continue;
2822 /* Set offset */
2823 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2824 build_unary_op (input_location,
2825 ADDR_EXPR,
2826 ivar_offset_ref (class_name,
2827 field_decl), 0));
2829 /* Set name */
2830 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2831 add_objc_string (DECL_NAME (field_decl),
2832 meth_var_names));
2834 /* Set type */
2835 encode_field_decl (field_decl,
2836 obstack_object_size (&util_obstack),
2837 OBJC_ENCODE_DONT_INLINE_DEFS);
2838 /* Null terminate string. */
2839 obstack_1grow (&util_obstack, 0);
2840 id = add_objc_string (get_identifier (XOBFINISH (&util_obstack, char *)),
2841 meth_var_types);
2842 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
2843 obstack_free (&util_obstack, util_firstobj);
2845 /* Set alignment */
2846 val = DECL_ALIGN_UNIT (field_decl);
2847 val = exact_log2 (val);
2848 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2849 build_int_cst (integer_type_node, val));
2851 /* Set size */
2852 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
2853 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2854 build_int_cst (integer_type_node, val));
2856 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2857 objc_build_constructor (type, ivar));
2860 field_decl = DECL_CHAIN (field_decl);
2861 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
2863 while (field_decl);
2865 return objc_build_constructor (build_array_type (type, 0), inits);
2869 struct ivar_list_t {
2870 uint32 entsize;
2871 uint32 count;
2872 struct iver_t list[count];
2876 static tree
2877 build_v2_ivar_list_t_template (tree list_type, int size)
2879 tree objc_ivar_list_record;
2880 tree decls, *chain = NULL;
2882 /* Anonymous. */
2883 objc_ivar_list_record = objc_start_struct (NULL_TREE);
2885 /* uint32 entsize; */
2886 decls = add_field_decl (integer_type_node, "entsize", &chain);
2888 /* uint32 count; */
2889 add_field_decl (integer_type_node, "count", &chain);
2891 /* struct objc_ivar ivar_list[]; */
2892 add_field_decl (build_sized_array_type (list_type, size),
2893 "list", &chain);
2895 objc_finish_struct (objc_ivar_list_record, decls);
2896 return objc_ivar_list_record;
2899 /* This routine declares a static variable of type 'struct ivar_list_t' and
2900 initializes it.
2901 chain is the source of the data, name is the name for the var.
2902 attr is the meta-data section tag attribute
2903 templ is the implementation template for the class. */
2905 static tree
2906 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
2908 tree decl, initlist, ivar_list_template;
2909 VEC(constructor_elt,gc) *inits = NULL;
2910 int size, ivar_t_size;
2912 if (!chain || !name || !(size = ivar_list_length (chain)))
2913 return NULL_TREE;
2915 generating_instance_variables = 1;
2916 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
2917 size);
2919 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
2920 objc_v2_ivar_template, chain);
2921 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
2923 decl = start_var_decl (ivar_list_template, name);
2924 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2925 build_int_cst (integer_type_node, ivar_t_size));
2926 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2927 build_int_cst (integer_type_node, size));
2928 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2929 OBJCMETA (decl, objc_meta, attr);
2930 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2931 generating_instance_variables = 0;
2932 return decl;
2935 /* Routine to build initializer list to initialize objects of type struct class_t; */
2937 static tree
2938 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
2939 tree ro, tree cache, tree vtable)
2941 VEC(constructor_elt,gc) *initlist = NULL;
2943 /* isa */
2944 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
2946 /* superclass */
2947 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
2949 /* cache */
2950 if (cache)
2951 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
2952 else
2953 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2955 /* vtable */
2956 if (vtable)
2957 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
2958 else
2959 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2961 /* ro */
2962 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
2964 return objc_build_constructor (type, initlist);
2967 /* Routine to build object of struct class_ro_t { ... }; */
2969 static tree
2970 build_v2_class_ro_t_initializer (tree type, tree name,
2971 unsigned int flags, unsigned int instanceStart,
2972 unsigned int instanceSize,
2973 tree ivarLayout,
2974 tree baseMethods, tree baseProtocols,
2975 tree ivars, tree property_list)
2977 tree expr, unsigned_char_star, ltyp;
2978 location_t loc;
2979 VEC(constructor_elt,gc) *initlist = NULL;
2981 /* TODO: fish out the real location from somewhere. */
2982 loc = UNKNOWN_LOCATION;
2984 /* flags */
2985 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2986 build_int_cst (integer_type_node, flags));
2988 /* instanceStart */
2989 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2990 build_int_cst (integer_type_node, instanceStart));
2992 /* instanceSize */
2993 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2994 build_int_cst (integer_type_node, instanceSize));
2996 /* This ABI is currently only used on m64 NeXT, we choose to
2997 make the alignment padding explicit. */
2998 /* reserved, pads alignment. */
2999 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3000 build_int_cst (integer_type_node, 0));
3002 /* ivarLayout */
3003 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3004 if (ivarLayout)
3005 expr = ivarLayout;
3006 else
3007 expr = convert (unsigned_char_star, null_pointer_node);
3008 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3010 /* name */
3011 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3013 /* baseMethods */
3014 ltyp = objc_method_list_ptr;
3015 if (baseMethods)
3016 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3017 else
3018 expr = convert (ltyp, null_pointer_node);
3019 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3021 /* baseProtocols */
3022 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3023 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3024 if (baseProtocols)
3025 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3026 else
3027 expr = convert (ltyp, null_pointer_node);
3028 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3030 /* ivars */
3031 ltyp = objc_v2_ivar_list_ptr;
3032 if (ivars)
3033 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3034 else
3035 expr = convert (ltyp, null_pointer_node);
3036 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3038 /* TODO: We don't yet have the weak/strong stuff... */
3039 /* weakIvarLayout */
3040 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3041 convert (unsigned_char_star, null_pointer_node));
3043 /* property list */
3044 ltyp = objc_prop_list_ptr;
3045 if (property_list)
3046 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3047 else
3048 expr = convert (ltyp, null_pointer_node);
3049 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3050 return objc_build_constructor (type, initlist);
3053 static GTY (()) VEC (ident_data_tuple, gc) * ehtype_list;
3055 /* Record a name as needing a catcher. */
3056 static void
3057 objc_v2_add_to_ehtype_list (tree name)
3059 ident_data_tuple e;
3060 if (ehtype_list)
3062 int count = 0;
3063 ident_data_tuple *ref;
3065 FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3066 if (ref->ident == name)
3067 return; /* Already entered. */
3069 else
3070 /* Arbitrary initial count. */
3071 ehtype_list = VEC_alloc (ident_data_tuple, gc, 8);
3072 /* Not found, or new list. */
3073 e.ident = name;
3074 e.data = NULL_TREE;
3075 VEC_safe_push (ident_data_tuple, gc, ehtype_list, &e);
3078 static void
3079 generate_v2_class_structs (struct imp_entry *impent)
3081 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3082 tree field, firstIvar, chain;
3083 tree class_superclass_expr, metaclass_superclass_expr, props;
3084 /* TODO: figure out how to compute this. */
3085 tree ivarLayout = NULL_TREE;
3086 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3087 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3088 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3089 location_t loc;
3090 char buf[BUFSIZE];
3091 unsigned int instanceStart, instanceSize;
3092 unsigned int flags = 0x01; /* RO_META */
3093 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3094 : 0 ;
3096 class_decl = impent->class_decl;
3097 metaclass_decl = impent->meta_decl;
3098 loc = DECL_SOURCE_LOCATION (class_decl);
3100 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3101 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3102 #ifdef OBJCPLUS
3103 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3104 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3105 #endif
3107 /* Generation of data for meta class */
3108 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3109 if (my_super_id)
3111 /* compute reference to root's name. For meta class, "isa" is reference
3112 to root class name. */
3113 tree my_root_id = my_super_id;
3114 tree my_root_int, interface;
3117 my_root_int = lookup_interface (my_root_id);
3119 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3120 my_root_id = CLASS_SUPER_NAME (my_root_int);
3121 else
3122 break;
3124 while (1);
3126 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3127 create extern if not already declared. */
3128 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3129 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3130 root_expr = create_extern_decl (objc_v2_class_template, buf);
3131 root_expr = build_fold_addr_expr (root_expr);
3133 /* Install class `isa' and `super' pointers at runtime. */
3134 interface = lookup_interface (my_super_id);
3135 gcc_assert (interface);
3136 /* Similarly, for OBJC_CLASS_$_<interface>... */
3137 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3138 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3139 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3140 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3141 /* ... and for OBJC_METACLASS_$_<interface>. */
3142 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3143 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3144 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3145 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3147 else
3149 /* root class. */
3150 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3151 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3152 class_superclass_expr = build_int_cst (NULL_TREE, 0);
3153 flags |= 0x02; /* RO_ROOT: it is also a root meta class */
3156 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3158 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3159 protocol_decl = generate_v2_protocol_list (impent->imp_template,
3160 impent->imp_context);
3162 else
3163 protocol_decl = 0;
3165 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3166 class_names);
3168 if (CLASS_CLS_METHODS (impent->imp_context))
3170 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3171 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3172 class_methods =
3173 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3174 buf, meta_clac_meth);
3177 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3179 /* Currently there are no class ivars and generation of class variables for
3180 the root of the inheritance has been removed. It causes multiple defines
3181 if there are two root classes in the link, because each will define its
3182 own identically-named offset variable. */
3184 class_ivars = NULL_TREE;
3185 /* TODO: Add total size of class variables when implemented. */
3186 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3188 /* So now build the META CLASS structs. */
3189 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3191 decl = start_var_decl (objc_v2_class_ro_template,
3192 newabi_append_ro (IDENTIFIER_POINTER
3193 (DECL_NAME (metaclass_decl))));
3195 /* TODO: ivarLayout needs t be built. */
3196 initlist =
3197 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3198 (flags | cls_flags), instanceStart,
3199 instanceSize, ivarLayout,
3200 class_methods, protocol_decl,
3201 class_ivars, NULL_TREE);
3202 /* The ROs sit in the default const section. */
3203 OBJCMETA (decl, objc_meta, meta_base);
3204 finish_var_decl (decl, initlist);
3206 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3207 initlist =
3208 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3209 root_expr,
3210 metaclass_superclass_expr,
3211 build_fold_addr_expr (decl),
3212 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3213 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3214 /* The class section attributes are set when they are created. */
3215 finish_var_decl (metaclass_decl, initlist);
3216 impent->meta_decl = metaclass_decl;
3218 /* So now build the CLASS structs. */
3220 flags = 0x0; /* ... */
3221 if (!my_super_id)
3222 flags |= 0x02; /* RO_ROOT: this is a root class */
3224 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3225 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3227 if (objc2_objc_exception_attr (impent->imp_template))
3228 flags |= 0x20; /* RO_EXCEPTION */
3230 if (CLASS_NST_METHODS (impent->imp_context))
3232 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3233 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3234 inst_methods =
3235 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3236 buf, meta_clai_meth);
3239 /* Sort out the ivars before we try to compute the class sizes. */
3240 if ((chain = CLASS_IVARS (impent->imp_template)))
3242 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3243 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3244 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3245 impent->imp_template);
3248 /* Compute instanceStart */
3249 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3250 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3251 if (my_super_id && field && TREE_CHAIN (field))
3252 field = TREE_CHAIN (field);
3254 firstIvar = field;
3256 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3257 firstIvar = TREE_CHAIN (firstIvar);
3259 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3261 /* Compute instanceSize */
3262 while (field && TREE_CHAIN (field)
3263 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3264 field = TREE_CHAIN (field);
3266 if (field && TREE_CODE (field) == FIELD_DECL)
3267 instanceSize = int_byte_position (field) * BITS_PER_UNIT
3268 + tree_low_cst (DECL_SIZE (field), 0);
3269 else
3270 instanceSize = 0;
3271 instanceSize /= BITS_PER_UNIT;
3273 props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3275 /* If the class has no ivars, instanceStart should be set to the superclass's
3276 instanceSize */
3277 instanceStart =
3278 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3279 : instanceSize;
3281 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3282 decl = start_var_decl (objc_v2_class_ro_template,
3283 newabi_append_ro (IDENTIFIER_POINTER
3284 (DECL_NAME (class_decl))));
3286 initlist =
3287 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3288 (flags | cls_flags), instanceStart,
3289 instanceSize, ivarLayout,
3290 inst_methods, protocol_decl,
3291 inst_ivars, props);
3292 /* The ROs sit in the default const section. */
3293 OBJCMETA (decl, objc_meta, meta_base);
3294 finish_var_decl (decl, initlist);
3296 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3297 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3298 build_fold_addr_expr (metaclass_decl),
3299 class_superclass_expr,
3300 build_fold_addr_expr (decl),
3301 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3302 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3304 /* The class section attributes are set when they are created. */
3305 finish_var_decl (class_decl, initlist);
3306 impent->class_decl = class_decl;
3308 objc_v2_add_to_class_list (class_decl);
3309 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3310 objc_v2_add_to_nonlazy_class_list (class_decl);
3312 if (flags & 0x20) /* RO_EXCEPTION */
3313 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3316 /* This routine outputs the (ivar_reference_offset, offset) tuples. */
3318 static void
3319 build_v2_ivar_offset_ref_table (void)
3321 int count;
3322 ivarref_entry *ref;
3324 if (!ivar_offset_refs || !VEC_length (ivarref_entry, ivar_offset_refs))
3325 return;
3327 FOR_EACH_VEC_ELT (ivarref_entry, ivar_offset_refs, count, ref)
3328 finish_var_decl (ref->decl, ref->offset);
3331 /* static int _OBJC_IMAGE_INFO[2] = { 0, 16 | flags }; */
3333 static void
3334 generate_v2_objc_image_info (void)
3336 tree decl, array_type;
3337 VEC(constructor_elt,gc) *v = NULL;
3338 int flags =
3339 ((flag_replace_objc_classes && imp_count ? 1 : 0)
3340 | (flag_objc_gc ? 2 : 0));
3342 flags |= 16;
3344 array_type = build_sized_array_type (integer_type_node, 2);
3346 decl = start_var_decl (array_type, "_OBJC_ImageInfo");
3348 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
3349 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
3350 /* The Runtime wants this. */
3351 DECL_PRESERVE_P (decl) = 1;
3352 OBJCMETA (decl, objc_meta, meta_info);
3353 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
3356 static void
3357 objc_generate_v2_next_metadata (void)
3359 struct imp_entry *impent;
3361 gcc_assert (!objc_static_instances); /* Not for NeXT */
3363 build_metadata_templates ();
3365 for (impent = imp_list; impent; impent = impent->next)
3367 /* If -gen-decls is present, Dump the @interface of each class.
3368 TODO: Dump the classes in the order they were found, rather than in
3369 reverse order as we are doing now. */
3370 if (flag_gen_declaration)
3371 dump_interface (gen_declaration_file, impent->imp_context);
3373 /* all of the following reference the string pool... */
3374 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3375 generate_v2_class_structs (impent);
3376 else
3377 generate_v2_category (impent);
3380 build_next_selector_translation_table ();
3381 build_v2_message_ref_translation_table ();
3383 /* This will add "Protocol" to the class refs. */
3384 generate_v2_protocols ();
3386 build_v2_classrefs_table ();
3387 build_v2_super_classrefs_table (/*metaclass= */false);
3388 build_v2_super_classrefs_table (/*metaclass= */true);
3390 build_v2_ivar_offset_ref_table ();
3392 build_v2_protocol_list_translation_table ();
3393 build_v2_protocol_list_address_table ();
3395 build_v2_address_table (class_list, "_OBJC_ClassList$",
3396 meta_label_classlist);
3397 build_v2_address_table (category_list, "_OBJC_CategoryList$",
3398 meta_label_categorylist);
3399 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3400 meta_label_nonlazy_classlist);
3401 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3402 meta_label_nonlazy_categorylist);
3404 /* This conveys information on GC usage and zero-link. */
3405 generate_v2_objc_image_info ();
3407 /* Generate catch objects for eh, if any are needed. */
3408 build_v2_eh_catch_objects ();
3410 /* Emit the string table last. */
3411 generate_strings ();
3414 /* NOTE --- Output NeXT V2 Exceptions --- */
3416 static GTY(()) tree objc_v2_ehtype_template;
3417 static GTY(()) tree next_v2_ehvtable_decl;
3418 static GTY(()) tree next_v2_EHTYPE_id_decl;
3420 static void
3421 build_v2_ehtype_template (void)
3423 tree decls, *chain = NULL;
3424 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3426 /* void *_objc_ehtype_vtable; */
3427 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3429 /* const char *className; */
3430 add_field_decl (string_type_node, "className", &chain);
3432 /* struct class_t *const cls; */
3433 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3435 objc_finish_struct (objc_v2_ehtype_template, decls);
3438 /* Template for the Objective-C family typeinfo type for ABI=2.
3439 This starts off the same as the gxx/cxx eh typeinfo.
3441 struct _objc_ehtype_t {
3442 void *_objc_ehtype_vtable_ptr; - as per c++
3443 const char *className; - as per c++
3444 struct class_t *const cls;
3448 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3451 static tree
3452 objc2_build_ehtype_initializer (tree name, tree cls)
3454 VEC(constructor_elt,gc) *initlist = NULL;
3455 tree addr, offs;
3457 /* This is done the same way as c++, missing the two first entries in the
3458 parent vtable. NOTE: there is a fix-me in the Apple/NeXT runtime source
3459 about this so, perhaps, this will change at some point. */
3460 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3461 if (!next_v2_ehvtable_decl)
3463 next_v2_ehvtable_decl =
3464 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3465 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3466 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3467 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3469 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3470 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3471 addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, offs);
3473 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3475 /* className */
3476 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3478 /* cls */
3479 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3481 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3484 static tree
3485 build_ehtype (tree name, const char *eh_name, bool weak)
3487 tree name_expr, class_name_expr, ehtype_decl, inits;
3489 name_expr = add_objc_string (name, class_names);
3490 /* Extern ref. for the class. ??? maybe we can look this up somewhere. */
3491 class_name_expr =
3492 create_extern_decl (objc_v2_class_template,
3493 objc_build_internal_classname (name, false));
3494 class_name_expr = build_fold_addr_expr (class_name_expr);
3495 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3496 if (weak)
3497 DECL_WEAK (ehtype_decl) = 1;
3498 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3499 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3500 finish_var_decl (ehtype_decl, inits);
3501 return ehtype_decl;
3504 /* This routine returns TRUE if CLS or any of its super classes has
3505 __attribute__ ((objc_exception)).
3508 static bool
3509 objc2_objc_exception_attr (tree cls)
3511 while (cls)
3513 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3514 return true;
3515 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3518 return false;
3521 static bool
3522 is_implemented (tree name)
3524 struct imp_entry *t;
3525 for (t = imp_list; t; t = t->next)
3526 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3527 && CLASS_NAME (t->imp_template) == name)
3528 return true;
3530 return false;
3533 /* We will build catch objects:
3534 for any type implemented here.
3535 for any type used in a catch that has no exception attribute. */
3536 static void build_v2_eh_catch_objects (void)
3538 int count=0;
3539 ident_data_tuple *ref;
3541 if (!ehtype_list || !VEC_length (ident_data_tuple, ehtype_list))
3542 return;
3544 FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3546 char buf[BUFSIZE];
3547 bool impl = is_implemented (ref->ident);
3548 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3549 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3550 if (!impl && excpt)
3551 /* The User says this class has a catcher already. */
3552 ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3553 else
3554 /* Create a catcher, weak if it wasn't marked. */
3555 ref->data = build_ehtype (ref->ident, buf, !excpt);
3559 static tree
3560 lookup_ehtype_ref (tree id)
3562 int count=0;
3563 ident_data_tuple *ref;
3565 if (!ehtype_list || !VEC_length (ident_data_tuple, ehtype_list))
3566 return NULL_TREE;
3568 FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
3569 if (ref->ident == id)
3570 return ref->data;
3571 return NULL_TREE;
3574 /* This hook, called via lang_eh_runtime_type, generates a runtime object
3575 which is either the address of the 'OBJC_EHTYPE_$_class' object or
3576 address of external OBJC_EHTYPE_id object.
3578 static tree
3579 next_runtime_02_eh_type (tree type)
3581 tree t;
3583 if (type == error_mark_node
3584 /*|| errorcount || sorrycount*/)
3585 goto err_mark_in;
3587 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3589 if (!next_v2_EHTYPE_id_decl)
3591 /* This is provided by the Apple/NeXT libobjc.dylib so we need
3592 only to reference it. */
3593 next_v2_EHTYPE_id_decl =
3594 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3595 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3596 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3597 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3599 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3602 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3604 #ifdef OBJCPLUS
3605 /* This routine is also called for c++'s catch clause; in which case,
3606 we use c++'s typeinfo decl. */
3607 return build_eh_type_type (type);
3608 #else
3609 error ("non-objective-c type '%T' cannot be caught", type);
3610 goto err_mark_in;
3611 #endif
3613 else
3614 t = OBJC_TYPE_NAME (TREE_TYPE (type));
3616 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3617 t = lookup_ehtype_ref (t);
3618 if (!t)
3619 goto err_mark_in;
3621 return build_fold_addr_expr (t);
3623 err_mark_in:
3624 return error_mark_node;
3627 static GTY(()) tree objc_eh_personality_decl;
3629 static tree
3630 objc_eh_personality (void)
3632 if (!objc_eh_personality_decl)
3633 objc_eh_personality_decl = build_personality_function ("objc");
3634 return objc_eh_personality_decl;
3637 /* NOTE --- interfaces --- */
3639 static tree
3640 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3642 tree t;
3643 if (rethrown)
3644 /* We have a separate re-throw entry. */
3645 t = build_function_call_vec (loc, objc_rethrow_exception_decl, NULL, NULL);
3646 else
3648 /* Throw like the others .. */
3649 VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
3650 VEC_quick_push (tree, parms, throw_expr);
3651 t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
3652 VEC_free (tree, gc, parms);
3654 return add_stmt (t);
3657 /* Build __builtin_eh_pointer. */
3659 static tree
3660 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3662 tree t;
3663 t = built_in_decls[BUILT_IN_EH_POINTER];
3664 t = build_call_expr (t, 1, integer_zero_node);
3665 return fold_convert (objc_object_type, t);
3668 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3669 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3671 tree t;
3673 /* Record the data for the catch in the try context so that we can
3674 finalize it later. Ellipsis is signalled by a NULL entry. */
3675 if (ellipsis)
3676 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3677 else
3678 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3679 (*cur_try_context)->current_catch = t;
3681 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3682 t = objc_build_exc_ptr (cur_try_context);
3683 t = convert (TREE_TYPE (decl), t);
3684 /* TODO location stuff. */
3685 if (type && type != error_mark_node)
3687 t = build1(NOP_EXPR, ptr_type_node, t);
3688 t = build_function_call (input_location, objc2_begin_catch_decl,
3689 tree_cons (NULL_TREE, t, NULL_TREE));
3691 /* We might want to build a catch object for this (if it's not id). */
3692 if (POINTER_TYPE_P (type)
3693 && !objc_is_object_id (TREE_TYPE (type))
3694 && TYPED_OBJECT (TREE_TYPE (type)))
3695 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3697 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3700 /* try { catch-body } finally { objc_end_catch (); } */
3701 static void
3702 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3704 struct objc_try_context *ct;
3705 tree try_exp, func, *l, t ;
3706 location_t loc = (*cur_try_context)->try_locus;
3708 if (!curr_catch || curr_catch == error_mark_node)
3709 return;
3711 t = CATCH_BODY (curr_catch);
3712 if (TREE_CODE (t) == BIND_EXPR)
3714 /* usual case of @catch (objc-expr). */
3715 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3716 BIND_EXPR_BODY (t) = NULL_TREE;
3717 l = &BIND_EXPR_BODY (t);
3719 else
3721 /* NULL entry, @catch (...) */
3722 objc_begin_try_stmt (loc, t);
3723 CATCH_BODY (curr_catch) = NULL_TREE;
3724 l = &CATCH_BODY (curr_catch);
3727 /* Pick up the new context we made in begin_try above.. */
3728 ct = *cur_try_context;
3729 func = build_function_call_vec (loc, objc2_end_catch_decl, NULL, NULL);
3730 append_to_statement_list (func, &ct->finally_body);
3731 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3732 *cur_try_context = ct->outer;
3733 free (ct);
3734 append_to_statement_list (try_exp, l);
3735 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3738 static tree
3739 finish_try_stmt (struct objc_try_context **cur_try_context)
3741 struct objc_try_context *c = *cur_try_context;
3742 tree stmt = c->try_body;
3743 if (c->catch_list)
3744 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3745 if (c->finally_body)
3746 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3747 return stmt;
3750 #include "gt-objc-objc-next-runtime-abi-02.h"