1 /* Next Runtime (ABI-2) private.
2 Copyright (C) 2011-2013 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)
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
25 This version is intended to match (logically) the output of Apple's
30 #include "coretypes.h"
33 #include "stringpool.h"
36 #include "cp/cp-tree.h"
41 #include "langhooks.h"
42 #include "c-family/c-objc.h"
45 /* When building Objective-C++, we are not linking against the C front-end
46 and so need to replicate the C tree-construction functions in some way. */
48 #define OBJCP_REMAP_FUNCTIONS
49 #include "objcp-decl.h"
54 #include "tree-iterator.h"
56 #include "objc-runtime-hooks.h"
57 #include "objc-runtime-shared-support.h"
58 #include "objc-encoding.h"
60 /* ABI 2 Private definitions. */
61 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
63 #define TAG_GETCLASS "objc_getClass"
64 #define TAG_GETMETACLASS "objc_getMetaClass"
66 #define TAG_MSGSEND "objc_msgSend"
67 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
68 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
69 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
71 #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
72 #define TAG_V2_EH_TYPE "objc_ehtype_t"
74 #define UTAG_V2_CLASS "_class_t"
75 #define UTAG_V2_CLASS_RO "_class_ro_t"
76 #define UTAG_V2_PROTOCOL "_protocol_t"
77 #define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
79 #define UTAG_V2_EH_TYPE "_objc_ehtype_t"
81 #define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
83 enum objc_v2_tree_index
91 OCTI_V2_IVAR_LIST_TEMPL
,
92 OCTI_V2_MESSAGE_REF_TEMPL
,
93 OCTI_V2_SUPER_MESSAGE_REF_TEMPL
,
95 OCTI_V2_MESSAGE_SELECTOR_TYPE
,
96 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE
,
98 OCTI_V2_SUPER_IMP_TYPE
,
103 OCTI_V2_PROPERTY_TEMPL
,
106 OCTI_V2_UMSG_FIXUP_DECL
,
107 OCTI_V2_UMSG_STRET_FIXUP_DECL
,
108 OCTI_V2_UMSG_ID_FIXUP_DECL
,
109 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL
,
110 OCTI_V2_UMSG_SUPER2_FIXUP_DECL
,
111 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL
,
113 /* Exceptions - related. */
114 OCTI_V2_BEGIN_CATCH_DECL
,
115 OCTI_V2_END_CATCH_DECL
,
116 OCTI_V2_RETHROW_DECL
,
121 #define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
122 #define objc_v2_class_ro_template \
123 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
124 #define objc_v2_category_template \
125 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
126 #define objc_v2_protocol_template \
127 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
129 /* struct message_ref_t */
130 #define objc_v2_message_ref_template \
131 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
133 #define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
135 /* struct super_message_ref_t */
136 #define objc_v2_super_message_ref_template \
137 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
139 /* struct message_ref_t* */
140 #define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
141 /* struct super_super_message_ref_t */
142 #define objc_v2_super_selector_type \
143 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
144 #define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
145 #define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
147 #define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
148 #define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
150 #define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
151 #define objc_v2_property_template \
152 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
156 /* objc_msgSend_fixup_rtp */
157 #define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
158 /* objc_msgSend_stret_fixup_rtp */
159 #define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
160 /* objc_msgSendId_fixup_rtp */
161 #define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
162 /* objc_msgSendId_stret_fixup_rtp */
163 #define umsg_id_stret_fixup_decl \
164 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
165 /* objc_msgSendSuper2_fixup_rtp */
166 #define umsg_id_super2_fixup_decl \
167 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
168 /* objc_msgSendSuper2_stret_fixup_rtp */
169 #define umsg_id_super2_stret_fixup_decl \
170 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
172 #define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
173 #define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
174 #define objc_rethrow_exception_decl \
175 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
177 /* rt_trees identifiers - shared between NeXT implementations. These allow
178 the FE to tag meta-data in a manner that survives LTO and can be used when
179 the runtime requires that certain meta-data items appear in particular
182 #include "objc-next-metadata-tags.h"
183 extern GTY(()) tree objc_rt_trees
[OCTI_RT_META_MAX
];
185 /* The OCTI_V2_... enumeration itself is in above. */
186 static GTY(()) tree objc_v2_global_trees
[OCTI_V2_MAX
];
188 static void next_runtime_02_initialize (void);
190 static void build_v2_message_ref_templates (void);
191 static void build_v2_class_templates (void);
192 static void build_v2_super_template (void);
193 static void build_v2_category_template (void);
194 static void build_v2_protocol_template (void);
196 static tree
next_runtime_abi_02_super_superclassfield_id (void);
198 static tree
next_runtime_abi_02_class_decl (tree
);
199 static tree
next_runtime_abi_02_metaclass_decl (tree
);
200 static tree
next_runtime_abi_02_category_decl (tree
);
201 static tree
next_runtime_abi_02_protocol_decl (tree
);
202 static tree
next_runtime_abi_02_string_decl (tree
, const char *, string_section
);
204 static tree
next_runtime_abi_02_get_class_reference (tree
);
205 static tree
next_runtime_abi_02_build_selector_reference (location_t
, tree
, tree
);
206 static tree
next_runtime_abi_02_get_protocol_reference (location_t
, tree
);
207 static tree
next_runtime_abi_02_build_ivar_ref (location_t
, tree
, tree
);
208 static tree
next_runtime_abi_02_get_class_super_ref (location_t
, struct imp_entry
*, bool);
209 static tree
next_runtime_abi_02_get_category_super_ref (location_t
, struct imp_entry
*, bool);
211 static tree
next_runtime_abi_02_receiver_is_class_object (tree
);
212 static void next_runtime_abi_02_get_arg_type_list_base (vec
<tree
, va_gc
> **,
214 static tree
next_runtime_abi_02_build_objc_method_call (location_t
, tree
, tree
,
215 tree
, tree
, tree
, int);
216 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
217 static tree
next_runtime_abi_02_build_const_string_constructor (location_t
, tree
, int);
219 static tree
create_extern_decl (tree
, const char *);
221 static void objc_generate_v2_next_metadata (void);
222 static bool objc2_objc_exception_attr (tree
);
224 /* void build_v2_protocol_reference (tree);*/
225 static void build_v2_ehtype_template (void);
226 static void build_v2_eh_catch_objects (void);
227 static tree
next_runtime_02_eh_type (tree
);
228 static tree
objc_eh_personality (void);
229 static tree
build_throw_stmt (location_t
, tree
, bool);
230 static tree
objc_build_exc_ptr (struct objc_try_context
**);
231 static tree
begin_catch (struct objc_try_context
**, tree
, tree
, tree
, bool);
232 static void finish_catch (struct objc_try_context
**, tree
);
233 static tree
finish_try_stmt (struct objc_try_context
**);
235 /* TODO: Use an objc-map. */
236 static GTY ((length ("SIZEHASHTABLE"))) hash
*extern_names
;
239 objc_next_runtime_abi_02_init (objc_runtime_hooks
*rthooks
)
241 extern_names
= ggc_alloc_cleared_vec_hash (SIZEHASHTABLE
);
243 if (flag_objc_exceptions
&& flag_objc_sjlj_exceptions
)
245 inform (UNKNOWN_LOCATION
, "%<-fobjc-sjlj-exceptions%> is ignored for "
246 "%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
247 flag_objc_sjlj_exceptions
= 0;
250 rthooks
->initialize
= next_runtime_02_initialize
;
251 rthooks
->default_constant_string_class_name
= DEF_CONSTANT_STRING_CLASS_NAME
;
252 rthooks
->tag_getclass
= TAG_GETCLASS
;
253 rthooks
->super_superclassfield_ident
= next_runtime_abi_02_super_superclassfield_id
;
255 rthooks
->class_decl
= next_runtime_abi_02_class_decl
;
256 rthooks
->metaclass_decl
= next_runtime_abi_02_metaclass_decl
;
257 rthooks
->category_decl
= next_runtime_abi_02_category_decl
;
258 rthooks
->protocol_decl
= next_runtime_abi_02_protocol_decl
;
259 rthooks
->string_decl
= next_runtime_abi_02_string_decl
;
261 rthooks
->get_class_reference
= next_runtime_abi_02_get_class_reference
;
262 rthooks
->build_selector_reference
= next_runtime_abi_02_build_selector_reference
;
263 rthooks
->get_protocol_reference
= next_runtime_abi_02_get_protocol_reference
;
264 rthooks
->build_ivar_reference
= next_runtime_abi_02_build_ivar_ref
;
265 rthooks
->get_class_super_ref
= next_runtime_abi_02_get_class_super_ref
;
266 rthooks
->get_category_super_ref
= next_runtime_abi_02_get_category_super_ref
;
268 rthooks
->receiver_is_class_object
= next_runtime_abi_02_receiver_is_class_object
;
269 rthooks
->get_arg_type_list_base
= next_runtime_abi_02_get_arg_type_list_base
;
270 rthooks
->build_objc_method_call
= next_runtime_abi_02_build_objc_method_call
;
272 rthooks
->setup_const_string_class_decl
=
273 next_runtime_abi_02_setup_const_string_class_decl
;
274 rthooks
->build_const_string_constructor
=
275 next_runtime_abi_02_build_const_string_constructor
;
277 rthooks
->build_throw_stmt
= build_throw_stmt
;
278 rthooks
->build_exc_ptr
= objc_build_exc_ptr
;
279 rthooks
->begin_catch
= begin_catch
;
280 rthooks
->finish_catch
= finish_catch
;
281 rthooks
->finish_try_stmt
= finish_try_stmt
;
283 rthooks
->generate_metadata
= objc_generate_v2_next_metadata
;
287 /* We need a way to convey what kind of meta-data are represented by a given
288 variable, since each type is expected (by the runtime) to be found in a
289 specific named section. The solution must be usable with LTO.
291 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
292 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
293 identification attributes in the front end. The back-end may choose to act
294 on these as it requires. */
297 next_runtime_abi_02_init_metadata_attributes (void)
300 objc_meta
= get_identifier ("OBJC2META");
303 meta_base
= get_identifier ("V2_BASE");
305 meta_class
= get_identifier ("G2_CLAS");
306 meta_metaclass
= get_identifier ("G2_META");
308 meta_protocol
= meta_base
;
311 meta_clai_vars
= meta_base
;
317 meta_proto_cls_meth
=
318 meta_proto_nst_meth
= meta_base
;
321 meta_catg_prot
= meta_base
;
323 meta_sel_refs
= get_identifier ("V2_SRFS");
328 meta_prop_name_attr
= get_identifier ("V2_STRG");
330 meta_mref
= get_identifier ("V2_MREF");
331 meta_class_ref
= get_identifier ("V2_CLRF");
332 meta_superclass_ref
= get_identifier ("V2_SURF");
334 meta_label_classlist
= get_identifier ("V2_CLAB");
335 meta_label_nonlazy_classlist
= get_identifier ("V2_NLCL");
336 meta_label_categorylist
= get_identifier ("V2_CALA");
337 meta_label_nonlazy_categorylist
= get_identifier ("V2_NLCA");
339 meta_label_protocollist
= get_identifier ("V2_PLST");
340 meta_proto_ref
= get_identifier ("V2_PRFS");
342 meta_info
= get_identifier ("V2_INFO");
344 meta_ehtype
= get_identifier ("V2_EHTY");
346 meta_const_str
= get_identifier ("V2_CSTR");
349 static void next_runtime_02_initialize (void)
353 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
355 if (!global_options_set
.x_flag_objc_call_cxx_cdtors
)
356 global_options
.x_flag_objc_call_cxx_cdtors
= 1;
359 /* Set up attributes to be attached to the meta-data so that they
360 will be placed in the correct sections. */
361 next_runtime_abi_02_init_metadata_attributes ();
363 /* `struct objc_selector *' */
364 objc_selector_type
= build_pointer_type (xref_tag (RECORD_TYPE
,
365 get_identifier (TAG_SELECTOR
)));
367 /* IMP : id (*) (id, _message_ref_t*, ...)
368 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
369 objc_v2_selector_type. */
370 build_v2_message_ref_templates ();
372 objc_v2_ivar_list_ptr
=
373 build_pointer_type (xref_tag (RECORD_TYPE
,
374 get_identifier ("_ivar_list_t")));
377 build_pointer_type (xref_tag (RECORD_TYPE
,
378 get_identifier ("_prop_list_t")));
380 build_v2_class_templates ();
381 build_v2_super_template ();
382 build_v2_protocol_template ();
383 build_v2_category_template ();
385 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
386 type
= build_varargs_function_type_list (objc_object_type
,
388 objc_v2_selector_type
,
390 umsg_fixup_decl
= add_builtin_function ("objc_msgSend_fixup",
391 type
, 0, NOT_BUILT_IN
,
393 TREE_NOTHROW (umsg_fixup_decl
) = 0;
395 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
396 umsg_stret_fixup_decl
= add_builtin_function ("objc_msgSend_stret_fixup",
397 type
, 0, NOT_BUILT_IN
,
399 TREE_NOTHROW (umsg_stret_fixup_decl
) = 0;
401 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
402 umsg_id_fixup_decl
= add_builtin_function ("objc_msgSendId_fixup",
403 type
, 0, NOT_BUILT_IN
,
405 TREE_NOTHROW (umsg_id_fixup_decl
) = 0;
407 /* id objc_msgSendId_stret_fixup_rtp
408 (id, struct message_ref_t*, ...); */
409 umsg_id_stret_fixup_decl
= add_builtin_function ("objc_msgSendId_stret_fixup",
410 type
, 0, NOT_BUILT_IN
,
412 TREE_NOTHROW (umsg_id_stret_fixup_decl
) = 0;
414 /* id objc_msgSendSuper2_fixup_rtp
415 (struct objc_super *, struct message_ref_t*, ...); */
416 type
= build_varargs_function_type_list (objc_object_type
,
418 objc_v2_super_selector_type
,
420 umsg_id_super2_fixup_decl
= add_builtin_function ("objc_msgSendSuper2_fixup",
421 type
, 0, NOT_BUILT_IN
,
423 TREE_NOTHROW (umsg_id_super2_fixup_decl
) = 0;
425 /* id objc_msgSendSuper2_stret_fixup_rtp
426 (struct objc_super *, struct message_ref_t*, ...); */
427 umsg_id_super2_stret_fixup_decl
=
428 add_builtin_function ("objc_msgSendSuper2_stret_fixup",
429 type
, 0, NOT_BUILT_IN
,
431 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl
) = 0;
433 /* Present in the library, but unused by the FE. */
434 /* Protocol *objc_getProtocol (const char *)
435 type = build_function_type_list (objc_protocol_type,
436 const_string_type_node,
438 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
439 type, 0, NOT_BUILT_IN,
441 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
443 UOBJC_V2_CACHE_decl
= create_extern_decl (ptr_type_node
,
444 "_objc_empty_cache");
446 UOBJC_V2_VTABLE_decl
= create_extern_decl (objc_v2_imp_type
,
447 "_objc_empty_vtable");
449 /* id objc_getClass (const char *); */
450 type
= build_function_type_list (objc_object_type
,
451 const_string_type_node
,
453 objc_get_class_decl
= add_builtin_function (TAG_GETCLASS
,
454 type
, 0, NOT_BUILT_IN
,
457 /* id objc_getMetaClass (const char *); */
458 objc_get_meta_class_decl
= add_builtin_function (TAG_GETMETACLASS
,
459 type
, 0, NOT_BUILT_IN
,
462 /* This is the type of all of the following functions
463 objc_copyStruct(). */
464 type
= build_function_type_list (void_type_node
,
471 /* Declare the following function:
473 objc_copyStruct (void *destination, const void *source,
474 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
475 objc_copyStruct_decl
= add_builtin_function ("objc_copyStruct",
476 type
, 0, NOT_BUILT_IN
,
478 TREE_NOTHROW (objc_copyStruct_decl
) = 0;
479 objc_getPropertyStruct_decl
= NULL_TREE
;
480 objc_setPropertyStruct_decl
= NULL_TREE
;
482 gcc_assert (!flag_objc_sjlj_exceptions
);
484 /* Although we warn that fobjc-exceptions is required for exceptions
485 code, we carry on and create it anyway. */
487 /* This can be required, even when exceptions code is not present,
488 when an __attribute__((objc_exception)) is applied to a
490 build_v2_ehtype_template ();
492 /* void * objc_begin_catch (void *) */
493 type
= build_function_type_list (ptr_type_node
,
494 ptr_type_node
, NULL_TREE
);
496 objc2_begin_catch_decl
= add_builtin_function ("objc_begin_catch",
497 type
, 0, NOT_BUILT_IN
,
499 TREE_NOTHROW (objc2_begin_catch_decl
) = 0;
501 /* void objc_end_catch () */
502 type
= build_function_type_list (void_type_node
, NULL_TREE
);
503 objc2_end_catch_decl
= add_builtin_function ("objc_end_catch",
504 type
, 0, NOT_BUILT_IN
,
506 TREE_NOTHROW (objc2_end_catch_decl
) = 0;
508 /* void objc_exception_rethrow (void) */
509 objc_rethrow_exception_decl
=
510 add_builtin_function ("objc_exception_rethrow",
511 type
, 0, NOT_BUILT_IN
,
513 TREE_NOTHROW (objc_rethrow_exception_decl
) = 0;
514 using_eh_for_cleanups ();
515 lang_hooks
.eh_runtime_type
= next_runtime_02_eh_type
;
516 lang_hooks
.eh_personality
= objc_eh_personality
;
519 /* NOTE --- templates --- */
521 /* Set 'objc_v2_message_ref_template' to the data type node for
522 'struct _message_ref_t'. This needs to be done just once per
523 compilation. Also Set 'objc_v2_super_message_ref_template' to data
524 type node for 'struct _super_message_ref_t'. */
526 /* struct _message_ref_t
531 where IMP is: id (*) (id, _message_ref_t*, ...)
534 /* struct _super_message_ref_t
539 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
543 build_v2_message_ref_templates (void)
545 tree ptr_message_ref_t
;
546 tree decls
, *chain
= NULL
;
548 /* struct _message_ref_t {...} */
549 objc_v2_message_ref_template
=
550 objc_start_struct (get_identifier ("_message_ref_t"));
554 build_pointer_type (xref_tag (RECORD_TYPE
,
555 get_identifier ("_message_ref_t")));
558 build_pointer_type (build_function_type_list
564 decls
= add_field_decl (objc_v2_imp_type
, "messenger", &chain
);
567 add_field_decl (objc_selector_type
, "name", &chain
);
569 objc_finish_struct (objc_v2_message_ref_template
, decls
);
571 objc_v2_selector_type
= build_pointer_type (objc_v2_message_ref_template
);
574 /* struct _super_message_ref_t {...} */
575 objc_v2_super_message_ref_template
=
576 objc_start_struct (get_identifier ("_super_message_ref_t"));
578 /* SUPER_IMP messenger; */
579 ptr_message_ref_t
= build_pointer_type
580 (xref_tag (RECORD_TYPE
,
581 get_identifier ("_super_message_ref_t")));
583 objc_v2_super_imp_type
=
584 build_pointer_type (build_function_type_list
590 add_field_decl (objc_v2_super_imp_type
, "messenger", &chain
);
593 add_field_decl (objc_selector_type
, "name", &chain
);
595 objc_finish_struct (objc_v2_super_message_ref_template
, decls
);
596 objc_v2_super_selector_type
=
597 build_pointer_type (objc_v2_super_message_ref_template
);
600 /* Build following types which represent each class implementation.
604 uint32_t const flags;
605 uint32_t const instanceStart;
606 uint32_t const instanceSize;
608 uint32_t const reserved;
610 const uint8_t * const ivarLayout;
611 const char *const name;
612 const struct method_list_t * const baseMethods;
613 const struct objc_protocol_list *const baseProtocols;
614 const struct ivar_list_t *const ivars;
615 const uint8_t * const weakIvarLayout;
616 const struct _prop_list_t * const properties;
622 struct class_t *superclass;
626 ...When this is active - it will point to a rw version, but
627 when we build the meta-data we point it to the ro...
628 struct class_ro_t *data;
634 build_v2_class_templates (void)
637 tree decls
, *chain
= NULL
;
639 /* struct class_ro_t {...} */
640 objc_v2_class_ro_template
=
641 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO
));
643 /* uint32_t const flags; */
644 decls
= add_field_decl (integer_type_node
, "flags", &chain
);
646 /* uint32_t const instanceStart; */
647 add_field_decl (integer_type_node
, "instanceStart", &chain
);
649 /* uint32_t const instanceSize; */
650 add_field_decl (integer_type_node
, "instanceSize", &chain
);
652 /* This ABI is currently only used on m64 NeXT. We always
653 explicitly declare the alignment padding. */
654 /* uint32_t const reserved; */
655 add_field_decl (integer_type_node
, "reserved", &chain
);
657 /* const uint8_t * const ivarLayout; */
658 cnst_strg_type
= build_pointer_type (unsigned_char_type_node
);
659 add_field_decl (cnst_strg_type
, "ivarLayout", &chain
);
661 /* const char *const name; */
662 add_field_decl (string_type_node
, "name", &chain
);
664 /* const struct method_list_t * const baseMethods; */
665 add_field_decl (objc_method_list_ptr
, "baseMethods", &chain
);
667 /* const struct objc_protocol_list *const baseProtocols; */
668 add_field_decl (build_pointer_type
669 (xref_tag (RECORD_TYPE
,
670 get_identifier (UTAG_V2_PROTOCOL_LIST
))),
671 "baseProtocols", &chain
);
673 /* const struct ivar_list_t *const ivars; */
674 add_field_decl (objc_v2_ivar_list_ptr
, "ivars", &chain
);
676 /* const uint8_t * const weakIvarLayout; */
677 add_field_decl (cnst_strg_type
, "weakIvarLayout", &chain
);
679 /* struct _prop_list_t * baseProperties; */
680 add_field_decl (objc_prop_list_ptr
, "baseProperties", &chain
);
682 objc_finish_struct (objc_v2_class_ro_template
, decls
);
685 /* struct class_t {...} */
686 objc_v2_class_template
=
687 objc_start_struct (get_identifier (UTAG_V2_CLASS
));
689 /* struct class_t *isa; */
690 decls
= add_field_decl (build_pointer_type (objc_v2_class_template
),
693 /* struct class_t * const superclass; */
694 add_field_decl (build_pointer_type (objc_v2_class_template
),
695 "superclass", &chain
);
698 add_field_decl (build_pointer_type (void_type_node
), "cache", &chain
);
701 add_field_decl (build_pointer_type (objc_v2_imp_type
), "vtable", &chain
);
703 /* struct class_ro_t *ro; */
704 add_field_decl (build_pointer_type (objc_v2_class_ro_template
), "ro", &chain
);
706 objc_finish_struct (objc_v2_class_template
, decls
);
709 /* struct _objc_super
711 struct _objc_object *self;
715 build_v2_super_template (void)
717 tree decls
, *chain
= NULL
;
719 objc_super_template
= objc_start_struct (get_identifier (UTAG_SUPER
));
721 /* struct _objc_object *self; */
722 decls
= add_field_decl (objc_object_type
, "self", &chain
);
725 add_field_decl (objc_class_type
, "cls", &chain
);
727 objc_finish_struct (objc_super_template
, decls
);
733 const char * const protocol_name;
734 const struct protocol_list_t * const protocol_list;
735 const struct method_list_t * const instance_methods;
736 const struct method_list_t * const class_methods;
737 const struct method_list_t * optionalInstanceMethods;
738 const struct method_list_t * optionalClassMethod
739 const struct _prop_list_t * const properties;
741 const uint32_t flags;
745 build_v2_protocol_template (void)
747 tree decls
, *chain
= NULL
;
749 objc_v2_protocol_template
=
750 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL
));
753 decls
= add_field_decl (objc_object_type
, "isa", &chain
);
755 /* char *protocol_name; */
756 add_field_decl (string_type_node
, "protocol_name", &chain
);
758 /* const struct protocol_list_t * const protocol_list; */
759 add_field_decl (build_pointer_type (objc_v2_protocol_template
),
760 "protocol_list", &chain
);
762 /* const struct method_list_t * const instance_methods; */
763 add_field_decl (objc_method_proto_list_ptr
, "instance_methods", &chain
);
765 /* const struct method_list_t * const class_methods; */
766 add_field_decl (objc_method_proto_list_ptr
, "class_methods", &chain
);
768 /* const struct method_list_t * optionalInstanceMethods; */
769 add_field_decl (objc_method_proto_list_ptr
, "optionalInstanceMethods", &chain
);
771 /* const struct method_list_t * optionalClassMethods; */
772 add_field_decl (objc_method_proto_list_ptr
, "optionalClassMethods", &chain
);
774 /* struct _prop_list_t * properties; */
775 add_field_decl (objc_prop_list_ptr
, "properties", &chain
);
777 /* const uint32_t size; */
778 add_field_decl (integer_type_node
, "size", &chain
);
780 /* const uint32_t flags; */
781 add_field_decl (integer_type_node
, "flags", &chain
);
783 objc_finish_struct (objc_v2_protocol_template
, decls
);
786 /* Build type for a category:
789 const char * const name;
790 struct class_t *const cls;
791 const struct method_list_t * const instance_methods;
792 const struct method_list_t * const class_methods;
793 const struct protocol_list_t * const protocols;
794 const struct _prop_list_t * const properties;
799 build_v2_category_template (void)
801 tree decls
, *chain
= NULL
;
803 objc_v2_category_template
=
804 objc_start_struct (get_identifier ("_category_t"));
807 decls
= add_field_decl (string_type_node
, "name", &chain
);
809 /* struct class_t *const cls; */
810 add_field_decl (build_pointer_type (objc_v2_class_template
), "cls", &chain
);
812 /* struct method_list_t *instance_methods; */
813 add_field_decl (objc_method_list_ptr
, "instance_methods", &chain
);
815 /* struct method_list_t *class_methods; */
816 add_field_decl (objc_method_list_ptr
, "class_methods", &chain
);
818 /* struct protocol_list_t *protocol_list; */
819 add_field_decl (build_pointer_type (objc_v2_protocol_template
),
820 "protocol_list", &chain
);
822 /* struct _prop_list_t * properties; */
823 add_field_decl (objc_prop_list_ptr
, "properties", &chain
);
825 objc_finish_struct (objc_v2_category_template
, decls
);
828 /* NOTE --- Decls, Identifiers, Names etc. --- */
830 /* This routine is given a name and returns a matching extern variable
834 hash_name_lookup (hash
*hashlist
, tree name
)
838 target
= hashlist
[IDENTIFIER_HASH_VALUE (name
) % SIZEHASHTABLE
];
842 if (name
== DECL_NAME (target
->key
))
845 target
= target
->next
;
850 /* This routine is given an extern variable and enters it in its hash
851 table. Note that hashing is done on its inner IDENTIFIER_NODE
855 hash_name_enter (hash
*hashlist
, tree id
)
858 int slot
= IDENTIFIER_HASH_VALUE (DECL_NAME (id
)) % SIZEHASHTABLE
;
860 obj
= ggc_alloc_hashed_entry ();
862 obj
->next
= hashlist
[slot
];
865 hashlist
[slot
] = obj
; /* append to front */
868 /* Create a declaration "extern <type> <name>;"
869 The var will need to be finalized (e.g. by calling finish_var_decl()). */
872 create_extern_decl (tree type
, const char *name
)
874 tree id
= get_identifier (name
);
875 tree var
= hash_name_lookup (extern_names
, id
);
879 var
= start_var_decl (type
, name
);
880 TREE_STATIC (var
) = 0;
881 DECL_EXTERNAL (var
) = 1;
882 TREE_PUBLIC (var
) = 1;
883 hash_name_enter (extern_names
, var
);
887 /* Create a globally visible definition for variable NAME of a given TYPE. The
888 finish_var_decl() routine will need to be called on it afterwards. */
891 create_global_decl (tree type
, const char *name
)
893 tree id
= get_identifier (name
);
894 tree var
= hash_name_lookup (extern_names
, id
);
897 DECL_EXTERNAL (var
) = 0;
898 TREE_STATIC (var
) = 1;
902 var
= start_var_decl (type
, name
);
903 hash_name_enter (extern_names
, var
);
905 TREE_PUBLIC (var
) = 1;
909 /* Create a symbol with __attribute__ ((visibility ("hidden")))
910 attribute (private extern). */
913 create_hidden_decl (tree type
, const char *name
)
915 tree decl
= create_global_decl (type
, name
);
916 DECL_VISIBILITY (decl
) = VISIBILITY_HIDDEN
;
917 DECL_VISIBILITY_SPECIFIED (decl
) = 1;
921 /* Irritatingly, we have a different superclass field name for ABI=2. */
922 /* PS/TODO: The field name does not matter, it is only used internally
923 by the compiler. We can rename it to whatever we want. ;-) */
926 next_runtime_abi_02_super_superclassfield_id (void)
928 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
929 most look it once at startup then always return it. */
930 if (!super_superclassfield_id
)
931 super_superclassfield_id
= get_identifier ("cls");
932 return super_superclassfield_id
;
936 next_runtime_abi_02_class_decl (tree klass
)
940 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s",
941 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
942 /* ObjC2 classes are extern visible. */
943 decl
= create_global_decl (objc_v2_class_template
, buf
);
944 OBJCMETA (decl
, objc_meta
, meta_class
);
949 next_runtime_abi_02_metaclass_decl (tree klass
)
953 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
954 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
955 /* ObjC2 classes are extern visible. */
956 decl
= create_global_decl (objc_v2_class_template
, buf
);
957 OBJCMETA (decl
, objc_meta
, meta_metaclass
);
962 next_runtime_abi_02_category_decl (tree klass
)
966 snprintf (buf
, BUFSIZE
, "_OBJC_Category_%s_on_%s",
967 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass
)),
968 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
969 decl
= start_var_decl (objc_v2_category_template
, buf
);
970 OBJCMETA (decl
, objc_meta
, meta_category
);
975 next_runtime_abi_02_protocol_decl (tree p
)
980 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
981 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
982 IDENTIFIER_POINTER (PROTOCOL_NAME (p
)));
983 decl
= start_var_decl (objc_v2_protocol_template
, buf
);
984 OBJCMETA (decl
, objc_meta
, meta_protocol
);
989 next_runtime_abi_02_string_decl (tree type
, const char *name
, string_section where
)
991 tree var
= start_var_decl (type
, name
);
995 OBJCMETA (var
, objc_meta
, meta_class_name
);
998 OBJCMETA (var
, objc_meta
, meta_meth_name
);
1000 case meth_var_types
:
1001 OBJCMETA (var
, objc_meta
, meta_meth_type
);
1003 case prop_names_attr
:
1004 OBJCMETA (var
, objc_meta
, meta_prop_name_attr
);
1007 OBJCMETA (var
, objc_meta
, meta_base
);
1013 /* NOTE --- entry --- */
1015 typedef struct GTY(()) ident_data_tuple
{
1018 } ident_data_tuple
;
1020 /* This routine creates a file scope static variable of type 'Class'
1021 to hold the address of a class. */
1024 build_v2_class_reference_decl (tree ident
)
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
);
1035 /* This routine builds a class refs entry for each class name used.
1036 Initially, a (static-ref, IDENT) tuple is added to the list. The
1037 ident is replaced with address of the class metadata (of type
1038 'Class') in the output routine. */
1040 static GTY (()) vec
<ident_data_tuple
, va_gc
> *classrefs
;
1043 objc_v2_get_class_reference (tree ident
)
1050 ident_data_tuple
*ref
;
1051 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
1053 if (ref
->ident
== ident
)
1056 ref
->data
= build_v2_class_reference_decl (ident
);
1062 /* Somewhat arbitrary initial provision. */
1063 vec_alloc (classrefs
, 16);
1065 /* We come here if we don't find the entry - or if the table was yet
1067 decl
= build_v2_class_reference_decl (ident
);
1070 vec_safe_push (classrefs
, e
);
1075 next_runtime_abi_02_get_class_reference (tree ident
)
1077 if (!flag_zero_link
)
1078 return objc_v2_get_class_reference (ident
);
1081 /* We fall back to using objc_getClass (). */
1082 vec
<tree
, va_gc
> *v
;
1085 /* ??? add_class_reference (ident); - is pointless, since the
1086 system lib does not export the equivalent symbols. Maybe we
1087 need to build a class ref anyway. */
1088 t
= my_build_string_pointer (IDENTIFIER_LENGTH (ident
) + 1,
1089 IDENTIFIER_POINTER (ident
));
1091 t
= build_function_call_vec (input_location
, objc_get_class_decl
, v
, 0);
1097 /* Used by build_function_type_for_method. Append the types for
1098 receiver & _cmd at the start of a method argument list to ARGTYPES.
1099 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1100 trying to define a method or call one. SUPERFLAG says this is for a
1101 send to super. METH may be NULL, in the case that there is no
1105 next_runtime_abi_02_get_arg_type_list_base (vec
<tree
, va_gc
> **argtypes
,
1106 tree meth
, int context
,
1112 receiver_type
= objc_super_type
;
1113 else if (context
== METHOD_DEF
&& TREE_CODE (meth
) == INSTANCE_METHOD_DECL
)
1114 receiver_type
= objc_instance_type
;
1116 receiver_type
= objc_object_type
;
1118 vec_safe_push (*argtypes
, receiver_type
);
1119 /* Selector type - will eventually change to `int'. */
1120 vec_safe_push (*argtypes
,
1121 superflag
? objc_v2_super_selector_type
1122 : objc_v2_selector_type
);
1125 /* TODO: Merge this with the message refs. */
1127 build_selector_reference_decl (tree ident
)
1130 char *t
, buf
[BUFSIZE
];
1132 snprintf (buf
, BUFSIZE
, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident
));
1137 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
1140 decl
= start_var_decl (objc_selector_type
, buf
);
1141 OBJCMETA (decl
, objc_meta
, meta_sel_refs
);
1146 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED
,
1148 tree proto ATTRIBUTE_UNUSED
)
1150 tree
*chain
= &sel_ref_chain
;
1155 if (TREE_VALUE (*chain
) == ident
)
1156 return TREE_PURPOSE (*chain
);
1158 chain
= &TREE_CHAIN (*chain
);
1161 expr
= build_selector_reference_decl (ident
);
1162 *chain
= tree_cons (expr
, ident
, NULL_TREE
);
1167 /* Declare a variable of type 'struct message_ref_t'. */
1168 /* This will be finished in build_v2_message_ref_translation_table ().
1169 We take an idea from LLVM in making the names a bit more connected
1170 and thus the asm more readable. */
1173 build_v2_message_reference_decl (tree sel_name
, tree message_func_ident
)
1176 char buf
[BUFSIZE
], *t
;
1179 /* Skip past the objc_msgSend it's the same for all... */
1180 if (IDENTIFIER_POINTER (message_func_ident
)[offset
] == '_')
1183 snprintf (buf
, BUFSIZE
, "_OBJC_MsgRef_%s_%s",
1184 &(IDENTIFIER_POINTER (message_func_ident
)[offset
]),
1185 IDENTIFIER_POINTER (sel_name
));
1190 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
1193 decl
= start_var_decl (objc_v2_message_ref_template
, buf
);
1194 OBJCMETA (decl
, objc_meta
, meta_mref
);
1198 typedef struct GTY(()) msgref_entry
{
1204 static GTY (()) vec
<msgref_entry
, va_gc
> *msgrefs
;
1206 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1207 later on to initialize the table of 'struct message_ref_t'
1211 build_v2_selector_messenger_reference (tree sel_name
, tree message_func_decl
)
1219 FOR_EACH_VEC_ELT (*msgrefs
, count
, ref
)
1220 if (ref
->func
== message_func_decl
&& ref
->selname
== sel_name
)
1221 return ref
->refdecl
;
1224 /* Somewhat arbitrary initial provision. */
1225 vec_alloc (msgrefs
, 32);
1227 /* We come here if we don't find a match or at the start. */
1228 decl
= build_v2_message_reference_decl (sel_name
,
1229 DECL_NAME (message_func_decl
));
1230 e
.func
= message_func_decl
;
1231 e
.selname
= sel_name
;
1233 vec_safe_push (msgrefs
, e
);
1238 build_v2_protocollist_ref_decl (tree protocol
)
1241 tree protocol_ident
= PROTOCOL_NAME (protocol
);
1244 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRef_%s",
1245 IDENTIFIER_POINTER (protocol_ident
));
1246 /* TODO: other compiler versions make these hidden & weak. */
1247 decl
= create_global_decl (objc_protocol_type
, buf
);
1248 /* Let optimizer know that this decl is not removable. */
1249 DECL_PRESERVE_P (decl
) = 1;
1250 OBJCMETA (decl
, objc_meta
, meta_proto_ref
);
1254 typedef struct GTY(()) prot_list_entry
{
1258 static GTY (()) vec
<prot_list_entry
, va_gc
> *protrefs
;
1261 objc_v2_get_protocol_reference (tree ident
)
1268 prot_list_entry
*ref
;
1269 FOR_EACH_VEC_ELT (*protrefs
, count
, ref
)
1271 if (ref
->id
== ident
)
1274 ref
->refdecl
= build_v2_protocollist_ref_decl (ident
);
1275 return ref
->refdecl
;
1280 /* Somewhat arbitrary initial provision. */
1281 vec_alloc (protrefs
, 32);
1283 /* We come here if we don't find the entry - or if the table was yet
1285 decl
= build_v2_protocollist_ref_decl (ident
);
1288 vec_safe_push (protrefs
, e
);
1293 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED
,
1296 if (!PROTOCOL_FORWARD_DECL (p
))
1297 PROTOCOL_FORWARD_DECL (p
) = next_runtime_abi_02_protocol_decl (p
);
1299 return objc_v2_get_protocol_reference (p
);
1302 /* This routine returns the ivar declaration, if component is a valid
1303 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1304 returns the class name in CLASS. */
1307 objc_is_ivar (tree expr
, tree component
, tree
*klass
)
1309 tree field
= NULL_TREE
;
1310 tree basetype
= TYPE_MAIN_VARIANT (TREE_TYPE (expr
));
1312 if (TREE_CODE (basetype
) == RECORD_TYPE
1313 && TYPE_HAS_OBJC_INFO (basetype
) && TYPE_OBJC_INTERFACE (basetype
))
1315 *klass
= lookup_interface (OBJC_TYPE_NAME (basetype
));
1320 tree ivar_chain
= CLASS_RAW_IVARS (*klass
);
1323 field
= is_ivar (ivar_chain
, component
);
1324 if (field
!= NULL_TREE
)
1327 *klass
= lookup_interface (CLASS_SUPER_NAME (*klass
));
1336 create_ivar_offset_name (char *buf
, tree class_name
, tree field_decl
)
1338 tree fname
= DECL_NAME (field_decl
);
1340 sprintf (buf
, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name
),
1341 IDENTIFIER_POINTER (fname
));
1345 /* This routine generates new abi's ivar reference tree. It amounts
1346 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1347 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1348 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1351 objc_v2_build_ivar_ref (tree datum
, tree component
)
1353 tree field
, ref
, class_name
, offset
, ftype
, expr
;
1354 char var_offset_name
[512];
1356 field
= objc_is_ivar (datum
, component
, &class_name
);
1360 /* This routine only handles non-bitfield fields */
1361 /* DECL_INITIAL macro is set to width of bitfield and can be relied
1362 on to check for bitfield ivars. Note that I cannot rely on
1363 DECL_BIT_FIELD macro because it is only set when the whole struct
1364 is seen (at finish_struct) and not when the ivar chain is
1366 if (DECL_INITIAL (field
))
1369 create_ivar_offset_name (var_offset_name
, CLASS_NAME (class_name
), field
);
1371 offset
= create_extern_decl (TREE_TYPE (size_zero_node
), var_offset_name
);
1373 ftype
= TREE_TYPE (field
);
1376 expr
= build_c_cast (input_location
,
1377 string_type_node
, build_fold_addr_expr (datum
));
1379 /* (char*)datum + offset */
1380 expr
= fold_build_pointer_plus_loc (input_location
, expr
, offset
);
1382 /* (ftype*)((char*)datum + offset) */
1383 expr
= build_c_cast (input_location
, build_pointer_type (ftype
), expr
);
1385 /* Finally: *(ftype*)((char*)datum + offset) */
1386 ref
= build_indirect_ref (input_location
, expr
, RO_UNARY_STAR
);
1388 /* We must set type of the resulting expression to be the same as
1389 the field type. This is because, build_indirect_ref (...)
1390 rebuilds the type which may result in lost information; as in the
1391 case of protocol-qualified types (id <protocol> ). */
1392 TREE_TYPE (ref
) = ftype
;
1394 if (TREE_READONLY (datum
) || TREE_READONLY (field
))
1395 TREE_READONLY (ref
) = 1;
1397 if (TREE_THIS_VOLATILE (datum
) || TREE_THIS_VOLATILE (field
))
1398 TREE_THIS_VOLATILE (ref
) = 1;
1400 if (TREE_DEPRECATED (field
))
1401 warn_deprecated_use (field
, NULL_TREE
);
1406 /* IVAR refs are made via an externally referenceable offset and built
1407 on the fly. That is, unless they refer to (private) fields in the
1410 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED
,
1414 if ((ivar
= objc_v2_build_ivar_ref (base
, id
)))
1416 return objc_build_component_ref (base
, id
);
1419 /* [super ...] references are listed here (and built into a table at
1420 meta -data emit time). */
1422 build_v2_superclass_ref_decl (tree ident
, bool inst
)
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
);
1434 static GTY (()) vec
<ident_data_tuple
, va_gc
> *class_super_refs
;
1435 static GTY (()) vec
<ident_data_tuple
, va_gc
> *metaclass_super_refs
;
1438 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED
,
1439 struct imp_entry
*imp
, bool inst_meth
)
1443 tree id
= CLASS_NAME (imp
->imp_context
);
1444 vec
<ident_data_tuple
, va_gc
> *list
= inst_meth
? class_super_refs
1445 : metaclass_super_refs
;
1450 ident_data_tuple
*ref
;
1451 FOR_EACH_VEC_ELT (*list
, count
, ref
)
1453 if (ref
->ident
== id
)
1456 ref
->data
= build_v2_superclass_ref_decl (id
, inst_meth
);
1463 /* Somewhat arbitrary initial provision. */
1466 vec_alloc (class_super_refs
, 16);
1467 list
= class_super_refs
;
1471 vec_alloc (metaclass_super_refs
, 16);
1472 list
= metaclass_super_refs
;
1475 /* We come here if we don't find the entry - or if the table was yet
1477 decl
= build_v2_superclass_ref_decl (id
, inst_meth
);
1480 vec_safe_push (list
, e
);
1485 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED
,
1486 struct imp_entry
*imp
, bool inst_meth
)
1488 /* ??? is this OK when zero-link = true? */
1489 tree super_name
= CLASS_SUPER_NAME (imp
->imp_template
);
1492 if (!flag_zero_link
)
1494 super_class
= objc_get_class_reference (CLASS_NAME (imp
->imp_template
));
1498 /* If we are in a class method, we must retrieve the
1499 _metaclass_ for the current class, pointed at by the
1500 class's "isa" pointer. The following assumes that "isa" is
1501 the first ivar in a class (which it must be). */
1503 build_indirect_ref (input_location
,
1504 build_c_cast (input_location
,
1505 build_pointer_type (objc_class_type
),
1510 /* ??? Do we need to add the class ref anway for zero-link? */
1511 /* else do it the slow way. */
1512 super_class
= (inst_meth
? objc_get_class_decl
: objc_get_meta_class_decl
);
1513 super_name
= my_build_string_pointer (IDENTIFIER_LENGTH (super_name
) + 1,
1514 IDENTIFIER_POINTER (super_name
));
1515 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1516 return build_function_call (input_location
,
1518 build_tree_list (NULL_TREE
, super_name
));
1522 next_runtime_abi_02_receiver_is_class_object (tree receiver
)
1524 if (TREE_CODE (receiver
) == VAR_DECL
1525 && IS_CLASS (TREE_TYPE (receiver
))
1526 && vec_safe_length (classrefs
))
1529 ident_data_tuple
*ref
;
1530 /* The receiver is a variable created by build_class_reference_decl. */
1531 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
1532 if (ref
->data
== receiver
)
1538 /* Assign all arguments in VALUES which have side-effect to a temporary
1539 and replaced that argument in VALUES list with the temporary. The
1540 arguments will be passed to a function with FNTYPE. */
1543 objc_copy_to_temp_side_effect_params (tree fntype
, tree values
)
1546 function_args_iterator iter
;
1548 /* Skip over receiver and the &_msf_ref types. */
1549 function_args_iter_init (&iter
, fntype
);
1550 function_args_iter_next (&iter
);
1551 function_args_iter_next (&iter
);
1553 for (valtail
= values
; valtail
;
1554 valtail
= TREE_CHAIN (valtail
), function_args_iter_next (&iter
))
1556 tree value
= TREE_VALUE (valtail
);
1557 tree type
= function_args_iter_cond (&iter
);
1558 if (type
== NULL_TREE
)
1560 if (!TREE_SIDE_EFFECTS (value
))
1562 /* To prevent re-evaluation. */
1563 value
= save_expr (value
);
1565 TREE_VALUE (valtail
) = value
;
1570 /* Build the new abi's messaging library call. It looks like:
1571 (*_msg.messenger) (receiver, &_msg, ...) */
1574 build_v2_build_objc_method_call (int super_flag
, tree method_prototype
,
1575 tree lookup_object
, tree selector
,
1580 tree sender
, rcv_p
, t
;
1583 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1584 : objc_object_type
);
1585 tree ftype
= build_function_type_for_method (ret_type
, method_prototype
,
1586 METHOD_REF
, super_flag
);
1589 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
1590 ftype
= build_type_attribute_variant (
1591 ftype
, METHOD_TYPE_ATTRIBUTES (method_prototype
));
1593 sender_cast
= build_pointer_type (ftype
);
1596 method_params
= objc_copy_to_temp_side_effect_params (ftype
,
1599 /* Get &message_ref_t.messenger. */
1600 sender
= build_c_cast (input_location
,
1601 build_pointer_type (super_flag
1602 ? objc_v2_super_imp_type
1603 : objc_v2_imp_type
),
1606 sender
= build_indirect_ref (input_location
, sender
, RO_UNARY_STAR
);
1608 rcv_p
= (super_flag
? objc_super_type
: objc_object_type
);
1610 lookup_object
= build_c_cast (input_location
, rcv_p
, lookup_object
);
1612 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1613 lookup_object
= save_expr (lookup_object
);
1615 method_params
= tree_cons (NULL_TREE
, lookup_object
,
1616 tree_cons (NULL_TREE
, selector
,
1618 t
= build3 (OBJ_TYPE_REF
, sender_cast
, sender
, lookup_object
, size_zero_node
);
1619 ret_val
= build_function_call (input_location
, t
, method_params
);
1622 /* receiver != nil ? ret_val : 0 */
1626 if (TREE_CODE (ret_type
) == RECORD_TYPE
1627 || TREE_CODE (ret_type
) == UNION_TYPE
)
1629 vec
<constructor_elt
, va_gc
> *rtt
= NULL
;
1630 /* ??? CHECKME. hmmm..... think we need something more
1632 CONSTRUCTOR_APPEND_ELT (rtt
, NULL_TREE
, NULL_TREE
);
1633 ftree
= objc_build_constructor (ret_type
, rtt
);
1636 ftree
= fold_convert (ret_type
, integer_zero_node
);
1638 ifexp
= build_binary_op (input_location
, NE_EXPR
,
1640 fold_convert (rcv_p
, integer_zero_node
), 1);
1643 ret_val
= build_conditional_expr (input_location
,
1644 ifexp
, ret_val
, ftree
,
1645 tf_warning_or_error
);
1648 ret_val
= build_conditional_expr (input_location
,
1658 next_runtime_abi_02_build_objc_method_call (location_t loc
,
1659 tree method_prototype
,
1666 tree ret_type
, selector
;
1667 tree message_func_decl
;
1668 bool check_for_nil
= flag_objc_nilcheck
;
1670 ret_type
= method_prototype
1671 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1674 /* Do we need to check for nil receivers ? */
1675 /* For now, message sent to classes need no nil check. In the
1676 future, class declaration marked as weak_import must be nil
1679 || (TREE_CODE (receiver
) == VAR_DECL
1680 && TREE_TYPE (receiver
) == objc_class_type
))
1681 check_for_nil
= false;
1683 if (!targetm
.calls
.struct_value_rtx (0, 0)
1684 && (TREE_CODE (ret_type
) == RECORD_TYPE
1685 || TREE_CODE (ret_type
) == UNION_TYPE
)
1686 && targetm
.calls
.return_in_memory (ret_type
, 0))
1689 message_func_decl
= umsg_id_super2_stret_fixup_decl
;
1691 message_func_decl
= objc_is_id (rtype
)
1692 ? umsg_id_stret_fixup_decl
1693 : umsg_stret_fixup_decl
;
1698 message_func_decl
= umsg_id_super2_fixup_decl
;
1700 message_func_decl
= objc_is_id (rtype
)
1701 ? umsg_id_fixup_decl
1705 selector
= build_v2_selector_messenger_reference (sel_name
,
1708 /* selector = &_msg; */
1709 selector
= build_unary_op (loc
, ADDR_EXPR
, selector
, 0);
1711 selector
= build_c_cast (loc
, (super
? objc_v2_super_selector_type
1712 : objc_v2_selector_type
),
1715 /* (*_msg.messenger) (receiver, &_msg, ...); */
1716 return build_v2_build_objc_method_call (super
, method_prototype
,
1718 method_params
, check_for_nil
);
1721 /* NOTE --- Constant String Class Stuff --- */
1724 next_runtime_abi_02_setup_const_string_class_decl (void)
1726 if (!constant_string_global_id
)
1728 /* Hopefully, this should not represent a serious limitation. */
1730 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s", constant_string_class_name
);
1731 constant_string_global_id
= get_identifier (buf
);
1734 string_class_decl
= lookup_name (constant_string_global_id
);
1736 /* In OBJC2 abi, constant string class reference refers to class
1737 name for NSConstantString class. This declaration may not be
1738 available yet (in fact it is not in most cases). So, declare an
1739 extern OBJC_CLASS_$_NSConstantString in its place. */
1740 if (!string_class_decl
)
1742 create_extern_decl (objc_v2_class_template
,
1743 IDENTIFIER_POINTER (constant_string_global_id
));
1745 return (string_class_decl
!= NULL_TREE
);
1749 next_runtime_abi_02_build_const_string_constructor (location_t loc
, tree string
,
1752 tree constructor
, fields
, var
;
1753 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1755 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1756 fields
= TYPE_FIELDS (internal_const_str_type
);
1757 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1758 build_unary_op (loc
, ADDR_EXPR
, string_class_decl
, 0));
1760 fields
= DECL_CHAIN (fields
);
1761 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1762 build_unary_op (loc
, ADDR_EXPR
, string
, 1));
1764 /* ??? check if this should be long. */
1765 fields
= DECL_CHAIN (fields
);
1766 CONSTRUCTOR_APPEND_ELT (v
, fields
, build_int_cst (NULL_TREE
, length
));
1767 constructor
= objc_build_constructor (internal_const_str_type
, v
);
1769 var
= build_decl (input_location
, CONST_DECL
, NULL
, TREE_TYPE (constructor
));
1770 DECL_INITIAL (var
) = constructor
;
1771 TREE_STATIC (var
) = 1;
1772 DECL_CONTEXT (var
) = NULL
;
1773 OBJCMETA (var
, objc_meta
, meta_const_str
);
1777 /* NOTE --- NeXT V2 Metadata templates --- */
1779 /* This routine builds the following type:
1782 const char * const name; // property name
1783 const char * const attributes; // comma-delimited, encoded,
1784 // property attributes
1789 build_v2_property_template (void)
1792 tree decls
, *chain
= NULL
;
1794 prop_record
= objc_start_struct (get_identifier ("_prop_t"));
1795 /* const char * name */
1796 decls
= add_field_decl (string_type_node
, "name", &chain
);
1798 /* const char * attribute */
1799 add_field_decl (string_type_node
, "attribute", &chain
);
1801 objc_finish_struct (prop_record
, decls
);
1807 unsigned long int *offset;
1816 build_v2_ivar_t_template (void)
1818 tree objc_ivar_id
, objc_ivar_record
;
1819 tree decls
, *chain
= NULL
;
1821 objc_ivar_id
= get_identifier ("_ivar_t");
1822 objc_ivar_record
= objc_start_struct (objc_ivar_id
);
1824 /* unsigned long int *offset; */
1825 decls
= add_field_decl (build_pointer_type
1826 (TREE_TYPE (size_zero_node
)), "offset", &chain
);
1829 add_field_decl (string_type_node
, "name", &chain
);
1832 add_field_decl (string_type_node
, "type", &chain
);
1834 /* uint32_t alignment; */
1835 add_field_decl (integer_type_node
, "alignment", &chain
);
1837 /* uint32_t size; */
1838 add_field_decl (integer_type_node
, "size", &chain
);
1840 objc_finish_struct (objc_ivar_record
, decls
);
1841 return objc_ivar_record
;
1845 build_metadata_templates (void)
1848 if (!objc_method_template
)
1849 objc_method_template
= build_method_template ();
1851 if (!objc_v2_property_template
)
1852 objc_v2_property_template
= build_v2_property_template ();
1854 if (!objc_v2_ivar_template
)
1855 objc_v2_ivar_template
= build_v2_ivar_t_template ();
1859 /* NOTE --- Output NeXT V2 Metadata --- */
1861 /* Routine builds name of Interface's main meta-data of type class_t. */
1864 objc_build_internal_classname (tree ident
, bool metaclass
)
1866 static char string
[512];
1867 snprintf (string
, 512, "%s_%s", metaclass
? "OBJC_METACLASS_$"
1869 IDENTIFIER_POINTER (ident
));
1873 /* Build the name for object of type struct class_ro_t */
1876 newabi_append_ro (const char *name
)
1880 static char string
[BUFSIZE
];
1881 dollar
= strchr (name
, '$');
1882 gcc_assert (dollar
);
1885 strncpy (p
, name
, (int)(dollar
- name
));
1886 p
+= (int)(dollar
- name
);
1887 sprintf (p
, "RO_%s", dollar
);
1891 /* Build the struct message_ref_t msg =
1892 {objc_msgSend_fixup_xxx, @selector(func)}
1896 void build_v2_message_ref_translation_table (void)
1901 if (!vec_safe_length (msgrefs
))
1904 FOR_EACH_VEC_ELT (*msgrefs
, count
, ref
)
1906 vec
<constructor_elt
, va_gc
> *initializer
;
1907 tree expr
, constructor
;
1908 tree struct_type
= TREE_TYPE (ref
->refdecl
);
1909 location_t loc
= DECL_SOURCE_LOCATION (ref
->refdecl
);
1912 /* First 'IMP messenger' field... */
1913 expr
= build_unary_op (loc
, ADDR_EXPR
, ref
->func
, 0);
1914 expr
= convert (objc_v2_imp_type
, expr
);
1915 CONSTRUCTOR_APPEND_ELT (initializer
, NULL_TREE
, expr
);
1917 /* ... then 'SEL name' field. */
1918 expr
= build_selector (ref
->selname
);
1919 CONSTRUCTOR_APPEND_ELT (initializer
, NULL_TREE
, expr
);
1920 constructor
= objc_build_constructor (struct_type
, initializer
);
1921 finish_var_decl (ref
->refdecl
, constructor
);
1925 /* Build decl = initializer; for each externally visible class
1929 build_v2_classrefs_table (void)
1932 ident_data_tuple
*ref
;
1934 if (!vec_safe_length (classrefs
))
1937 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
1939 tree expr
= ref
->ident
;
1940 tree decl
= ref
->data
;
1941 /* Interface with no implementation and yet one of its messages
1942 has been used. Need to generate a full address-of tree for it
1944 if (TREE_CODE (expr
) == IDENTIFIER_NODE
)
1946 const char *name
= objc_build_internal_classname (expr
, false);
1947 expr
= create_extern_decl (objc_v2_class_template
, name
);
1948 expr
= convert (objc_class_type
, build_fold_addr_expr (expr
));
1950 /* The runtime wants this, even if it appears unused, so we must force the
1952 DECL_PRESERVE_P (decl) = 1; */
1953 finish_var_decl (decl
, expr
);
1957 /* Build decl = initializer; for each externally visible super class
1961 build_v2_super_classrefs_table (bool metaclass
)
1964 ident_data_tuple
*ref
;
1965 vec
<ident_data_tuple
, va_gc
> *list
= metaclass
? metaclass_super_refs
1968 if (!vec_safe_length (list
))
1971 FOR_EACH_VEC_ELT (*list
, count
, ref
)
1973 tree expr
= ref
->ident
;
1974 tree decl
= ref
->data
;
1975 /* Interface with no implementation and yet one of its messages
1976 has been used. Need to generate a full address-of tree for it
1978 if (TREE_CODE (expr
) == IDENTIFIER_NODE
)
1980 const char * name
= objc_build_internal_classname (expr
, metaclass
);
1981 expr
= create_extern_decl (objc_v2_class_template
, name
);
1982 expr
= convert (objc_class_type
, build_fold_addr_expr (expr
));
1984 finish_var_decl (decl
, expr
);
1988 /* Add the global class meta-data declaration to the list which later
1989 on ends up in the __class_list section. */
1991 static GTY(()) vec
<tree
, va_gc
> *class_list
;
1994 objc_v2_add_to_class_list (tree global_class_decl
)
1996 vec_safe_push (class_list
, global_class_decl
);
1999 static GTY(()) vec
<tree
, va_gc
> *nonlazy_class_list
;
2001 /* Add the global class meta-data declaration to the list which later
2002 on ends up in the __nonlazy_class section. */
2005 objc_v2_add_to_nonlazy_class_list (tree global_class_decl
)
2007 vec_safe_push (nonlazy_class_list
, global_class_decl
);
2010 static GTY(()) vec
<tree
, va_gc
> *category_list
;
2012 /* Add the category meta-data declaration to the list which later on
2013 ends up in the __nonlazy_category section. */
2016 objc_v2_add_to_category_list (tree decl
)
2018 vec_safe_push (category_list
, decl
);
2021 static GTY(()) vec
<tree
, va_gc
> *nonlazy_category_list
;
2023 /* Add the category meta-data declaration to the list which later on
2024 ends up in the __category_list section. */
2027 objc_v2_add_to_nonlazy_category_list (tree decl
)
2029 vec_safe_push (nonlazy_category_list
, decl
);
2033 has_load_impl (tree clsmeth
)
2037 tree id
= METHOD_SEL_NAME (clsmeth
);
2038 if (IDENTIFIER_LENGTH (id
) == 4
2039 && strncmp (IDENTIFIER_POINTER (id
), "load", 4) == 0)
2041 clsmeth
= DECL_CHAIN (clsmeth
);
2047 /* Build a __{class,category}_list section table containing address of
2048 all @implemented {class,category} meta-data. */
2051 build_v2_address_table (vec
<tree
, va_gc
> *src
, const char *nam
, tree attr
)
2054 tree type
, decl
, expr
;
2055 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2057 if (!vec_safe_length (src
))
2060 FOR_EACH_VEC_ELT (*src
, count
, decl
)
2063 tree purpose
= build_int_cst (NULL_TREE
, count
);
2065 tree purpose
= NULL_TREE
;
2067 expr
= convert (objc_class_type
, build_fold_addr_expr (decl
));
2068 CONSTRUCTOR_APPEND_ELT (initlist
, purpose
, expr
);
2070 gcc_assert (count
> 0);
2071 type
= build_array_type (objc_class_type
,
2072 build_index_type (build_int_cst (NULL_TREE
, count
- 1)));
2073 decl
= start_var_decl (type
, nam
);
2074 /* The runtime wants this, even if it appears unused, so we must
2075 force the output. */
2076 DECL_PRESERVE_P (decl
) = 1;
2077 expr
= objc_build_constructor (type
, initlist
);
2078 OBJCMETA (decl
, objc_meta
, attr
);
2079 finish_var_decl (decl
, expr
);
2082 /* Build decl = initializer; for each protocol referenced in
2083 @protocol(MyProt) expression. Refs as built in the entry section
2087 build_v2_protocol_list_translation_table (void)
2090 prot_list_entry
*ref
;
2095 FOR_EACH_VEC_ELT (*protrefs
, count
, ref
)
2099 gcc_assert (TREE_CODE (ref
->id
) == PROTOCOL_INTERFACE_TYPE
);
2100 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
2101 IDENTIFIER_POINTER (PROTOCOL_NAME (ref
->id
)));
2102 expr
= start_var_decl (objc_v2_protocol_template
, buf
);
2103 expr
= convert (objc_protocol_type
, build_fold_addr_expr (expr
));
2104 finish_var_decl (ref
->refdecl
, expr
);
2106 /* TODO: Maybe we could explicitly delete the vec. now? */
2109 static GTY (()) vec
<prot_list_entry
, va_gc
> *protlist
;
2111 /* Add the local protocol meta-data declaration to the list which
2112 later on ends up in the __protocol_list section. */
2115 objc_add_to_protocol_list (tree protocol_interface_decl
, tree protocol_decl
)
2119 /* Arbitrary init count. */
2120 vec_alloc (protlist
, 32);
2121 e
.id
= protocol_interface_decl
;
2122 e
.refdecl
= protocol_decl
;
2123 vec_safe_push (protlist
, e
);
2126 /* Build the __protocol_list section table containing address of all
2127 generate protocol_t meta-data. */
2130 build_v2_protocol_list_address_table (void)
2133 prot_list_entry
*ref
;
2134 if (!vec_safe_length (protlist
))
2137 FOR_EACH_VEC_ELT (*protlist
, count
, ref
)
2141 gcc_assert (ref
->id
&& TREE_CODE (ref
->id
) == PROTOCOL_INTERFACE_TYPE
);
2142 snprintf (buf
, BUFSIZE
, "_OBJC_LabelProtocol_%s",
2143 IDENTIFIER_POINTER (PROTOCOL_NAME (ref
->id
)));
2144 decl
= create_global_decl (objc_protocol_type
, buf
);
2145 expr
= convert (objc_protocol_type
, build_fold_addr_expr (ref
->refdecl
));
2146 OBJCMETA (decl
, objc_meta
, meta_label_protocollist
);
2147 finish_var_decl (decl
, expr
);
2150 /* TODO: delete the vec. */
2151 /* TODO: upgrade to the clang/llvm hidden version. */
2154 /* This routine declares a variable to hold meta data for 'struct
2155 protocol_list_t'. */
2158 generate_v2_protocol_list (tree i_or_p
, tree klass_ctxt
)
2160 tree refs_decl
, lproto
, e
, plist
, ptempl_p_t
;
2162 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2165 if (TREE_CODE (i_or_p
) == CLASS_INTERFACE_TYPE
2166 || TREE_CODE (i_or_p
) == CATEGORY_INTERFACE_TYPE
)
2167 plist
= CLASS_PROTOCOL_LIST (i_or_p
);
2168 else if (TREE_CODE (i_or_p
) == PROTOCOL_INTERFACE_TYPE
)
2169 plist
= PROTOCOL_LIST (i_or_p
);
2174 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
2175 if (TREE_CODE (TREE_VALUE (lproto
)) == PROTOCOL_INTERFACE_TYPE
2176 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto
)))
2179 /* Build initializer. */
2181 ptempl_p_t
= build_pointer_type (objc_v2_protocol_template
);
2182 e
= build_int_cst (ptempl_p_t
, size
);
2183 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, e
);
2185 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
2187 tree pval
= TREE_VALUE (lproto
);
2189 if (TREE_CODE (pval
) == PROTOCOL_INTERFACE_TYPE
2190 && PROTOCOL_FORWARD_DECL (pval
))
2192 tree fwref
= PROTOCOL_FORWARD_DECL (pval
);
2193 location_t loc
= DECL_SOURCE_LOCATION (fwref
) ;
2194 e
= build_unary_op (loc
, ADDR_EXPR
, fwref
, 0);
2195 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, e
);
2199 /* static struct protocol_list_t *list[size]; */
2201 switch (TREE_CODE (i_or_p
))
2203 case PROTOCOL_INTERFACE_TYPE
:
2204 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRefs_%s",
2205 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p
)));
2207 case CLASS_INTERFACE_TYPE
:
2208 snprintf (buf
, BUFSIZE
, "_OBJC_ClassProtocols_%s",
2209 IDENTIFIER_POINTER (CLASS_NAME (i_or_p
)));
2211 case CATEGORY_INTERFACE_TYPE
:
2212 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryProtocols_%s_%s",
2213 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)),
2214 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt
)));
2220 refs_decl
= start_var_decl (build_sized_array_type (ptempl_p_t
, size
+1),
2222 /* ObjC2 puts all these in the base section. */
2223 OBJCMETA (refs_decl
, objc_meta
, meta_base
);
2224 DECL_PRESERVE_P (refs_decl
) = 1;
2225 finish_var_decl (refs_decl
,
2226 objc_build_constructor (TREE_TYPE (refs_decl
),initlist
));
2230 /* This routine builds one 'struct method_t' initializer list. Note
2231 that the old ABI is supposed to build 'struct objc_method' which
2232 has 3 fields, but it does not build the initialization expression
2233 for 'method_imp' which for protocols is NULL any way. To be
2234 consistent with declaration of 'struct method_t', in the new ABI we
2235 set the method_t.imp to NULL. */
2238 build_v2_descriptor_table_initializer (tree type
, tree entries
)
2240 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2243 vec
<constructor_elt
, va_gc
> *eltlist
= NULL
;
2244 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
,
2245 build_selector (METHOD_SEL_NAME (entries
)));
2246 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
,
2247 add_objc_string (METHOD_ENCODING (entries
),
2249 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
, null_pointer_node
);
2251 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
2252 objc_build_constructor (type
, eltlist
));
2253 entries
= TREE_CHAIN (entries
);
2257 return objc_build_constructor (build_array_type (type
, 0), initlist
);
2260 /* struct method_list_t
2263 uint32_t method_count;
2264 struct objc_method method_list[method_count];
2268 build_v2_method_list_template (tree list_type
, int size
)
2270 tree method_list_t_record
;
2271 tree array_type
, decls
, *chain
= NULL
;
2273 method_list_t_record
= objc_start_struct (NULL_TREE
);
2275 /* uint32_t const entsize; */
2276 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2278 /* int method_count; */
2279 add_field_decl (integer_type_node
, "method_count", &chain
);
2281 /* struct objc_method method_list[]; */
2282 array_type
= build_sized_array_type (list_type
, size
);
2283 add_field_decl (array_type
, "method_list", &chain
);
2285 objc_finish_struct (method_list_t_record
, decls
);
2286 return method_list_t_record
;
2289 /* Note, as above that we are building to the objc_method_template
2290 which has the *imp field. ABI0/1 build with
2291 objc_method_prototype_template which is missing this field. */
2293 generate_v2_meth_descriptor_table (tree chain
, tree protocol
,
2294 const char *prefix
, tree attr
)
2296 tree method_list_template
, initlist
, decl
, methods
;
2298 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2301 if (!chain
|| !prefix
)
2308 if (! METHOD_ENCODING (methods
))
2309 METHOD_ENCODING (methods
) = encode_method_prototype (methods
);
2310 methods
= TREE_CHAIN (methods
);
2315 method_list_template
= build_v2_method_list_template (objc_method_template
,
2317 snprintf (buf
, BUFSIZE
, "%s_%s", prefix
,
2318 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
2320 decl
= start_var_decl (method_list_template
, buf
);
2322 entsize
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template
));
2323 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, entsize
));
2324 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
2326 build_v2_descriptor_table_initializer (objc_method_template
,
2328 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
2329 /* Get into the right section. */
2330 OBJCMETA (decl
, objc_meta
, attr
);
2331 finish_var_decl (decl
, objc_build_constructor (method_list_template
, v
));
2335 /* This routine builds the initializer list to initialize the 'struct
2336 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2339 build_v2_property_table_initializer (tree type
, tree context
)
2342 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2343 if (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
)
2344 x
= CLASS_PROPERTY_DECL (context
);
2346 x
= IMPL_PROPERTY_DECL (context
);
2348 for (; x
; x
= TREE_CHAIN (x
))
2350 vec
<constructor_elt
, va_gc
> *elemlist
= NULL
;
2351 /* NOTE! sections where property name/attribute go MUST change
2353 tree attribute
, name_ident
= PROPERTY_NAME (x
);
2355 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
2356 add_objc_string (name_ident
, prop_names_attr
));
2358 attribute
= objc_v2_encode_prop_attr (x
);
2359 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
2360 add_objc_string (attribute
, prop_names_attr
));
2362 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2363 objc_build_constructor (type
, elemlist
));
2366 return objc_build_constructor (build_array_type (type
, 0),inits
);
2369 /* This routine builds the following type:
2372 uint32_t entsize; // sizeof (struct _prop_t)
2373 uint32_t prop_count;
2374 struct _prop_t prop_list [prop_count];
2379 build_v2_property_list_template (tree list_type
, int size
)
2381 tree property_list_t_record
;
2382 tree array_type
, decls
, *chain
= NULL
;
2385 property_list_t_record
= objc_start_struct (NULL_TREE
);
2387 /* uint32_t const entsize; */
2388 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2390 /* int prop_count; */
2391 add_field_decl (integer_type_node
, "prop_count", &chain
);
2393 /* struct _prop_t prop_list[]; */
2394 array_type
= build_sized_array_type (list_type
, size
);
2395 add_field_decl (array_type
, "prop_list", &chain
);
2397 objc_finish_struct (property_list_t_record
, decls
);
2398 return property_list_t_record
;
2401 /* Top-level routine to generate property tables for each
2405 generate_v2_property_table (tree context
, tree klass_ctxt
)
2407 tree x
, decl
, initlist
, property_list_template
;
2408 bool is_proto
= false;
2409 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2410 int init_val
, size
= 0;
2415 gcc_assert (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
);
2416 x
= CLASS_PROPERTY_DECL (context
);
2420 x
= IMPL_PROPERTY_DECL (klass_ctxt
);
2422 for (; x
; x
= TREE_CHAIN (x
))
2428 property_list_template
=
2429 build_v2_property_list_template (objc_v2_property_template
,
2432 initlist
= build_v2_property_table_initializer (objc_v2_property_template
,
2436 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template
));
2438 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolPropList_%s",
2439 IDENTIFIER_POINTER (PROTOCOL_NAME (context
)));
2441 snprintf (buf
, BUFSIZE
, "_OBJC_ClassPropList_%s",
2442 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)));
2444 decl
= start_var_decl (property_list_template
, buf
);
2446 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2447 build_int_cst (NULL_TREE
, init_val
));
2448 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2449 build_int_cst (NULL_TREE
, size
));
2450 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
2452 OBJCMETA (decl
, objc_meta
, meta_base
);
2453 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), inits
));
2458 build_v2_protocol_initializer (tree type
, tree protocol_name
, tree protocol_list
,
2459 tree inst_methods
, tree class_methods
,
2460 tree opt_ins_meth
, tree opt_cls_meth
,
2465 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2467 /* TODO: find a better representation of location from the inputs. */
2468 loc
= UNKNOWN_LOCATION
;
2470 /* This is NULL for the new ABI. */
2471 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2472 convert (objc_object_type
, null_pointer_node
));
2474 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_name
);
2475 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_list
);
2477 ttyp
= objc_method_proto_list_ptr
;
2479 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
2481 expr
= convert (ttyp
, null_pointer_node
);
2482 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2485 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
2487 expr
= convert (ttyp
, null_pointer_node
);
2488 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2491 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, opt_ins_meth
, 0));
2493 expr
= convert (ttyp
, null_pointer_node
);
2494 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2497 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, opt_cls_meth
, 0));
2499 expr
= convert (ttyp
, null_pointer_node
);
2500 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2502 ttyp
= objc_prop_list_ptr
;
2504 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
2506 expr
= convert (ttyp
, null_pointer_node
);
2507 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2509 /* const uint32_t size; = sizeof(struct protocol_t) */
2510 expr
= build_int_cst (integer_type_node
,
2511 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template
)));
2512 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2513 /* const uint32_t flags; = 0 */
2514 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, integer_zero_node
);
2516 return objc_build_constructor (type
, inits
);
2519 /* Main routine to build all meta data for all protocols used in a
2520 translation unit. */
2523 generate_v2_protocols (void)
2528 if (!protocol_chain
)
2531 /* If a protocol was directly referenced, pull in indirect
2533 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
2534 if (PROTOCOL_FORWARD_DECL (p
) && PROTOCOL_LIST (p
))
2535 generate_protocol_references (PROTOCOL_LIST (p
));
2537 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
2540 tree inst_meth
, class_meth
, opt_inst_meth
, opt_class_meth
, props
;
2541 tree decl
, initlist
, protocol_name_expr
, refs_decl
, refs_expr
;
2543 /* If protocol wasn't referenced, don't generate any code. */
2544 decl
= PROTOCOL_FORWARD_DECL (p
);
2549 loc
= DECL_SOURCE_LOCATION (decl
);
2553 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p
), p
,
2554 "_OBJC_ProtocolInstanceMethods",
2555 meta_proto_nst_meth
);
2558 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p
), p
,
2559 "_OBJC_ProtocolClassMethods",
2560 meta_proto_cls_meth
);
2563 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p
), p
,
2564 "_OBJC_OptProtocolInstMethods",
2565 meta_proto_nst_meth
);
2568 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p
), p
,
2569 "_OBJC_OptProtocolClassMethods",
2570 meta_proto_cls_meth
);
2572 if (PROTOCOL_LIST (p
))
2573 refs_decl
= generate_v2_protocol_list (p
, NULL_TREE
);
2577 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2578 protocol_name_expr
= add_objc_string (PROTOCOL_NAME (p
), class_names
);
2581 refs_expr
= convert (build_pointer_type (objc_v2_protocol_template
),
2582 build_unary_op (loc
, ADDR_EXPR
, refs_decl
, 0));
2584 refs_expr
= build_int_cst (NULL_TREE
, 0);
2586 props
= generate_v2_property_table (p
, NULL_TREE
);
2588 initlist
= build_v2_protocol_initializer (TREE_TYPE (decl
),
2589 protocol_name_expr
, refs_expr
,
2590 inst_meth
, class_meth
,
2591 opt_inst_meth
, opt_class_meth
,
2593 finish_var_decl (decl
, initlist
);
2594 objc_add_to_protocol_list (p
, decl
);
2599 /* Make sure we get the Protocol class linked in - reference
2601 p
= objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME
));
2602 /* ... but since we don't specifically use the reference... we
2603 need to force it. */
2604 DECL_PRESERVE_P (p
) = 1;
2609 generate_v2_dispatch_table (tree chain
, const char *name
, tree attr
)
2611 tree decl
, method_list_template
, initlist
;
2612 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2615 if (!chain
|| !name
|| !(size
= list_length (chain
)))
2618 method_list_template
2619 = build_v2_method_list_template (objc_method_template
, size
);
2621 = build_dispatch_table_initializer (objc_method_template
, chain
);
2623 decl
= start_var_decl (method_list_template
, name
);
2625 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template
));
2626 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2627 build_int_cst (integer_type_node
, init_val
));
2628 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2629 build_int_cst (integer_type_node
, size
));
2630 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
2632 OBJCMETA (decl
, objc_meta
, attr
);
2633 finish_var_decl (decl
,
2634 objc_build_constructor (TREE_TYPE (decl
), v
));
2638 /* Init a category. */
2640 build_v2_category_initializer (tree type
, tree cat_name
, tree class_name
,
2641 tree inst_methods
, tree class_methods
,
2642 tree protocol_list
, tree property_list
,
2646 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2648 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, cat_name
);
2649 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, class_name
);
2651 ltyp
= objc_method_list_ptr
;
2653 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
2655 expr
= convert (ltyp
, null_pointer_node
);
2656 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2659 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
2661 expr
= convert (ltyp
, null_pointer_node
);
2662 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2664 /* protocol_list = */
2665 ltyp
= build_pointer_type (objc_v2_protocol_template
);
2667 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
2669 expr
= convert (ltyp
, null_pointer_node
);
2670 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2672 ltyp
= objc_prop_list_ptr
;
2674 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
2676 expr
= convert (ltyp
, null_pointer_node
);
2677 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2679 return objc_build_constructor (type
, v
);
2682 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2685 generate_v2_category (struct imp_entry
*impent
)
2687 tree initlist
, cat_name_expr
, class_name_expr
;
2688 tree protocol_decl
, category
, props
, t
;
2689 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
2690 tree cat
= impent
->imp_context
;
2691 tree cat_decl
= impent
->class_decl
;
2695 loc
= DECL_SOURCE_LOCATION (cat_decl
);
2697 /* ??? not sure this is really necessary, the following references should
2698 force appropriate linkage linkage...
2699 -- but ... ensure a reference to the class... */
2700 t
= objc_v2_get_class_reference (CLASS_NAME (cat
));
2701 /* ... which we ignore so force it out.. */
2702 DECL_PRESERVE_P (t
) = 1;
2704 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat
)));
2705 class_name_expr
= create_extern_decl (objc_v2_class_template
, buf
);
2706 class_name_expr
= build_fold_addr_expr (class_name_expr
);
2708 cat_name_expr
= add_objc_string (CLASS_SUPER_NAME (cat
), class_names
);
2709 category
= lookup_category (impent
->imp_template
, CLASS_SUPER_NAME (cat
));
2711 if (category
&& CLASS_PROTOCOL_LIST (category
))
2713 generate_protocol_references (CLASS_PROTOCOL_LIST (category
));
2714 protocol_decl
= generate_v2_protocol_list (category
, cat
);
2717 protocol_decl
= NULL_TREE
;
2719 /* decl = update_var_decl(impent->class_decl); */
2721 props
= generate_v2_property_table (NULL_TREE
, cat
);
2723 if (CLASS_NST_METHODS (cat
))
2725 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryInstanceMethods_%s_%s",
2726 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
2727 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
2728 inst_methods
= generate_v2_dispatch_table (CLASS_NST_METHODS (cat
), buf
,
2732 if (CLASS_CLS_METHODS (cat
))
2734 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryClassMethods_%s_%s",
2735 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
2736 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
2737 class_methods
= generate_v2_dispatch_table (CLASS_CLS_METHODS (cat
), buf
,
2741 initlist
= build_v2_category_initializer (TREE_TYPE (cat_decl
),
2742 cat_name_expr
, class_name_expr
,
2743 inst_methods
, class_methods
,
2744 protocol_decl
, props
, loc
);
2746 finish_var_decl (cat_decl
, initlist
);
2747 impent
->class_decl
= cat_decl
;
2749 /* Add to list of pointers in __category_list section. */
2750 objc_v2_add_to_category_list (cat_decl
);
2751 if (has_load_impl (CLASS_CLS_METHODS (impent
->imp_context
)))
2752 objc_v2_add_to_nonlazy_category_list (cat_decl
);
2755 /* This routine declares a variable to hold the offset for ivar
2756 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
2758 typedef struct GTY(()) ivarref_entry
2764 static GTY (()) vec
<ivarref_entry
, va_gc
> *ivar_offset_refs
;
2767 ivar_offset_ref (tree class_name
, tree field_decl
)
2769 tree decl
, field_decl_id
;
2774 create_ivar_offset_name (buf
, class_name
, field_decl
);
2775 field_decl_id
= get_identifier (buf
);
2777 if (ivar_offset_refs
)
2781 FOR_EACH_VEC_ELT (*ivar_offset_refs
, count
, ref
)
2782 if (DECL_NAME (ref
->decl
) == field_decl_id
)
2786 /* Somewhat arbitrary initial provision. */
2787 vec_alloc (ivar_offset_refs
, 32);
2789 /* We come here if we don't find a match or at the start. */
2790 global_var
= (TREE_PUBLIC (field_decl
) || TREE_PROTECTED (field_decl
));
2792 decl
= create_global_decl (TREE_TYPE (size_zero_node
), buf
);
2794 decl
= create_hidden_decl (TREE_TYPE (size_zero_node
), buf
);
2796 /* Make sure it ends up in an ObjC section. */
2797 OBJCMETA (decl
, objc_meta
, meta_base
);
2800 e
.offset
= byte_position (field_decl
);
2801 vec_safe_push (ivar_offset_refs
, e
);
2805 /* This routine builds initializer-list needed to initialize 'struct
2806 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
2807 'struct ivar_t' and FIELD_DECL is list of ivars for the target
2811 build_v2_ivar_list_initializer (tree class_name
, tree type
, tree field_decl
)
2813 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2817 vec
<constructor_elt
, va_gc
> *ivar
= NULL
;
2821 /* Unnamed bitfields are ignored. */
2822 if (!DECL_NAME (field_decl
))
2824 field_decl
= DECL_CHAIN (field_decl
);
2829 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
2830 build_unary_op (input_location
,
2832 ivar_offset_ref (class_name
,
2836 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
2837 add_objc_string (DECL_NAME (field_decl
),
2841 id
= add_objc_string (encode_field_decl (field_decl
),
2843 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
, id
);
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
));
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
);
2865 return objc_build_constructor (build_array_type (type
, 0), inits
);
2873 struct iver_t list[count];
2878 build_v2_ivar_list_t_template (tree list_type
, int size
)
2880 tree objc_ivar_list_record
;
2881 tree decls
, *chain
= NULL
;
2884 objc_ivar_list_record
= objc_start_struct (NULL_TREE
);
2886 /* uint32 entsize; */
2887 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2890 add_field_decl (integer_type_node
, "count", &chain
);
2892 /* struct objc_ivar ivar_list[]; */
2893 add_field_decl (build_sized_array_type (list_type
, size
),
2896 objc_finish_struct (objc_ivar_list_record
, decls
);
2897 return objc_ivar_list_record
;
2900 /* This routine declares a static variable of type 'struct
2901 ivar_list_t' and initializes it. chain is the source of the data,
2902 name is the name for the var. attr is the meta-data section tag
2903 attribute. templ is the implementation template for the class. */
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
, va_gc
> *inits
= NULL
;
2910 int size
, ivar_t_size
;
2912 if (!chain
|| !name
|| !(size
= ivar_list_length (chain
)))
2915 generating_instance_variables
= 1;
2916 ivar_list_template
= build_v2_ivar_list_t_template (objc_v2_ivar_template
,
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;
2935 /* Routine to build initializer list to initialize objects of type
2939 build_v2_class_t_initializer (tree type
, tree isa
, tree superclass
,
2940 tree ro
, tree cache
, tree vtable
)
2942 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2945 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, isa
);
2948 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, superclass
);
2952 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, cache
);
2954 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, null_pointer_node
);
2958 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, vtable
);
2960 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, null_pointer_node
);
2963 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, ro
);
2965 return objc_build_constructor (type
, initlist
);
2968 /* Routine to build object of struct class_ro_t { ... }; */
2971 build_v2_class_ro_t_initializer (tree type
, tree name
,
2972 unsigned int flags
, unsigned int instanceStart
,
2973 unsigned int instanceSize
,
2975 tree baseMethods
, tree baseProtocols
,
2976 tree ivars
, tree property_list
)
2978 tree expr
, unsigned_char_star
, ltyp
;
2980 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2982 /* TODO: fish out the real location from somewhere. */
2983 loc
= UNKNOWN_LOCATION
;
2986 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
2987 build_int_cst (integer_type_node
, flags
));
2990 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
2991 build_int_cst (integer_type_node
, instanceStart
));
2994 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
2995 build_int_cst (integer_type_node
, instanceSize
));
2997 /* This ABI is currently only used on m64 NeXT. We always
2998 explicitly declare the alignment padding. */
2999 /* reserved, pads alignment. */
3000 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3001 build_int_cst (integer_type_node
, 0));
3004 unsigned_char_star
= build_pointer_type (unsigned_char_type_node
);
3008 expr
= convert (unsigned_char_star
, null_pointer_node
);
3009 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3012 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, default_conversion (name
));
3015 ltyp
= objc_method_list_ptr
;
3017 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, baseMethods
, 0));
3019 expr
= convert (ltyp
, null_pointer_node
);
3020 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3023 ltyp
= build_pointer_type (xref_tag (RECORD_TYPE
,
3024 get_identifier (UTAG_V2_PROTOCOL_LIST
)));
3026 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, baseProtocols
, 0));
3028 expr
= convert (ltyp
, null_pointer_node
);
3029 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3032 ltyp
= objc_v2_ivar_list_ptr
;
3034 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, ivars
, 0));
3036 expr
= convert (ltyp
, null_pointer_node
);
3037 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3039 /* TODO: We don't yet have the weak/strong stuff... */
3040 /* weakIvarLayout */
3041 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3042 convert (unsigned_char_star
, null_pointer_node
));
3045 ltyp
= objc_prop_list_ptr
;
3047 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
3049 expr
= convert (ltyp
, null_pointer_node
);
3050 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3051 return objc_build_constructor (type
, initlist
);
3054 static GTY (()) vec
<ident_data_tuple
, va_gc
> *ehtype_list
;
3056 /* Record a name as needing a catcher. */
3058 objc_v2_add_to_ehtype_list (tree name
)
3064 ident_data_tuple
*ref
;
3066 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3067 if (ref
->ident
== name
)
3068 return; /* Already entered. */
3071 /* Arbitrary initial count. */
3072 vec_alloc (ehtype_list
, 8);
3074 /* Not found, or new list. */
3077 vec_safe_push (ehtype_list
, e
);
3081 generate_v2_class_structs (struct imp_entry
*impent
)
3083 tree decl
, name_expr
, initlist
, protocol_decl
, metaclass_decl
, class_decl
;
3084 tree field
, firstIvar
, chain
;
3085 tree class_superclass_expr
, metaclass_superclass_expr
, props
;
3086 /* TODO: figure out how to compute this. */
3087 tree ivarLayout
= NULL_TREE
;
3088 tree my_super_id
= NULL_TREE
, root_expr
= NULL_TREE
;
3089 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
3090 tree inst_ivars
= NULL_TREE
, class_ivars
= NULL_TREE
;
3093 unsigned int instanceStart
, instanceSize
;
3094 unsigned int flags
= 0x01; /* RO_META */
3095 int cls_flags
= impent
->has_cxx_cdtors
? OBJC2_CLS_HAS_CXX_STRUCTORS
3098 class_decl
= impent
->class_decl
;
3099 metaclass_decl
= impent
->meta_decl
;
3100 loc
= DECL_SOURCE_LOCATION (class_decl
);
3102 DECL_EXTERNAL (class_decl
) = DECL_EXTERNAL (metaclass_decl
) = 0;
3103 TREE_PUBLIC (class_decl
) = TREE_PUBLIC (metaclass_decl
) = 1;
3105 gcc_assert (!CP_DECL_CONTEXT (class_decl
) || CP_DECL_CONTEXT (class_decl
) == global_namespace
);
3106 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl
) || CP_DECL_CONTEXT (metaclass_decl
) == global_namespace
);
3109 /* Generation of data for meta class. */
3110 my_super_id
= CLASS_SUPER_NAME (impent
->imp_template
);
3113 /* Compute reference to root's name. For a meta class, "isa" is
3114 a reference to the root class name. */
3115 tree my_root_id
= my_super_id
;
3116 tree my_root_int
, interface
;
3119 my_root_int
= lookup_interface (my_root_id
);
3121 if (my_root_int
&& CLASS_SUPER_NAME (my_root_int
))
3122 my_root_id
= CLASS_SUPER_NAME (my_root_int
);
3128 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3129 create extern if not already declared. */
3130 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
3131 IDENTIFIER_POINTER (CLASS_NAME (my_root_int
)));
3132 root_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3133 root_expr
= build_fold_addr_expr (root_expr
);
3135 /* Install class `isa' and `super' pointers at runtime. */
3136 interface
= lookup_interface (my_super_id
);
3137 gcc_assert (interface
);
3138 /* Similarly, for OBJC_CLASS_$_<interface>... */
3139 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s",
3140 IDENTIFIER_POINTER (CLASS_NAME (interface
)));
3141 class_superclass_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3142 class_superclass_expr
= build_fold_addr_expr (class_superclass_expr
);
3143 /* ... and for OBJC_METACLASS_$_<interface>. */
3144 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
3145 IDENTIFIER_POINTER (CLASS_NAME (interface
)));
3146 metaclass_superclass_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3147 metaclass_superclass_expr
= build_fold_addr_expr (metaclass_superclass_expr
);
3152 root_expr
= build_unary_op (loc
, ADDR_EXPR
, metaclass_decl
, 0);
3153 metaclass_superclass_expr
= build_unary_op (loc
, ADDR_EXPR
, class_decl
, 0);
3154 class_superclass_expr
= build_int_cst (NULL_TREE
, 0);
3155 flags
|= 0x02; /* RO_ROOT: it is also a root meta class. */
3158 if (CLASS_PROTOCOL_LIST (impent
->imp_template
))
3160 generate_protocol_references (CLASS_PROTOCOL_LIST (impent
->imp_template
));
3161 protocol_decl
= generate_v2_protocol_list (impent
->imp_template
,
3162 impent
->imp_context
);
3167 name_expr
= add_objc_string (CLASS_NAME (impent
->imp_template
),
3170 if (CLASS_CLS_METHODS (impent
->imp_context
))
3172 snprintf (buf
, BUFSIZE
, "_OBJC_ClassMethods_%s",
3173 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3175 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent
->imp_context
),
3176 buf
, meta_clac_meth
);
3179 instanceStart
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template
));
3181 /* Currently there are no class ivars and generation of class
3182 variables for the root of the inheritance has been removed. It
3183 causes multiple defines if there are two root classes in the
3184 link, because each will define its own identically-named offset
3187 class_ivars
= NULL_TREE
;
3188 /* TODO: Add total size of class variables when implemented. */
3189 instanceSize
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template
));
3191 /* So now build the META CLASS structs. */
3192 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3194 decl
= start_var_decl (objc_v2_class_ro_template
,
3195 newabi_append_ro (IDENTIFIER_POINTER
3196 (DECL_NAME (metaclass_decl
))));
3198 /* TODO: ivarLayout needs t be built. */
3200 build_v2_class_ro_t_initializer (TREE_TYPE (decl
), name_expr
,
3201 (flags
| cls_flags
), instanceStart
,
3202 instanceSize
, ivarLayout
,
3203 class_methods
, protocol_decl
,
3204 class_ivars
, NULL_TREE
);
3205 /* The ROs sit in the default const section. */
3206 OBJCMETA (decl
, objc_meta
, meta_base
);
3207 finish_var_decl (decl
, initlist
);
3209 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3211 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl
),
3213 metaclass_superclass_expr
,
3214 build_fold_addr_expr (decl
),
3215 build_fold_addr_expr (UOBJC_V2_CACHE_decl
),
3216 build_fold_addr_expr (UOBJC_V2_VTABLE_decl
));
3217 /* The class section attributes are set when they are created. */
3218 finish_var_decl (metaclass_decl
, initlist
);
3219 impent
->meta_decl
= metaclass_decl
;
3221 /* So now build the CLASS structs. */
3223 flags
= 0x0; /* ... */
3225 flags
|= 0x02; /* RO_ROOT: this is a root class */
3227 if (DECL_VISIBILITY (class_decl
) == VISIBILITY_HIDDEN
)
3228 flags
|= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3230 if (objc2_objc_exception_attr (impent
->imp_template
))
3231 flags
|= 0x20; /* RO_EXCEPTION */
3233 if (CLASS_NST_METHODS (impent
->imp_context
))
3235 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceMethods_%s",
3236 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3238 generate_v2_dispatch_table (CLASS_NST_METHODS (impent
->imp_context
),
3239 buf
, meta_clai_meth
);
3242 /* Sort out the ivars before we try to compute the class sizes. */
3243 if ((chain
= CLASS_IVARS (impent
->imp_template
)))
3245 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceIvars_%s",
3246 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3247 inst_ivars
= generate_v2_ivars_list (chain
, buf
, meta_clai_vars
,
3248 impent
->imp_template
);
3251 /* Compute instanceStart. */
3252 gcc_assert (CLASS_STATIC_TEMPLATE (impent
->imp_template
));
3253 field
= TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent
->imp_template
));
3254 if (my_super_id
&& field
&& TREE_CHAIN (field
))
3255 field
= TREE_CHAIN (field
);
3259 while (firstIvar
&& TREE_CODE (firstIvar
) != FIELD_DECL
)
3260 firstIvar
= TREE_CHAIN (firstIvar
);
3262 gcc_assert (inst_ivars
? (firstIvar
!= NULL_TREE
): true);
3264 /* Compute instanceSize. */
3265 while (field
&& TREE_CHAIN (field
)
3266 && TREE_CODE (TREE_CHAIN (field
)) == FIELD_DECL
)
3267 field
= TREE_CHAIN (field
);
3269 if (field
&& TREE_CODE (field
) == FIELD_DECL
)
3270 instanceSize
= int_byte_position (field
) * BITS_PER_UNIT
3271 + tree_to_shwi (DECL_SIZE (field
));
3274 instanceSize
/= BITS_PER_UNIT
;
3276 props
= generate_v2_property_table (NULL_TREE
, impent
->imp_context
);
3278 /* If the class has no ivars, instanceStart should be set to the
3279 superclass's instanceSize. */
3281 (inst_ivars
!= NULL_TREE
) ? (unsigned) int_byte_position (firstIvar
)
3284 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3285 decl
= start_var_decl (objc_v2_class_ro_template
,
3286 newabi_append_ro (IDENTIFIER_POINTER
3287 (DECL_NAME (class_decl
))));
3290 build_v2_class_ro_t_initializer (TREE_TYPE (decl
), name_expr
,
3291 (flags
| cls_flags
), instanceStart
,
3292 instanceSize
, ivarLayout
,
3293 inst_methods
, protocol_decl
,
3295 /* The ROs sit in the default const section. */
3296 OBJCMETA (decl
, objc_meta
, meta_base
);
3297 finish_var_decl (decl
, initlist
);
3299 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3300 initlist
= build_v2_class_t_initializer (TREE_TYPE (class_decl
),
3301 build_fold_addr_expr (metaclass_decl
),
3302 class_superclass_expr
,
3303 build_fold_addr_expr (decl
),
3304 build_fold_addr_expr (UOBJC_V2_CACHE_decl
),
3305 build_fold_addr_expr (UOBJC_V2_VTABLE_decl
));
3307 /* The class section attributes are set when they are created. */
3308 finish_var_decl (class_decl
, initlist
);
3309 impent
->class_decl
= class_decl
;
3311 objc_v2_add_to_class_list (class_decl
);
3312 if (has_load_impl (CLASS_CLS_METHODS (impent
->imp_context
)))
3313 objc_v2_add_to_nonlazy_class_list (class_decl
);
3315 if (flags
& 0x20) /* RO_EXCEPTION */
3316 objc_v2_add_to_ehtype_list (CLASS_NAME (impent
->imp_template
));
3319 /* This routine outputs the (ivar_reference_offset, offset)
3323 build_v2_ivar_offset_ref_table (void)
3328 if (!vec_safe_length (ivar_offset_refs
))
3331 FOR_EACH_VEC_ELT (*ivar_offset_refs
, count
, ref
)
3332 finish_var_decl (ref
->decl
, ref
->offset
);
3336 objc_generate_v2_next_metadata (void)
3338 struct imp_entry
*impent
;
3340 /* FIXME: Make sure that we generate no metadata if there is nothing
3343 gcc_assert (!objc_static_instances
); /* Not for NeXT */
3345 build_metadata_templates ();
3347 for (impent
= imp_list
; impent
; impent
= impent
->next
)
3349 /* If -gen-decls is present, Dump the @interface of each class.
3350 TODO: Dump the classes in the order they were found, rather
3351 than in reverse order as we are doing now. */
3352 if (flag_gen_declaration
)
3353 dump_interface (gen_declaration_file
, impent
->imp_context
);
3355 /* all of the following reference the string pool... */
3356 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
3357 generate_v2_class_structs (impent
);
3359 generate_v2_category (impent
);
3362 build_next_selector_translation_table ();
3363 build_v2_message_ref_translation_table ();
3365 /* This will add "Protocol" to the class refs. */
3366 generate_v2_protocols ();
3368 build_v2_classrefs_table ();
3369 build_v2_super_classrefs_table (/*metaclass= */false);
3370 build_v2_super_classrefs_table (/*metaclass= */true);
3372 build_v2_ivar_offset_ref_table ();
3374 build_v2_protocol_list_translation_table ();
3375 build_v2_protocol_list_address_table ();
3377 build_v2_address_table (class_list
, "_OBJC_ClassList$",
3378 meta_label_classlist
);
3379 build_v2_address_table (category_list
, "_OBJC_CategoryList$",
3380 meta_label_categorylist
);
3381 build_v2_address_table (nonlazy_class_list
, "_OBJC_NonLazyClassList$",
3382 meta_label_nonlazy_classlist
);
3383 build_v2_address_table (nonlazy_category_list
, "_OBJC_NonLazyCategoryList$",
3384 meta_label_nonlazy_categorylist
);
3386 /* Generate catch objects for eh, if any are needed. */
3387 build_v2_eh_catch_objects ();
3389 /* Emit the string table last. */
3390 generate_strings ();
3393 /* NOTE --- Output NeXT V2 Exceptions --- */
3395 static GTY(()) tree objc_v2_ehtype_template
;
3396 static GTY(()) tree next_v2_ehvtable_decl
;
3397 static GTY(()) tree next_v2_EHTYPE_id_decl
;
3400 build_v2_ehtype_template (void)
3402 tree decls
, *chain
= NULL
;
3403 objc_v2_ehtype_template
= objc_start_struct (get_identifier (UTAG_V2_EH_TYPE
));
3405 /* void *_objc_ehtype_vtable; */
3406 decls
= add_field_decl (ptr_type_node
, "_objc_ehtype_vtable_ptr", &chain
);
3408 /* const char *className; */
3409 add_field_decl (string_type_node
, "className", &chain
);
3411 /* struct class_t *const cls; */
3412 add_field_decl (build_pointer_type (objc_v2_class_template
), "cls", &chain
);
3414 objc_finish_struct (objc_v2_ehtype_template
, decls
);
3417 /* Template for the Objective-C family typeinfo type for ABI=2. This
3418 starts off the same as the gxx/cxx eh typeinfo.
3420 struct _objc_ehtype_t
3422 void *_objc_ehtype_vtable_ptr; - as per c++
3423 const char *className; - as per c++
3424 struct class_t *const cls;
3428 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3432 objc2_build_ehtype_initializer (tree name
, tree cls
)
3434 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3437 /* This is done the same way as c++, missing the two first entries
3438 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3439 runtime source about this so, perhaps, this will change at some
3441 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3442 if (!next_v2_ehvtable_decl
)
3444 next_v2_ehvtable_decl
=
3445 start_var_decl (ptr_type_node
, TAG_NEXT_EHVTABLE_NAME
);
3446 TREE_STATIC (next_v2_ehvtable_decl
) = 0;
3447 DECL_EXTERNAL (next_v2_ehvtable_decl
) = 1;
3448 TREE_PUBLIC (next_v2_ehvtable_decl
) = 1;
3450 addr
= build_fold_addr_expr_with_type (next_v2_ehvtable_decl
, ptr_type_node
);
3451 offs
= size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node
)));
3452 addr
= fold_build_pointer_plus (addr
, offs
);
3454 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, addr
);
3457 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, name
);
3460 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, cls
);
3462 return objc_build_constructor (objc_v2_ehtype_template
, initlist
);
3466 build_ehtype (tree name
, const char *eh_name
, bool weak
)
3468 tree name_expr
, class_name_expr
, ehtype_decl
, inits
;
3470 name_expr
= add_objc_string (name
, class_names
);
3471 /* Extern ref. for the class. ??? Maybe we can look this up
3474 create_extern_decl (objc_v2_class_template
,
3475 objc_build_internal_classname (name
, false));
3476 class_name_expr
= build_fold_addr_expr (class_name_expr
);
3477 ehtype_decl
= create_global_decl (objc_v2_ehtype_template
, eh_name
);
3479 DECL_WEAK (ehtype_decl
) = 1;
3480 inits
= objc2_build_ehtype_initializer (name_expr
, class_name_expr
);
3481 OBJCMETA (ehtype_decl
, objc_meta
, meta_ehtype
);
3482 finish_var_decl (ehtype_decl
, inits
);
3486 /* This routine returns TRUE if CLS or any of its super classes has
3487 __attribute__ ((objc_exception)). */
3490 objc2_objc_exception_attr (tree cls
)
3494 if (CLASS_HAS_EXCEPTION_ATTR (cls
))
3496 cls
= lookup_interface (CLASS_SUPER_NAME (cls
));
3503 is_implemented (tree name
)
3505 struct imp_entry
*t
;
3506 for (t
= imp_list
; t
; t
= t
->next
)
3507 if (TREE_CODE (t
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
3508 && CLASS_NAME (t
->imp_template
) == name
)
3514 /* We will build catch objects:
3515 for any type implemented here.
3516 for any type used in a catch that has no exception attribute. */
3517 static void build_v2_eh_catch_objects (void)
3520 ident_data_tuple
*ref
;
3522 if (!vec_safe_length (ehtype_list
))
3525 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3528 bool impl
= is_implemented (ref
->ident
);
3529 bool excpt
= objc2_objc_exception_attr (lookup_interface (ref
->ident
));
3530 snprintf (buf
, BUFSIZE
, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref
->ident
));
3532 /* The User says this class has a catcher already. */
3533 ref
->data
= create_extern_decl (objc_v2_ehtype_template
, buf
);
3535 /* Create a catcher, weak if it wasn't marked. */
3536 ref
->data
= build_ehtype (ref
->ident
, buf
, !excpt
);
3541 lookup_ehtype_ref (tree id
)
3544 ident_data_tuple
*ref
;
3546 if (!vec_safe_length (ehtype_list
))
3549 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3550 if (ref
->ident
== id
)
3555 /* This hook, called via lang_eh_runtime_type, generates a runtime
3556 object which is either the address of the 'OBJC_EHTYPE_$_class'
3557 object or address of external OBJC_EHTYPE_id object. */
3559 next_runtime_02_eh_type (tree type
)
3563 if (type
== error_mark_node
3564 /*|| errorcount || sorrycount*/)
3567 if (POINTER_TYPE_P (type
) && objc_is_object_id (TREE_TYPE (type
)))
3569 if (!next_v2_EHTYPE_id_decl
)
3571 /* This is provided by the Apple/NeXT libobjc.dylib so we
3572 need only to reference it. */
3573 next_v2_EHTYPE_id_decl
=
3574 start_var_decl (objc_v2_ehtype_template
, "OBJC_EHTYPE_id");
3575 DECL_EXTERNAL (next_v2_EHTYPE_id_decl
) = 1;
3576 TREE_PUBLIC (next_v2_EHTYPE_id_decl
) = 1;
3577 TREE_STATIC (next_v2_EHTYPE_id_decl
) = 0;
3579 return build_fold_addr_expr (next_v2_EHTYPE_id_decl
);
3582 if (!POINTER_TYPE_P (type
) || !TYPED_OBJECT (TREE_TYPE (type
)))
3585 /* This routine is also called for c++'s catch clause; in which
3586 case, we use c++'s typeinfo decl. */
3587 return build_eh_type_type (type
);
3589 error ("non-objective-c type '%T' cannot be caught", type
);
3594 t
= OBJC_TYPE_NAME (TREE_TYPE (type
));
3596 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3597 t
= lookup_ehtype_ref (t
);
3601 return build_fold_addr_expr (t
);
3604 return error_mark_node
;
3607 static GTY(()) tree objc_eh_personality_decl
;
3610 objc_eh_personality (void)
3612 if (!objc_eh_personality_decl
)
3613 objc_eh_personality_decl
= build_personality_function ("objc");
3614 return objc_eh_personality_decl
;
3617 /* NOTE --- interfaces --- */
3620 build_throw_stmt (location_t loc
, tree throw_expr
, bool rethrown
)
3624 /* We have a separate re-throw entry. */
3625 t
= build_function_call_vec (loc
, objc_rethrow_exception_decl
, NULL
, NULL
);
3628 /* Throw like the others... */
3629 vec
<tree
, va_gc
> *parms
;
3630 vec_alloc (parms
, 1);
3631 parms
->quick_push (throw_expr
);
3632 t
= build_function_call_vec (loc
, objc_exception_throw_decl
, parms
, 0);
3635 return add_stmt (t
);
3638 /* Build __builtin_eh_pointer. */
3641 objc_build_exc_ptr (struct objc_try_context
**x ATTRIBUTE_UNUSED
)
3644 t
= builtin_decl_explicit (BUILT_IN_EH_POINTER
);
3645 t
= build_call_expr (t
, 1, integer_zero_node
);
3646 return fold_convert (objc_object_type
, t
);
3649 static tree
begin_catch (struct objc_try_context
**cur_try_context
, tree type
,
3650 tree decl
, tree compound
, bool ellipsis ATTRIBUTE_UNUSED
)
3654 /* Record the data for the catch in the try context so that we can
3655 finalize it later. Ellipsis is signalled by a NULL entry. */
3657 t
= build_stmt (input_location
, CATCH_EXPR
, NULL_TREE
, compound
);
3659 t
= build_stmt (input_location
, CATCH_EXPR
, type
, compound
);
3660 (*cur_try_context
)->current_catch
= t
;
3662 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3663 t
= objc_build_exc_ptr (cur_try_context
);
3664 t
= convert (TREE_TYPE (decl
), t
);
3665 /* FIXME: location. */
3666 if (type
&& type
!= error_mark_node
)
3668 t
= build1(NOP_EXPR
, ptr_type_node
, t
);
3669 t
= build_function_call (input_location
, objc2_begin_catch_decl
,
3670 tree_cons (NULL_TREE
, t
, NULL_TREE
));
3672 /* We might want to build a catch object for this (if it's not
3674 if (POINTER_TYPE_P (type
)
3675 && !objc_is_object_id (TREE_TYPE (type
))
3676 && TYPED_OBJECT (TREE_TYPE (type
)))
3677 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type
)));
3679 return build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
3682 /* try { catch-body } finally { objc_end_catch (); } */
3684 finish_catch (struct objc_try_context
**cur_try_context
, tree curr_catch
)
3686 struct objc_try_context
*ct
;
3687 tree try_exp
, func
, *l
, t
;
3688 location_t loc
= (*cur_try_context
)->try_locus
;
3690 if (!curr_catch
|| curr_catch
== error_mark_node
)
3693 t
= CATCH_BODY (curr_catch
);
3694 if (TREE_CODE (t
) == BIND_EXPR
)
3696 /* Usual case of @catch (objc-expr). */
3697 objc_begin_try_stmt (loc
, BIND_EXPR_BODY (t
));
3698 BIND_EXPR_BODY (t
) = NULL_TREE
;
3699 l
= &BIND_EXPR_BODY (t
);
3703 /* NULL entry, meaning @catch (...). */
3704 objc_begin_try_stmt (loc
, t
);
3705 CATCH_BODY (curr_catch
) = NULL_TREE
;
3706 l
= &CATCH_BODY (curr_catch
);
3709 /* Pick up the new context we made in begin_try above... */
3710 ct
= *cur_try_context
;
3711 func
= build_function_call_vec (loc
, objc2_end_catch_decl
, NULL
, NULL
);
3712 append_to_statement_list (func
, &ct
->finally_body
);
3713 try_exp
= build_stmt (loc
, TRY_FINALLY_EXPR
, ct
->try_body
, ct
->finally_body
);
3714 *cur_try_context
= ct
->outer
;
3716 append_to_statement_list (try_exp
, l
);
3717 append_to_statement_list (curr_catch
, &((*cur_try_context
)->catch_list
));
3721 finish_try_stmt (struct objc_try_context
**cur_try_context
)
3723 struct objc_try_context
*c
= *cur_try_context
;
3724 tree stmt
= c
->try_body
;
3726 stmt
= build_stmt (c
->try_locus
, TRY_CATCH_EXPR
, stmt
, c
->catch_list
);
3727 if (c
->finally_body
)
3728 stmt
= build_stmt (c
->try_locus
, TRY_FINALLY_EXPR
, stmt
, c
->finally_body
);
3732 #include "gt-objc-objc-next-runtime-abi-02.h"