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
);
1661 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1662 lookup_object
= save_expr (lookup_object
);
1664 method_params
= tree_cons (NULL_TREE
, lookup_object
,
1665 tree_cons (NULL_TREE
, selector
,
1667 t
= build3 (OBJ_TYPE_REF
, sender_cast
, sender
, lookup_object
,
1668 build_int_cst (TREE_TYPE (lookup_object
), 0));
1669 ret_val
= build_function_call (input_location
, t
, method_params
);
1672 /* receiver != nil ? ret_val : 0 */
1676 if (TREE_CODE (ret_type
) == RECORD_TYPE
1677 || TREE_CODE (ret_type
) == UNION_TYPE
)
1678 /* An empty constructor is zero-filled by the middle end. */
1679 ftree
= objc_build_constructor (ret_type
, NULL
);
1681 ftree
= fold_convert (ret_type
, integer_zero_node
);
1683 ifexp
= build_binary_op (input_location
, NE_EXPR
,
1685 fold_convert (rcv_p
, integer_zero_node
), 1);
1688 ret_val
= build_conditional_expr (input_location
,
1689 ifexp
, ret_val
, ftree
,
1690 tf_warning_or_error
);
1692 ret_val
= build_conditional_expr (input_location
,
1694 ret_val
, NULL_TREE
, input_location
,
1695 ftree
, NULL_TREE
, input_location
);
1696 ret_val
= fold_convert (ret_type
, ret_val
);
1703 build_v2_build_objc_method_call (int super
, tree method_prototype
,
1704 tree lookup_object
, tree selector
,
1705 tree method_params
, location_t loc
,
1706 bool check_for_nil
, bool rx_is_id
)
1708 tree sender
, sender_cast
, method
, t
;
1709 tree rcv_p
= (super
? objc_super_type
: objc_object_type
);
1710 vec
<tree
, va_gc
> *parms
;
1711 unsigned nparm
= (method_params
? list_length (method_params
) : 0);
1713 /* If a prototype for the method to be called exists, then cast
1714 the sender's return type and arguments to match that of the method.
1715 Otherwise, leave sender as is. */
1718 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1719 : objc_object_type
);
1720 tree ftype
= build_function_type_for_method (ret_type
, method_prototype
,
1723 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
1724 ftype
= build_type_attribute_variant (ftype
,
1725 METHOD_TYPE_ATTRIBUTES
1726 (method_prototype
));
1728 sender_cast
= build_pointer_type (ftype
);
1730 lookup_object
= build_c_cast (loc
, rcv_p
, lookup_object
);
1732 if (error_operand_p (lookup_object
))
1733 return error_mark_node
;
1735 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1736 lookup_object
= save_expr (lookup_object
);
1738 /* Param list + 2 slots for object and selector. */
1739 vec_alloc (parms
, nparm
+ 2);
1741 /* If we are returning an item that must be returned in memory, and the
1742 target ABI does this by an invisible pointer provided as the first arg,
1743 we need to adjust the message signature to include this. The second
1744 part of this excludes targets that provide some alternate scheme for
1745 structure returns. */
1746 if (ret_type
&& !VOID_TYPE_P (ret_type
)
1747 && targetm
.calls
.return_in_memory (ret_type
, 0)
1748 && !(targetm
.calls
.struct_value_rtx (0, 0)
1749 && (TREE_CODE (ret_type
) == RECORD_TYPE
1750 || TREE_CODE (ret_type
) == UNION_TYPE
)))
1753 sender
= umsg_id_super2_stret_fixup_decl
;
1755 sender
= rx_is_id
? umsg_id_stret_fixup_decl
1756 : umsg_stret_fixup_decl
;
1761 sender
= umsg_id_super2_fixup_decl
;
1763 sender
= rx_is_id
? umsg_id_fixup_decl
1767 method
= build_fold_addr_expr_loc (loc
, sender
);
1769 /* Pass the object to the method. */
1770 parms
->quick_push (lookup_object
);
1771 /* Pass the selector to the method. */
1772 parms
->quick_push (selector
);
1773 /* Now append the remainder of the parms. */
1775 for (; method_params
; method_params
= TREE_CHAIN (method_params
))
1776 parms
->quick_push (TREE_VALUE (method_params
));
1778 /* Build an obj_type_ref, with the correct cast for the method call. */
1779 t
= build3 (OBJ_TYPE_REF
, sender_cast
, method
,
1780 lookup_object
, build_int_cst (TREE_TYPE (lookup_object
), 0));
1781 tree ret_val
= build_function_call_vec (loc
, vNULL
, t
, parms
, NULL
);
1785 /* receiver != nil ? ret_val : 0 */
1789 if (TREE_CODE (ret_type
) == RECORD_TYPE
1790 || TREE_CODE (ret_type
) == UNION_TYPE
)
1792 /* An empty constructor is zero-filled by the middle end. */
1793 ftree
= objc_build_constructor (ret_type
, NULL
);
1796 ftree
= fold_convert (ret_type
, integer_zero_node
);
1798 ifexp
= build_binary_op (loc
, NE_EXPR
,
1800 fold_convert (rcv_p
, integer_zero_node
), 1);
1803 ret_val
= build_conditional_expr (loc
, ifexp
, ret_val
, ftree
,
1804 tf_warning_or_error
);
1806 ret_val
= build_conditional_expr (loc
, ifexp
, 1,
1807 ret_val
, NULL_TREE
, loc
,
1808 ftree
, NULL_TREE
, loc
);
1809 ret_val
= fold_convert (ret_type
, ret_val
);
1816 next_runtime_abi_02_build_objc_method_call (location_t loc
,
1817 tree method_prototype
,
1824 /* Do we need to check for nil receivers ? */
1825 /* For now, message sent to classes need no nil check. In the
1826 future, class declaration marked as weak_import must be nil
1828 bool check_for_nil
= flag_objc_nilcheck
;
1830 || (VAR_P (receiver
)
1831 && TREE_TYPE (receiver
) == objc_class_type
))
1832 check_for_nil
= false;
1834 if (flag_next_runtime
>= USE_FIXUP_BEFORE
)
1837 = next_runtime_abi_02_build_selector_reference (loc
, sel_name
,
1839 return build_v2_build_objc_method_call (super
, method_prototype
,
1843 objc_is_id (rtype
));
1846 /* else we have to build a pair of the function and selector. */
1847 tree message_func_decl
;
1848 tree ret_type
= method_prototype
1849 ? TREE_VALUE (TREE_TYPE (method_prototype
))
1852 /* See comment for the fixup version above. */
1853 if (ret_type
&& !VOID_TYPE_P (ret_type
)
1854 && targetm
.calls
.return_in_memory (ret_type
, 0)
1855 && !(targetm
.calls
.struct_value_rtx (0, 0)
1856 && (TREE_CODE (ret_type
) == RECORD_TYPE
1857 || TREE_CODE (ret_type
) == UNION_TYPE
)))
1860 message_func_decl
= umsg_id_super2_stret_fixup_decl
;
1862 message_func_decl
= objc_is_id (rtype
)
1863 ? umsg_id_stret_fixup_decl
1864 : umsg_stret_fixup_decl
;
1869 message_func_decl
= umsg_id_super2_fixup_decl
;
1871 message_func_decl
= objc_is_id (rtype
)
1872 ? umsg_id_fixup_decl
1876 tree selector
= build_v2_selector_messenger_reference (sel_name
,
1879 /* selector = &_msg; */
1880 selector
= build_unary_op (loc
, ADDR_EXPR
, selector
, 0);
1882 selector
= build_c_cast (loc
, (super
? objc_v2_super_selector_type
1883 : objc_v2_selector_type
),
1886 /* (*_msg.messenger) (receiver, &_msg, ...); */
1887 return build_v2_objc_method_fixup_call (super
, method_prototype
, receiver
,
1888 selector
, method_params
,
1892 /* NOTE --- Constant String Class Stuff --- */
1895 next_runtime_abi_02_setup_const_string_class_decl (void)
1897 if (!constant_string_global_id
)
1899 /* Hopefully, this should not represent a serious limitation. */
1901 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s", constant_string_class_name
);
1902 constant_string_global_id
= get_identifier (buf
);
1905 string_class_decl
= lookup_name (constant_string_global_id
);
1907 /* In OBJC2 abi, constant string class reference refers to class
1908 name for NSConstantString class. This declaration may not be
1909 available yet (in fact it is not in most cases). So, declare an
1910 extern OBJC_CLASS_$_NSConstantString in its place. */
1911 if (!string_class_decl
)
1913 create_extern_decl (objc_v2_class_template
,
1914 IDENTIFIER_POINTER (constant_string_global_id
));
1916 return (string_class_decl
!= NULL_TREE
);
1920 next_runtime_abi_02_build_const_string_constructor (location_t loc
, tree string
,
1923 tree constructor
, fields
, var
;
1924 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1926 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1927 fields
= TYPE_FIELDS (internal_const_str_type
);
1928 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1929 build_unary_op (loc
, ADDR_EXPR
, string_class_decl
, 0));
1931 fields
= DECL_CHAIN (fields
);
1932 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1933 build_unary_op (loc
, ADDR_EXPR
, string
, 1));
1935 /* ??? check if this should be long. */
1936 fields
= DECL_CHAIN (fields
);
1937 CONSTRUCTOR_APPEND_ELT (v
, fields
, build_int_cst (NULL_TREE
, length
));
1938 constructor
= objc_build_constructor (internal_const_str_type
, v
);
1940 var
= build_decl (input_location
, CONST_DECL
, NULL
, TREE_TYPE (constructor
));
1941 DECL_INITIAL (var
) = constructor
;
1942 TREE_STATIC (var
) = 1;
1943 DECL_CONTEXT (var
) = NULL
;
1944 OBJCMETA (var
, objc_meta
, meta_const_str
);
1948 /* NOTE --- NeXT V2 Metadata templates --- */
1950 /* This routine builds the following type:
1953 const char * const name; // property name
1954 const char * const attributes; // comma-delimited, encoded,
1955 // property attributes
1960 build_v2_property_template (void)
1963 tree decls
, *chain
= NULL
;
1965 prop_record
= objc_start_struct (get_identifier ("_prop_t"));
1966 /* const char * name */
1967 decls
= add_field_decl (string_type_node
, "name", &chain
);
1969 /* const char * attribute */
1970 add_field_decl (string_type_node
, "attribute", &chain
);
1972 objc_finish_struct (prop_record
, decls
);
1978 unsigned long int *offset;
1987 build_v2_ivar_t_template (void)
1989 tree objc_ivar_id
, objc_ivar_record
;
1990 tree decls
, *chain
= NULL
;
1992 objc_ivar_id
= get_identifier ("_ivar_t");
1993 objc_ivar_record
= objc_start_struct (objc_ivar_id
);
1995 /* unsigned long int *offset; */
1996 decls
= add_field_decl (build_pointer_type
1997 (TREE_TYPE (size_zero_node
)), "offset", &chain
);
2000 add_field_decl (string_type_node
, "name", &chain
);
2003 add_field_decl (string_type_node
, "type", &chain
);
2005 /* uint32_t alignment; */
2006 add_field_decl (integer_type_node
, "alignment", &chain
);
2008 /* uint32_t size; */
2009 add_field_decl (integer_type_node
, "size", &chain
);
2011 objc_finish_struct (objc_ivar_record
, decls
);
2012 return objc_ivar_record
;
2016 build_metadata_templates (void)
2019 if (!objc_method_template
)
2020 objc_method_template
= build_method_template ();
2022 if (!objc_v2_property_template
)
2023 objc_v2_property_template
= build_v2_property_template ();
2025 if (!objc_v2_ivar_template
)
2026 objc_v2_ivar_template
= build_v2_ivar_t_template ();
2030 /* NOTE --- Output NeXT V2 Metadata --- */
2032 /* Routine builds name of Interface's main meta-data of type class_t. */
2035 objc_build_internal_classname (tree ident
, bool metaclass
)
2037 static char string
[512];
2038 snprintf (string
, 512, "%s_%s", metaclass
? "OBJC_METACLASS_$"
2040 IDENTIFIER_POINTER (ident
));
2044 /* Build the name for object of type struct class_ro_t */
2047 newabi_append_ro (const char *name
)
2051 static char string
[BUFSIZE
];
2052 dollar
= strchr (name
, '$');
2053 gcc_assert (dollar
);
2056 strncpy (p
, name
, (int)(dollar
- name
));
2057 p
+= (int)(dollar
- name
);
2058 sprintf (p
, "RO_%s", dollar
);
2062 /* Build the struct message_ref_t msg =
2063 {objc_msgSend_fixup_xxx, @selector(func)}
2067 void build_v2_message_ref_translation_table (void)
2072 if (!vec_safe_length (msgrefs
))
2075 FOR_EACH_VEC_ELT (*msgrefs
, count
, ref
)
2077 vec
<constructor_elt
, va_gc
> *initializer
;
2078 tree expr
, constructor
;
2079 tree struct_type
= TREE_TYPE (ref
->refdecl
);
2080 location_t loc
= DECL_SOURCE_LOCATION (ref
->refdecl
);
2083 /* First 'IMP messenger' field... */
2084 expr
= build_unary_op (loc
, ADDR_EXPR
, ref
->func
, 0);
2085 expr
= convert (objc_v2_imp_type
, expr
);
2086 CONSTRUCTOR_APPEND_ELT (initializer
, NULL_TREE
, expr
);
2088 /* ... then 'SEL name' field. */
2089 expr
= build_selector (ref
->selname
);
2090 CONSTRUCTOR_APPEND_ELT (initializer
, NULL_TREE
, expr
);
2091 constructor
= objc_build_constructor (struct_type
, initializer
);
2092 finish_var_decl (ref
->refdecl
, constructor
);
2096 /* Build decl = initializer; for each externally visible class
2100 build_v2_classrefs_table (void)
2103 ident_data_tuple
*ref
;
2105 if (!vec_safe_length (classrefs
))
2108 FOR_EACH_VEC_ELT (*classrefs
, count
, ref
)
2110 tree expr
= ref
->ident
;
2111 tree decl
= ref
->data
;
2112 /* Interface with no implementation and yet one of its messages
2113 has been used. Need to generate a full address-of tree for it
2115 if (TREE_CODE (expr
) == IDENTIFIER_NODE
)
2117 const char *name
= objc_build_internal_classname (expr
, false);
2118 expr
= create_extern_decl (objc_v2_class_template
, name
);
2119 expr
= convert (objc_class_type
, build_fold_addr_expr (expr
));
2121 /* The runtime wants this, even if it appears unused, so we must force the
2123 DECL_PRESERVE_P (decl
) = 1;
2124 finish_var_decl (decl
, expr
);
2128 /* Build decl = initializer; for each externally visible super class
2132 build_v2_super_classrefs_table (bool metaclass
)
2135 ident_data_tuple
*ref
;
2136 vec
<ident_data_tuple
, va_gc
> *list
= metaclass
? metaclass_super_refs
2139 if (!vec_safe_length (list
))
2142 FOR_EACH_VEC_ELT (*list
, count
, ref
)
2144 tree expr
= ref
->ident
;
2145 tree decl
= ref
->data
;
2146 /* Interface with no implementation and yet one of its messages
2147 has been used. Need to generate a full address-of tree for it
2149 if (TREE_CODE (expr
) == IDENTIFIER_NODE
)
2151 const char * name
= objc_build_internal_classname (expr
, metaclass
);
2152 expr
= create_extern_decl (objc_v2_class_template
, name
);
2153 expr
= convert (objc_class_type
, build_fold_addr_expr (expr
));
2155 finish_var_decl (decl
, expr
);
2159 /* Add the global class meta-data declaration to the list which later
2160 on ends up in the __class_list section. */
2162 static GTY(()) vec
<tree
, va_gc
> *class_list
;
2165 objc_v2_add_to_class_list (tree global_class_decl
)
2167 vec_safe_push (class_list
, global_class_decl
);
2170 static GTY(()) vec
<tree
, va_gc
> *nonlazy_class_list
;
2172 /* Add the global class meta-data declaration to the list which later
2173 on ends up in the __nonlazy_class section. */
2176 objc_v2_add_to_nonlazy_class_list (tree global_class_decl
)
2178 vec_safe_push (nonlazy_class_list
, global_class_decl
);
2181 static GTY(()) vec
<tree
, va_gc
> *category_list
;
2183 /* Add the category meta-data declaration to the list which later on
2184 ends up in the __nonlazy_category section. */
2187 objc_v2_add_to_category_list (tree decl
)
2189 vec_safe_push (category_list
, decl
);
2192 static GTY(()) vec
<tree
, va_gc
> *nonlazy_category_list
;
2194 /* Add the category meta-data declaration to the list which later on
2195 ends up in the __category_list section. */
2198 objc_v2_add_to_nonlazy_category_list (tree decl
)
2200 vec_safe_push (nonlazy_category_list
, decl
);
2204 has_load_impl (tree clsmeth
)
2208 tree id
= METHOD_SEL_NAME (clsmeth
);
2209 if (IDENTIFIER_LENGTH (id
) == 4
2210 && startswith (IDENTIFIER_POINTER (id
), "load"))
2212 clsmeth
= DECL_CHAIN (clsmeth
);
2218 /* Build a __{class,category}_list section table containing address of
2219 all @implemented {class,category} meta-data. */
2222 build_v2_address_table (vec
<tree
, va_gc
> *src
, const char *nam
, tree attr
)
2225 tree type
, decl
, expr
;
2226 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2228 if (!vec_safe_length (src
))
2231 FOR_EACH_VEC_ELT (*src
, count
, decl
)
2234 tree purpose
= build_int_cst (NULL_TREE
, count
);
2236 tree purpose
= NULL_TREE
;
2238 expr
= convert (objc_class_type
, build_fold_addr_expr (decl
));
2239 CONSTRUCTOR_APPEND_ELT (initlist
, purpose
, expr
);
2241 gcc_assert (count
> 0);
2242 type
= build_array_type (objc_class_type
,
2243 build_index_type (build_int_cst (NULL_TREE
, count
- 1)));
2244 decl
= start_var_decl (type
, nam
);
2245 /* The runtime wants this, even if it appears unused, so we must
2246 force the output. */
2247 DECL_PRESERVE_P (decl
) = 1;
2248 expr
= objc_build_constructor (type
, initlist
);
2249 OBJCMETA (decl
, objc_meta
, attr
);
2250 finish_var_decl (decl
, expr
);
2253 /* Build decl = initializer; for each protocol referenced in
2254 @protocol(MyProt) expression. Refs as built in the entry section
2258 build_v2_protocol_list_translation_table (void)
2261 prot_list_entry
*ref
;
2266 FOR_EACH_VEC_ELT (*protrefs
, count
, ref
)
2270 gcc_assert (TREE_CODE (ref
->id
) == PROTOCOL_INTERFACE_TYPE
);
2271 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
2272 IDENTIFIER_POINTER (PROTOCOL_NAME (ref
->id
)));
2273 expr
= start_var_decl (objc_v2_protocol_template
, buf
);
2274 expr
= convert (objc_protocol_type
, build_fold_addr_expr (expr
));
2275 finish_var_decl (ref
->refdecl
, expr
);
2277 /* TODO: Maybe we could explicitly delete the vec. now? */
2280 static GTY (()) vec
<prot_list_entry
, va_gc
> *protlist
;
2282 /* Add the local protocol meta-data declaration to the list which
2283 later on ends up in the __protocol_list section. */
2286 objc_add_to_protocol_list (tree protocol_interface_decl
, tree protocol_decl
)
2290 /* Arbitrary init count. */
2291 vec_alloc (protlist
, 32);
2292 e
.id
= protocol_interface_decl
;
2293 e
.refdecl
= protocol_decl
;
2294 vec_safe_push (protlist
, e
);
2297 /* Build the __protocol_list section table containing address of all
2298 generate protocol_t meta-data. */
2301 build_v2_protocol_list_address_table (void)
2304 prot_list_entry
*ref
;
2305 if (!vec_safe_length (protlist
))
2308 FOR_EACH_VEC_ELT (*protlist
, count
, ref
)
2312 gcc_assert (ref
->id
&& TREE_CODE (ref
->id
) == PROTOCOL_INTERFACE_TYPE
);
2313 snprintf (buf
, BUFSIZE
, "_OBJC_LabelProtocol_%s",
2314 IDENTIFIER_POINTER (PROTOCOL_NAME (ref
->id
)));
2315 if (flag_next_runtime
>= USE_FIXUP_BEFORE
)
2317 decl
= create_hidden_decl (objc_protocol_type
, buf
, /*is def=*/true);
2318 DECL_WEAK (decl
) = true;
2321 decl
= create_global_decl (objc_protocol_type
, buf
, /*is def=*/true);
2322 expr
= convert (objc_protocol_type
, build_fold_addr_expr (ref
->refdecl
));
2323 OBJCMETA (decl
, objc_meta
, meta_label_protocollist
);
2324 finish_var_decl (decl
, expr
);
2325 DECL_PRESERVE_P (decl
) = 1;
2328 /* TODO: delete the vec. */
2329 /* TODO: upgrade to the clang/llvm hidden version. */
2332 /* This routine declares a variable to hold meta data for 'struct
2333 protocol_list_t'. */
2336 generate_v2_protocol_list (tree i_or_p
, tree klass_ctxt
)
2338 tree refs_decl
, lproto
, e
, plist
, ptempl_p_t
;
2340 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2343 if (TREE_CODE (i_or_p
) == CLASS_INTERFACE_TYPE
2344 || TREE_CODE (i_or_p
) == CATEGORY_INTERFACE_TYPE
)
2345 plist
= CLASS_PROTOCOL_LIST (i_or_p
);
2346 else if (TREE_CODE (i_or_p
) == PROTOCOL_INTERFACE_TYPE
)
2347 plist
= PROTOCOL_LIST (i_or_p
);
2352 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
2353 if (TREE_CODE (TREE_VALUE (lproto
)) == PROTOCOL_INTERFACE_TYPE
2354 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto
)))
2357 /* Build initializer. */
2359 ptempl_p_t
= build_pointer_type (objc_v2_protocol_template
);
2360 e
= build_int_cst (ptempl_p_t
, size
);
2361 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, e
);
2363 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
2365 tree pval
= TREE_VALUE (lproto
);
2367 if (TREE_CODE (pval
) == PROTOCOL_INTERFACE_TYPE
2368 && PROTOCOL_FORWARD_DECL (pval
))
2370 tree fwref
= PROTOCOL_FORWARD_DECL (pval
);
2371 location_t loc
= DECL_SOURCE_LOCATION (fwref
) ;
2372 e
= build_unary_op (loc
, ADDR_EXPR
, fwref
, 0);
2373 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, e
);
2377 /* static struct protocol_list_t *list[size]; */
2379 switch (TREE_CODE (i_or_p
))
2381 case PROTOCOL_INTERFACE_TYPE
:
2382 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRefs_%s",
2383 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p
)));
2385 case CLASS_INTERFACE_TYPE
:
2386 snprintf (buf
, BUFSIZE
, "_OBJC_ClassProtocols_%s",
2387 IDENTIFIER_POINTER (CLASS_NAME (i_or_p
)));
2389 case CATEGORY_INTERFACE_TYPE
:
2390 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryProtocols_%s_%s",
2391 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)),
2392 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt
)));
2398 refs_decl
= start_var_decl (build_sized_array_type (ptempl_p_t
, size
+1),
2400 /* ObjC2 puts all these in the base section. */
2401 OBJCMETA (refs_decl
, objc_meta
, meta_base
);
2402 DECL_PRESERVE_P (refs_decl
) = 1;
2403 finish_var_decl (refs_decl
,
2404 objc_build_constructor (TREE_TYPE (refs_decl
),initlist
));
2408 /* This routine builds one 'struct method_t' initializer list. Note
2409 that the old ABI is supposed to build 'struct objc_method' which
2410 has 3 fields, but it does not build the initialization expression
2411 for 'method_imp' which for protocols is NULL any way. To be
2412 consistent with declaration of 'struct method_t', in the new ABI we
2413 set the method_t.imp to NULL. */
2416 build_v2_descriptor_table_initializer (tree type
, tree entries
)
2418 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
2421 vec
<constructor_elt
, va_gc
> *eltlist
= NULL
;
2422 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
,
2423 build_selector (METHOD_SEL_NAME (entries
)));
2424 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
,
2425 add_objc_string (METHOD_ENCODING (entries
),
2427 CONSTRUCTOR_APPEND_ELT (eltlist
, NULL_TREE
, null_pointer_node
);
2429 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
2430 objc_build_constructor (type
, eltlist
));
2431 entries
= TREE_CHAIN (entries
);
2435 return objc_build_constructor (build_array_type (type
, 0), initlist
);
2438 /* struct method_list_t
2441 uint32_t method_count;
2442 struct objc_method method_list[method_count];
2446 build_v2_method_list_template (tree list_type
, int size
)
2448 tree method_list_t_record
;
2449 tree array_type
, decls
, *chain
= NULL
;
2451 method_list_t_record
= objc_start_struct (NULL_TREE
);
2453 /* uint32_t const entsize; */
2454 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2456 /* int method_count; */
2457 add_field_decl (integer_type_node
, "method_count", &chain
);
2459 /* struct objc_method method_list[]; */
2460 array_type
= build_sized_array_type (list_type
, size
);
2461 add_field_decl (array_type
, "method_list", &chain
);
2463 objc_finish_struct (method_list_t_record
, decls
);
2464 return method_list_t_record
;
2467 /* Note, as above that we are building to the objc_method_template
2468 which has the *imp field. ABI0/1 build with
2469 objc_method_prototype_template which is missing this field. */
2471 generate_v2_meth_descriptor_table (tree chain
, tree protocol
,
2472 const char *prefix
, tree attr
,
2473 vec
<tree
>& all_meths
)
2475 tree method_list_template
, initlist
, decl
;
2477 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2480 if (!chain
|| !prefix
)
2483 tree method
= chain
;
2487 if (! METHOD_ENCODING (method
))
2488 METHOD_ENCODING (method
) = encode_method_prototype (method
);
2489 all_meths
.safe_push (method
);
2490 method
= TREE_CHAIN (method
);
2495 method_list_template
= build_v2_method_list_template (objc_method_template
,
2497 snprintf (buf
, BUFSIZE
, "%s_%s", prefix
,
2498 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
2500 decl
= start_var_decl (method_list_template
, buf
);
2502 entsize
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template
));
2503 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, entsize
));
2504 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
2506 build_v2_descriptor_table_initializer (objc_method_template
,
2508 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
2509 /* Get into the right section. */
2510 OBJCMETA (decl
, objc_meta
, attr
);
2511 finish_var_decl (decl
, objc_build_constructor (method_list_template
, v
));
2516 generate_v2_meth_type_list (vec
<tree
>& all_meths
, tree protocol
,
2519 if (all_meths
.is_empty () || !prefix
)
2522 unsigned size
= all_meths
.length ();
2523 tree list_type
= build_sized_array_type (string_type_node
, size
);
2525 asprintf (&nam
, "%s_%s", prefix
,
2526 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
2527 tree decl
= start_var_decl (list_type
, nam
);
2529 OBJCMETA (decl
, objc_meta
, meta_base
);
2530 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2532 for (unsigned i
= 0; i
< size
; ++i
)
2533 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2534 add_objc_string (METHOD_ENCODING (all_meths
[i
]),
2536 finish_var_decl (decl
, objc_build_constructor (list_type
, v
));
2540 /* This routine builds the initializer list to initialize the 'struct
2541 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2544 build_v2_property_table_initializer (tree type
, tree context
)
2547 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2548 if (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
)
2549 x
= CLASS_PROPERTY_DECL (context
);
2551 x
= IMPL_PROPERTY_DECL (context
);
2553 for (; x
; x
= TREE_CHAIN (x
))
2555 vec
<constructor_elt
, va_gc
> *elemlist
= NULL
;
2556 /* NOTE! sections where property name/attribute go MUST change
2558 tree attribute
, name_ident
= PROPERTY_NAME (x
);
2560 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
2561 add_objc_string (name_ident
, prop_names_attr
));
2563 attribute
= objc_v2_encode_prop_attr (x
);
2564 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
2565 add_objc_string (attribute
, prop_names_attr
));
2567 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2568 objc_build_constructor (type
, elemlist
));
2571 return objc_build_constructor (build_array_type (type
, 0),inits
);
2574 /* This routine builds the following type:
2577 uint32_t entsize; // sizeof (struct _prop_t)
2578 uint32_t prop_count;
2579 struct _prop_t prop_list [prop_count];
2584 build_v2_property_list_template (tree list_type
, int size
)
2586 tree property_list_t_record
;
2587 tree array_type
, decls
, *chain
= NULL
;
2590 property_list_t_record
= objc_start_struct (NULL_TREE
);
2592 /* uint32_t const entsize; */
2593 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
2595 /* int prop_count; */
2596 add_field_decl (integer_type_node
, "prop_count", &chain
);
2598 /* struct _prop_t prop_list[]; */
2599 array_type
= build_sized_array_type (list_type
, size
);
2600 add_field_decl (array_type
, "prop_list", &chain
);
2602 objc_finish_struct (property_list_t_record
, decls
);
2603 return property_list_t_record
;
2606 /* Top-level routine to generate property tables for each
2610 generate_v2_property_table (tree context
, tree klass_ctxt
)
2612 tree x
, decl
, initlist
, property_list_template
;
2613 bool is_proto
= false;
2614 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2615 int init_val
, size
= 0;
2620 gcc_assert (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
);
2621 x
= CLASS_PROPERTY_DECL (context
);
2625 x
= IMPL_PROPERTY_DECL (klass_ctxt
);
2627 for (; x
; x
= TREE_CHAIN (x
))
2633 property_list_template
=
2634 build_v2_property_list_template (objc_v2_property_template
,
2637 initlist
= build_v2_property_table_initializer (objc_v2_property_template
,
2641 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template
));
2643 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolPropList_%s",
2644 IDENTIFIER_POINTER (PROTOCOL_NAME (context
)));
2646 snprintf (buf
, BUFSIZE
, "_OBJC_ClassPropList_%s",
2647 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)));
2649 decl
= start_var_decl (property_list_template
, buf
);
2651 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2652 build_int_cst (NULL_TREE
, init_val
));
2653 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2654 build_int_cst (NULL_TREE
, size
));
2655 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
2657 OBJCMETA (decl
, objc_meta
, meta_base
);
2658 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), inits
));
2663 build_v2_protocol_initializer (tree type
, tree protocol_name
, tree protocol_list
,
2664 tree inst_methods
, tree class_methods
,
2665 tree opt_ins_meth
, tree opt_cls_meth
,
2666 tree property_list
, tree ext_meth_types
,
2667 tree demangled_name
, tree class_prop_list
)
2671 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
2673 /* TODO: find a better representation of location from the inputs. */
2674 loc
= UNKNOWN_LOCATION
;
2676 /* This is NULL for the new ABI. */
2677 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
2678 convert (objc_object_type
, null_pointer_node
));
2680 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_name
);
2681 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_list
);
2683 ttyp
= objc_method_proto_list_ptr
;
2685 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
2687 expr
= convert (ttyp
, null_pointer_node
);
2688 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2691 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
2693 expr
= convert (ttyp
, null_pointer_node
);
2694 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2697 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, opt_ins_meth
, 0));
2699 expr
= convert (ttyp
, null_pointer_node
);
2700 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2703 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, opt_cls_meth
, 0));
2705 expr
= convert (ttyp
, null_pointer_node
);
2706 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2708 ttyp
= objc_prop_list_ptr
;
2710 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
2712 expr
= convert (ttyp
, null_pointer_node
);
2713 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2715 /* const uint32_t size; = sizeof(struct protocol_t) */
2716 expr
= build_int_cst (integer_type_node
,
2717 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template
)));
2718 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2719 /* const uint32_t flags; = 0 */
2720 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, integer_zero_node
);
2722 ttyp
= build_pointer_type (string_type_node
);
2724 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, ext_meth_types
, 0));
2726 expr
= convert (ttyp
, null_pointer_node
);
2727 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2729 ttyp
= string_type_node
;
2731 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, demangled_name
, 0));
2733 expr
= convert (ttyp
, null_pointer_node
);
2734 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2736 ttyp
= objc_prop_list_ptr
;
2737 if (class_prop_list
)
2738 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_prop_list
, 0));
2740 expr
= convert (ttyp
, null_pointer_node
);
2741 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
2743 return objc_build_constructor (type
, inits
);
2746 /* Main routine to build all meta data for all protocols used in a
2747 translation unit. */
2750 generate_v2_protocols (void)
2755 if (!protocol_chain
)
2758 /* If a protocol was directly referenced, pull in indirect
2760 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
2761 if (PROTOCOL_FORWARD_DECL (p
) && PROTOCOL_LIST (p
))
2762 generate_protocol_references (PROTOCOL_LIST (p
));
2764 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
2767 tree inst_meth
, class_meth
, opt_inst_meth
, opt_class_meth
, props
;
2768 tree decl
, initlist
, protocol_name_expr
, refs_decl
, refs_expr
;
2770 /* If protocol wasn't referenced, don't generate any code. */
2771 decl
= PROTOCOL_FORWARD_DECL (p
);
2776 loc
= DECL_SOURCE_LOCATION (decl
);
2779 vec
<tree
> all_meths
= vNULL
;
2781 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p
), p
,
2782 "_OBJC_ProtocolInstanceMethods",
2783 meta_proto_nst_meth
, all_meths
);
2786 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p
), p
,
2787 "_OBJC_ProtocolClassMethods",
2788 meta_proto_cls_meth
, all_meths
);
2791 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p
), p
,
2792 "_OBJC_ProtocolOptInstMethods",
2793 meta_proto_nst_meth
, all_meths
);
2796 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p
), p
,
2797 "_OBJC_ProtocolOptClassMethods",
2798 meta_proto_cls_meth
, all_meths
);
2800 if (PROTOCOL_LIST (p
))
2801 refs_decl
= generate_v2_protocol_list (p
, NULL_TREE
);
2805 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2806 protocol_name_expr
= add_objc_string (PROTOCOL_NAME (p
), class_names
);
2809 refs_expr
= convert (build_pointer_type (objc_v2_protocol_template
),
2810 build_unary_op (loc
, ADDR_EXPR
, refs_decl
, 0));
2812 refs_expr
= build_int_cst (NULL_TREE
, 0);
2814 props
= generate_v2_property_table (p
, NULL_TREE
);
2817 = generate_v2_meth_type_list (all_meths
, p
,
2818 "_OBJC_ProtocolMethodTypes");
2819 tree demangled_name
= NULL_TREE
;
2820 tree class_prop_list
= NULL_TREE
;
2822 initlist
= build_v2_protocol_initializer (TREE_TYPE (decl
),
2823 protocol_name_expr
, refs_expr
,
2824 inst_meth
, class_meth
,
2825 opt_inst_meth
, opt_class_meth
,
2826 props
, ext_meth_types
,
2827 demangled_name
,class_prop_list
);
2828 finish_var_decl (decl
, initlist
);
2829 objc_add_to_protocol_list (p
, decl
);
2830 all_meths
.truncate (0);
2835 /* Make sure we get the Protocol class linked in - reference
2837 p
= objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME
));
2838 /* ... but since we don't specifically use the reference... we
2839 need to force it. */
2840 DECL_PRESERVE_P (p
) = 1;
2845 generate_v2_dispatch_table (tree chain
, const char *name
, tree attr
)
2847 tree decl
, method_list_template
, initlist
;
2848 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2851 if (!chain
|| !name
|| !(size
= list_length (chain
)))
2854 method_list_template
2855 = build_v2_method_list_template (objc_method_template
, size
);
2857 = build_dispatch_table_initializer (objc_method_template
, chain
);
2859 decl
= start_var_decl (method_list_template
, name
);
2861 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template
));
2862 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2863 build_int_cst (integer_type_node
, init_val
));
2864 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2865 build_int_cst (integer_type_node
, size
));
2866 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
2868 OBJCMETA (decl
, objc_meta
, attr
);
2869 finish_var_decl (decl
,
2870 objc_build_constructor (TREE_TYPE (decl
), v
));
2874 /* Init a category. */
2876 build_v2_category_initializer (tree type
, tree cat_name
, tree class_name
,
2877 tree inst_methods
, tree class_methods
,
2878 tree protocol_list
, tree property_list
,
2882 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2884 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, cat_name
);
2885 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, class_name
);
2887 ltyp
= objc_method_list_ptr
;
2889 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
2891 expr
= convert (ltyp
, null_pointer_node
);
2892 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2895 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
2897 expr
= convert (ltyp
, null_pointer_node
);
2898 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2900 /* protocol_list = */
2901 ltyp
= build_pointer_type (objc_v2_protocol_template
);
2903 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
2905 expr
= convert (ltyp
, null_pointer_node
);
2906 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2908 ltyp
= objc_prop_list_ptr
;
2910 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
2912 expr
= convert (ltyp
, null_pointer_node
);
2913 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2915 return objc_build_constructor (type
, v
);
2918 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2921 generate_v2_category (struct imp_entry
*impent
)
2923 tree initlist
, cat_name_expr
, class_name_expr
;
2924 tree protocol_decl
, category
, props
, t
;
2925 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
2926 tree cat
= impent
->imp_context
;
2927 tree cat_decl
= impent
->class_decl
;
2931 loc
= DECL_SOURCE_LOCATION (cat_decl
);
2933 /* ??? not sure this is really necessary, the following references should
2934 force appropriate linkage linkage...
2935 -- but ... ensure a reference to the class... */
2936 t
= objc_v2_get_class_reference (CLASS_NAME (cat
));
2937 /* ... which we ignore so force it out.. */
2938 DECL_PRESERVE_P (t
) = 1;
2940 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat
)));
2941 class_name_expr
= create_extern_decl (objc_v2_class_template
, buf
);
2942 class_name_expr
= build_fold_addr_expr (class_name_expr
);
2944 cat_name_expr
= add_objc_string (CLASS_SUPER_NAME (cat
), class_names
);
2945 category
= lookup_category (impent
->imp_template
, CLASS_SUPER_NAME (cat
));
2947 if (category
&& CLASS_PROTOCOL_LIST (category
))
2949 generate_protocol_references (CLASS_PROTOCOL_LIST (category
));
2950 protocol_decl
= generate_v2_protocol_list (category
, cat
);
2953 protocol_decl
= NULL_TREE
;
2955 /* decl = update_var_decl(impent->class_decl); */
2957 props
= generate_v2_property_table (NULL_TREE
, cat
);
2959 if (CLASS_NST_METHODS (cat
))
2961 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryInstanceMethods_%s_%s",
2962 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
2963 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
2964 inst_methods
= generate_v2_dispatch_table (CLASS_NST_METHODS (cat
), buf
,
2968 if (CLASS_CLS_METHODS (cat
))
2970 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryClassMethods_%s_%s",
2971 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
2972 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
2973 class_methods
= generate_v2_dispatch_table (CLASS_CLS_METHODS (cat
), buf
,
2977 initlist
= build_v2_category_initializer (TREE_TYPE (cat_decl
),
2978 cat_name_expr
, class_name_expr
,
2979 inst_methods
, class_methods
,
2980 protocol_decl
, props
, loc
);
2982 finish_var_decl (cat_decl
, initlist
);
2983 impent
->class_decl
= cat_decl
;
2985 /* Add to list of pointers in __category_list section. */
2986 objc_v2_add_to_category_list (cat_decl
);
2987 if (has_load_impl (CLASS_CLS_METHODS (impent
->imp_context
)))
2988 objc_v2_add_to_nonlazy_category_list (cat_decl
);
2991 /* This routine declares a variable to hold the offset for ivar
2992 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
2994 struct GTY(()) ivarref_entry
3000 static GTY (()) vec
<ivarref_entry
, va_gc
> *ivar_offset_refs
;
3003 ivar_offset_ref (tree class_name
, tree field_decl
)
3005 tree decl
, field_decl_id
;
3010 create_ivar_offset_name (buf
, class_name
, field_decl
);
3011 field_decl_id
= get_identifier (buf
);
3013 if (ivar_offset_refs
)
3017 FOR_EACH_VEC_ELT (*ivar_offset_refs
, count
, ref
)
3018 if (DECL_NAME (ref
->decl
) == field_decl_id
)
3022 /* Somewhat arbitrary initial provision. */
3023 vec_alloc (ivar_offset_refs
, 32);
3025 /* We come here if we don't find a match or at the start. */
3026 global_var
= (TREE_PUBLIC (field_decl
) || TREE_PROTECTED (field_decl
));
3028 decl
= create_global_decl (TREE_TYPE (size_zero_node
), buf
);
3030 decl
= create_hidden_decl (TREE_TYPE (size_zero_node
), buf
);
3032 /* Identify so that we can indirect these where the ABI requires. */
3033 OBJCMETA (decl
, objc_meta
, meta_ivar_ref
);
3036 e
.offset
= byte_position (field_decl
);
3037 vec_safe_push (ivar_offset_refs
, e
);
3041 /* This routine builds initializer-list needed to initialize 'struct
3042 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
3043 'struct ivar_t' and FIELD_DECL is list of ivars for the target
3047 build_v2_ivar_list_initializer (tree class_name
, tree type
, tree field_decl
)
3049 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
3053 vec
<constructor_elt
, va_gc
> *ivar
= NULL
;
3057 /* Unnamed bitfields are ignored. */
3058 if (!DECL_NAME (field_decl
))
3060 field_decl
= DECL_CHAIN (field_decl
);
3065 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3066 build_unary_op (input_location
,
3068 ivar_offset_ref (class_name
,
3072 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3073 add_objc_string (DECL_NAME (field_decl
),
3077 id
= add_objc_string (encode_field_decl (field_decl
),
3079 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
, id
);
3081 /* Set alignment. */
3082 val
= DECL_ALIGN_UNIT (field_decl
);
3083 val
= exact_log2 (val
);
3084 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3085 build_int_cst (integer_type_node
, val
));
3088 val
= TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl
));
3089 CONSTRUCTOR_APPEND_ELT (ivar
, NULL_TREE
,
3090 build_int_cst (integer_type_node
, val
));
3092 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3093 objc_build_constructor (type
, ivar
));
3096 field_decl
= DECL_CHAIN (field_decl
);
3097 while (field_decl
&& TREE_CODE (field_decl
) != FIELD_DECL
);
3101 return objc_build_constructor (build_array_type (type
, 0), inits
);
3109 struct iver_t list[count];
3114 build_v2_ivar_list_t_template (tree list_type
, int size
)
3116 tree objc_ivar_list_record
;
3117 tree decls
, *chain
= NULL
;
3120 objc_ivar_list_record
= objc_start_struct (NULL_TREE
);
3122 /* uint32 entsize; */
3123 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
3126 add_field_decl (integer_type_node
, "count", &chain
);
3128 /* struct objc_ivar ivar_list[]; */
3129 add_field_decl (build_sized_array_type (list_type
, size
),
3132 objc_finish_struct (objc_ivar_list_record
, decls
);
3133 return objc_ivar_list_record
;
3136 /* This routine declares a static variable of type 'struct
3137 ivar_list_t' and initializes it. chain is the source of the data,
3138 name is the name for the var. attr is the meta-data section tag
3139 attribute. templ is the implementation template for the class. */
3142 generate_v2_ivars_list (tree chain
, const char *name
, tree attr
, tree templ
)
3144 tree decl
, initlist
, ivar_list_template
;
3145 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
3146 int size
, ivar_t_size
;
3148 if (!chain
|| !name
|| !(size
= ivar_list_length (chain
)))
3151 generating_instance_variables
= 1;
3152 ivar_list_template
= build_v2_ivar_list_t_template (objc_v2_ivar_template
,
3155 initlist
= build_v2_ivar_list_initializer (CLASS_NAME (templ
),
3156 objc_v2_ivar_template
, chain
);
3157 ivar_t_size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template
));
3159 decl
= start_var_decl (ivar_list_template
, name
);
3160 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3161 build_int_cst (integer_type_node
, ivar_t_size
));
3162 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
3163 build_int_cst (integer_type_node
, size
));
3164 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
3165 OBJCMETA (decl
, objc_meta
, attr
);
3166 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), inits
));
3167 generating_instance_variables
= 0;
3171 /* Routine to build initializer list to initialize objects of type
3175 build_v2_class_t_initializer (tree type
, tree isa
, tree superclass
,
3176 tree ro
, tree cache
, tree vtable
)
3178 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3181 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, isa
);
3184 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, superclass
);
3188 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, cache
);
3190 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, null_pointer_node
);
3194 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, vtable
);
3196 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, null_pointer_node
);
3199 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, ro
);
3201 return objc_build_constructor (type
, initlist
);
3204 /* Routine to build object of struct class_ro_t { ... }; */
3207 build_v2_class_ro_t_initializer (tree type
, tree name
,
3208 unsigned int flags
, unsigned int instanceStart
,
3209 unsigned int instanceSize
,
3211 tree baseMethods
, tree baseProtocols
,
3212 tree ivars
, tree property_list
)
3214 tree expr
, unsigned_char_star
, ltyp
;
3216 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3218 /* TODO: fish out the real location from somewhere. */
3219 loc
= UNKNOWN_LOCATION
;
3222 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3223 build_int_cst (integer_type_node
, flags
));
3226 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3227 build_int_cst (integer_type_node
, instanceStart
));
3230 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3231 build_int_cst (integer_type_node
, instanceSize
));
3233 /* This ABI is currently only used on m64 NeXT. We always
3234 explicitly declare the alignment padding. */
3235 /* reserved, pads alignment. */
3236 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3237 build_int_cst (integer_type_node
, 0));
3240 unsigned_char_star
= build_pointer_type (unsigned_char_type_node
);
3244 expr
= convert (unsigned_char_star
, null_pointer_node
);
3245 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3248 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, default_conversion (name
));
3251 ltyp
= objc_method_list_ptr
;
3253 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, baseMethods
, 0));
3255 expr
= convert (ltyp
, null_pointer_node
);
3256 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3259 ltyp
= build_pointer_type (xref_tag (RECORD_TYPE
,
3260 get_identifier (UTAG_V2_PROTOCOL_LIST
)));
3262 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, baseProtocols
, 0));
3264 expr
= convert (ltyp
, null_pointer_node
);
3265 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3268 ltyp
= objc_v2_ivar_list_ptr
;
3270 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, ivars
, 0));
3272 expr
= convert (ltyp
, null_pointer_node
);
3273 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3275 /* TODO: We don't yet have the weak/strong stuff... */
3276 /* weakIvarLayout */
3277 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
,
3278 convert (unsigned_char_star
, null_pointer_node
));
3281 ltyp
= objc_prop_list_ptr
;
3283 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
3285 expr
= convert (ltyp
, null_pointer_node
);
3286 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, expr
);
3287 return objc_build_constructor (type
, initlist
);
3290 static GTY (()) vec
<ident_data_tuple
, va_gc
> *ehtype_list
;
3292 /* Record a name as needing a catcher. */
3294 objc_v2_add_to_ehtype_list (tree name
)
3300 ident_data_tuple
*ref
;
3302 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3303 if (ref
->ident
== name
)
3304 return; /* Already entered. */
3307 /* Arbitrary initial count. */
3308 vec_alloc (ehtype_list
, 8);
3310 /* Not found, or new list. */
3313 vec_safe_push (ehtype_list
, e
);
3317 generate_v2_class_structs (struct imp_entry
*impent
)
3319 tree decl
, name_expr
, initlist
, protocol_decl
, metaclass_decl
, class_decl
;
3320 tree field
, firstIvar
, chain
;
3321 tree class_superclass_expr
, metaclass_superclass_expr
, props
;
3322 /* TODO: figure out how to compute this. */
3323 tree ivarLayout
= NULL_TREE
;
3324 tree my_super_id
= NULL_TREE
, root_expr
= NULL_TREE
;
3325 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
3326 tree inst_ivars
= NULL_TREE
, class_ivars
= NULL_TREE
;
3329 unsigned int instanceStart
, instanceSize
;
3330 unsigned int flags
= 0x01; /* RO_META */
3331 int cls_flags
= impent
->has_cxx_cdtors
? OBJC2_CLS_HAS_CXX_STRUCTORS
3334 class_decl
= impent
->class_decl
;
3335 metaclass_decl
= impent
->meta_decl
;
3336 loc
= DECL_SOURCE_LOCATION (class_decl
);
3338 DECL_EXTERNAL (class_decl
) = DECL_EXTERNAL (metaclass_decl
) = 0;
3339 TREE_PUBLIC (class_decl
) = TREE_PUBLIC (metaclass_decl
) = 1;
3341 gcc_assert (!CP_DECL_CONTEXT (class_decl
) || CP_DECL_CONTEXT (class_decl
) == global_namespace
);
3342 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl
) || CP_DECL_CONTEXT (metaclass_decl
) == global_namespace
);
3345 /* Generation of data for meta class. */
3346 my_super_id
= CLASS_SUPER_NAME (impent
->imp_template
);
3349 /* Compute reference to root's name. For a meta class, "isa" is
3350 a reference to the root class name. */
3351 tree my_root_id
= my_super_id
;
3352 tree my_root_int
, interface
;
3355 my_root_int
= lookup_interface (my_root_id
);
3357 if (my_root_int
&& CLASS_SUPER_NAME (my_root_int
))
3358 my_root_id
= CLASS_SUPER_NAME (my_root_int
);
3364 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3365 create extern if not already declared. */
3366 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
3367 IDENTIFIER_POINTER (CLASS_NAME (my_root_int
)));
3368 root_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3369 root_expr
= build_fold_addr_expr (root_expr
);
3371 /* Install class `isa' and `super' pointers at runtime. */
3372 interface
= lookup_interface (my_super_id
);
3373 gcc_assert (interface
);
3374 /* Similarly, for OBJC_CLASS_$_<interface>... */
3375 snprintf (buf
, BUFSIZE
, "OBJC_CLASS_$_%s",
3376 IDENTIFIER_POINTER (CLASS_NAME (interface
)));
3377 class_superclass_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3378 class_superclass_expr
= build_fold_addr_expr (class_superclass_expr
);
3379 /* ... and for OBJC_METACLASS_$_<interface>. */
3380 snprintf (buf
, BUFSIZE
, "OBJC_METACLASS_$_%s",
3381 IDENTIFIER_POINTER (CLASS_NAME (interface
)));
3382 metaclass_superclass_expr
= create_extern_decl (objc_v2_class_template
, buf
);
3383 metaclass_superclass_expr
= build_fold_addr_expr (metaclass_superclass_expr
);
3388 root_expr
= build_unary_op (loc
, ADDR_EXPR
, metaclass_decl
, 0);
3389 metaclass_superclass_expr
= build_unary_op (loc
, ADDR_EXPR
, class_decl
, 0);
3390 class_superclass_expr
= build_int_cst (NULL_TREE
, 0);
3391 flags
|= 0x02; /* RO_ROOT: it is also a root meta class. */
3394 if (CLASS_PROTOCOL_LIST (impent
->imp_template
))
3396 generate_protocol_references (CLASS_PROTOCOL_LIST (impent
->imp_template
));
3397 protocol_decl
= generate_v2_protocol_list (impent
->imp_template
,
3398 impent
->imp_context
);
3403 name_expr
= add_objc_string (CLASS_NAME (impent
->imp_template
),
3406 if (CLASS_CLS_METHODS (impent
->imp_context
))
3408 snprintf (buf
, BUFSIZE
, "_OBJC_ClassMethods_%s",
3409 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3411 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent
->imp_context
),
3412 buf
, meta_clac_meth
);
3415 instanceStart
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template
));
3417 /* Currently there are no class ivars and generation of class
3418 variables for the root of the inheritance has been removed. It
3419 causes multiple defines if there are two root classes in the
3420 link, because each will define its own identically-named offset
3423 class_ivars
= NULL_TREE
;
3424 /* TODO: Add total size of class variables when implemented. */
3425 instanceSize
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template
));
3427 /* So now build the META CLASS structs. */
3428 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3430 decl
= start_var_decl (objc_v2_class_ro_template
,
3431 newabi_append_ro (IDENTIFIER_POINTER
3432 (DECL_NAME (metaclass_decl
))));
3434 /* TODO: ivarLayout needs t be built. */
3436 build_v2_class_ro_t_initializer (TREE_TYPE (decl
), name_expr
,
3437 (flags
| cls_flags
), instanceStart
,
3438 instanceSize
, ivarLayout
,
3439 class_methods
, protocol_decl
,
3440 class_ivars
, NULL_TREE
);
3441 /* The ROs sit in the default const section. */
3442 OBJCMETA (decl
, objc_meta
, meta_base
);
3443 finish_var_decl (decl
, initlist
);
3445 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3447 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl
),
3449 metaclass_superclass_expr
,
3450 build_fold_addr_expr (decl
),
3451 build_fold_addr_expr (UOBJC_V2_CACHE_decl
),
3452 build_fold_addr_expr (UOBJC_V2_VTABLE_decl
));
3453 /* The class section attributes are set when they are created. */
3454 finish_var_decl (metaclass_decl
, initlist
);
3455 impent
->meta_decl
= metaclass_decl
;
3457 /* So now build the CLASS structs. */
3459 flags
= 0x0; /* ... */
3461 flags
|= 0x02; /* RO_ROOT: this is a root class */
3463 if (DECL_VISIBILITY (class_decl
) == VISIBILITY_HIDDEN
)
3464 flags
|= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3466 if (objc2_objc_exception_attr (impent
->imp_template
))
3467 flags
|= 0x20; /* RO_EXCEPTION */
3469 if (CLASS_NST_METHODS (impent
->imp_context
))
3471 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceMethods_%s",
3472 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3474 generate_v2_dispatch_table (CLASS_NST_METHODS (impent
->imp_context
),
3475 buf
, meta_clai_meth
);
3478 /* Sort out the ivars before we try to compute the class sizes. */
3479 if ((chain
= CLASS_IVARS (impent
->imp_template
)))
3481 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceIvars_%s",
3482 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
3483 inst_ivars
= generate_v2_ivars_list (chain
, buf
, meta_clai_vars
,
3484 impent
->imp_template
);
3487 /* Compute instanceStart. */
3488 gcc_assert (CLASS_STATIC_TEMPLATE (impent
->imp_template
));
3489 field
= TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent
->imp_template
));
3490 if (my_super_id
&& field
&& TREE_CHAIN (field
))
3491 field
= TREE_CHAIN (field
);
3495 while (firstIvar
&& TREE_CODE (firstIvar
) != FIELD_DECL
)
3496 firstIvar
= TREE_CHAIN (firstIvar
);
3498 gcc_assert (inst_ivars
? (firstIvar
!= NULL_TREE
): true);
3500 /* Compute instanceSize. */
3501 while (field
&& TREE_CHAIN (field
)
3502 && TREE_CODE (TREE_CHAIN (field
)) == FIELD_DECL
)
3503 field
= TREE_CHAIN (field
);
3505 if (field
&& TREE_CODE (field
) == FIELD_DECL
)
3506 instanceSize
= int_byte_position (field
) * BITS_PER_UNIT
3507 + tree_to_shwi (DECL_SIZE (field
));
3510 instanceSize
/= BITS_PER_UNIT
;
3512 props
= generate_v2_property_table (NULL_TREE
, impent
->imp_context
);
3514 /* If the class has no ivars, instanceStart should be set to the
3515 superclass's instanceSize. */
3517 (inst_ivars
!= NULL_TREE
) ? (unsigned) int_byte_position (firstIvar
)
3520 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3521 decl
= start_var_decl (objc_v2_class_ro_template
,
3522 newabi_append_ro (IDENTIFIER_POINTER
3523 (DECL_NAME (class_decl
))));
3526 build_v2_class_ro_t_initializer (TREE_TYPE (decl
), name_expr
,
3527 (flags
| cls_flags
), instanceStart
,
3528 instanceSize
, ivarLayout
,
3529 inst_methods
, protocol_decl
,
3531 /* The ROs sit in the default const section. */
3532 OBJCMETA (decl
, objc_meta
, meta_base
);
3533 finish_var_decl (decl
, initlist
);
3535 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3536 initlist
= build_v2_class_t_initializer (TREE_TYPE (class_decl
),
3537 build_fold_addr_expr (metaclass_decl
),
3538 class_superclass_expr
,
3539 build_fold_addr_expr (decl
),
3540 build_fold_addr_expr (UOBJC_V2_CACHE_decl
),
3541 build_fold_addr_expr (UOBJC_V2_VTABLE_decl
));
3543 /* The class section attributes are set when they are created. */
3544 finish_var_decl (class_decl
, initlist
);
3545 impent
->class_decl
= class_decl
;
3547 objc_v2_add_to_class_list (class_decl
);
3548 if (has_load_impl (CLASS_CLS_METHODS (impent
->imp_context
)))
3549 objc_v2_add_to_nonlazy_class_list (class_decl
);
3551 if (flags
& 0x20) /* RO_EXCEPTION */
3552 objc_v2_add_to_ehtype_list (CLASS_NAME (impent
->imp_template
));
3555 /* This routine outputs the (ivar_reference_offset, offset)
3559 build_v2_ivar_offset_ref_table (void)
3564 if (!vec_safe_length (ivar_offset_refs
))
3567 FOR_EACH_VEC_ELT (*ivar_offset_refs
, count
, ref
)
3568 finish_var_decl (ref
->decl
, ref
->offset
);
3572 objc_generate_v2_next_metadata (void)
3574 struct imp_entry
*impent
;
3576 /* FIXME: Make sure that we generate no metadata if there is nothing
3579 gcc_assert (!objc_static_instances
); /* Not for NeXT */
3581 build_metadata_templates ();
3583 for (impent
= imp_list
; impent
; impent
= impent
->next
)
3585 /* If -gen-decls is present, Dump the @interface of each class.
3586 TODO: Dump the classes in the order they were found, rather
3587 than in reverse order as we are doing now. */
3588 if (flag_gen_declaration
)
3589 dump_interface (gen_declaration_file
, impent
->imp_context
);
3591 /* all of the following reference the string pool... */
3592 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
3593 generate_v2_class_structs (impent
);
3595 generate_v2_category (impent
);
3598 build_next_selector_translation_table ();
3599 build_v2_message_ref_translation_table ();
3601 /* This will add "Protocol" to the class refs. */
3602 generate_v2_protocols ();
3604 build_v2_classrefs_table ();
3605 build_v2_super_classrefs_table (/*metaclass= */false);
3606 build_v2_super_classrefs_table (/*metaclass= */true);
3608 build_v2_ivar_offset_ref_table ();
3610 build_v2_protocol_list_translation_table ();
3611 build_v2_protocol_list_address_table ();
3613 build_v2_address_table (class_list
, "_OBJC_ClassList$",
3614 meta_label_classlist
);
3615 build_v2_address_table (category_list
, "_OBJC_CategoryList$",
3616 meta_label_categorylist
);
3617 build_v2_address_table (nonlazy_class_list
, "_OBJC_NonLazyClassList$",
3618 meta_label_nonlazy_classlist
);
3619 build_v2_address_table (nonlazy_category_list
, "_OBJC_NonLazyCategoryList$",
3620 meta_label_nonlazy_categorylist
);
3622 /* Generate catch objects for eh, if any are needed. */
3623 build_v2_eh_catch_objects ();
3625 /* Emit the string table last. */
3626 generate_strings ();
3629 /* NOTE --- Output NeXT V2 Exceptions --- */
3631 static GTY(()) tree objc_v2_ehtype_template
;
3632 static GTY(()) tree next_v2_ehvtable_decl
;
3633 static GTY(()) tree next_v2_EHTYPE_id_decl
;
3636 build_v2_ehtype_template (void)
3638 tree decls
, *chain
= NULL
;
3639 objc_v2_ehtype_template
= objc_start_struct (get_identifier (UTAG_V2_EH_TYPE
));
3641 /* void *_objc_ehtype_vtable; */
3642 decls
= add_field_decl (ptr_type_node
, "_objc_ehtype_vtable_ptr", &chain
);
3644 /* const char *className; */
3645 add_field_decl (string_type_node
, "className", &chain
);
3647 /* struct class_t *const cls; */
3648 add_field_decl (build_pointer_type (objc_v2_class_template
), "cls", &chain
);
3650 objc_finish_struct (objc_v2_ehtype_template
, decls
);
3653 /* Template for the Objective-C family typeinfo type for ABI=2. This
3654 starts off the same as the gxx/cxx eh typeinfo.
3656 struct _objc_ehtype_t
3658 void *_objc_ehtype_vtable_ptr; - as per c++
3659 const char *className; - as per c++
3660 struct class_t *const cls;
3664 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3668 objc2_build_ehtype_initializer (tree name
, tree cls
)
3670 vec
<constructor_elt
, va_gc
> *initlist
= NULL
;
3673 /* This is done the same way as c++, missing the two first entries
3674 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3675 runtime source about this so, perhaps, this will change at some
3677 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3678 if (!next_v2_ehvtable_decl
)
3680 next_v2_ehvtable_decl
=
3681 start_var_decl (ptr_type_node
, TAG_NEXT_EHVTABLE_NAME
);
3682 TREE_STATIC (next_v2_ehvtable_decl
) = 0;
3683 DECL_EXTERNAL (next_v2_ehvtable_decl
) = 1;
3684 TREE_PUBLIC (next_v2_ehvtable_decl
) = 1;
3686 addr
= build_fold_addr_expr_with_type (next_v2_ehvtable_decl
, ptr_type_node
);
3687 offs
= size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node
)));
3688 addr
= fold_build_pointer_plus (addr
, offs
);
3690 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, addr
);
3693 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, name
);
3696 CONSTRUCTOR_APPEND_ELT (initlist
, NULL_TREE
, cls
);
3698 return objc_build_constructor (objc_v2_ehtype_template
, initlist
);
3702 build_ehtype (tree name
, const char *eh_name
, bool weak
)
3704 tree name_expr
, class_name_expr
, ehtype_decl
, inits
;
3706 name_expr
= add_objc_string (name
, class_names
);
3707 /* Extern ref. for the class. ??? Maybe we can look this up
3710 create_extern_decl (objc_v2_class_template
,
3711 objc_build_internal_classname (name
, false));
3712 class_name_expr
= build_fold_addr_expr (class_name_expr
);
3713 ehtype_decl
= create_global_decl (objc_v2_ehtype_template
, eh_name
);
3715 DECL_WEAK (ehtype_decl
) = 1;
3716 inits
= objc2_build_ehtype_initializer (name_expr
, class_name_expr
);
3717 OBJCMETA (ehtype_decl
, objc_meta
, meta_ehtype
);
3718 finish_var_decl (ehtype_decl
, inits
);
3722 /* This routine returns TRUE if CLS or any of its super classes has
3723 __attribute__ ((objc_exception)). */
3726 objc2_objc_exception_attr (tree cls
)
3730 if (CLASS_HAS_EXCEPTION_ATTR (cls
))
3732 cls
= lookup_interface (CLASS_SUPER_NAME (cls
));
3739 is_implemented (tree name
)
3741 struct imp_entry
*t
;
3742 for (t
= imp_list
; t
; t
= t
->next
)
3743 if (TREE_CODE (t
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
3744 && CLASS_NAME (t
->imp_template
) == name
)
3750 /* We will build catch objects:
3751 for any type implemented here.
3752 for any type used in a catch that has no exception attribute. */
3753 static void build_v2_eh_catch_objects (void)
3756 ident_data_tuple
*ref
;
3758 if (!vec_safe_length (ehtype_list
))
3761 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3764 bool impl
= is_implemented (ref
->ident
);
3765 bool excpt
= objc2_objc_exception_attr (lookup_interface (ref
->ident
));
3766 snprintf (buf
, BUFSIZE
, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref
->ident
));
3768 /* The User says this class has a catcher already. */
3769 ref
->data
= create_extern_decl (objc_v2_ehtype_template
, buf
);
3771 /* Create a catcher, weak if it wasn't marked. */
3772 ref
->data
= build_ehtype (ref
->ident
, buf
, !excpt
);
3777 lookup_ehtype_ref (tree id
)
3780 ident_data_tuple
*ref
;
3782 if (!vec_safe_length (ehtype_list
))
3785 FOR_EACH_VEC_ELT (*ehtype_list
, count
, ref
)
3786 if (ref
->ident
== id
)
3791 /* This hook, called via lang_eh_runtime_type, generates a runtime
3792 object which is either the address of the 'OBJC_EHTYPE_$_class'
3793 object or address of external OBJC_EHTYPE_id object. */
3795 next_runtime_02_eh_type (tree type
)
3799 if (type
== error_mark_node
3800 /*|| errorcount || sorrycount*/)
3803 if (POINTER_TYPE_P (type
) && objc_is_object_id (TREE_TYPE (type
)))
3805 if (!next_v2_EHTYPE_id_decl
)
3807 /* This is provided by the Apple/NeXT libobjc.dylib so we
3808 need only to reference it. */
3809 next_v2_EHTYPE_id_decl
=
3810 start_var_decl (objc_v2_ehtype_template
, "OBJC_EHTYPE_id");
3811 DECL_EXTERNAL (next_v2_EHTYPE_id_decl
) = 1;
3812 TREE_PUBLIC (next_v2_EHTYPE_id_decl
) = 1;
3813 TREE_STATIC (next_v2_EHTYPE_id_decl
) = 0;
3815 return build_fold_addr_expr (next_v2_EHTYPE_id_decl
);
3818 if (!POINTER_TYPE_P (type
) || !TYPED_OBJECT (TREE_TYPE (type
)))
3821 /* This routine is also called for c++'s catch clause; in which
3822 case, we use c++'s typeinfo decl. */
3823 return build_eh_type_type (type
);
3825 error ("non-objective-c type %qT cannot be caught", type
);
3830 t
= OBJC_TYPE_NAME (TREE_TYPE (type
));
3832 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3833 t
= lookup_ehtype_ref (t
);
3837 return build_fold_addr_expr (t
);
3840 return error_mark_node
;
3843 static GTY(()) tree objc_eh_personality_decl
;
3846 objc_eh_personality (void)
3848 if (!objc_eh_personality_decl
)
3849 objc_eh_personality_decl
= build_personality_function ("objc");
3850 return objc_eh_personality_decl
;
3853 /* NOTE --- interfaces --- */
3856 build_throw_stmt (location_t loc
, tree throw_expr
, bool rethrown
)
3860 /* We have a separate re-throw entry. */
3861 t
= build_function_call_vec (loc
, vNULL
, objc_rethrow_exception_decl
,
3865 /* Throw like the others... */
3866 vec
<tree
, va_gc
> *parms
;
3867 vec_alloc (parms
, 1);
3868 parms
->quick_push (throw_expr
);
3869 t
= build_function_call_vec (loc
, vNULL
, objc_exception_throw_decl
,
3873 return add_stmt (t
);
3876 /* Build __builtin_eh_pointer. */
3879 objc_build_exc_ptr (struct objc_try_context
**x ATTRIBUTE_UNUSED
)
3882 t
= builtin_decl_explicit (BUILT_IN_EH_POINTER
);
3883 t
= build_call_expr (t
, 1, integer_zero_node
);
3884 return fold_convert (objc_object_type
, t
);
3887 static tree
begin_catch (struct objc_try_context
**cur_try_context
, tree type
,
3888 tree decl
, tree compound
, bool ellipsis ATTRIBUTE_UNUSED
)
3892 /* Record the data for the catch in the try context so that we can
3893 finalize it later. Ellipsis is signalled by a NULL entry. */
3895 t
= build_stmt (input_location
, CATCH_EXPR
, NULL_TREE
, compound
);
3897 t
= build_stmt (input_location
, CATCH_EXPR
, type
, compound
);
3898 (*cur_try_context
)->current_catch
= t
;
3900 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3901 t
= objc_build_exc_ptr (cur_try_context
);
3902 t
= convert (TREE_TYPE (decl
), t
);
3903 /* FIXME: location. */
3904 if (type
&& type
!= error_mark_node
)
3906 t
= build1(NOP_EXPR
, ptr_type_node
, t
);
3907 t
= build_function_call (input_location
, objc2_begin_catch_decl
,
3908 tree_cons (NULL_TREE
, t
, NULL_TREE
));
3910 /* We might want to build a catch object for this (if it's not
3912 if (POINTER_TYPE_P (type
)
3913 && !objc_is_object_id (TREE_TYPE (type
))
3914 && TYPED_OBJECT (TREE_TYPE (type
)))
3915 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type
)));
3917 return build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
3920 /* try { catch-body } finally { objc_end_catch (); } */
3922 finish_catch (struct objc_try_context
**cur_try_context
, tree curr_catch
)
3924 struct objc_try_context
*ct
;
3925 tree try_exp
, func
, *l
, t
;
3926 location_t loc
= (*cur_try_context
)->try_locus
;
3928 if (!curr_catch
|| curr_catch
== error_mark_node
)
3931 t
= CATCH_BODY (curr_catch
);
3932 if (TREE_CODE (t
) == BIND_EXPR
)
3934 /* Usual case of @catch (objc-expr). */
3935 objc_begin_try_stmt (loc
, BIND_EXPR_BODY (t
));
3936 BIND_EXPR_BODY (t
) = NULL_TREE
;
3937 l
= &BIND_EXPR_BODY (t
);
3941 /* NULL entry, meaning @catch (...). */
3942 objc_begin_try_stmt (loc
, t
);
3943 CATCH_BODY (curr_catch
) = NULL_TREE
;
3944 l
= &CATCH_BODY (curr_catch
);
3947 /* Pick up the new context we made in begin_try above... */
3948 ct
= *cur_try_context
;
3949 func
= build_function_call_vec (loc
, vNULL
, objc2_end_catch_decl
, NULL
,
3951 append_to_statement_list (func
, &ct
->finally_body
);
3952 try_exp
= build_stmt (loc
, TRY_FINALLY_EXPR
, ct
->try_body
, ct
->finally_body
);
3953 *cur_try_context
= ct
->outer
;
3955 append_to_statement_list (try_exp
, l
);
3956 append_to_statement_list (curr_catch
, &((*cur_try_context
)->catch_list
));
3960 finish_try_stmt (struct objc_try_context
**cur_try_context
)
3962 struct objc_try_context
*c
= *cur_try_context
;
3963 tree stmt
= c
->try_body
;
3965 stmt
= build_stmt (c
->try_locus
, TRY_CATCH_EXPR
, stmt
, c
->catch_list
);
3966 if (c
->finally_body
)
3967 stmt
= build_stmt (c
->try_locus
, TRY_FINALLY_EXPR
, stmt
, c
->finally_body
);
3971 #include "gt-objc-objc-next-runtime-abi-02.h"