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