1/* Next Runtime (ABI-2) private.
2 Copyright (C) 2011-2024 Free Software Foundation, Inc.
3
4 Contributed by Iain Sandoe and based, in part, on an implementation in
5 'branches/apple/trunk' contributed by Apple Computer Inc.
6
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 3, or (at your option)
12any later version.
13
14GCC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
22
23/* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
24
25 This version is intended to match (logically) the output of Apple's
26 4.2.1 compiler. */
27
28#include "config.h"
29#include "system.h"
30#include "coretypes.h"
31#include "tree.h"
32#include "stringpool.h"
33#include "attribs.h"
34
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"
44
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 */
51
52#include "target.h"
53#include "tree-iterator.h"
54#include "opts.h"
55
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"
60
61/* ABI 2 Private definitions. */
62#define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
63
64#define TAG_GETCLASS "objc_getClass"
65#define TAG_GETMETACLASS "objc_getMetaClass"
66
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"
73
74#define USE_FIXUP_BEFORE 100600
75#define TAG_FIXUP "_fixup"
76
77
78#define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
79#define TAG_V2_EH_TYPE "objc_ehtype_t"
80
81#define UTAG_V2_CLASS "_class_t"
82#define UTAG_V2_CLASS_RO "_class_ro_t"
83#define UTAG_V2_PROTOCOL "_protocol_t"
84#define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
85
86#define UTAG_V2_EH_TYPE "_objc_ehtype_t"
87
88#define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
89
90enum objc_v2_tree_index
91{
92 /* Templates. */
93 OCTI_V2_CLS_TEMPL,
94 OCTI_V2_CAT_TEMPL,
95 OCTI_V2_CLS_RO_TEMPL,
96 OCTI_V2_PROTO_TEMPL,
97 OCTI_V2_IVAR_TEMPL,
98 OCTI_V2_IVAR_LIST_TEMPL,
99 OCTI_V2_MESSAGE_REF_TEMPL,
100 OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
101
102 OCTI_V2_MESSAGE_SELECTOR_TYPE,
103 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
104 OCTI_V2_IMP_TYPE,
105 OCTI_V2_SUPER_IMP_TYPE,
106
107 OCTI_V2_CACHE_DECL,
108 OCTI_V2_VTABLE_DECL,
109
110 OCTI_V2_PROPERTY_TEMPL,
111
112 /* V2 messaging. */
113 OCTI_V2_UMSG_FIXUP_DECL,
114 OCTI_V2_UMSG_STRET_FIXUP_DECL,
115 OCTI_V2_UMSG_ID_FIXUP_DECL,
116 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
117 OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
118 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
119
120 /* Exceptions - related. */
121 OCTI_V2_BEGIN_CATCH_DECL,
122 OCTI_V2_END_CATCH_DECL,
123 OCTI_V2_RETHROW_DECL,
124
125 OCTI_V2_MAX
126};
127
128#define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
129#define objc_v2_class_ro_template \
130 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
131#define objc_v2_category_template \
132 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
133#define objc_v2_protocol_template \
134 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
135
136/* struct message_ref_t */
137#define objc_v2_message_ref_template \
138 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
139
140#define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
141
142/* struct super_message_ref_t */
143#define objc_v2_super_message_ref_template \
144 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
145
146/* struct message_ref_t* */
147#define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
148/* struct super_super_message_ref_t */
149#define objc_v2_super_selector_type \
150 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
151#define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
152#define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
153
154#define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
155#define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
156
157#define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
158#define objc_v2_property_template \
159 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
160
161/* V2 Messaging */
162
163/* objc_msgSend_fixup_rtp */
164#define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
165/* objc_msgSend_stret_fixup_rtp */
166#define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
167/* objc_msgSendId_fixup_rtp */
168#define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
169/* objc_msgSendId_stret_fixup_rtp */
170#define umsg_id_stret_fixup_decl \
171 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
172/* objc_msgSendSuper2_fixup_rtp */
173#define umsg_id_super2_fixup_decl \
174 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
175/* objc_msgSendSuper2_stret_fixup_rtp */
176#define umsg_id_super2_stret_fixup_decl \
177 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
178
179#define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
180#define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
181#define objc_rethrow_exception_decl \
182 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
183
184/* The OCTI_V2_... enumeration itself is in above. */
185static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
186
187static void next_runtime_02_initialize (void);
188
189static void build_v2_message_ref_templates (void);
190static void build_v2_class_templates (void);
191static void build_v2_super_template (void);
192static void build_v2_category_template (void);
193static void build_v2_protocol_template (void);
194
195static tree next_runtime_abi_02_super_superclassfield_id (void);
196
197static tree next_runtime_abi_02_class_decl (tree);
198static tree next_runtime_abi_02_metaclass_decl (tree);
199static tree next_runtime_abi_02_category_decl (tree);
200static tree next_runtime_abi_02_protocol_decl (tree);
201static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
202
203static tree next_runtime_abi_02_get_class_reference (tree);
204static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
205static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
206static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
207static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
208static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
209
210static tree next_runtime_abi_02_receiver_is_class_object (tree);
211static void next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **,
212 tree, int, int);
213static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
214 tree, tree, tree, int);
215static bool next_runtime_abi_02_setup_const_string_class_decl (void);
216static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
217
218static tree create_extern_decl (tree, const char *);
219
220static void objc_generate_v2_next_metadata (void);
221static bool objc2_objc_exception_attr (tree);
222
223/* void build_v2_protocol_reference (tree);*/
224static void build_v2_ehtype_template (void);
225static void build_v2_eh_catch_objects (void);
226static tree next_runtime_02_eh_type (tree);
227static tree objc_eh_personality (void);
228static tree build_throw_stmt (location_t, tree, bool);
229static tree objc_build_exc_ptr (struct objc_try_context **);
230static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
231static void finish_catch (struct objc_try_context **, tree);
232static tree finish_try_stmt (struct objc_try_context **);
233
234/* TODO: Use an objc-map. */
235static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
236
237bool
238objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
239{
240 extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
241
242 if (flag_objc_sjlj_exceptions)
243 {
244 inform (UNKNOWN_LOCATION,
245 "%<-fobjc-sjlj-exceptions%> is ignored for "
246 "%<-fnext-runtime%> when %<-fobjc-abi-version%> "
247 "greater than 1");
248 flag_objc_sjlj_exceptions = 0;
249 }
250
251 /* NeXT ABI 2 is intended to default to checking for nil receivers. */
252 if (! OPTION_SET_P (flag_objc_nilcheck))
253 flag_objc_nilcheck = 1;
254
255 rthooks->initialize = next_runtime_02_initialize;
256 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
257 rthooks->tag_getclass = TAG_GETCLASS;
258 rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
259
260 rthooks->class_decl = next_runtime_abi_02_class_decl;
261 rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
262 rthooks->category_decl = next_runtime_abi_02_category_decl;
263 rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
264 rthooks->string_decl = next_runtime_abi_02_string_decl;
265
266 rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
267 rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
268 rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
269 rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
270 rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
271 rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
272
273 rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
274 rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
275 rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
276
277 rthooks->setup_const_string_class_decl =
278 next_runtime_abi_02_setup_const_string_class_decl;
279 rthooks->build_const_string_constructor =
280 next_runtime_abi_02_build_const_string_constructor;
281
282 rthooks->build_throw_stmt = build_throw_stmt;
283 rthooks->build_exc_ptr = objc_build_exc_ptr;
284 rthooks->begin_catch = begin_catch;
285 rthooks->finish_catch = finish_catch;
286 rthooks->finish_try_stmt = finish_try_stmt;
287
288 rthooks->generate_metadata = objc_generate_v2_next_metadata;
289 return true;
290}
291
292/* We need a way to convey what kind of meta-data are represented by a given
293 variable, since each type is expected (by the runtime) to be found in a
294 specific named section. The solution must be usable with LTO.
295
296 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
297 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
298 identification attributes in the front end. The back-end may choose to act
299 on these as it requires. */
300
301static void
302next_runtime_abi_02_init_metadata_attributes (void)
303{
304 if (!objc_meta)
305 objc_meta = get_identifier ("OBJC2META");
306
307 if (!meta_base)
308 meta_base = get_identifier ("V2_BASE");
309
310 meta_class = get_identifier ("G2_CLAS");
311 meta_metaclass = get_identifier ("G2_META");
312 meta_category = meta_base;
313 meta_protocol = get_identifier ("V2_PCOL");
314
315 meta_clac_vars =
316 meta_clai_vars = meta_base;
317
318 meta_clac_meth =
319 meta_clai_meth =
320 meta_catc_meth =
321 meta_cati_meth =
322 meta_proto_cls_meth =
323 meta_proto_nst_meth = meta_base;
324
325 meta_clas_prot =
326 meta_catg_prot = meta_base;
327
328 meta_sel_refs = get_identifier ("V2_SRFS");
329
330 meta_class_name = get_identifier ("V2_CNAM");
331 meta_meth_name = get_identifier ("V2_MNAM");
332
333 meta_meth_type = get_identifier ("V2_MTYP");
334 meta_prop_name_attr = get_identifier ("V2_STRG");
335
336 meta_mref = get_identifier ("V2_MREF");
337 meta_class_ref = get_identifier ("V2_CLRF");
338 meta_superclass_ref = get_identifier ("V2_SURF");
339
340 meta_label_classlist = get_identifier ("V2_CLAB");
341 meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
342 meta_label_categorylist = get_identifier ("V2_CALA");
343 meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
344
345 meta_label_protocollist = get_identifier ("V2_PLST");
346 meta_proto_ref = get_identifier ("V2_PRFS");
347
348 meta_info = get_identifier ("V2_INFO");
349
350 meta_ehtype = get_identifier ("V2_EHTY");
351
352 meta_const_str = get_identifier ("V2_CSTR");
353
354 meta_ivar_ref = get_identifier ("V2_IVRF");
355}
356
357static void next_runtime_02_initialize (void)
358{
359 tree type;
360#ifdef OBJCPLUS
361 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
362 default. */
363 if (!OPTION_SET_P (flag_objc_call_cxx_cdtors))
364 global_options.x_flag_objc_call_cxx_cdtors = 1;
365#endif
366
367 /* Set up attributes to be attached to the meta-data so that they
368 will be placed in the correct sections. */
369 next_runtime_abi_02_init_metadata_attributes ();
370
371 /* `struct objc_selector *' */
372 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
373 get_identifier (TAG_SELECTOR)));
374
375 /* SEL typedef. */
376 type = lang_hooks.decls.pushdecl (build_decl (input_location,
377 TYPE_DECL,
378 objc_selector_name,
379 objc_selector_type));
380 suppress_warning (type);
381
382 /* IMP : id (*) (id, _message_ref_t*, ...)
383 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
384 objc_v2_selector_type. */
385 build_v2_message_ref_templates ();
386
387 objc_v2_ivar_list_ptr =
388 build_pointer_type (xref_tag (RECORD_TYPE,
389 get_identifier ("_ivar_list_t")));
390
391 objc_prop_list_ptr =
392 build_pointer_type (xref_tag (RECORD_TYPE,
393 get_identifier ("_prop_list_t")));
394
395 build_v2_class_templates ();
396 build_v2_super_template ();
397 build_v2_protocol_template ();
398 build_v2_category_template ();
399
400 bool fixup_p = flag_next_runtime < USE_FIXUP_BEFORE;
401 if (fixup_p)
402 {
403 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
404 type = build_varargs_function_type_list (objc_object_type,
405 objc_object_type,
406 objc_v2_selector_type,
407 NULL_TREE);
408 }
409 else
410 {
411 /* id objc_msgSendXXXX (id, SEL, ...); */
412 type = build_varargs_function_type_list (objc_object_type,
413 objc_object_type,
414 objc_selector_type,
415 NULL_TREE);
416 }
417 const char *fnam = fixup_p ? TAG_MSGSEND TAG_FIXUP : TAG_MSGSEND;
418 umsg_fixup_decl = add_builtin_function (name: fnam, type, function_code: 0, cl: NOT_BUILT_IN,
419 NULL, NULL_TREE);
420 TREE_NOTHROW (umsg_fixup_decl) = 0;
421
422 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
423 fnam = fixup_p ? TAG_MSGSEND_STRET TAG_FIXUP : TAG_MSGSEND_STRET;
424 umsg_stret_fixup_decl = add_builtin_function (name: fnam, type, function_code: 0, cl: NOT_BUILT_IN,
425 NULL, NULL_TREE);
426 TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
427
428 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
429 fnam = fixup_p ? TAG_MSGSENDID TAG_FIXUP : TAG_MSGSENDID;
430 umsg_id_fixup_decl = add_builtin_function (name: fnam, type, function_code: 0, cl: NOT_BUILT_IN,
431 NULL, NULL_TREE);
432 TREE_NOTHROW (umsg_id_fixup_decl) = 0;
433
434 /* id objc_msgSendId_stret_fixup_rtp (id, struct message_ref_t*, ...); */
435 fnam = fixup_p ? TAG_MSGSENDID_STRET TAG_FIXUP : TAG_MSGSENDID_STRET;
436 umsg_id_stret_fixup_decl = add_builtin_function (name: fnam, type, function_code: 0, cl: NOT_BUILT_IN,
437 NULL, NULL_TREE);
438 TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
439
440 /* id objc_msgSendSuper2_fixup_rtp
441 (struct objc_super *, struct message_ref_t*, ...); */
442 type = build_varargs_function_type_list (objc_object_type,
443 objc_super_type,
444 objc_v2_super_selector_type,
445 NULL_TREE);
446 fnam = fixup_p ? TAG_MSGSENDSUPER TAG_FIXUP : TAG_MSGSENDSUPER;
447 umsg_id_super2_fixup_decl = add_builtin_function (name: fnam, type, function_code: 0, cl: NOT_BUILT_IN,
448 NULL, NULL_TREE);
449 TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
450
451 /* id objc_msgSendSuper2_stret_fixup_rtp
452 (struct objc_super *, struct message_ref_t*, ...); */
453 fnam = fixup_p ? TAG_MSGSENDSUPER_STRET TAG_FIXUP : TAG_MSGSENDSUPER_STRET;
454 umsg_id_super2_stret_fixup_decl = add_builtin_function (name: fnam, type, function_code: 0,
455 cl: NOT_BUILT_IN, NULL,
456 NULL_TREE);
457 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
458
459 /* Present in the library, but unused by the FE. */
460 /* Protocol *objc_getProtocol (const char *)
461 type = build_function_type_list (objc_protocol_type,
462 const_string_type_node,
463 NULL_TREE);
464 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
465 type, 0, NOT_BUILT_IN,
466 NULL, NULL_TREE);
467 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
468
469 UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
470 "_objc_empty_cache");
471
472 UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
473 "_objc_empty_vtable");
474
475 /* id objc_getClass (const char *); */
476 type = build_function_type_list (objc_object_type,
477 const_string_type_node,
478 NULL_TREE);
479 objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
480 type, function_code: 0, cl: NOT_BUILT_IN,
481 NULL, NULL_TREE);
482
483 /* id objc_getMetaClass (const char *); */
484 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
485 type, function_code: 0, cl: NOT_BUILT_IN,
486 NULL, NULL_TREE);
487
488 /* This is the type of all of the following functions
489 objc_copyStruct(). */
490 type = build_function_type_list (void_type_node,
491 ptr_type_node,
492 const_ptr_type_node,
493 ptrdiff_type_node,
494 boolean_type_node,
495 boolean_type_node,
496 NULL_TREE);
497 /* Declare the following function:
498 void
499 objc_copyStruct (void *destination, const void *source,
500 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
501 objc_copyStruct_decl = add_builtin_function (name: "objc_copyStruct",
502 type, function_code: 0, cl: NOT_BUILT_IN,
503 NULL, NULL_TREE);
504 TREE_NOTHROW (objc_copyStruct_decl) = 0;
505 objc_getPropertyStruct_decl = NULL_TREE;
506 objc_setPropertyStruct_decl = NULL_TREE;
507
508 gcc_checking_assert (!flag_objc_sjlj_exceptions);
509
510 /* Although we warn that fobjc-exceptions is required for exceptions
511 code, we carry on and create it anyway. */
512
513 /* This can be required, even when exceptions code is not present,
514 when an __attribute__((objc_exception)) is applied to a
515 class. */
516 build_v2_ehtype_template ();
517
518 /* void * objc_begin_catch (void *) */
519 type = build_function_type_list (ptr_type_node,
520 ptr_type_node, NULL_TREE);
521
522 objc2_begin_catch_decl = add_builtin_function (name: "objc_begin_catch",
523 type, function_code: 0, cl: NOT_BUILT_IN,
524 NULL, NULL_TREE);
525 TREE_NOTHROW (objc2_begin_catch_decl) = 0;
526
527 /* void objc_end_catch () */
528 type = build_function_type_list (void_type_node, NULL_TREE);
529 objc2_end_catch_decl = add_builtin_function (name: "objc_end_catch",
530 type, function_code: 0, cl: NOT_BUILT_IN,
531 NULL, NULL_TREE);
532 TREE_NOTHROW (objc2_end_catch_decl) = 0;
533
534 /* void objc_exception_rethrow (void) */
535 objc_rethrow_exception_decl =
536 add_builtin_function (name: "objc_exception_rethrow",
537 type, function_code: 0, cl: NOT_BUILT_IN,
538 NULL, NULL_TREE);
539 TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
540 using_eh_for_cleanups ();
541 lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
542 lang_hooks.eh_personality = objc_eh_personality;
543}
544
545/* NOTE --- templates --- */
546
547/* Set 'objc_v2_message_ref_template' to the data type node for
548 'struct _message_ref_t'. This needs to be done just once per
549 compilation. Also Set 'objc_v2_super_message_ref_template' to data
550 type node for 'struct _super_message_ref_t'. */
551
552/* struct _message_ref_t
553 {
554 IMP messenger;
555 SEL name;
556 };
557 where IMP is: id (*) (id, _message_ref_t*, ...)
558*/
559
560/* struct _super_message_ref_t
561 {
562 SUPER_IMP messenger;
563 SEL name;
564 };
565 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
566*/
567
568static void
569build_v2_message_ref_templates (void)
570{
571 tree ptr_message_ref_t;
572 tree decls, *chain = NULL;
573
574 /* struct _message_ref_t {...} */
575 objc_v2_message_ref_template =
576 objc_start_struct (get_identifier ("_message_ref_t"));
577
578 /* IMP messenger; */
579 ptr_message_ref_t =
580 build_pointer_type (xref_tag (RECORD_TYPE,
581 get_identifier ("_message_ref_t")));
582
583 objc_v2_imp_type =
584 build_pointer_type (build_function_type_list
585 (objc_object_type,
586 objc_object_type,
587 ptr_message_ref_t,
588 NULL_TREE));
589
590 decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
591
592 /* SEL name; */
593 add_field_decl (objc_selector_type, "name", &chain);
594
595 objc_finish_struct (objc_v2_message_ref_template, decls);
596
597 objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
598
599 chain = NULL;
600 /* struct _super_message_ref_t {...} */
601 objc_v2_super_message_ref_template =
602 objc_start_struct (get_identifier ("_super_message_ref_t"));
603
604 /* SUPER_IMP messenger; */
605 ptr_message_ref_t = build_pointer_type
606 (xref_tag (RECORD_TYPE,
607 get_identifier ("_super_message_ref_t")));
608
609 objc_v2_super_imp_type =
610 build_pointer_type (build_function_type_list
611 (objc_object_type,
612 objc_super_type,
613 ptr_message_ref_t,
614 NULL_TREE));
615
616 add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
617
618 /* SEL name; */
619 add_field_decl (objc_selector_type, "name", &chain);
620
621 objc_finish_struct (objc_v2_super_message_ref_template, decls);
622 objc_v2_super_selector_type =
623 build_pointer_type (objc_v2_super_message_ref_template);
624}
625
626/* Build following types which represent each class implementation.
627
628struct class_ro_t
629{
630 uint32_t const flags;
631 uint32_t const instanceStart;
632 uint32_t const instanceSize;
633#ifdef __LP64__
634 uint32_t const reserved;
635#endif
636 const uint8_t * const ivarLayout;
637 const char *const name;
638 const struct method_list_t * const baseMethods;
639 const struct objc_protocol_list *const baseProtocols;
640 const struct ivar_list_t *const ivars;
641 const uint8_t * const weakIvarLayout;
642 const struct _prop_list_t * const properties;
643};
644
645struct class_t
646{
647 struct class_t *isa;
648 struct class_t *superclass;
649 void *cache;
650 IMP *vtable;
651
652 ...When this is active - it will point to a rw version, but
653 when we build the meta-data we point it to the ro...
654 struct class_ro_t *data;
655};
656
657*/
658
659static void
660build_v2_class_templates (void)
661{
662 tree cnst_strg_type;
663 tree decls, *chain = NULL;
664
665 /* struct class_ro_t {...} */
666 objc_v2_class_ro_template =
667 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
668
669 /* uint32_t const flags; */
670 decls = add_field_decl (integer_type_node, "flags", &chain);
671
672 /* uint32_t const instanceStart; */
673 add_field_decl (integer_type_node, "instanceStart", &chain);
674
675 /* uint32_t const instanceSize; */
676 add_field_decl (integer_type_node, "instanceSize", &chain);
677
678 /* This ABI is currently only used on m64 NeXT. We always
679 explicitly declare the alignment padding. */
680 /* uint32_t const reserved; */
681 add_field_decl (integer_type_node, "reserved", &chain);
682
683 /* const uint8_t * const ivarLayout; */
684 cnst_strg_type = build_pointer_type (unsigned_char_type_node);
685 add_field_decl (cnst_strg_type, "ivarLayout", &chain);
686
687 /* const char *const name; */
688 add_field_decl (string_type_node, "name", &chain);
689
690 /* const struct method_list_t * const baseMethods; */
691 add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
692
693 /* const struct objc_protocol_list *const baseProtocols; */
694 add_field_decl (build_pointer_type
695 (xref_tag (RECORD_TYPE,
696 get_identifier (UTAG_V2_PROTOCOL_LIST))),
697 "baseProtocols", &chain);
698
699 /* const struct ivar_list_t *const ivars; */
700 add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
701
702 /* const uint8_t * const weakIvarLayout; */
703 add_field_decl (cnst_strg_type, "weakIvarLayout", &chain);
704
705 /* struct _prop_list_t * baseProperties; */
706 add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
707
708 objc_finish_struct (objc_v2_class_ro_template, decls);
709
710 chain = NULL;
711 /* struct class_t {...} */
712 objc_v2_class_template =
713 objc_start_struct (get_identifier (UTAG_V2_CLASS));
714
715 /* struct class_t *isa; */
716 decls = add_field_decl (build_pointer_type (objc_v2_class_template),
717 "isa", &chain);
718
719 /* struct class_t * const superclass; */
720 add_field_decl (build_pointer_type (objc_v2_class_template),
721 "superclass", &chain);
722
723 /* void *cache; */
724 add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
725
726 /* IMP *vtable; */
727 add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
728
729 /* struct class_ro_t *ro; */
730 add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
731
732 objc_finish_struct (objc_v2_class_template, decls);
733}
734
735/* struct _objc_super
736 {
737 struct _objc_object *self;
738 Class cls;
739 }; */
740void
741build_v2_super_template (void)
742{
743 tree decls, *chain = NULL;
744
745 objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
746
747 /* struct _objc_object *self; */
748 decls = add_field_decl (objc_object_type, "self", &chain);
749
750 /* Class cls; */
751 add_field_decl (objc_class_type, "cls", &chain);
752
753 objc_finish_struct (objc_super_template, decls);
754}
755
756/* struct protocol_t
757 {
758 Class isa;
759 const char * const protocol_name;
760 const struct protocol_list_t * const protocol_list;
761 const struct method_list_t * const instance_methods;
762 const struct method_list_t * const class_methods;
763 const struct method_list_t * optionalInstanceMethods;
764 const struct method_list_t * optionalClassMethod
765 const struct _prop_list_t * const properties;
766 const uint32_t size;
767 const uint32_t flags;
768 const char ** extended_method_types;
769 const char * demangled_name;
770 const struct _prop_list_t * class_properties;
771 }
772*/
773static void
774build_v2_protocol_template (void)
775{
776 tree decls, *chain = NULL;
777
778 objc_v2_protocol_template =
779 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
780
781 /* Class isa; */
782 decls = add_field_decl (objc_object_type, "isa", &chain);
783
784 /* char *protocol_name; */
785 add_field_decl (string_type_node, "protocol_name", &chain);
786
787 /* const struct protocol_list_t * const protocol_list; */
788 add_field_decl (build_pointer_type (objc_v2_protocol_template),
789 "protocol_list", &chain);
790
791 /* const struct method_list_t * const instance_methods; */
792 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
793
794 /* const struct method_list_t * const class_methods; */
795 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
796
797 /* const struct method_list_t * optionalInstanceMethods; */
798 add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
799
800 /* const struct method_list_t * optionalClassMethods; */
801 add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
802
803 /* struct _prop_list_t * properties; */
804 add_field_decl (objc_prop_list_ptr, "properties", &chain);
805
806 /* const uint32_t size; */
807 add_field_decl (integer_type_node, "size", &chain);
808
809 /* const uint32_t flags; */
810 add_field_decl (integer_type_node, "flags", &chain);
811
812 /* const char **extendedMethodTypes; */
813 tree ptr_to_ptr_to_char = build_pointer_type (string_type_node);
814 add_field_decl (ptr_to_ptr_to_char, "extended_method_types", &chain);
815
816 /* const char *demangledName; */
817 add_field_decl (string_type_node, "demangled_name", &chain);
818
819 /* const struct _prop_list_t *class_properties; */
820 add_field_decl (objc_prop_list_ptr, "class_properties", &chain);
821
822 objc_finish_struct (objc_v2_protocol_template, decls);
823}
824
825/* Build type for a category:
826 struct category_t
827 {
828 const char * const name;
829 struct class_t *const cls;
830 const struct method_list_t * const instance_methods;
831 const struct method_list_t * const class_methods;
832 const struct protocol_list_t * const protocols;
833 const struct _prop_list_t * const properties;
834 }
835*/
836
837static void
838build_v2_category_template (void)
839{
840 tree decls, *chain = NULL;
841
842 objc_v2_category_template =
843 objc_start_struct (get_identifier ("_category_t"));
844
845 /* char *name; */
846 decls = add_field_decl (string_type_node, "name", &chain);
847
848 /* struct class_t *const cls; */
849 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
850
851 /* struct method_list_t *instance_methods; */
852 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
853
854 /* struct method_list_t *class_methods; */
855 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
856
857 /* struct protocol_list_t *protocol_list; */
858 add_field_decl (build_pointer_type (objc_v2_protocol_template),
859 "protocol_list", &chain );
860
861 /* struct _prop_list_t * properties; */
862 add_field_decl (objc_prop_list_ptr, "properties", &chain);
863
864 objc_finish_struct (objc_v2_category_template, decls);
865}
866
867/* NOTE --- Decls, Identifiers, Names etc. --- */
868
869/* This routine is given a name and returns a matching extern variable
870 if one is found. */
871
872static tree
873hash_name_lookup (hash *hashlist, tree name)
874{
875 hash target;
876
877 target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
878
879 while (target)
880 {
881 if (name == DECL_NAME (target->key))
882 return target->key;
883
884 target = target->next;
885 }
886 return 0;
887}
888
889/* This routine is given an extern variable and enters it in its hash
890 table. Note that hashing is done on its inner IDENTIFIER_NODE
891 node. */
892
893static void
894hash_name_enter (hash *hashlist, tree id)
895{
896 hash obj;
897 int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
898
899 obj = ggc_alloc<hashed_entry> ();
900 obj->list = 0;
901 obj->next = hashlist[slot];
902 obj->key = id;
903
904 hashlist[slot] = obj; /* append to front */
905}
906
907/* Create a declaration "extern <type> <name>;"
908 The var will need to be finalized (e.g. by calling finish_var_decl()). */
909
910static tree
911create_extern_decl (tree type, const char *name)
912{
913 tree id = get_identifier (name);
914 tree var = hash_name_lookup (hashlist: extern_names, name: id);
915 if (var)
916 return var;
917 /* New name. */
918 var = start_var_decl (type, name);
919 TREE_STATIC (var) = 0;
920 DECL_EXTERNAL (var) = 1;
921 TREE_PUBLIC (var) = 1;
922 hash_name_enter (hashlist: extern_names, id: var);
923 return var;
924}
925
926/* Create a globally visible definition for variable NAME of a given TYPE. The
927 finish_var_decl() routine will need to be called on it afterwards. */
928static tree
929create_global_decl (tree type, const char *name, bool is_def = false);
930
931static tree
932create_global_decl (tree type, const char *name, bool is_def)
933{
934 tree id = get_identifier (name);
935 tree var = hash_name_lookup (hashlist: extern_names, name: id);
936 if (var)
937 is_def = true;
938 else
939 {
940 var = start_var_decl (type, name);
941 hash_name_enter (hashlist: extern_names, id: var);
942 }
943 if (is_def)
944 {
945 DECL_EXTERNAL (var) = 0;
946 TREE_STATIC (var) = 1;
947 }
948 TREE_PUBLIC (var) = 1;
949 return var;
950}
951
952/* Create a symbol with __attribute__ ((visibility ("hidden")))
953 attribute (private extern). */
954static tree
955create_hidden_decl (tree type, const char *name, bool is_def = false);
956
957static tree
958create_hidden_decl (tree type, const char *name, bool is_def)
959{
960 tree decl = create_global_decl (type, name, is_def);
961 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
962 DECL_VISIBILITY_SPECIFIED (decl) = 1;
963 return decl;
964}
965
966/* Irritatingly, we have a different superclass field name for ABI=2. */
967/* PS/TODO: The field name does not matter, it is only used internally
968 by the compiler. We can rename it to whatever we want. ;-) */
969
970static tree
971next_runtime_abi_02_super_superclassfield_id (void)
972{
973 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
974 most look it once at startup then always return it. */
975 if (!super_superclassfield_id)
976 super_superclassfield_id = get_identifier ("cls");
977 return super_superclassfield_id;
978}
979
980static tree
981next_runtime_abi_02_class_decl (tree klass)
982{
983 tree decl;
984 char buf[BUFSIZE];
985 snprintf (s: buf, BUFSIZE, format: "OBJC_CLASS_$_%s",
986 IDENTIFIER_POINTER (CLASS_NAME (klass)));
987 /* ObjC2 classes are extern visible. */
988 decl = create_global_decl (objc_v2_class_template, name: buf);
989 OBJCMETA (decl, objc_meta, meta_class);
990 return decl;
991}
992
993static tree
994next_runtime_abi_02_metaclass_decl (tree klass)
995{
996 tree decl;
997 char buf[BUFSIZE];
998 snprintf (s: buf, BUFSIZE, format: "OBJC_METACLASS_$_%s",
999 IDENTIFIER_POINTER (CLASS_NAME (klass)));
1000 /* ObjC2 classes are extern visible. */
1001 decl = create_global_decl (objc_v2_class_template, name: buf);
1002 OBJCMETA (decl, objc_meta, meta_metaclass);
1003 return decl;
1004}
1005
1006static tree
1007next_runtime_abi_02_category_decl (tree klass)
1008{
1009 tree decl;
1010 char buf[BUFSIZE];
1011 snprintf (s: buf, BUFSIZE, format: "_OBJC_Category_%s_%s",
1012 IDENTIFIER_POINTER (CLASS_NAME (klass)),
1013 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)));
1014 decl = start_var_decl (objc_v2_category_template, buf);
1015 OBJCMETA (decl, objc_meta, meta_category);
1016 return decl;
1017}
1018
1019static tree
1020next_runtime_abi_02_protocol_decl (tree p)
1021{
1022 tree decl;
1023 char buf[BUFSIZE];
1024
1025 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
1026 snprintf (s: buf, BUFSIZE, format: "_OBJC_Protocol_%s",
1027 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
1028 if (flag_next_runtime >= USE_FIXUP_BEFORE)
1029 {
1030 decl = create_hidden_decl (objc_v2_protocol_template, name: buf);
1031 DECL_WEAK (decl) = true;
1032 }
1033 else
1034 decl = start_var_decl (objc_v2_protocol_template, buf);
1035 OBJCMETA (decl, objc_meta, meta_protocol);
1036 DECL_PRESERVE_P (decl) = 1;
1037 return decl;
1038}
1039
1040static tree
1041next_runtime_abi_02_string_decl (tree type, const char *name, string_section where)
1042{
1043 tree var = start_var_decl (type, name);
1044 switch (where)
1045 {
1046 case class_names:
1047 OBJCMETA (var, objc_meta, meta_class_name);
1048 break;
1049 case meth_var_names:
1050 OBJCMETA (var, objc_meta, meta_meth_name);
1051 break;
1052 case meth_var_types:
1053 OBJCMETA (var, objc_meta, meta_meth_type);
1054 break;
1055 case prop_names_attr:
1056 OBJCMETA (var, objc_meta, meta_prop_name_attr);
1057 break;
1058 default:
1059 OBJCMETA (var, objc_meta, meta_base);
1060 break;
1061 }
1062 return var;
1063}
1064
1065/* NOTE --- entry --- */
1066
1067struct GTY(()) ident_data_tuple {
1068 tree ident;
1069 tree data;
1070};
1071
1072/* This routine creates a file scope static variable of type 'Class'
1073 to hold the address of a class. */
1074
1075static tree
1076build_v2_class_reference_decl (tree ident)
1077{
1078 tree decl;
1079 char buf[BUFSIZE];
1080
1081 snprintf (s: buf, BUFSIZE, format: "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1082 decl = start_var_decl (objc_class_type, buf);
1083 OBJCMETA (decl, objc_meta, meta_class_ref);
1084 return decl;
1085}
1086
1087/* This routine builds a class refs entry for each class name used.
1088 Initially, a (static-ref, IDENT) tuple is added to the list. The
1089 ident is replaced with address of the class metadata (of type
1090 'Class') in the output routine. */
1091
1092static GTY (()) vec<ident_data_tuple, va_gc> *classrefs;
1093
1094static tree
1095objc_v2_get_class_reference (tree ident)
1096{
1097 tree decl;
1098 ident_data_tuple e;
1099 if (classrefs)
1100 {
1101 int count;
1102 ident_data_tuple *ref;
1103 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1104 {
1105 if (ref->ident == ident)
1106 {
1107 if (!ref->data)
1108 ref->data = build_v2_class_reference_decl (ident);
1109 return ref->data;
1110 }
1111 }
1112 }
1113 else
1114 /* Somewhat arbitrary initial provision. */
1115 vec_alloc (v&: classrefs, nelems: 16);
1116
1117 /* We come here if we don't find the entry - or if the table was yet
1118 to be created. */
1119 decl = build_v2_class_reference_decl (ident);
1120 e.ident = ident;
1121 e.data = decl;
1122 vec_safe_push (v&: classrefs, obj: e);
1123 return decl;
1124}
1125
1126static tree
1127next_runtime_abi_02_get_class_reference (tree ident)
1128{
1129 if (!flag_zero_link)
1130 return objc_v2_get_class_reference (ident);
1131 else
1132 {
1133 /* We fall back to using objc_getClass (). */
1134 vec<tree, va_gc> *v;
1135 vec_alloc (v, nelems: 1);
1136 tree t;
1137 /* ??? add_class_reference (ident); - is pointless, since the
1138 system lib does not export the equivalent symbols. Maybe we
1139 need to build a class ref anyway. */
1140 t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1141 IDENTIFIER_POINTER (ident));
1142 v->quick_push (obj: t);
1143 t = build_function_call_vec (input_location, vNULL, objc_get_class_decl,
1144 v, 0);
1145 vec_free (v);
1146 return t;
1147 }
1148}
1149
1150/* Used by build_function_type_for_method. Append the types for
1151 receiver & _cmd at the start of a method argument list to ARGTYPES.
1152 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1153 trying to define a method or call one. SUPERFLAG says this is for a
1154 send to super. METH may be NULL, in the case that there is no
1155 prototype. */
1156
1157static void
1158next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1159 tree meth, int context,
1160 int superflag)
1161{
1162 tree receiver_type;
1163
1164 if (superflag)
1165 receiver_type = objc_super_type;
1166 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1167 receiver_type = objc_instance_type;
1168 else
1169 receiver_type = objc_object_type;
1170
1171 vec_safe_push (v&: *argtypes, obj: receiver_type);
1172 if (flag_next_runtime < USE_FIXUP_BEFORE)
1173 /* Selector type - will eventually change to `int'. */
1174 vec_safe_push (v&: *argtypes, obj: superflag ? objc_v2_super_selector_type
1175 : objc_v2_selector_type);
1176 else
1177 vec_safe_push (v&: *argtypes, objc_selector_type);
1178}
1179
1180/* TODO: Merge this with the message refs. */
1181static tree
1182build_selector_reference_decl (tree ident)
1183{
1184 tree decl;
1185 char *t, buf[BUFSIZE];
1186
1187 snprintf (s: buf, BUFSIZE, format: "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1188 t = buf;
1189 while (*t)
1190 {
1191 if (*t==':')
1192 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1193 t++;
1194 }
1195 decl = start_var_decl (objc_selector_type, buf);
1196 OBJCMETA (decl, objc_meta, meta_sel_refs);
1197 return decl;
1198}
1199
1200static tree
1201next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1202 tree ident,
1203 tree proto ATTRIBUTE_UNUSED)
1204{
1205 tree *chain = &sel_ref_chain;
1206 tree expr;
1207
1208 while (*chain)
1209 {
1210 if (TREE_VALUE (*chain) == ident)
1211 return TREE_PURPOSE (*chain);
1212
1213 chain = &TREE_CHAIN (*chain);
1214 }
1215
1216 expr = build_selector_reference_decl (ident);
1217 *chain = tree_cons (expr, ident, NULL_TREE);
1218
1219 return expr;
1220}
1221
1222/* Declare a variable of type 'struct message_ref_t'. */
1223/* This will be finished in build_v2_message_ref_translation_table ().
1224 We take an idea from LLVM in making the names a bit more connected
1225 and thus the asm more readable. */
1226
1227static tree
1228build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1229{
1230 tree decl;
1231 char buf[BUFSIZE], *t;
1232 int offset = 12;
1233
1234 /* Skip past the objc_msgSend it's the same for all... */
1235 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1236 offset++;
1237
1238 snprintf (s: buf, BUFSIZE, format: "_OBJC_MsgRef_%s_%s",
1239 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1240 IDENTIFIER_POINTER (sel_name));
1241 t = buf;
1242 while (*t)
1243 {
1244 if (*t==':')
1245 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1246 t++;
1247 }
1248 decl = start_var_decl (objc_v2_message_ref_template, buf);
1249 OBJCMETA (decl, objc_meta, meta_mref);
1250 return decl;
1251}
1252
1253struct GTY(()) msgref_entry {
1254 tree func;
1255 tree selname;
1256 tree refdecl;
1257};
1258
1259static GTY (()) vec<msgref_entry, va_gc> *msgrefs;
1260
1261/* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1262 later on to initialize the table of 'struct message_ref_t'
1263 elements. */
1264
1265static tree
1266build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1267{
1268 tree decl;
1269 msgref_entry e;
1270 if (msgrefs)
1271 {
1272 int count;
1273 msgref_entry *ref;
1274 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1275 if (ref->func == message_func_decl && ref->selname == sel_name)
1276 return ref->refdecl;
1277 }
1278 else
1279 /* Somewhat arbitrary initial provision. */
1280 vec_alloc (v&: msgrefs, nelems: 32);
1281
1282 /* We come here if we don't find a match or at the start. */
1283 decl = build_v2_message_reference_decl (sel_name,
1284 DECL_NAME (message_func_decl));
1285 e.func = message_func_decl;
1286 e.selname = sel_name;
1287 e.refdecl = decl;
1288 vec_safe_push (v&: msgrefs, obj: e);
1289 return decl;
1290}
1291
1292static tree
1293build_v2_protocollist_ref_decl (tree protocol)
1294{
1295 tree decl;
1296 tree protocol_ident = PROTOCOL_NAME (protocol);
1297 char buf[BUFSIZE];
1298
1299 snprintf (s: buf, BUFSIZE, format: "_OBJC_ProtocolRef_%s",
1300 IDENTIFIER_POINTER (protocol_ident));
1301 /* TODO: other compiler versions make these hidden & weak. */
1302 decl = create_global_decl (objc_protocol_type, name: buf);
1303 /* Let optimizer know that this decl is not removable. */
1304 DECL_PRESERVE_P (decl) = 1;
1305 OBJCMETA (decl, objc_meta, meta_proto_ref);
1306 return decl;
1307}
1308
1309struct GTY(()) prot_list_entry {
1310 tree id;
1311 tree refdecl;
1312};
1313static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
1314
1315static tree
1316objc_v2_get_protocol_reference (tree ident)
1317{
1318 tree decl;
1319 prot_list_entry e;
1320 if (protrefs)
1321 {
1322 int count;
1323 prot_list_entry *ref;
1324 FOR_EACH_VEC_ELT (*protrefs, count, ref)
1325 {
1326 if (ref->id == ident)
1327 {
1328 if (!ref->refdecl)
1329 ref->refdecl = build_v2_protocollist_ref_decl (protocol: ident);
1330 return ref->refdecl;
1331 }
1332 }
1333 }
1334 else
1335 /* Somewhat arbitrary initial provision. */
1336 vec_alloc (v&: protrefs, nelems: 32);
1337
1338 /* We come here if we don't find the entry - or if the table was yet
1339 to be created. */
1340 decl = build_v2_protocollist_ref_decl (protocol: ident);
1341 e.id = ident;
1342 e.refdecl = decl;
1343 vec_safe_push (v&: protrefs, obj: e);
1344 return decl;
1345}
1346
1347static tree
1348next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1349 tree p)
1350{
1351 if (!PROTOCOL_FORWARD_DECL (p))
1352 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1353
1354 return objc_v2_get_protocol_reference (ident: p);
1355}
1356
1357/* This routine returns the ivar declaration, if component is a valid
1358 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1359 returns the class name in CLASS. */
1360
1361static tree
1362objc_is_ivar (tree expr, tree component, tree *klass)
1363{
1364 tree field = NULL_TREE;
1365 tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1366
1367 if (TREE_CODE (basetype) == RECORD_TYPE
1368 && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1369 {
1370 *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1371 if (*klass)
1372 {
1373 do
1374 {
1375 tree ivar_chain = CLASS_RAW_IVARS (*klass);
1376 if (ivar_chain)
1377 {
1378 field = is_ivar (decl_chain: ivar_chain, ident: component);
1379 if (field != NULL_TREE)
1380 break;
1381 }
1382 *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1383 }
1384 while (*klass);
1385 }
1386 }
1387 return field;
1388}
1389
1390static void
1391create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1392{
1393 tree fname = DECL_NAME (field_decl);
1394
1395 sprintf (s: buf, format: "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1396 IDENTIFIER_POINTER (fname));
1397 return;
1398}
1399
1400/* This routine generates new abi's ivar reference tree. It amounts
1401 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1402 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1403 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1404
1405static tree
1406objc_v2_build_ivar_ref (tree datum, tree component)
1407{
1408 tree field, ref, class_name, offset, ftype, expr;
1409 char var_offset_name[512];
1410
1411 field = objc_is_ivar (expr: datum, component, klass: &class_name);
1412 if (!field)
1413 return NULL_TREE;
1414
1415 /* This routine only handles non-bitfield fields */
1416 if (DECL_C_BIT_FIELD (field))
1417 return NULL_TREE;
1418
1419 create_ivar_offset_name (buf: var_offset_name, CLASS_NAME (class_name), field_decl: field);
1420
1421 offset = create_extern_decl (TREE_TYPE (size_zero_node), name: var_offset_name);
1422
1423 ftype = TREE_TYPE (field);
1424
1425 /* (char*)datum */
1426 expr = build_c_cast (input_location,
1427 string_type_node, build_fold_addr_expr (datum));
1428
1429 /* (char*)datum + offset */
1430 expr = fold_build_pointer_plus_loc (loc: input_location, ptr: expr, off: offset);
1431
1432 /* (ftype*)((char*)datum + offset) */
1433 expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1434
1435 /* Finally: *(ftype*)((char*)datum + offset) */
1436 ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1437
1438 /* We must set type of the resulting expression to be the same as
1439 the field type. This is because, build_indirect_ref (...)
1440 rebuilds the type which may result in lost information; as in the
1441 case of protocol-qualified types (id <protocol> ). */
1442 TREE_TYPE (ref) = ftype;
1443
1444 if (TREE_READONLY (datum) || TREE_READONLY (field))
1445 TREE_READONLY (ref) = 1;
1446
1447 if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1448 TREE_THIS_VOLATILE (ref) = 1;
1449
1450 if (TREE_DEPRECATED (field))
1451 warn_deprecated_use (field, NULL_TREE);
1452
1453 return ref;
1454}
1455
1456/* IVAR refs are made via an externally referenceable offset and built
1457 on the fly. That is, unless they refer to (private) fields in the
1458 class structure. */
1459static tree
1460next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1461 tree base, tree id)
1462{
1463 tree ivar;
1464 if ((ivar = objc_v2_build_ivar_ref (datum: base, component: id)))
1465 return ivar;
1466 return objc_build_component_ref (base, id);
1467}
1468
1469/* [super ...] references are listed here (and built into a table at
1470 meta -data emit time). */
1471static tree
1472build_v2_superclass_ref_decl (tree ident, bool inst)
1473{
1474 tree decl;
1475 char buf[BUFSIZE];
1476
1477 snprintf (s: buf, BUFSIZE, format: "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1478 IDENTIFIER_POINTER (ident));
1479 decl = start_var_decl (objc_class_type, buf);
1480 OBJCMETA (decl, objc_meta, meta_superclass_ref);
1481 return decl;
1482}
1483
1484static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs;
1485static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs;
1486
1487/* Find or build a superclass reference decl for class NAME. */
1488
1489static tree
1490objc_get_superclass_ref_decl (tree name, bool inst_meth)
1491{
1492 tree decl;
1493 vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs
1494 : metaclass_super_refs;
1495
1496 if (list)
1497 {
1498 int count;
1499 ident_data_tuple *ref;
1500 FOR_EACH_VEC_ELT (*list, count, ref)
1501 {
1502 if (ref->ident == name)
1503 {
1504 if (!ref->data)
1505 ref->data = build_v2_superclass_ref_decl (ident: name, inst: inst_meth);
1506 return ref->data;
1507 }
1508 }
1509 }
1510 else
1511 {
1512 /* Somewhat arbitrary initial provision. */
1513 if (inst_meth)
1514 {
1515 vec_alloc (v&: class_super_refs, nelems: 16);
1516 list = class_super_refs;
1517 }
1518 else
1519 {
1520 vec_alloc (v&: metaclass_super_refs, nelems: 16);
1521 list = metaclass_super_refs;
1522 }
1523 }
1524 /* We come here if we don't find the entry - or if the table was yet
1525 to be created. */
1526 decl = build_v2_superclass_ref_decl (ident: name, inst: inst_meth);
1527 ident_data_tuple e;
1528 e.ident = name;
1529 e.data = decl;
1530 vec_safe_push (v&: list, obj: e);
1531 return decl;
1532}
1533
1534/* Get a reference to the superclass for IMP. */
1535
1536static tree
1537next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1538 struct imp_entry *imp, bool inst_meth)
1539{
1540 tree name = CLASS_NAME (imp->imp_context);
1541 return objc_get_superclass_ref_decl (name, inst_meth);
1542}
1543
1544/* Get a reference to the superclass for category IMP. */
1545
1546static tree
1547next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1548 struct imp_entry *imp,
1549 bool inst_meth)
1550{
1551 if (flag_zero_link)
1552 {
1553 /* Do it the slow way. */
1554 tree get_cl_fn = inst_meth ? objc_get_class_decl
1555 : objc_get_meta_class_decl;
1556 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1557 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1558 IDENTIFIER_POINTER (super_name));
1559 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1560 return build_function_call (input_location, get_cl_fn,
1561 build_tree_list (NULL_TREE, super_name));
1562 }
1563
1564 /* This is the 'usual' path. */
1565 tree cls_name = CLASS_NAME (imp->imp_template);
1566 if (!inst_meth)
1567 return objc_get_superclass_ref_decl (name: cls_name, inst_meth);
1568 return objc_get_class_reference (cls_name);
1569}
1570
1571static tree
1572next_runtime_abi_02_receiver_is_class_object (tree receiver)
1573{
1574 if (VAR_P (receiver)
1575 && IS_CLASS (TREE_TYPE (receiver))
1576 && vec_safe_length (v: classrefs))
1577 {
1578 int count;
1579 ident_data_tuple *ref;
1580 /* The receiver is a variable created by build_class_reference_decl. */
1581 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1582 if (ref->data == receiver)
1583 return ref->ident;
1584 }
1585 return NULL_TREE;
1586}
1587
1588/* Assign all arguments in VALUES which have side-effect to a temporary
1589 and replaced that argument in VALUES list with the temporary. The
1590 arguments will be passed to a function with FNTYPE. */
1591
1592static tree
1593objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1594{
1595 tree valtail;
1596 function_args_iterator iter;
1597
1598 /* Skip over receiver and the &_msf_ref types. */
1599 function_args_iter_init (i: &iter, fntype);
1600 function_args_iter_next (i: &iter);
1601 function_args_iter_next (i: &iter);
1602
1603 for (valtail = values; valtail;
1604 valtail = TREE_CHAIN (valtail), function_args_iter_next (i: &iter))
1605 {
1606 tree value = TREE_VALUE (valtail);
1607 tree type = function_args_iter_cond (i: &iter);
1608 if (type == NULL_TREE)
1609 break;
1610 if (!TREE_SIDE_EFFECTS (value))
1611 continue;
1612 /* To prevent re-evaluation. */
1613 value = save_expr (value);
1614 add_stmt (value);
1615 TREE_VALUE (valtail) = value;
1616 }
1617 return values;
1618}
1619
1620/* Build the new abi's messaging library call. It looks like:
1621 (*_msg.messenger) (receiver, &_msg, ...) */
1622
1623static tree
1624build_v2_objc_method_fixup_call (int super_flag, tree method_prototype,
1625 tree lookup_object, tree selector,
1626 tree method_params, bool check_for_nil)
1627{
1628 tree ret_val;
1629 tree sender, rcv_p, t;
1630 tree ret_type
1631 = (method_prototype
1632 ? TREE_VALUE (TREE_TYPE (method_prototype))
1633 : objc_object_type);
1634 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1635 METHOD_REF, super_flag);
1636 tree sender_cast;
1637
1638 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1639 ftype = build_type_attribute_variant (
1640 ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1641
1642 sender_cast = build_pointer_type (ftype);
1643
1644 if (check_for_nil)
1645 method_params = objc_copy_to_temp_side_effect_params (fntype: ftype,
1646 values: method_params);
1647
1648 /* Get &message_ref_t.messenger. */
1649 sender = build_c_cast (input_location,
1650 build_pointer_type (super_flag
1651 ? objc_v2_super_imp_type
1652 : objc_v2_imp_type),
1653 selector);
1654
1655 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1656
1657 rcv_p = (super_flag ? objc_super_type : objc_object_type);
1658
1659 lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1660 if (sender == error_mark_node || lookup_object == error_mark_node)
1661 return error_mark_node;
1662
1663 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1664 lookup_object = save_expr (lookup_object);
1665
1666 method_params = tree_cons (NULL_TREE, lookup_object,
1667 tree_cons (NULL_TREE, selector,
1668 method_params));
1669 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object,
1670 build_int_cst (TREE_TYPE (lookup_object), 0));
1671 ret_val = build_function_call (input_location, t, method_params);
1672 if (check_for_nil)
1673 {
1674 /* receiver != nil ? ret_val : 0 */
1675 tree ftree;
1676 tree ifexp;
1677
1678 if (TREE_CODE (ret_type) == RECORD_TYPE
1679 || TREE_CODE (ret_type) == UNION_TYPE)
1680 /* An empty constructor is zero-filled by the middle end. */
1681 ftree = objc_build_constructor (ret_type, NULL);
1682 else
1683 ftree = fold_convert (ret_type, integer_zero_node);
1684
1685 ifexp = build_binary_op (input_location, NE_EXPR,
1686 lookup_object,
1687 fold_convert (rcv_p, integer_zero_node), 1);
1688
1689#ifdef OBJCPLUS
1690 ret_val = build_conditional_expr (input_location,
1691 ifexp, ret_val, ftree,
1692 tf_warning_or_error);
1693#else
1694 ret_val = build_conditional_expr (input_location,
1695 ifexp, 0,
1696 ret_val, NULL_TREE, input_location,
1697 ftree, NULL_TREE, input_location);
1698 ret_val = fold_convert (ret_type, ret_val);
1699#endif
1700 }
1701 return ret_val;
1702}
1703
1704static tree
1705build_v2_build_objc_method_call (int super, tree method_prototype,
1706 tree lookup_object, tree selector,
1707 tree method_params, location_t loc,
1708 bool check_for_nil, bool rx_is_id)
1709{
1710 tree sender, sender_cast, method, t;
1711 tree rcv_p = (super ? objc_super_type : objc_object_type);
1712 vec<tree, va_gc> *parms;
1713 unsigned nparm = (method_params ? list_length (method_params) : 0);
1714
1715 /* If a prototype for the method to be called exists, then cast
1716 the sender's return type and arguments to match that of the method.
1717 Otherwise, leave sender as is. */
1718 tree ret_type
1719 = (method_prototype
1720 ? TREE_VALUE (TREE_TYPE (method_prototype))
1721 : objc_object_type);
1722 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1723 METHOD_REF, super);
1724
1725 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1726 ftype = build_type_attribute_variant (ftype,
1727 METHOD_TYPE_ATTRIBUTES
1728 (method_prototype));
1729
1730 sender_cast = build_pointer_type (ftype);
1731
1732 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
1733
1734 if (error_operand_p (t: lookup_object))
1735 return error_mark_node;
1736
1737 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1738 lookup_object = save_expr (lookup_object);
1739
1740 /* Param list + 2 slots for object and selector. */
1741 vec_alloc (v&: parms, nelems: nparm + 2);
1742
1743 /* If we are returning an item that must be returned in memory, and the
1744 target ABI does this by an invisible pointer provided as the first arg,
1745 we need to adjust the message signature to include this. The second
1746 part of this excludes targets that provide some alternate scheme for
1747 structure returns. */
1748 if (ret_type && !VOID_TYPE_P (ret_type)
1749 && targetm.calls.return_in_memory (ret_type, 0)
1750 && !(targetm.calls.struct_value_rtx (0, 0)
1751 && (TREE_CODE (ret_type) == RECORD_TYPE
1752 || TREE_CODE (ret_type) == UNION_TYPE)))
1753 {
1754 if (super)
1755 sender = umsg_id_super2_stret_fixup_decl;
1756 else
1757 sender = rx_is_id ? umsg_id_stret_fixup_decl
1758 : umsg_stret_fixup_decl;
1759 }
1760 else
1761 {
1762 if (super)
1763 sender = umsg_id_super2_fixup_decl;
1764 else
1765 sender = rx_is_id ? umsg_id_fixup_decl
1766 : umsg_fixup_decl;
1767 }
1768
1769 method = build_fold_addr_expr_loc (loc, sender);
1770
1771 /* Pass the object to the method. */
1772 parms->quick_push (obj: lookup_object);
1773 /* Pass the selector to the method. */
1774 parms->quick_push (obj: selector);
1775 /* Now append the remainder of the parms. */
1776 if (nparm)
1777 for (; method_params; method_params = TREE_CHAIN (method_params))
1778 parms->quick_push (TREE_VALUE (method_params));
1779
1780 /* Build an obj_type_ref, with the correct cast for the method call. */
1781 t = build3 (OBJ_TYPE_REF, sender_cast, method,
1782 lookup_object, build_int_cst (TREE_TYPE (lookup_object), 0));
1783 tree ret_val = build_function_call_vec (loc, vNULL, t, parms, NULL);
1784 vec_free (v&: parms);
1785 if (check_for_nil)
1786 {
1787 /* receiver != nil ? ret_val : 0 */
1788 tree ftree;
1789 tree ifexp;
1790
1791 if (TREE_CODE (ret_type) == RECORD_TYPE
1792 || TREE_CODE (ret_type) == UNION_TYPE)
1793 {
1794 /* An empty constructor is zero-filled by the middle end. */
1795 ftree = objc_build_constructor (ret_type, NULL);
1796 }
1797 else
1798 ftree = fold_convert (ret_type, integer_zero_node);
1799
1800 ifexp = build_binary_op (loc, NE_EXPR,
1801 lookup_object,
1802 fold_convert (rcv_p, integer_zero_node), 1);
1803
1804#ifdef OBJCPLUS
1805 ret_val = build_conditional_expr (loc, ifexp, ret_val, ftree,
1806 tf_warning_or_error);
1807#else
1808 ret_val = build_conditional_expr (loc, ifexp, 1,
1809 ret_val, NULL_TREE, loc,
1810 ftree, NULL_TREE, loc);
1811 ret_val = fold_convert (ret_type, ret_val);
1812#endif
1813 }
1814 return ret_val;
1815}
1816
1817static tree
1818next_runtime_abi_02_build_objc_method_call (location_t loc,
1819 tree method_prototype,
1820 tree receiver,
1821 tree rtype,
1822 tree sel_name,
1823 tree method_params,
1824 int super)
1825{
1826 /* Do we need to check for nil receivers ? */
1827 /* For now, message sent to classes need no nil check. In the
1828 future, class declaration marked as weak_import must be nil
1829 checked. */
1830 bool check_for_nil = flag_objc_nilcheck;
1831 if (super
1832 || (VAR_P (receiver)
1833 && TREE_TYPE (receiver) == objc_class_type))
1834 check_for_nil = false;
1835
1836 if (flag_next_runtime >= USE_FIXUP_BEFORE)
1837 {
1838 tree selector
1839 = next_runtime_abi_02_build_selector_reference (loc, ident: sel_name,
1840 proto: method_prototype);
1841 return build_v2_build_objc_method_call (super, method_prototype,
1842 lookup_object: receiver, selector,
1843 method_params, loc,
1844 check_for_nil,
1845 rx_is_id: objc_is_id (rtype));
1846 }
1847
1848 /* else we have to build a pair of the function and selector. */
1849 tree message_func_decl;
1850 tree ret_type = method_prototype
1851 ? TREE_VALUE (TREE_TYPE (method_prototype))
1852 : objc_object_type;
1853
1854 /* See comment for the fixup version above. */
1855 if (ret_type && !VOID_TYPE_P (ret_type)
1856 && targetm.calls.return_in_memory (ret_type, 0)
1857 && !(targetm.calls.struct_value_rtx (0, 0)
1858 && (TREE_CODE (ret_type) == RECORD_TYPE
1859 || TREE_CODE (ret_type) == UNION_TYPE)))
1860 {
1861 if (super)
1862 message_func_decl = umsg_id_super2_stret_fixup_decl;
1863 else
1864 message_func_decl = objc_is_id (rtype)
1865 ? umsg_id_stret_fixup_decl
1866 : umsg_stret_fixup_decl;
1867 }
1868 else
1869 {
1870 if (super)
1871 message_func_decl = umsg_id_super2_fixup_decl;
1872 else
1873 message_func_decl = objc_is_id (rtype)
1874 ? umsg_id_fixup_decl
1875 : umsg_fixup_decl;
1876 }
1877
1878 tree selector = build_v2_selector_messenger_reference (sel_name,
1879 message_func_decl);
1880
1881 /* selector = &_msg; */
1882 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1883
1884 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1885 : objc_v2_selector_type),
1886 selector);
1887
1888 /* (*_msg.messenger) (receiver, &_msg, ...); */
1889 return build_v2_objc_method_fixup_call (super_flag: super, method_prototype, lookup_object: receiver,
1890 selector, method_params,
1891 check_for_nil);
1892}
1893
1894/* NOTE --- Constant String Class Stuff --- */
1895
1896static bool
1897next_runtime_abi_02_setup_const_string_class_decl (void)
1898{
1899 if (!constant_string_global_id)
1900 {
1901 /* Hopefully, this should not represent a serious limitation. */
1902 char buf[BUFSIZE];
1903 snprintf (s: buf, BUFSIZE, format: "OBJC_CLASS_$_%s", constant_string_class_name);
1904 constant_string_global_id = get_identifier (buf);
1905 }
1906
1907 string_class_decl = lookup_name (constant_string_global_id);
1908
1909 /* In OBJC2 abi, constant string class reference refers to class
1910 name for NSConstantString class. This declaration may not be
1911 available yet (in fact it is not in most cases). So, declare an
1912 extern OBJC_CLASS_$_NSConstantString in its place. */
1913 if (!string_class_decl)
1914 string_class_decl =
1915 create_extern_decl (objc_v2_class_template,
1916 IDENTIFIER_POINTER (constant_string_global_id));
1917
1918 return (string_class_decl != NULL_TREE);
1919}
1920
1921static tree
1922next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1923 int length)
1924{
1925 tree constructor, fields, var;
1926 vec<constructor_elt, va_gc> *v = NULL;
1927
1928 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1929 fields = TYPE_FIELDS (internal_const_str_type);
1930 CONSTRUCTOR_APPEND_ELT (v, fields,
1931 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1932
1933 fields = DECL_CHAIN (fields);
1934 CONSTRUCTOR_APPEND_ELT (v, fields,
1935 build_unary_op (loc, ADDR_EXPR, string, 1));
1936
1937 /* ??? check if this should be long. */
1938 fields = DECL_CHAIN (fields);
1939 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1940 constructor = objc_build_constructor (internal_const_str_type, v);
1941
1942 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1943 DECL_INITIAL (var) = constructor;
1944 TREE_STATIC (var) = 1;
1945 DECL_CONTEXT (var) = NULL;
1946 OBJCMETA (var, objc_meta, meta_const_str);
1947 return var;
1948}
1949
1950/* NOTE --- NeXT V2 Metadata templates --- */
1951
1952/* This routine builds the following type:
1953 struct _prop_t
1954 {
1955 const char * const name; // property name
1956 const char * const attributes; // comma-delimited, encoded,
1957 // property attributes
1958 };
1959*/
1960
1961static tree
1962build_v2_property_template (void)
1963{
1964 tree prop_record;
1965 tree decls, *chain = NULL;
1966
1967 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1968 /* const char * name */
1969 decls = add_field_decl (string_type_node, "name", &chain);
1970
1971 /* const char * attribute */
1972 add_field_decl (string_type_node, "attribute", &chain);
1973
1974 objc_finish_struct (prop_record, decls);
1975 return prop_record;
1976}
1977
1978/* struct ivar_t
1979 {
1980 unsigned long int *offset;
1981 char *name;
1982 char *type;
1983 uint32_t alignment;
1984 uint32_t size;
1985 };
1986*/
1987
1988static tree
1989build_v2_ivar_t_template (void)
1990{
1991 tree objc_ivar_id, objc_ivar_record;
1992 tree decls, *chain = NULL;
1993
1994 objc_ivar_id = get_identifier ("_ivar_t");
1995 objc_ivar_record = objc_start_struct (objc_ivar_id);
1996
1997 /* unsigned long int *offset; */
1998 decls = add_field_decl (build_pointer_type
1999 (TREE_TYPE (size_zero_node)), "offset", &chain);
2000
2001 /* char *name; */
2002 add_field_decl (string_type_node, "name", &chain);
2003
2004 /* char *type; */
2005 add_field_decl (string_type_node, "type", &chain);
2006
2007 /* uint32_t alignment; */
2008 add_field_decl (integer_type_node, "alignment", &chain);
2009
2010 /* uint32_t size; */
2011 add_field_decl (integer_type_node, "size", &chain);
2012
2013 objc_finish_struct (objc_ivar_record, decls);
2014 return objc_ivar_record;
2015}
2016
2017static void
2018build_metadata_templates (void)
2019{
2020
2021 if (!objc_method_template)
2022 objc_method_template = build_method_template ();
2023
2024 if (!objc_v2_property_template)
2025 objc_v2_property_template = build_v2_property_template ();
2026
2027 if (!objc_v2_ivar_template)
2028 objc_v2_ivar_template = build_v2_ivar_t_template ();
2029
2030}
2031
2032/* NOTE --- Output NeXT V2 Metadata --- */
2033
2034/* Routine builds name of Interface's main meta-data of type class_t. */
2035
2036static char *
2037objc_build_internal_classname (tree ident, bool metaclass)
2038{
2039 static char string[512];
2040 snprintf (s: string, maxlen: 512, format: "%s_%s", metaclass ? "OBJC_METACLASS_$"
2041 : "OBJC_CLASS_$",
2042 IDENTIFIER_POINTER (ident));
2043 return string;
2044}
2045
2046/* Build the name for object of type struct class_ro_t */
2047
2048static const char *
2049newabi_append_ro (const char *name)
2050{
2051 const char *dollar;
2052 char *p;
2053 static char string[BUFSIZE];
2054 dollar = strchr (s: name, c: '$');
2055 gcc_assert (dollar);
2056 p = string;
2057 *p = '_'; p++;
2058 strncpy (dest: p, src: name, n: (int)(dollar - name));
2059 p += (int)(dollar - name);
2060 sprintf (s: p, format: "RO_%s", dollar);
2061 return string;
2062}
2063
2064/* Build the struct message_ref_t msg =
2065 {objc_msgSend_fixup_xxx, @selector(func)}
2066 table. */
2067
2068static
2069void build_v2_message_ref_translation_table (void)
2070{
2071 int count;
2072 msgref_entry *ref;
2073
2074 if (!vec_safe_length (v: msgrefs))
2075 return;
2076
2077 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
2078 {
2079 vec<constructor_elt, va_gc> *initializer;
2080 tree expr, constructor;
2081 tree struct_type = TREE_TYPE (ref->refdecl);
2082 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
2083
2084 initializer = NULL;
2085 /* First 'IMP messenger' field... */
2086 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
2087 expr = convert (objc_v2_imp_type, expr);
2088 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2089
2090 /* ... then 'SEL name' field. */
2091 expr = build_selector (ref->selname);
2092 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2093 constructor = objc_build_constructor (struct_type, initializer);
2094 finish_var_decl (ref->refdecl, constructor);
2095 }
2096}
2097
2098/* Build decl = initializer; for each externally visible class
2099 reference. */
2100
2101static void
2102build_v2_classrefs_table (void)
2103{
2104 int count;
2105 ident_data_tuple *ref;
2106
2107 if (!vec_safe_length (v: classrefs))
2108 return;
2109
2110 FOR_EACH_VEC_ELT (*classrefs, count, ref)
2111 {
2112 tree expr = ref->ident;
2113 tree decl = ref->data;
2114 /* Interface with no implementation and yet one of its messages
2115 has been used. Need to generate a full address-of tree for it
2116 here. */
2117 if (TREE_CODE (expr) == IDENTIFIER_NODE)
2118 {
2119 const char *name = objc_build_internal_classname (ident: expr, metaclass: false);
2120 expr = create_extern_decl (objc_v2_class_template, name);
2121 expr = convert (objc_class_type, build_fold_addr_expr (expr));
2122 }
2123 /* The runtime wants this, even if it appears unused, so we must force the
2124 output. */
2125 DECL_PRESERVE_P (decl) = 1;
2126 finish_var_decl (decl, expr);
2127 }
2128}
2129
2130/* Build decl = initializer; for each externally visible super class
2131 reference. */
2132
2133static void
2134build_v2_super_classrefs_table (bool metaclass)
2135{
2136 int count;
2137 ident_data_tuple *ref;
2138 vec<ident_data_tuple, va_gc> *list = metaclass ? metaclass_super_refs
2139 : class_super_refs;
2140
2141 if (!vec_safe_length (v: list))
2142 return;
2143
2144 FOR_EACH_VEC_ELT (*list, count, ref)
2145 {
2146 tree expr = ref->ident;
2147 tree decl = ref->data;
2148 /* Interface with no implementation and yet one of its messages
2149 has been used. Need to generate a full address-of tree for it
2150 here. */
2151 if (TREE_CODE (expr) == IDENTIFIER_NODE)
2152 {
2153 const char * name = objc_build_internal_classname (ident: expr, metaclass);
2154 expr = create_extern_decl (objc_v2_class_template, name);
2155 expr = convert (objc_class_type, build_fold_addr_expr (expr));
2156 }
2157 finish_var_decl (decl, expr);
2158 }
2159}
2160
2161/* Add the global class meta-data declaration to the list which later
2162 on ends up in the __class_list section. */
2163
2164static GTY(()) vec<tree, va_gc> *class_list;
2165
2166static void
2167objc_v2_add_to_class_list (tree global_class_decl)
2168{
2169 vec_safe_push (v&: class_list, obj: global_class_decl);
2170}
2171
2172static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
2173
2174/* Add the global class meta-data declaration to the list which later
2175 on ends up in the __nonlazy_class section. */
2176
2177static void
2178objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2179{
2180 vec_safe_push (v&: nonlazy_class_list, obj: global_class_decl);
2181}
2182
2183static GTY(()) vec<tree, va_gc> *category_list;
2184
2185/* Add the category meta-data declaration to the list which later on
2186 ends up in the __nonlazy_category section. */
2187
2188static void
2189objc_v2_add_to_category_list (tree decl)
2190{
2191 vec_safe_push (v&: category_list, obj: decl);
2192}
2193
2194static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
2195
2196/* Add the category meta-data declaration to the list which later on
2197 ends up in the __category_list section. */
2198
2199static void
2200objc_v2_add_to_nonlazy_category_list (tree decl)
2201{
2202 vec_safe_push (v&: nonlazy_category_list, obj: decl);
2203}
2204
2205static bool
2206has_load_impl (tree clsmeth)
2207{
2208 while (clsmeth)
2209 {
2210 tree id = METHOD_SEL_NAME (clsmeth);
2211 if (IDENTIFIER_LENGTH (id) == 4
2212 && startswith (IDENTIFIER_POINTER (id), prefix: "load"))
2213 return true;
2214 clsmeth = DECL_CHAIN (clsmeth);
2215 }
2216
2217 return false;
2218}
2219
2220/* Build a __{class,category}_list section table containing address of
2221 all @implemented {class,category} meta-data. */
2222
2223static void
2224build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
2225{
2226 int count=0;
2227 tree type, decl, expr;
2228 vec<constructor_elt, va_gc> *initlist = NULL;
2229
2230 if (!vec_safe_length (v: src))
2231 return;
2232
2233 FOR_EACH_VEC_ELT (*src, count, decl)
2234 {
2235#ifndef OBJCPLUS
2236 tree purpose = build_int_cst (NULL_TREE, count);
2237#else
2238 tree purpose = NULL_TREE;
2239#endif
2240 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2241 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2242 }
2243 gcc_assert (count > 0);
2244 type = build_array_type (objc_class_type,
2245 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2246 decl = start_var_decl (type, nam);
2247 /* The runtime wants this, even if it appears unused, so we must
2248 force the output. */
2249 DECL_PRESERVE_P (decl) = 1;
2250 expr = objc_build_constructor (type, initlist);
2251 OBJCMETA (decl, objc_meta, attr);
2252 DECL_USER_ALIGN (decl) = 1;
2253 finish_var_decl (decl, expr);
2254}
2255
2256/* Build decl = initializer; for each protocol referenced in
2257 @protocol(MyProt) expression. Refs as built in the entry section
2258 above. */
2259
2260static void
2261build_v2_protocol_list_translation_table (void)
2262{
2263 int count;
2264 prot_list_entry *ref;
2265
2266 if (!protrefs)
2267 return;
2268
2269 FOR_EACH_VEC_ELT (*protrefs, count, ref)
2270 {
2271 char buf[BUFSIZE];
2272 tree expr;
2273 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2274 snprintf (s: buf, BUFSIZE, format: "_OBJC_Protocol_%s",
2275 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2276 expr = start_var_decl (objc_v2_protocol_template, buf);
2277 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2278 finish_var_decl (ref->refdecl, expr);
2279 }
2280 /* TODO: Maybe we could explicitly delete the vec. now? */
2281}
2282
2283static GTY (()) vec<prot_list_entry, va_gc> *protlist;
2284
2285/* Add the local protocol meta-data declaration to the list which
2286 later on ends up in the __protocol_list section. */
2287
2288static void
2289objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2290{
2291 prot_list_entry e;
2292 if (!protlist)
2293 /* Arbitrary init count. */
2294 vec_alloc (v&: protlist, nelems: 32);
2295 e.id = protocol_interface_decl;
2296 e.refdecl = protocol_decl;
2297 vec_safe_push (v&: protlist, obj: e);
2298}
2299
2300/* Build the __protocol_list section table containing address of all
2301 generate protocol_t meta-data. */
2302
2303static void
2304build_v2_protocol_list_address_table (void)
2305{
2306 int count;
2307 prot_list_entry *ref;
2308 if (!vec_safe_length (v: protlist))
2309 return;
2310
2311 FOR_EACH_VEC_ELT (*protlist, count, ref)
2312 {
2313 tree decl, expr;
2314 char buf[BUFSIZE];
2315 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2316 snprintf (s: buf, BUFSIZE, format: "_OBJC_LabelProtocol_%s",
2317 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2318 if (flag_next_runtime >= USE_FIXUP_BEFORE)
2319 {
2320 decl = create_hidden_decl (objc_protocol_type, name: buf, /*is def=*/is_def: true);
2321 DECL_WEAK (decl) = true;
2322 }
2323 else
2324 decl = create_global_decl (objc_protocol_type, name: buf, /*is def=*/is_def: true);
2325 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2326 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2327 DECL_PRESERVE_P (decl) = 1;
2328 DECL_USER_ALIGN (decl) = 1;
2329 finish_var_decl (decl, expr);
2330 }
2331
2332 /* TODO: delete the vec. */
2333 /* TODO: upgrade to the clang/llvm hidden version. */
2334}
2335
2336/* This routine declares a variable to hold meta data for 'struct
2337 protocol_list_t'. */
2338
2339static tree
2340generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2341{
2342 tree refs_decl, lproto, e, plist, ptempl_p_t;
2343 int size = 0;
2344 vec<constructor_elt, va_gc> *initlist = NULL;
2345 char buf[BUFSIZE];
2346
2347 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2348 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2349 plist = CLASS_PROTOCOL_LIST (i_or_p);
2350 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2351 plist = PROTOCOL_LIST (i_or_p);
2352 else
2353 gcc_unreachable ();
2354
2355 /* Compute size. */
2356 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2357 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2358 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2359 size++;
2360
2361 /* Build initializer. */
2362
2363 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2364 e = build_int_cst (ptempl_p_t, size);
2365 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2366
2367 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2368 {
2369 tree pval = TREE_VALUE (lproto);
2370
2371 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2372 && PROTOCOL_FORWARD_DECL (pval))
2373 {
2374 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2375 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2376 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2377 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2378 }
2379 }
2380
2381 /* static struct protocol_list_t *list[size]; */
2382
2383 switch (TREE_CODE (i_or_p))
2384 {
2385 case PROTOCOL_INTERFACE_TYPE:
2386 snprintf (s: buf, BUFSIZE, format: "_OBJC_ProtocolRefs_%s",
2387 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2388 break;
2389 case CLASS_INTERFACE_TYPE:
2390 snprintf (s: buf, BUFSIZE, format: "_OBJC_ClassProtocols_%s",
2391 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2392 break;
2393 case CATEGORY_INTERFACE_TYPE:
2394 snprintf (s: buf, BUFSIZE, format: "_OBJC_CategoryProtocols_%s_%s",
2395 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2396 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2397 break;
2398 default:
2399 gcc_unreachable ();
2400 }
2401
2402 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2403 buf);
2404 /* ObjC2 puts all these in the base section. */
2405 OBJCMETA (refs_decl, objc_meta, meta_base);
2406 DECL_PRESERVE_P (refs_decl) = 1;
2407 DECL_USER_ALIGN (refs_decl) = 1;
2408 finish_var_decl (refs_decl,
2409 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2410 return refs_decl;
2411}
2412
2413/* This routine builds one 'struct method_t' initializer list. Note
2414 that the old ABI is supposed to build 'struct objc_method' which
2415 has 3 fields, but it does not build the initialization expression
2416 for 'method_imp' which for protocols is NULL any way. To be
2417 consistent with declaration of 'struct method_t', in the new ABI we
2418 set the method_t.imp to NULL. */
2419
2420static tree
2421build_v2_descriptor_table_initializer (tree type, tree entries)
2422{
2423 vec<constructor_elt, va_gc> *initlist = NULL;
2424 do
2425 {
2426 vec<constructor_elt, va_gc> *eltlist = NULL;
2427 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2428 build_selector (METHOD_SEL_NAME (entries)));
2429 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2430 add_objc_string (METHOD_ENCODING (entries),
2431 meth_var_types));
2432 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2433
2434 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2435 objc_build_constructor (type, eltlist));
2436 entries = TREE_CHAIN (entries);
2437 }
2438 while (entries);
2439
2440 return objc_build_constructor (build_array_type (type, 0), initlist);
2441}
2442
2443/* struct method_list_t
2444 {
2445 uint32_t entsize;
2446 uint32_t method_count;
2447 struct objc_method method_list[method_count];
2448 }; */
2449
2450static tree
2451build_v2_method_list_template (tree list_type, int size)
2452{
2453 tree method_list_t_record;
2454 tree array_type, decls, *chain = NULL;
2455
2456 method_list_t_record = objc_start_struct (NULL_TREE);
2457
2458 /* uint32_t const entsize; */
2459 decls = add_field_decl (integer_type_node, "entsize", &chain);
2460
2461 /* int method_count; */
2462 add_field_decl (integer_type_node, "method_count", &chain);
2463
2464 /* struct objc_method method_list[]; */
2465 array_type = build_sized_array_type (list_type, size);
2466 add_field_decl (array_type, "method_list", &chain);
2467
2468 objc_finish_struct (method_list_t_record, decls);
2469 return method_list_t_record;
2470}
2471
2472/* Note, as above that we are building to the objc_method_template
2473 which has the *imp field. ABI0/1 build with
2474 objc_method_prototype_template which is missing this field. */
2475static tree
2476generate_v2_meth_descriptor_table (tree chain, tree protocol,
2477 const char *prefix, tree attr,
2478 vec<tree>& all_meths)
2479{
2480 tree method_list_template, initlist, decl;
2481 int size, entsize;
2482 vec<constructor_elt, va_gc> *v = NULL;
2483 char buf[BUFSIZE];
2484
2485 if (!chain || !prefix)
2486 return NULL_TREE;
2487
2488 tree method = chain;
2489 size = 0;
2490 while (method)
2491 {
2492 if (! METHOD_ENCODING (method))
2493 METHOD_ENCODING (method) = encode_method_prototype (method_decl: method);
2494 all_meths.safe_push (obj: method);
2495 method = TREE_CHAIN (method);
2496 size++;
2497 }
2498
2499 gcc_assert (size);
2500 method_list_template = build_v2_method_list_template (objc_method_template,
2501 size);
2502 snprintf (s: buf, BUFSIZE, format: "%s_%s", prefix,
2503 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2504
2505 decl = start_var_decl (method_list_template, buf);
2506
2507 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2508 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2509 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2510 initlist =
2511 build_v2_descriptor_table_initializer (objc_method_template,
2512 entries: chain);
2513 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2514 /* Get into the right section. */
2515 OBJCMETA (decl, objc_meta, attr);
2516 DECL_USER_ALIGN (decl) = 1;
2517 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2518 return decl;
2519}
2520
2521static tree
2522generate_v2_meth_type_list (vec<tree>& all_meths, tree protocol,
2523 const char *prefix)
2524{
2525 if (all_meths.is_empty () || !prefix)
2526 return NULL_TREE;
2527
2528 unsigned size = all_meths.length ();
2529 tree list_type = build_sized_array_type (string_type_node, size);
2530 char *nam;
2531 asprintf (ptr: &nam, fmt: "%s_%s", prefix,
2532 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2533 tree decl = start_var_decl (list_type, nam);
2534 free (ptr: nam);
2535 vec<constructor_elt, va_gc> *v = NULL;
2536
2537 for (unsigned i = 0; i < size; ++i)
2538 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2539 add_objc_string (METHOD_ENCODING (all_meths[i]),
2540 meth_var_types));
2541 OBJCMETA (decl, objc_meta, meta_base);
2542 DECL_USER_ALIGN (decl) = 1;
2543 finish_var_decl (decl, objc_build_constructor (list_type, v));
2544 return decl;
2545}
2546
2547/* This routine builds the initializer list to initialize the 'struct
2548 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2549
2550static tree
2551build_v2_property_table_initializer (tree type, tree context)
2552{
2553 tree x;
2554 vec<constructor_elt, va_gc> *inits = NULL;
2555 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2556 x = CLASS_PROPERTY_DECL (context);
2557 else
2558 x = IMPL_PROPERTY_DECL (context);
2559
2560 for (; x; x = TREE_CHAIN (x))
2561 {
2562 vec<constructor_elt, va_gc> *elemlist = NULL;
2563 /* NOTE! sections where property name/attribute go MUST change
2564 later. */
2565 tree attribute, name_ident = PROPERTY_NAME (x);
2566
2567 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2568 add_objc_string (name_ident, prop_names_attr));
2569
2570 attribute = objc_v2_encode_prop_attr (property: x);
2571 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2572 add_objc_string (attribute, prop_names_attr));
2573
2574 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2575 objc_build_constructor (type, elemlist));
2576 }
2577
2578 return objc_build_constructor (build_array_type (type, 0),inits);
2579}
2580
2581/* This routine builds the following type:
2582 struct _prop_list_t
2583 {
2584 uint32_t entsize; // sizeof (struct _prop_t)
2585 uint32_t prop_count;
2586 struct _prop_t prop_list [prop_count];
2587 }
2588*/
2589
2590static tree
2591build_v2_property_list_template (tree list_type, int size)
2592{
2593 tree property_list_t_record;
2594 tree array_type, decls, *chain = NULL;
2595
2596 /* anonymous. */
2597 property_list_t_record = objc_start_struct (NULL_TREE);
2598
2599 /* uint32_t const entsize; */
2600 decls = add_field_decl (integer_type_node, "entsize", &chain);
2601
2602 /* int prop_count; */
2603 add_field_decl (integer_type_node, "prop_count", &chain);
2604
2605 /* struct _prop_t prop_list[]; */
2606 array_type = build_sized_array_type (list_type, size);
2607 add_field_decl (array_type, "prop_list", &chain);
2608
2609 objc_finish_struct (property_list_t_record, decls);
2610 return property_list_t_record;
2611}
2612
2613/* Top-level routine to generate property tables for each
2614 implementation. */
2615
2616static tree
2617generate_v2_property_table (tree context, tree klass_ctxt)
2618{
2619 tree x, decl, initlist, property_list_template;
2620 bool is_proto = false;
2621 vec<constructor_elt, va_gc> *inits = NULL;
2622 int init_val, size = 0;
2623 char buf[BUFSIZE];
2624
2625 if (context)
2626 {
2627 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2628 x = CLASS_PROPERTY_DECL (context);
2629 is_proto = true;
2630 }
2631 else
2632 x = IMPL_PROPERTY_DECL (klass_ctxt);
2633
2634 for (; x; x = TREE_CHAIN (x))
2635 size++;
2636
2637 if (size == 0)
2638 return NULL_TREE;
2639
2640 property_list_template =
2641 build_v2_property_list_template (objc_v2_property_template,
2642 size);
2643
2644 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2645 context: is_proto ? context
2646 : klass_ctxt);
2647
2648 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2649 if (is_proto)
2650 snprintf (s: buf, BUFSIZE, format: "_OBJC_ProtocolPropList_%s",
2651 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2652 else
2653 snprintf (s: buf, BUFSIZE, format: "_OBJC_ClassPropList_%s",
2654 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2655
2656 decl = start_var_decl (property_list_template, buf);
2657
2658 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2659 build_int_cst (NULL_TREE, init_val));
2660 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2661 build_int_cst (NULL_TREE, size));
2662 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2663
2664 OBJCMETA (decl, objc_meta, meta_base);
2665 DECL_USER_ALIGN (decl) = 1;
2666 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2667 return decl;
2668}
2669
2670static tree
2671build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2672 tree inst_methods, tree class_methods,
2673 tree opt_ins_meth, tree opt_cls_meth,
2674 tree property_list, tree ext_meth_types,
2675 tree demangled_name, tree class_prop_list)
2676{
2677 tree expr, ttyp;
2678 location_t loc;
2679 vec<constructor_elt, va_gc> *inits = NULL;
2680
2681 /* TODO: find a better representation of location from the inputs. */
2682 loc = UNKNOWN_LOCATION;
2683
2684 /* This is NULL for the new ABI. */
2685 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2686 convert (objc_object_type, null_pointer_node));
2687
2688 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2689 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2690
2691 ttyp = objc_method_proto_list_ptr;
2692 if (inst_methods)
2693 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2694 else
2695 expr = convert (ttyp, null_pointer_node);
2696 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2697
2698 if (class_methods)
2699 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2700 else
2701 expr = convert (ttyp, null_pointer_node);
2702 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2703
2704 if (opt_ins_meth)
2705 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2706 else
2707 expr = convert (ttyp, null_pointer_node);
2708 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2709
2710 if (opt_cls_meth)
2711 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2712 else
2713 expr = convert (ttyp, null_pointer_node);
2714 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2715
2716 ttyp = objc_prop_list_ptr;
2717 if (property_list)
2718 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2719 else
2720 expr = convert (ttyp, null_pointer_node);
2721 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2722
2723 /* const uint32_t size; = sizeof(struct protocol_t) */
2724 expr = build_int_cst (integer_type_node,
2725 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2726 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2727 /* const uint32_t flags; = 0 */
2728 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2729
2730 ttyp = build_pointer_type (string_type_node);
2731 if (ext_meth_types)
2732 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, ext_meth_types, 0));
2733 else
2734 expr = convert (ttyp, null_pointer_node);
2735 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2736
2737 ttyp = string_type_node;
2738 if (demangled_name)
2739 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, demangled_name, 0));
2740 else
2741 expr = convert (ttyp, null_pointer_node);
2742 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2743
2744 ttyp = objc_prop_list_ptr;
2745 if (class_prop_list)
2746 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_prop_list, 0));
2747 else
2748 expr = convert (ttyp, null_pointer_node);
2749 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2750
2751 return objc_build_constructor (type, inits);
2752}
2753
2754/* Main routine to build all meta data for all protocols used in a
2755 translation unit. */
2756
2757static void
2758generate_v2_protocols (void)
2759{
2760 tree p ;
2761 bool some = false;
2762
2763 if (!protocol_chain)
2764 return ;
2765
2766 /* If a protocol was directly referenced, pull in indirect
2767 references. */
2768 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2769 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2770 generate_protocol_references (PROTOCOL_LIST (p));
2771
2772 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2773 {
2774 location_t loc;
2775 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2776 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2777
2778 /* If protocol wasn't referenced, don't generate any code. */
2779 decl = PROTOCOL_FORWARD_DECL (p);
2780
2781 if (!decl)
2782 continue;
2783
2784 loc = DECL_SOURCE_LOCATION (decl);
2785 some = true;
2786
2787 vec<tree> all_meths = vNULL;
2788 inst_meth =
2789 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), protocol: p,
2790 prefix: "_OBJC_ProtocolInstanceMethods",
2791 meta_proto_nst_meth, all_meths);
2792
2793 class_meth =
2794 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), protocol: p,
2795 prefix: "_OBJC_ProtocolClassMethods",
2796 meta_proto_cls_meth, all_meths);
2797
2798 opt_inst_meth =
2799 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), protocol: p,
2800 prefix: "_OBJC_ProtocolOptInstMethods",
2801 meta_proto_nst_meth, all_meths);
2802
2803 opt_class_meth =
2804 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), protocol: p,
2805 prefix: "_OBJC_ProtocolOptClassMethods",
2806 meta_proto_cls_meth, all_meths);
2807
2808 if (PROTOCOL_LIST (p))
2809 refs_decl = generate_v2_protocol_list (i_or_p: p, NULL_TREE);
2810 else
2811 refs_decl = 0;
2812
2813 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2814 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2815
2816 if (refs_decl)
2817 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2818 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2819 else
2820 refs_expr = build_int_cst (NULL_TREE, 0);
2821
2822 props = generate_v2_property_table (context: p, NULL_TREE);
2823
2824 tree ext_meth_types
2825 = generate_v2_meth_type_list (all_meths, protocol: p,
2826 prefix: "_OBJC_ProtocolMethodTypes");
2827 tree demangled_name = NULL_TREE;
2828 tree class_prop_list = NULL_TREE;
2829
2830 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2831 protocol_name: protocol_name_expr, protocol_list: refs_expr,
2832 inst_methods: inst_meth, class_methods: class_meth,
2833 opt_ins_meth: opt_inst_meth, opt_cls_meth: opt_class_meth,
2834 property_list: props, ext_meth_types,
2835 demangled_name,class_prop_list);
2836 finish_var_decl (decl, initlist);
2837 objc_add_to_protocol_list (protocol_interface_decl: p, protocol_decl: decl);
2838 all_meths.truncate (size: 0);
2839 }
2840
2841 if (some)
2842 {
2843 /* Make sure we get the Protocol class linked in - reference
2844 it... */
2845 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2846 /* ... but since we don't specifically use the reference... we
2847 need to force it. */
2848 DECL_PRESERVE_P (p) = 1;
2849 }
2850}
2851
2852static tree
2853generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2854{
2855 tree decl, method_list_template, initlist;
2856 vec<constructor_elt, va_gc> *v = NULL;
2857 int size, init_val;
2858
2859 if (!chain || !name || !(size = list_length (chain)))
2860 return NULL_TREE;
2861
2862 method_list_template
2863 = build_v2_method_list_template (objc_method_template, size);
2864 initlist
2865 = build_dispatch_table_initializer (objc_method_template, chain);
2866
2867 decl = start_var_decl (method_list_template, name);
2868
2869 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2870 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2871 build_int_cst (integer_type_node, init_val));
2872 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2873 build_int_cst (integer_type_node, size));
2874 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2875
2876 OBJCMETA (decl, objc_meta, attr);
2877 DECL_USER_ALIGN (decl) = 1;
2878 finish_var_decl (decl,
2879 objc_build_constructor (TREE_TYPE (decl), v));
2880 return decl;
2881}
2882
2883/* Init a category. */
2884static tree
2885build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2886 tree inst_methods, tree class_methods,
2887 tree protocol_list, tree property_list,
2888 location_t loc)
2889{
2890 tree expr, ltyp;
2891 vec<constructor_elt, va_gc> *v = NULL;
2892
2893 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2894 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2895
2896 ltyp = objc_method_list_ptr;
2897 if (inst_methods)
2898 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2899 else
2900 expr = convert (ltyp, null_pointer_node);
2901 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2902
2903 if (class_methods)
2904 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2905 else
2906 expr = convert (ltyp, null_pointer_node);
2907 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2908
2909 /* protocol_list = */
2910 ltyp = build_pointer_type (objc_v2_protocol_template);
2911 if (protocol_list)
2912 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2913 else
2914 expr = convert (ltyp, null_pointer_node);
2915 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2916
2917 ltyp = objc_prop_list_ptr;
2918 if (property_list)
2919 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2920 else
2921 expr = convert (ltyp, null_pointer_node);
2922 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2923
2924 return objc_build_constructor (type, v);
2925}
2926
2927/* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2928
2929static void
2930generate_v2_category (struct imp_entry *impent)
2931{
2932 tree initlist, cat_name_expr, class_name_expr;
2933 tree protocol_decl, category, props, t;
2934 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2935 tree cat = impent->imp_context;
2936 tree cat_decl = impent->class_decl;
2937 location_t loc;
2938 char buf[BUFSIZE];
2939
2940 loc = DECL_SOURCE_LOCATION (cat_decl);
2941
2942 /* ??? not sure this is really necessary, the following references should
2943 force appropriate linkage linkage...
2944 -- but ... ensure a reference to the class... */
2945 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2946 /* ... which we ignore so force it out.. */
2947 DECL_PRESERVE_P (t) = 1;
2948
2949 snprintf (s: buf, BUFSIZE, format: "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2950 class_name_expr = create_extern_decl (objc_v2_class_template, name: buf);
2951 class_name_expr = build_fold_addr_expr (class_name_expr);
2952
2953 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2954 category = lookup_category (klass: impent->imp_template, CLASS_SUPER_NAME (cat));
2955
2956 if (category && CLASS_PROTOCOL_LIST (category))
2957 {
2958 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2959 protocol_decl = generate_v2_protocol_list (i_or_p: category, klass_ctxt: cat);
2960 }
2961 else
2962 protocol_decl = NULL_TREE;
2963
2964/* decl = update_var_decl(impent->class_decl); */
2965
2966 props = generate_v2_property_table (NULL_TREE, klass_ctxt: cat);
2967
2968 if (CLASS_NST_METHODS (cat))
2969 {
2970 snprintf (s: buf, BUFSIZE, format: "_OBJC_CategoryInstanceMethods_%s_%s",
2971 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2972 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2973 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), name: buf,
2974 meta_cati_meth);
2975 }
2976
2977 if (CLASS_CLS_METHODS (cat))
2978 {
2979 snprintf (s: buf, BUFSIZE, format: "_OBJC_CategoryClassMethods_%s_%s",
2980 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2981 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2982 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), name: buf,
2983 meta_catc_meth);
2984 }
2985
2986 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2987 cat_name: cat_name_expr, class_name: class_name_expr,
2988 inst_methods, class_methods,
2989 protocol_list: protocol_decl, property_list: props, loc);
2990
2991 finish_var_decl (cat_decl, initlist);
2992 impent->class_decl = cat_decl;
2993
2994 /* Add to list of pointers in __category_list section. */
2995 objc_v2_add_to_category_list (decl: cat_decl);
2996 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2997 objc_v2_add_to_nonlazy_category_list (decl: cat_decl);
2998}
2999
3000/* This routine declares a variable to hold the offset for ivar
3001 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
3002
3003struct GTY(()) ivarref_entry
3004{
3005 tree decl;
3006 tree offset;
3007};
3008
3009static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
3010
3011static tree
3012ivar_offset_ref (tree class_name, tree field_decl)
3013{
3014 tree decl, field_decl_id;
3015 ivarref_entry e;
3016 bool global_var;
3017 char buf[512];
3018
3019 create_ivar_offset_name (buf, class_name, field_decl);
3020 field_decl_id = get_identifier (buf);
3021
3022 if (ivar_offset_refs)
3023 {
3024 int count;
3025 ivarref_entry *ref;
3026 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3027 if (DECL_NAME (ref->decl) == field_decl_id)
3028 return ref->decl;
3029 }
3030 else
3031 /* Somewhat arbitrary initial provision. */
3032 vec_alloc (v&: ivar_offset_refs, nelems: 32);
3033
3034 /* We come here if we don't find a match or at the start. */
3035 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
3036 if (global_var)
3037 decl = create_global_decl (TREE_TYPE (size_zero_node), name: buf);
3038 else
3039 decl = create_hidden_decl (TREE_TYPE (size_zero_node), name: buf);
3040
3041 /* Identify so that we can indirect these where the ABI requires. */
3042 OBJCMETA (decl, objc_meta, meta_ivar_ref);
3043
3044 e.decl = decl;
3045 e.offset = byte_position (field_decl);
3046 vec_safe_push (v&: ivar_offset_refs, obj: e);
3047 return decl;
3048}
3049
3050/* This routine builds initializer-list needed to initialize 'struct
3051 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
3052 'struct ivar_t' and FIELD_DECL is list of ivars for the target
3053 class. */
3054
3055static tree
3056build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
3057{
3058 vec<constructor_elt, va_gc> *inits = NULL;
3059
3060 do
3061 {
3062 vec<constructor_elt, va_gc> *ivar = NULL;
3063 int val;
3064 tree id;
3065
3066 /* Unnamed bitfields are ignored. */
3067 if (!DECL_NAME (field_decl))
3068 {
3069 field_decl = DECL_CHAIN (field_decl);
3070 continue;
3071 }
3072
3073 /* Set offset. */
3074 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3075 build_unary_op (input_location,
3076 ADDR_EXPR,
3077 ivar_offset_ref (class_name,
3078 field_decl), 0));
3079
3080 /* Set name. */
3081 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3082 add_objc_string (DECL_NAME (field_decl),
3083 meth_var_names));
3084
3085 /* Set type. */
3086 id = add_objc_string (ident: encode_field_decl (field_decl),
3087 meth_var_types);
3088 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
3089
3090 /* Set alignment. */
3091 val = DECL_ALIGN_UNIT (field_decl);
3092 val = exact_log2 (x: val);
3093 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3094 build_int_cst (integer_type_node, val));
3095
3096 /* Set size. */
3097 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
3098 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3099 build_int_cst (integer_type_node, val));
3100
3101 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3102 objc_build_constructor (type, ivar));
3103
3104 do
3105 field_decl = DECL_CHAIN (field_decl);
3106 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
3107 }
3108 while (field_decl);
3109
3110 return objc_build_constructor (build_array_type (type, 0), inits);
3111}
3112
3113/*
3114 struct ivar_list_t
3115 {
3116 uint32 entsize;
3117 uint32 count;
3118 struct iver_t list[count];
3119 };
3120*/
3121
3122static tree
3123build_v2_ivar_list_t_template (tree list_type, int size)
3124{
3125 tree objc_ivar_list_record;
3126 tree decls, *chain = NULL;
3127
3128 /* Anonymous. */
3129 objc_ivar_list_record = objc_start_struct (NULL_TREE);
3130
3131 /* uint32 entsize; */
3132 decls = add_field_decl (integer_type_node, "entsize", &chain);
3133
3134 /* uint32 count; */
3135 add_field_decl (integer_type_node, "count", &chain);
3136
3137 /* struct objc_ivar ivar_list[]; */
3138 add_field_decl (build_sized_array_type (list_type, size),
3139 "list", &chain);
3140
3141 objc_finish_struct (objc_ivar_list_record, decls);
3142 return objc_ivar_list_record;
3143}
3144
3145/* This routine declares a static variable of type 'struct
3146 ivar_list_t' and initializes it. chain is the source of the data,
3147 name is the name for the var. attr is the meta-data section tag
3148 attribute. templ is the implementation template for the class. */
3149
3150static tree
3151generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
3152{
3153 tree decl, initlist, ivar_list_template;
3154 vec<constructor_elt, va_gc> *inits = NULL;
3155 int size, ivar_t_size;
3156
3157 if (!chain || !name || !(size = ivar_list_length (t: chain)))
3158 return NULL_TREE;
3159
3160 generating_instance_variables = 1;
3161 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
3162 size);
3163
3164 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
3165 objc_v2_ivar_template, field_decl: chain);
3166 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
3167
3168 decl = start_var_decl (ivar_list_template, name);
3169 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3170 build_int_cst (integer_type_node, ivar_t_size));
3171 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3172 build_int_cst (integer_type_node, size));
3173 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
3174 OBJCMETA (decl, objc_meta, attr);
3175 DECL_USER_ALIGN (decl) = 1;
3176 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
3177 generating_instance_variables = 0;
3178 return decl;
3179}
3180
3181/* Routine to build initializer list to initialize objects of type
3182 struct class_t; */
3183
3184static tree
3185build_v2_class_t_initializer (tree type, tree isa, tree superclass,
3186 tree ro, tree cache, tree vtable)
3187{
3188 vec<constructor_elt, va_gc> *initlist = NULL;
3189
3190 /* isa */
3191 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
3192
3193 /* superclass */
3194 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
3195
3196 /* cache */
3197 if (cache)
3198 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
3199 else
3200 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3201
3202 /* vtable */
3203 if (vtable)
3204 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
3205 else
3206 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3207
3208 /* ro */
3209 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
3210
3211 return objc_build_constructor (type, initlist);
3212}
3213
3214/* Routine to build object of struct class_ro_t { ... }; */
3215
3216static tree
3217build_v2_class_ro_t_initializer (tree type, tree name,
3218 unsigned int flags, unsigned int instanceStart,
3219 unsigned int instanceSize,
3220 tree ivarLayout,
3221 tree baseMethods, tree baseProtocols,
3222 tree ivars, tree property_list)
3223{
3224 tree expr, unsigned_char_star, ltyp;
3225 location_t loc;
3226 vec<constructor_elt, va_gc> *initlist = NULL;
3227
3228 /* TODO: fish out the real location from somewhere. */
3229 loc = UNKNOWN_LOCATION;
3230
3231 /* flags */
3232 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3233 build_int_cst (integer_type_node, flags));
3234
3235 /* instanceStart */
3236 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3237 build_int_cst (integer_type_node, instanceStart));
3238
3239 /* instanceSize */
3240 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3241 build_int_cst (integer_type_node, instanceSize));
3242
3243 /* This ABI is currently only used on m64 NeXT. We always
3244 explicitly declare the alignment padding. */
3245 /* reserved, pads alignment. */
3246 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3247 integer_zero_node);
3248
3249 /* ivarLayout */
3250 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3251 if (ivarLayout)
3252 expr = ivarLayout;
3253 else
3254 expr = convert (unsigned_char_star, null_pointer_node);
3255 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3256
3257 /* name */
3258 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3259
3260 /* baseMethods */
3261 ltyp = objc_method_list_ptr;
3262 if (baseMethods)
3263 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3264 else
3265 expr = convert (ltyp, null_pointer_node);
3266 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3267
3268 /* baseProtocols */
3269 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3270 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3271 if (baseProtocols)
3272 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3273 else
3274 expr = convert (ltyp, null_pointer_node);
3275 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3276
3277 /* ivars */
3278 ltyp = objc_v2_ivar_list_ptr;
3279 if (ivars)
3280 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3281 else
3282 expr = convert (ltyp, null_pointer_node);
3283 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3284
3285 /* TODO: We don't yet have the weak/strong stuff... */
3286 /* weakIvarLayout */
3287 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3288 convert (unsigned_char_star, null_pointer_node));
3289
3290 /* property list */
3291 ltyp = objc_prop_list_ptr;
3292 if (property_list)
3293 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3294 else
3295 expr = convert (ltyp, null_pointer_node);
3296 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3297 return objc_build_constructor (type, initlist);
3298}
3299
3300static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
3301
3302/* Record a name as needing a catcher. */
3303static void
3304objc_v2_add_to_ehtype_list (tree name)
3305{
3306 ident_data_tuple e;
3307 if (ehtype_list)
3308 {
3309 int count = 0;
3310 ident_data_tuple *ref;
3311
3312 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3313 if (ref->ident == name)
3314 return; /* Already entered. */
3315 }
3316 else
3317 /* Arbitrary initial count. */
3318 vec_alloc (v&: ehtype_list, nelems: 8);
3319
3320 /* Not found, or new list. */
3321 e.ident = name;
3322 e.data = NULL_TREE;
3323 vec_safe_push (v&: ehtype_list, obj: e);
3324}
3325
3326static void
3327generate_v2_class_structs (struct imp_entry *impent)
3328{
3329 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3330 tree field, firstIvar, chain;
3331 tree class_superclass_expr, metaclass_superclass_expr, props;
3332 /* TODO: figure out how to compute this. */
3333 tree ivarLayout = NULL_TREE;
3334 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3335 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3336 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3337 location_t loc;
3338 char buf[BUFSIZE];
3339 unsigned int instanceStart, instanceSize;
3340 unsigned int flags = 0x01; /* RO_META */
3341 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3342 : 0 ;
3343
3344 class_decl = impent->class_decl;
3345 metaclass_decl = impent->meta_decl;
3346 loc = DECL_SOURCE_LOCATION (class_decl);
3347
3348 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3349 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3350#ifdef OBJCPLUS
3351 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3352 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3353#endif
3354
3355 /* Generation of data for meta class. */
3356 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3357 if (my_super_id)
3358 {
3359 /* Compute reference to root's name. For a meta class, "isa" is
3360 a reference to the root class name. */
3361 tree my_root_id = my_super_id;
3362 tree my_root_int, interface;
3363 do
3364 {
3365 my_root_int = lookup_interface (my_root_id);
3366
3367 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3368 my_root_id = CLASS_SUPER_NAME (my_root_int);
3369 else
3370 break;
3371 }
3372 while (1);
3373
3374 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3375 create extern if not already declared. */
3376 snprintf (s: buf, BUFSIZE, format: "OBJC_METACLASS_$_%s",
3377 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3378 root_expr = create_extern_decl (objc_v2_class_template, name: buf);
3379 root_expr = build_fold_addr_expr (root_expr);
3380
3381 /* Install class `isa' and `super' pointers at runtime. */
3382 interface = lookup_interface (my_super_id);
3383 gcc_assert (interface);
3384 /* Similarly, for OBJC_CLASS_$_<interface>... */
3385 snprintf (s: buf, BUFSIZE, format: "OBJC_CLASS_$_%s",
3386 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3387 class_superclass_expr = create_extern_decl (objc_v2_class_template, name: buf);
3388 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3389 /* ... and for OBJC_METACLASS_$_<interface>. */
3390 snprintf (s: buf, BUFSIZE, format: "OBJC_METACLASS_$_%s",
3391 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3392 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, name: buf);
3393 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3394 }
3395 else
3396 {
3397 /* Root class. */
3398 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3399 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3400 class_superclass_expr = build_int_cst (NULL_TREE, 0);
3401 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */
3402 }
3403
3404 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3405 {
3406 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3407 protocol_decl = generate_v2_protocol_list (i_or_p: impent->imp_template,
3408 klass_ctxt: impent->imp_context);
3409 }
3410 else
3411 protocol_decl = 0;
3412
3413 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3414 class_names);
3415
3416 if (CLASS_CLS_METHODS (impent->imp_context))
3417 {
3418 snprintf (s: buf, BUFSIZE, format: "_OBJC_ClassMethods_%s",
3419 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3420 class_methods =
3421 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3422 name: buf, meta_clac_meth);
3423 }
3424
3425 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3426
3427 /* Currently there are no class ivars and generation of class
3428 variables for the root of the inheritance has been removed. It
3429 causes multiple defines if there are two root classes in the
3430 link, because each will define its own identically-named offset
3431 variable. */
3432
3433 class_ivars = NULL_TREE;
3434 /* TODO: Add total size of class variables when implemented. */
3435 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3436
3437 /* So now build the META CLASS structs. */
3438 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3439
3440 decl = start_var_decl (objc_v2_class_ro_template,
3441 newabi_append_ro (IDENTIFIER_POINTER
3442 (DECL_NAME (metaclass_decl))));
3443 /* TODO: ivarLayout needs t be built. */
3444 initlist =
3445 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name: name_expr,
3446 flags: (flags | cls_flags), instanceStart,
3447 instanceSize, ivarLayout,
3448 baseMethods: class_methods, baseProtocols: protocol_decl,
3449 ivars: class_ivars, NULL_TREE);
3450 /* The ROs sit in the default const section. */
3451 OBJCMETA (decl, objc_meta, meta_base);
3452 DECL_USER_ALIGN (decl) = 1;
3453 finish_var_decl (decl, initlist);
3454
3455 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3456 initlist =
3457 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3458 isa: root_expr,
3459 superclass: metaclass_superclass_expr,
3460 build_fold_addr_expr (decl),
3461 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3462 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3463 /* The class section attributes are set when they are created. */
3464 DECL_USER_ALIGN (metaclass_decl) = 1;
3465 finish_var_decl (metaclass_decl, initlist);
3466 impent->meta_decl = metaclass_decl;
3467
3468 /* So now build the CLASS structs. */
3469
3470 flags = 0x0; /* ... */
3471 if (!my_super_id)
3472 flags |= 0x02; /* RO_ROOT: this is a root class */
3473
3474 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3475 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3476
3477 if (objc2_objc_exception_attr (impent->imp_template))
3478 flags |= 0x20; /* RO_EXCEPTION */
3479
3480 if (CLASS_NST_METHODS (impent->imp_context))
3481 {
3482 snprintf (s: buf, BUFSIZE, format: "_OBJC_InstanceMethods_%s",
3483 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3484 inst_methods =
3485 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3486 name: buf, meta_clai_meth);
3487 }
3488
3489 /* Sort out the ivars before we try to compute the class sizes. */
3490 if ((chain = CLASS_IVARS (impent->imp_template)))
3491 {
3492 snprintf (s: buf, BUFSIZE, format: "_OBJC_InstanceIvars_%s",
3493 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3494 inst_ivars = generate_v2_ivars_list (chain, name: buf, meta_clai_vars,
3495 templ: impent->imp_template);
3496 }
3497
3498 /* Compute instanceStart. */
3499 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3500 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3501 if (my_super_id && field && TREE_CHAIN (field))
3502 field = TREE_CHAIN (field);
3503
3504 firstIvar = field;
3505
3506 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3507 firstIvar = TREE_CHAIN (firstIvar);
3508
3509 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3510
3511 /* Compute instanceSize. */
3512 while (field && TREE_CHAIN (field)
3513 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3514 field = TREE_CHAIN (field);
3515
3516 if (field && TREE_CODE (field) == FIELD_DECL)
3517 instanceSize = int_byte_position (field) * BITS_PER_UNIT
3518 + tree_to_shwi (DECL_SIZE (field));
3519 else
3520 instanceSize = 0;
3521 instanceSize /= BITS_PER_UNIT;
3522
3523 props = generate_v2_property_table (NULL_TREE, klass_ctxt: impent->imp_context);
3524
3525 /* If the class has no ivars, instanceStart should be set to the
3526 superclass's instanceSize. */
3527 instanceStart =
3528 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3529 : instanceSize;
3530
3531 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3532 decl = start_var_decl (objc_v2_class_ro_template,
3533 newabi_append_ro (IDENTIFIER_POINTER
3534 (DECL_NAME (class_decl))));
3535
3536 initlist =
3537 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name: name_expr,
3538 flags: (flags | cls_flags), instanceStart,
3539 instanceSize, ivarLayout,
3540 baseMethods: inst_methods, baseProtocols: protocol_decl,
3541 ivars: inst_ivars, property_list: props);
3542 /* The ROs sit in the default const section. */
3543 OBJCMETA (decl, objc_meta, meta_base);
3544 DECL_USER_ALIGN (decl) = 1;
3545 finish_var_decl (decl, initlist);
3546
3547 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3548 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3549 build_fold_addr_expr (metaclass_decl),
3550 superclass: class_superclass_expr,
3551 build_fold_addr_expr (decl),
3552 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3553 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3554
3555 /* The class section attributes are set when they are created. */
3556 DECL_USER_ALIGN (class_decl) = 1;
3557 finish_var_decl (class_decl, initlist);
3558 impent->class_decl = class_decl;
3559
3560 objc_v2_add_to_class_list (global_class_decl: class_decl);
3561 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3562 objc_v2_add_to_nonlazy_class_list (global_class_decl: class_decl);
3563
3564 if (flags & 0x20) /* RO_EXCEPTION */
3565 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3566}
3567
3568/* This routine outputs the (ivar_reference_offset, offset)
3569 tuples. */
3570
3571static void
3572build_v2_ivar_offset_ref_table (void)
3573{
3574 int count;
3575 ivarref_entry *ref;
3576
3577 if (!vec_safe_length (v: ivar_offset_refs))
3578 return;
3579
3580 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3581 finish_var_decl (ref->decl, ref->offset);
3582}
3583
3584static void
3585objc_generate_v2_next_metadata (void)
3586{
3587 struct imp_entry *impent;
3588
3589 /* FIXME: Make sure that we generate no metadata if there is nothing
3590 to put into it. */
3591
3592 gcc_assert (!objc_static_instances); /* Not for NeXT */
3593
3594 build_metadata_templates ();
3595
3596 for (impent = imp_list; impent; impent = impent->next)
3597 {
3598 /* If -gen-decls is present, Dump the @interface of each class.
3599 TODO: Dump the classes in the order they were found, rather
3600 than in reverse order as we are doing now. */
3601 if (flag_gen_declaration)
3602 dump_interface (gen_declaration_file, impent->imp_context);
3603
3604 /* all of the following reference the string pool... */
3605 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3606 generate_v2_class_structs (impent);
3607 else
3608 generate_v2_category (impent);
3609 }
3610
3611 build_next_selector_translation_table ();
3612 build_v2_message_ref_translation_table ();
3613
3614 /* This will add "Protocol" to the class refs. */
3615 generate_v2_protocols ();
3616
3617 build_v2_classrefs_table ();
3618 build_v2_super_classrefs_table (/*metaclass= */false);
3619 build_v2_super_classrefs_table (/*metaclass= */true);
3620
3621 build_v2_ivar_offset_ref_table ();
3622
3623 build_v2_protocol_list_translation_table ();
3624 build_v2_protocol_list_address_table ();
3625
3626 build_v2_address_table (src: class_list, nam: "_OBJC_ClassList$",
3627 meta_label_classlist);
3628 build_v2_address_table (src: category_list, nam: "_OBJC_CategoryList$",
3629 meta_label_categorylist);
3630 build_v2_address_table (src: nonlazy_class_list, nam: "_OBJC_NonLazyClassList$",
3631 meta_label_nonlazy_classlist);
3632 build_v2_address_table (src: nonlazy_category_list, nam: "_OBJC_NonLazyCategoryList$",
3633 meta_label_nonlazy_categorylist);
3634
3635 /* Generate catch objects for eh, if any are needed. */
3636 build_v2_eh_catch_objects ();
3637
3638 /* Emit the string table last. */
3639 generate_strings ();
3640}
3641
3642/* NOTE --- Output NeXT V2 Exceptions --- */
3643
3644static GTY(()) tree objc_v2_ehtype_template;
3645static GTY(()) tree next_v2_ehvtable_decl;
3646static GTY(()) tree next_v2_EHTYPE_id_decl;
3647
3648static void
3649build_v2_ehtype_template (void)
3650{
3651 tree decls, *chain = NULL;
3652 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3653
3654 /* void *_objc_ehtype_vtable; */
3655 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3656
3657 /* const char *className; */
3658 add_field_decl (string_type_node, "className", &chain);
3659
3660 /* struct class_t *const cls; */
3661 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3662
3663 objc_finish_struct (objc_v2_ehtype_template, decls);
3664}
3665
3666/* Template for the Objective-C family typeinfo type for ABI=2. This
3667 starts off the same as the gxx/cxx eh typeinfo.
3668
3669 struct _objc_ehtype_t
3670 {
3671 void *_objc_ehtype_vtable_ptr; - as per c++
3672 const char *className; - as per c++
3673 struct class_t *const cls;
3674 }
3675*/
3676
3677/* This routine builds initializer list for object of type struct _objc_ehtype_t.
3678*/
3679
3680static tree
3681objc2_build_ehtype_initializer (tree name, tree cls)
3682{
3683 vec<constructor_elt, va_gc> *initlist = NULL;
3684 tree addr, offs;
3685
3686 /* This is done the same way as c++, missing the two first entries
3687 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3688 runtime source about this so, perhaps, this will change at some
3689 point. */
3690 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3691 if (!next_v2_ehvtable_decl)
3692 {
3693 next_v2_ehvtable_decl =
3694 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3695 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3696 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3697 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3698 }
3699 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3700 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3701 addr = fold_build_pointer_plus (addr, offs);
3702
3703 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3704
3705 /* className */
3706 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3707
3708 /* cls */
3709 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3710
3711 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3712}
3713
3714static tree
3715build_ehtype (tree name, const char *eh_name, bool weak)
3716{
3717 tree name_expr, class_name_expr, ehtype_decl, inits;
3718
3719 name_expr = add_objc_string (ident: name, class_names);
3720 /* Extern ref. for the class. ??? Maybe we can look this up
3721 somewhere. */
3722 class_name_expr =
3723 create_extern_decl (objc_v2_class_template,
3724 name: objc_build_internal_classname (ident: name, metaclass: false));
3725 class_name_expr = build_fold_addr_expr (class_name_expr);
3726 ehtype_decl = create_global_decl (type: objc_v2_ehtype_template, name: eh_name);
3727 if (weak)
3728 DECL_WEAK (ehtype_decl) = 1;
3729 inits = objc2_build_ehtype_initializer (name: name_expr, cls: class_name_expr);
3730 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3731 DECL_USER_ALIGN (ehtype_decl) = 1;
3732 finish_var_decl (ehtype_decl, inits);
3733 return ehtype_decl;
3734}
3735
3736/* This routine returns TRUE if CLS or any of its super classes has
3737 __attribute__ ((objc_exception)). */
3738
3739static bool
3740objc2_objc_exception_attr (tree cls)
3741{
3742 while (cls)
3743 {
3744 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3745 return true;
3746 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3747 }
3748
3749 return false;
3750}
3751
3752static bool
3753is_implemented (tree name)
3754{
3755 struct imp_entry *t;
3756 for (t = imp_list; t; t = t->next)
3757 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3758 && CLASS_NAME (t->imp_template) == name)
3759 return true;
3760
3761 return false;
3762}
3763
3764/* We will build catch objects:
3765 for any type implemented here.
3766 for any type used in a catch that has no exception attribute. */
3767static void build_v2_eh_catch_objects (void)
3768{
3769 int count=0;
3770 ident_data_tuple *ref;
3771
3772 if (!vec_safe_length (v: ehtype_list))
3773 return;
3774
3775 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3776 {
3777 char buf[BUFSIZE];
3778 bool impl = is_implemented (name: ref->ident);
3779 bool excpt = objc2_objc_exception_attr (cls: lookup_interface (ref->ident));
3780 snprintf (s: buf, BUFSIZE, format: "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3781 if (!impl && excpt)
3782 /* The User says this class has a catcher already. */
3783 ref->data = create_extern_decl (type: objc_v2_ehtype_template, name: buf);
3784 else
3785 /* Create a catcher, weak if it wasn't marked. */
3786 ref->data = build_ehtype (name: ref->ident, eh_name: buf, weak: !excpt);
3787 }
3788}
3789
3790static tree
3791lookup_ehtype_ref (tree id)
3792{
3793 int count=0;
3794 ident_data_tuple *ref;
3795
3796 if (!vec_safe_length (v: ehtype_list))
3797 return NULL_TREE;
3798
3799 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3800 if (ref->ident == id)
3801 return ref->data;
3802 return NULL_TREE;
3803}
3804
3805/* This hook, called via lang_eh_runtime_type, generates a runtime
3806 object which is either the address of the 'OBJC_EHTYPE_$_class'
3807 object or address of external OBJC_EHTYPE_id object. */
3808static tree
3809next_runtime_02_eh_type (tree type)
3810{
3811 tree t;
3812
3813 if (type == error_mark_node
3814 /*|| errorcount || sorrycount*/)
3815 goto err_mark_in;
3816
3817 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3818 {
3819 if (!next_v2_EHTYPE_id_decl)
3820 {
3821 /* This is provided by the Apple/NeXT libobjc.dylib so we
3822 need only to reference it. */
3823 next_v2_EHTYPE_id_decl =
3824 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3825 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3826 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3827 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3828 }
3829 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3830 }
3831
3832 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3833 {
3834#ifdef OBJCPLUS
3835 /* This routine is also called for c++'s catch clause; in which
3836 case, we use c++'s typeinfo decl. */
3837 return build_eh_type_type (type);
3838#else
3839 error ("non-objective-c type %qT cannot be caught", type);
3840 goto err_mark_in;
3841#endif
3842 }
3843 else
3844 t = OBJC_TYPE_NAME (TREE_TYPE (type));
3845
3846 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3847 t = lookup_ehtype_ref (id: t);
3848 if (!t)
3849 goto err_mark_in;
3850
3851 return build_fold_addr_expr (t);
3852
3853err_mark_in:
3854 return error_mark_node;
3855}
3856
3857static GTY(()) tree objc_eh_personality_decl;
3858
3859static tree
3860objc_eh_personality (void)
3861{
3862 if (!objc_eh_personality_decl)
3863 objc_eh_personality_decl = build_personality_function ("objc");
3864 return objc_eh_personality_decl;
3865}
3866
3867/* NOTE --- interfaces --- */
3868
3869static tree
3870build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3871{
3872 tree t;
3873 if (rethrown)
3874 /* We have a separate re-throw entry. */
3875 t = build_function_call_vec (loc, vNULL, objc_rethrow_exception_decl,
3876 NULL, NULL);
3877 else
3878 {
3879 /* Throw like the others... */
3880 vec<tree, va_gc> *parms;
3881 vec_alloc (v&: parms, nelems: 1);
3882 parms->quick_push (obj: throw_expr);
3883 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl,
3884 parms, 0);
3885 vec_free (v&: parms);
3886 }
3887 return add_stmt (t);
3888}
3889
3890/* Build __builtin_eh_pointer. */
3891
3892static tree
3893objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3894{
3895 tree t;
3896 t = builtin_decl_explicit (fncode: BUILT_IN_EH_POINTER);
3897 t = build_call_expr (t, 1, integer_zero_node);
3898 return fold_convert (objc_object_type, t);
3899}
3900
3901static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3902 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3903{
3904 tree t;
3905
3906 /* Record the data for the catch in the try context so that we can
3907 finalize it later. Ellipsis is signalled by a NULL entry. */
3908 if (ellipsis)
3909 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3910 else
3911 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3912 (*cur_try_context)->current_catch = t;
3913
3914 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3915 t = objc_build_exc_ptr (x: cur_try_context);
3916 t = convert (TREE_TYPE (decl), t);
3917 /* FIXME: location. */
3918 if (type && type != error_mark_node)
3919 {
3920 t = build1(NOP_EXPR, ptr_type_node, t);
3921 t = build_function_call (input_location, objc2_begin_catch_decl,
3922 tree_cons (NULL_TREE, t, NULL_TREE));
3923
3924 /* We might want to build a catch object for this (if it's not
3925 id). */
3926 if (POINTER_TYPE_P (type)
3927 && !objc_is_object_id (TREE_TYPE (type))
3928 && TYPED_OBJECT (TREE_TYPE (type)))
3929 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3930 }
3931 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3932}
3933
3934/* try { catch-body } finally { objc_end_catch (); } */
3935static void
3936finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3937{
3938 struct objc_try_context *ct;
3939 tree try_exp, func, *l, t ;
3940 location_t loc = (*cur_try_context)->try_locus;
3941
3942 if (!curr_catch || curr_catch == error_mark_node)
3943 return;
3944
3945 t = CATCH_BODY (curr_catch);
3946 if (TREE_CODE (t) == BIND_EXPR)
3947 {
3948 /* Usual case of @catch (objc-expr). */
3949 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3950 BIND_EXPR_BODY (t) = NULL_TREE;
3951 l = &BIND_EXPR_BODY (t);
3952 }
3953 else
3954 {
3955 /* NULL entry, meaning @catch (...). */
3956 objc_begin_try_stmt (loc, t);
3957 CATCH_BODY (curr_catch) = NULL_TREE;
3958 l = &CATCH_BODY (curr_catch);
3959 }
3960
3961 /* Pick up the new context we made in begin_try above... */
3962 ct = *cur_try_context;
3963 func = build_function_call_vec (loc, vNULL, objc2_end_catch_decl, NULL,
3964 NULL);
3965 append_to_statement_list (func, &ct->finally_body);
3966 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3967 *cur_try_context = ct->outer;
3968 free (ptr: ct);
3969 append_to_statement_list (try_exp, l);
3970 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3971}
3972
3973static tree
3974finish_try_stmt (struct objc_try_context **cur_try_context)
3975{
3976 struct objc_try_context *c = *cur_try_context;
3977 tree stmt = c->try_body;
3978 if (c->catch_list)
3979 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3980 if (c->finally_body)
3981 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3982 return stmt;
3983}
3984
3985#include "gt-objc-objc-next-runtime-abi-02.h"
3986

source code of gcc/objc/objc-next-runtime-abi-02.cc