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