hppa: Always enable PIE on 64-bit target
[official-gcc.git] / gcc / objc / objc-next-runtime-abi-02.cc
bloba622f4cbf4eee799098b9095ae4856e1c577f204
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)
12 any later version.
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
26 4.2.1 compiler. */
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tree.h"
32 #include "stringpool.h"
33 #include "attribs.h"
35 #ifdef OBJCPLUS
36 #include "cp/cp-tree.h"
37 #else
38 #include "c/c-tree.h"
39 #include "c/c-lang.h"
40 #endif
41 #include "langhooks.h"
42 #include "c-family/c-objc.h"
43 #include "objc-act.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. */
47 #ifdef OBJCPLUS
48 #define OBJCP_REMAP_FUNCTIONS
49 #include "objcp-decl.h"
50 #endif /* OBJCPLUS */
52 #include "target.h"
53 #include "tree-iterator.h"
54 #include "opts.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
92 /* Templates. */
93 OCTI_V2_CLS_TEMPL,
94 OCTI_V2_CAT_TEMPL,
95 OCTI_V2_CLS_RO_TEMPL,
96 OCTI_V2_PROTO_TEMPL,
97 OCTI_V2_IVAR_TEMPL,
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,
104 OCTI_V2_IMP_TYPE,
105 OCTI_V2_SUPER_IMP_TYPE,
107 OCTI_V2_CACHE_DECL,
108 OCTI_V2_VTABLE_DECL,
110 OCTI_V2_PROPERTY_TEMPL,
112 /* V2 messaging. */
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,
125 OCTI_V2_MAX
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]
161 /* V2 Messaging */
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> **,
212 tree, int, int);
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;
237 bool
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%> "
247 "greater than 1");
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;
289 return true;
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. */
301 static void
302 next_runtime_abi_02_init_metadata_attributes (void)
304 if (!objc_meta)
305 objc_meta = get_identifier ("OBJC2META");
307 if (!meta_base)
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");
315 meta_clac_vars =
316 meta_clai_vars = meta_base;
318 meta_clac_meth =
319 meta_clai_meth =
320 meta_catc_meth =
321 meta_cati_meth =
322 meta_proto_cls_meth =
323 meta_proto_nst_meth = meta_base;
325 meta_clas_prot =
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)
359 tree type;
360 #ifdef OBJCPLUS
361 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
362 default. */
363 if (!OPTION_SET_P (flag_objc_call_cxx_cdtors))
364 global_options.x_flag_objc_call_cxx_cdtors = 1;
365 #endif
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)));
375 /* SEL typedef. */
376 type = lang_hooks.decls.pushdecl (build_decl (input_location,
377 TYPE_DECL,
378 objc_selector_name,
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")));
391 objc_prop_list_ptr =
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;
401 if (fixup_p)
403 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
404 type = build_varargs_function_type_list (objc_object_type,
405 objc_object_type,
406 objc_v2_selector_type,
407 NULL_TREE);
409 else
411 /* id objc_msgSendXXXX (id, SEL, ...); */
412 type = build_varargs_function_type_list (objc_object_type,
413 objc_object_type,
414 objc_selector_type,
415 NULL_TREE);
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,
419 NULL, NULL_TREE);
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,
425 NULL, NULL_TREE);
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,
431 NULL, NULL_TREE);
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,
437 NULL, NULL_TREE);
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,
443 objc_super_type,
444 objc_v2_super_selector_type,
445 NULL_TREE);
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,
448 NULL, NULL_TREE);
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,
455 NOT_BUILT_IN, NULL,
456 NULL_TREE);
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,
463 NULL_TREE);
464 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
465 type, 0, NOT_BUILT_IN,
466 NULL, NULL_TREE);
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,
478 NULL_TREE);
479 objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
480 type, 0, NOT_BUILT_IN,
481 NULL, NULL_TREE);
483 /* id objc_getMetaClass (const char *); */
484 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
485 type, 0, NOT_BUILT_IN,
486 NULL, NULL_TREE);
488 /* This is the type of all of the following functions
489 objc_copyStruct(). */
490 type = build_function_type_list (void_type_node,
491 ptr_type_node,
492 const_ptr_type_node,
493 ptrdiff_type_node,
494 boolean_type_node,
495 boolean_type_node,
496 NULL_TREE);
497 /* Declare the following function:
498 void
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,
503 NULL, NULL_TREE);
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
515 class. */
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,
524 NULL, NULL_TREE);
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,
531 NULL, NULL_TREE);
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,
538 NULL, NULL_TREE);
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
554 IMP messenger;
555 SEL name;
557 where IMP is: id (*) (id, _message_ref_t*, ...)
560 /* struct _super_message_ref_t
562 SUPER_IMP messenger;
563 SEL name;
565 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
568 static void
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"));
578 /* IMP messenger; */
579 ptr_message_ref_t =
580 build_pointer_type (xref_tag (RECORD_TYPE,
581 get_identifier ("_message_ref_t")));
583 objc_v2_imp_type =
584 build_pointer_type (build_function_type_list
585 (objc_object_type,
586 objc_object_type,
587 ptr_message_ref_t,
588 NULL_TREE));
590 decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
592 /* SEL name; */
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);
599 chain = NULL;
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
611 (objc_object_type,
612 objc_super_type,
613 ptr_message_ref_t,
614 NULL_TREE));
616 add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
618 /* SEL name; */
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.
628 struct class_ro_t
630 uint32_t const flags;
631 uint32_t const instanceStart;
632 uint32_t const instanceSize;
633 #ifdef __LP64__
634 uint32_t const reserved;
635 #endif
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;
645 struct class_t
647 struct class_t *isa;
648 struct class_t *superclass;
649 void *cache;
650 IMP *vtable;
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;
659 static void
660 build_v2_class_templates (void)
662 tree cnst_strg_type;
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);
710 chain = NULL;
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),
717 "isa", &chain);
719 /* struct class_t * const superclass; */
720 add_field_decl (build_pointer_type (objc_v2_class_template),
721 "superclass", &chain);
723 /* void *cache; */
724 add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
726 /* IMP *vtable; */
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;
738 Class cls;
739 }; */
740 void
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);
750 /* Class cls; */
751 add_field_decl (objc_class_type, "cls", &chain);
753 objc_finish_struct (objc_super_template, decls);
756 /* struct protocol_t
758 Class isa;
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;
766 const uint32_t size;
767 const uint32_t flags;
768 const char ** extended_method_types;
769 const char * demangled_name;
770 const struct _prop_list_t * class_properties;
773 static void
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));
781 /* Class isa; */
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:
826 struct category_t
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;
837 static void
838 build_v2_category_template (void)
840 tree decls, *chain = NULL;
842 objc_v2_category_template =
843 objc_start_struct (get_identifier ("_category_t"));
845 /* char *name; */
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
870 if one is found. */
872 static tree
873 hash_name_lookup (hash *hashlist, tree name)
875 hash target;
877 target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
879 while (target)
881 if (name == DECL_NAME (target->key))
882 return target->key;
884 target = target->next;
886 return 0;
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
891 node. */
893 static void
894 hash_name_enter (hash *hashlist, tree id)
896 hash obj;
897 int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
899 obj = ggc_alloc<hashed_entry> ();
900 obj->list = 0;
901 obj->next = hashlist[slot];
902 obj->key = id;
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()). */
910 static tree
911 create_extern_decl (tree type, const char *name)
913 tree id = get_identifier (name);
914 tree var = hash_name_lookup (extern_names, id);
915 if (var)
916 return var;
917 /* New name. */
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);
923 return 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. */
928 static tree
929 create_global_decl (tree type, const char *name, bool is_def = false);
931 static tree
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);
936 if (var)
937 is_def = true;
938 else
940 var = start_var_decl (type, name);
941 hash_name_enter (extern_names, var);
943 if (is_def)
945 DECL_EXTERNAL (var) = 0;
946 TREE_STATIC (var) = 1;
948 TREE_PUBLIC (var) = 1;
949 return var;
952 /* Create a symbol with __attribute__ ((visibility ("hidden")))
953 attribute (private extern). */
954 static tree
955 create_hidden_decl (tree type, const char *name, bool is_def = false);
957 static tree
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;
963 return decl;
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. ;-) */
970 static tree
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;
980 static tree
981 next_runtime_abi_02_class_decl (tree klass)
983 tree decl;
984 char buf[BUFSIZE];
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);
990 return decl;
993 static tree
994 next_runtime_abi_02_metaclass_decl (tree klass)
996 tree decl;
997 char buf[BUFSIZE];
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);
1003 return decl;
1006 static tree
1007 next_runtime_abi_02_category_decl (tree klass)
1009 tree decl;
1010 char buf[BUFSIZE];
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);
1016 return decl;
1019 static tree
1020 next_runtime_abi_02_protocol_decl (tree p)
1022 tree decl;
1023 char buf[BUFSIZE];
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;
1033 else
1034 decl = start_var_decl (objc_v2_protocol_template, buf);
1035 OBJCMETA (decl, objc_meta, meta_protocol);
1036 DECL_PRESERVE_P (decl) = 1;
1037 return decl;
1040 static tree
1041 next_runtime_abi_02_string_decl (tree type, const char *name, string_section where)
1043 tree var = start_var_decl (type, name);
1044 switch (where)
1046 case class_names:
1047 OBJCMETA (var, objc_meta, meta_class_name);
1048 break;
1049 case meth_var_names:
1050 OBJCMETA (var, objc_meta, meta_meth_name);
1051 break;
1052 case meth_var_types:
1053 OBJCMETA (var, objc_meta, meta_meth_type);
1054 break;
1055 case prop_names_attr:
1056 OBJCMETA (var, objc_meta, meta_prop_name_attr);
1057 break;
1058 default:
1059 OBJCMETA (var, objc_meta, meta_base);
1060 break;
1062 return var;
1065 /* NOTE --- entry --- */
1067 struct GTY(()) ident_data_tuple {
1068 tree ident;
1069 tree data;
1072 /* This routine creates a file scope static variable of type 'Class'
1073 to hold the address of a class. */
1075 static tree
1076 build_v2_class_reference_decl (tree ident)
1078 tree decl;
1079 char buf[BUFSIZE];
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);
1084 return decl;
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;
1094 static tree
1095 objc_v2_get_class_reference (tree ident)
1097 tree decl;
1098 ident_data_tuple e;
1099 if (classrefs)
1101 int count;
1102 ident_data_tuple *ref;
1103 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1105 if (ref->ident == ident)
1107 if (!ref->data)
1108 ref->data = build_v2_class_reference_decl (ident);
1109 return ref->data;
1113 else
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
1118 to be created. */
1119 decl = build_v2_class_reference_decl (ident);
1120 e.ident = ident;
1121 e.data = decl;
1122 vec_safe_push (classrefs, e);
1123 return decl;
1126 static tree
1127 next_runtime_abi_02_get_class_reference (tree ident)
1129 if (!flag_zero_link)
1130 return objc_v2_get_class_reference (ident);
1131 else
1133 /* We fall back to using objc_getClass (). */
1134 vec<tree, va_gc> *v;
1135 vec_alloc (v, 1);
1136 tree t;
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));
1142 v->quick_push (t);
1143 t = build_function_call_vec (input_location, vNULL, objc_get_class_decl,
1144 v, 0);
1145 vec_free (v);
1146 return t;
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
1155 prototype. */
1157 static void
1158 next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1159 tree meth, int context,
1160 int superflag)
1162 tree receiver_type;
1164 if (superflag)
1165 receiver_type = objc_super_type;
1166 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1167 receiver_type = objc_instance_type;
1168 else
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);
1176 else
1177 vec_safe_push (*argtypes, objc_selector_type);
1180 /* TODO: Merge this with the message refs. */
1181 static tree
1182 build_selector_reference_decl (tree ident)
1184 tree decl;
1185 char *t, buf[BUFSIZE];
1187 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1188 t = buf;
1189 while (*t)
1191 if (*t==':')
1192 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1193 t++;
1195 decl = start_var_decl (objc_selector_type, buf);
1196 OBJCMETA (decl, objc_meta, meta_sel_refs);
1197 return decl;
1200 static tree
1201 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1202 tree ident,
1203 tree proto ATTRIBUTE_UNUSED)
1205 tree *chain = &sel_ref_chain;
1206 tree expr;
1208 while (*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);
1219 return expr;
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. */
1227 static tree
1228 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1230 tree decl;
1231 char buf[BUFSIZE], *t;
1232 int offset = 12;
1234 /* Skip past the objc_msgSend it's the same for all... */
1235 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1236 offset++;
1238 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1239 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1240 IDENTIFIER_POINTER (sel_name));
1241 t = buf;
1242 while (*t)
1244 if (*t==':')
1245 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1246 t++;
1248 decl = start_var_decl (objc_v2_message_ref_template, buf);
1249 OBJCMETA (decl, objc_meta, meta_mref);
1250 return decl;
1253 struct GTY(()) msgref_entry {
1254 tree func;
1255 tree selname;
1256 tree refdecl;
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'
1263 elements. */
1265 static tree
1266 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1268 tree decl;
1269 msgref_entry e;
1270 if (msgrefs)
1272 int count;
1273 msgref_entry *ref;
1274 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1275 if (ref->func == message_func_decl && ref->selname == sel_name)
1276 return ref->refdecl;
1278 else
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;
1287 e.refdecl = decl;
1288 vec_safe_push (msgrefs, e);
1289 return decl;
1292 static tree
1293 build_v2_protocollist_ref_decl (tree protocol)
1295 tree decl;
1296 tree protocol_ident = PROTOCOL_NAME (protocol);
1297 char buf[BUFSIZE];
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);
1306 return decl;
1309 struct GTY(()) prot_list_entry {
1310 tree id;
1311 tree refdecl;
1313 static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
1315 static tree
1316 objc_v2_get_protocol_reference (tree ident)
1318 tree decl;
1319 prot_list_entry e;
1320 if (protrefs)
1322 int count;
1323 prot_list_entry *ref;
1324 FOR_EACH_VEC_ELT (*protrefs, count, ref)
1326 if (ref->id == ident)
1328 if (!ref->refdecl)
1329 ref->refdecl = build_v2_protocollist_ref_decl (ident);
1330 return ref->refdecl;
1334 else
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
1339 to be created. */
1340 decl = build_v2_protocollist_ref_decl (ident);
1341 e.id = ident;
1342 e.refdecl = decl;
1343 vec_safe_push (protrefs, e);
1344 return decl;
1347 static tree
1348 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1349 tree p)
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. */
1361 static tree
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));
1371 if (*klass)
1375 tree ivar_chain = CLASS_RAW_IVARS (*klass);
1376 if (ivar_chain)
1378 field = is_ivar (ivar_chain, component);
1379 if (field != NULL_TREE)
1380 break;
1382 *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1384 while (*klass);
1387 return field;
1390 static void
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));
1397 return;
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. */
1405 static tree
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);
1412 if (!field)
1413 return NULL_TREE;
1415 /* This routine only handles non-bitfield fields */
1416 if (DECL_C_BIT_FIELD (field))
1417 return NULL_TREE;
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);
1425 /* (char*)datum */
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);
1453 return ref;
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
1458 class structure. */
1459 static tree
1460 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1461 tree base, tree id)
1463 tree ivar;
1464 if ((ivar = objc_v2_build_ivar_ref (base, id)))
1465 return ivar;
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). */
1471 static tree
1472 build_v2_superclass_ref_decl (tree ident, bool inst)
1474 tree decl;
1475 char buf[BUFSIZE];
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);
1481 return decl;
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. */
1489 static tree
1490 objc_get_superclass_ref_decl (tree name, bool inst_meth)
1492 tree decl;
1493 vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs
1494 : metaclass_super_refs;
1496 if (list)
1498 int count;
1499 ident_data_tuple *ref;
1500 FOR_EACH_VEC_ELT (*list, count, ref)
1502 if (ref->ident == name)
1504 if (!ref->data)
1505 ref->data = build_v2_superclass_ref_decl (name, inst_meth);
1506 return ref->data;
1510 else
1512 /* Somewhat arbitrary initial provision. */
1513 if (inst_meth)
1515 vec_alloc (class_super_refs, 16);
1516 list = class_super_refs;
1518 else
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
1525 to be created. */
1526 decl = build_v2_superclass_ref_decl (name, inst_meth);
1527 ident_data_tuple e;
1528 e.ident = name;
1529 e.data = decl;
1530 vec_safe_push (list, e);
1531 return decl;
1534 /* Get a reference to the superclass for IMP. */
1536 static tree
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. */
1546 static tree
1547 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1548 struct imp_entry *imp,
1549 bool inst_meth)
1551 if (flag_zero_link)
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);
1566 if (!inst_meth)
1567 return objc_get_superclass_ref_decl (cls_name, inst_meth);
1568 return objc_get_class_reference (cls_name);
1571 static tree
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))
1578 int count;
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)
1583 return ref->ident;
1585 return NULL_TREE;
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. */
1592 static tree
1593 objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1595 tree valtail;
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)
1609 break;
1610 if (!TREE_SIDE_EFFECTS (value))
1611 continue;
1612 /* To prevent re-evaluation. */
1613 value = save_expr (value);
1614 add_stmt (value);
1615 TREE_VALUE (valtail) = value;
1617 return values;
1620 /* Build the new abi's messaging library call. It looks like:
1621 (*_msg.messenger) (receiver, &_msg, ...) */
1623 static tree
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)
1628 tree ret_val;
1629 tree sender, rcv_p, t;
1630 tree ret_type
1631 = (method_prototype
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);
1636 tree sender_cast;
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);
1644 if (check_for_nil)
1645 method_params = objc_copy_to_temp_side_effect_params (ftype,
1646 method_params);
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),
1653 selector);
1655 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1657 rcv_p = (super_flag ? objc_super_type : objc_object_type);
1659 lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1660 if (sender == error_mark_node || lookup_object == error_mark_node)
1661 return error_mark_node;
1663 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1664 lookup_object = save_expr (lookup_object);
1666 method_params = tree_cons (NULL_TREE, lookup_object,
1667 tree_cons (NULL_TREE, selector,
1668 method_params));
1669 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object,
1670 build_int_cst (TREE_TYPE (lookup_object), 0));
1671 ret_val = build_function_call (input_location, t, method_params);
1672 if (check_for_nil)
1674 /* receiver != nil ? ret_val : 0 */
1675 tree ftree;
1676 tree ifexp;
1678 if (TREE_CODE (ret_type) == RECORD_TYPE
1679 || TREE_CODE (ret_type) == UNION_TYPE)
1680 /* An empty constructor is zero-filled by the middle end. */
1681 ftree = objc_build_constructor (ret_type, NULL);
1682 else
1683 ftree = fold_convert (ret_type, integer_zero_node);
1685 ifexp = build_binary_op (input_location, NE_EXPR,
1686 lookup_object,
1687 fold_convert (rcv_p, integer_zero_node), 1);
1689 #ifdef OBJCPLUS
1690 ret_val = build_conditional_expr (input_location,
1691 ifexp, ret_val, ftree,
1692 tf_warning_or_error);
1693 #else
1694 ret_val = build_conditional_expr (input_location,
1695 ifexp, 0,
1696 ret_val, NULL_TREE, input_location,
1697 ftree, NULL_TREE, input_location);
1698 ret_val = fold_convert (ret_type, ret_val);
1699 #endif
1701 return ret_val;
1704 static tree
1705 build_v2_build_objc_method_call (int super, tree method_prototype,
1706 tree lookup_object, tree selector,
1707 tree method_params, location_t loc,
1708 bool check_for_nil, bool rx_is_id)
1710 tree sender, sender_cast, method, t;
1711 tree rcv_p = (super ? objc_super_type : objc_object_type);
1712 vec<tree, va_gc> *parms;
1713 unsigned nparm = (method_params ? list_length (method_params) : 0);
1715 /* If a prototype for the method to be called exists, then cast
1716 the sender's return type and arguments to match that of the method.
1717 Otherwise, leave sender as is. */
1718 tree ret_type
1719 = (method_prototype
1720 ? TREE_VALUE (TREE_TYPE (method_prototype))
1721 : objc_object_type);
1722 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1723 METHOD_REF, super);
1725 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1726 ftype = build_type_attribute_variant (ftype,
1727 METHOD_TYPE_ATTRIBUTES
1728 (method_prototype));
1730 sender_cast = build_pointer_type (ftype);
1732 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
1734 if (error_operand_p (lookup_object))
1735 return error_mark_node;
1737 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1738 lookup_object = save_expr (lookup_object);
1740 /* Param list + 2 slots for object and selector. */
1741 vec_alloc (parms, nparm + 2);
1743 /* If we are returning an item that must be returned in memory, and the
1744 target ABI does this by an invisible pointer provided as the first arg,
1745 we need to adjust the message signature to include this. The second
1746 part of this excludes targets that provide some alternate scheme for
1747 structure returns. */
1748 if (ret_type && !VOID_TYPE_P (ret_type)
1749 && targetm.calls.return_in_memory (ret_type, 0)
1750 && !(targetm.calls.struct_value_rtx (0, 0)
1751 && (TREE_CODE (ret_type) == RECORD_TYPE
1752 || TREE_CODE (ret_type) == UNION_TYPE)))
1754 if (super)
1755 sender = umsg_id_super2_stret_fixup_decl;
1756 else
1757 sender = rx_is_id ? umsg_id_stret_fixup_decl
1758 : umsg_stret_fixup_decl;
1760 else
1762 if (super)
1763 sender = umsg_id_super2_fixup_decl;
1764 else
1765 sender = rx_is_id ? umsg_id_fixup_decl
1766 : umsg_fixup_decl;
1769 method = build_fold_addr_expr_loc (loc, sender);
1771 /* Pass the object to the method. */
1772 parms->quick_push (lookup_object);
1773 /* Pass the selector to the method. */
1774 parms->quick_push (selector);
1775 /* Now append the remainder of the parms. */
1776 if (nparm)
1777 for (; method_params; method_params = TREE_CHAIN (method_params))
1778 parms->quick_push (TREE_VALUE (method_params));
1780 /* Build an obj_type_ref, with the correct cast for the method call. */
1781 t = build3 (OBJ_TYPE_REF, sender_cast, method,
1782 lookup_object, build_int_cst (TREE_TYPE (lookup_object), 0));
1783 tree ret_val = build_function_call_vec (loc, vNULL, t, parms, NULL);
1784 vec_free (parms);
1785 if (check_for_nil)
1787 /* receiver != nil ? ret_val : 0 */
1788 tree ftree;
1789 tree ifexp;
1791 if (TREE_CODE (ret_type) == RECORD_TYPE
1792 || TREE_CODE (ret_type) == UNION_TYPE)
1794 /* An empty constructor is zero-filled by the middle end. */
1795 ftree = objc_build_constructor (ret_type, NULL);
1797 else
1798 ftree = fold_convert (ret_type, integer_zero_node);
1800 ifexp = build_binary_op (loc, NE_EXPR,
1801 lookup_object,
1802 fold_convert (rcv_p, integer_zero_node), 1);
1804 #ifdef OBJCPLUS
1805 ret_val = build_conditional_expr (loc, ifexp, ret_val, ftree,
1806 tf_warning_or_error);
1807 #else
1808 ret_val = build_conditional_expr (loc, ifexp, 1,
1809 ret_val, NULL_TREE, loc,
1810 ftree, NULL_TREE, loc);
1811 ret_val = fold_convert (ret_type, ret_val);
1812 #endif
1814 return ret_val;
1817 static tree
1818 next_runtime_abi_02_build_objc_method_call (location_t loc,
1819 tree method_prototype,
1820 tree receiver,
1821 tree rtype,
1822 tree sel_name,
1823 tree method_params,
1824 int super)
1826 /* Do we need to check for nil receivers ? */
1827 /* For now, message sent to classes need no nil check. In the
1828 future, class declaration marked as weak_import must be nil
1829 checked. */
1830 bool check_for_nil = flag_objc_nilcheck;
1831 if (super
1832 || (VAR_P (receiver)
1833 && TREE_TYPE (receiver) == objc_class_type))
1834 check_for_nil = false;
1836 if (flag_next_runtime >= USE_FIXUP_BEFORE)
1838 tree selector
1839 = next_runtime_abi_02_build_selector_reference (loc, sel_name,
1840 method_prototype);
1841 return build_v2_build_objc_method_call (super, method_prototype,
1842 receiver, selector,
1843 method_params, loc,
1844 check_for_nil,
1845 objc_is_id (rtype));
1848 /* else we have to build a pair of the function and selector. */
1849 tree message_func_decl;
1850 tree ret_type = method_prototype
1851 ? TREE_VALUE (TREE_TYPE (method_prototype))
1852 : objc_object_type;
1854 /* See comment for the fixup version above. */
1855 if (ret_type && !VOID_TYPE_P (ret_type)
1856 && targetm.calls.return_in_memory (ret_type, 0)
1857 && !(targetm.calls.struct_value_rtx (0, 0)
1858 && (TREE_CODE (ret_type) == RECORD_TYPE
1859 || TREE_CODE (ret_type) == UNION_TYPE)))
1861 if (super)
1862 message_func_decl = umsg_id_super2_stret_fixup_decl;
1863 else
1864 message_func_decl = objc_is_id (rtype)
1865 ? umsg_id_stret_fixup_decl
1866 : umsg_stret_fixup_decl;
1868 else
1870 if (super)
1871 message_func_decl = umsg_id_super2_fixup_decl;
1872 else
1873 message_func_decl = objc_is_id (rtype)
1874 ? umsg_id_fixup_decl
1875 : umsg_fixup_decl;
1878 tree selector = build_v2_selector_messenger_reference (sel_name,
1879 message_func_decl);
1881 /* selector = &_msg; */
1882 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1884 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1885 : objc_v2_selector_type),
1886 selector);
1888 /* (*_msg.messenger) (receiver, &_msg, ...); */
1889 return build_v2_objc_method_fixup_call (super, method_prototype, receiver,
1890 selector, method_params,
1891 check_for_nil);
1894 /* NOTE --- Constant String Class Stuff --- */
1896 static bool
1897 next_runtime_abi_02_setup_const_string_class_decl (void)
1899 if (!constant_string_global_id)
1901 /* Hopefully, this should not represent a serious limitation. */
1902 char buf[BUFSIZE];
1903 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1904 constant_string_global_id = get_identifier (buf);
1907 string_class_decl = lookup_name (constant_string_global_id);
1909 /* In OBJC2 abi, constant string class reference refers to class
1910 name for NSConstantString class. This declaration may not be
1911 available yet (in fact it is not in most cases). So, declare an
1912 extern OBJC_CLASS_$_NSConstantString in its place. */
1913 if (!string_class_decl)
1914 string_class_decl =
1915 create_extern_decl (objc_v2_class_template,
1916 IDENTIFIER_POINTER (constant_string_global_id));
1918 return (string_class_decl != NULL_TREE);
1921 static tree
1922 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1923 int length)
1925 tree constructor, fields, var;
1926 vec<constructor_elt, va_gc> *v = NULL;
1928 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1929 fields = TYPE_FIELDS (internal_const_str_type);
1930 CONSTRUCTOR_APPEND_ELT (v, fields,
1931 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1933 fields = DECL_CHAIN (fields);
1934 CONSTRUCTOR_APPEND_ELT (v, fields,
1935 build_unary_op (loc, ADDR_EXPR, string, 1));
1937 /* ??? check if this should be long. */
1938 fields = DECL_CHAIN (fields);
1939 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1940 constructor = objc_build_constructor (internal_const_str_type, v);
1942 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1943 DECL_INITIAL (var) = constructor;
1944 TREE_STATIC (var) = 1;
1945 DECL_CONTEXT (var) = NULL;
1946 OBJCMETA (var, objc_meta, meta_const_str);
1947 return var;
1950 /* NOTE --- NeXT V2 Metadata templates --- */
1952 /* This routine builds the following type:
1953 struct _prop_t
1955 const char * const name; // property name
1956 const char * const attributes; // comma-delimited, encoded,
1957 // property attributes
1961 static tree
1962 build_v2_property_template (void)
1964 tree prop_record;
1965 tree decls, *chain = NULL;
1967 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1968 /* const char * name */
1969 decls = add_field_decl (string_type_node, "name", &chain);
1971 /* const char * attribute */
1972 add_field_decl (string_type_node, "attribute", &chain);
1974 objc_finish_struct (prop_record, decls);
1975 return prop_record;
1978 /* struct ivar_t
1980 unsigned long int *offset;
1981 char *name;
1982 char *type;
1983 uint32_t alignment;
1984 uint32_t size;
1988 static tree
1989 build_v2_ivar_t_template (void)
1991 tree objc_ivar_id, objc_ivar_record;
1992 tree decls, *chain = NULL;
1994 objc_ivar_id = get_identifier ("_ivar_t");
1995 objc_ivar_record = objc_start_struct (objc_ivar_id);
1997 /* unsigned long int *offset; */
1998 decls = add_field_decl (build_pointer_type
1999 (TREE_TYPE (size_zero_node)), "offset", &chain);
2001 /* char *name; */
2002 add_field_decl (string_type_node, "name", &chain);
2004 /* char *type; */
2005 add_field_decl (string_type_node, "type", &chain);
2007 /* uint32_t alignment; */
2008 add_field_decl (integer_type_node, "alignment", &chain);
2010 /* uint32_t size; */
2011 add_field_decl (integer_type_node, "size", &chain);
2013 objc_finish_struct (objc_ivar_record, decls);
2014 return objc_ivar_record;
2017 static void
2018 build_metadata_templates (void)
2021 if (!objc_method_template)
2022 objc_method_template = build_method_template ();
2024 if (!objc_v2_property_template)
2025 objc_v2_property_template = build_v2_property_template ();
2027 if (!objc_v2_ivar_template)
2028 objc_v2_ivar_template = build_v2_ivar_t_template ();
2032 /* NOTE --- Output NeXT V2 Metadata --- */
2034 /* Routine builds name of Interface's main meta-data of type class_t. */
2036 static char *
2037 objc_build_internal_classname (tree ident, bool metaclass)
2039 static char string[512];
2040 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
2041 : "OBJC_CLASS_$",
2042 IDENTIFIER_POINTER (ident));
2043 return string;
2046 /* Build the name for object of type struct class_ro_t */
2048 static const char *
2049 newabi_append_ro (const char *name)
2051 const char *dollar;
2052 char *p;
2053 static char string[BUFSIZE];
2054 dollar = strchr (name, '$');
2055 gcc_assert (dollar);
2056 p = string;
2057 *p = '_'; p++;
2058 strncpy (p, name, (int)(dollar - name));
2059 p += (int)(dollar - name);
2060 sprintf (p, "RO_%s", dollar);
2061 return string;
2064 /* Build the struct message_ref_t msg =
2065 {objc_msgSend_fixup_xxx, @selector(func)}
2066 table. */
2068 static
2069 void build_v2_message_ref_translation_table (void)
2071 int count;
2072 msgref_entry *ref;
2074 if (!vec_safe_length (msgrefs))
2075 return;
2077 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
2079 vec<constructor_elt, va_gc> *initializer;
2080 tree expr, constructor;
2081 tree struct_type = TREE_TYPE (ref->refdecl);
2082 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
2084 initializer = NULL;
2085 /* First 'IMP messenger' field... */
2086 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
2087 expr = convert (objc_v2_imp_type, expr);
2088 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2090 /* ... then 'SEL name' field. */
2091 expr = build_selector (ref->selname);
2092 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2093 constructor = objc_build_constructor (struct_type, initializer);
2094 finish_var_decl (ref->refdecl, constructor);
2098 /* Build decl = initializer; for each externally visible class
2099 reference. */
2101 static void
2102 build_v2_classrefs_table (void)
2104 int count;
2105 ident_data_tuple *ref;
2107 if (!vec_safe_length (classrefs))
2108 return;
2110 FOR_EACH_VEC_ELT (*classrefs, count, ref)
2112 tree expr = ref->ident;
2113 tree decl = ref->data;
2114 /* Interface with no implementation and yet one of its messages
2115 has been used. Need to generate a full address-of tree for it
2116 here. */
2117 if (TREE_CODE (expr) == IDENTIFIER_NODE)
2119 const char *name = objc_build_internal_classname (expr, false);
2120 expr = create_extern_decl (objc_v2_class_template, name);
2121 expr = convert (objc_class_type, build_fold_addr_expr (expr));
2123 /* The runtime wants this, even if it appears unused, so we must force the
2124 output. */
2125 DECL_PRESERVE_P (decl) = 1;
2126 finish_var_decl (decl, expr);
2130 /* Build decl = initializer; for each externally visible super class
2131 reference. */
2133 static void
2134 build_v2_super_classrefs_table (bool metaclass)
2136 int count;
2137 ident_data_tuple *ref;
2138 vec<ident_data_tuple, va_gc> *list = metaclass ? metaclass_super_refs
2139 : class_super_refs;
2141 if (!vec_safe_length (list))
2142 return;
2144 FOR_EACH_VEC_ELT (*list, count, ref)
2146 tree expr = ref->ident;
2147 tree decl = ref->data;
2148 /* Interface with no implementation and yet one of its messages
2149 has been used. Need to generate a full address-of tree for it
2150 here. */
2151 if (TREE_CODE (expr) == IDENTIFIER_NODE)
2153 const char * name = objc_build_internal_classname (expr, metaclass);
2154 expr = create_extern_decl (objc_v2_class_template, name);
2155 expr = convert (objc_class_type, build_fold_addr_expr (expr));
2157 finish_var_decl (decl, expr);
2161 /* Add the global class meta-data declaration to the list which later
2162 on ends up in the __class_list section. */
2164 static GTY(()) vec<tree, va_gc> *class_list;
2166 static void
2167 objc_v2_add_to_class_list (tree global_class_decl)
2169 vec_safe_push (class_list, global_class_decl);
2172 static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
2174 /* Add the global class meta-data declaration to the list which later
2175 on ends up in the __nonlazy_class section. */
2177 static void
2178 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2180 vec_safe_push (nonlazy_class_list, global_class_decl);
2183 static GTY(()) vec<tree, va_gc> *category_list;
2185 /* Add the category meta-data declaration to the list which later on
2186 ends up in the __nonlazy_category section. */
2188 static void
2189 objc_v2_add_to_category_list (tree decl)
2191 vec_safe_push (category_list, decl);
2194 static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
2196 /* Add the category meta-data declaration to the list which later on
2197 ends up in the __category_list section. */
2199 static void
2200 objc_v2_add_to_nonlazy_category_list (tree decl)
2202 vec_safe_push (nonlazy_category_list, decl);
2205 static bool
2206 has_load_impl (tree clsmeth)
2208 while (clsmeth)
2210 tree id = METHOD_SEL_NAME (clsmeth);
2211 if (IDENTIFIER_LENGTH (id) == 4
2212 && startswith (IDENTIFIER_POINTER (id), "load"))
2213 return true;
2214 clsmeth = DECL_CHAIN (clsmeth);
2217 return false;
2220 /* Build a __{class,category}_list section table containing address of
2221 all @implemented {class,category} meta-data. */
2223 static void
2224 build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
2226 int count=0;
2227 tree type, decl, expr;
2228 vec<constructor_elt, va_gc> *initlist = NULL;
2230 if (!vec_safe_length (src))
2231 return;
2233 FOR_EACH_VEC_ELT (*src, count, decl)
2235 #ifndef OBJCPLUS
2236 tree purpose = build_int_cst (NULL_TREE, count);
2237 #else
2238 tree purpose = NULL_TREE;
2239 #endif
2240 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2241 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2243 gcc_assert (count > 0);
2244 type = build_array_type (objc_class_type,
2245 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2246 decl = start_var_decl (type, nam);
2247 /* The runtime wants this, even if it appears unused, so we must
2248 force the output. */
2249 DECL_PRESERVE_P (decl) = 1;
2250 expr = objc_build_constructor (type, initlist);
2251 OBJCMETA (decl, objc_meta, attr);
2252 finish_var_decl (decl, expr);
2255 /* Build decl = initializer; for each protocol referenced in
2256 @protocol(MyProt) expression. Refs as built in the entry section
2257 above. */
2259 static void
2260 build_v2_protocol_list_translation_table (void)
2262 int count;
2263 prot_list_entry *ref;
2265 if (!protrefs)
2266 return;
2268 FOR_EACH_VEC_ELT (*protrefs, count, ref)
2270 char buf[BUFSIZE];
2271 tree expr;
2272 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2273 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2274 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2275 expr = start_var_decl (objc_v2_protocol_template, buf);
2276 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2277 finish_var_decl (ref->refdecl, expr);
2279 /* TODO: Maybe we could explicitly delete the vec. now? */
2282 static GTY (()) vec<prot_list_entry, va_gc> *protlist;
2284 /* Add the local protocol meta-data declaration to the list which
2285 later on ends up in the __protocol_list section. */
2287 static void
2288 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2290 prot_list_entry e;
2291 if (!protlist)
2292 /* Arbitrary init count. */
2293 vec_alloc (protlist, 32);
2294 e.id = protocol_interface_decl;
2295 e.refdecl = protocol_decl;
2296 vec_safe_push (protlist, e);
2299 /* Build the __protocol_list section table containing address of all
2300 generate protocol_t meta-data. */
2302 static void
2303 build_v2_protocol_list_address_table (void)
2305 int count;
2306 prot_list_entry *ref;
2307 if (!vec_safe_length (protlist))
2308 return;
2310 FOR_EACH_VEC_ELT (*protlist, count, ref)
2312 tree decl, expr;
2313 char buf[BUFSIZE];
2314 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2315 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2316 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2317 if (flag_next_runtime >= USE_FIXUP_BEFORE)
2319 decl = create_hidden_decl (objc_protocol_type, buf, /*is def=*/true);
2320 DECL_WEAK (decl) = true;
2322 else
2323 decl = create_global_decl (objc_protocol_type, buf, /*is def=*/true);
2324 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2325 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2326 finish_var_decl (decl, expr);
2327 DECL_PRESERVE_P (decl) = 1;
2330 /* TODO: delete the vec. */
2331 /* TODO: upgrade to the clang/llvm hidden version. */
2334 /* This routine declares a variable to hold meta data for 'struct
2335 protocol_list_t'. */
2337 static tree
2338 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2340 tree refs_decl, lproto, e, plist, ptempl_p_t;
2341 int size = 0;
2342 vec<constructor_elt, va_gc> *initlist = NULL;
2343 char buf[BUFSIZE];
2345 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2346 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2347 plist = CLASS_PROTOCOL_LIST (i_or_p);
2348 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2349 plist = PROTOCOL_LIST (i_or_p);
2350 else
2351 gcc_unreachable ();
2353 /* Compute size. */
2354 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2355 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2356 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2357 size++;
2359 /* Build initializer. */
2361 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2362 e = build_int_cst (ptempl_p_t, size);
2363 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2365 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2367 tree pval = TREE_VALUE (lproto);
2369 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2370 && PROTOCOL_FORWARD_DECL (pval))
2372 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2373 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2374 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2375 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2379 /* static struct protocol_list_t *list[size]; */
2381 switch (TREE_CODE (i_or_p))
2383 case PROTOCOL_INTERFACE_TYPE:
2384 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2385 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2386 break;
2387 case CLASS_INTERFACE_TYPE:
2388 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2389 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2390 break;
2391 case CATEGORY_INTERFACE_TYPE:
2392 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2393 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2394 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2395 break;
2396 default:
2397 gcc_unreachable ();
2400 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2401 buf);
2402 /* ObjC2 puts all these in the base section. */
2403 OBJCMETA (refs_decl, objc_meta, meta_base);
2404 DECL_PRESERVE_P (refs_decl) = 1;
2405 finish_var_decl (refs_decl,
2406 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2407 return refs_decl;
2410 /* This routine builds one 'struct method_t' initializer list. Note
2411 that the old ABI is supposed to build 'struct objc_method' which
2412 has 3 fields, but it does not build the initialization expression
2413 for 'method_imp' which for protocols is NULL any way. To be
2414 consistent with declaration of 'struct method_t', in the new ABI we
2415 set the method_t.imp to NULL. */
2417 static tree
2418 build_v2_descriptor_table_initializer (tree type, tree entries)
2420 vec<constructor_elt, va_gc> *initlist = NULL;
2423 vec<constructor_elt, va_gc> *eltlist = NULL;
2424 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2425 build_selector (METHOD_SEL_NAME (entries)));
2426 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2427 add_objc_string (METHOD_ENCODING (entries),
2428 meth_var_types));
2429 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2431 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2432 objc_build_constructor (type, eltlist));
2433 entries = TREE_CHAIN (entries);
2435 while (entries);
2437 return objc_build_constructor (build_array_type (type, 0), initlist);
2440 /* struct method_list_t
2442 uint32_t entsize;
2443 uint32_t method_count;
2444 struct objc_method method_list[method_count];
2445 }; */
2447 static tree
2448 build_v2_method_list_template (tree list_type, int size)
2450 tree method_list_t_record;
2451 tree array_type, decls, *chain = NULL;
2453 method_list_t_record = objc_start_struct (NULL_TREE);
2455 /* uint32_t const entsize; */
2456 decls = add_field_decl (integer_type_node, "entsize", &chain);
2458 /* int method_count; */
2459 add_field_decl (integer_type_node, "method_count", &chain);
2461 /* struct objc_method method_list[]; */
2462 array_type = build_sized_array_type (list_type, size);
2463 add_field_decl (array_type, "method_list", &chain);
2465 objc_finish_struct (method_list_t_record, decls);
2466 return method_list_t_record;
2469 /* Note, as above that we are building to the objc_method_template
2470 which has the *imp field. ABI0/1 build with
2471 objc_method_prototype_template which is missing this field. */
2472 static tree
2473 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2474 const char *prefix, tree attr,
2475 vec<tree>& all_meths)
2477 tree method_list_template, initlist, decl;
2478 int size, entsize;
2479 vec<constructor_elt, va_gc> *v = NULL;
2480 char buf[BUFSIZE];
2482 if (!chain || !prefix)
2483 return NULL_TREE;
2485 tree method = chain;
2486 size = 0;
2487 while (method)
2489 if (! METHOD_ENCODING (method))
2490 METHOD_ENCODING (method) = encode_method_prototype (method);
2491 all_meths.safe_push (method);
2492 method = TREE_CHAIN (method);
2493 size++;
2496 gcc_assert (size);
2497 method_list_template = build_v2_method_list_template (objc_method_template,
2498 size);
2499 snprintf (buf, BUFSIZE, "%s_%s", prefix,
2500 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2502 decl = start_var_decl (method_list_template, buf);
2504 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2505 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2506 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2507 initlist =
2508 build_v2_descriptor_table_initializer (objc_method_template,
2509 chain);
2510 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2511 /* Get into the right section. */
2512 OBJCMETA (decl, objc_meta, attr);
2513 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2514 return decl;
2517 static tree
2518 generate_v2_meth_type_list (vec<tree>& all_meths, tree protocol,
2519 const char *prefix)
2521 if (all_meths.is_empty () || !prefix)
2522 return NULL_TREE;
2524 unsigned size = all_meths.length ();
2525 tree list_type = build_sized_array_type (string_type_node, size);
2526 char *nam;
2527 asprintf (&nam, "%s_%s", prefix,
2528 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2529 tree decl = start_var_decl (list_type, nam);
2530 free (nam);
2531 OBJCMETA (decl, objc_meta, meta_base);
2532 vec<constructor_elt, va_gc> *v = NULL;
2534 for (unsigned i = 0; i < size; ++i)
2535 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2536 add_objc_string (METHOD_ENCODING (all_meths[i]),
2537 meth_var_types));
2538 finish_var_decl (decl, objc_build_constructor (list_type, v));
2539 return decl;
2542 /* This routine builds the initializer list to initialize the 'struct
2543 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2545 static tree
2546 build_v2_property_table_initializer (tree type, tree context)
2548 tree x;
2549 vec<constructor_elt, va_gc> *inits = NULL;
2550 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2551 x = CLASS_PROPERTY_DECL (context);
2552 else
2553 x = IMPL_PROPERTY_DECL (context);
2555 for (; x; x = TREE_CHAIN (x))
2557 vec<constructor_elt, va_gc> *elemlist = NULL;
2558 /* NOTE! sections where property name/attribute go MUST change
2559 later. */
2560 tree attribute, name_ident = PROPERTY_NAME (x);
2562 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2563 add_objc_string (name_ident, prop_names_attr));
2565 attribute = objc_v2_encode_prop_attr (x);
2566 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2567 add_objc_string (attribute, prop_names_attr));
2569 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2570 objc_build_constructor (type, elemlist));
2573 return objc_build_constructor (build_array_type (type, 0),inits);
2576 /* This routine builds the following type:
2577 struct _prop_list_t
2579 uint32_t entsize; // sizeof (struct _prop_t)
2580 uint32_t prop_count;
2581 struct _prop_t prop_list [prop_count];
2585 static tree
2586 build_v2_property_list_template (tree list_type, int size)
2588 tree property_list_t_record;
2589 tree array_type, decls, *chain = NULL;
2591 /* anonymous. */
2592 property_list_t_record = objc_start_struct (NULL_TREE);
2594 /* uint32_t const entsize; */
2595 decls = add_field_decl (integer_type_node, "entsize", &chain);
2597 /* int prop_count; */
2598 add_field_decl (integer_type_node, "prop_count", &chain);
2600 /* struct _prop_t prop_list[]; */
2601 array_type = build_sized_array_type (list_type, size);
2602 add_field_decl (array_type, "prop_list", &chain);
2604 objc_finish_struct (property_list_t_record, decls);
2605 return property_list_t_record;
2608 /* Top-level routine to generate property tables for each
2609 implementation. */
2611 static tree
2612 generate_v2_property_table (tree context, tree klass_ctxt)
2614 tree x, decl, initlist, property_list_template;
2615 bool is_proto = false;
2616 vec<constructor_elt, va_gc> *inits = NULL;
2617 int init_val, size = 0;
2618 char buf[BUFSIZE];
2620 if (context)
2622 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2623 x = CLASS_PROPERTY_DECL (context);
2624 is_proto = true;
2626 else
2627 x = IMPL_PROPERTY_DECL (klass_ctxt);
2629 for (; x; x = TREE_CHAIN (x))
2630 size++;
2632 if (size == 0)
2633 return NULL_TREE;
2635 property_list_template =
2636 build_v2_property_list_template (objc_v2_property_template,
2637 size);
2639 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2640 is_proto ? context
2641 : klass_ctxt);
2643 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2644 if (is_proto)
2645 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2646 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2647 else
2648 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2649 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2651 decl = start_var_decl (property_list_template, buf);
2653 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2654 build_int_cst (NULL_TREE, init_val));
2655 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2656 build_int_cst (NULL_TREE, size));
2657 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2659 OBJCMETA (decl, objc_meta, meta_base);
2660 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2661 return decl;
2664 static tree
2665 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2666 tree inst_methods, tree class_methods,
2667 tree opt_ins_meth, tree opt_cls_meth,
2668 tree property_list, tree ext_meth_types,
2669 tree demangled_name, tree class_prop_list)
2671 tree expr, ttyp;
2672 location_t loc;
2673 vec<constructor_elt, va_gc> *inits = NULL;
2675 /* TODO: find a better representation of location from the inputs. */
2676 loc = UNKNOWN_LOCATION;
2678 /* This is NULL for the new ABI. */
2679 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2680 convert (objc_object_type, null_pointer_node));
2682 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2683 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2685 ttyp = objc_method_proto_list_ptr;
2686 if (inst_methods)
2687 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2688 else
2689 expr = convert (ttyp, null_pointer_node);
2690 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2692 if (class_methods)
2693 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2694 else
2695 expr = convert (ttyp, null_pointer_node);
2696 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2698 if (opt_ins_meth)
2699 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2700 else
2701 expr = convert (ttyp, null_pointer_node);
2702 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2704 if (opt_cls_meth)
2705 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2706 else
2707 expr = convert (ttyp, null_pointer_node);
2708 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2710 ttyp = objc_prop_list_ptr;
2711 if (property_list)
2712 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2713 else
2714 expr = convert (ttyp, null_pointer_node);
2715 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2717 /* const uint32_t size; = sizeof(struct protocol_t) */
2718 expr = build_int_cst (integer_type_node,
2719 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2720 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2721 /* const uint32_t flags; = 0 */
2722 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2724 ttyp = build_pointer_type (string_type_node);
2725 if (ext_meth_types)
2726 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, ext_meth_types, 0));
2727 else
2728 expr = convert (ttyp, null_pointer_node);
2729 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2731 ttyp = string_type_node;
2732 if (demangled_name)
2733 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, demangled_name, 0));
2734 else
2735 expr = convert (ttyp, null_pointer_node);
2736 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2738 ttyp = objc_prop_list_ptr;
2739 if (class_prop_list)
2740 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_prop_list, 0));
2741 else
2742 expr = convert (ttyp, null_pointer_node);
2743 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2745 return objc_build_constructor (type, inits);
2748 /* Main routine to build all meta data for all protocols used in a
2749 translation unit. */
2751 static void
2752 generate_v2_protocols (void)
2754 tree p ;
2755 bool some = false;
2757 if (!protocol_chain)
2758 return ;
2760 /* If a protocol was directly referenced, pull in indirect
2761 references. */
2762 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2763 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2764 generate_protocol_references (PROTOCOL_LIST (p));
2766 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2768 location_t loc;
2769 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2770 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2772 /* If protocol wasn't referenced, don't generate any code. */
2773 decl = PROTOCOL_FORWARD_DECL (p);
2775 if (!decl)
2776 continue;
2778 loc = DECL_SOURCE_LOCATION (decl);
2779 some = true;
2781 vec<tree> all_meths = vNULL;
2782 inst_meth =
2783 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2784 "_OBJC_ProtocolInstanceMethods",
2785 meta_proto_nst_meth, all_meths);
2787 class_meth =
2788 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2789 "_OBJC_ProtocolClassMethods",
2790 meta_proto_cls_meth, all_meths);
2792 opt_inst_meth =
2793 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2794 "_OBJC_ProtocolOptInstMethods",
2795 meta_proto_nst_meth, all_meths);
2797 opt_class_meth =
2798 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2799 "_OBJC_ProtocolOptClassMethods",
2800 meta_proto_cls_meth, all_meths);
2802 if (PROTOCOL_LIST (p))
2803 refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2804 else
2805 refs_decl = 0;
2807 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2808 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2810 if (refs_decl)
2811 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2812 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2813 else
2814 refs_expr = build_int_cst (NULL_TREE, 0);
2816 props = generate_v2_property_table (p, NULL_TREE);
2818 tree ext_meth_types
2819 = generate_v2_meth_type_list (all_meths, p,
2820 "_OBJC_ProtocolMethodTypes");
2821 tree demangled_name = NULL_TREE;
2822 tree class_prop_list = NULL_TREE;
2824 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2825 protocol_name_expr, refs_expr,
2826 inst_meth, class_meth,
2827 opt_inst_meth, opt_class_meth,
2828 props, ext_meth_types,
2829 demangled_name,class_prop_list);
2830 finish_var_decl (decl, initlist);
2831 objc_add_to_protocol_list (p, decl);
2832 all_meths.truncate (0);
2835 if (some)
2837 /* Make sure we get the Protocol class linked in - reference
2838 it... */
2839 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2840 /* ... but since we don't specifically use the reference... we
2841 need to force it. */
2842 DECL_PRESERVE_P (p) = 1;
2846 static tree
2847 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2849 tree decl, method_list_template, initlist;
2850 vec<constructor_elt, va_gc> *v = NULL;
2851 int size, init_val;
2853 if (!chain || !name || !(size = list_length (chain)))
2854 return NULL_TREE;
2856 method_list_template
2857 = build_v2_method_list_template (objc_method_template, size);
2858 initlist
2859 = build_dispatch_table_initializer (objc_method_template, chain);
2861 decl = start_var_decl (method_list_template, name);
2863 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2864 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2865 build_int_cst (integer_type_node, init_val));
2866 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2867 build_int_cst (integer_type_node, size));
2868 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2870 OBJCMETA (decl, objc_meta, attr);
2871 finish_var_decl (decl,
2872 objc_build_constructor (TREE_TYPE (decl), v));
2873 return decl;
2876 /* Init a category. */
2877 static tree
2878 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2879 tree inst_methods, tree class_methods,
2880 tree protocol_list, tree property_list,
2881 location_t loc)
2883 tree expr, ltyp;
2884 vec<constructor_elt, va_gc> *v = NULL;
2886 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2887 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2889 ltyp = objc_method_list_ptr;
2890 if (inst_methods)
2891 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2892 else
2893 expr = convert (ltyp, null_pointer_node);
2894 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2896 if (class_methods)
2897 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2898 else
2899 expr = convert (ltyp, null_pointer_node);
2900 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2902 /* protocol_list = */
2903 ltyp = build_pointer_type (objc_v2_protocol_template);
2904 if (protocol_list)
2905 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2906 else
2907 expr = convert (ltyp, null_pointer_node);
2908 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2910 ltyp = objc_prop_list_ptr;
2911 if (property_list)
2912 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2913 else
2914 expr = convert (ltyp, null_pointer_node);
2915 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2917 return objc_build_constructor (type, v);
2920 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2922 static void
2923 generate_v2_category (struct imp_entry *impent)
2925 tree initlist, cat_name_expr, class_name_expr;
2926 tree protocol_decl, category, props, t;
2927 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2928 tree cat = impent->imp_context;
2929 tree cat_decl = impent->class_decl;
2930 location_t loc;
2931 char buf[BUFSIZE];
2933 loc = DECL_SOURCE_LOCATION (cat_decl);
2935 /* ??? not sure this is really necessary, the following references should
2936 force appropriate linkage linkage...
2937 -- but ... ensure a reference to the class... */
2938 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2939 /* ... which we ignore so force it out.. */
2940 DECL_PRESERVE_P (t) = 1;
2942 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2943 class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2944 class_name_expr = build_fold_addr_expr (class_name_expr);
2946 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2947 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2949 if (category && CLASS_PROTOCOL_LIST (category))
2951 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2952 protocol_decl = generate_v2_protocol_list (category, cat);
2954 else
2955 protocol_decl = NULL_TREE;
2957 /* decl = update_var_decl(impent->class_decl); */
2959 props = generate_v2_property_table (NULL_TREE, cat);
2961 if (CLASS_NST_METHODS (cat))
2963 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2964 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2965 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2966 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2967 meta_cati_meth);
2970 if (CLASS_CLS_METHODS (cat))
2972 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2973 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2974 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2975 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2976 meta_catc_meth);
2979 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2980 cat_name_expr, class_name_expr,
2981 inst_methods, class_methods,
2982 protocol_decl, props, loc);
2984 finish_var_decl (cat_decl, initlist);
2985 impent->class_decl = cat_decl;
2987 /* Add to list of pointers in __category_list section. */
2988 objc_v2_add_to_category_list (cat_decl);
2989 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2990 objc_v2_add_to_nonlazy_category_list (cat_decl);
2993 /* This routine declares a variable to hold the offset for ivar
2994 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
2996 struct GTY(()) ivarref_entry
2998 tree decl;
2999 tree offset;
3002 static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
3004 static tree
3005 ivar_offset_ref (tree class_name, tree field_decl)
3007 tree decl, field_decl_id;
3008 ivarref_entry e;
3009 bool global_var;
3010 char buf[512];
3012 create_ivar_offset_name (buf, class_name, field_decl);
3013 field_decl_id = get_identifier (buf);
3015 if (ivar_offset_refs)
3017 int count;
3018 ivarref_entry *ref;
3019 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3020 if (DECL_NAME (ref->decl) == field_decl_id)
3021 return ref->decl;
3023 else
3024 /* Somewhat arbitrary initial provision. */
3025 vec_alloc (ivar_offset_refs, 32);
3027 /* We come here if we don't find a match or at the start. */
3028 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
3029 if (global_var)
3030 decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
3031 else
3032 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
3034 /* Identify so that we can indirect these where the ABI requires. */
3035 OBJCMETA (decl, objc_meta, meta_ivar_ref);
3037 e.decl = decl;
3038 e.offset = byte_position (field_decl);
3039 vec_safe_push (ivar_offset_refs, e);
3040 return decl;
3043 /* This routine builds initializer-list needed to initialize 'struct
3044 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
3045 'struct ivar_t' and FIELD_DECL is list of ivars for the target
3046 class. */
3048 static tree
3049 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
3051 vec<constructor_elt, va_gc> *inits = NULL;
3055 vec<constructor_elt, va_gc> *ivar = NULL;
3056 int val;
3057 tree id;
3059 /* Unnamed bitfields are ignored. */
3060 if (!DECL_NAME (field_decl))
3062 field_decl = DECL_CHAIN (field_decl);
3063 continue;
3066 /* Set offset. */
3067 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3068 build_unary_op (input_location,
3069 ADDR_EXPR,
3070 ivar_offset_ref (class_name,
3071 field_decl), 0));
3073 /* Set name. */
3074 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3075 add_objc_string (DECL_NAME (field_decl),
3076 meth_var_names));
3078 /* Set type. */
3079 id = add_objc_string (encode_field_decl (field_decl),
3080 meth_var_types);
3081 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
3083 /* Set alignment. */
3084 val = DECL_ALIGN_UNIT (field_decl);
3085 val = exact_log2 (val);
3086 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3087 build_int_cst (integer_type_node, val));
3089 /* Set size. */
3090 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
3091 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3092 build_int_cst (integer_type_node, val));
3094 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3095 objc_build_constructor (type, ivar));
3098 field_decl = DECL_CHAIN (field_decl);
3099 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
3101 while (field_decl);
3103 return objc_build_constructor (build_array_type (type, 0), inits);
3107 struct ivar_list_t
3109 uint32 entsize;
3110 uint32 count;
3111 struct iver_t list[count];
3115 static tree
3116 build_v2_ivar_list_t_template (tree list_type, int size)
3118 tree objc_ivar_list_record;
3119 tree decls, *chain = NULL;
3121 /* Anonymous. */
3122 objc_ivar_list_record = objc_start_struct (NULL_TREE);
3124 /* uint32 entsize; */
3125 decls = add_field_decl (integer_type_node, "entsize", &chain);
3127 /* uint32 count; */
3128 add_field_decl (integer_type_node, "count", &chain);
3130 /* struct objc_ivar ivar_list[]; */
3131 add_field_decl (build_sized_array_type (list_type, size),
3132 "list", &chain);
3134 objc_finish_struct (objc_ivar_list_record, decls);
3135 return objc_ivar_list_record;
3138 /* This routine declares a static variable of type 'struct
3139 ivar_list_t' and initializes it. chain is the source of the data,
3140 name is the name for the var. attr is the meta-data section tag
3141 attribute. templ is the implementation template for the class. */
3143 static tree
3144 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
3146 tree decl, initlist, ivar_list_template;
3147 vec<constructor_elt, va_gc> *inits = NULL;
3148 int size, ivar_t_size;
3150 if (!chain || !name || !(size = ivar_list_length (chain)))
3151 return NULL_TREE;
3153 generating_instance_variables = 1;
3154 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
3155 size);
3157 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
3158 objc_v2_ivar_template, chain);
3159 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
3161 decl = start_var_decl (ivar_list_template, name);
3162 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3163 build_int_cst (integer_type_node, ivar_t_size));
3164 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3165 build_int_cst (integer_type_node, size));
3166 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
3167 OBJCMETA (decl, objc_meta, attr);
3168 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
3169 generating_instance_variables = 0;
3170 return decl;
3173 /* Routine to build initializer list to initialize objects of type
3174 struct class_t; */
3176 static tree
3177 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
3178 tree ro, tree cache, tree vtable)
3180 vec<constructor_elt, va_gc> *initlist = NULL;
3182 /* isa */
3183 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
3185 /* superclass */
3186 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
3188 /* cache */
3189 if (cache)
3190 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
3191 else
3192 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3194 /* vtable */
3195 if (vtable)
3196 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
3197 else
3198 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3200 /* ro */
3201 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
3203 return objc_build_constructor (type, initlist);
3206 /* Routine to build object of struct class_ro_t { ... }; */
3208 static tree
3209 build_v2_class_ro_t_initializer (tree type, tree name,
3210 unsigned int flags, unsigned int instanceStart,
3211 unsigned int instanceSize,
3212 tree ivarLayout,
3213 tree baseMethods, tree baseProtocols,
3214 tree ivars, tree property_list)
3216 tree expr, unsigned_char_star, ltyp;
3217 location_t loc;
3218 vec<constructor_elt, va_gc> *initlist = NULL;
3220 /* TODO: fish out the real location from somewhere. */
3221 loc = UNKNOWN_LOCATION;
3223 /* flags */
3224 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3225 build_int_cst (integer_type_node, flags));
3227 /* instanceStart */
3228 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3229 build_int_cst (integer_type_node, instanceStart));
3231 /* instanceSize */
3232 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3233 build_int_cst (integer_type_node, instanceSize));
3235 /* This ABI is currently only used on m64 NeXT. We always
3236 explicitly declare the alignment padding. */
3237 /* reserved, pads alignment. */
3238 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3239 build_int_cst (integer_type_node, 0));
3241 /* ivarLayout */
3242 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3243 if (ivarLayout)
3244 expr = ivarLayout;
3245 else
3246 expr = convert (unsigned_char_star, null_pointer_node);
3247 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3249 /* name */
3250 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3252 /* baseMethods */
3253 ltyp = objc_method_list_ptr;
3254 if (baseMethods)
3255 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3256 else
3257 expr = convert (ltyp, null_pointer_node);
3258 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3260 /* baseProtocols */
3261 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3262 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3263 if (baseProtocols)
3264 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3265 else
3266 expr = convert (ltyp, null_pointer_node);
3267 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3269 /* ivars */
3270 ltyp = objc_v2_ivar_list_ptr;
3271 if (ivars)
3272 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3273 else
3274 expr = convert (ltyp, null_pointer_node);
3275 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3277 /* TODO: We don't yet have the weak/strong stuff... */
3278 /* weakIvarLayout */
3279 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3280 convert (unsigned_char_star, null_pointer_node));
3282 /* property list */
3283 ltyp = objc_prop_list_ptr;
3284 if (property_list)
3285 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3286 else
3287 expr = convert (ltyp, null_pointer_node);
3288 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3289 return objc_build_constructor (type, initlist);
3292 static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
3294 /* Record a name as needing a catcher. */
3295 static void
3296 objc_v2_add_to_ehtype_list (tree name)
3298 ident_data_tuple e;
3299 if (ehtype_list)
3301 int count = 0;
3302 ident_data_tuple *ref;
3304 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3305 if (ref->ident == name)
3306 return; /* Already entered. */
3308 else
3309 /* Arbitrary initial count. */
3310 vec_alloc (ehtype_list, 8);
3312 /* Not found, or new list. */
3313 e.ident = name;
3314 e.data = NULL_TREE;
3315 vec_safe_push (ehtype_list, e);
3318 static void
3319 generate_v2_class_structs (struct imp_entry *impent)
3321 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3322 tree field, firstIvar, chain;
3323 tree class_superclass_expr, metaclass_superclass_expr, props;
3324 /* TODO: figure out how to compute this. */
3325 tree ivarLayout = NULL_TREE;
3326 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3327 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3328 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3329 location_t loc;
3330 char buf[BUFSIZE];
3331 unsigned int instanceStart, instanceSize;
3332 unsigned int flags = 0x01; /* RO_META */
3333 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3334 : 0 ;
3336 class_decl = impent->class_decl;
3337 metaclass_decl = impent->meta_decl;
3338 loc = DECL_SOURCE_LOCATION (class_decl);
3340 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3341 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3342 #ifdef OBJCPLUS
3343 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3344 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3345 #endif
3347 /* Generation of data for meta class. */
3348 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3349 if (my_super_id)
3351 /* Compute reference to root's name. For a meta class, "isa" is
3352 a reference to the root class name. */
3353 tree my_root_id = my_super_id;
3354 tree my_root_int, interface;
3357 my_root_int = lookup_interface (my_root_id);
3359 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3360 my_root_id = CLASS_SUPER_NAME (my_root_int);
3361 else
3362 break;
3364 while (1);
3366 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3367 create extern if not already declared. */
3368 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3369 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3370 root_expr = create_extern_decl (objc_v2_class_template, buf);
3371 root_expr = build_fold_addr_expr (root_expr);
3373 /* Install class `isa' and `super' pointers at runtime. */
3374 interface = lookup_interface (my_super_id);
3375 gcc_assert (interface);
3376 /* Similarly, for OBJC_CLASS_$_<interface>... */
3377 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3378 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3379 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3380 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3381 /* ... and for OBJC_METACLASS_$_<interface>. */
3382 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3383 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3384 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3385 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3387 else
3389 /* Root class. */
3390 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3391 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3392 class_superclass_expr = build_int_cst (NULL_TREE, 0);
3393 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */
3396 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3398 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3399 protocol_decl = generate_v2_protocol_list (impent->imp_template,
3400 impent->imp_context);
3402 else
3403 protocol_decl = 0;
3405 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3406 class_names);
3408 if (CLASS_CLS_METHODS (impent->imp_context))
3410 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3411 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3412 class_methods =
3413 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3414 buf, meta_clac_meth);
3417 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3419 /* Currently there are no class ivars and generation of class
3420 variables for the root of the inheritance has been removed. It
3421 causes multiple defines if there are two root classes in the
3422 link, because each will define its own identically-named offset
3423 variable. */
3425 class_ivars = NULL_TREE;
3426 /* TODO: Add total size of class variables when implemented. */
3427 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3429 /* So now build the META CLASS structs. */
3430 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3432 decl = start_var_decl (objc_v2_class_ro_template,
3433 newabi_append_ro (IDENTIFIER_POINTER
3434 (DECL_NAME (metaclass_decl))));
3436 /* TODO: ivarLayout needs t be built. */
3437 initlist =
3438 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3439 (flags | cls_flags), instanceStart,
3440 instanceSize, ivarLayout,
3441 class_methods, protocol_decl,
3442 class_ivars, NULL_TREE);
3443 /* The ROs sit in the default const section. */
3444 OBJCMETA (decl, objc_meta, meta_base);
3445 finish_var_decl (decl, initlist);
3447 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3448 initlist =
3449 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3450 root_expr,
3451 metaclass_superclass_expr,
3452 build_fold_addr_expr (decl),
3453 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3454 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3455 /* The class section attributes are set when they are created. */
3456 finish_var_decl (metaclass_decl, initlist);
3457 impent->meta_decl = metaclass_decl;
3459 /* So now build the CLASS structs. */
3461 flags = 0x0; /* ... */
3462 if (!my_super_id)
3463 flags |= 0x02; /* RO_ROOT: this is a root class */
3465 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3466 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3468 if (objc2_objc_exception_attr (impent->imp_template))
3469 flags |= 0x20; /* RO_EXCEPTION */
3471 if (CLASS_NST_METHODS (impent->imp_context))
3473 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3474 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3475 inst_methods =
3476 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3477 buf, meta_clai_meth);
3480 /* Sort out the ivars before we try to compute the class sizes. */
3481 if ((chain = CLASS_IVARS (impent->imp_template)))
3483 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3484 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3485 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3486 impent->imp_template);
3489 /* Compute instanceStart. */
3490 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3491 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3492 if (my_super_id && field && TREE_CHAIN (field))
3493 field = TREE_CHAIN (field);
3495 firstIvar = field;
3497 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3498 firstIvar = TREE_CHAIN (firstIvar);
3500 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3502 /* Compute instanceSize. */
3503 while (field && TREE_CHAIN (field)
3504 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3505 field = TREE_CHAIN (field);
3507 if (field && TREE_CODE (field) == FIELD_DECL)
3508 instanceSize = int_byte_position (field) * BITS_PER_UNIT
3509 + tree_to_shwi (DECL_SIZE (field));
3510 else
3511 instanceSize = 0;
3512 instanceSize /= BITS_PER_UNIT;
3514 props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3516 /* If the class has no ivars, instanceStart should be set to the
3517 superclass's instanceSize. */
3518 instanceStart =
3519 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3520 : instanceSize;
3522 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3523 decl = start_var_decl (objc_v2_class_ro_template,
3524 newabi_append_ro (IDENTIFIER_POINTER
3525 (DECL_NAME (class_decl))));
3527 initlist =
3528 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3529 (flags | cls_flags), instanceStart,
3530 instanceSize, ivarLayout,
3531 inst_methods, protocol_decl,
3532 inst_ivars, props);
3533 /* The ROs sit in the default const section. */
3534 OBJCMETA (decl, objc_meta, meta_base);
3535 finish_var_decl (decl, initlist);
3537 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3538 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3539 build_fold_addr_expr (metaclass_decl),
3540 class_superclass_expr,
3541 build_fold_addr_expr (decl),
3542 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3543 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3545 /* The class section attributes are set when they are created. */
3546 finish_var_decl (class_decl, initlist);
3547 impent->class_decl = class_decl;
3549 objc_v2_add_to_class_list (class_decl);
3550 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3551 objc_v2_add_to_nonlazy_class_list (class_decl);
3553 if (flags & 0x20) /* RO_EXCEPTION */
3554 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3557 /* This routine outputs the (ivar_reference_offset, offset)
3558 tuples. */
3560 static void
3561 build_v2_ivar_offset_ref_table (void)
3563 int count;
3564 ivarref_entry *ref;
3566 if (!vec_safe_length (ivar_offset_refs))
3567 return;
3569 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3570 finish_var_decl (ref->decl, ref->offset);
3573 static void
3574 objc_generate_v2_next_metadata (void)
3576 struct imp_entry *impent;
3578 /* FIXME: Make sure that we generate no metadata if there is nothing
3579 to put into it. */
3581 gcc_assert (!objc_static_instances); /* Not for NeXT */
3583 build_metadata_templates ();
3585 for (impent = imp_list; impent; impent = impent->next)
3587 /* If -gen-decls is present, Dump the @interface of each class.
3588 TODO: Dump the classes in the order they were found, rather
3589 than in reverse order as we are doing now. */
3590 if (flag_gen_declaration)
3591 dump_interface (gen_declaration_file, impent->imp_context);
3593 /* all of the following reference the string pool... */
3594 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3595 generate_v2_class_structs (impent);
3596 else
3597 generate_v2_category (impent);
3600 build_next_selector_translation_table ();
3601 build_v2_message_ref_translation_table ();
3603 /* This will add "Protocol" to the class refs. */
3604 generate_v2_protocols ();
3606 build_v2_classrefs_table ();
3607 build_v2_super_classrefs_table (/*metaclass= */false);
3608 build_v2_super_classrefs_table (/*metaclass= */true);
3610 build_v2_ivar_offset_ref_table ();
3612 build_v2_protocol_list_translation_table ();
3613 build_v2_protocol_list_address_table ();
3615 build_v2_address_table (class_list, "_OBJC_ClassList$",
3616 meta_label_classlist);
3617 build_v2_address_table (category_list, "_OBJC_CategoryList$",
3618 meta_label_categorylist);
3619 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3620 meta_label_nonlazy_classlist);
3621 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3622 meta_label_nonlazy_categorylist);
3624 /* Generate catch objects for eh, if any are needed. */
3625 build_v2_eh_catch_objects ();
3627 /* Emit the string table last. */
3628 generate_strings ();
3631 /* NOTE --- Output NeXT V2 Exceptions --- */
3633 static GTY(()) tree objc_v2_ehtype_template;
3634 static GTY(()) tree next_v2_ehvtable_decl;
3635 static GTY(()) tree next_v2_EHTYPE_id_decl;
3637 static void
3638 build_v2_ehtype_template (void)
3640 tree decls, *chain = NULL;
3641 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3643 /* void *_objc_ehtype_vtable; */
3644 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3646 /* const char *className; */
3647 add_field_decl (string_type_node, "className", &chain);
3649 /* struct class_t *const cls; */
3650 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3652 objc_finish_struct (objc_v2_ehtype_template, decls);
3655 /* Template for the Objective-C family typeinfo type for ABI=2. This
3656 starts off the same as the gxx/cxx eh typeinfo.
3658 struct _objc_ehtype_t
3660 void *_objc_ehtype_vtable_ptr; - as per c++
3661 const char *className; - as per c++
3662 struct class_t *const cls;
3666 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3669 static tree
3670 objc2_build_ehtype_initializer (tree name, tree cls)
3672 vec<constructor_elt, va_gc> *initlist = NULL;
3673 tree addr, offs;
3675 /* This is done the same way as c++, missing the two first entries
3676 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3677 runtime source about this so, perhaps, this will change at some
3678 point. */
3679 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3680 if (!next_v2_ehvtable_decl)
3682 next_v2_ehvtable_decl =
3683 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3684 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3685 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3686 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3688 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3689 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3690 addr = fold_build_pointer_plus (addr, offs);
3692 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3694 /* className */
3695 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3697 /* cls */
3698 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3700 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3703 static tree
3704 build_ehtype (tree name, const char *eh_name, bool weak)
3706 tree name_expr, class_name_expr, ehtype_decl, inits;
3708 name_expr = add_objc_string (name, class_names);
3709 /* Extern ref. for the class. ??? Maybe we can look this up
3710 somewhere. */
3711 class_name_expr =
3712 create_extern_decl (objc_v2_class_template,
3713 objc_build_internal_classname (name, false));
3714 class_name_expr = build_fold_addr_expr (class_name_expr);
3715 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3716 if (weak)
3717 DECL_WEAK (ehtype_decl) = 1;
3718 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3719 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3720 finish_var_decl (ehtype_decl, inits);
3721 return ehtype_decl;
3724 /* This routine returns TRUE if CLS or any of its super classes has
3725 __attribute__ ((objc_exception)). */
3727 static bool
3728 objc2_objc_exception_attr (tree cls)
3730 while (cls)
3732 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3733 return true;
3734 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3737 return false;
3740 static bool
3741 is_implemented (tree name)
3743 struct imp_entry *t;
3744 for (t = imp_list; t; t = t->next)
3745 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3746 && CLASS_NAME (t->imp_template) == name)
3747 return true;
3749 return false;
3752 /* We will build catch objects:
3753 for any type implemented here.
3754 for any type used in a catch that has no exception attribute. */
3755 static void build_v2_eh_catch_objects (void)
3757 int count=0;
3758 ident_data_tuple *ref;
3760 if (!vec_safe_length (ehtype_list))
3761 return;
3763 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3765 char buf[BUFSIZE];
3766 bool impl = is_implemented (ref->ident);
3767 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3768 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3769 if (!impl && excpt)
3770 /* The User says this class has a catcher already. */
3771 ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3772 else
3773 /* Create a catcher, weak if it wasn't marked. */
3774 ref->data = build_ehtype (ref->ident, buf, !excpt);
3778 static tree
3779 lookup_ehtype_ref (tree id)
3781 int count=0;
3782 ident_data_tuple *ref;
3784 if (!vec_safe_length (ehtype_list))
3785 return NULL_TREE;
3787 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3788 if (ref->ident == id)
3789 return ref->data;
3790 return NULL_TREE;
3793 /* This hook, called via lang_eh_runtime_type, generates a runtime
3794 object which is either the address of the 'OBJC_EHTYPE_$_class'
3795 object or address of external OBJC_EHTYPE_id object. */
3796 static tree
3797 next_runtime_02_eh_type (tree type)
3799 tree t;
3801 if (type == error_mark_node
3802 /*|| errorcount || sorrycount*/)
3803 goto err_mark_in;
3805 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3807 if (!next_v2_EHTYPE_id_decl)
3809 /* This is provided by the Apple/NeXT libobjc.dylib so we
3810 need only to reference it. */
3811 next_v2_EHTYPE_id_decl =
3812 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3813 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3814 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3815 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3817 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3820 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3822 #ifdef OBJCPLUS
3823 /* This routine is also called for c++'s catch clause; in which
3824 case, we use c++'s typeinfo decl. */
3825 return build_eh_type_type (type);
3826 #else
3827 error ("non-objective-c type %qT cannot be caught", type);
3828 goto err_mark_in;
3829 #endif
3831 else
3832 t = OBJC_TYPE_NAME (TREE_TYPE (type));
3834 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3835 t = lookup_ehtype_ref (t);
3836 if (!t)
3837 goto err_mark_in;
3839 return build_fold_addr_expr (t);
3841 err_mark_in:
3842 return error_mark_node;
3845 static GTY(()) tree objc_eh_personality_decl;
3847 static tree
3848 objc_eh_personality (void)
3850 if (!objc_eh_personality_decl)
3851 objc_eh_personality_decl = build_personality_function ("objc");
3852 return objc_eh_personality_decl;
3855 /* NOTE --- interfaces --- */
3857 static tree
3858 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3860 tree t;
3861 if (rethrown)
3862 /* We have a separate re-throw entry. */
3863 t = build_function_call_vec (loc, vNULL, objc_rethrow_exception_decl,
3864 NULL, NULL);
3865 else
3867 /* Throw like the others... */
3868 vec<tree, va_gc> *parms;
3869 vec_alloc (parms, 1);
3870 parms->quick_push (throw_expr);
3871 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl,
3872 parms, 0);
3873 vec_free (parms);
3875 return add_stmt (t);
3878 /* Build __builtin_eh_pointer. */
3880 static tree
3881 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3883 tree t;
3884 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3885 t = build_call_expr (t, 1, integer_zero_node);
3886 return fold_convert (objc_object_type, t);
3889 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3890 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3892 tree t;
3894 /* Record the data for the catch in the try context so that we can
3895 finalize it later. Ellipsis is signalled by a NULL entry. */
3896 if (ellipsis)
3897 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3898 else
3899 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3900 (*cur_try_context)->current_catch = t;
3902 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3903 t = objc_build_exc_ptr (cur_try_context);
3904 t = convert (TREE_TYPE (decl), t);
3905 /* FIXME: location. */
3906 if (type && type != error_mark_node)
3908 t = build1(NOP_EXPR, ptr_type_node, t);
3909 t = build_function_call (input_location, objc2_begin_catch_decl,
3910 tree_cons (NULL_TREE, t, NULL_TREE));
3912 /* We might want to build a catch object for this (if it's not
3913 id). */
3914 if (POINTER_TYPE_P (type)
3915 && !objc_is_object_id (TREE_TYPE (type))
3916 && TYPED_OBJECT (TREE_TYPE (type)))
3917 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3919 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3922 /* try { catch-body } finally { objc_end_catch (); } */
3923 static void
3924 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3926 struct objc_try_context *ct;
3927 tree try_exp, func, *l, t ;
3928 location_t loc = (*cur_try_context)->try_locus;
3930 if (!curr_catch || curr_catch == error_mark_node)
3931 return;
3933 t = CATCH_BODY (curr_catch);
3934 if (TREE_CODE (t) == BIND_EXPR)
3936 /* Usual case of @catch (objc-expr). */
3937 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3938 BIND_EXPR_BODY (t) = NULL_TREE;
3939 l = &BIND_EXPR_BODY (t);
3941 else
3943 /* NULL entry, meaning @catch (...). */
3944 objc_begin_try_stmt (loc, t);
3945 CATCH_BODY (curr_catch) = NULL_TREE;
3946 l = &CATCH_BODY (curr_catch);
3949 /* Pick up the new context we made in begin_try above... */
3950 ct = *cur_try_context;
3951 func = build_function_call_vec (loc, vNULL, objc2_end_catch_decl, NULL,
3952 NULL);
3953 append_to_statement_list (func, &ct->finally_body);
3954 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3955 *cur_try_context = ct->outer;
3956 free (ct);
3957 append_to_statement_list (try_exp, l);
3958 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3961 static tree
3962 finish_try_stmt (struct objc_try_context **cur_try_context)
3964 struct objc_try_context *c = *cur_try_context;
3965 tree stmt = c->try_body;
3966 if (c->catch_list)
3967 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3968 if (c->finally_body)
3969 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3970 return stmt;
3973 #include "gt-objc-objc-next-runtime-abi-02.h"