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 TAG_FIXUP "_fixup"
78 #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
79 #define TAG_V2_EH_TYPE "objc_ehtype_t"
81 #define UTAG_V2_CLASS "_class_t"
82 #define UTAG_V2_CLASS_RO "_class_ro_t"
83 #define UTAG_V2_PROTOCOL "_protocol_t"
84 #define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
86 #define UTAG_V2_EH_TYPE "_objc_ehtype_t"
88 #define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
90 enum objc_v2_tree_index
98 OCTI_V2_IVAR_LIST_TEMPL
,
99 OCTI_V2_MESSAGE_REF_TEMPL
,
100 OCTI_V2_SUPER_MESSAGE_REF_TEMPL
,
102 OCTI_V2_MESSAGE_SELECTOR_TYPE
,
103 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE
,
105 OCTI_V2_SUPER_IMP_TYPE
,
110 OCTI_V2_PROPERTY_TEMPL
,
113 OCTI_V2_UMSG_FIXUP_DECL
,
114 OCTI_V2_UMSG_STRET_FIXUP_DECL
,
115 OCTI_V2_UMSG_ID_FIXUP_DECL
,
116 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL
,
117 OCTI_V2_UMSG_SUPER2_FIXUP_DECL
,
118 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL
,
120 /* Exceptions - related. */
121 OCTI_V2_BEGIN_CATCH_DECL
,
122 OCTI_V2_END_CATCH_DECL
,
123 OCTI_V2_RETHROW_DECL
,
128 #define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
129 #define objc_v2_class_ro_template \
130 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
131 #define objc_v2_category_template \
132 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
133 #define objc_v2_protocol_template \
134 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
136 /* struct message_ref_t */
137 #define objc_v2_message_ref_template \
138 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
140 #define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
142 /* struct super_message_ref_t */
143 #define objc_v2_super_message_ref_template \
144 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
146 /* struct message_ref_t* */
147 #define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
148 /* struct super_super_message_ref_t */
149 #define objc_v2_super_selector_type \
150 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
151 #define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
152 #define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
154 #define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
155 #define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
157 #define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
158 #define objc_v2_property_template \
159 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
163 /* objc_msgSend_fixup_rtp */
164 #define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
165 /* objc_msgSend_stret_fixup_rtp */
166 #define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
167 /* objc_msgSendId_fixup_rtp */
168 #define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
169 /* objc_msgSendId_stret_fixup_rtp */
170 #define umsg_id_stret_fixup_decl \
171 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
172 /* objc_msgSendSuper2_fixup_rtp */
173 #define umsg_id_super2_fixup_decl \
174 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
175 /* objc_msgSendSuper2_stret_fixup_rtp */
176 #define umsg_id_super2_stret_fixup_decl \
177 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
179 #define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
180 #define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
181 #define objc_rethrow_exception_decl \
182 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
184 /* The OCTI_V2_... enumeration itself is in above. */
185 static GTY(()) tree objc_v2_global_trees
[OCTI_V2_MAX
];
187 static void next_runtime_02_initialize (void);
189 static void build_v2_message_ref_templates (void);
190 static void build_v2_class_templates (void);
191 static void build_v2_super_template (void);
192 static void build_v2_category_template (void);
193 static void build_v2_protocol_template (void);
195 static tree
next_runtime_abi_02_super_superclassfield_id (void);
197 static tree
next_runtime_abi_02_class_decl (tree
);
198 static tree
next_runtime_abi_02_metaclass_decl (tree
);
199 static tree
next_runtime_abi_02_category_decl (tree
);
200 static tree
next_runtime_abi_02_protocol_decl (tree
);
201 static tree
next_runtime_abi_02_string_decl (tree
, const char *, string_section
);
203 static tree
next_runtime_abi_02_get_class_reference (tree
);
204 static tree
next_runtime_abi_02_build_selector_reference (location_t
, tree
, tree
);
205 static tree
next_runtime_abi_02_get_protocol_reference (location_t
, tree
);
206 static tree
next_runtime_abi_02_build_ivar_ref (location_t
, tree
, tree
);
207 static tree
next_runtime_abi_02_get_class_super_ref (location_t
, struct imp_entry
*, bool);
208 static tree
next_runtime_abi_02_get_category_super_ref (location_t
, struct imp_entry
*, bool);
210 static tree
next_runtime_abi_02_receiver_is_class_object (tree
);
211 static void next_runtime_abi_02_get_arg_type_list_base (vec
<tree
, va_gc
> **,
213 static tree
next_runtime_abi_02_build_objc_method_call (location_t
, tree
, tree
,
214 tree
, tree
, tree
, int);
215 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
216 static tree
next_runtime_abi_02_build_const_string_constructor (location_t
, tree
, int);
218 static tree
create_extern_decl (tree
, const char *);
220 static void objc_generate_v2_next_metadata (void);
221 static bool objc2_objc_exception_attr (tree
);
223 /* void build_v2_protocol_reference (tree);*/
224 static void build_v2_ehtype_template (void);
225 static void build_v2_eh_catch_objects (void);
226 static tree
next_runtime_02_eh_type (tree
);
227 static tree
objc_eh_personality (void);
228 static tree
build_throw_stmt (location_t
, tree
, bool);
229 static tree
objc_build_exc_ptr (struct objc_try_context
**);
230 static tree
begin_catch (struct objc_try_context
**, tree
, tree
, tree
, bool);
231 static void finish_catch (struct objc_try_context
**, tree
);
232 static tree
finish_try_stmt (struct objc_try_context
**);
234 /* TODO: Use an objc-map. */
235 static GTY ((length ("SIZEHASHTABLE"))) hash
*extern_names
;
238 objc_next_runtime_abi_02_init (objc_runtime_hooks
*rthooks
)
240 extern_names
= ggc_cleared_vec_alloc
<hash
> (SIZEHASHTABLE
);
242 if (flag_objc_sjlj_exceptions
)
244 inform (UNKNOWN_LOCATION
,
245 "%<-fobjc-sjlj-exceptions%> is ignored for "
246 "%<-fnext-runtime%> when %<-fobjc-abi-version%> "
248 flag_objc_sjlj_exceptions
= 0;
251 /* NeXT ABI 2 is intended to default to checking for nil receivers. */
252 if (! OPTION_SET_P (flag_objc_nilcheck
))
253 flag_objc_nilcheck
= 1;
255 rthooks
->initialize
= next_runtime_02_initialize
;
256 rthooks
->default_constant_string_class_name
= DEF_CONSTANT_STRING_CLASS_NAME
;
257 rthooks
->tag_getclass
= TAG_GETCLASS
;
258 rthooks
->super_superclassfield_ident
= next_runtime_abi_02_super_superclassfield_id
;
260 rthooks
->class_decl
= next_runtime_abi_02_class_decl
;
261 rthooks
->metaclass_decl
= next_runtime_abi_02_metaclass_decl
;
262 rthooks
->category_decl
= next_runtime_abi_02_category_decl
;
263 rthooks
->protocol_decl
= next_runtime_abi_02_protocol_decl
;
264 rthooks
->string_decl
= next_runtime_abi_02_string_decl
;
266 rthooks
->get_class_reference
= next_runtime_abi_02_get_class_reference
;
267 rthooks
->build_selector_reference
= next_runtime_abi_02_build_selector_reference
;
268 rthooks
->get_protocol_reference
= next_runtime_abi_02_get_protocol_reference
;
269 rthooks
->build_ivar_reference
= next_runtime_abi_02_build_ivar_ref
;
270 rthooks
->get_class_super_ref
= next_runtime_abi_02_get_class_super_ref
;
271 rthooks
->get_category_super_ref
= next_runtime_abi_02_get_category_super_ref
;
273 rthooks
->receiver_is_class_object
= next_runtime_abi_02_receiver_is_class_object
;
274 rthooks
->get_arg_type_list_base
= next_runtime_abi_02_get_arg_type_list_base
;
275 rthooks
->build_objc_method_call
= next_runtime_abi_02_build_objc_method_call
;
277 rthooks
->setup_const_string_class_decl
=
278 next_runtime_abi_02_setup_const_string_class_decl
;
279 rthooks
->build_const_string_constructor
=
280 next_runtime_abi_02_build_const_string_constructor
;
282 rthooks
->build_throw_stmt
= build_throw_stmt
;
283 rthooks
->build_exc_ptr
= objc_build_exc_ptr
;
284 rthooks
->begin_catch
= begin_catch
;
285 rthooks
->finish_catch
= finish_catch
;
286 rthooks
->finish_try_stmt
= finish_try_stmt
;
288 rthooks
->generate_metadata
= objc_generate_v2_next_metadata
;
292 /* We need a way to convey what kind of meta-data are represented by a given
293 variable, since each type is expected (by the runtime) to be found in a
294 specific named section. The solution must be usable with LTO.
296 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
297 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
298 identification attributes in the front end. The back-end may choose to act
299 on these as it requires. */
302 next_runtime_abi_02_init_metadata_attributes (void)
305 objc_meta
= get_identifier ("OBJC2META");
308 meta_base
= get_identifier ("V2_BASE");
310 meta_class
= get_identifier ("G2_CLAS");
311 meta_metaclass
= get_identifier ("G2_META");
312 meta_category
= meta_base
;
313 meta_protocol
= get_identifier ("V2_PCOL");
316 meta_clai_vars
= meta_base
;
322 meta_proto_cls_meth
=
323 meta_proto_nst_meth
= meta_base
;
326 meta_catg_prot
= meta_base
;
328 meta_sel_refs
= get_identifier ("V2_SRFS");
330 meta_class_name
= get_identifier ("V2_CNAM");
331 meta_meth_name
= get_identifier ("V2_MNAM");
333 meta_meth_type
= get_identifier ("V2_MTYP");
334 meta_prop_name_attr
= get_identifier ("V2_STRG");
336 meta_mref
= get_identifier ("V2_MREF");
337 meta_class_ref
= get_identifier ("V2_CLRF");
338 meta_superclass_ref
= get_identifier ("V2_SURF");
340 meta_label_classlist
= get_identifier ("V2_CLAB");
341 meta_label_nonlazy_classlist
= get_identifier ("V2_NLCL");
342 meta_label_categorylist
= get_identifier ("V2_CALA");
343 meta_label_nonlazy_categorylist
= get_identifier ("V2_NLCA");
345 meta_label_protocollist
= get_identifier ("V2_PLST");
346 meta_proto_ref
= get_identifier ("V2_PRFS");
348 meta_info
= get_identifier ("V2_INFO");
350 meta_ehtype
= get_identifier ("V2_EHTY");
352 meta_const_str
= get_identifier ("V2_CSTR");
354 meta_ivar_ref
= get_identifier ("V2_IVRF");
357 static void next_runtime_02_initialize (void)
361 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
363 if (!OPTION_SET_P (flag_objc_call_cxx_cdtors
))
364 global_options
.x_flag_objc_call_cxx_cdtors
= 1;
367 /* Set up attributes to be attached to the meta-data so that they
368 will be placed in the correct sections. */
369 next_runtime_abi_02_init_metadata_attributes ();
371 /* `struct objc_selector *' */
372 objc_selector_type
= build_pointer_type (xref_tag (RECORD_TYPE
,
373 get_identifier (TAG_SELECTOR
)));
376 type
= lang_hooks
.decls
.pushdecl (build_decl (input_location
,
379 objc_selector_type
));
380 suppress_warning (type
);
382 /* IMP : id (*) (id, _message_ref_t*, ...)
383 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
384 objc_v2_selector_type. */
385 build_v2_message_ref_templates ();
387 objc_v2_ivar_list_ptr
=
388 build_pointer_type (xref_tag (RECORD_TYPE
,
389 get_identifier ("_ivar_list_t")));
392 build_pointer_type (xref_tag (RECORD_TYPE
,
393 get_identifier ("_prop_list_t")));
395 build_v2_class_templates ();
396 build_v2_super_template ();
397 build_v2_protocol_template ();
398 build_v2_category_template ();
400 bool fixup_p
= flag_next_runtime
< USE_FIXUP_BEFORE
;
403 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
404 type
= build_varargs_function_type_list (objc_object_type
,
406 objc_v2_selector_type
,
411 /* id objc_msgSendXXXX (id, SEL, ...); */
412 type
= build_varargs_function_type_list (objc_object_type
,
417 const char *fnam
= fixup_p
? TAG_MSGSEND TAG_FIXUP
: TAG_MSGSEND
;
418 umsg_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
420 TREE_NOTHROW (umsg_fixup_decl
) = 0;
422 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
423 fnam
= fixup_p
? TAG_MSGSEND_STRET TAG_FIXUP
: TAG_MSGSEND_STRET
;
424 umsg_stret_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
426 TREE_NOTHROW (umsg_stret_fixup_decl
) = 0;
428 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
429 fnam
= fixup_p
? TAG_MSGSENDID TAG_FIXUP
: TAG_MSGSENDID
;
430 umsg_id_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
432 TREE_NOTHROW (umsg_id_fixup_decl
) = 0;
434 /* id objc_msgSendId_stret_fixup_rtp (id, struct message_ref_t*, ...); */
435 fnam
= fixup_p
? TAG_MSGSENDID_STRET TAG_FIXUP
: TAG_MSGSENDID_STRET
;
436 umsg_id_stret_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
438 TREE_NOTHROW (umsg_id_stret_fixup_decl
) = 0;
440 /* id objc_msgSendSuper2_fixup_rtp
441 (struct objc_super *, struct message_ref_t*, ...); */
442 type
= build_varargs_function_type_list (objc_object_type
,
444 objc_v2_super_selector_type
,
446 fnam
= fixup_p
? TAG_MSGSENDSUPER TAG_FIXUP
: TAG_MSGSENDSUPER
;
447 umsg_id_super2_fixup_decl
= add_builtin_function (fnam
, type
, 0, NOT_BUILT_IN
,
449 TREE_NOTHROW (umsg_id_super2_fixup_decl
) = 0;
451 /* id objc_msgSendSuper2_stret_fixup_rtp
452 (struct objc_super *, struct message_ref_t*, ...); */
453 fnam
= fixup_p
? TAG_MSGSENDSUPER_STRET TAG_FIXUP
: TAG_MSGSENDSUPER_STRET
;
454 umsg_id_super2_stret_fixup_decl
= add_builtin_function (fnam
, type
, 0,
457 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl
) = 0;
459 /* Present in the library, but unused by the FE. */
460 /* Protocol *objc_getProtocol (const char *)
461 type = build_function_type_list (objc_protocol_type,
462 const_string_type_node,
464 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
465 type, 0, NOT_BUILT_IN,
467 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
469 UOBJC_V2_CACHE_decl
= create_extern_decl (ptr_type_node
,
470 "_objc_empty_cache");
472 UOBJC_V2_VTABLE_decl
= create_extern_decl (objc_v2_imp_type
,
473 "_objc_empty_vtable");
475 /* id objc_getClass (const char *); */
476 type
= build_function_type_list (objc_object_type
,
477 const_string_type_node
,
479 objc_get_class_decl
= add_builtin_function (TAG_GETCLASS
,
480 type
, 0, NOT_BUILT_IN
,
483 /* id objc_getMetaClass (const char *); */
484 objc_get_meta_class_decl
= add_builtin_function (TAG_GETMETACLASS
,
485 type
, 0, NOT_BUILT_IN
,
488 /* This is the type of all of the following functions
489 objc_copyStruct(). */
490 type
= build_function_type_list (void_type_node
,
497 /* Declare the following function:
499 objc_copyStruct (void *destination, const void *source,
500 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
501 objc_copyStruct_decl
= add_builtin_function ("objc_copyStruct",
502 type
, 0, NOT_BUILT_IN
,
504 TREE_NOTHROW (objc_copyStruct_decl
) = 0;
505 objc_getPropertyStruct_decl
= NULL_TREE
;
506 objc_setPropertyStruct_decl
= NULL_TREE
;
508 gcc_checking_assert (!flag_objc_sjlj_exceptions
);
510 /* Although we warn that fobjc-exceptions is required for exceptions
511 code, we carry on and create it anyway. */
513 /* This can be required, even when exceptions code is not present,
514 when an __attribute__((objc_exception)) is applied to a
516 build_v2_ehtype_template ();
518 /* void * objc_begin_catch (void *) */
519 type
= build_function_type_list (ptr_type_node
,
520 ptr_type_node
, NULL_TREE
);
522 objc2_begin_catch_decl
= add_builtin_function ("objc_begin_catch",
523 type
, 0, NOT_BUILT_IN
,
525 TREE_NOTHROW (objc2_begin_catch_decl
) = 0;
527 /* void objc_end_catch () */
528 type
= build_function_type_list (void_type_node
, NULL_TREE
);
529 objc2_end_catch_decl
= add_builtin_function ("objc_end_catch",
530 type
, 0, NOT_BUILT_IN
,
532 TREE_NOTHROW (objc2_end_catch_decl
) = 0;
534 /* void objc_exception_rethrow (void) */
535 objc_rethrow_exception_decl
=
536 add_builtin_function ("objc_exception_rethrow",
537 type
, 0, NOT_BUILT_IN
,
539 TREE_NOTHROW (objc_rethrow_exception_decl
) = 0;
540 using_eh_for_cleanups ();
541 lang_hooks
.eh_runtime_type
= next_runtime_02_eh_type
;
542 lang_hooks
.eh_personality
= objc_eh_personality
;
545 /* NOTE --- templates --- */
547 /* Set 'objc_v2_message_ref_template' to the data type node for
548 'struct _message_ref_t'. This needs to be done just once per
549 compilation. Also Set 'objc_v2_super_message_ref_template' to data
550 type node for 'struct _super_message_ref_t'. */
552 /* struct _message_ref_t
557 where IMP is: id (*) (id, _message_ref_t*, ...)
560 /* struct _super_message_ref_t
565 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
569 build_v2_message_ref_templates (void)
571 tree ptr_message_ref_t
;
572 tree decls
, *chain
= NULL
;
574 /* struct _message_ref_t {...} */
575 objc_v2_message_ref_template
=
576 objc_start_struct (get_identifier ("_message_ref_t"));
580 build_pointer_type (xref_tag (RECORD_TYPE
,
581 get_identifier ("_message_ref_t")));
584 build_pointer_type (build_function_type_list
590 decls
= add_field_decl (objc_v2_imp_type
, "messenger", &chain
);
593 add_field_decl (objc_selector_type
, "name", &chain
);
595 objc_finish_struct (objc_v2_message_ref_template
, decls
);
597 objc_v2_selector_type
= build_pointer_type (objc_v2_message_ref_template
);
600 /* struct _super_message_ref_t {...} */
601 objc_v2_super_message_ref_template
=
602 objc_start_struct (get_identifier ("_super_message_ref_t"));
604 /* SUPER_IMP messenger; */
605 ptr_message_ref_t
= build_pointer_type
606 (xref_tag (RECORD_TYPE
,
607 get_identifier ("_super_message_ref_t")));
609 objc_v2_super_imp_type
=
610 build_pointer_type (build_function_type_list
616 add_field_decl (objc_v2_super_imp_type
, "messenger", &chain
);
619 add_field_decl (objc_selector_type
, "name", &chain
);
621 objc_finish_struct (objc_v2_super_message_ref_template
, decls
);
622 objc_v2_super_selector_type
=
623 build_pointer_type (objc_v2_super_message_ref_template
);
626 /* Build following types which represent each class implementation.
630 uint32_t const flags;
631 uint32_t const instanceStart;
632 uint32_t const instanceSize;
634 uint32_t const reserved;
636 const uint8_t * const ivarLayout;
637 const char *const name;
638 const struct method_list_t * const baseMethods;
639 const struct objc_protocol_list *const baseProtocols;
640 const struct ivar_list_t *const ivars;
641 const uint8_t * const weakIvarLayout;
642 const struct _prop_list_t * const properties;
648 struct class_t *superclass;
652 ...When this is active - it will point to a rw version, but
653 when we build the meta-data we point it to the ro...
654 struct class_ro_t *data;
660 build_v2_class_templates (void)
663 tree decls
, *chain
= NULL
;
665 /* struct class_ro_t {...} */
666 objc_v2_class_ro_template
=
667 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO
));
669 /* uint32_t const flags; */
670 decls
= add_field_decl (integer_type_node
, "flags", &chain
);
672 /* uint32_t const instanceStart; */
673 add_field_decl (integer_type_node
, "instanceStart", &chain
);
675 /* uint32_t const instanceSize; */
676 add_field_decl (integer_type_node
, "instanceSize", &chain
);
678 /* This ABI is currently only used on m64 NeXT. We always
679 explicitly declare the alignment padding. */
680 /* uint32_t const reserved; */
681 add_field_decl (integer_type_node
, "reserved", &chain
);
683 /* const uint8_t * const ivarLayout; */
684 cnst_strg_type
= build_pointer_type (unsigned_char_type_node
);
685 add_field_decl (cnst_strg_type
, "ivarLayout", &chain
);
687 /* const char *const name; */
688 add_field_decl (string_type_node
, "name", &chain
);
690 /* const struct method_list_t * const baseMethods; */
691 add_field_decl (objc_method_list_ptr
, "baseMethods", &chain
);
693 /* const struct objc_protocol_list *const baseProtocols; */
694 add_field_decl (build_pointer_type
695 (xref_tag (RECORD_TYPE
,
696 get_identifier (UTAG_V2_PROTOCOL_LIST
))),
697 "baseProtocols", &chain
);
699 /* const struct ivar_list_t *const ivars; */
700 add_field_decl (objc_v2_ivar_list_ptr
, "ivars", &chain
);
702 /* const uint8_t * const weakIvarLayout; */
703 add_field_decl (cnst_strg_type
, "weakIvarLayout", &chain
);
705 /* struct _prop_list_t * baseProperties; */
706 add_field_decl (objc_prop_list_ptr
, "baseProperties", &chain
);
708 objc_finish_struct (objc_v2_class_ro_template
, decls
);
711 /* struct class_t {...} */
712 objc_v2_class_template
=
713 objc_start_struct (get_identifier (UTAG_V2_CLASS
));
715 /* struct class_t *isa; */
716 decls
= add_field_decl (build_pointer_type (objc_v2_class_template
),
719 /* struct class_t * const superclass; */
720 add_field_decl (build_pointer_type (objc_v2_class_template
),
721 "superclass", &chain
);
724 add_field_decl (build_pointer_type (void_type_node
), "cache", &chain
);
727 add_field_decl (build_pointer_type (objc_v2_imp_type
), "vtable", &chain
);
729 /* struct class_ro_t *ro; */
730 add_field_decl (build_pointer_type (objc_v2_class_ro_template
), "ro", &chain
);
732 objc_finish_struct (objc_v2_class_template
, decls
);
735 /* struct _objc_super
737 struct _objc_object *self;
741 build_v2_super_template (void)
743 tree decls
, *chain
= NULL
;
745 objc_super_template
= objc_start_struct (get_identifier (UTAG_SUPER
));
747 /* struct _objc_object *self; */
748 decls
= add_field_decl (objc_object_type
, "self", &chain
);
751 add_field_decl (objc_class_type
, "cls", &chain
);
753 objc_finish_struct (objc_super_template
, decls
);
759 const char * const protocol_name;
760 const struct protocol_list_t * const protocol_list;
761 const struct method_list_t * const instance_methods;
762 const struct method_list_t * const class_methods;
763 const struct method_list_t * optionalInstanceMethods;
764 const struct method_list_t * optionalClassMethod
765 const struct _prop_list_t * const properties;
767 const uint32_t flags;
768 const char ** extended_method_types;
769 const char * demangled_name;
770 const struct _prop_list_t * class_properties;
774 build_v2_protocol_template (void)
776 tree decls
, *chain
= NULL
;
778 objc_v2_protocol_template
=
779 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL
));
782 decls
= add_field_decl (objc_object_type
, "isa", &chain
);
784 /* char *protocol_name; */
785 add_field_decl (string_type_node
, "protocol_name", &chain
);
787 /* const struct protocol_list_t * const protocol_list; */
788 add_field_decl (build_pointer_type (objc_v2_protocol_template
),
789 "protocol_list", &chain
);
791 /* const struct method_list_t * const instance_methods; */
792 add_field_decl (objc_method_proto_list_ptr
, "instance_methods", &chain
);
794 /* const struct method_list_t * const class_methods; */
795 add_field_decl (objc_method_proto_list_ptr
, "class_methods", &chain
);
797 /* const struct method_list_t * optionalInstanceMethods; */
798 add_field_decl (objc_method_proto_list_ptr
, "optionalInstanceMethods", &chain
);
800 /* const struct method_list_t * optionalClassMethods; */
801 add_field_decl (objc_method_proto_list_ptr
, "optionalClassMethods", &chain
);
803 /* struct _prop_list_t * properties; */
804 add_field_decl (objc_prop_list_ptr
, "properties", &chain
);
806 /* const uint32_t size; */
807 add_field_decl (integer_type_node
, "size", &chain
);
809 /* const uint32_t flags; */
810 add_field_decl (integer_type_node
, "flags", &chain
);
812 /* const char **extendedMethodTypes; */
813 tree ptr_to_ptr_to_char
= build_pointer_type (string_type_node
);
814 add_field_decl (ptr_to_ptr_to_char
, "extended_method_types", &chain
);
816 /* const char *demangledName; */
817 add_field_decl (string_type_node
, "demangled_name", &chain
);
819 /* const struct _prop_list_t *class_properties; */
820 add_field_decl (objc_prop_list_ptr
, "class_properties", &chain
);
822 objc_finish_struct (objc_v2_protocol_template
, decls
);
825 /* Build type for a category:
828 const char * const name;
829 struct class_t *const cls;
830 const struct method_list_t * const instance_methods;
831 const struct method_list_t * const class_methods;
832 const struct protocol_list_t * const protocols;
833 const struct _prop_list_t * const properties;
838 build_v2_category_template (void)
840 tree decls
, *chain
= NULL
;
842 objc_v2_category_template
=
843 objc_start_struct (get_identifier ("_category_t"));
846 decls
= add_field_decl (string_type_node
, "name", &chain
);
848 /* struct class_t *const cls; */
849 add_field_decl (build_pointer_type (objc_v2_class_template
), "cls", &chain
);
851 /* struct method_list_t *instance_methods; */
852 add_field_decl (objc_method_list_ptr
, "instance_methods", &chain
);
854 /* struct method_list_t *class_methods; */
855 add_field_decl (objc_method_list_ptr
, "class_methods", &chain
);
857 /* struct protocol_list_t *protocol_list; */
858 add_field_decl (build_pointer_type (objc_v2_protocol_template
),
859 "protocol_list", &chain
);
861 /* struct _prop_list_t * properties; */
862 add_field_decl (objc_prop_list_ptr
, "properties", &chain
);
864 objc_finish_struct (objc_v2_category_template
, decls
);
867 /* NOTE --- Decls, Identifiers, Names etc. --- */
869 /* This routine is given a name and returns a matching extern variable
873 hash_name_lookup (hash
*hashlist
, tree name
)
877 target
= hashlist
[IDENTIFIER_HASH_VALUE (name
) % SIZEHASHTABLE
];
881 if (name
== DECL_NAME (target
->key
))
884 target
= target
->next
;
889 /* This routine is given an extern variable and enters it in its hash
890 table. Note that hashing is done on its inner IDENTIFIER_NODE
894 hash_name_enter (hash
*hashlist
, tree id
)
897 int slot
= IDENTIFIER_HASH_VALUE (DECL_NAME (id
)) % SIZEHASHTABLE
;
899 obj
= ggc_alloc
<hashed_entry
> ();
901 obj
->next
= hashlist
[slot
];
904 hashlist
[slot
] = obj
; /* append to front */
907 /* Create a declaration "extern <type> <name>;"
908 The var will need to be finalized (e.g. by calling finish_var_decl()). */
911 create_extern_decl (tree type
, const char *name
)
913 tree id
= get_identifier (name
);
914 tree var
= hash_name_lookup (extern_names
, id
);
918 var
= start_var_decl (type
, name
);
919 TREE_STATIC (var
) = 0;
920 DECL_EXTERNAL (var
) = 1;
921 TREE_PUBLIC (var
) = 1;
922 hash_name_enter (extern_names
, var
);
926 /* Create a globally visible definition for variable NAME of a given TYPE. The
927 finish_var_decl() routine will need to be called on it afterwards. */
929 create_global_decl (tree type
, const char *name
, bool is_def
= false);
932 create_global_decl (tree type
, const char *name
, bool is_def
)
934 tree id
= get_identifier (name
);
935 tree var
= hash_name_lookup (extern_names
, id
);
940 var
= start_var_decl (type
, name
);
941 hash_name_enter (extern_names
, var
);
945 DECL_EXTERNAL (var
) = 0;
946 TREE_STATIC (var
) = 1;
948 TREE_PUBLIC (var
) = 1;
952 /* Create a symbol with __attribute__ ((visibility ("hidden")))
953 attribute (private extern). */
955 create_hidden_decl (tree type
, const char *name
, bool is_def
= false);
958 create_hidden_decl (tree type
, const char *name
, bool is_def
)
960 tree decl
= create_global_decl (type
, name
, is_def
);
961 DECL_VISIBILITY (decl
) = VISIBILITY_HIDDEN
;
962 DECL_VISIBILITY_SPECIFIED (decl
) = 1;
966 /* Irritatingly, we have a different superclass field name for ABI=2. */
967 /* PS/TODO: The field name does not matter, it is only used internally
968 by the compiler. We can rename it to whatever we want. ;-) */
971 next_runtime_abi_02_super_superclassfield_id (void)
973 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
974 most look it once at startup then always return it. */
975 if (!super_superclassfield_id
)
976 super_superclassfield_id
= get_identifier ("cls");
977 return super_superclassfield_id
;
981 next_runtime_abi_02_class_decl (tree klass
)
985 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s",
986 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
987 /* ObjC2 classes are extern visible. */
988 decl
= create_global_decl (objc_v2_class_template
, buf
);
989 OBJCMETA (decl
, objc_meta
, meta_class
);
994 next_runtime_abi_02_metaclass_decl (tree klass
)
998 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
999 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
1000 /* ObjC2 classes are extern visible. */
1001 decl
= create_global_decl (objc_v2_class_template
, buf
);
1002 OBJCMETA (decl
, objc_meta
, meta_metaclass
);
1007 next_runtime_abi_02_category_decl (tree klass
)
1011 snprintf (buf
, BUFSIZE
, "_OBJC_Category_%s_%s",
1012 IDENTIFIER_POINTER (CLASS_NAME (klass
)),
1013 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass
)));
1014 decl
= start_var_decl (objc_v2_category_template
, buf
);
1015 OBJCMETA (decl
, objc_meta
, meta_category
);
1020 next_runtime_abi_02_protocol_decl (tree p
)
1025 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
1026 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
1027 IDENTIFIER_POINTER (PROTOCOL_NAME (p
)));
1028 if (flag_next_runtime
>= USE_FIXUP_BEFORE
)
1030 decl
= create_hidden_decl (objc_v2_protocol_template
, buf
);
1031 DECL_WEAK (decl
) = true;
1034 decl
= start_var_decl (objc_v2_protocol_template
, buf
);
1035 OBJCMETA (decl
, objc_meta
, meta_protocol
);
1036 DECL_PRESERVE_P (decl
) = 1;
1041 next_runtime_abi_02_string_decl (tree type
, const char *name
, string_section where
)
1043 tree var
= start_var_decl (type
, name
);
1047 OBJCMETA (var
, objc_meta
, meta_class_name
);
1049 case meth_var_names
:
1050 OBJCMETA (var
, objc_meta
, meta_meth_name
);
1052 case meth_var_types
:
1053 OBJCMETA (var
, objc_meta
, meta_meth_type
);
1055 case prop_names_attr
:
1056 OBJCMETA (var
, objc_meta
, meta_prop_name_attr
);
1059 OBJCMETA (var
, objc_meta
, meta_base
);
1065 /* NOTE --- entry --- */
1067 struct GTY(()) ident_data_tuple
{
1072 /* This routine creates a file scope static variable of type 'Class'
1073 to hold the address of a class. */
1076 build_v2_class_reference_decl (tree ident
)
1081 snprintf (buf
, BUFSIZE
, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident
));
1082 decl
= start_var_decl (objc_class_type
, buf
);
1083 OBJCMETA (decl
, objc_meta
, meta_class_ref
);
1087 /* This routine builds a class refs entry for each class name used.
1088 Initially, a (static-ref, IDENT) tuple is added to the list. The
1089 ident is replaced with address of the class metadata (of type
1090 'Class') in the output routine. */
1092 static GTY (()) vec
<ident_data_tuple
, va_gc
> *classrefs
;
1095 objc_v2_get_class_reference (tree ident
)
1102 ident_data_tuple
*ref
;
1103 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
1105 if (ref
->ident
== ident
)
1108 ref
->data
= build_v2_class_reference_decl (ident
);
1114 /* Somewhat arbitrary initial provision. */
1115 vec_alloc (classrefs
, 16);
1117 /* We come here if we don't find the entry - or if the table was yet
1119 decl
= build_v2_class_reference_decl (ident
);
1122 vec_safe_push (classrefs
, e
);
1127 next_runtime_abi_02_get_class_reference (tree ident
)
1129 if (!flag_zero_link
)
1130 return objc_v2_get_class_reference (ident
);
1133 /* We fall back to using objc_getClass (). */
1134 vec
<tree
, va_gc
> *v
;
1137 /* ??? add_class_reference (ident); - is pointless, since the
1138 system lib does not export the equivalent symbols. Maybe we
1139 need to build a class ref anyway. */
1140 t
= my_build_string_pointer (IDENTIFIER_LENGTH (ident
) + 1,
1141 IDENTIFIER_POINTER (ident
));
1143 t
= build_function_call_vec (input_location
, vNULL
, objc_get_class_decl
,
1150 /* Used by build_function_type_for_method. Append the types for
1151 receiver & _cmd at the start of a method argument list to ARGTYPES.
1152 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1153 trying to define a method or call one. SUPERFLAG says this is for a
1154 send to super. METH may be NULL, in the case that there is no
1158 next_runtime_abi_02_get_arg_type_list_base (vec
<tree
, va_gc
> **argtypes
,
1159 tree meth
, int context
,
1165 receiver_type
= objc_super_type
;
1166 else if (context
== METHOD_DEF
&& TREE_CODE (meth
) == INSTANCE_METHOD_DECL
)
1167 receiver_type
= objc_instance_type
;
1169 receiver_type
= objc_object_type
;
1171 vec_safe_push (*argtypes
, receiver_type
);
1172 if (flag_next_runtime
< USE_FIXUP_BEFORE
)
1173 /* Selector type - will eventually change to `int'. */
1174 vec_safe_push (*argtypes
, superflag
? objc_v2_super_selector_type
1175 : objc_v2_selector_type
);
1177 vec_safe_push (*argtypes
, objc_selector_type
);
1180 /* TODO: Merge this with the message refs. */
1182 build_selector_reference_decl (tree ident
)
1185 char *t
, buf
[BUFSIZE
];
1187 snprintf (buf
, BUFSIZE
, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident
));
1192 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
1195 decl
= start_var_decl (objc_selector_type
, buf
);
1196 OBJCMETA (decl
, objc_meta
, meta_sel_refs
);
1201 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED
,
1203 tree proto ATTRIBUTE_UNUSED
)
1205 tree
*chain
= &sel_ref_chain
;
1210 if (TREE_VALUE (*chain
) == ident
)
1211 return TREE_PURPOSE (*chain
);
1213 chain
= &TREE_CHAIN (*chain
);
1216 expr
= build_selector_reference_decl (ident
);
1217 *chain
= tree_cons (expr
, ident
, NULL_TREE
);
1222 /* Declare a variable of type 'struct message_ref_t'. */
1223 /* This will be finished in build_v2_message_ref_translation_table ().
1224 We take an idea from LLVM in making the names a bit more connected
1225 and thus the asm more readable. */
1228 build_v2_message_reference_decl (tree sel_name
, tree message_func_ident
)
1231 char buf
[BUFSIZE
], *t
;
1234 /* Skip past the objc_msgSend it's the same for all... */
1235 if (IDENTIFIER_POINTER (message_func_ident
)[offset
] == '_')
1238 snprintf (buf
, BUFSIZE
, "_OBJC_MsgRef_%s_%s",
1239 &(IDENTIFIER_POINTER (message_func_ident
)[offset
]),
1240 IDENTIFIER_POINTER (sel_name
));
1245 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
1248 decl
= start_var_decl (objc_v2_message_ref_template
, buf
);
1249 OBJCMETA (decl
, objc_meta
, meta_mref
);
1253 struct GTY(()) msgref_entry
{
1259 static GTY (()) vec
<msgref_entry
, va_gc
> *msgrefs
;
1261 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1262 later on to initialize the table of 'struct message_ref_t'
1266 build_v2_selector_messenger_reference (tree sel_name
, tree message_func_decl
)
1274 FOR_EACH_VEC_ELT (*msgrefs
, count
, ref
)
1275 if (ref
->func
== message_func_decl
&& ref
->selname
== sel_name
)
1276 return ref
->refdecl
;
1279 /* Somewhat arbitrary initial provision. */
1280 vec_alloc (msgrefs
, 32);
1282 /* We come here if we don't find a match or at the start. */
1283 decl
= build_v2_message_reference_decl (sel_name
,
1284 DECL_NAME (message_func_decl
));
1285 e
.func
= message_func_decl
;
1286 e
.selname
= sel_name
;
1288 vec_safe_push (msgrefs
, e
);
1293 build_v2_protocollist_ref_decl (tree protocol
)
1296 tree protocol_ident
= PROTOCOL_NAME (protocol
);
1299 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRef_%s",
1300 IDENTIFIER_POINTER (protocol_ident
));
1301 /* TODO: other compiler versions make these hidden & weak. */
1302 decl
= create_global_decl (objc_protocol_type
, buf
);
1303 /* Let optimizer know that this decl is not removable. */
1304 DECL_PRESERVE_P (decl
) = 1;
1305 OBJCMETA (decl
, objc_meta
, meta_proto_ref
);
1309 struct GTY(()) prot_list_entry
{
1313 static GTY (()) vec
<prot_list_entry
, va_gc
> *protrefs
;
1316 objc_v2_get_protocol_reference (tree ident
)
1323 prot_list_entry
*ref
;
1324 FOR_EACH_VEC_ELT (*protrefs
, count
, ref
)
1326 if (ref
->id
== ident
)
1329 ref
->refdecl
= build_v2_protocollist_ref_decl (ident
);
1330 return ref
->refdecl
;
1335 /* Somewhat arbitrary initial provision. */
1336 vec_alloc (protrefs
, 32);
1338 /* We come here if we don't find the entry - or if the table was yet
1340 decl
= build_v2_protocollist_ref_decl (ident
);
1343 vec_safe_push (protrefs
, e
);
1348 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED
,
1351 if (!PROTOCOL_FORWARD_DECL (p
))
1352 PROTOCOL_FORWARD_DECL (p
) = next_runtime_abi_02_protocol_decl (p
);
1354 return objc_v2_get_protocol_reference (p
);
1357 /* This routine returns the ivar declaration, if component is a valid
1358 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1359 returns the class name in CLASS. */
1362 objc_is_ivar (tree expr
, tree component
, tree
*klass
)
1364 tree field
= NULL_TREE
;
1365 tree basetype
= TYPE_MAIN_VARIANT (TREE_TYPE (expr
));
1367 if (TREE_CODE (basetype
) == RECORD_TYPE
1368 && TYPE_HAS_OBJC_INFO (basetype
) && TYPE_OBJC_INTERFACE (basetype
))
1370 *klass
= lookup_interface (OBJC_TYPE_NAME (basetype
));
1375 tree ivar_chain
= CLASS_RAW_IVARS (*klass
);
1378 field
= is_ivar (ivar_chain
, component
);
1379 if (field
!= NULL_TREE
)
1382 *klass
= lookup_interface (CLASS_SUPER_NAME (*klass
));
1391 create_ivar_offset_name (char *buf
, tree class_name
, tree field_decl
)
1393 tree fname
= DECL_NAME (field_decl
);
1395 sprintf (buf
, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name
),
1396 IDENTIFIER_POINTER (fname
));
1400 /* This routine generates new abi's ivar reference tree. It amounts
1401 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1402 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1403 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1406 objc_v2_build_ivar_ref (tree datum
, tree component
)
1408 tree field
, ref
, class_name
, offset
, ftype
, expr
;
1409 char var_offset_name
[512];
1411 field
= objc_is_ivar (datum
, component
, &class_name
);
1415 /* This routine only handles non-bitfield fields */
1416 if (DECL_C_BIT_FIELD (field
))
1419 create_ivar_offset_name (var_offset_name
, CLASS_NAME (class_name
), field
);
1421 offset
= create_extern_decl (TREE_TYPE (size_zero_node
), var_offset_name
);
1423 ftype
= TREE_TYPE (field
);
1426 expr
= build_c_cast (input_location
,
1427 string_type_node
, build_fold_addr_expr (datum
));
1429 /* (char*)datum + offset */
1430 expr
= fold_build_pointer_plus_loc (input_location
, expr
, offset
);
1432 /* (ftype*)((char*)datum + offset) */
1433 expr
= build_c_cast (input_location
, build_pointer_type (ftype
), expr
);
1435 /* Finally: *(ftype*)((char*)datum + offset) */
1436 ref
= build_indirect_ref (input_location
, expr
, RO_UNARY_STAR
);
1438 /* We must set type of the resulting expression to be the same as
1439 the field type. This is because, build_indirect_ref (...)
1440 rebuilds the type which may result in lost information; as in the
1441 case of protocol-qualified types (id <protocol> ). */
1442 TREE_TYPE (ref
) = ftype
;
1444 if (TREE_READONLY (datum
) || TREE_READONLY (field
))
1445 TREE_READONLY (ref
) = 1;
1447 if (TREE_THIS_VOLATILE (datum
) || TREE_THIS_VOLATILE (field
))
1448 TREE_THIS_VOLATILE (ref
) = 1;
1450 if (TREE_DEPRECATED (field
))
1451 warn_deprecated_use (field
, NULL_TREE
);
1456 /* IVAR refs are made via an externally referenceable offset and built
1457 on the fly. That is, unless they refer to (private) fields in the
1460 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED
,
1464 if ((ivar
= objc_v2_build_ivar_ref (base
, id
)))
1466 return objc_build_component_ref (base
, id
);
1469 /* [super ...] references are listed here (and built into a table at
1470 meta -data emit time). */
1472 build_v2_superclass_ref_decl (tree ident
, bool inst
)
1477 snprintf (buf
, BUFSIZE
, "_OBJC_%sSuperRef_%s", (inst
?"":"Meta"),
1478 IDENTIFIER_POINTER (ident
));
1479 decl
= start_var_decl (objc_class_type
, buf
);
1480 OBJCMETA (decl
, objc_meta
, meta_superclass_ref
);
1484 static GTY (()) vec
<ident_data_tuple
, va_gc
> *class_super_refs
;
1485 static GTY (()) vec
<ident_data_tuple
, va_gc
> *metaclass_super_refs
;
1487 /* Find or build a superclass reference decl for class NAME. */
1490 objc_get_superclass_ref_decl (tree name
, bool inst_meth
)
1493 vec
<ident_data_tuple
, va_gc
> *list
= inst_meth
? class_super_refs
1494 : metaclass_super_refs
;
1499 ident_data_tuple
*ref
;
1500 FOR_EACH_VEC_ELT (*list
, count
, ref
)
1502 if (ref
->ident
== name
)
1505 ref
->data
= build_v2_superclass_ref_decl (name
, inst_meth
);
1512 /* Somewhat arbitrary initial provision. */
1515 vec_alloc (class_super_refs
, 16);
1516 list
= class_super_refs
;
1520 vec_alloc (metaclass_super_refs
, 16);
1521 list
= metaclass_super_refs
;
1524 /* We come here if we don't find the entry - or if the table was yet
1526 decl
= build_v2_superclass_ref_decl (name
, inst_meth
);
1530 vec_safe_push (list
, e
);
1534 /* Get a reference to the superclass for IMP. */
1537 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED
,
1538 struct imp_entry
*imp
, bool inst_meth
)
1540 tree name
= CLASS_NAME (imp
->imp_context
);
1541 return objc_get_superclass_ref_decl (name
, inst_meth
);
1544 /* Get a reference to the superclass for category IMP. */
1547 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED
,
1548 struct imp_entry
*imp
,
1553 /* Do it the slow way. */
1554 tree get_cl_fn
= inst_meth
? objc_get_class_decl
1555 : objc_get_meta_class_decl
;
1556 tree super_name
= CLASS_SUPER_NAME (imp
->imp_template
);
1557 super_name
= my_build_string_pointer (IDENTIFIER_LENGTH (super_name
) + 1,
1558 IDENTIFIER_POINTER (super_name
));
1559 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1560 return build_function_call (input_location
, get_cl_fn
,
1561 build_tree_list (NULL_TREE
, super_name
));
1564 /* This is the 'usual' path. */
1565 tree cls_name
= CLASS_NAME (imp
->imp_template
);
1567 return objc_get_superclass_ref_decl (cls_name
, inst_meth
);
1568 return objc_get_class_reference (cls_name
);
1572 next_runtime_abi_02_receiver_is_class_object (tree receiver
)
1574 if (VAR_P (receiver
)
1575 && IS_CLASS (TREE_TYPE (receiver
))
1576 && vec_safe_length (classrefs
))
1579 ident_data_tuple
*ref
;
1580 /* The receiver is a variable created by build_class_reference_decl. */
1581 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
1582 if (ref
->data
== receiver
)
1588 /* Assign all arguments in VALUES which have side-effect to a temporary
1589 and replaced that argument in VALUES list with the temporary. The
1590 arguments will be passed to a function with FNTYPE. */
1593 objc_copy_to_temp_side_effect_params (tree fntype
, tree values
)
1596 function_args_iterator iter
;
1598 /* Skip over receiver and the &_msf_ref types. */
1599 function_args_iter_init (&iter
, fntype
);
1600 function_args_iter_next (&iter
);
1601 function_args_iter_next (&iter
);
1603 for (valtail
= values
; valtail
;
1604 valtail
= TREE_CHAIN (valtail
), function_args_iter_next (&iter
))
1606 tree value
= TREE_VALUE (valtail
);
1607 tree type
= function_args_iter_cond (&iter
);
1608 if (type
== NULL_TREE
)
1610 if (!TREE_SIDE_EFFECTS (value
))
1612 /* To prevent re-evaluation. */
1613 value
= save_expr (value
);
1615 TREE_VALUE (valtail
) = value
;
1620 /* Build the new abi's messaging library call. It looks like:
1621 (*_msg.messenger) (receiver, &_msg, ...) */
1624 build_v2_objc_method_fixup_call (int super_flag
, tree method_prototype
,
1625 tree lookup_object
, tree selector
,
1626 tree method_params
, bool check_for_nil
)
1629 tree sender
, rcv_p
, t
;
1632 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1633 : objc_object_type
);
1634 tree ftype
= build_function_type_for_method (ret_type
, method_prototype
,
1635 METHOD_REF
, super_flag
);
1638 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
1639 ftype
= build_type_attribute_variant (
1640 ftype
, METHOD_TYPE_ATTRIBUTES (method_prototype
));
1642 sender_cast
= build_pointer_type (ftype
);
1645 method_params
= objc_copy_to_temp_side_effect_params (ftype
,
1648 /* Get &message_ref_t.messenger. */
1649 sender
= build_c_cast (input_location
,
1650 build_pointer_type (super_flag
1651 ? objc_v2_super_imp_type
1652 : objc_v2_imp_type
),
1655 sender
= build_indirect_ref (input_location
, sender
, RO_UNARY_STAR
);
1657 rcv_p
= (super_flag
? objc_super_type
: objc_object_type
);
1659 lookup_object
= build_c_cast (input_location
, rcv_p
, lookup_object
);
1660 if (sender
== error_mark_node
|| lookup_object
== error_mark_node
)
1661 return error_mark_node
;
1663 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1664 lookup_object
= save_expr (lookup_object
);
1666 method_params
= tree_cons (NULL_TREE
, lookup_object
,
1667 tree_cons (NULL_TREE
, selector
,
1669 t
= build3 (OBJ_TYPE_REF
, sender_cast
, sender
, lookup_object
,
1670 build_int_cst (TREE_TYPE (lookup_object
), 0));
1671 ret_val
= build_function_call (input_location
, t
, method_params
);
1674 /* receiver != nil ? ret_val : 0 */
1678 if (TREE_CODE (ret_type
) == RECORD_TYPE
1679 || TREE_CODE (ret_type
) == UNION_TYPE
)
1680 /* An empty constructor is zero-filled by the middle end. */
1681 ftree
= objc_build_constructor (ret_type
, NULL
);
1683 ftree
= fold_convert (ret_type
, integer_zero_node
);
1685 ifexp
= build_binary_op (input_location
, NE_EXPR
,
1687 fold_convert (rcv_p
, integer_zero_node
), 1);
1690 ret_val
= build_conditional_expr (input_location
,
1691 ifexp
, ret_val
, ftree
,
1692 tf_warning_or_error
);
1694 ret_val
= build_conditional_expr (input_location
,
1696 ret_val
, NULL_TREE
, input_location
,
1697 ftree
, NULL_TREE
, input_location
);
1698 ret_val
= fold_convert (ret_type
, ret_val
);
1705 build_v2_build_objc_method_call (int super
, tree method_prototype
,
1706 tree lookup_object
, tree selector
,
1707 tree method_params
, location_t loc
,
1708 bool check_for_nil
, bool rx_is_id
)
1710 tree sender
, sender_cast
, method
, t
;
1711 tree rcv_p
= (super
? objc_super_type
: objc_object_type
);
1712 vec
<tree
, va_gc
> *parms
;
1713 unsigned nparm
= (method_params
? list_length (method_params
) : 0);
1715 /* If a prototype for the method to be called exists, then cast
1716 the sender's return type and arguments to match that of the method.
1717 Otherwise, leave sender as is. */
1720 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1721 : objc_object_type
);
1722 tree ftype
= build_function_type_for_method (ret_type
, method_prototype
,
1725 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
1726 ftype
= build_type_attribute_variant (ftype
,
1727 METHOD_TYPE_ATTRIBUTES
1728 (method_prototype
));
1730 sender_cast
= build_pointer_type (ftype
);
1732 lookup_object
= build_c_cast (loc
, rcv_p
, lookup_object
);
1734 if (error_operand_p (lookup_object
))
1735 return error_mark_node
;
1737 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1738 lookup_object
= save_expr (lookup_object
);
1740 /* Param list + 2 slots for object and selector. */
1741 vec_alloc (parms
, nparm
+ 2);
1743 /* If we are returning an item that must be returned in memory, and the
1744 target ABI does this by an invisible pointer provided as the first arg,
1745 we need to adjust the message signature to include this. The second
1746 part of this excludes targets that provide some alternate scheme for
1747 structure returns. */
1748 if (ret_type
&& !VOID_TYPE_P (ret_type
)
1749 && targetm
.calls
.return_in_memory (ret_type
, 0)
1750 && !(targetm
.calls
.struct_value_rtx (0, 0)
1751 && (TREE_CODE (ret_type
) == RECORD_TYPE
1752 || TREE_CODE (ret_type
) == UNION_TYPE
)))
1755 sender
= umsg_id_super2_stret_fixup_decl
;
1757 sender
= rx_is_id
? umsg_id_stret_fixup_decl
1758 : umsg_stret_fixup_decl
;
1763 sender
= umsg_id_super2_fixup_decl
;
1765 sender
= rx_is_id
? umsg_id_fixup_decl
1769 method
= build_fold_addr_expr_loc (loc
, sender
);
1771 /* Pass the object to the method. */
1772 parms
->quick_push (lookup_object
);
1773 /* Pass the selector to the method. */
1774 parms
->quick_push (selector
);
1775 /* Now append the remainder of the parms. */
1777 for (; method_params
; method_params
= TREE_CHAIN (method_params
))
1778 parms
->quick_push (TREE_VALUE (method_params
));
1780 /* Build an obj_type_ref, with the correct cast for the method call. */
1781 t
= build3 (OBJ_TYPE_REF
, sender_cast
, method
,
1782 lookup_object
, build_int_cst (TREE_TYPE (lookup_object
), 0));
1783 tree ret_val
= build_function_call_vec (loc
, vNULL
, t
, parms
, NULL
);
1787 /* receiver != nil ? ret_val : 0 */
1791 if (TREE_CODE (ret_type
) == RECORD_TYPE
1792 || TREE_CODE (ret_type
) == UNION_TYPE
)
1794 /* An empty constructor is zero-filled by the middle end. */
1795 ftree
= objc_build_constructor (ret_type
, NULL
);
1798 ftree
= fold_convert (ret_type
, integer_zero_node
);
1800 ifexp
= build_binary_op (loc
, NE_EXPR
,
1802 fold_convert (rcv_p
, integer_zero_node
), 1);
1805 ret_val
= build_conditional_expr (loc
, ifexp
, ret_val
, ftree
,
1806 tf_warning_or_error
);
1808 ret_val
= build_conditional_expr (loc
, ifexp
, 1,
1809 ret_val
, NULL_TREE
, loc
,
1810 ftree
, NULL_TREE
, loc
);
1811 ret_val
= fold_convert (ret_type
, ret_val
);
1818 next_runtime_abi_02_build_objc_method_call (location_t loc
,
1819 tree method_prototype
,
1826 /* Do we need to check for nil receivers ? */
1827 /* For now, message sent to classes need no nil check. In the
1828 future, class declaration marked as weak_import must be nil
1830 bool check_for_nil
= flag_objc_nilcheck
;
1832 || (VAR_P (receiver
)
1833 && TREE_TYPE (receiver
) == objc_class_type
))
1834 check_for_nil
= false;
1836 if (flag_next_runtime
>= USE_FIXUP_BEFORE
)
1839 = next_runtime_abi_02_build_selector_reference (loc
, sel_name
,
1841 return build_v2_build_objc_method_call (super
, method_prototype
,
1845 objc_is_id (rtype
));
1848 /* else we have to build a pair of the function and selector. */
1849 tree message_func_decl
;
1850 tree ret_type
= method_prototype
1851 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1854 /* See comment for the fixup version above. */
1855 if (ret_type
&& !VOID_TYPE_P (ret_type
)
1856 && targetm
.calls
.return_in_memory (ret_type
, 0)
1857 && !(targetm
.calls
.struct_value_rtx (0, 0)
1858 && (TREE_CODE (ret_type
) == RECORD_TYPE
1859 || TREE_CODE (ret_type
) == UNION_TYPE
)))
1862 message_func_decl
= umsg_id_super2_stret_fixup_decl
;
1864 message_func_decl
= objc_is_id (rtype
)
1865 ? umsg_id_stret_fixup_decl
1866 : umsg_stret_fixup_decl
;
1871 message_func_decl
= umsg_id_super2_fixup_decl
;
1873 message_func_decl
= objc_is_id (rtype
)
1874 ? umsg_id_fixup_decl
1878 tree selector
= build_v2_selector_messenger_reference (sel_name
,
1881 /* selector = &_msg; */
1882 selector
= build_unary_op (loc
, ADDR_EXPR
, selector
, 0);
1884 selector
= build_c_cast (loc
, (super
? objc_v2_super_selector_type
1885 : objc_v2_selector_type
),
1888 /* (*_msg.messenger) (receiver, &_msg, ...); */
1889 return build_v2_objc_method_fixup_call (super
, method_prototype
, receiver
,
1890 selector
, method_params
,
1894 /* NOTE --- Constant String Class Stuff --- */
1897 next_runtime_abi_02_setup_const_string_class_decl (void)
1899 if (!constant_string_global_id
)
1901 /* Hopefully, this should not represent a serious limitation. */
1903 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s", constant_string_class_name
);
1904 constant_string_global_id
= get_identifier (buf
);
1907 string_class_decl
= lookup_name (constant_string_global_id
);
1909 /* In OBJC2 abi, constant string class reference refers to class
1910 name for NSConstantString class. This declaration may not be
1911 available yet (in fact it is not in most cases). So, declare an
1912 extern OBJC_CLASS_$_NSConstantString in its place. */
1913 if (!string_class_decl
)
1915 create_extern_decl (objc_v2_class_template
,
1916 IDENTIFIER_POINTER (constant_string_global_id
));
1918 return (string_class_decl
!= NULL_TREE
);
1922 next_runtime_abi_02_build_const_string_constructor (location_t loc
, tree string
,
1925 tree constructor
, fields
, var
;
1926 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1928 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1929 fields
= TYPE_FIELDS (internal_const_str_type
);
1930 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1931 build_unary_op (loc
, ADDR_EXPR
, string_class_decl
, 0));
1933 fields
= DECL_CHAIN (fields
);
1934 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1935 build_unary_op (loc
, ADDR_EXPR
, string
, 1));
1937 /* ??? check if this should be long. */
1938 fields
= DECL_CHAIN (fields
);
1939 CONSTRUCTOR_APPEND_ELT (v
, fields
, build_int_cst (NULL_TREE
, length
));
1940 constructor
= objc_build_constructor (internal_const_str_type
, v
);
1942 var
= build_decl (input_location
, CONST_DECL
, NULL
, TREE_TYPE (constructor
));
1943 DECL_INITIAL (var
) = constructor
;
1944 TREE_STATIC (var
) = 1;
1945 DECL_CONTEXT (var
) = NULL
;
1946 OBJCMETA (var
, objc_meta
, meta_const_str
);
1950 /* NOTE --- NeXT V2 Metadata templates --- */
1952 /* This routine builds the following type:
1955 const char * const name; // property name
1956 const char * const attributes; // comma-delimited, encoded,
1957 // property attributes
1962 build_v2_property_template (void)
1965 tree decls
, *chain
= NULL
;
1967 prop_record
= objc_start_struct (get_identifier ("_prop_t"));
1968 /* const char * name */
1969 decls
= add_field_decl (string_type_node
, "name", &chain
);
1971 /* const char * attribute */
1972 add_field_decl (string_type_node
, "attribute", &chain
);
1974 objc_finish_struct (prop_record
, decls
);
1980 unsigned long int *offset;
1989 build_v2_ivar_t_template (void)
1991 tree objc_ivar_id
, objc_ivar_record
;
1992 tree decls
, *chain
= NULL
;
1994 objc_ivar_id
= get_identifier ("_ivar_t");
1995 objc_ivar_record
= objc_start_struct (objc_ivar_id
);
1997 /* unsigned long int *offset; */
1998 decls
= add_field_decl (build_pointer_type
1999 (TREE_TYPE (size_zero_node
)), "offset", &chain
);
2002 add_field_decl (string_type_node
, "name", &chain
);
2005 add_field_decl (string_type_node
, "type", &chain
);
2007 /* uint32_t alignment; */
2008 add_field_decl (integer_type_node
, "alignment", &chain
);
2010 /* uint32_t size; */
2011 add_field_decl (integer_type_node
, "size", &chain
);
2013 objc_finish_struct (objc_ivar_record
, decls
);
2014 return objc_ivar_record
;
2018 build_metadata_templates (void)
2021 if (!objc_method_template
)
2022 objc_method_template
= build_method_template ();
2024 if (!objc_v2_property_template
)
2025 objc_v2_property_template
= build_v2_property_template ();
2027 if (!objc_v2_ivar_template
)
2028 objc_v2_ivar_template
= build_v2_ivar_t_template ();
2032 /* NOTE --- Output NeXT V2 Metadata --- */
2034 /* Routine builds name of Interface's main meta-data of type class_t. */
2037 objc_build_internal_classname (tree ident
, bool metaclass
)
2039 static char string
[512];
2040 snprintf (string
, 512, "%s_%s", metaclass
? "OBJC_METACLASS_$"
2042 IDENTIFIER_POINTER (ident
));
2046 /* Build the name for object of type struct class_ro_t */
2049 newabi_append_ro (const char *name
)
2053 static char string
[BUFSIZE
];
2054 dollar
= strchr (name
, '$');
2055 gcc_assert (dollar
);
2058 strncpy (p
, name
, (int)(dollar
- name
));
2059 p
+= (int)(dollar
- name
);
2060 sprintf (p
, "RO_%s", dollar
);
2064 /* Build the struct message_ref_t msg =
2065 {objc_msgSend_fixup_xxx, @selector(func)}
2069 void build_v2_message_ref_translation_table (void)
2074 if (!vec_safe_length (msgrefs
))
2077 FOR_EACH_VEC_ELT (*msgrefs
, count
, ref
)
2079 vec
<constructor_elt
, va_gc
> *initializer
;
2080 tree expr
, constructor
;
2081 tree struct_type
= TREE_TYPE (ref
->refdecl
);
2082 location_t loc
= DECL_SOURCE_LOCATION (ref
->refdecl
);
2085 /* First 'IMP messenger' field... */
2086 expr
= build_unary_op (loc
, ADDR_EXPR
, ref
->func
, 0);
2087 expr
= convert (objc_v2_imp_type
, expr
);
2088 CONSTRUCTOR_APPEND_ELT (initializer
, NULL_TREE
, expr
);
2090 /* ... then 'SEL name' field. */
2091 expr
= build_selector (ref
->selname
);
2092 CONSTRUCTOR_APPEND_ELT (initializer
, NULL_TREE
, expr
);
2093 constructor
= objc_build_constructor (struct_type
, initializer
);
2094 finish_var_decl (ref
->refdecl
, constructor
);
2098 /* Build decl = initializer; for each externally visible class
2102 build_v2_classrefs_table (void)
2105 ident_data_tuple
*ref
;
2107 if (!vec_safe_length (classrefs
))
2110 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
2112 tree expr
= ref
->ident
;
2113 tree decl
= ref
->data
;
2114 /* Interface with no implementation and yet one of its messages
2115 has been used. Need to generate a full address-of tree for it
2117 if (TREE_CODE (expr
) == IDENTIFIER_NODE
)
2119 const char *name
= objc_build_internal_classname (expr
, false);
2120 expr
= create_extern_decl (objc_v2_class_template
, name
);
2121 expr
= convert (objc_class_type
, build_fold_addr_expr (expr
));
2123 /* The runtime wants this, even if it appears unused, so we must force the
2125 DECL_PRESERVE_P (decl
) = 1;
2126 finish_var_decl (decl
, expr
);
2130 /* Build decl = initializer; for each externally visible super class
2134 build_v2_super_classrefs_table (bool metaclass
)
2137 ident_data_tuple
*ref
;
2138 vec
<ident_data_tuple
, va_gc
> *list
= metaclass
? metaclass_super_refs
2141 if (!vec_safe_length (list
))
2144 FOR_EACH_VEC_ELT (*list
, count
, ref
)
2146 tree expr
= ref
->ident
;
2147 tree decl
= ref
->data
;
2148 /* Interface with no implementation and yet one of its messages
2149 has been used. Need to generate a full address-of tree for it
2151 if (TREE_CODE (expr
) == IDENTIFIER_NODE
)
2153 const char * name
= objc_build_internal_classname (expr
, metaclass
);
2154 expr
= create_extern_decl (objc_v2_class_template
, name
);
2155 expr
= convert (objc_class_type
, build_fold_addr_expr (expr
));
2157 finish_var_decl (decl
, expr
);
2161 /* Add the global class meta-data declaration to the list which later
2162 on ends up in the __class_list section. */
2164 static GTY(()) vec
<tree
, va_gc
> *class_list
;
2167 objc_v2_add_to_class_list (tree global_class_decl
)
2169 vec_safe_push (class_list
, global_class_decl
);
2172 static GTY(()) vec
<tree
, va_gc
> *nonlazy_class_list
;
2174 /* Add the global class meta-data declaration to the list which later
2175 on ends up in the __nonlazy_class section. */
2178 objc_v2_add_to_nonlazy_class_list (tree global_class_decl
)
2180 vec_safe_push (nonlazy_class_list
, global_class_decl
);
2183 static GTY(()) vec
<tree
, va_gc
> *category_list
;
2185 /* Add the category meta-data declaration to the list which later on
2186 ends up in the __nonlazy_category section. */
2189 objc_v2_add_to_category_list (tree decl
)
2191 vec_safe_push (category_list
, decl
);
2194 static GTY(()) vec
<tree
, va_gc
> *nonlazy_category_list
;
2196 /* Add the category meta-data declaration to the list which later on
2197 ends up in the __category_list section. */
2200 objc_v2_add_to_nonlazy_category_list (tree decl
)
2202 vec_safe_push (nonlazy_category_list
, decl
);
2206 has_load_impl (tree clsmeth
)
2210 tree id
= METHOD_SEL_NAME (clsmeth
);
2211 if (IDENTIFIER_LENGTH (id
) == 4
2212 && startswith (IDENTIFIER_POINTER (id
), "load"))
2214 clsmeth
= DECL_CHAIN (clsmeth
);
2220 /* Build a __{class,category}_list section table containing address of
2221 all @implemented {class,category} meta-data. */
2224 build_v2_address_table (vec
<tree
, va_gc
> *src
, const char *nam
, tree attr
)
2227 tree type
, decl
, expr
;
2228 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2230 if (!vec_safe_length (src
))
2233 FOR_EACH_VEC_ELT (*src
, count
, decl
)
2236 tree purpose
= build_int_cst (NULL_TREE
, count
);
2238 tree purpose
= NULL_TREE
;
2240 expr
= convert (objc_class_type
, build_fold_addr_expr (decl
));
2241 CONSTRUCTOR_APPEND_ELT (initlist
, purpose
, expr
);
2243 gcc_assert (count
> 0);
2244 type
= build_array_type (objc_class_type
,
2245 build_index_type (build_int_cst (NULL_TREE
, count
- 1)));
2246 decl
= start_var_decl (type
, nam
);
2247 /* The runtime wants this, even if it appears unused, so we must
2248 force the output. */
2249 DECL_PRESERVE_P (decl
) = 1;
2250 expr
= objc_build_constructor (type
, initlist
);
2251 OBJCMETA (decl
, objc_meta
, attr
);
2252 finish_var_decl (decl
, expr
);
2255 /* Build decl = initializer; for each protocol referenced in
2256 @protocol(MyProt) expression. Refs as built in the entry section
2260 build_v2_protocol_list_translation_table (void)
2263 prot_list_entry
*ref
;
2268 FOR_EACH_VEC_ELT (*protrefs
, count
, ref
)
2272 gcc_assert (TREE_CODE (ref
->id
) == PROTOCOL_INTERFACE_TYPE
);
2273 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
2274 IDENTIFIER_POINTER (PROTOCOL_NAME (ref
->id
)));
2275 expr
= start_var_decl (objc_v2_protocol_template
, buf
);
2276 expr
= convert (objc_protocol_type
, build_fold_addr_expr (expr
));
2277 finish_var_decl (ref
->refdecl
, expr
);
2279 /* TODO: Maybe we could explicitly delete the vec. now? */
2282 static GTY (()) vec
<prot_list_entry
, va_gc
> *protlist
;
2284 /* Add the local protocol meta-data declaration to the list which
2285 later on ends up in the __protocol_list section. */
2288 objc_add_to_protocol_list (tree protocol_interface_decl
, tree protocol_decl
)
2292 /* Arbitrary init count. */
2293 vec_alloc (protlist
, 32);
2294 e
.id
= protocol_interface_decl
;
2295 e
.refdecl
= protocol_decl
;
2296 vec_safe_push (protlist
, e
);
2299 /* Build the __protocol_list section table containing address of all
2300 generate protocol_t meta-data. */
2303 build_v2_protocol_list_address_table (void)
2306 prot_list_entry
*ref
;
2307 if (!vec_safe_length (protlist
))
2310 FOR_EACH_VEC_ELT (*protlist
, count
, ref
)
2314 gcc_assert (ref
->id
&& TREE_CODE (ref
->id
) == PROTOCOL_INTERFACE_TYPE
);
2315 snprintf (buf
, BUFSIZE
, "_OBJC_LabelProtocol_%s",
2316 IDENTIFIER_POINTER (PROTOCOL_NAME (ref
->id
)));
2317 if (flag_next_runtime
>= USE_FIXUP_BEFORE
)
2319 decl
= create_hidden_decl (objc_protocol_type
, buf
, /*is def=*/true);
2320 DECL_WEAK (decl
) = true;
2323 decl
= create_global_decl (objc_protocol_type
, buf
, /*is def=*/true);
2324 expr
= convert (objc_protocol_type
, build_fold_addr_expr (ref
->refdecl
));
2325 OBJCMETA (decl
, objc_meta
, meta_label_protocollist
);
2326 finish_var_decl (decl
, expr
);
2327 DECL_PRESERVE_P (decl
) = 1;
2330 /* TODO: delete the vec. */
2331 /* TODO: upgrade to the clang/llvm hidden version. */
2334 /* This routine declares a variable to hold meta data for 'struct
2335 protocol_list_t'. */
2338 generate_v2_protocol_list (tree i_or_p
, tree klass_ctxt
)
2340 tree refs_decl
, lproto
, e
, plist
, ptempl_p_t
;
2342 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2345 if (TREE_CODE (i_or_p
) == CLASS_INTERFACE_TYPE
2346 || TREE_CODE (i_or_p
) == CATEGORY_INTERFACE_TYPE
)
2347 plist
= CLASS_PROTOCOL_LIST (i_or_p
);
2348 else if (TREE_CODE (i_or_p
) == PROTOCOL_INTERFACE_TYPE
)
2349 plist
= PROTOCOL_LIST (i_or_p
);
2354 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
2355 if (TREE_CODE (TREE_VALUE (lproto
)) == PROTOCOL_INTERFACE_TYPE
2356 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto
)))
2359 /* Build initializer. */
2361 ptempl_p_t
= build_pointer_type (objc_v2_protocol_template
);
2362 e
= build_int_cst (ptempl_p_t
, size
);
2363 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, e
);
2365 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
2367 tree pval
= TREE_VALUE (lproto
);
2369 if (TREE_CODE (pval
) == PROTOCOL_INTERFACE_TYPE
2370 && PROTOCOL_FORWARD_DECL (pval
))
2372 tree fwref
= PROTOCOL_FORWARD_DECL (pval
);
2373 location_t loc
= DECL_SOURCE_LOCATION (fwref
) ;
2374 e
= build_unary_op (loc
, ADDR_EXPR
, fwref
, 0);
2375 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, e
);
2379 /* static struct protocol_list_t *list[size]; */
2381 switch (TREE_CODE (i_or_p
))
2383 case PROTOCOL_INTERFACE_TYPE
:
2384 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRefs_%s",
2385 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p
)));
2387 case CLASS_INTERFACE_TYPE
:
2388 snprintf (buf
, BUFSIZE
, "_OBJC_ClassProtocols_%s",
2389 IDENTIFIER_POINTER (CLASS_NAME (i_or_p
)));
2391 case CATEGORY_INTERFACE_TYPE
:
2392 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryProtocols_%s_%s",
2393 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)),
2394 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt
)));
2400 refs_decl
= start_var_decl (build_sized_array_type (ptempl_p_t
, size
+1),
2402 /* ObjC2 puts all these in the base section. */
2403 OBJCMETA (refs_decl
, objc_meta
, meta_base
);
2404 DECL_PRESERVE_P (refs_decl
) = 1;
2405 finish_var_decl (refs_decl
,
2406 objc_build_constructor (TREE_TYPE (refs_decl
),initlist
));
2410 /* This routine builds one 'struct method_t' initializer list. Note
2411 that the old ABI is supposed to build 'struct objc_method' which
2412 has 3 fields, but it does not build the initialization expression
2413 for 'method_imp' which for protocols is NULL any way. To be
2414 consistent with declaration of 'struct method_t', in the new ABI we
2415 set the method_t.imp to NULL. */
2418 build_v2_descriptor_table_initializer (tree type
, tree entries
)
2420 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2423 vec
<constructor_elt
, va_gc
> *eltlist
= NULL
;
2424 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
,
2425 build_selector (METHOD_SEL_NAME (entries
)));
2426 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
,
2427 add_objc_string (METHOD_ENCODING (entries
),
2429 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
, null_pointer_node
);
2431 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
2432 objc_build_constructor (type
, eltlist
));
2433 entries
= TREE_CHAIN (entries
);
2437 return objc_build_constructor (build_array_type (type
, 0), initlist
);
2440 /* struct method_list_t
2443 uint32_t method_count;
2444 struct objc_method method_list[method_count];
2448 build_v2_method_list_template (tree list_type
, int size
)
2450 tree method_list_t_record
;
2451 tree array_type
, decls
, *chain
= NULL
;
2453 method_list_t_record
= objc_start_struct (NULL_TREE
);
2455 /* uint32_t const entsize; */
2456 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2458 /* int method_count; */
2459 add_field_decl (integer_type_node
, "method_count", &chain
);
2461 /* struct objc_method method_list[]; */
2462 array_type
= build_sized_array_type (list_type
, size
);
2463 add_field_decl (array_type
, "method_list", &chain
);
2465 objc_finish_struct (method_list_t_record
, decls
);
2466 return method_list_t_record
;
2469 /* Note, as above that we are building to the objc_method_template
2470 which has the *imp field. ABI0/1 build with
2471 objc_method_prototype_template which is missing this field. */
2473 generate_v2_meth_descriptor_table (tree chain
, tree protocol
,
2474 const char *prefix
, tree attr
,
2475 vec
<tree
>& all_meths
)
2477 tree method_list_template
, initlist
, decl
;
2479 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2482 if (!chain
|| !prefix
)
2485 tree method
= chain
;
2489 if (! METHOD_ENCODING (method
))
2490 METHOD_ENCODING (method
) = encode_method_prototype (method
);
2491 all_meths
.safe_push (method
);
2492 method
= TREE_CHAIN (method
);
2497 method_list_template
= build_v2_method_list_template (objc_method_template
,
2499 snprintf (buf
, BUFSIZE
, "%s_%s", prefix
,
2500 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
2502 decl
= start_var_decl (method_list_template
, buf
);
2504 entsize
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template
));
2505 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, entsize
));
2506 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
2508 build_v2_descriptor_table_initializer (objc_method_template
,
2510 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
2511 /* Get into the right section. */
2512 OBJCMETA (decl
, objc_meta
, attr
);
2513 finish_var_decl (decl
, objc_build_constructor (method_list_template
, v
));
2518 generate_v2_meth_type_list (vec
<tree
>& all_meths
, tree protocol
,
2521 if (all_meths
.is_empty () || !prefix
)
2524 unsigned size
= all_meths
.length ();
2525 tree list_type
= build_sized_array_type (string_type_node
, size
);
2527 asprintf (&nam
, "%s_%s", prefix
,
2528 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
2529 tree decl
= start_var_decl (list_type
, nam
);
2531 OBJCMETA (decl
, objc_meta
, meta_base
);
2532 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2534 for (unsigned i
= 0; i
< size
; ++i
)
2535 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2536 add_objc_string (METHOD_ENCODING (all_meths
[i
]),
2538 finish_var_decl (decl
, objc_build_constructor (list_type
, v
));
2542 /* This routine builds the initializer list to initialize the 'struct
2543 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2546 build_v2_property_table_initializer (tree type
, tree context
)
2549 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2550 if (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
)
2551 x
= CLASS_PROPERTY_DECL (context
);
2553 x
= IMPL_PROPERTY_DECL (context
);
2555 for (; x
; x
= TREE_CHAIN (x
))
2557 vec
<constructor_elt
, va_gc
> *elemlist
= NULL
;
2558 /* NOTE! sections where property name/attribute go MUST change
2560 tree attribute
, name_ident
= PROPERTY_NAME (x
);
2562 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
2563 add_objc_string (name_ident
, prop_names_attr
));
2565 attribute
= objc_v2_encode_prop_attr (x
);
2566 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
2567 add_objc_string (attribute
, prop_names_attr
));
2569 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2570 objc_build_constructor (type
, elemlist
));
2573 return objc_build_constructor (build_array_type (type
, 0),inits
);
2576 /* This routine builds the following type:
2579 uint32_t entsize; // sizeof (struct _prop_t)
2580 uint32_t prop_count;
2581 struct _prop_t prop_list [prop_count];
2586 build_v2_property_list_template (tree list_type
, int size
)
2588 tree property_list_t_record
;
2589 tree array_type
, decls
, *chain
= NULL
;
2592 property_list_t_record
= objc_start_struct (NULL_TREE
);
2594 /* uint32_t const entsize; */
2595 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2597 /* int prop_count; */
2598 add_field_decl (integer_type_node
, "prop_count", &chain
);
2600 /* struct _prop_t prop_list[]; */
2601 array_type
= build_sized_array_type (list_type
, size
);
2602 add_field_decl (array_type
, "prop_list", &chain
);
2604 objc_finish_struct (property_list_t_record
, decls
);
2605 return property_list_t_record
;
2608 /* Top-level routine to generate property tables for each
2612 generate_v2_property_table (tree context
, tree klass_ctxt
)
2614 tree x
, decl
, initlist
, property_list_template
;
2615 bool is_proto
= false;
2616 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2617 int init_val
, size
= 0;
2622 gcc_assert (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
);
2623 x
= CLASS_PROPERTY_DECL (context
);
2627 x
= IMPL_PROPERTY_DECL (klass_ctxt
);
2629 for (; x
; x
= TREE_CHAIN (x
))
2635 property_list_template
=
2636 build_v2_property_list_template (objc_v2_property_template
,
2639 initlist
= build_v2_property_table_initializer (objc_v2_property_template
,
2643 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template
));
2645 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolPropList_%s",
2646 IDENTIFIER_POINTER (PROTOCOL_NAME (context
)));
2648 snprintf (buf
, BUFSIZE
, "_OBJC_ClassPropList_%s",
2649 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)));
2651 decl
= start_var_decl (property_list_template
, buf
);
2653 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2654 build_int_cst (NULL_TREE
, init_val
));
2655 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2656 build_int_cst (NULL_TREE
, size
));
2657 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
2659 OBJCMETA (decl
, objc_meta
, meta_base
);
2660 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), inits
));
2665 build_v2_protocol_initializer (tree type
, tree protocol_name
, tree protocol_list
,
2666 tree inst_methods
, tree class_methods
,
2667 tree opt_ins_meth
, tree opt_cls_meth
,
2668 tree property_list
, tree ext_meth_types
,
2669 tree demangled_name
, tree class_prop_list
)
2673 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2675 /* TODO: find a better representation of location from the inputs. */
2676 loc
= UNKNOWN_LOCATION
;
2678 /* This is NULL for the new ABI. */
2679 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2680 convert (objc_object_type
, null_pointer_node
));
2682 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_name
);
2683 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_list
);
2685 ttyp
= objc_method_proto_list_ptr
;
2687 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
2689 expr
= convert (ttyp
, null_pointer_node
);
2690 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2693 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
2695 expr
= convert (ttyp
, null_pointer_node
);
2696 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2699 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, opt_ins_meth
, 0));
2701 expr
= convert (ttyp
, null_pointer_node
);
2702 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2705 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, opt_cls_meth
, 0));
2707 expr
= convert (ttyp
, null_pointer_node
);
2708 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2710 ttyp
= objc_prop_list_ptr
;
2712 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
2714 expr
= convert (ttyp
, null_pointer_node
);
2715 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2717 /* const uint32_t size; = sizeof(struct protocol_t) */
2718 expr
= build_int_cst (integer_type_node
,
2719 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template
)));
2720 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2721 /* const uint32_t flags; = 0 */
2722 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, integer_zero_node
);
2724 ttyp
= build_pointer_type (string_type_node
);
2726 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, ext_meth_types
, 0));
2728 expr
= convert (ttyp
, null_pointer_node
);
2729 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2731 ttyp
= string_type_node
;
2733 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, demangled_name
, 0));
2735 expr
= convert (ttyp
, null_pointer_node
);
2736 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2738 ttyp
= objc_prop_list_ptr
;
2739 if (class_prop_list
)
2740 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_prop_list
, 0));
2742 expr
= convert (ttyp
, null_pointer_node
);
2743 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2745 return objc_build_constructor (type
, inits
);
2748 /* Main routine to build all meta data for all protocols used in a
2749 translation unit. */
2752 generate_v2_protocols (void)
2757 if (!protocol_chain
)
2760 /* If a protocol was directly referenced, pull in indirect
2762 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
2763 if (PROTOCOL_FORWARD_DECL (p
) && PROTOCOL_LIST (p
))
2764 generate_protocol_references (PROTOCOL_LIST (p
));
2766 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
2769 tree inst_meth
, class_meth
, opt_inst_meth
, opt_class_meth
, props
;
2770 tree decl
, initlist
, protocol_name_expr
, refs_decl
, refs_expr
;
2772 /* If protocol wasn't referenced, don't generate any code. */
2773 decl
= PROTOCOL_FORWARD_DECL (p
);
2778 loc
= DECL_SOURCE_LOCATION (decl
);
2781 vec
<tree
> all_meths
= vNULL
;
2783 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p
), p
,
2784 "_OBJC_ProtocolInstanceMethods",
2785 meta_proto_nst_meth
, all_meths
);
2788 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p
), p
,
2789 "_OBJC_ProtocolClassMethods",
2790 meta_proto_cls_meth
, all_meths
);
2793 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p
), p
,
2794 "_OBJC_ProtocolOptInstMethods",
2795 meta_proto_nst_meth
, all_meths
);
2798 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p
), p
,
2799 "_OBJC_ProtocolOptClassMethods",
2800 meta_proto_cls_meth
, all_meths
);
2802 if (PROTOCOL_LIST (p
))
2803 refs_decl
= generate_v2_protocol_list (p
, NULL_TREE
);
2807 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2808 protocol_name_expr
= add_objc_string (PROTOCOL_NAME (p
), class_names
);
2811 refs_expr
= convert (build_pointer_type (objc_v2_protocol_template
),
2812 build_unary_op (loc
, ADDR_EXPR
, refs_decl
, 0));
2814 refs_expr
= build_int_cst (NULL_TREE
, 0);
2816 props
= generate_v2_property_table (p
, NULL_TREE
);
2819 = generate_v2_meth_type_list (all_meths
, p
,
2820 "_OBJC_ProtocolMethodTypes");
2821 tree demangled_name
= NULL_TREE
;
2822 tree class_prop_list
= NULL_TREE
;
2824 initlist
= build_v2_protocol_initializer (TREE_TYPE (decl
),
2825 protocol_name_expr
, refs_expr
,
2826 inst_meth
, class_meth
,
2827 opt_inst_meth
, opt_class_meth
,
2828 props
, ext_meth_types
,
2829 demangled_name
,class_prop_list
);
2830 finish_var_decl (decl
, initlist
);
2831 objc_add_to_protocol_list (p
, decl
);
2832 all_meths
.truncate (0);
2837 /* Make sure we get the Protocol class linked in - reference
2839 p
= objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME
));
2840 /* ... but since we don't specifically use the reference... we
2841 need to force it. */
2842 DECL_PRESERVE_P (p
) = 1;
2847 generate_v2_dispatch_table (tree chain
, const char *name
, tree attr
)
2849 tree decl
, method_list_template
, initlist
;
2850 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2853 if (!chain
|| !name
|| !(size
= list_length (chain
)))
2856 method_list_template
2857 = build_v2_method_list_template (objc_method_template
, size
);
2859 = build_dispatch_table_initializer (objc_method_template
, chain
);
2861 decl
= start_var_decl (method_list_template
, name
);
2863 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template
));
2864 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2865 build_int_cst (integer_type_node
, init_val
));
2866 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2867 build_int_cst (integer_type_node
, size
));
2868 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
2870 OBJCMETA (decl
, objc_meta
, attr
);
2871 finish_var_decl (decl
,
2872 objc_build_constructor (TREE_TYPE (decl
), v
));
2876 /* Init a category. */
2878 build_v2_category_initializer (tree type
, tree cat_name
, tree class_name
,
2879 tree inst_methods
, tree class_methods
,
2880 tree protocol_list
, tree property_list
,
2884 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2886 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, cat_name
);
2887 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, class_name
);
2889 ltyp
= objc_method_list_ptr
;
2891 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
2893 expr
= convert (ltyp
, null_pointer_node
);
2894 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2897 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
2899 expr
= convert (ltyp
, null_pointer_node
);
2900 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2902 /* protocol_list = */
2903 ltyp
= build_pointer_type (objc_v2_protocol_template
);
2905 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
2907 expr
= convert (ltyp
, null_pointer_node
);
2908 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2910 ltyp
= objc_prop_list_ptr
;
2912 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
2914 expr
= convert (ltyp
, null_pointer_node
);
2915 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2917 return objc_build_constructor (type
, v
);
2920 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2923 generate_v2_category (struct imp_entry
*impent
)
2925 tree initlist
, cat_name_expr
, class_name_expr
;
2926 tree protocol_decl
, category
, props
, t
;
2927 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
2928 tree cat
= impent
->imp_context
;
2929 tree cat_decl
= impent
->class_decl
;
2933 loc
= DECL_SOURCE_LOCATION (cat_decl
);
2935 /* ??? not sure this is really necessary, the following references should
2936 force appropriate linkage linkage...
2937 -- but ... ensure a reference to the class... */
2938 t
= objc_v2_get_class_reference (CLASS_NAME (cat
));
2939 /* ... which we ignore so force it out.. */
2940 DECL_PRESERVE_P (t
) = 1;
2942 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat
)));
2943 class_name_expr
= create_extern_decl (objc_v2_class_template
, buf
);
2944 class_name_expr
= build_fold_addr_expr (class_name_expr
);
2946 cat_name_expr
= add_objc_string (CLASS_SUPER_NAME (cat
), class_names
);
2947 category
= lookup_category (impent
->imp_template
, CLASS_SUPER_NAME (cat
));
2949 if (category
&& CLASS_PROTOCOL_LIST (category
))
2951 generate_protocol_references (CLASS_PROTOCOL_LIST (category
));
2952 protocol_decl
= generate_v2_protocol_list (category
, cat
);
2955 protocol_decl
= NULL_TREE
;
2957 /* decl = update_var_decl(impent->class_decl); */
2959 props
= generate_v2_property_table (NULL_TREE
, cat
);
2961 if (CLASS_NST_METHODS (cat
))
2963 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryInstanceMethods_%s_%s",
2964 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
2965 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
2966 inst_methods
= generate_v2_dispatch_table (CLASS_NST_METHODS (cat
), buf
,
2970 if (CLASS_CLS_METHODS (cat
))
2972 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryClassMethods_%s_%s",
2973 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
2974 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
2975 class_methods
= generate_v2_dispatch_table (CLASS_CLS_METHODS (cat
), buf
,
2979 initlist
= build_v2_category_initializer (TREE_TYPE (cat_decl
),
2980 cat_name_expr
, class_name_expr
,
2981 inst_methods
, class_methods
,
2982 protocol_decl
, props
, loc
);
2984 finish_var_decl (cat_decl
, initlist
);
2985 impent
->class_decl
= cat_decl
;
2987 /* Add to list of pointers in __category_list section. */
2988 objc_v2_add_to_category_list (cat_decl
);
2989 if (has_load_impl (CLASS_CLS_METHODS (impent
->imp_context
)))
2990 objc_v2_add_to_nonlazy_category_list (cat_decl
);
2993 /* This routine declares a variable to hold the offset for ivar
2994 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
2996 struct GTY(()) ivarref_entry
3002 static GTY (()) vec
<ivarref_entry
, va_gc
> *ivar_offset_refs
;
3005 ivar_offset_ref (tree class_name
, tree field_decl
)
3007 tree decl
, field_decl_id
;
3012 create_ivar_offset_name (buf
, class_name
, field_decl
);
3013 field_decl_id
= get_identifier (buf
);
3015 if (ivar_offset_refs
)
3019 FOR_EACH_VEC_ELT (*ivar_offset_refs
, count
, ref
)
3020 if (DECL_NAME (ref
->decl
) == field_decl_id
)
3024 /* Somewhat arbitrary initial provision. */
3025 vec_alloc (ivar_offset_refs
, 32);
3027 /* We come here if we don't find a match or at the start. */
3028 global_var
= (TREE_PUBLIC (field_decl
) || TREE_PROTECTED (field_decl
));
3030 decl
= create_global_decl (TREE_TYPE (size_zero_node
), buf
);
3032 decl
= create_hidden_decl (TREE_TYPE (size_zero_node
), buf
);
3034 /* Identify so that we can indirect these where the ABI requires. */
3035 OBJCMETA (decl
, objc_meta
, meta_ivar_ref
);
3038 e
.offset
= byte_position (field_decl
);
3039 vec_safe_push (ivar_offset_refs
, e
);
3043 /* This routine builds initializer-list needed to initialize 'struct
3044 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
3045 'struct ivar_t' and FIELD_DECL is list of ivars for the target
3049 build_v2_ivar_list_initializer (tree class_name
, tree type
, tree field_decl
)
3051 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
3055 vec
<constructor_elt
, va_gc
> *ivar
= NULL
;
3059 /* Unnamed bitfields are ignored. */
3060 if (!DECL_NAME (field_decl
))
3062 field_decl
= DECL_CHAIN (field_decl
);
3067 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3068 build_unary_op (input_location
,
3070 ivar_offset_ref (class_name
,
3074 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3075 add_objc_string (DECL_NAME (field_decl
),
3079 id
= add_objc_string (encode_field_decl (field_decl
),
3081 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
, id
);
3083 /* Set alignment. */
3084 val
= DECL_ALIGN_UNIT (field_decl
);
3085 val
= exact_log2 (val
);
3086 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3087 build_int_cst (integer_type_node
, val
));
3090 val
= TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl
));
3091 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3092 build_int_cst (integer_type_node
, val
));
3094 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3095 objc_build_constructor (type
, ivar
));
3098 field_decl
= DECL_CHAIN (field_decl
);
3099 while (field_decl
&& TREE_CODE (field_decl
) != FIELD_DECL
);
3103 return objc_build_constructor (build_array_type (type
, 0), inits
);
3111 struct iver_t list[count];
3116 build_v2_ivar_list_t_template (tree list_type
, int size
)
3118 tree objc_ivar_list_record
;
3119 tree decls
, *chain
= NULL
;
3122 objc_ivar_list_record
= objc_start_struct (NULL_TREE
);
3124 /* uint32 entsize; */
3125 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
3128 add_field_decl (integer_type_node
, "count", &chain
);
3130 /* struct objc_ivar ivar_list[]; */
3131 add_field_decl (build_sized_array_type (list_type
, size
),
3134 objc_finish_struct (objc_ivar_list_record
, decls
);
3135 return objc_ivar_list_record
;
3138 /* This routine declares a static variable of type 'struct
3139 ivar_list_t' and initializes it. chain is the source of the data,
3140 name is the name for the var. attr is the meta-data section tag
3141 attribute. templ is the implementation template for the class. */
3144 generate_v2_ivars_list (tree chain
, const char *name
, tree attr
, tree templ
)
3146 tree decl
, initlist
, ivar_list_template
;
3147 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
3148 int size
, ivar_t_size
;
3150 if (!chain
|| !name
|| !(size
= ivar_list_length (chain
)))
3153 generating_instance_variables
= 1;
3154 ivar_list_template
= build_v2_ivar_list_t_template (objc_v2_ivar_template
,
3157 initlist
= build_v2_ivar_list_initializer (CLASS_NAME (templ
),
3158 objc_v2_ivar_template
, chain
);
3159 ivar_t_size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template
));
3161 decl
= start_var_decl (ivar_list_template
, name
);
3162 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3163 build_int_cst (integer_type_node
, ivar_t_size
));
3164 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3165 build_int_cst (integer_type_node
, size
));
3166 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
3167 OBJCMETA (decl
, objc_meta
, attr
);
3168 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), inits
));
3169 generating_instance_variables
= 0;
3173 /* Routine to build initializer list to initialize objects of type
3177 build_v2_class_t_initializer (tree type
, tree isa
, tree superclass
,
3178 tree ro
, tree cache
, tree vtable
)
3180 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3183 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, isa
);
3186 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, superclass
);
3190 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, cache
);
3192 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, null_pointer_node
);
3196 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, vtable
);
3198 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, null_pointer_node
);
3201 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, ro
);
3203 return objc_build_constructor (type
, initlist
);
3206 /* Routine to build object of struct class_ro_t { ... }; */
3209 build_v2_class_ro_t_initializer (tree type
, tree name
,
3210 unsigned int flags
, unsigned int instanceStart
,
3211 unsigned int instanceSize
,
3213 tree baseMethods
, tree baseProtocols
,
3214 tree ivars
, tree property_list
)
3216 tree expr
, unsigned_char_star
, ltyp
;
3218 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3220 /* TODO: fish out the real location from somewhere. */
3221 loc
= UNKNOWN_LOCATION
;
3224 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3225 build_int_cst (integer_type_node
, flags
));
3228 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3229 build_int_cst (integer_type_node
, instanceStart
));
3232 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3233 build_int_cst (integer_type_node
, instanceSize
));
3235 /* This ABI is currently only used on m64 NeXT. We always
3236 explicitly declare the alignment padding. */
3237 /* reserved, pads alignment. */
3238 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3239 build_int_cst (integer_type_node
, 0));
3242 unsigned_char_star
= build_pointer_type (unsigned_char_type_node
);
3246 expr
= convert (unsigned_char_star
, null_pointer_node
);
3247 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3250 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, default_conversion (name
));
3253 ltyp
= objc_method_list_ptr
;
3255 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, baseMethods
, 0));
3257 expr
= convert (ltyp
, null_pointer_node
);
3258 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3261 ltyp
= build_pointer_type (xref_tag (RECORD_TYPE
,
3262 get_identifier (UTAG_V2_PROTOCOL_LIST
)));
3264 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, baseProtocols
, 0));
3266 expr
= convert (ltyp
, null_pointer_node
);
3267 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3270 ltyp
= objc_v2_ivar_list_ptr
;
3272 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, ivars
, 0));
3274 expr
= convert (ltyp
, null_pointer_node
);
3275 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3277 /* TODO: We don't yet have the weak/strong stuff... */
3278 /* weakIvarLayout */
3279 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3280 convert (unsigned_char_star
, null_pointer_node
));
3283 ltyp
= objc_prop_list_ptr
;
3285 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
3287 expr
= convert (ltyp
, null_pointer_node
);
3288 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3289 return objc_build_constructor (type
, initlist
);
3292 static GTY (()) vec
<ident_data_tuple
, va_gc
> *ehtype_list
;
3294 /* Record a name as needing a catcher. */
3296 objc_v2_add_to_ehtype_list (tree name
)
3302 ident_data_tuple
*ref
;
3304 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3305 if (ref
->ident
== name
)
3306 return; /* Already entered. */
3309 /* Arbitrary initial count. */
3310 vec_alloc (ehtype_list
, 8);
3312 /* Not found, or new list. */
3315 vec_safe_push (ehtype_list
, e
);
3319 generate_v2_class_structs (struct imp_entry
*impent
)
3321 tree decl
, name_expr
, initlist
, protocol_decl
, metaclass_decl
, class_decl
;
3322 tree field
, firstIvar
, chain
;
3323 tree class_superclass_expr
, metaclass_superclass_expr
, props
;
3324 /* TODO: figure out how to compute this. */
3325 tree ivarLayout
= NULL_TREE
;
3326 tree my_super_id
= NULL_TREE
, root_expr
= NULL_TREE
;
3327 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
3328 tree inst_ivars
= NULL_TREE
, class_ivars
= NULL_TREE
;
3331 unsigned int instanceStart
, instanceSize
;
3332 unsigned int flags
= 0x01; /* RO_META */
3333 int cls_flags
= impent
->has_cxx_cdtors
? OBJC2_CLS_HAS_CXX_STRUCTORS
3336 class_decl
= impent
->class_decl
;
3337 metaclass_decl
= impent
->meta_decl
;
3338 loc
= DECL_SOURCE_LOCATION (class_decl
);
3340 DECL_EXTERNAL (class_decl
) = DECL_EXTERNAL (metaclass_decl
) = 0;
3341 TREE_PUBLIC (class_decl
) = TREE_PUBLIC (metaclass_decl
) = 1;
3343 gcc_assert (!CP_DECL_CONTEXT (class_decl
) || CP_DECL_CONTEXT (class_decl
) == global_namespace
);
3344 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl
) || CP_DECL_CONTEXT (metaclass_decl
) == global_namespace
);
3347 /* Generation of data for meta class. */
3348 my_super_id
= CLASS_SUPER_NAME (impent
->imp_template
);
3351 /* Compute reference to root's name. For a meta class, "isa" is
3352 a reference to the root class name. */
3353 tree my_root_id
= my_super_id
;
3354 tree my_root_int
, interface
;
3357 my_root_int
= lookup_interface (my_root_id
);
3359 if (my_root_int
&& CLASS_SUPER_NAME (my_root_int
))
3360 my_root_id
= CLASS_SUPER_NAME (my_root_int
);
3366 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3367 create extern if not already declared. */
3368 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
3369 IDENTIFIER_POINTER (CLASS_NAME (my_root_int
)));
3370 root_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3371 root_expr
= build_fold_addr_expr (root_expr
);
3373 /* Install class `isa' and `super' pointers at runtime. */
3374 interface
= lookup_interface (my_super_id
);
3375 gcc_assert (interface
);
3376 /* Similarly, for OBJC_CLASS_$_<interface>... */
3377 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s",
3378 IDENTIFIER_POINTER (CLASS_NAME (interface
)));
3379 class_superclass_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3380 class_superclass_expr
= build_fold_addr_expr (class_superclass_expr
);
3381 /* ... and for OBJC_METACLASS_$_<interface>. */
3382 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
3383 IDENTIFIER_POINTER (CLASS_NAME (interface
)));
3384 metaclass_superclass_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3385 metaclass_superclass_expr
= build_fold_addr_expr (metaclass_superclass_expr
);
3390 root_expr
= build_unary_op (loc
, ADDR_EXPR
, metaclass_decl
, 0);
3391 metaclass_superclass_expr
= build_unary_op (loc
, ADDR_EXPR
, class_decl
, 0);
3392 class_superclass_expr
= build_int_cst (NULL_TREE
, 0);
3393 flags
|= 0x02; /* RO_ROOT: it is also a root meta class. */
3396 if (CLASS_PROTOCOL_LIST (impent
->imp_template
))
3398 generate_protocol_references (CLASS_PROTOCOL_LIST (impent
->imp_template
));
3399 protocol_decl
= generate_v2_protocol_list (impent
->imp_template
,
3400 impent
->imp_context
);
3405 name_expr
= add_objc_string (CLASS_NAME (impent
->imp_template
),
3408 if (CLASS_CLS_METHODS (impent
->imp_context
))
3410 snprintf (buf
, BUFSIZE
, "_OBJC_ClassMethods_%s",
3411 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3413 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent
->imp_context
),
3414 buf
, meta_clac_meth
);
3417 instanceStart
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template
));
3419 /* Currently there are no class ivars and generation of class
3420 variables for the root of the inheritance has been removed. It
3421 causes multiple defines if there are two root classes in the
3422 link, because each will define its own identically-named offset
3425 class_ivars
= NULL_TREE
;
3426 /* TODO: Add total size of class variables when implemented. */
3427 instanceSize
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template
));
3429 /* So now build the META CLASS structs. */
3430 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3432 decl
= start_var_decl (objc_v2_class_ro_template
,
3433 newabi_append_ro (IDENTIFIER_POINTER
3434 (DECL_NAME (metaclass_decl
))));
3436 /* TODO: ivarLayout needs t be built. */
3438 build_v2_class_ro_t_initializer (TREE_TYPE (decl
), name_expr
,
3439 (flags
| cls_flags
), instanceStart
,
3440 instanceSize
, ivarLayout
,
3441 class_methods
, protocol_decl
,
3442 class_ivars
, NULL_TREE
);
3443 /* The ROs sit in the default const section. */
3444 OBJCMETA (decl
, objc_meta
, meta_base
);
3445 finish_var_decl (decl
, initlist
);
3447 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3449 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl
),
3451 metaclass_superclass_expr
,
3452 build_fold_addr_expr (decl
),
3453 build_fold_addr_expr (UOBJC_V2_CACHE_decl
),
3454 build_fold_addr_expr (UOBJC_V2_VTABLE_decl
));
3455 /* The class section attributes are set when they are created. */
3456 finish_var_decl (metaclass_decl
, initlist
);
3457 impent
->meta_decl
= metaclass_decl
;
3459 /* So now build the CLASS structs. */
3461 flags
= 0x0; /* ... */
3463 flags
|= 0x02; /* RO_ROOT: this is a root class */
3465 if (DECL_VISIBILITY (class_decl
) == VISIBILITY_HIDDEN
)
3466 flags
|= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3468 if (objc2_objc_exception_attr (impent
->imp_template
))
3469 flags
|= 0x20; /* RO_EXCEPTION */
3471 if (CLASS_NST_METHODS (impent
->imp_context
))
3473 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceMethods_%s",
3474 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3476 generate_v2_dispatch_table (CLASS_NST_METHODS (impent
->imp_context
),
3477 buf
, meta_clai_meth
);
3480 /* Sort out the ivars before we try to compute the class sizes. */
3481 if ((chain
= CLASS_IVARS (impent
->imp_template
)))
3483 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceIvars_%s",
3484 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3485 inst_ivars
= generate_v2_ivars_list (chain
, buf
, meta_clai_vars
,
3486 impent
->imp_template
);
3489 /* Compute instanceStart. */
3490 gcc_assert (CLASS_STATIC_TEMPLATE (impent
->imp_template
));
3491 field
= TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent
->imp_template
));
3492 if (my_super_id
&& field
&& TREE_CHAIN (field
))
3493 field
= TREE_CHAIN (field
);
3497 while (firstIvar
&& TREE_CODE (firstIvar
) != FIELD_DECL
)
3498 firstIvar
= TREE_CHAIN (firstIvar
);
3500 gcc_assert (inst_ivars
? (firstIvar
!= NULL_TREE
): true);
3502 /* Compute instanceSize. */
3503 while (field
&& TREE_CHAIN (field
)
3504 && TREE_CODE (TREE_CHAIN (field
)) == FIELD_DECL
)
3505 field
= TREE_CHAIN (field
);
3507 if (field
&& TREE_CODE (field
) == FIELD_DECL
)
3508 instanceSize
= int_byte_position (field
) * BITS_PER_UNIT
3509 + tree_to_shwi (DECL_SIZE (field
));
3512 instanceSize
/= BITS_PER_UNIT
;
3514 props
= generate_v2_property_table (NULL_TREE
, impent
->imp_context
);
3516 /* If the class has no ivars, instanceStart should be set to the
3517 superclass's instanceSize. */
3519 (inst_ivars
!= NULL_TREE
) ? (unsigned) int_byte_position (firstIvar
)
3522 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3523 decl
= start_var_decl (objc_v2_class_ro_template
,
3524 newabi_append_ro (IDENTIFIER_POINTER
3525 (DECL_NAME (class_decl
))));
3528 build_v2_class_ro_t_initializer (TREE_TYPE (decl
), name_expr
,
3529 (flags
| cls_flags
), instanceStart
,
3530 instanceSize
, ivarLayout
,
3531 inst_methods
, protocol_decl
,
3533 /* The ROs sit in the default const section. */
3534 OBJCMETA (decl
, objc_meta
, meta_base
);
3535 finish_var_decl (decl
, initlist
);
3537 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3538 initlist
= build_v2_class_t_initializer (TREE_TYPE (class_decl
),
3539 build_fold_addr_expr (metaclass_decl
),
3540 class_superclass_expr
,
3541 build_fold_addr_expr (decl
),
3542 build_fold_addr_expr (UOBJC_V2_CACHE_decl
),
3543 build_fold_addr_expr (UOBJC_V2_VTABLE_decl
));
3545 /* The class section attributes are set when they are created. */
3546 finish_var_decl (class_decl
, initlist
);
3547 impent
->class_decl
= class_decl
;
3549 objc_v2_add_to_class_list (class_decl
);
3550 if (has_load_impl (CLASS_CLS_METHODS (impent
->imp_context
)))
3551 objc_v2_add_to_nonlazy_class_list (class_decl
);
3553 if (flags
& 0x20) /* RO_EXCEPTION */
3554 objc_v2_add_to_ehtype_list (CLASS_NAME (impent
->imp_template
));
3557 /* This routine outputs the (ivar_reference_offset, offset)
3561 build_v2_ivar_offset_ref_table (void)
3566 if (!vec_safe_length (ivar_offset_refs
))
3569 FOR_EACH_VEC_ELT (*ivar_offset_refs
, count
, ref
)
3570 finish_var_decl (ref
->decl
, ref
->offset
);
3574 objc_generate_v2_next_metadata (void)
3576 struct imp_entry
*impent
;
3578 /* FIXME: Make sure that we generate no metadata if there is nothing
3581 gcc_assert (!objc_static_instances
); /* Not for NeXT */
3583 build_metadata_templates ();
3585 for (impent
= imp_list
; impent
; impent
= impent
->next
)
3587 /* If -gen-decls is present, Dump the @interface of each class.
3588 TODO: Dump the classes in the order they were found, rather
3589 than in reverse order as we are doing now. */
3590 if (flag_gen_declaration
)
3591 dump_interface (gen_declaration_file
, impent
->imp_context
);
3593 /* all of the following reference the string pool... */
3594 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
3595 generate_v2_class_structs (impent
);
3597 generate_v2_category (impent
);
3600 build_next_selector_translation_table ();
3601 build_v2_message_ref_translation_table ();
3603 /* This will add "Protocol" to the class refs. */
3604 generate_v2_protocols ();
3606 build_v2_classrefs_table ();
3607 build_v2_super_classrefs_table (/*metaclass= */false);
3608 build_v2_super_classrefs_table (/*metaclass= */true);
3610 build_v2_ivar_offset_ref_table ();
3612 build_v2_protocol_list_translation_table ();
3613 build_v2_protocol_list_address_table ();
3615 build_v2_address_table (class_list
, "_OBJC_ClassList$",
3616 meta_label_classlist
);
3617 build_v2_address_table (category_list
, "_OBJC_CategoryList$",
3618 meta_label_categorylist
);
3619 build_v2_address_table (nonlazy_class_list
, "_OBJC_NonLazyClassList$",
3620 meta_label_nonlazy_classlist
);
3621 build_v2_address_table (nonlazy_category_list
, "_OBJC_NonLazyCategoryList$",
3622 meta_label_nonlazy_categorylist
);
3624 /* Generate catch objects for eh, if any are needed. */
3625 build_v2_eh_catch_objects ();
3627 /* Emit the string table last. */
3628 generate_strings ();
3631 /* NOTE --- Output NeXT V2 Exceptions --- */
3633 static GTY(()) tree objc_v2_ehtype_template
;
3634 static GTY(()) tree next_v2_ehvtable_decl
;
3635 static GTY(()) tree next_v2_EHTYPE_id_decl
;
3638 build_v2_ehtype_template (void)
3640 tree decls
, *chain
= NULL
;
3641 objc_v2_ehtype_template
= objc_start_struct (get_identifier (UTAG_V2_EH_TYPE
));
3643 /* void *_objc_ehtype_vtable; */
3644 decls
= add_field_decl (ptr_type_node
, "_objc_ehtype_vtable_ptr", &chain
);
3646 /* const char *className; */
3647 add_field_decl (string_type_node
, "className", &chain
);
3649 /* struct class_t *const cls; */
3650 add_field_decl (build_pointer_type (objc_v2_class_template
), "cls", &chain
);
3652 objc_finish_struct (objc_v2_ehtype_template
, decls
);
3655 /* Template for the Objective-C family typeinfo type for ABI=2. This
3656 starts off the same as the gxx/cxx eh typeinfo.
3658 struct _objc_ehtype_t
3660 void *_objc_ehtype_vtable_ptr; - as per c++
3661 const char *className; - as per c++
3662 struct class_t *const cls;
3666 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3670 objc2_build_ehtype_initializer (tree name
, tree cls
)
3672 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3675 /* This is done the same way as c++, missing the two first entries
3676 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3677 runtime source about this so, perhaps, this will change at some
3679 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3680 if (!next_v2_ehvtable_decl
)
3682 next_v2_ehvtable_decl
=
3683 start_var_decl (ptr_type_node
, TAG_NEXT_EHVTABLE_NAME
);
3684 TREE_STATIC (next_v2_ehvtable_decl
) = 0;
3685 DECL_EXTERNAL (next_v2_ehvtable_decl
) = 1;
3686 TREE_PUBLIC (next_v2_ehvtable_decl
) = 1;
3688 addr
= build_fold_addr_expr_with_type (next_v2_ehvtable_decl
, ptr_type_node
);
3689 offs
= size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node
)));
3690 addr
= fold_build_pointer_plus (addr
, offs
);
3692 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, addr
);
3695 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, name
);
3698 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, cls
);
3700 return objc_build_constructor (objc_v2_ehtype_template
, initlist
);
3704 build_ehtype (tree name
, const char *eh_name
, bool weak
)
3706 tree name_expr
, class_name_expr
, ehtype_decl
, inits
;
3708 name_expr
= add_objc_string (name
, class_names
);
3709 /* Extern ref. for the class. ??? Maybe we can look this up
3712 create_extern_decl (objc_v2_class_template
,
3713 objc_build_internal_classname (name
, false));
3714 class_name_expr
= build_fold_addr_expr (class_name_expr
);
3715 ehtype_decl
= create_global_decl (objc_v2_ehtype_template
, eh_name
);
3717 DECL_WEAK (ehtype_decl
) = 1;
3718 inits
= objc2_build_ehtype_initializer (name_expr
, class_name_expr
);
3719 OBJCMETA (ehtype_decl
, objc_meta
, meta_ehtype
);
3720 finish_var_decl (ehtype_decl
, inits
);
3724 /* This routine returns TRUE if CLS or any of its super classes has
3725 __attribute__ ((objc_exception)). */
3728 objc2_objc_exception_attr (tree cls
)
3732 if (CLASS_HAS_EXCEPTION_ATTR (cls
))
3734 cls
= lookup_interface (CLASS_SUPER_NAME (cls
));
3741 is_implemented (tree name
)
3743 struct imp_entry
*t
;
3744 for (t
= imp_list
; t
; t
= t
->next
)
3745 if (TREE_CODE (t
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
3746 && CLASS_NAME (t
->imp_template
) == name
)
3752 /* We will build catch objects:
3753 for any type implemented here.
3754 for any type used in a catch that has no exception attribute. */
3755 static void build_v2_eh_catch_objects (void)
3758 ident_data_tuple
*ref
;
3760 if (!vec_safe_length (ehtype_list
))
3763 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3766 bool impl
= is_implemented (ref
->ident
);
3767 bool excpt
= objc2_objc_exception_attr (lookup_interface (ref
->ident
));
3768 snprintf (buf
, BUFSIZE
, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref
->ident
));
3770 /* The User says this class has a catcher already. */
3771 ref
->data
= create_extern_decl (objc_v2_ehtype_template
, buf
);
3773 /* Create a catcher, weak if it wasn't marked. */
3774 ref
->data
= build_ehtype (ref
->ident
, buf
, !excpt
);
3779 lookup_ehtype_ref (tree id
)
3782 ident_data_tuple
*ref
;
3784 if (!vec_safe_length (ehtype_list
))
3787 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3788 if (ref
->ident
== id
)
3793 /* This hook, called via lang_eh_runtime_type, generates a runtime
3794 object which is either the address of the 'OBJC_EHTYPE_$_class'
3795 object or address of external OBJC_EHTYPE_id object. */
3797 next_runtime_02_eh_type (tree type
)
3801 if (type
== error_mark_node
3802 /*|| errorcount || sorrycount*/)
3805 if (POINTER_TYPE_P (type
) && objc_is_object_id (TREE_TYPE (type
)))
3807 if (!next_v2_EHTYPE_id_decl
)
3809 /* This is provided by the Apple/NeXT libobjc.dylib so we
3810 need only to reference it. */
3811 next_v2_EHTYPE_id_decl
=
3812 start_var_decl (objc_v2_ehtype_template
, "OBJC_EHTYPE_id");
3813 DECL_EXTERNAL (next_v2_EHTYPE_id_decl
) = 1;
3814 TREE_PUBLIC (next_v2_EHTYPE_id_decl
) = 1;
3815 TREE_STATIC (next_v2_EHTYPE_id_decl
) = 0;
3817 return build_fold_addr_expr (next_v2_EHTYPE_id_decl
);
3820 if (!POINTER_TYPE_P (type
) || !TYPED_OBJECT (TREE_TYPE (type
)))
3823 /* This routine is also called for c++'s catch clause; in which
3824 case, we use c++'s typeinfo decl. */
3825 return build_eh_type_type (type
);
3827 error ("non-objective-c type %qT cannot be caught", type
);
3832 t
= OBJC_TYPE_NAME (TREE_TYPE (type
));
3834 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3835 t
= lookup_ehtype_ref (t
);
3839 return build_fold_addr_expr (t
);
3842 return error_mark_node
;
3845 static GTY(()) tree objc_eh_personality_decl
;
3848 objc_eh_personality (void)
3850 if (!objc_eh_personality_decl
)
3851 objc_eh_personality_decl
= build_personality_function ("objc");
3852 return objc_eh_personality_decl
;
3855 /* NOTE --- interfaces --- */
3858 build_throw_stmt (location_t loc
, tree throw_expr
, bool rethrown
)
3862 /* We have a separate re-throw entry. */
3863 t
= build_function_call_vec (loc
, vNULL
, objc_rethrow_exception_decl
,
3867 /* Throw like the others... */
3868 vec
<tree
, va_gc
> *parms
;
3869 vec_alloc (parms
, 1);
3870 parms
->quick_push (throw_expr
);
3871 t
= build_function_call_vec (loc
, vNULL
, objc_exception_throw_decl
,
3875 return add_stmt (t
);
3878 /* Build __builtin_eh_pointer. */
3881 objc_build_exc_ptr (struct objc_try_context
**x ATTRIBUTE_UNUSED
)
3884 t
= builtin_decl_explicit (BUILT_IN_EH_POINTER
);
3885 t
= build_call_expr (t
, 1, integer_zero_node
);
3886 return fold_convert (objc_object_type
, t
);
3889 static tree
begin_catch (struct objc_try_context
**cur_try_context
, tree type
,
3890 tree decl
, tree compound
, bool ellipsis ATTRIBUTE_UNUSED
)
3894 /* Record the data for the catch in the try context so that we can
3895 finalize it later. Ellipsis is signalled by a NULL entry. */
3897 t
= build_stmt (input_location
, CATCH_EXPR
, NULL_TREE
, compound
);
3899 t
= build_stmt (input_location
, CATCH_EXPR
, type
, compound
);
3900 (*cur_try_context
)->current_catch
= t
;
3902 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3903 t
= objc_build_exc_ptr (cur_try_context
);
3904 t
= convert (TREE_TYPE (decl
), t
);
3905 /* FIXME: location. */
3906 if (type
&& type
!= error_mark_node
)
3908 t
= build1(NOP_EXPR
, ptr_type_node
, t
);
3909 t
= build_function_call (input_location
, objc2_begin_catch_decl
,
3910 tree_cons (NULL_TREE
, t
, NULL_TREE
));
3912 /* We might want to build a catch object for this (if it's not
3914 if (POINTER_TYPE_P (type
)
3915 && !objc_is_object_id (TREE_TYPE (type
))
3916 && TYPED_OBJECT (TREE_TYPE (type
)))
3917 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type
)));
3919 return build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
3922 /* try { catch-body } finally { objc_end_catch (); } */
3924 finish_catch (struct objc_try_context
**cur_try_context
, tree curr_catch
)
3926 struct objc_try_context
*ct
;
3927 tree try_exp
, func
, *l
, t
;
3928 location_t loc
= (*cur_try_context
)->try_locus
;
3930 if (!curr_catch
|| curr_catch
== error_mark_node
)
3933 t
= CATCH_BODY (curr_catch
);
3934 if (TREE_CODE (t
) == BIND_EXPR
)
3936 /* Usual case of @catch (objc-expr). */
3937 objc_begin_try_stmt (loc
, BIND_EXPR_BODY (t
));
3938 BIND_EXPR_BODY (t
) = NULL_TREE
;
3939 l
= &BIND_EXPR_BODY (t
);
3943 /* NULL entry, meaning @catch (...). */
3944 objc_begin_try_stmt (loc
, t
);
3945 CATCH_BODY (curr_catch
) = NULL_TREE
;
3946 l
= &CATCH_BODY (curr_catch
);
3949 /* Pick up the new context we made in begin_try above... */
3950 ct
= *cur_try_context
;
3951 func
= build_function_call_vec (loc
, vNULL
, objc2_end_catch_decl
, NULL
,
3953 append_to_statement_list (func
, &ct
->finally_body
);
3954 try_exp
= build_stmt (loc
, TRY_FINALLY_EXPR
, ct
->try_body
, ct
->finally_body
);
3955 *cur_try_context
= ct
->outer
;
3957 append_to_statement_list (try_exp
, l
);
3958 append_to_statement_list (curr_catch
, &((*cur_try_context
)->catch_list
));
3962 finish_try_stmt (struct objc_try_context
**cur_try_context
)
3964 struct objc_try_context
*c
= *cur_try_context
;
3965 tree stmt
= c
->try_body
;
3967 stmt
= build_stmt (c
->try_locus
, TRY_CATCH_EXPR
, stmt
, c
->catch_list
);
3968 if (c
->finally_body
)
3969 stmt
= build_stmt (c
->try_locus
, TRY_FINALLY_EXPR
, stmt
, c
->finally_body
);
3973 #include "gt-objc-objc-next-runtime-abi-02.h"