1 /* Next Runtime (ABI-2) private.
2 Copyright (C) 2011-2024 Free Software Foundation, Inc.
4 Contributed by Iain Sandoe and based, in part, on an implementation in
5 'branches/apple/trunk' contributed by Apple Computer Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
25 This version is intended to match (logically) the output of Apple's
30 #include "coretypes.h"
32 #include "stringpool.h"
36 #include "cp/cp-tree.h"
41 #include "langhooks.h"
42 #include "c-family/c-objc.h"
45 /* When building Objective-C++, we are not linking against the C front-end
46 and so need to replicate the C tree-construction functions in some way. */
48 #define OBJCP_REMAP_FUNCTIONS
49 #include "objcp-decl.h"
53 #include "tree-iterator.h"
56 #include "objc-runtime-hooks.h"
57 #include "objc-runtime-shared-support.h"
58 #include "objc-next-metadata-tags.h"
59 #include "objc-encoding.h"
61 /* ABI 2 Private definitions. */
62 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
64 #define TAG_GETCLASS "objc_getClass"
65 #define TAG_GETMETACLASS "objc_getMetaClass"
67 #define TAG_MSGSEND "objc_msgSend"
68 #define TAG_MSGSENDID "objc_msgSendId"
69 #define TAG_MSGSENDSUPER "objc_msgSendSuper2"
70 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
71 #define TAG_MSGSENDID_STRET "objc_msgSendId_stret"
72 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper2_stret"
74 #define USE_FIXUP_BEFORE 100600
75 #define WEAK_PROTOCOLS_AFTER 100700
76 #define TAG_FIXUP "_fixup"
79 #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
80 #define TAG_V2_EH_TYPE "objc_ehtype_t"
82 #define UTAG_V2_CLASS "_class_t"
83 #define UTAG_V2_CLASS_RO "_class_ro_t"
84 #define UTAG_V2_PROTOCOL "_protocol_t"
85 #define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
87 #define UTAG_V2_EH_TYPE "_objc_ehtype_t"
89 #define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
91 enum objc_v2_tree_index
99 OCTI_V2_IVAR_LIST_TEMPL
,
100 OCTI_V2_MESSAGE_REF_TEMPL
,
101 OCTI_V2_SUPER_MESSAGE_REF_TEMPL
,
103 OCTI_V2_MESSAGE_SELECTOR_TYPE
,
104 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE
,
106 OCTI_V2_SUPER_IMP_TYPE
,
111 OCTI_V2_PROPERTY_TEMPL
,
114 OCTI_V2_UMSG_FIXUP_DECL
,
115 OCTI_V2_UMSG_STRET_FIXUP_DECL
,
116 OCTI_V2_UMSG_ID_FIXUP_DECL
,
117 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL
,
118 OCTI_V2_UMSG_SUPER2_FIXUP_DECL
,
119 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL
,
121 /* Exceptions - related. */
122 OCTI_V2_BEGIN_CATCH_DECL
,
123 OCTI_V2_END_CATCH_DECL
,
124 OCTI_V2_RETHROW_DECL
,
129 #define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
130 #define objc_v2_class_ro_template \
131 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
132 #define objc_v2_category_template \
133 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
134 #define objc_v2_protocol_template \
135 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
137 /* struct message_ref_t */
138 #define objc_v2_message_ref_template \
139 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
141 #define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
143 /* struct super_message_ref_t */
144 #define objc_v2_super_message_ref_template \
145 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
147 /* struct message_ref_t* */
148 #define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
149 /* struct super_super_message_ref_t */
150 #define objc_v2_super_selector_type \
151 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
152 #define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
153 #define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
155 #define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
156 #define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
158 #define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
159 #define objc_v2_property_template \
160 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
164 /* objc_msgSend_fixup_rtp */
165 #define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
166 /* objc_msgSend_stret_fixup_rtp */
167 #define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
168 /* objc_msgSendId_fixup_rtp */
169 #define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
170 /* objc_msgSendId_stret_fixup_rtp */
171 #define umsg_id_stret_fixup_decl \
172 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
173 /* objc_msgSendSuper2_fixup_rtp */
174 #define umsg_id_super2_fixup_decl \
175 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
176 /* objc_msgSendSuper2_stret_fixup_rtp */
177 #define umsg_id_super2_stret_fixup_decl \
178 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
180 #define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
181 #define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
182 #define objc_rethrow_exception_decl \
183 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
185 /* The OCTI_V2_... enumeration itself is in above. */
186 static GTY(()) tree objc_v2_global_trees
[OCTI_V2_MAX
];
188 static void next_runtime_02_initialize (void);
190 static void build_v2_message_ref_templates (void);
191 static void build_v2_class_templates (void);
192 static void build_v2_super_template (void);
193 static void build_v2_category_template (void);
194 static void build_v2_protocol_template (void);
196 static tree
next_runtime_abi_02_super_superclassfield_id (void);
198 static tree
next_runtime_abi_02_class_decl (tree
);
199 static tree
next_runtime_abi_02_metaclass_decl (tree
);
200 static tree
next_runtime_abi_02_category_decl (tree
);
201 static tree
next_runtime_abi_02_protocol_decl (tree
);
202 static tree
next_runtime_abi_02_string_decl (tree
, const char *, string_section
);
204 static tree
next_runtime_abi_02_get_class_reference (tree
);
205 static tree
next_runtime_abi_02_build_selector_reference (location_t
, tree
, tree
);
206 static tree
next_runtime_abi_02_get_protocol_reference (location_t
, tree
);
207 static tree
next_runtime_abi_02_build_ivar_ref (location_t
, tree
, tree
);
208 static tree
next_runtime_abi_02_get_class_super_ref (location_t
, struct imp_entry
*, bool);
209 static tree
next_runtime_abi_02_get_category_super_ref (location_t
, struct imp_entry
*, bool);
211 static tree
next_runtime_abi_02_receiver_is_class_object (tree
);
212 static void next_runtime_abi_02_get_arg_type_list_base (vec
<tree
, va_gc
> **,
214 static tree
next_runtime_abi_02_build_objc_method_call (location_t
, tree
, tree
,
215 tree
, tree
, tree
, int);
216 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
217 static tree
next_runtime_abi_02_build_const_string_constructor (location_t
, tree
, int);
219 static tree
create_extern_decl (tree
, const char *);
221 static void objc_generate_v2_next_metadata (void);
222 static bool objc2_objc_exception_attr (tree
);
224 /* void build_v2_protocol_reference (tree);*/
225 static void build_v2_ehtype_template (void);
226 static void build_v2_eh_catch_objects (void);
227 static tree
next_runtime_02_eh_type (tree
);
228 static tree
objc_eh_personality (void);
229 static tree
build_throw_stmt (location_t
, tree
, bool);
230 static tree
objc_build_exc_ptr (struct objc_try_context
**);
231 static tree
begin_catch (struct objc_try_context
**, tree
, tree
, tree
, bool);
232 static void finish_catch (struct objc_try_context
**, tree
);
233 static tree
finish_try_stmt (struct objc_try_context
**);
235 /* TODO: Use an objc-map. */
236 static GTY ((length ("SIZEHASHTABLE"))) hash
*extern_names
;
239 objc_next_runtime_abi_02_init (objc_runtime_hooks
*rthooks
)
241 extern_names
= ggc_cleared_vec_alloc
<hash
> (SIZEHASHTABLE
);
243 if (flag_objc_sjlj_exceptions
)
245 inform (UNKNOWN_LOCATION
,
246 "%<-fobjc-sjlj-exceptions%> is ignored for "
247 "%<-fnext-runtime%> when %<-fobjc-abi-version%> "
249 flag_objc_sjlj_exceptions
= 0;
252 /* NeXT ABI 2 is intended to default to checking for nil receivers. */
253 if (! OPTION_SET_P (flag_objc_nilcheck
))
254 flag_objc_nilcheck
= 1;
256 rthooks
->initialize
= next_runtime_02_initialize
;
257 rthooks
->default_constant_string_class_name
= DEF_CONSTANT_STRING_CLASS_NAME
;
258 rthooks
->tag_getclass
= TAG_GETCLASS
;
259 rthooks
->super_superclassfield_ident
= next_runtime_abi_02_super_superclassfield_id
;
261 rthooks
->class_decl
= next_runtime_abi_02_class_decl
;
262 rthooks
->metaclass_decl
= next_runtime_abi_02_metaclass_decl
;
263 rthooks
->category_decl
= next_runtime_abi_02_category_decl
;
264 rthooks
->protocol_decl
= next_runtime_abi_02_protocol_decl
;
265 rthooks
->string_decl
= next_runtime_abi_02_string_decl
;
267 rthooks
->get_class_reference
= next_runtime_abi_02_get_class_reference
;
268 rthooks
->build_selector_reference
= next_runtime_abi_02_build_selector_reference
;
269 rthooks
->get_protocol_reference
= next_runtime_abi_02_get_protocol_reference
;
270 rthooks
->build_ivar_reference
= next_runtime_abi_02_build_ivar_ref
;
271 rthooks
->get_class_super_ref
= next_runtime_abi_02_get_class_super_ref
;
272 rthooks
->get_category_super_ref
= next_runtime_abi_02_get_category_super_ref
;
274 rthooks
->receiver_is_class_object
= next_runtime_abi_02_receiver_is_class_object
;
275 rthooks
->get_arg_type_list_base
= next_runtime_abi_02_get_arg_type_list_base
;
276 rthooks
->build_objc_method_call
= next_runtime_abi_02_build_objc_method_call
;
278 rthooks
->setup_const_string_class_decl
=
279 next_runtime_abi_02_setup_const_string_class_decl
;
280 rthooks
->build_const_string_constructor
=
281 next_runtime_abi_02_build_const_string_constructor
;
283 rthooks
->build_throw_stmt
= build_throw_stmt
;
284 rthooks
->build_exc_ptr
= objc_build_exc_ptr
;
285 rthooks
->begin_catch
= begin_catch
;
286 rthooks
->finish_catch
= finish_catch
;
287 rthooks
->finish_try_stmt
= finish_try_stmt
;
289 rthooks
->generate_metadata
= objc_generate_v2_next_metadata
;
293 /* We need a way to convey what kind of meta-data are represented by a given
294 variable, since each type is expected (by the runtime) to be found in a
295 specific named section. The solution must be usable with LTO.
297 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
298 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
299 identification attributes in the front end. The back-end may choose to act
300 on these as it requires. */
303 next_runtime_abi_02_init_metadata_attributes (void)
306 objc_meta
= get_identifier ("OBJC2META");
309 meta_base
= get_identifier ("V2_BASE");
311 meta_class
= get_identifier ("G2_CLAS");
312 meta_metaclass
= get_identifier ("G2_META");
313 meta_category
= meta_base
;
314 meta_protocol
= get_identifier ("V2_PCOL");
317 meta_clai_vars
= meta_base
;
323 meta_proto_cls_meth
=
324 meta_proto_nst_meth
= meta_base
;
327 meta_catg_prot
= meta_base
;
329 meta_sel_refs
= get_identifier ("V2_SRFS");
331 meta_class_name
= get_identifier ("V2_CNAM");
332 meta_meth_name
= get_identifier ("V2_MNAM");
334 meta_meth_type
= get_identifier ("V2_MTYP");
335 meta_prop_name_attr
= get_identifier ("V2_STRG");
337 meta_mref
= get_identifier ("V2_MREF");
338 meta_class_ref
= get_identifier ("V2_CLRF");
339 meta_superclass_ref
= get_identifier ("V2_SURF");
341 meta_label_classlist
= get_identifier ("V2_CLAB");
342 meta_label_nonlazy_classlist
= get_identifier ("V2_NLCL");
343 meta_label_categorylist
= get_identifier ("V2_CALA");
344 meta_label_nonlazy_categorylist
= get_identifier ("V2_NLCA");
346 meta_label_protocollist
= get_identifier ("V2_PLST");
347 meta_proto_ref
= get_identifier ("V2_PRFS");
349 meta_info
= get_identifier ("V2_INFO");
351 meta_ehtype
= get_identifier ("V2_EHTY");
353 meta_const_str
= get_identifier ("V2_CSTR");
355 meta_ivar_ref
= get_identifier ("V2_IVRF");
358 static void next_runtime_02_initialize (void)
362 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
364 if (!OPTION_SET_P (flag_objc_call_cxx_cdtors
))
365 global_options
.x_flag_objc_call_cxx_cdtors
= 1;
368 /* Set up attributes to be attached to the meta-data so that they
369 will be placed in the correct sections. */
370 next_runtime_abi_02_init_metadata_attributes ();
372 /* `struct objc_selector *' */
373 objc_selector_type
= build_pointer_type (xref_tag (RECORD_TYPE
,
374 get_identifier (TAG_SELECTOR
)));
377 type
= lang_hooks
.decls
.pushdecl (build_decl (input_location
,
380 objc_selector_type
));
381 suppress_warning (type
);
383 /* IMP : id (*) (id, _message_ref_t*, ...)
384 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
385 objc_v2_selector_type. */
386 build_v2_message_ref_templates ();
388 objc_v2_ivar_list_ptr
=
389 build_pointer_type (xref_tag (RECORD_TYPE
,
390 get_identifier ("_ivar_list_t")));
393 build_pointer_type (xref_tag (RECORD_TYPE
,
394 get_identifier ("_prop_list_t")));
396 build_v2_class_templates ();
397 build_v2_super_template ();
398 build_v2_protocol_template ();
399 build_v2_category_template ();
401 bool fixup_p
= flag_next_runtime
< USE_FIXUP_BEFORE
;
404 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
405 type
= build_varargs_function_type_list (objc_object_type
,
407 objc_v2_selector_type
,
412 /* id objc_msgSendXXXX (id, SEL, ...); */
413 type
= build_varargs_function_type_list (objc_object_type
,
418 const char *fnam
= fixup_p
? TAG_MSGSEND TAG_FIXUP
: TAG_MSGSEND
;
419 umsg_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
421 TREE_NOTHROW (umsg_fixup_decl
) = 0;
423 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
424 fnam
= fixup_p
? TAG_MSGSEND_STRET TAG_FIXUP
: TAG_MSGSEND_STRET
;
425 umsg_stret_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
427 TREE_NOTHROW (umsg_stret_fixup_decl
) = 0;
429 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
430 fnam
= fixup_p
? TAG_MSGSENDID TAG_FIXUP
: TAG_MSGSENDID
;
431 umsg_id_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
433 TREE_NOTHROW (umsg_id_fixup_decl
) = 0;
435 /* id objc_msgSendId_stret_fixup_rtp (id, struct message_ref_t*, ...); */
436 fnam
= fixup_p
? TAG_MSGSENDID_STRET TAG_FIXUP
: TAG_MSGSENDID_STRET
;
437 umsg_id_stret_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
439 TREE_NOTHROW (umsg_id_stret_fixup_decl
) = 0;
441 /* id objc_msgSendSuper2_fixup_rtp
442 (struct objc_super *, struct message_ref_t*, ...); */
443 type
= build_varargs_function_type_list (objc_object_type
,
445 objc_v2_super_selector_type
,
447 fnam
= fixup_p
? TAG_MSGSENDSUPER TAG_FIXUP
: TAG_MSGSENDSUPER
;
448 umsg_id_super2_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
450 TREE_NOTHROW (umsg_id_super2_fixup_decl
) = 0;
452 /* id objc_msgSendSuper2_stret_fixup_rtp
453 (struct objc_super *, struct message_ref_t*, ...); */
454 fnam
= fixup_p
? TAG_MSGSENDSUPER_STRET TAG_FIXUP
: TAG_MSGSENDSUPER_STRET
;
455 umsg_id_super2_stret_fixup_decl
= add_builtin_function (fnam
, type
, 0,
458 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl
) = 0;
460 /* Present in the library, but unused by the FE. */
461 /* Protocol *objc_getProtocol (const char *)
462 type = build_function_type_list (objc_protocol_type,
463 const_string_type_node,
465 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
466 type, 0, NOT_BUILT_IN,
468 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
470 UOBJC_V2_CACHE_decl
= create_extern_decl (ptr_type_node
,
471 "_objc_empty_cache");
473 UOBJC_V2_VTABLE_decl
= create_extern_decl (objc_v2_imp_type
,
474 "_objc_empty_vtable");
476 /* id objc_getClass (const char *); */
477 type
= build_function_type_list (objc_object_type
,
478 const_string_type_node
,
480 objc_get_class_decl
= add_builtin_function (TAG_GETCLASS
,
481 type
, 0, NOT_BUILT_IN
,
484 /* id objc_getMetaClass (const char *); */
485 objc_get_meta_class_decl
= add_builtin_function (TAG_GETMETACLASS
,
486 type
, 0, NOT_BUILT_IN
,
489 /* This is the type of all of the following functions
490 objc_copyStruct(). */
491 type
= build_function_type_list (void_type_node
,
498 /* Declare the following function:
500 objc_copyStruct (void *destination, const void *source,
501 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
502 objc_copyStruct_decl
= add_builtin_function ("objc_copyStruct",
503 type
, 0, NOT_BUILT_IN
,
505 TREE_NOTHROW (objc_copyStruct_decl
) = 0;
506 objc_getPropertyStruct_decl
= NULL_TREE
;
507 objc_setPropertyStruct_decl
= NULL_TREE
;
509 gcc_checking_assert (!flag_objc_sjlj_exceptions
);
511 /* Although we warn that fobjc-exceptions is required for exceptions
512 code, we carry on and create it anyway. */
514 /* This can be required, even when exceptions code is not present,
515 when an __attribute__((objc_exception)) is applied to a
517 build_v2_ehtype_template ();
519 /* void * objc_begin_catch (void *) */
520 type
= build_function_type_list (ptr_type_node
,
521 ptr_type_node
, NULL_TREE
);
523 objc2_begin_catch_decl
= add_builtin_function ("objc_begin_catch",
524 type
, 0, NOT_BUILT_IN
,
526 TREE_NOTHROW (objc2_begin_catch_decl
) = 0;
528 /* void objc_end_catch () */
529 type
= build_function_type_list (void_type_node
, NULL_TREE
);
530 objc2_end_catch_decl
= add_builtin_function ("objc_end_catch",
531 type
, 0, NOT_BUILT_IN
,
533 TREE_NOTHROW (objc2_end_catch_decl
) = 0;
535 /* void objc_exception_rethrow (void) */
536 objc_rethrow_exception_decl
=
537 add_builtin_function ("objc_exception_rethrow",
538 type
, 0, NOT_BUILT_IN
,
540 TREE_NOTHROW (objc_rethrow_exception_decl
) = 0;
541 using_eh_for_cleanups ();
542 lang_hooks
.eh_runtime_type
= next_runtime_02_eh_type
;
543 lang_hooks
.eh_personality
= objc_eh_personality
;
546 /* NOTE --- templates --- */
548 /* Set 'objc_v2_message_ref_template' to the data type node for
549 'struct _message_ref_t'. This needs to be done just once per
550 compilation. Also Set 'objc_v2_super_message_ref_template' to data
551 type node for 'struct _super_message_ref_t'. */
553 /* struct _message_ref_t
558 where IMP is: id (*) (id, _message_ref_t*, ...)
561 /* struct _super_message_ref_t
566 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
570 build_v2_message_ref_templates (void)
572 tree ptr_message_ref_t
;
573 tree decls
, *chain
= NULL
;
575 /* struct _message_ref_t {...} */
576 objc_v2_message_ref_template
=
577 objc_start_struct (get_identifier ("_message_ref_t"));
581 build_pointer_type (xref_tag (RECORD_TYPE
,
582 get_identifier ("_message_ref_t")));
585 build_pointer_type (build_function_type_list
591 decls
= add_field_decl (objc_v2_imp_type
, "messenger", &chain
);
594 add_field_decl (objc_selector_type
, "name", &chain
);
596 objc_finish_struct (objc_v2_message_ref_template
, decls
);
598 objc_v2_selector_type
= build_pointer_type (objc_v2_message_ref_template
);
601 /* struct _super_message_ref_t {...} */
602 objc_v2_super_message_ref_template
=
603 objc_start_struct (get_identifier ("_super_message_ref_t"));
605 /* SUPER_IMP messenger; */
606 ptr_message_ref_t
= build_pointer_type
607 (xref_tag (RECORD_TYPE
,
608 get_identifier ("_super_message_ref_t")));
610 objc_v2_super_imp_type
=
611 build_pointer_type (build_function_type_list
617 add_field_decl (objc_v2_super_imp_type
, "messenger", &chain
);
620 add_field_decl (objc_selector_type
, "name", &chain
);
622 objc_finish_struct (objc_v2_super_message_ref_template
, decls
);
623 objc_v2_super_selector_type
=
624 build_pointer_type (objc_v2_super_message_ref_template
);
627 /* Build following types which represent each class implementation.
631 uint32_t const flags;
632 uint32_t const instanceStart;
633 uint32_t const instanceSize;
635 uint32_t const reserved;
637 const uint8_t * const ivarLayout;
638 const char *const name;
639 const struct method_list_t * const baseMethods;
640 const struct objc_protocol_list *const baseProtocols;
641 const struct ivar_list_t *const ivars;
642 const uint8_t * const weakIvarLayout;
643 const struct _prop_list_t * const properties;
649 struct class_t *superclass;
653 ...When this is active - it will point to a rw version, but
654 when we build the meta-data we point it to the ro...
655 struct class_ro_t *data;
661 build_v2_class_templates (void)
664 tree decls
, *chain
= NULL
;
666 /* struct class_ro_t {...} */
667 objc_v2_class_ro_template
=
668 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO
));
670 /* uint32_t const flags; */
671 decls
= add_field_decl (integer_type_node
, "flags", &chain
);
673 /* uint32_t const instanceStart; */
674 add_field_decl (integer_type_node
, "instanceStart", &chain
);
676 /* uint32_t const instanceSize; */
677 add_field_decl (integer_type_node
, "instanceSize", &chain
);
679 /* This ABI is currently only used on m64 NeXT. We always
680 explicitly declare the alignment padding. */
681 /* uint32_t const reserved; */
682 add_field_decl (integer_type_node
, "reserved", &chain
);
684 /* const uint8_t * const ivarLayout; */
685 cnst_strg_type
= build_pointer_type (unsigned_char_type_node
);
686 add_field_decl (cnst_strg_type
, "ivarLayout", &chain
);
688 /* const char *const name; */
689 add_field_decl (string_type_node
, "name", &chain
);
691 /* const struct method_list_t * const baseMethods; */
692 add_field_decl (objc_method_list_ptr
, "baseMethods", &chain
);
694 /* const struct objc_protocol_list *const baseProtocols; */
695 add_field_decl (build_pointer_type
696 (xref_tag (RECORD_TYPE
,
697 get_identifier (UTAG_V2_PROTOCOL_LIST
))),
698 "baseProtocols", &chain
);
700 /* const struct ivar_list_t *const ivars; */
701 add_field_decl (objc_v2_ivar_list_ptr
, "ivars", &chain
);
703 /* const uint8_t * const weakIvarLayout; */
704 add_field_decl (cnst_strg_type
, "weakIvarLayout", &chain
);
706 /* struct _prop_list_t * baseProperties; */
707 add_field_decl (objc_prop_list_ptr
, "baseProperties", &chain
);
709 objc_finish_struct (objc_v2_class_ro_template
, decls
);
712 /* struct class_t {...} */
713 objc_v2_class_template
=
714 objc_start_struct (get_identifier (UTAG_V2_CLASS
));
716 /* struct class_t *isa; */
717 decls
= add_field_decl (build_pointer_type (objc_v2_class_template
),
720 /* struct class_t * const superclass; */
721 add_field_decl (build_pointer_type (objc_v2_class_template
),
722 "superclass", &chain
);
725 add_field_decl (build_pointer_type (void_type_node
), "cache", &chain
);
728 add_field_decl (build_pointer_type (objc_v2_imp_type
), "vtable", &chain
);
730 /* struct class_ro_t *ro; */
731 add_field_decl (build_pointer_type (objc_v2_class_ro_template
), "ro", &chain
);
733 objc_finish_struct (objc_v2_class_template
, decls
);
736 /* struct _objc_super
738 struct _objc_object *self;
742 build_v2_super_template (void)
744 tree decls
, *chain
= NULL
;
746 objc_super_template
= objc_start_struct (get_identifier (UTAG_SUPER
));
748 /* struct _objc_object *self; */
749 decls
= add_field_decl (objc_object_type
, "self", &chain
);
752 add_field_decl (objc_class_type
, "cls", &chain
);
754 objc_finish_struct (objc_super_template
, decls
);
760 const char * const protocol_name;
761 const struct protocol_list_t * const protocol_list;
762 const struct method_list_t * const instance_methods;
763 const struct method_list_t * const class_methods;
764 const struct method_list_t * optionalInstanceMethods;
765 const struct method_list_t * optionalClassMethod
766 const struct _prop_list_t * const properties;
768 const uint32_t flags;
769 const char ** extended_method_types;
770 const char * demangled_name;
771 const struct _prop_list_t * class_properties;
775 build_v2_protocol_template (void)
777 tree decls
, *chain
= NULL
;
779 objc_v2_protocol_template
=
780 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL
));
783 decls
= add_field_decl (objc_object_type
, "isa", &chain
);
785 /* char *protocol_name; */
786 add_field_decl (string_type_node
, "protocol_name", &chain
);
788 /* const struct protocol_list_t * const protocol_list; */
789 add_field_decl (build_pointer_type (objc_v2_protocol_template
),
790 "protocol_list", &chain
);
792 /* const struct method_list_t * const instance_methods; */
793 add_field_decl (objc_method_proto_list_ptr
, "instance_methods", &chain
);
795 /* const struct method_list_t * const class_methods; */
796 add_field_decl (objc_method_proto_list_ptr
, "class_methods", &chain
);
798 /* const struct method_list_t * optionalInstanceMethods; */
799 add_field_decl (objc_method_proto_list_ptr
, "optionalInstanceMethods", &chain
);
801 /* const struct method_list_t * optionalClassMethods; */
802 add_field_decl (objc_method_proto_list_ptr
, "optionalClassMethods", &chain
);
804 /* struct _prop_list_t * properties; */
805 add_field_decl (objc_prop_list_ptr
, "properties", &chain
);
807 /* const uint32_t size; */
808 add_field_decl (integer_type_node
, "size", &chain
);
810 /* const uint32_t flags; */
811 add_field_decl (integer_type_node
, "flags", &chain
);
813 /* const char **extendedMethodTypes; */
814 tree ptr_to_ptr_to_char
= build_pointer_type (string_type_node
);
815 add_field_decl (ptr_to_ptr_to_char
, "extended_method_types", &chain
);
817 /* const char *demangledName; */
818 add_field_decl (string_type_node
, "demangled_name", &chain
);
820 /* const struct _prop_list_t *class_properties; */
821 add_field_decl (objc_prop_list_ptr
, "class_properties", &chain
);
823 objc_finish_struct (objc_v2_protocol_template
, decls
);
826 /* Build type for a category:
829 const char * const name;
830 struct class_t *const cls;
831 const struct method_list_t * const instance_methods;
832 const struct method_list_t * const class_methods;
833 const struct protocol_list_t * const protocols;
834 const struct _prop_list_t * const properties;
839 build_v2_category_template (void)
841 tree decls
, *chain
= NULL
;
843 objc_v2_category_template
=
844 objc_start_struct (get_identifier ("_category_t"));
847 decls
= add_field_decl (string_type_node
, "name", &chain
);
849 /* struct class_t *const cls; */
850 add_field_decl (build_pointer_type (objc_v2_class_template
), "cls", &chain
);
852 /* struct method_list_t *instance_methods; */
853 add_field_decl (objc_method_list_ptr
, "instance_methods", &chain
);
855 /* struct method_list_t *class_methods; */
856 add_field_decl (objc_method_list_ptr
, "class_methods", &chain
);
858 /* struct protocol_list_t *protocol_list; */
859 add_field_decl (build_pointer_type (objc_v2_protocol_template
),
860 "protocol_list", &chain
);
862 /* struct _prop_list_t * properties; */
863 add_field_decl (objc_prop_list_ptr
, "properties", &chain
);
865 objc_finish_struct (objc_v2_category_template
, decls
);
868 /* NOTE --- Decls, Identifiers, Names etc. --- */
870 /* This routine is given a name and returns a matching extern variable
874 hash_name_lookup (hash
*hashlist
, tree name
)
878 target
= hashlist
[IDENTIFIER_HASH_VALUE (name
) % SIZEHASHTABLE
];
882 if (name
== DECL_NAME (target
->key
))
885 target
= target
->next
;
890 /* This routine is given an extern variable and enters it in its hash
891 table. Note that hashing is done on its inner IDENTIFIER_NODE
895 hash_name_enter (hash
*hashlist
, tree id
)
898 int slot
= IDENTIFIER_HASH_VALUE (DECL_NAME (id
)) % SIZEHASHTABLE
;
900 obj
= ggc_alloc
<hashed_entry
> ();
902 obj
->next
= hashlist
[slot
];
905 hashlist
[slot
] = obj
; /* append to front */
908 /* Create a declaration "extern <type> <name>;"
909 The var will need to be finalized (e.g. by calling finish_var_decl()). */
912 create_extern_decl (tree type
, const char *name
)
914 tree id
= get_identifier (name
);
915 tree var
= hash_name_lookup (extern_names
, id
);
919 var
= start_var_decl (type
, name
);
920 TREE_STATIC (var
) = 0;
921 DECL_EXTERNAL (var
) = 1;
922 TREE_PUBLIC (var
) = 1;
923 hash_name_enter (extern_names
, var
);
927 /* Create a globally visible definition for variable NAME of a given TYPE. The
928 finish_var_decl() routine will need to be called on it afterwards. */
930 create_global_decl (tree type
, const char *name
, bool is_def
= false);
933 create_global_decl (tree type
, const char *name
, bool is_def
)
935 tree id
= get_identifier (name
);
936 tree var
= hash_name_lookup (extern_names
, id
);
941 var
= start_var_decl (type
, name
);
942 hash_name_enter (extern_names
, var
);
946 DECL_EXTERNAL (var
) = 0;
947 TREE_STATIC (var
) = 1;
949 TREE_PUBLIC (var
) = 1;
953 /* Create a symbol with __attribute__ ((visibility ("hidden")))
954 attribute (private extern). */
956 create_hidden_decl (tree type
, const char *name
, bool is_def
= false);
959 create_hidden_decl (tree type
, const char *name
, bool is_def
)
961 tree decl
= create_global_decl (type
, name
, is_def
);
962 DECL_VISIBILITY (decl
) = VISIBILITY_HIDDEN
;
963 DECL_VISIBILITY_SPECIFIED (decl
) = 1;
967 /* Irritatingly, we have a different superclass field name for ABI=2. */
968 /* PS/TODO: The field name does not matter, it is only used internally
969 by the compiler. We can rename it to whatever we want. ;-) */
972 next_runtime_abi_02_super_superclassfield_id (void)
974 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
975 most look it once at startup then always return it. */
976 if (!super_superclassfield_id
)
977 super_superclassfield_id
= get_identifier ("cls");
978 return super_superclassfield_id
;
982 next_runtime_abi_02_class_decl (tree klass
)
986 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s",
987 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
988 /* ObjC2 classes are extern visible. */
989 decl
= create_global_decl (objc_v2_class_template
, buf
);
990 OBJCMETA (decl
, objc_meta
, meta_class
);
995 next_runtime_abi_02_metaclass_decl (tree klass
)
999 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
1000 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
1001 /* ObjC2 classes are extern visible. */
1002 decl
= create_global_decl (objc_v2_class_template
, buf
);
1003 OBJCMETA (decl
, objc_meta
, meta_metaclass
);
1008 next_runtime_abi_02_category_decl (tree klass
)
1012 snprintf (buf
, BUFSIZE
, "_OBJC_Category_%s_%s",
1013 IDENTIFIER_POINTER (CLASS_NAME (klass
)),
1014 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass
)));
1015 decl
= start_var_decl (objc_v2_category_template
, buf
);
1016 OBJCMETA (decl
, objc_meta
, meta_category
);
1021 next_runtime_abi_02_protocol_decl (tree p
)
1026 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
1027 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
1028 IDENTIFIER_POINTER (PROTOCOL_NAME (p
)));
1029 if (flag_next_runtime
>= WEAK_PROTOCOLS_AFTER
)
1031 decl
= create_hidden_decl (objc_v2_protocol_template
, buf
);
1032 DECL_WEAK (decl
) = true;
1035 decl
= start_var_decl (objc_v2_protocol_template
, buf
);
1036 OBJCMETA (decl
, objc_meta
, meta_protocol
);
1037 DECL_PRESERVE_P (decl
) = 1;
1042 next_runtime_abi_02_string_decl (tree type
, const char *name
, string_section where
)
1044 tree var
= start_var_decl (type
, name
);
1048 OBJCMETA (var
, objc_meta
, meta_class_name
);
1050 case meth_var_names
:
1051 OBJCMETA (var
, objc_meta
, meta_meth_name
);
1053 case meth_var_types
:
1054 OBJCMETA (var
, objc_meta
, meta_meth_type
);
1056 case prop_names_attr
:
1057 OBJCMETA (var
, objc_meta
, meta_prop_name_attr
);
1060 OBJCMETA (var
, objc_meta
, meta_base
);
1066 /* NOTE --- entry --- */
1068 struct GTY(()) ident_data_tuple
{
1073 /* This routine creates a file scope static variable of type 'Class'
1074 to hold the address of a class. */
1077 build_v2_class_reference_decl (tree ident
)
1082 snprintf (buf
, BUFSIZE
, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident
));
1083 decl
= start_var_decl (objc_class_type
, buf
);
1084 OBJCMETA (decl
, objc_meta
, meta_class_ref
);
1088 /* This routine builds a class refs entry for each class name used.
1089 Initially, a (static-ref, IDENT) tuple is added to the list. The
1090 ident is replaced with address of the class metadata (of type
1091 'Class') in the output routine. */
1093 static GTY (()) vec
<ident_data_tuple
, va_gc
> *classrefs
;
1096 objc_v2_get_class_reference (tree ident
)
1103 ident_data_tuple
*ref
;
1104 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
1106 if (ref
->ident
== ident
)
1109 ref
->data
= build_v2_class_reference_decl (ident
);
1115 /* Somewhat arbitrary initial provision. */
1116 vec_alloc (classrefs
, 16);
1118 /* We come here if we don't find the entry - or if the table was yet
1120 decl
= build_v2_class_reference_decl (ident
);
1123 vec_safe_push (classrefs
, e
);
1128 next_runtime_abi_02_get_class_reference (tree ident
)
1130 if (!flag_zero_link
)
1131 return objc_v2_get_class_reference (ident
);
1134 /* We fall back to using objc_getClass (). */
1135 vec
<tree
, va_gc
> *v
;
1138 /* ??? add_class_reference (ident); - is pointless, since the
1139 system lib does not export the equivalent symbols. Maybe we
1140 need to build a class ref anyway. */
1141 t
= my_build_string_pointer (IDENTIFIER_LENGTH (ident
) + 1,
1142 IDENTIFIER_POINTER (ident
));
1144 t
= build_function_call_vec (input_location
, vNULL
, objc_get_class_decl
,
1151 /* Used by build_function_type_for_method. Append the types for
1152 receiver & _cmd at the start of a method argument list to ARGTYPES.
1153 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1154 trying to define a method or call one. SUPERFLAG says this is for a
1155 send to super. METH may be NULL, in the case that there is no
1159 next_runtime_abi_02_get_arg_type_list_base (vec
<tree
, va_gc
> **argtypes
,
1160 tree meth
, int context
,
1166 receiver_type
= objc_super_type
;
1167 else if (context
== METHOD_DEF
&& TREE_CODE (meth
) == INSTANCE_METHOD_DECL
)
1168 receiver_type
= objc_instance_type
;
1170 receiver_type
= objc_object_type
;
1172 vec_safe_push (*argtypes
, receiver_type
);
1173 if (flag_next_runtime
< USE_FIXUP_BEFORE
)
1174 /* Selector type - will eventually change to `int'. */
1175 vec_safe_push (*argtypes
, superflag
? objc_v2_super_selector_type
1176 : objc_v2_selector_type
);
1178 vec_safe_push (*argtypes
, objc_selector_type
);
1181 /* TODO: Merge this with the message refs. */
1183 build_selector_reference_decl (tree ident
)
1186 char *t
, buf
[BUFSIZE
];
1188 snprintf (buf
, BUFSIZE
, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident
));
1193 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
1196 decl
= start_var_decl (objc_selector_type
, buf
);
1197 OBJCMETA (decl
, objc_meta
, meta_sel_refs
);
1202 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED
,
1204 tree proto ATTRIBUTE_UNUSED
)
1206 tree
*chain
= &sel_ref_chain
;
1211 if (TREE_VALUE (*chain
) == ident
)
1212 return TREE_PURPOSE (*chain
);
1214 chain
= &TREE_CHAIN (*chain
);
1217 expr
= build_selector_reference_decl (ident
);
1218 *chain
= tree_cons (expr
, ident
, NULL_TREE
);
1223 /* Declare a variable of type 'struct message_ref_t'. */
1224 /* This will be finished in build_v2_message_ref_translation_table ().
1225 We take an idea from LLVM in making the names a bit more connected
1226 and thus the asm more readable. */
1229 build_v2_message_reference_decl (tree sel_name
, tree message_func_ident
)
1232 char buf
[BUFSIZE
], *t
;
1235 /* Skip past the objc_msgSend it's the same for all... */
1236 if (IDENTIFIER_POINTER (message_func_ident
)[offset
] == '_')
1239 snprintf (buf
, BUFSIZE
, "_OBJC_MsgRef_%s_%s",
1240 &(IDENTIFIER_POINTER (message_func_ident
)[offset
]),
1241 IDENTIFIER_POINTER (sel_name
));
1246 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
1249 decl
= start_var_decl (objc_v2_message_ref_template
, buf
);
1250 OBJCMETA (decl
, objc_meta
, meta_mref
);
1254 struct GTY(()) msgref_entry
{
1260 static GTY (()) vec
<msgref_entry
, va_gc
> *msgrefs
;
1262 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1263 later on to initialize the table of 'struct message_ref_t'
1267 build_v2_selector_messenger_reference (tree sel_name
, tree message_func_decl
)
1275 FOR_EACH_VEC_ELT (*msgrefs
, count
, ref
)
1276 if (ref
->func
== message_func_decl
&& ref
->selname
== sel_name
)
1277 return ref
->refdecl
;
1280 /* Somewhat arbitrary initial provision. */
1281 vec_alloc (msgrefs
, 32);
1283 /* We come here if we don't find a match or at the start. */
1284 decl
= build_v2_message_reference_decl (sel_name
,
1285 DECL_NAME (message_func_decl
));
1286 e
.func
= message_func_decl
;
1287 e
.selname
= sel_name
;
1289 vec_safe_push (msgrefs
, e
);
1294 build_v2_protocollist_ref_decl (tree protocol
)
1297 tree protocol_ident
= PROTOCOL_NAME (protocol
);
1300 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRef_%s",
1301 IDENTIFIER_POINTER (protocol_ident
));
1302 /* TODO: other compiler versions make these hidden & weak. */
1303 decl
= create_global_decl (objc_protocol_type
, buf
);
1304 /* Let optimizer know that this decl is not removable. */
1305 DECL_PRESERVE_P (decl
) = 1;
1306 OBJCMETA (decl
, objc_meta
, meta_proto_ref
);
1310 struct GTY(()) prot_list_entry
{
1314 static GTY (()) vec
<prot_list_entry
, va_gc
> *protrefs
;
1317 objc_v2_get_protocol_reference (tree ident
)
1324 prot_list_entry
*ref
;
1325 FOR_EACH_VEC_ELT (*protrefs
, count
, ref
)
1327 if (ref
->id
== ident
)
1330 ref
->refdecl
= build_v2_protocollist_ref_decl (ident
);
1331 return ref
->refdecl
;
1336 /* Somewhat arbitrary initial provision. */
1337 vec_alloc (protrefs
, 32);
1339 /* We come here if we don't find the entry - or if the table was yet
1341 decl
= build_v2_protocollist_ref_decl (ident
);
1344 vec_safe_push (protrefs
, e
);
1349 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED
,
1352 if (!PROTOCOL_FORWARD_DECL (p
))
1353 PROTOCOL_FORWARD_DECL (p
) = next_runtime_abi_02_protocol_decl (p
);
1355 return objc_v2_get_protocol_reference (p
);
1358 /* This routine returns the ivar declaration, if component is a valid
1359 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1360 returns the class name in CLASS. */
1363 objc_is_ivar (tree expr
, tree component
, tree
*klass
)
1365 tree field
= NULL_TREE
;
1366 tree basetype
= TYPE_MAIN_VARIANT (TREE_TYPE (expr
));
1368 if (TREE_CODE (basetype
) == RECORD_TYPE
1369 && TYPE_HAS_OBJC_INFO (basetype
) && TYPE_OBJC_INTERFACE (basetype
))
1371 *klass
= lookup_interface (OBJC_TYPE_NAME (basetype
));
1376 tree ivar_chain
= CLASS_RAW_IVARS (*klass
);
1379 field
= is_ivar (ivar_chain
, component
);
1380 if (field
!= NULL_TREE
)
1383 *klass
= lookup_interface (CLASS_SUPER_NAME (*klass
));
1392 create_ivar_offset_name (char *buf
, tree class_name
, tree field_decl
)
1394 tree fname
= DECL_NAME (field_decl
);
1396 sprintf (buf
, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name
),
1397 IDENTIFIER_POINTER (fname
));
1401 /* This routine generates new abi's ivar reference tree. It amounts
1402 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1403 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1404 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1407 objc_v2_build_ivar_ref (tree datum
, tree component
)
1409 tree field
, ref
, class_name
, offset
, ftype
, expr
;
1410 char var_offset_name
[512];
1412 field
= objc_is_ivar (datum
, component
, &class_name
);
1416 /* This routine only handles non-bitfield fields */
1417 if (DECL_C_BIT_FIELD (field
))
1420 create_ivar_offset_name (var_offset_name
, CLASS_NAME (class_name
), field
);
1422 offset
= create_extern_decl (TREE_TYPE (size_zero_node
), var_offset_name
);
1424 ftype
= TREE_TYPE (field
);
1427 expr
= build_c_cast (input_location
,
1428 string_type_node
, build_fold_addr_expr (datum
));
1430 /* (char*)datum + offset */
1431 expr
= fold_build_pointer_plus_loc (input_location
, expr
, offset
);
1433 /* (ftype*)((char*)datum + offset) */
1434 expr
= build_c_cast (input_location
, build_pointer_type (ftype
), expr
);
1436 /* Finally: *(ftype*)((char*)datum + offset) */
1437 ref
= build_indirect_ref (input_location
, expr
, RO_UNARY_STAR
);
1439 /* We must set type of the resulting expression to be the same as
1440 the field type. This is because, build_indirect_ref (...)
1441 rebuilds the type which may result in lost information; as in the
1442 case of protocol-qualified types (id <protocol> ). */
1443 TREE_TYPE (ref
) = ftype
;
1445 if (TREE_READONLY (datum
) || TREE_READONLY (field
))
1446 TREE_READONLY (ref
) = 1;
1448 if (TREE_THIS_VOLATILE (datum
) || TREE_THIS_VOLATILE (field
))
1449 TREE_THIS_VOLATILE (ref
) = 1;
1451 if (TREE_DEPRECATED (field
))
1452 warn_deprecated_use (field
, NULL_TREE
);
1457 /* IVAR refs are made via an externally referenceable offset and built
1458 on the fly. That is, unless they refer to (private) fields in the
1461 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED
,
1465 if ((ivar
= objc_v2_build_ivar_ref (base
, id
)))
1467 return objc_build_component_ref (base
, id
);
1470 /* [super ...] references are listed here (and built into a table at
1471 meta -data emit time). */
1473 build_v2_superclass_ref_decl (tree ident
, bool inst
)
1478 snprintf (buf
, BUFSIZE
, "_OBJC_%sSuperRef_%s", (inst
?"":"Meta"),
1479 IDENTIFIER_POINTER (ident
));
1480 decl
= start_var_decl (objc_class_type
, buf
);
1481 OBJCMETA (decl
, objc_meta
, meta_superclass_ref
);
1485 static GTY (()) vec
<ident_data_tuple
, va_gc
> *class_super_refs
;
1486 static GTY (()) vec
<ident_data_tuple
, va_gc
> *metaclass_super_refs
;
1488 /* Find or build a superclass reference decl for class NAME. */
1491 objc_get_superclass_ref_decl (tree name
, bool inst_meth
)
1494 vec
<ident_data_tuple
, va_gc
> *list
= inst_meth
? class_super_refs
1495 : metaclass_super_refs
;
1500 ident_data_tuple
*ref
;
1501 FOR_EACH_VEC_ELT (*list
, count
, ref
)
1503 if (ref
->ident
== name
)
1506 ref
->data
= build_v2_superclass_ref_decl (name
, inst_meth
);
1513 /* Somewhat arbitrary initial provision. */
1516 vec_alloc (class_super_refs
, 16);
1517 list
= class_super_refs
;
1521 vec_alloc (metaclass_super_refs
, 16);
1522 list
= metaclass_super_refs
;
1525 /* We come here if we don't find the entry - or if the table was yet
1527 decl
= build_v2_superclass_ref_decl (name
, inst_meth
);
1531 vec_safe_push (list
, e
);
1535 /* Get a reference to the superclass for IMP. */
1538 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED
,
1539 struct imp_entry
*imp
, bool inst_meth
)
1541 tree name
= CLASS_NAME (imp
->imp_context
);
1542 return objc_get_superclass_ref_decl (name
, inst_meth
);
1545 /* Get a reference to the superclass for category IMP. */
1548 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED
,
1549 struct imp_entry
*imp
,
1554 /* Do it the slow way. */
1555 tree get_cl_fn
= inst_meth
? objc_get_class_decl
1556 : objc_get_meta_class_decl
;
1557 tree super_name
= CLASS_SUPER_NAME (imp
->imp_template
);
1558 super_name
= my_build_string_pointer (IDENTIFIER_LENGTH (super_name
) + 1,
1559 IDENTIFIER_POINTER (super_name
));
1560 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1561 return build_function_call (input_location
, get_cl_fn
,
1562 build_tree_list (NULL_TREE
, super_name
));
1565 /* This is the 'usual' path. */
1566 tree cls_name
= CLASS_NAME (imp
->imp_template
);
1568 return objc_get_superclass_ref_decl (cls_name
, inst_meth
);
1569 return objc_get_class_reference (cls_name
);
1573 next_runtime_abi_02_receiver_is_class_object (tree receiver
)
1575 if (VAR_P (receiver
)
1576 && IS_CLASS (TREE_TYPE (receiver
))
1577 && vec_safe_length (classrefs
))
1580 ident_data_tuple
*ref
;
1581 /* The receiver is a variable created by build_class_reference_decl. */
1582 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
1583 if (ref
->data
== receiver
)
1589 /* Assign all arguments in VALUES which have side-effect to a temporary
1590 and replaced that argument in VALUES list with the temporary. The
1591 arguments will be passed to a function with FNTYPE. */
1594 objc_copy_to_temp_side_effect_params (tree fntype
, tree values
)
1597 function_args_iterator iter
;
1599 /* Skip over receiver and the &_msf_ref types. */
1600 function_args_iter_init (&iter
, fntype
);
1601 function_args_iter_next (&iter
);
1602 function_args_iter_next (&iter
);
1604 for (valtail
= values
; valtail
;
1605 valtail
= TREE_CHAIN (valtail
), function_args_iter_next (&iter
))
1607 tree value
= TREE_VALUE (valtail
);
1608 tree type
= function_args_iter_cond (&iter
);
1609 if (type
== NULL_TREE
)
1611 if (!TREE_SIDE_EFFECTS (value
))
1613 /* To prevent re-evaluation. */
1614 value
= save_expr (value
);
1616 TREE_VALUE (valtail
) = value
;
1621 /* Build the new abi's messaging library call. It looks like:
1622 (*_msg.messenger) (receiver, &_msg, ...) */
1625 build_v2_objc_method_fixup_call (int super_flag
, tree method_prototype
,
1626 tree lookup_object
, tree selector
,
1627 tree method_params
, bool check_for_nil
)
1630 tree sender
, rcv_p
, t
;
1633 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1634 : objc_object_type
);
1635 tree ftype
= build_function_type_for_method (ret_type
, method_prototype
,
1636 METHOD_REF
, super_flag
);
1639 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
1640 ftype
= build_type_attribute_variant (
1641 ftype
, METHOD_TYPE_ATTRIBUTES (method_prototype
));
1643 sender_cast
= build_pointer_type (ftype
);
1646 method_params
= objc_copy_to_temp_side_effect_params (ftype
,
1649 /* Get &message_ref_t.messenger. */
1650 sender
= build_c_cast (input_location
,
1651 build_pointer_type (super_flag
1652 ? objc_v2_super_imp_type
1653 : objc_v2_imp_type
),
1656 sender
= build_indirect_ref (input_location
, sender
, RO_UNARY_STAR
);
1658 rcv_p
= (super_flag
? objc_super_type
: objc_object_type
);
1660 lookup_object
= build_c_cast (input_location
, rcv_p
, lookup_object
);
1661 if (sender
== error_mark_node
|| lookup_object
== error_mark_node
)
1662 return error_mark_node
;
1664 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1665 lookup_object
= save_expr (lookup_object
);
1667 method_params
= tree_cons (NULL_TREE
, lookup_object
,
1668 tree_cons (NULL_TREE
, selector
,
1670 t
= build3 (OBJ_TYPE_REF
, sender_cast
, sender
, lookup_object
,
1671 build_int_cst (TREE_TYPE (lookup_object
), 0));
1672 ret_val
= build_function_call (input_location
, t
, method_params
);
1675 /* receiver != nil ? ret_val : 0 */
1679 if (TREE_CODE (ret_type
) == RECORD_TYPE
1680 || TREE_CODE (ret_type
) == UNION_TYPE
)
1681 /* An empty constructor is zero-filled by the middle end. */
1682 ftree
= objc_build_constructor (ret_type
, NULL
);
1684 ftree
= fold_convert (ret_type
, integer_zero_node
);
1686 ifexp
= build_binary_op (input_location
, NE_EXPR
,
1688 fold_convert (rcv_p
, integer_zero_node
), 1);
1691 ret_val
= build_conditional_expr (input_location
,
1692 ifexp
, ret_val
, ftree
,
1693 tf_warning_or_error
);
1695 ret_val
= build_conditional_expr (input_location
,
1697 ret_val
, NULL_TREE
, input_location
,
1698 ftree
, NULL_TREE
, input_location
);
1699 ret_val
= fold_convert (ret_type
, ret_val
);
1706 build_v2_build_objc_method_call (int super
, tree method_prototype
,
1707 tree lookup_object
, tree selector
,
1708 tree method_params
, location_t loc
,
1709 bool check_for_nil
, bool rx_is_id
)
1711 tree sender
, sender_cast
, method
, t
;
1712 tree rcv_p
= (super
? objc_super_type
: objc_object_type
);
1713 vec
<tree
, va_gc
> *parms
;
1714 unsigned nparm
= (method_params
? list_length (method_params
) : 0);
1716 /* If a prototype for the method to be called exists, then cast
1717 the sender's return type and arguments to match that of the method.
1718 Otherwise, leave sender as is. */
1721 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1722 : objc_object_type
);
1723 tree ftype
= build_function_type_for_method (ret_type
, method_prototype
,
1726 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
1727 ftype
= build_type_attribute_variant (ftype
,
1728 METHOD_TYPE_ATTRIBUTES
1729 (method_prototype
));
1731 sender_cast
= build_pointer_type (ftype
);
1733 lookup_object
= build_c_cast (loc
, rcv_p
, lookup_object
);
1735 if (error_operand_p (lookup_object
))
1736 return error_mark_node
;
1738 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1739 lookup_object
= save_expr (lookup_object
);
1741 /* Param list + 2 slots for object and selector. */
1742 vec_alloc (parms
, nparm
+ 2);
1744 /* If we are returning an item that must be returned in memory, and the
1745 target ABI does this by an invisible pointer provided as the first arg,
1746 we need to adjust the message signature to include this. The second
1747 part of this excludes targets that provide some alternate scheme for
1748 structure returns. */
1749 if (ret_type
&& !VOID_TYPE_P (ret_type
)
1750 && targetm
.calls
.return_in_memory (ret_type
, 0)
1751 && !(targetm
.calls
.struct_value_rtx (0, 0)
1752 && (TREE_CODE (ret_type
) == RECORD_TYPE
1753 || TREE_CODE (ret_type
) == UNION_TYPE
)))
1756 sender
= umsg_id_super2_stret_fixup_decl
;
1758 sender
= rx_is_id
? umsg_id_stret_fixup_decl
1759 : umsg_stret_fixup_decl
;
1764 sender
= umsg_id_super2_fixup_decl
;
1766 sender
= rx_is_id
? umsg_id_fixup_decl
1770 method
= build_fold_addr_expr_loc (loc
, sender
);
1772 /* Pass the object to the method. */
1773 parms
->quick_push (lookup_object
);
1774 /* Pass the selector to the method. */
1775 parms
->quick_push (selector
);
1776 /* Now append the remainder of the parms. */
1778 for (; method_params
; method_params
= TREE_CHAIN (method_params
))
1779 parms
->quick_push (TREE_VALUE (method_params
));
1781 /* Build an obj_type_ref, with the correct cast for the method call. */
1782 t
= build3 (OBJ_TYPE_REF
, sender_cast
, method
,
1783 lookup_object
, build_int_cst (TREE_TYPE (lookup_object
), 0));
1784 tree ret_val
= build_function_call_vec (loc
, vNULL
, t
, parms
, NULL
);
1788 /* receiver != nil ? ret_val : 0 */
1792 if (TREE_CODE (ret_type
) == RECORD_TYPE
1793 || TREE_CODE (ret_type
) == UNION_TYPE
)
1795 /* An empty constructor is zero-filled by the middle end. */
1796 ftree
= objc_build_constructor (ret_type
, NULL
);
1799 ftree
= fold_convert (ret_type
, integer_zero_node
);
1801 ifexp
= build_binary_op (loc
, NE_EXPR
,
1803 fold_convert (rcv_p
, integer_zero_node
), 1);
1806 ret_val
= build_conditional_expr (loc
, ifexp
, ret_val
, ftree
,
1807 tf_warning_or_error
);
1809 ret_val
= build_conditional_expr (loc
, ifexp
, 1,
1810 ret_val
, NULL_TREE
, loc
,
1811 ftree
, NULL_TREE
, loc
);
1812 ret_val
= fold_convert (ret_type
, ret_val
);
1819 next_runtime_abi_02_build_objc_method_call (location_t loc
,
1820 tree method_prototype
,
1827 /* Do we need to check for nil receivers ? */
1828 /* For now, message sent to classes need no nil check. In the
1829 future, class declaration marked as weak_import must be nil
1831 bool check_for_nil
= flag_objc_nilcheck
;
1833 || (VAR_P (receiver
)
1834 && TREE_TYPE (receiver
) == objc_class_type
))
1835 check_for_nil
= false;
1837 if (flag_next_runtime
>= USE_FIXUP_BEFORE
)
1840 = next_runtime_abi_02_build_selector_reference (loc
, sel_name
,
1842 return build_v2_build_objc_method_call (super
, method_prototype
,
1846 objc_is_id (rtype
));
1849 /* else we have to build a pair of the function and selector. */
1850 tree message_func_decl
;
1851 tree ret_type
= method_prototype
1852 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1855 /* See comment for the fixup version above. */
1856 if (ret_type
&& !VOID_TYPE_P (ret_type
)
1857 && targetm
.calls
.return_in_memory (ret_type
, 0)
1858 && !(targetm
.calls
.struct_value_rtx (0, 0)
1859 && (TREE_CODE (ret_type
) == RECORD_TYPE
1860 || TREE_CODE (ret_type
) == UNION_TYPE
)))
1863 message_func_decl
= umsg_id_super2_stret_fixup_decl
;
1865 message_func_decl
= objc_is_id (rtype
)
1866 ? umsg_id_stret_fixup_decl
1867 : umsg_stret_fixup_decl
;
1872 message_func_decl
= umsg_id_super2_fixup_decl
;
1874 message_func_decl
= objc_is_id (rtype
)
1875 ? umsg_id_fixup_decl
1879 tree selector
= build_v2_selector_messenger_reference (sel_name
,
1882 /* selector = &_msg; */
1883 selector
= build_unary_op (loc
, ADDR_EXPR
, selector
, 0);
1885 selector
= build_c_cast (loc
, (super
? objc_v2_super_selector_type
1886 : objc_v2_selector_type
),
1889 /* (*_msg.messenger) (receiver, &_msg, ...); */
1890 return build_v2_objc_method_fixup_call (super
, method_prototype
, receiver
,
1891 selector
, method_params
,
1895 /* NOTE --- Constant String Class Stuff --- */
1898 next_runtime_abi_02_setup_const_string_class_decl (void)
1900 if (!constant_string_global_id
)
1902 /* Hopefully, this should not represent a serious limitation. */
1904 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s", constant_string_class_name
);
1905 constant_string_global_id
= get_identifier (buf
);
1908 string_class_decl
= lookup_name (constant_string_global_id
);
1910 /* In OBJC2 abi, constant string class reference refers to class
1911 name for NSConstantString class. This declaration may not be
1912 available yet (in fact it is not in most cases). So, declare an
1913 extern OBJC_CLASS_$_NSConstantString in its place. */
1914 if (!string_class_decl
)
1916 create_extern_decl (objc_v2_class_template
,
1917 IDENTIFIER_POINTER (constant_string_global_id
));
1919 return (string_class_decl
!= NULL_TREE
);
1923 next_runtime_abi_02_build_const_string_constructor (location_t loc
, tree string
,
1926 tree constructor
, fields
, var
;
1927 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1929 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1930 fields
= TYPE_FIELDS (internal_const_str_type
);
1931 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1932 build_unary_op (loc
, ADDR_EXPR
, string_class_decl
, 0));
1934 fields
= DECL_CHAIN (fields
);
1935 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1936 build_unary_op (loc
, ADDR_EXPR
, string
, 1));
1938 /* ??? check if this should be long. */
1939 fields
= DECL_CHAIN (fields
);
1940 CONSTRUCTOR_APPEND_ELT (v
, fields
, build_int_cst (NULL_TREE
, length
));
1941 constructor
= objc_build_constructor (internal_const_str_type
, v
);
1943 var
= build_decl (input_location
, CONST_DECL
, NULL
, TREE_TYPE (constructor
));
1944 DECL_INITIAL (var
) = constructor
;
1945 TREE_STATIC (var
) = 1;
1946 DECL_CONTEXT (var
) = NULL
;
1947 OBJCMETA (var
, objc_meta
, meta_const_str
);
1951 /* NOTE --- NeXT V2 Metadata templates --- */
1953 /* This routine builds the following type:
1956 const char * const name; // property name
1957 const char * const attributes; // comma-delimited, encoded,
1958 // property attributes
1963 build_v2_property_template (void)
1966 tree decls
, *chain
= NULL
;
1968 prop_record
= objc_start_struct (get_identifier ("_prop_t"));
1969 /* const char * name */
1970 decls
= add_field_decl (string_type_node
, "name", &chain
);
1972 /* const char * attribute */
1973 add_field_decl (string_type_node
, "attribute", &chain
);
1975 objc_finish_struct (prop_record
, decls
);
1981 unsigned long int *offset;
1990 build_v2_ivar_t_template (void)
1992 tree objc_ivar_id
, objc_ivar_record
;
1993 tree decls
, *chain
= NULL
;
1995 objc_ivar_id
= get_identifier ("_ivar_t");
1996 objc_ivar_record
= objc_start_struct (objc_ivar_id
);
1998 /* unsigned long int *offset; */
1999 decls
= add_field_decl (build_pointer_type
2000 (TREE_TYPE (size_zero_node
)), "offset", &chain
);
2003 add_field_decl (string_type_node
, "name", &chain
);
2006 add_field_decl (string_type_node
, "type", &chain
);
2008 /* uint32_t alignment; */
2009 add_field_decl (integer_type_node
, "alignment", &chain
);
2011 /* uint32_t size; */
2012 add_field_decl (integer_type_node
, "size", &chain
);
2014 objc_finish_struct (objc_ivar_record
, decls
);
2015 return objc_ivar_record
;
2019 build_metadata_templates (void)
2022 if (!objc_method_template
)
2023 objc_method_template
= build_method_template ();
2025 if (!objc_v2_property_template
)
2026 objc_v2_property_template
= build_v2_property_template ();
2028 if (!objc_v2_ivar_template
)
2029 objc_v2_ivar_template
= build_v2_ivar_t_template ();
2033 /* NOTE --- Output NeXT V2 Metadata --- */
2035 /* Routine builds name of Interface's main meta-data of type class_t. */
2038 objc_build_internal_classname (tree ident
, bool metaclass
)
2040 static char string
[512];
2041 snprintf (string
, 512, "%s_%s", metaclass
? "OBJC_METACLASS_$"
2043 IDENTIFIER_POINTER (ident
));
2047 /* Build the name for object of type struct class_ro_t */
2050 newabi_append_ro (const char *name
)
2054 static char string
[BUFSIZE
];
2055 dollar
= strchr (name
, '$');
2056 gcc_assert (dollar
);
2059 strncpy (p
, name
, (int)(dollar
- name
));
2060 p
+= (int)(dollar
- name
);
2061 sprintf (p
, "RO_%s", dollar
);
2065 /* Build the struct message_ref_t msg =
2066 {objc_msgSend_fixup_xxx, @selector(func)}
2070 void build_v2_message_ref_translation_table (void)
2075 if (!vec_safe_length (msgrefs
))
2078 FOR_EACH_VEC_ELT (*msgrefs
, count
, ref
)
2080 vec
<constructor_elt
, va_gc
> *initializer
;
2081 tree expr
, constructor
;
2082 tree struct_type
= TREE_TYPE (ref
->refdecl
);
2083 location_t loc
= DECL_SOURCE_LOCATION (ref
->refdecl
);
2086 /* First 'IMP messenger' field... */
2087 expr
= build_unary_op (loc
, ADDR_EXPR
, ref
->func
, 0);
2088 expr
= convert (objc_v2_imp_type
, expr
);
2089 CONSTRUCTOR_APPEND_ELT (initializer
, NULL_TREE
, expr
);
2091 /* ... then 'SEL name' field. */
2092 expr
= build_selector (ref
->selname
);
2093 CONSTRUCTOR_APPEND_ELT (initializer
, NULL_TREE
, expr
);
2094 constructor
= objc_build_constructor (struct_type
, initializer
);
2095 finish_var_decl (ref
->refdecl
, constructor
);
2099 /* Build decl = initializer; for each externally visible class
2103 build_v2_classrefs_table (void)
2106 ident_data_tuple
*ref
;
2108 if (!vec_safe_length (classrefs
))
2111 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
2113 tree expr
= ref
->ident
;
2114 tree decl
= ref
->data
;
2115 /* Interface with no implementation and yet one of its messages
2116 has been used. Need to generate a full address-of tree for it
2118 if (TREE_CODE (expr
) == IDENTIFIER_NODE
)
2120 const char *name
= objc_build_internal_classname (expr
, false);
2121 expr
= create_extern_decl (objc_v2_class_template
, name
);
2122 expr
= convert (objc_class_type
, build_fold_addr_expr (expr
));
2124 /* The runtime wants this, even if it appears unused, so we must force the
2126 DECL_PRESERVE_P (decl
) = 1;
2127 finish_var_decl (decl
, expr
);
2131 /* Build decl = initializer; for each externally visible super class
2135 build_v2_super_classrefs_table (bool metaclass
)
2138 ident_data_tuple
*ref
;
2139 vec
<ident_data_tuple
, va_gc
> *list
= metaclass
? metaclass_super_refs
2142 if (!vec_safe_length (list
))
2145 FOR_EACH_VEC_ELT (*list
, count
, ref
)
2147 tree expr
= ref
->ident
;
2148 tree decl
= ref
->data
;
2149 /* Interface with no implementation and yet one of its messages
2150 has been used. Need to generate a full address-of tree for it
2152 if (TREE_CODE (expr
) == IDENTIFIER_NODE
)
2154 const char * name
= objc_build_internal_classname (expr
, metaclass
);
2155 expr
= create_extern_decl (objc_v2_class_template
, name
);
2156 expr
= convert (objc_class_type
, build_fold_addr_expr (expr
));
2158 finish_var_decl (decl
, expr
);
2162 /* Add the global class meta-data declaration to the list which later
2163 on ends up in the __class_list section. */
2165 static GTY(()) vec
<tree
, va_gc
> *class_list
;
2168 objc_v2_add_to_class_list (tree global_class_decl
)
2170 vec_safe_push (class_list
, global_class_decl
);
2173 static GTY(()) vec
<tree
, va_gc
> *nonlazy_class_list
;
2175 /* Add the global class meta-data declaration to the list which later
2176 on ends up in the __nonlazy_class section. */
2179 objc_v2_add_to_nonlazy_class_list (tree global_class_decl
)
2181 vec_safe_push (nonlazy_class_list
, global_class_decl
);
2184 static GTY(()) vec
<tree
, va_gc
> *category_list
;
2186 /* Add the category meta-data declaration to the list which later on
2187 ends up in the __nonlazy_category section. */
2190 objc_v2_add_to_category_list (tree decl
)
2192 vec_safe_push (category_list
, decl
);
2195 static GTY(()) vec
<tree
, va_gc
> *nonlazy_category_list
;
2197 /* Add the category meta-data declaration to the list which later on
2198 ends up in the __category_list section. */
2201 objc_v2_add_to_nonlazy_category_list (tree decl
)
2203 vec_safe_push (nonlazy_category_list
, decl
);
2207 has_load_impl (tree clsmeth
)
2211 tree id
= METHOD_SEL_NAME (clsmeth
);
2212 if (IDENTIFIER_LENGTH (id
) == 4
2213 && startswith (IDENTIFIER_POINTER (id
), "load"))
2215 clsmeth
= DECL_CHAIN (clsmeth
);
2221 /* Build a __{class,category}_list section table containing address of
2222 all @implemented {class,category} meta-data. */
2225 build_v2_address_table (vec
<tree
, va_gc
> *src
, const char *nam
, tree attr
)
2228 tree type
, decl
, expr
;
2229 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2231 if (!vec_safe_length (src
))
2234 FOR_EACH_VEC_ELT (*src
, count
, decl
)
2237 tree purpose
= build_int_cst (NULL_TREE
, count
);
2239 tree purpose
= NULL_TREE
;
2241 expr
= convert (objc_class_type
, build_fold_addr_expr (decl
));
2242 CONSTRUCTOR_APPEND_ELT (initlist
, purpose
, expr
);
2244 gcc_assert (count
> 0);
2245 type
= build_array_type (objc_class_type
,
2246 build_index_type (build_int_cst (NULL_TREE
, count
- 1)));
2247 decl
= start_var_decl (type
, nam
);
2248 /* The runtime wants this, even if it appears unused, so we must
2249 force the output. */
2250 DECL_PRESERVE_P (decl
) = 1;
2251 expr
= objc_build_constructor (type
, initlist
);
2252 OBJCMETA (decl
, objc_meta
, attr
);
2253 DECL_USER_ALIGN (decl
) = 1;
2254 finish_var_decl (decl
, expr
);
2257 /* Build decl = initializer; for each protocol referenced in
2258 @protocol(MyProt) expression. Refs as built in the entry section
2262 build_v2_protocol_list_translation_table (void)
2265 prot_list_entry
*ref
;
2270 FOR_EACH_VEC_ELT (*protrefs
, count
, ref
)
2274 gcc_assert (TREE_CODE (ref
->id
) == PROTOCOL_INTERFACE_TYPE
);
2275 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
2276 IDENTIFIER_POINTER (PROTOCOL_NAME (ref
->id
)));
2277 expr
= start_var_decl (objc_v2_protocol_template
, buf
);
2278 expr
= convert (objc_protocol_type
, build_fold_addr_expr (expr
));
2279 finish_var_decl (ref
->refdecl
, expr
);
2281 /* TODO: Maybe we could explicitly delete the vec. now? */
2284 static GTY (()) vec
<prot_list_entry
, va_gc
> *protlist
;
2286 /* Add the local protocol meta-data declaration to the list which
2287 later on ends up in the __protocol_list section. */
2290 objc_add_to_protocol_list (tree protocol_interface_decl
, tree protocol_decl
)
2294 /* Arbitrary init count. */
2295 vec_alloc (protlist
, 32);
2296 e
.id
= protocol_interface_decl
;
2297 e
.refdecl
= protocol_decl
;
2298 vec_safe_push (protlist
, e
);
2301 /* Build the __protocol_list section table containing address of all
2302 generate protocol_t meta-data. */
2305 build_v2_protocol_list_address_table (void)
2308 prot_list_entry
*ref
;
2309 if (!vec_safe_length (protlist
))
2312 FOR_EACH_VEC_ELT (*protlist
, count
, ref
)
2316 gcc_assert (ref
->id
&& TREE_CODE (ref
->id
) == PROTOCOL_INTERFACE_TYPE
);
2317 snprintf (buf
, BUFSIZE
, "_OBJC_LabelProtocol_%s",
2318 IDENTIFIER_POINTER (PROTOCOL_NAME (ref
->id
)));
2319 if (flag_next_runtime
>= WEAK_PROTOCOLS_AFTER
)
2321 decl
= create_hidden_decl (objc_protocol_type
, buf
, /*is def=*/true);
2322 DECL_WEAK (decl
) = true;
2325 decl
= create_global_decl (objc_protocol_type
, buf
, /*is def=*/true);
2326 expr
= convert (objc_protocol_type
, build_fold_addr_expr (ref
->refdecl
));
2327 OBJCMETA (decl
, objc_meta
, meta_label_protocollist
);
2328 DECL_PRESERVE_P (decl
) = 1;
2329 DECL_USER_ALIGN (decl
) = 1;
2330 finish_var_decl (decl
, expr
);
2333 /* TODO: delete the vec. */
2334 /* TODO: upgrade to the clang/llvm hidden version. */
2337 /* This routine declares a variable to hold meta data for 'struct
2338 protocol_list_t'. */
2341 generate_v2_protocol_list (tree i_or_p
, tree klass_ctxt
)
2343 tree refs_decl
, lproto
, e
, plist
, ptempl_p_t
;
2345 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2348 if (TREE_CODE (i_or_p
) == CLASS_INTERFACE_TYPE
2349 || TREE_CODE (i_or_p
) == CATEGORY_INTERFACE_TYPE
)
2350 plist
= CLASS_PROTOCOL_LIST (i_or_p
);
2351 else if (TREE_CODE (i_or_p
) == PROTOCOL_INTERFACE_TYPE
)
2352 plist
= PROTOCOL_LIST (i_or_p
);
2357 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
2358 if (TREE_CODE (TREE_VALUE (lproto
)) == PROTOCOL_INTERFACE_TYPE
2359 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto
)))
2362 /* Build initializer. */
2364 ptempl_p_t
= build_pointer_type (objc_v2_protocol_template
);
2365 e
= build_int_cst (ptempl_p_t
, size
);
2366 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, e
);
2368 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
2370 tree pval
= TREE_VALUE (lproto
);
2372 if (TREE_CODE (pval
) == PROTOCOL_INTERFACE_TYPE
2373 && PROTOCOL_FORWARD_DECL (pval
))
2375 tree fwref
= PROTOCOL_FORWARD_DECL (pval
);
2376 location_t loc
= DECL_SOURCE_LOCATION (fwref
) ;
2377 e
= build_unary_op (loc
, ADDR_EXPR
, fwref
, 0);
2378 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, e
);
2382 /* static struct protocol_list_t *list[size]; */
2384 switch (TREE_CODE (i_or_p
))
2386 case PROTOCOL_INTERFACE_TYPE
:
2387 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRefs_%s",
2388 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p
)));
2390 case CLASS_INTERFACE_TYPE
:
2391 snprintf (buf
, BUFSIZE
, "_OBJC_ClassProtocols_%s",
2392 IDENTIFIER_POINTER (CLASS_NAME (i_or_p
)));
2394 case CATEGORY_INTERFACE_TYPE
:
2395 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryProtocols_%s_%s",
2396 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)),
2397 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt
)));
2403 refs_decl
= start_var_decl (build_sized_array_type (ptempl_p_t
, size
+1),
2405 /* ObjC2 puts all these in the base section. */
2406 OBJCMETA (refs_decl
, objc_meta
, meta_base
);
2407 DECL_PRESERVE_P (refs_decl
) = 1;
2408 DECL_USER_ALIGN (refs_decl
) = 1;
2409 finish_var_decl (refs_decl
,
2410 objc_build_constructor (TREE_TYPE (refs_decl
),initlist
));
2414 /* This routine builds one 'struct method_t' initializer list. Note
2415 that the old ABI is supposed to build 'struct objc_method' which
2416 has 3 fields, but it does not build the initialization expression
2417 for 'method_imp' which for protocols is NULL any way. To be
2418 consistent with declaration of 'struct method_t', in the new ABI we
2419 set the method_t.imp to NULL. */
2422 build_v2_descriptor_table_initializer (tree type
, tree entries
)
2424 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2427 vec
<constructor_elt
, va_gc
> *eltlist
= NULL
;
2428 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
,
2429 build_selector (METHOD_SEL_NAME (entries
)));
2430 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
,
2431 add_objc_string (METHOD_ENCODING (entries
),
2433 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
, null_pointer_node
);
2435 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
2436 objc_build_constructor (type
, eltlist
));
2437 entries
= TREE_CHAIN (entries
);
2441 return objc_build_constructor (build_array_type (type
, 0), initlist
);
2444 /* struct method_list_t
2447 uint32_t method_count;
2448 struct objc_method method_list[method_count];
2452 build_v2_method_list_template (tree list_type
, int size
)
2454 tree method_list_t_record
;
2455 tree array_type
, decls
, *chain
= NULL
;
2457 method_list_t_record
= objc_start_struct (NULL_TREE
);
2459 /* uint32_t const entsize; */
2460 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2462 /* int method_count; */
2463 add_field_decl (integer_type_node
, "method_count", &chain
);
2465 /* struct objc_method method_list[]; */
2466 array_type
= build_sized_array_type (list_type
, size
);
2467 add_field_decl (array_type
, "method_list", &chain
);
2469 objc_finish_struct (method_list_t_record
, decls
);
2470 return method_list_t_record
;
2473 /* Note, as above that we are building to the objc_method_template
2474 which has the *imp field. ABI0/1 build with
2475 objc_method_prototype_template which is missing this field. */
2477 generate_v2_meth_descriptor_table (tree chain
, tree protocol
,
2478 const char *prefix
, tree attr
,
2479 vec
<tree
>& all_meths
)
2481 tree method_list_template
, initlist
, decl
;
2483 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2486 if (!chain
|| !prefix
)
2489 tree method
= chain
;
2493 if (! METHOD_ENCODING (method
))
2494 METHOD_ENCODING (method
) = encode_method_prototype (method
);
2495 all_meths
.safe_push (method
);
2496 method
= TREE_CHAIN (method
);
2501 method_list_template
= build_v2_method_list_template (objc_method_template
,
2503 snprintf (buf
, BUFSIZE
, "%s_%s", prefix
,
2504 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
2506 decl
= start_var_decl (method_list_template
, buf
);
2508 entsize
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template
));
2509 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, entsize
));
2510 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
2512 build_v2_descriptor_table_initializer (objc_method_template
,
2514 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
2515 /* Get into the right section. */
2516 OBJCMETA (decl
, objc_meta
, attr
);
2517 DECL_USER_ALIGN (decl
) = 1;
2518 finish_var_decl (decl
, objc_build_constructor (method_list_template
, v
));
2523 generate_v2_meth_type_list (vec
<tree
>& all_meths
, tree protocol
,
2526 if (all_meths
.is_empty () || !prefix
)
2529 unsigned size
= all_meths
.length ();
2530 tree list_type
= build_sized_array_type (string_type_node
, size
);
2532 asprintf (&nam
, "%s_%s", prefix
,
2533 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
2534 tree decl
= start_var_decl (list_type
, nam
);
2536 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2538 for (unsigned i
= 0; i
< size
; ++i
)
2539 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2540 add_objc_string (METHOD_ENCODING (all_meths
[i
]),
2542 OBJCMETA (decl
, objc_meta
, meta_base
);
2543 DECL_USER_ALIGN (decl
) = 1;
2544 finish_var_decl (decl
, objc_build_constructor (list_type
, v
));
2548 /* This routine builds the initializer list to initialize the 'struct
2549 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2552 build_v2_property_table_initializer (tree type
, tree context
)
2555 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2556 if (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
)
2557 x
= CLASS_PROPERTY_DECL (context
);
2559 x
= IMPL_PROPERTY_DECL (context
);
2561 for (; x
; x
= TREE_CHAIN (x
))
2563 vec
<constructor_elt
, va_gc
> *elemlist
= NULL
;
2564 /* NOTE! sections where property name/attribute go MUST change
2566 tree attribute
, name_ident
= PROPERTY_NAME (x
);
2568 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
2569 add_objc_string (name_ident
, prop_names_attr
));
2571 attribute
= objc_v2_encode_prop_attr (x
);
2572 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
2573 add_objc_string (attribute
, prop_names_attr
));
2575 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2576 objc_build_constructor (type
, elemlist
));
2579 return objc_build_constructor (build_array_type (type
, 0),inits
);
2582 /* This routine builds the following type:
2585 uint32_t entsize; // sizeof (struct _prop_t)
2586 uint32_t prop_count;
2587 struct _prop_t prop_list [prop_count];
2592 build_v2_property_list_template (tree list_type
, int size
)
2594 tree property_list_t_record
;
2595 tree array_type
, decls
, *chain
= NULL
;
2598 property_list_t_record
= objc_start_struct (NULL_TREE
);
2600 /* uint32_t const entsize; */
2601 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2603 /* int prop_count; */
2604 add_field_decl (integer_type_node
, "prop_count", &chain
);
2606 /* struct _prop_t prop_list[]; */
2607 array_type
= build_sized_array_type (list_type
, size
);
2608 add_field_decl (array_type
, "prop_list", &chain
);
2610 objc_finish_struct (property_list_t_record
, decls
);
2611 return property_list_t_record
;
2614 /* Top-level routine to generate property tables for each
2618 generate_v2_property_table (tree context
, tree klass_ctxt
)
2620 tree x
, decl
, initlist
, property_list_template
;
2621 bool is_proto
= false;
2622 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2623 int init_val
, size
= 0;
2628 gcc_assert (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
);
2629 x
= CLASS_PROPERTY_DECL (context
);
2633 x
= IMPL_PROPERTY_DECL (klass_ctxt
);
2635 for (; x
; x
= TREE_CHAIN (x
))
2641 property_list_template
=
2642 build_v2_property_list_template (objc_v2_property_template
,
2645 initlist
= build_v2_property_table_initializer (objc_v2_property_template
,
2649 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template
));
2651 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolPropList_%s",
2652 IDENTIFIER_POINTER (PROTOCOL_NAME (context
)));
2654 snprintf (buf
, BUFSIZE
, "_OBJC_ClassPropList_%s",
2655 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)));
2657 decl
= start_var_decl (property_list_template
, buf
);
2659 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2660 build_int_cst (NULL_TREE
, init_val
));
2661 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2662 build_int_cst (NULL_TREE
, size
));
2663 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
2665 OBJCMETA (decl
, objc_meta
, meta_base
);
2666 DECL_USER_ALIGN (decl
) = 1;
2667 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), inits
));
2672 build_v2_protocol_initializer (tree type
, tree protocol_name
, tree protocol_list
,
2673 tree inst_methods
, tree class_methods
,
2674 tree opt_ins_meth
, tree opt_cls_meth
,
2675 tree property_list
, tree ext_meth_types
,
2676 tree demangled_name
, tree class_prop_list
)
2680 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2682 /* TODO: find a better representation of location from the inputs. */
2683 loc
= UNKNOWN_LOCATION
;
2685 /* This is NULL for the new ABI. */
2686 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2687 convert (objc_object_type
, null_pointer_node
));
2689 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_name
);
2690 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_list
);
2692 ttyp
= objc_method_proto_list_ptr
;
2694 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
2696 expr
= convert (ttyp
, null_pointer_node
);
2697 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2700 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
2702 expr
= convert (ttyp
, null_pointer_node
);
2703 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2706 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, opt_ins_meth
, 0));
2708 expr
= convert (ttyp
, null_pointer_node
);
2709 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2712 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, opt_cls_meth
, 0));
2714 expr
= convert (ttyp
, null_pointer_node
);
2715 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2717 ttyp
= objc_prop_list_ptr
;
2719 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
2721 expr
= convert (ttyp
, null_pointer_node
);
2722 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2724 /* const uint32_t size; = sizeof(struct protocol_t) */
2725 expr
= build_int_cst (integer_type_node
,
2726 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template
)));
2727 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2728 /* const uint32_t flags; = 0 */
2729 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, integer_zero_node
);
2731 ttyp
= build_pointer_type (string_type_node
);
2733 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, ext_meth_types
, 0));
2735 expr
= convert (ttyp
, null_pointer_node
);
2736 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2738 ttyp
= string_type_node
;
2740 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, demangled_name
, 0));
2742 expr
= convert (ttyp
, null_pointer_node
);
2743 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2745 ttyp
= objc_prop_list_ptr
;
2746 if (class_prop_list
)
2747 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_prop_list
, 0));
2749 expr
= convert (ttyp
, null_pointer_node
);
2750 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2752 return objc_build_constructor (type
, inits
);
2755 /* Main routine to build all meta data for all protocols used in a
2756 translation unit. */
2759 generate_v2_protocols (void)
2764 if (!protocol_chain
)
2767 /* If a protocol was directly referenced, pull in indirect
2769 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
2770 if (PROTOCOL_FORWARD_DECL (p
) && PROTOCOL_LIST (p
))
2771 generate_protocol_references (PROTOCOL_LIST (p
));
2773 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
2776 tree inst_meth
, class_meth
, opt_inst_meth
, opt_class_meth
, props
;
2777 tree decl
, initlist
, protocol_name_expr
, refs_decl
, refs_expr
;
2779 /* If protocol wasn't referenced, don't generate any code. */
2780 decl
= PROTOCOL_FORWARD_DECL (p
);
2785 loc
= DECL_SOURCE_LOCATION (decl
);
2788 vec
<tree
> all_meths
= vNULL
;
2790 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p
), p
,
2791 "_OBJC_ProtocolInstanceMethods",
2792 meta_proto_nst_meth
, all_meths
);
2795 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p
), p
,
2796 "_OBJC_ProtocolClassMethods",
2797 meta_proto_cls_meth
, all_meths
);
2800 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p
), p
,
2801 "_OBJC_ProtocolOptInstMethods",
2802 meta_proto_nst_meth
, all_meths
);
2805 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p
), p
,
2806 "_OBJC_ProtocolOptClassMethods",
2807 meta_proto_cls_meth
, all_meths
);
2809 if (PROTOCOL_LIST (p
))
2810 refs_decl
= generate_v2_protocol_list (p
, NULL_TREE
);
2814 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2815 protocol_name_expr
= add_objc_string (PROTOCOL_NAME (p
), class_names
);
2818 refs_expr
= convert (build_pointer_type (objc_v2_protocol_template
),
2819 build_unary_op (loc
, ADDR_EXPR
, refs_decl
, 0));
2821 refs_expr
= build_int_cst (NULL_TREE
, 0);
2823 props
= generate_v2_property_table (p
, NULL_TREE
);
2826 = generate_v2_meth_type_list (all_meths
, p
,
2827 "_OBJC_ProtocolMethodTypes");
2828 tree demangled_name
= NULL_TREE
;
2829 tree class_prop_list
= NULL_TREE
;
2831 initlist
= build_v2_protocol_initializer (TREE_TYPE (decl
),
2832 protocol_name_expr
, refs_expr
,
2833 inst_meth
, class_meth
,
2834 opt_inst_meth
, opt_class_meth
,
2835 props
, ext_meth_types
,
2836 demangled_name
,class_prop_list
);
2837 finish_var_decl (decl
, initlist
);
2838 objc_add_to_protocol_list (p
, decl
);
2839 all_meths
.truncate (0);
2844 /* Make sure we get the Protocol class linked in - reference
2846 p
= objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME
));
2847 /* ... but since we don't specifically use the reference... we
2848 need to force it. */
2849 DECL_PRESERVE_P (p
) = 1;
2854 generate_v2_dispatch_table (tree chain
, const char *name
, tree attr
)
2856 tree decl
, method_list_template
, initlist
;
2857 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2860 if (!chain
|| !name
|| !(size
= list_length (chain
)))
2863 method_list_template
2864 = build_v2_method_list_template (objc_method_template
, size
);
2866 = build_dispatch_table_initializer (objc_method_template
, chain
);
2868 decl
= start_var_decl (method_list_template
, name
);
2870 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template
));
2871 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2872 build_int_cst (integer_type_node
, init_val
));
2873 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2874 build_int_cst (integer_type_node
, size
));
2875 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
2877 OBJCMETA (decl
, objc_meta
, attr
);
2878 DECL_USER_ALIGN (decl
) = 1;
2879 finish_var_decl (decl
,
2880 objc_build_constructor (TREE_TYPE (decl
), v
));
2884 /* Init a category. */
2886 build_v2_category_initializer (tree type
, tree cat_name
, tree class_name
,
2887 tree inst_methods
, tree class_methods
,
2888 tree protocol_list
, tree property_list
,
2892 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2894 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, cat_name
);
2895 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, class_name
);
2897 ltyp
= objc_method_list_ptr
;
2899 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
2901 expr
= convert (ltyp
, null_pointer_node
);
2902 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2905 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
2907 expr
= convert (ltyp
, null_pointer_node
);
2908 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2910 /* protocol_list = */
2911 ltyp
= build_pointer_type (objc_v2_protocol_template
);
2913 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
2915 expr
= convert (ltyp
, null_pointer_node
);
2916 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2918 ltyp
= objc_prop_list_ptr
;
2920 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
2922 expr
= convert (ltyp
, null_pointer_node
);
2923 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2925 return objc_build_constructor (type
, v
);
2928 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2931 generate_v2_category (struct imp_entry
*impent
)
2933 tree initlist
, cat_name_expr
, class_name_expr
;
2934 tree protocol_decl
, category
, props
, t
;
2935 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
2936 tree cat
= impent
->imp_context
;
2937 tree cat_decl
= impent
->class_decl
;
2941 loc
= DECL_SOURCE_LOCATION (cat_decl
);
2943 /* ??? not sure this is really necessary, the following references should
2944 force appropriate linkage linkage...
2945 -- but ... ensure a reference to the class... */
2946 t
= objc_v2_get_class_reference (CLASS_NAME (cat
));
2947 /* ... which we ignore so force it out.. */
2948 DECL_PRESERVE_P (t
) = 1;
2950 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat
)));
2951 class_name_expr
= create_extern_decl (objc_v2_class_template
, buf
);
2952 class_name_expr
= build_fold_addr_expr (class_name_expr
);
2954 cat_name_expr
= add_objc_string (CLASS_SUPER_NAME (cat
), class_names
);
2955 category
= lookup_category (impent
->imp_template
, CLASS_SUPER_NAME (cat
));
2957 if (category
&& CLASS_PROTOCOL_LIST (category
))
2959 generate_protocol_references (CLASS_PROTOCOL_LIST (category
));
2960 protocol_decl
= generate_v2_protocol_list (category
, cat
);
2963 protocol_decl
= NULL_TREE
;
2965 /* decl = update_var_decl(impent->class_decl); */
2967 props
= generate_v2_property_table (NULL_TREE
, cat
);
2969 if (CLASS_NST_METHODS (cat
))
2971 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryInstanceMethods_%s_%s",
2972 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
2973 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
2974 inst_methods
= generate_v2_dispatch_table (CLASS_NST_METHODS (cat
), buf
,
2978 if (CLASS_CLS_METHODS (cat
))
2980 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryClassMethods_%s_%s",
2981 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
2982 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
2983 class_methods
= generate_v2_dispatch_table (CLASS_CLS_METHODS (cat
), buf
,
2987 initlist
= build_v2_category_initializer (TREE_TYPE (cat_decl
),
2988 cat_name_expr
, class_name_expr
,
2989 inst_methods
, class_methods
,
2990 protocol_decl
, props
, loc
);
2992 finish_var_decl (cat_decl
, initlist
);
2993 impent
->class_decl
= cat_decl
;
2995 /* Add to list of pointers in __category_list section. */
2996 objc_v2_add_to_category_list (cat_decl
);
2997 if (has_load_impl (CLASS_CLS_METHODS (impent
->imp_context
)))
2998 objc_v2_add_to_nonlazy_category_list (cat_decl
);
3001 /* This routine declares a variable to hold the offset for ivar
3002 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
3004 struct GTY(()) ivarref_entry
3010 static GTY (()) vec
<ivarref_entry
, va_gc
> *ivar_offset_refs
;
3013 ivar_offset_ref (tree class_name
, tree field_decl
)
3015 tree decl
, field_decl_id
;
3020 create_ivar_offset_name (buf
, class_name
, field_decl
);
3021 field_decl_id
= get_identifier (buf
);
3023 if (ivar_offset_refs
)
3027 FOR_EACH_VEC_ELT (*ivar_offset_refs
, count
, ref
)
3028 if (DECL_NAME (ref
->decl
) == field_decl_id
)
3032 /* Somewhat arbitrary initial provision. */
3033 vec_alloc (ivar_offset_refs
, 32);
3035 /* We come here if we don't find a match or at the start. */
3036 global_var
= (TREE_PUBLIC (field_decl
) || TREE_PROTECTED (field_decl
));
3038 decl
= create_global_decl (TREE_TYPE (size_zero_node
), buf
);
3040 decl
= create_hidden_decl (TREE_TYPE (size_zero_node
), buf
);
3042 /* Identify so that we can indirect these where the ABI requires. */
3043 OBJCMETA (decl
, objc_meta
, meta_ivar_ref
);
3046 e
.offset
= byte_position (field_decl
);
3047 vec_safe_push (ivar_offset_refs
, e
);
3051 /* This routine builds initializer-list needed to initialize 'struct
3052 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
3053 'struct ivar_t' and FIELD_DECL is list of ivars for the target
3057 build_v2_ivar_list_initializer (tree class_name
, tree type
, tree field_decl
)
3059 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
3063 vec
<constructor_elt
, va_gc
> *ivar
= NULL
;
3067 /* Unnamed bitfields are ignored. */
3068 if (!DECL_NAME (field_decl
))
3070 field_decl
= DECL_CHAIN (field_decl
);
3075 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3076 build_unary_op (input_location
,
3078 ivar_offset_ref (class_name
,
3082 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3083 add_objc_string (DECL_NAME (field_decl
),
3087 id
= add_objc_string (encode_field_decl (field_decl
),
3089 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
, id
);
3091 /* Set alignment. */
3092 val
= DECL_ALIGN_UNIT (field_decl
);
3093 val
= exact_log2 (val
);
3094 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3095 build_int_cst (integer_type_node
, val
));
3098 val
= TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl
));
3099 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3100 build_int_cst (integer_type_node
, val
));
3102 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3103 objc_build_constructor (type
, ivar
));
3106 field_decl
= DECL_CHAIN (field_decl
);
3107 while (field_decl
&& TREE_CODE (field_decl
) != FIELD_DECL
);
3111 return objc_build_constructor (build_array_type (type
, 0), inits
);
3119 struct iver_t list[count];
3124 build_v2_ivar_list_t_template (tree list_type
, int size
)
3126 tree objc_ivar_list_record
;
3127 tree decls
, *chain
= NULL
;
3130 objc_ivar_list_record
= objc_start_struct (NULL_TREE
);
3132 /* uint32 entsize; */
3133 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
3136 add_field_decl (integer_type_node
, "count", &chain
);
3138 /* struct objc_ivar ivar_list[]; */
3139 add_field_decl (build_sized_array_type (list_type
, size
),
3142 objc_finish_struct (objc_ivar_list_record
, decls
);
3143 return objc_ivar_list_record
;
3146 /* This routine declares a static variable of type 'struct
3147 ivar_list_t' and initializes it. chain is the source of the data,
3148 name is the name for the var. attr is the meta-data section tag
3149 attribute. templ is the implementation template for the class. */
3152 generate_v2_ivars_list (tree chain
, const char *name
, tree attr
, tree templ
)
3154 tree decl
, initlist
, ivar_list_template
;
3155 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
3156 int size
, ivar_t_size
;
3158 if (!chain
|| !name
|| !(size
= ivar_list_length (chain
)))
3161 generating_instance_variables
= 1;
3162 ivar_list_template
= build_v2_ivar_list_t_template (objc_v2_ivar_template
,
3165 initlist
= build_v2_ivar_list_initializer (CLASS_NAME (templ
),
3166 objc_v2_ivar_template
, chain
);
3167 ivar_t_size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template
));
3169 decl
= start_var_decl (ivar_list_template
, name
);
3170 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3171 build_int_cst (integer_type_node
, ivar_t_size
));
3172 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3173 build_int_cst (integer_type_node
, size
));
3174 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
3175 OBJCMETA (decl
, objc_meta
, attr
);
3176 DECL_USER_ALIGN (decl
) = 1;
3177 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), inits
));
3178 generating_instance_variables
= 0;
3182 /* Routine to build initializer list to initialize objects of type
3186 build_v2_class_t_initializer (tree type
, tree isa
, tree superclass
,
3187 tree ro
, tree cache
, tree vtable
)
3189 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3192 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, isa
);
3195 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, superclass
);
3199 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, cache
);
3201 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, null_pointer_node
);
3205 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, vtable
);
3207 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, null_pointer_node
);
3210 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, ro
);
3212 return objc_build_constructor (type
, initlist
);
3215 /* Routine to build object of struct class_ro_t { ... }; */
3218 build_v2_class_ro_t_initializer (tree type
, tree name
,
3219 unsigned int flags
, unsigned int instanceStart
,
3220 unsigned int instanceSize
,
3222 tree baseMethods
, tree baseProtocols
,
3223 tree ivars
, tree property_list
)
3225 tree expr
, unsigned_char_star
, ltyp
;
3227 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3229 /* TODO: fish out the real location from somewhere. */
3230 loc
= UNKNOWN_LOCATION
;
3233 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3234 build_int_cst (integer_type_node
, flags
));
3237 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3238 build_int_cst (integer_type_node
, instanceStart
));
3241 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3242 build_int_cst (integer_type_node
, instanceSize
));
3244 /* This ABI is currently only used on m64 NeXT. We always
3245 explicitly declare the alignment padding. */
3246 /* reserved, pads alignment. */
3247 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3251 unsigned_char_star
= build_pointer_type (unsigned_char_type_node
);
3255 expr
= convert (unsigned_char_star
, null_pointer_node
);
3256 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3259 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, default_conversion (name
));
3262 ltyp
= objc_method_list_ptr
;
3264 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, baseMethods
, 0));
3266 expr
= convert (ltyp
, null_pointer_node
);
3267 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3270 ltyp
= build_pointer_type (xref_tag (RECORD_TYPE
,
3271 get_identifier (UTAG_V2_PROTOCOL_LIST
)));
3273 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, baseProtocols
, 0));
3275 expr
= convert (ltyp
, null_pointer_node
);
3276 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3279 ltyp
= objc_v2_ivar_list_ptr
;
3281 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, ivars
, 0));
3283 expr
= convert (ltyp
, null_pointer_node
);
3284 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3286 /* TODO: We don't yet have the weak/strong stuff... */
3287 /* weakIvarLayout */
3288 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3289 convert (unsigned_char_star
, null_pointer_node
));
3292 ltyp
= objc_prop_list_ptr
;
3294 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
3296 expr
= convert (ltyp
, null_pointer_node
);
3297 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3298 return objc_build_constructor (type
, initlist
);
3301 static GTY (()) vec
<ident_data_tuple
, va_gc
> *ehtype_list
;
3303 /* Record a name as needing a catcher. */
3305 objc_v2_add_to_ehtype_list (tree name
)
3311 ident_data_tuple
*ref
;
3313 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3314 if (ref
->ident
== name
)
3315 return; /* Already entered. */
3318 /* Arbitrary initial count. */
3319 vec_alloc (ehtype_list
, 8);
3321 /* Not found, or new list. */
3324 vec_safe_push (ehtype_list
, e
);
3328 generate_v2_class_structs (struct imp_entry
*impent
)
3330 tree decl
, name_expr
, initlist
, protocol_decl
, metaclass_decl
, class_decl
;
3331 tree field
, firstIvar
, chain
;
3332 tree class_superclass_expr
, metaclass_superclass_expr
, props
;
3333 /* TODO: figure out how to compute this. */
3334 tree ivarLayout
= NULL_TREE
;
3335 tree my_super_id
= NULL_TREE
, root_expr
= NULL_TREE
;
3336 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
3337 tree inst_ivars
= NULL_TREE
, class_ivars
= NULL_TREE
;
3340 unsigned int instanceStart
, instanceSize
;
3341 unsigned int flags
= 0x01; /* RO_META */
3342 int cls_flags
= impent
->has_cxx_cdtors
? OBJC2_CLS_HAS_CXX_STRUCTORS
3345 class_decl
= impent
->class_decl
;
3346 metaclass_decl
= impent
->meta_decl
;
3347 loc
= DECL_SOURCE_LOCATION (class_decl
);
3349 DECL_EXTERNAL (class_decl
) = DECL_EXTERNAL (metaclass_decl
) = 0;
3350 TREE_PUBLIC (class_decl
) = TREE_PUBLIC (metaclass_decl
) = 1;
3352 gcc_assert (!CP_DECL_CONTEXT (class_decl
) || CP_DECL_CONTEXT (class_decl
) == global_namespace
);
3353 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl
) || CP_DECL_CONTEXT (metaclass_decl
) == global_namespace
);
3356 /* Generation of data for meta class. */
3357 my_super_id
= CLASS_SUPER_NAME (impent
->imp_template
);
3360 /* Compute reference to root's name. For a meta class, "isa" is
3361 a reference to the root class name. */
3362 tree my_root_id
= my_super_id
;
3363 tree my_root_int
, interface
;
3366 my_root_int
= lookup_interface (my_root_id
);
3368 if (my_root_int
&& CLASS_SUPER_NAME (my_root_int
))
3369 my_root_id
= CLASS_SUPER_NAME (my_root_int
);
3375 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3376 create extern if not already declared. */
3377 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
3378 IDENTIFIER_POINTER (CLASS_NAME (my_root_int
)));
3379 root_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3380 root_expr
= build_fold_addr_expr (root_expr
);
3382 /* Install class `isa' and `super' pointers at runtime. */
3383 interface
= lookup_interface (my_super_id
);
3384 gcc_assert (interface
);
3385 /* Similarly, for OBJC_CLASS_$_<interface>... */
3386 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s",
3387 IDENTIFIER_POINTER (CLASS_NAME (interface
)));
3388 class_superclass_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3389 class_superclass_expr
= build_fold_addr_expr (class_superclass_expr
);
3390 /* ... and for OBJC_METACLASS_$_<interface>. */
3391 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
3392 IDENTIFIER_POINTER (CLASS_NAME (interface
)));
3393 metaclass_superclass_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3394 metaclass_superclass_expr
= build_fold_addr_expr (metaclass_superclass_expr
);
3399 root_expr
= build_unary_op (loc
, ADDR_EXPR
, metaclass_decl
, 0);
3400 metaclass_superclass_expr
= build_unary_op (loc
, ADDR_EXPR
, class_decl
, 0);
3401 class_superclass_expr
= build_int_cst (NULL_TREE
, 0);
3402 flags
|= 0x02; /* RO_ROOT: it is also a root meta class. */
3405 if (CLASS_PROTOCOL_LIST (impent
->imp_template
))
3407 generate_protocol_references (CLASS_PROTOCOL_LIST (impent
->imp_template
));
3408 protocol_decl
= generate_v2_protocol_list (impent
->imp_template
,
3409 impent
->imp_context
);
3414 name_expr
= add_objc_string (CLASS_NAME (impent
->imp_template
),
3417 if (CLASS_CLS_METHODS (impent
->imp_context
))
3419 snprintf (buf
, BUFSIZE
, "_OBJC_ClassMethods_%s",
3420 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3422 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent
->imp_context
),
3423 buf
, meta_clac_meth
);
3426 instanceStart
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template
));
3428 /* Currently there are no class ivars and generation of class
3429 variables for the root of the inheritance has been removed. It
3430 causes multiple defines if there are two root classes in the
3431 link, because each will define its own identically-named offset
3434 class_ivars
= NULL_TREE
;
3435 /* TODO: Add total size of class variables when implemented. */
3436 instanceSize
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template
));
3438 /* So now build the META CLASS structs. */
3439 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3441 decl
= start_var_decl (objc_v2_class_ro_template
,
3442 newabi_append_ro (IDENTIFIER_POINTER
3443 (DECL_NAME (metaclass_decl
))));
3444 /* TODO: ivarLayout needs t be built. */
3446 build_v2_class_ro_t_initializer (TREE_TYPE (decl
), name_expr
,
3447 (flags
| cls_flags
), instanceStart
,
3448 instanceSize
, ivarLayout
,
3449 class_methods
, protocol_decl
,
3450 class_ivars
, NULL_TREE
);
3451 /* The ROs sit in the default const section. */
3452 OBJCMETA (decl
, objc_meta
, meta_base
);
3453 DECL_USER_ALIGN (decl
) = 1;
3454 finish_var_decl (decl
, initlist
);
3456 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3458 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl
),
3460 metaclass_superclass_expr
,
3461 build_fold_addr_expr (decl
),
3462 build_fold_addr_expr (UOBJC_V2_CACHE_decl
),
3463 build_fold_addr_expr (UOBJC_V2_VTABLE_decl
));
3464 /* The class section attributes are set when they are created. */
3465 DECL_USER_ALIGN (metaclass_decl
) = 1;
3466 finish_var_decl (metaclass_decl
, initlist
);
3467 impent
->meta_decl
= metaclass_decl
;
3469 /* So now build the CLASS structs. */
3471 flags
= 0x0; /* ... */
3473 flags
|= 0x02; /* RO_ROOT: this is a root class */
3475 if (DECL_VISIBILITY (class_decl
) == VISIBILITY_HIDDEN
)
3476 flags
|= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3478 if (objc2_objc_exception_attr (impent
->imp_template
))
3479 flags
|= 0x20; /* RO_EXCEPTION */
3481 if (CLASS_NST_METHODS (impent
->imp_context
))
3483 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceMethods_%s",
3484 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3486 generate_v2_dispatch_table (CLASS_NST_METHODS (impent
->imp_context
),
3487 buf
, meta_clai_meth
);
3490 /* Sort out the ivars before we try to compute the class sizes. */
3491 if ((chain
= CLASS_IVARS (impent
->imp_template
)))
3493 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceIvars_%s",
3494 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3495 inst_ivars
= generate_v2_ivars_list (chain
, buf
, meta_clai_vars
,
3496 impent
->imp_template
);
3499 /* Compute instanceStart. */
3500 gcc_assert (CLASS_STATIC_TEMPLATE (impent
->imp_template
));
3501 field
= TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent
->imp_template
));
3502 if (my_super_id
&& field
&& TREE_CHAIN (field
))
3503 field
= TREE_CHAIN (field
);
3507 while (firstIvar
&& TREE_CODE (firstIvar
) != FIELD_DECL
)
3508 firstIvar
= TREE_CHAIN (firstIvar
);
3510 gcc_assert (inst_ivars
? (firstIvar
!= NULL_TREE
): true);
3512 /* Compute instanceSize. */
3513 while (field
&& TREE_CHAIN (field
)
3514 && TREE_CODE (TREE_CHAIN (field
)) == FIELD_DECL
)
3515 field
= TREE_CHAIN (field
);
3517 if (field
&& TREE_CODE (field
) == FIELD_DECL
)
3518 instanceSize
= int_byte_position (field
) * BITS_PER_UNIT
3519 + tree_to_shwi (DECL_SIZE (field
));
3522 instanceSize
/= BITS_PER_UNIT
;
3524 props
= generate_v2_property_table (NULL_TREE
, impent
->imp_context
);
3526 /* If the class has no ivars, instanceStart should be set to the
3527 superclass's instanceSize. */
3529 (inst_ivars
!= NULL_TREE
) ? (unsigned) int_byte_position (firstIvar
)
3532 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3533 decl
= start_var_decl (objc_v2_class_ro_template
,
3534 newabi_append_ro (IDENTIFIER_POINTER
3535 (DECL_NAME (class_decl
))));
3538 build_v2_class_ro_t_initializer (TREE_TYPE (decl
), name_expr
,
3539 (flags
| cls_flags
), instanceStart
,
3540 instanceSize
, ivarLayout
,
3541 inst_methods
, protocol_decl
,
3543 /* The ROs sit in the default const section. */
3544 OBJCMETA (decl
, objc_meta
, meta_base
);
3545 DECL_USER_ALIGN (decl
) = 1;
3546 finish_var_decl (decl
, initlist
);
3548 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3549 initlist
= build_v2_class_t_initializer (TREE_TYPE (class_decl
),
3550 build_fold_addr_expr (metaclass_decl
),
3551 class_superclass_expr
,
3552 build_fold_addr_expr (decl
),
3553 build_fold_addr_expr (UOBJC_V2_CACHE_decl
),
3554 build_fold_addr_expr (UOBJC_V2_VTABLE_decl
));
3556 /* The class section attributes are set when they are created. */
3557 DECL_USER_ALIGN (class_decl
) = 1;
3558 finish_var_decl (class_decl
, initlist
);
3559 impent
->class_decl
= class_decl
;
3561 objc_v2_add_to_class_list (class_decl
);
3562 if (has_load_impl (CLASS_CLS_METHODS (impent
->imp_context
)))
3563 objc_v2_add_to_nonlazy_class_list (class_decl
);
3565 if (flags
& 0x20) /* RO_EXCEPTION */
3566 objc_v2_add_to_ehtype_list (CLASS_NAME (impent
->imp_template
));
3569 /* This routine outputs the (ivar_reference_offset, offset)
3573 build_v2_ivar_offset_ref_table (void)
3578 if (!vec_safe_length (ivar_offset_refs
))
3581 FOR_EACH_VEC_ELT (*ivar_offset_refs
, count
, ref
)
3582 finish_var_decl (ref
->decl
, ref
->offset
);
3586 objc_generate_v2_next_metadata (void)
3588 struct imp_entry
*impent
;
3590 /* FIXME: Make sure that we generate no metadata if there is nothing
3593 gcc_assert (!objc_static_instances
); /* Not for NeXT */
3595 build_metadata_templates ();
3597 for (impent
= imp_list
; impent
; impent
= impent
->next
)
3599 /* If -gen-decls is present, Dump the @interface of each class.
3600 TODO: Dump the classes in the order they were found, rather
3601 than in reverse order as we are doing now. */
3602 if (flag_gen_declaration
)
3603 dump_interface (gen_declaration_file
, impent
->imp_context
);
3605 /* all of the following reference the string pool... */
3606 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
3607 generate_v2_class_structs (impent
);
3609 generate_v2_category (impent
);
3612 build_next_selector_translation_table ();
3613 build_v2_message_ref_translation_table ();
3615 /* This will add "Protocol" to the class refs. */
3616 generate_v2_protocols ();
3618 build_v2_classrefs_table ();
3619 build_v2_super_classrefs_table (/*metaclass= */false);
3620 build_v2_super_classrefs_table (/*metaclass= */true);
3622 build_v2_ivar_offset_ref_table ();
3624 build_v2_protocol_list_translation_table ();
3625 build_v2_protocol_list_address_table ();
3627 build_v2_address_table (class_list
, "_OBJC_ClassList$",
3628 meta_label_classlist
);
3629 build_v2_address_table (category_list
, "_OBJC_CategoryList$",
3630 meta_label_categorylist
);
3631 build_v2_address_table (nonlazy_class_list
, "_OBJC_NonLazyClassList$",
3632 meta_label_nonlazy_classlist
);
3633 build_v2_address_table (nonlazy_category_list
, "_OBJC_NonLazyCategoryList$",
3634 meta_label_nonlazy_categorylist
);
3636 /* Generate catch objects for eh, if any are needed. */
3637 build_v2_eh_catch_objects ();
3639 /* Emit the string table last. */
3640 generate_strings ();
3643 /* NOTE --- Output NeXT V2 Exceptions --- */
3645 static GTY(()) tree objc_v2_ehtype_template
;
3646 static GTY(()) tree next_v2_ehvtable_decl
;
3647 static GTY(()) tree next_v2_EHTYPE_id_decl
;
3650 build_v2_ehtype_template (void)
3652 tree decls
, *chain
= NULL
;
3653 objc_v2_ehtype_template
= objc_start_struct (get_identifier (UTAG_V2_EH_TYPE
));
3655 /* void *_objc_ehtype_vtable; */
3656 decls
= add_field_decl (ptr_type_node
, "_objc_ehtype_vtable_ptr", &chain
);
3658 /* const char *className; */
3659 add_field_decl (string_type_node
, "className", &chain
);
3661 /* struct class_t *const cls; */
3662 add_field_decl (build_pointer_type (objc_v2_class_template
), "cls", &chain
);
3664 objc_finish_struct (objc_v2_ehtype_template
, decls
);
3667 /* Template for the Objective-C family typeinfo type for ABI=2. This
3668 starts off the same as the gxx/cxx eh typeinfo.
3670 struct _objc_ehtype_t
3672 void *_objc_ehtype_vtable_ptr; - as per c++
3673 const char *className; - as per c++
3674 struct class_t *const cls;
3678 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3682 objc2_build_ehtype_initializer (tree name
, tree cls
)
3684 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3687 /* This is done the same way as c++, missing the two first entries
3688 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3689 runtime source about this so, perhaps, this will change at some
3691 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3692 if (!next_v2_ehvtable_decl
)
3694 next_v2_ehvtable_decl
=
3695 start_var_decl (ptr_type_node
, TAG_NEXT_EHVTABLE_NAME
);
3696 TREE_STATIC (next_v2_ehvtable_decl
) = 0;
3697 DECL_EXTERNAL (next_v2_ehvtable_decl
) = 1;
3698 TREE_PUBLIC (next_v2_ehvtable_decl
) = 1;
3700 addr
= build_fold_addr_expr_with_type (next_v2_ehvtable_decl
, ptr_type_node
);
3701 offs
= size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node
)));
3702 addr
= fold_build_pointer_plus (addr
, offs
);
3704 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, addr
);
3707 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, name
);
3710 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, cls
);
3712 return objc_build_constructor (objc_v2_ehtype_template
, initlist
);
3716 build_ehtype (tree name
, const char *eh_name
, bool weak
)
3718 tree name_expr
, class_name_expr
, ehtype_decl
, inits
;
3720 name_expr
= add_objc_string (name
, class_names
);
3721 /* Extern ref. for the class. ??? Maybe we can look this up
3724 create_extern_decl (objc_v2_class_template
,
3725 objc_build_internal_classname (name
, false));
3726 class_name_expr
= build_fold_addr_expr (class_name_expr
);
3727 ehtype_decl
= create_global_decl (objc_v2_ehtype_template
, eh_name
);
3729 DECL_WEAK (ehtype_decl
) = 1;
3730 inits
= objc2_build_ehtype_initializer (name_expr
, class_name_expr
);
3731 OBJCMETA (ehtype_decl
, objc_meta
, meta_ehtype
);
3732 DECL_USER_ALIGN (ehtype_decl
) = 1;
3733 finish_var_decl (ehtype_decl
, inits
);
3737 /* This routine returns TRUE if CLS or any of its super classes has
3738 __attribute__ ((objc_exception)). */
3741 objc2_objc_exception_attr (tree cls
)
3745 if (CLASS_HAS_EXCEPTION_ATTR (cls
))
3747 cls
= lookup_interface (CLASS_SUPER_NAME (cls
));
3754 is_implemented (tree name
)
3756 struct imp_entry
*t
;
3757 for (t
= imp_list
; t
; t
= t
->next
)
3758 if (TREE_CODE (t
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
3759 && CLASS_NAME (t
->imp_template
) == name
)
3765 /* We will build catch objects:
3766 for any type implemented here.
3767 for any type used in a catch that has no exception attribute. */
3768 static void build_v2_eh_catch_objects (void)
3771 ident_data_tuple
*ref
;
3773 if (!vec_safe_length (ehtype_list
))
3776 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3779 bool impl
= is_implemented (ref
->ident
);
3780 bool excpt
= objc2_objc_exception_attr (lookup_interface (ref
->ident
));
3781 snprintf (buf
, BUFSIZE
, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref
->ident
));
3783 /* The User says this class has a catcher already. */
3784 ref
->data
= create_extern_decl (objc_v2_ehtype_template
, buf
);
3786 /* Create a catcher, weak if it wasn't marked. */
3787 ref
->data
= build_ehtype (ref
->ident
, buf
, !excpt
);
3792 lookup_ehtype_ref (tree id
)
3795 ident_data_tuple
*ref
;
3797 if (!vec_safe_length (ehtype_list
))
3800 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3801 if (ref
->ident
== id
)
3806 /* This hook, called via lang_eh_runtime_type, generates a runtime
3807 object which is either the address of the 'OBJC_EHTYPE_$_class'
3808 object or address of external OBJC_EHTYPE_id object. */
3810 next_runtime_02_eh_type (tree type
)
3814 if (type
== error_mark_node
3815 /*|| errorcount || sorrycount*/)
3818 if (POINTER_TYPE_P (type
) && objc_is_object_id (TREE_TYPE (type
)))
3820 if (!next_v2_EHTYPE_id_decl
)
3822 /* This is provided by the Apple/NeXT libobjc.dylib so we
3823 need only to reference it. */
3824 next_v2_EHTYPE_id_decl
=
3825 start_var_decl (objc_v2_ehtype_template
, "OBJC_EHTYPE_id");
3826 DECL_EXTERNAL (next_v2_EHTYPE_id_decl
) = 1;
3827 TREE_PUBLIC (next_v2_EHTYPE_id_decl
) = 1;
3828 TREE_STATIC (next_v2_EHTYPE_id_decl
) = 0;
3830 return build_fold_addr_expr (next_v2_EHTYPE_id_decl
);
3833 if (!POINTER_TYPE_P (type
) || !TYPED_OBJECT (TREE_TYPE (type
)))
3836 /* This routine is also called for c++'s catch clause; in which
3837 case, we use c++'s typeinfo decl. */
3838 return build_eh_type_type (type
);
3840 error ("non-objective-c type %qT cannot be caught", type
);
3845 t
= OBJC_TYPE_NAME (TREE_TYPE (type
));
3847 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3848 t
= lookup_ehtype_ref (t
);
3852 return build_fold_addr_expr (t
);
3855 return error_mark_node
;
3858 static GTY(()) tree objc_eh_personality_decl
;
3861 objc_eh_personality (void)
3863 if (!objc_eh_personality_decl
)
3864 objc_eh_personality_decl
= build_personality_function ("objc");
3865 return objc_eh_personality_decl
;
3868 /* NOTE --- interfaces --- */
3871 build_throw_stmt (location_t loc
, tree throw_expr
, bool rethrown
)
3875 /* We have a separate re-throw entry. */
3876 t
= build_function_call_vec (loc
, vNULL
, objc_rethrow_exception_decl
,
3880 /* Throw like the others... */
3881 vec
<tree
, va_gc
> *parms
;
3882 vec_alloc (parms
, 1);
3883 parms
->quick_push (throw_expr
);
3884 t
= build_function_call_vec (loc
, vNULL
, objc_exception_throw_decl
,
3888 return add_stmt (t
);
3891 /* Build __builtin_eh_pointer. */
3894 objc_build_exc_ptr (struct objc_try_context
**x ATTRIBUTE_UNUSED
)
3897 t
= builtin_decl_explicit (BUILT_IN_EH_POINTER
);
3898 t
= build_call_expr (t
, 1, integer_zero_node
);
3899 return fold_convert (objc_object_type
, t
);
3902 static tree
begin_catch (struct objc_try_context
**cur_try_context
, tree type
,
3903 tree decl
, tree compound
, bool ellipsis ATTRIBUTE_UNUSED
)
3907 /* Record the data for the catch in the try context so that we can
3908 finalize it later. Ellipsis is signalled by a NULL entry. */
3910 t
= build_stmt (input_location
, CATCH_EXPR
, NULL_TREE
, compound
);
3912 t
= build_stmt (input_location
, CATCH_EXPR
, type
, compound
);
3913 (*cur_try_context
)->current_catch
= t
;
3915 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3916 t
= objc_build_exc_ptr (cur_try_context
);
3917 t
= convert (TREE_TYPE (decl
), t
);
3918 /* FIXME: location. */
3919 if (type
&& type
!= error_mark_node
)
3921 t
= build1(NOP_EXPR
, ptr_type_node
, t
);
3922 t
= build_function_call (input_location
, objc2_begin_catch_decl
,
3923 tree_cons (NULL_TREE
, t
, NULL_TREE
));
3925 /* We might want to build a catch object for this (if it's not
3927 if (POINTER_TYPE_P (type
)
3928 && !objc_is_object_id (TREE_TYPE (type
))
3929 && TYPED_OBJECT (TREE_TYPE (type
)))
3930 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type
)));
3932 return build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
3935 /* try { catch-body } finally { objc_end_catch (); } */
3937 finish_catch (struct objc_try_context
**cur_try_context
, tree curr_catch
)
3939 struct objc_try_context
*ct
;
3940 tree try_exp
, func
, *l
, t
;
3941 location_t loc
= (*cur_try_context
)->try_locus
;
3943 if (!curr_catch
|| curr_catch
== error_mark_node
)
3946 t
= CATCH_BODY (curr_catch
);
3947 if (TREE_CODE (t
) == BIND_EXPR
)
3949 /* Usual case of @catch (objc-expr). */
3950 objc_begin_try_stmt (loc
, BIND_EXPR_BODY (t
));
3951 BIND_EXPR_BODY (t
) = NULL_TREE
;
3952 l
= &BIND_EXPR_BODY (t
);
3956 /* NULL entry, meaning @catch (...). */
3957 objc_begin_try_stmt (loc
, t
);
3958 CATCH_BODY (curr_catch
) = NULL_TREE
;
3959 l
= &CATCH_BODY (curr_catch
);
3962 /* Pick up the new context we made in begin_try above... */
3963 ct
= *cur_try_context
;
3964 func
= build_function_call_vec (loc
, vNULL
, objc2_end_catch_decl
, NULL
,
3966 append_to_statement_list (func
, &ct
->finally_body
);
3967 try_exp
= build_stmt (loc
, TRY_FINALLY_EXPR
, ct
->try_body
, ct
->finally_body
);
3968 *cur_try_context
= ct
->outer
;
3970 append_to_statement_list (try_exp
, l
);
3971 append_to_statement_list (curr_catch
, &((*cur_try_context
)->catch_list
));
3975 finish_try_stmt (struct objc_try_context
**cur_try_context
)
3977 struct objc_try_context
*c
= *cur_try_context
;
3978 tree stmt
= c
->try_body
;
3980 stmt
= build_stmt (c
->try_locus
, TRY_CATCH_EXPR
, stmt
, c
->catch_list
);
3981 if (c
->finally_body
)
3982 stmt
= build_stmt (c
->try_locus
, TRY_FINALLY_EXPR
, stmt
, c
->finally_body
);
3986 #include "gt-objc-objc-next-runtime-abi-02.h"