]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/objc/objc-next-runtime-abi-02.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / objc / objc-next-runtime-abi-02.cc
CommitLineData
d764a8e6 1/* Next Runtime (ABI-2) private.
a945c346 2 Copyright (C) 2011-2024 Free Software Foundation, Inc.
d764a8e6
IS
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.
944fb799 24
d4c433f9
NP
25 This version is intended to match (logically) the output of Apple's
26 4.2.1 compiler. */
d764a8e6
IS
27
28#include "config.h"
29#include "system.h"
30#include "coretypes.h"
314e6352 31#include "tree.h"
d8a2d370 32#include "stringpool.h"
314e6352 33#include "attribs.h"
d764a8e6
IS
34
35#ifdef OBJCPLUS
d4a10d0a 36#include "cp/cp-tree.h"
d764a8e6 37#else
d4a10d0a
SB
38#include "c/c-tree.h"
39#include "c/c-lang.h"
d764a8e6
IS
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
d764a8e6 52#include "target.h"
d764a8e6 53#include "tree-iterator.h"
816da497 54#include "opts.h"
d764a8e6 55
d764a8e6 56#include "objc-runtime-hooks.h"
d764a8e6 57#include "objc-runtime-shared-support.h"
c9419fae 58#include "objc-next-metadata-tags.h"
f027ee7c 59#include "objc-encoding.h"
d764a8e6
IS
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"
3ba0afac
IS
68#define TAG_MSGSENDID "objc_msgSendId"
69#define TAG_MSGSENDSUPER "objc_msgSendSuper2"
d764a8e6 70#define TAG_MSGSEND_STRET "objc_msgSend_stret"
3ba0afac
IS
71#define TAG_MSGSENDID_STRET "objc_msgSendId_stret"
72#define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper2_stret"
73
8703bf5d 74#define USE_FIXUP_BEFORE 100600
3ba0afac
IS
75#define TAG_FIXUP "_fixup"
76
d764a8e6
IS
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
944fb799 91{
d764a8e6
IS
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,
944fb799 101
d764a8e6
IS
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,
944fb799 111
d764a8e6
IS
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,
944fb799 119
d764a8e6
IS
120 /* Exceptions - related. */
121 OCTI_V2_BEGIN_CATCH_DECL,
122 OCTI_V2_END_CATCH_DECL,
123 OCTI_V2_RETHROW_DECL,
944fb799 124
d764a8e6
IS
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 \
944fb799 138 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
d764a8e6
IS
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 \
944fb799 144 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
d764a8e6
IS
145
146/* struct message_ref_t* */
944fb799 147#define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
d764a8e6
IS
148/* struct super_super_message_ref_t */
149#define objc_v2_super_selector_type \
944fb799 150 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
d764a8e6 151#define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
944fb799 152#define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
d764a8e6
IS
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 */
944fb799 164#define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
d764a8e6 165/* objc_msgSend_stret_fixup_rtp */
944fb799 166#define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
d764a8e6 167/* objc_msgSendId_fixup_rtp */
944fb799 168#define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
d764a8e6
IS
169/* objc_msgSendId_stret_fixup_rtp */
170#define umsg_id_stret_fixup_decl \
944fb799 171 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
d764a8e6
IS
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
d764a8e6
IS
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);
9771b263
DN
211static void next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **,
212 tree, int, int);
d764a8e6
IS
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
3cc2dd4b 234/* TODO: Use an objc-map. */
d764a8e6
IS
235static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
236
944fb799 237bool
d764a8e6
IS
238objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
239{
766090c2 240 extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
d764a8e6 241
79866639 242 if (flag_objc_sjlj_exceptions)
d764a8e6 243 {
a9c697b8
MS
244 inform (UNKNOWN_LOCATION,
245 "%<-fobjc-sjlj-exceptions%> is ignored for "
246 "%<-fnext-runtime%> when %<-fobjc-abi-version%> "
247 "greater than 1");
d764a8e6
IS
248 flag_objc_sjlj_exceptions = 0;
249 }
250
de0b250b 251 /* NeXT ABI 2 is intended to default to checking for nil receivers. */
00f34291 252 if (! OPTION_SET_P (flag_objc_nilcheck))
de0b250b
IS
253 flag_objc_nilcheck = 1;
254
d764a8e6
IS
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.
944fb799 295
d764a8e6
IS
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");
ecd616f6
IS
312 meta_category = meta_base;
313 meta_protocol = get_identifier ("V2_PCOL");
d764a8e6
IS
314
315 meta_clac_vars =
316 meta_clai_vars = meta_base;
317
318 meta_clac_meth =
319 meta_clai_meth =
320 meta_catc_meth =
944fb799 321 meta_cati_meth =
d764a8e6
IS
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
a788c455
IS
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");
d764a8e6
IS
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");
eb870e5e
IS
353
354 meta_ivar_ref = get_identifier ("V2_IVRF");
d764a8e6
IS
355}
356
357static void next_runtime_02_initialize (void)
358{
359 tree type;
360#ifdef OBJCPLUS
c2beaa02
NP
361 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
362 default. */
00f34291 363 if (!OPTION_SET_P (flag_objc_call_cxx_cdtors))
d764a8e6
IS
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
bb93020f
IS
375 /* SEL typedef. */
376 type = lang_hooks.decls.pushdecl (build_decl (input_location,
377 TYPE_DECL,
378 objc_selector_name,
379 objc_selector_type));
ed94172c 380 suppress_warning (type);
bb93020f 381
d764a8e6
IS
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
944fb799
MS
387 objc_v2_ivar_list_ptr =
388 build_pointer_type (xref_tag (RECORD_TYPE,
d764a8e6
IS
389 get_identifier ("_ivar_list_t")));
390
944fb799 391 objc_prop_list_ptr =
d764a8e6
IS
392 build_pointer_type (xref_tag (RECORD_TYPE,
393 get_identifier ("_prop_list_t")));
944fb799 394
d764a8e6
IS
395 build_v2_class_templates ();
396 build_v2_super_template ();
397 build_v2_protocol_template ();
398 build_v2_category_template ();
399
8703bf5d 400 bool fixup_p = flag_next_runtime < USE_FIXUP_BEFORE;
3ba0afac
IS
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 (fnam, type, 0, NOT_BUILT_IN,
d764a8e6
IS
419 NULL, NULL_TREE);
420 TREE_NOTHROW (umsg_fixup_decl) = 0;
421
422 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
3ba0afac
IS
423 fnam = fixup_p ? TAG_MSGSEND_STRET TAG_FIXUP : TAG_MSGSEND_STRET;
424 umsg_stret_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
d764a8e6
IS
425 NULL, NULL_TREE);
426 TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
427
428 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
3ba0afac
IS
429 fnam = fixup_p ? TAG_MSGSENDID TAG_FIXUP : TAG_MSGSENDID;
430 umsg_id_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
d764a8e6
IS
431 NULL, NULL_TREE);
432 TREE_NOTHROW (umsg_id_fixup_decl) = 0;
433
3ba0afac
IS
434 /* id objc_msgSendId_stret_fixup_rtp (id, struct message_ref_t*, ...); */
435 fnam = fixup_p ? TAG_MSGSENDID_STRET TAG_FIXUP : TAG_MSGSENDID_STRET;
436 umsg_id_stret_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
d764a8e6
IS
437 NULL, NULL_TREE);
438 TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
439
944fb799 440 /* id objc_msgSendSuper2_fixup_rtp
d764a8e6
IS
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);
3ba0afac
IS
446 fnam = fixup_p ? TAG_MSGSENDSUPER TAG_FIXUP : TAG_MSGSENDSUPER;
447 umsg_id_super2_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
d764a8e6
IS
448 NULL, NULL_TREE);
449 TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
450
944fb799 451 /* id objc_msgSendSuper2_stret_fixup_rtp
d764a8e6 452 (struct objc_super *, struct message_ref_t*, ...); */
3ba0afac
IS
453 fnam = fixup_p ? TAG_MSGSENDSUPER_STRET TAG_FIXUP : TAG_MSGSENDSUPER_STRET;
454 umsg_id_super2_stret_fixup_decl = add_builtin_function (fnam, type, 0,
455 NOT_BUILT_IN, NULL,
456 NULL_TREE);
d764a8e6
IS
457 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
458
459 /* Present in the library, but unused by the FE. */
944fb799 460 /* Protocol *objc_getProtocol (const char *)
d764a8e6
IS
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);
944fb799 479 objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
d764a8e6
IS
480 type, 0, NOT_BUILT_IN,
481 NULL, NULL_TREE);
482
483 /* id objc_getMetaClass (const char *); */
944fb799 484 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
d764a8e6
IS
485 type, 0, NOT_BUILT_IN,
486 NULL, NULL_TREE);
487
c2beaa02
NP
488 /* This is the type of all of the following functions
489 objc_copyStruct(). */
d764a8e6
IS
490 type = build_function_type_list (void_type_node,
491 ptr_type_node,
492 const_ptr_type_node,
944fb799 493 ptrdiff_type_node,
d764a8e6
IS
494 boolean_type_node,
495 boolean_type_node,
496 NULL_TREE);
497 /* Declare the following function:
498 void
944fb799 499 objc_copyStruct (void *destination, const void *source,
c2beaa02 500 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
d764a8e6
IS
501 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
502 type, 0, NOT_BUILT_IN,
503 NULL, NULL_TREE);
504 TREE_NOTHROW (objc_copyStruct_decl) = 0;
505 objc_getPropertyStruct_decl = NULL_TREE;
506 objc_setPropertyStruct_decl = NULL_TREE;
507
79866639 508 gcc_checking_assert (!flag_objc_sjlj_exceptions);
d764a8e6 509
c2beaa02
NP
510 /* Although we warn that fobjc-exceptions is required for exceptions
511 code, we carry on and create it anyway. */
d764a8e6
IS
512
513 /* This can be required, even when exceptions code is not present,
c2beaa02
NP
514 when an __attribute__((objc_exception)) is applied to a
515 class. */
d764a8e6
IS
516 build_v2_ehtype_template ();
517
518 /* void * objc_begin_catch (void *) */
491add72
NF
519 type = build_function_type_list (ptr_type_node,
520 ptr_type_node, NULL_TREE);
d764a8e6
IS
521
522 objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
523 type, 0, NOT_BUILT_IN,
524 NULL, NULL_TREE);
525 TREE_NOTHROW (objc2_begin_catch_decl) = 0;
526
527 /* void objc_end_catch () */
491add72 528 type = build_function_type_list (void_type_node, NULL_TREE);
d764a8e6
IS
529 objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
530 type, 0, NOT_BUILT_IN,
531 NULL, NULL_TREE);
532 TREE_NOTHROW (objc2_end_catch_decl) = 0;
533
534 /* void objc_exception_rethrow (void) */
944fb799 535 objc_rethrow_exception_decl =
d764a8e6
IS
536 add_builtin_function ("objc_exception_rethrow",
537 type, 0, NOT_BUILT_IN,
538 NULL, NULL_TREE);
539 TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
540 using_eh_for_cleanups ();
541 lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
542 lang_hooks.eh_personality = objc_eh_personality;
543}
544
545/* NOTE --- templates --- */
546
c2beaa02
NP
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'. */
d764a8e6 551
c2beaa02
NP
552/* struct _message_ref_t
553 {
d764a8e6
IS
554 IMP messenger;
555 SEL name;
556 };
557 where IMP is: id (*) (id, _message_ref_t*, ...)
558*/
559
c2beaa02
NP
560/* struct _super_message_ref_t
561 {
d764a8e6
IS
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; */
944fb799
MS
579 ptr_message_ref_t =
580 build_pointer_type (xref_tag (RECORD_TYPE,
d764a8e6
IS
581 get_identifier ("_message_ref_t")));
582
944fb799
MS
583 objc_v2_imp_type =
584 build_pointer_type (build_function_type_list
d764a8e6
IS
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; */
944fb799
MS
605 ptr_message_ref_t = build_pointer_type
606 (xref_tag (RECORD_TYPE,
d764a8e6
IS
607 get_identifier ("_super_message_ref_t")));
608
944fb799
MS
609 objc_v2_super_imp_type =
610 build_pointer_type (build_function_type_list
d764a8e6
IS
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);
944fb799 622 objc_v2_super_selector_type =
d764a8e6
IS
623 build_pointer_type (objc_v2_super_message_ref_template);
624}
625
626/* Build following types which represent each class implementation.
627
c2beaa02
NP
628struct class_ro_t
629{
d764a8e6
IS
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
c2beaa02
NP
645struct class_t
646{
d764a8e6
IS
647 struct class_t *isa;
648 struct class_t *superclass;
649 void *cache;
650 IMP *vtable;
944fb799 651
d764a8e6
IS
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 {...} */
944fb799 666 objc_v2_class_ro_template =
d764a8e6
IS
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
c2beaa02 672 /* uint32_t const instanceStart; */
d764a8e6
IS
673 add_field_decl (integer_type_node, "instanceStart", &chain);
674
c2beaa02 675 /* uint32_t const instanceSize; */
d764a8e6
IS
676 add_field_decl (integer_type_node, "instanceSize", &chain);
677
c2beaa02
NP
678 /* This ABI is currently only used on m64 NeXT. We always
679 explicitly declare the alignment padding. */
680 /* uint32_t const reserved; */
d764a8e6
IS
681 add_field_decl (integer_type_node, "reserved", &chain);
682
c2beaa02 683 /* const uint8_t * const ivarLayout; */
d764a8e6
IS
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
c2beaa02 690 /* const struct method_list_t * const baseMethods; */
d764a8e6
IS
691 add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
692
c2beaa02 693 /* const struct objc_protocol_list *const baseProtocols; */
944fb799
MS
694 add_field_decl (build_pointer_type
695 (xref_tag (RECORD_TYPE,
d764a8e6
IS
696 get_identifier (UTAG_V2_PROTOCOL_LIST))),
697 "baseProtocols", &chain);
698
c2beaa02 699 /* const struct ivar_list_t *const ivars; */
944fb799 700 add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
d764a8e6
IS
701
702 /* const uint8_t * const weakIvarLayout; */
703 add_field_decl (cnst_strg_type, "weakIvarLayout", &chain);
704
c2beaa02 705 /* struct _prop_list_t * baseProperties; */
d764a8e6
IS
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 {...} */
944fb799 712 objc_v2_class_template =
d764a8e6
IS
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
c2beaa02 719 /* struct class_t * const superclass; */
d764a8e6
IS
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; */
944fb799 730 add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
d764a8e6
IS
731
732 objc_finish_struct (objc_v2_class_template, decls);
733}
734
c2beaa02
NP
735/* struct _objc_super
736 {
d764a8e6
IS
737 struct _objc_object *self;
738 Class cls;
c2beaa02 739 }; */
d764a8e6
IS
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
c2beaa02
NP
756/* struct protocol_t
757 {
944fb799 758 Class isa;
d764a8e6
IS
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;
6224a8aa
IS
768 const char ** extended_method_types;
769 const char * demangled_name;
770 const struct _prop_list_t * class_properties;
d764a8e6
IS
771 }
772*/
773static void
774build_v2_protocol_template (void)
775{
776 tree decls, *chain = NULL;
777
944fb799 778 objc_v2_protocol_template =
d764a8e6
IS
779 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
780
c2beaa02 781 /* Class isa; */
d764a8e6
IS
782 decls = add_field_decl (objc_object_type, "isa", &chain);
783
c2beaa02 784 /* char *protocol_name; */
d764a8e6
IS
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
c2beaa02 797 /* const struct method_list_t * optionalInstanceMethods; */
d764a8e6
IS
798 add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
799
c2beaa02 800 /* const struct method_list_t * optionalClassMethods; */
d764a8e6
IS
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
c2beaa02 806 /* const uint32_t size; */
d764a8e6
IS
807 add_field_decl (integer_type_node, "size", &chain);
808
c2beaa02 809 /* const uint32_t flags; */
d764a8e6
IS
810 add_field_decl (integer_type_node, "flags", &chain);
811
6224a8aa
IS
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
d764a8e6
IS
822 objc_finish_struct (objc_v2_protocol_template, decls);
823}
824
825/* Build type for a category:
c2beaa02
NP
826 struct category_t
827 {
d764a8e6
IS
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
944fb799 842 objc_v2_category_template =
d764a8e6
IS
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
c2beaa02
NP
869/* This routine is given a name and returns a matching extern variable
870 if one is found. */
d764a8e6
IS
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
c2beaa02
NP
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. */
d764a8e6 892
944fb799 893static void
d764a8e6
IS
894hash_name_enter (hash *hashlist, tree id)
895{
896 hash obj;
897 int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
898
766090c2 899 obj = ggc_alloc<hashed_entry> ();
d764a8e6
IS
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 (extern_names, id);
915 if (var)
916 return var;
917 /* New name. */
944fb799 918 var = start_var_decl (type, name);
d764a8e6
IS
919 TREE_STATIC (var) = 0;
920 DECL_EXTERNAL (var) = 1;
921 TREE_PUBLIC (var) = 1;
922 hash_name_enter (extern_names, var);
923 return var;
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. */
07c7498d
IS
928static tree
929create_global_decl (tree type, const char *name, bool is_def = false);
d764a8e6
IS
930
931static tree
07c7498d 932create_global_decl (tree type, const char *name, bool is_def)
d764a8e6
IS
933{
934 tree id = get_identifier (name);
935 tree var = hash_name_lookup (extern_names, id);
936 if (var)
07c7498d 937 is_def = true;
d764a8e6
IS
938 else
939 {
940 var = start_var_decl (type, name);
941 hash_name_enter (extern_names, var);
942 }
07c7498d
IS
943 if (is_def)
944 {
945 DECL_EXTERNAL (var) = 0;
946 TREE_STATIC (var) = 1;
947 }
d764a8e6
IS
948 TREE_PUBLIC (var) = 1;
949 return var;
950}
951
c2beaa02
NP
952/* Create a symbol with __attribute__ ((visibility ("hidden")))
953 attribute (private extern). */
07c7498d
IS
954static tree
955create_hidden_decl (tree type, const char *name, bool is_def = false);
d764a8e6 956
944fb799 957static tree
07c7498d 958create_hidden_decl (tree type, const char *name, bool is_def)
d764a8e6 959{
07c7498d 960 tree decl = create_global_decl (type, name, is_def);
d764a8e6
IS
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. */
c2beaa02
NP
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. ;-) */
d764a8e6
IS
969
970static tree
971next_runtime_abi_02_super_superclassfield_id (void)
972{
c2beaa02
NP
973 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
974 most look it once at startup then always return it. */
d764a8e6
IS
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];
944fb799 985 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
d764a8e6
IS
986 IDENTIFIER_POINTER (CLASS_NAME (klass)));
987 /* ObjC2 classes are extern visible. */
988 decl = create_global_decl (objc_v2_class_template, buf);
989 OBJCMETA (decl, objc_meta, meta_class);
990 return decl;
991}
992
993static tree
994next_runtime_abi_02_metaclass_decl (tree klass)
995{
996 tree decl;
997 char buf[BUFSIZE];
944fb799 998 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
d764a8e6
IS
999 IDENTIFIER_POINTER (CLASS_NAME (klass)));
1000 /* ObjC2 classes are extern visible. */
1001 decl = create_global_decl (objc_v2_class_template, buf);
1002 OBJCMETA (decl, objc_meta, meta_metaclass);
1003 return decl;
1004}
1005
1006static tree
1007next_runtime_abi_02_category_decl (tree klass)
1008{
1009 tree decl;
1010 char buf[BUFSIZE];
1174b08b
IS
1011 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_%s",
1012 IDENTIFIER_POINTER (CLASS_NAME (klass)),
1013 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)));
d764a8e6
IS
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 (buf, BUFSIZE, "_OBJC_Protocol_%s",
1027 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
07c7498d
IS
1028 if (flag_next_runtime >= USE_FIXUP_BEFORE)
1029 {
1030 decl = create_hidden_decl (objc_v2_protocol_template, buf);
1031 DECL_WEAK (decl) = true;
1032 }
1033 else
1034 decl = start_var_decl (objc_v2_protocol_template, buf);
d764a8e6 1035 OBJCMETA (decl, objc_meta, meta_protocol);
ecd5727c 1036 DECL_PRESERVE_P (decl) = 1;
d764a8e6
IS
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;
944fb799 1058 default:
d764a8e6
IS
1059 OBJCMETA (var, objc_meta, meta_base);
1060 break;
1061 }
1062 return var;
1063}
1064
1065/* NOTE --- entry --- */
1066
a79683d5 1067struct GTY(()) ident_data_tuple {
d764a8e6
IS
1068 tree ident;
1069 tree data;
a79683d5 1070};
d764a8e6 1071
c2beaa02
NP
1072/* This routine creates a file scope static variable of type 'Class'
1073 to hold the address of a class. */
d764a8e6
IS
1074
1075static tree
1076build_v2_class_reference_decl (tree ident)
1077{
1078 tree decl;
1079 char buf[BUFSIZE];
1080
1081 snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1082 decl = start_var_decl (objc_class_type, buf);
1083 OBJCMETA (decl, objc_meta, meta_class_ref);
1084 return decl;
1085}
1086
1087/* This routine builds a class refs entry for each class name used.
c2beaa02
NP
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. */
d764a8e6 1091
9771b263 1092static GTY (()) vec<ident_data_tuple, va_gc> *classrefs;
d764a8e6
IS
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;
9771b263 1103 FOR_EACH_VEC_ELT (*classrefs, count, ref)
d764a8e6
IS
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. */
9771b263 1115 vec_alloc (classrefs, 16);
c2beaa02 1116
d764a8e6
IS
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;
9771b263 1122 vec_safe_push (classrefs, e);
d764a8e6
IS
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 (). */
9771b263
DN
1134 vec<tree, va_gc> *v;
1135 vec_alloc (v, 1);
d764a8e6 1136 tree t;
c2beaa02 1137 /* ??? add_class_reference (ident); - is pointless, since the
d764a8e6
IS
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));
9771b263 1142 v->quick_push (t);
81e5eca8
MP
1143 t = build_function_call_vec (input_location, vNULL, objc_get_class_decl,
1144 v, 0);
9771b263 1145 vec_free (v);
d764a8e6
IS
1146 return t;
1147 }
1148}
1149
6174da1b
NF
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. */
d764a8e6 1156
6174da1b 1157static void
9771b263
DN
1158next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1159 tree meth, int context,
1160 int superflag)
d764a8e6 1161{
6174da1b 1162 tree receiver_type;
d764a8e6 1163
d764a8e6 1164 if (superflag)
6174da1b 1165 receiver_type = objc_super_type;
d764a8e6 1166 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
6174da1b 1167 receiver_type = objc_instance_type;
d764a8e6 1168 else
6174da1b 1169 receiver_type = objc_object_type;
d764a8e6 1170
9771b263 1171 vec_safe_push (*argtypes, receiver_type);
8703bf5d 1172 if (flag_next_runtime < USE_FIXUP_BEFORE)
3ba0afac
IS
1173 /* Selector type - will eventually change to `int'. */
1174 vec_safe_push (*argtypes, superflag ? objc_v2_super_selector_type
1175 : objc_v2_selector_type);
1176 else
1177 vec_safe_push (*argtypes, objc_selector_type);
d764a8e6
IS
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 (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1188 t = buf;
1189 while (*t)
1190 {
944fb799 1191 if (*t==':')
d764a8e6
IS
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'. */
c2beaa02
NP
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
d764a8e6
IS
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
c2beaa02 1234 /* Skip past the objc_msgSend it's the same for all... */
d764a8e6
IS
1235 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1236 offset++;
1237
1238 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1239 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1240 IDENTIFIER_POINTER (sel_name));
1241 t = buf;
1242 while (*t)
1243 {
944fb799 1244 if (*t==':')
d764a8e6
IS
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
a79683d5 1253struct GTY(()) msgref_entry {
d764a8e6
IS
1254 tree func;
1255 tree selname;
1256 tree refdecl;
a79683d5 1257};
d764a8e6 1258
9771b263 1259static GTY (()) vec<msgref_entry, va_gc> *msgrefs;
d764a8e6 1260
c2beaa02
NP
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. */
d764a8e6
IS
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;
9771b263 1274 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
d764a8e6
IS
1275 if (ref->func == message_func_decl && ref->selname == sel_name)
1276 return ref->refdecl;
1277 }
1278 else
1279 /* Somewhat arbitrary initial provision. */
9771b263 1280 vec_alloc (msgrefs, 32);
c2beaa02 1281
d764a8e6 1282 /* We come here if we don't find a match or at the start. */
944fb799 1283 decl = build_v2_message_reference_decl (sel_name,
d764a8e6
IS
1284 DECL_NAME (message_func_decl));
1285 e.func = message_func_decl;
1286 e.selname = sel_name;
1287 e.refdecl = decl;
9771b263 1288 vec_safe_push (msgrefs, e);
d764a8e6
IS
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
944fb799 1299 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
d764a8e6
IS
1300 IDENTIFIER_POINTER (protocol_ident));
1301 /* TODO: other compiler versions make these hidden & weak. */
1302 decl = create_global_decl (objc_protocol_type, buf);
1303 /* Let optimizer know that this decl is not removable. */
1304 DECL_PRESERVE_P (decl) = 1;
1305 OBJCMETA (decl, objc_meta, meta_proto_ref);
1306 return decl;
1307}
1308
a79683d5 1309struct GTY(()) prot_list_entry {
d764a8e6
IS
1310 tree id;
1311 tree refdecl;
a79683d5 1312};
9771b263 1313static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
d764a8e6
IS
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;
9771b263 1324 FOR_EACH_VEC_ELT (*protrefs, count, ref)
d764a8e6
IS
1325 {
1326 if (ref->id == ident)
1327 {
1328 if (!ref->refdecl)
1329 ref->refdecl = build_v2_protocollist_ref_decl (ident);
1330 return ref->refdecl;
1331 }
1332 }
1333 }
1334 else
1335 /* Somewhat arbitrary initial provision. */
9771b263 1336 vec_alloc (protrefs, 32);
c2beaa02 1337
d764a8e6
IS
1338 /* We come here if we don't find the entry - or if the table was yet
1339 to be created. */
1340 decl = build_v2_protocollist_ref_decl (ident);
1341 e.id = ident;
1342 e.refdecl = decl;
9771b263 1343 vec_safe_push (protrefs, e);
d764a8e6
IS
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 (p);
1355}
1356
c2beaa02
NP
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. */
d764a8e6
IS
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
944fb799 1367 if (TREE_CODE (basetype) == RECORD_TYPE
d764a8e6
IS
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 (ivar_chain, 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;
944fb799 1388}
d764a8e6
IS
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 (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1396 IDENTIFIER_POINTER (fname));
1397 return;
1398}
1399
c2beaa02
NP
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. */
d764a8e6
IS
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 (datum, component, &class_name);
1412 if (!field)
1413 return NULL_TREE;
1414
1415 /* This routine only handles non-bitfield fields */
73699d92 1416 if (DECL_C_BIT_FIELD (field))
d764a8e6
IS
1417 return NULL_TREE;
1418
1419 create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field);
1420
1421 offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1422
1423 ftype = TREE_TYPE (field);
1424
1425 /* (char*)datum */
944fb799 1426 expr = build_c_cast (input_location,
d764a8e6
IS
1427 string_type_node, build_fold_addr_expr (datum));
1428
1429 /* (char*)datum + offset */
5d49b6a7 1430 expr = fold_build_pointer_plus_loc (input_location, expr, offset);
944fb799 1431
d764a8e6
IS
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
c2beaa02
NP
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> ). */
d764a8e6
IS
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
587ae1e3 1458 class structure. */
d764a8e6 1459static tree
944fb799 1460next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
d764a8e6
IS
1461 tree base, tree id)
1462{
1463 tree ivar;
1464 if ((ivar = objc_v2_build_ivar_ref (base, id)))
1465 return ivar;
1466 return objc_build_component_ref (base, id);
1467}
1468
c2beaa02
NP
1469/* [super ...] references are listed here (and built into a table at
1470 meta -data emit time). */
d764a8e6
IS
1471static tree
1472build_v2_superclass_ref_decl (tree ident, bool inst)
1473{
1474 tree decl;
1475 char buf[BUFSIZE];
1476
1477 snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1478 IDENTIFIER_POINTER (ident));
1479 decl = start_var_decl (objc_class_type, buf);
1480 OBJCMETA (decl, objc_meta, meta_superclass_ref);
1481 return decl;
1482}
1483
9771b263
DN
1484static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs;
1485static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs;
d764a8e6 1486
c28d91bf
IS
1487/* Find or build a superclass reference decl for class NAME. */
1488
d764a8e6 1489static tree
c28d91bf 1490objc_get_superclass_ref_decl (tree name, bool inst_meth)
d764a8e6
IS
1491{
1492 tree decl;
9771b263 1493 vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs
d764a8e6
IS
1494 : metaclass_super_refs;
1495
1496 if (list)
1497 {
1498 int count;
1499 ident_data_tuple *ref;
9771b263 1500 FOR_EACH_VEC_ELT (*list, count, ref)
d764a8e6 1501 {
c28d91bf 1502 if (ref->ident == name)
d764a8e6
IS
1503 {
1504 if (!ref->data)
c28d91bf 1505 ref->data = build_v2_superclass_ref_decl (name, inst_meth);
d764a8e6
IS
1506 return ref->data;
1507 }
1508 }
1509 }
1510 else
1511 {
1512 /* Somewhat arbitrary initial provision. */
1513 if (inst_meth)
9771b263
DN
1514 {
1515 vec_alloc (class_super_refs, 16);
1516 list = class_super_refs;
1517 }
d764a8e6 1518 else
9771b263
DN
1519 {
1520 vec_alloc (metaclass_super_refs, 16);
1521 list = metaclass_super_refs;
1522 }
d764a8e6
IS
1523 }
1524 /* We come here if we don't find the entry - or if the table was yet
1525 to be created. */
c28d91bf
IS
1526 decl = build_v2_superclass_ref_decl (name, inst_meth);
1527 ident_data_tuple e;
1528 e.ident = name;
d764a8e6 1529 e.data = decl;
9771b263 1530 vec_safe_push (list, e);
d764a8e6
IS
1531 return decl;
1532}
1533
c28d91bf
IS
1534/* Get a reference to the superclass for IMP. */
1535
d764a8e6 1536static tree
c28d91bf
IS
1537next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1538 struct imp_entry *imp, bool inst_meth)
d764a8e6 1539{
c28d91bf
IS
1540 tree name = CLASS_NAME (imp->imp_context);
1541 return objc_get_superclass_ref_decl (name, inst_meth);
1542}
d764a8e6 1543
c28d91bf
IS
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)
d764a8e6 1552 {
c28d91bf
IS
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));
d764a8e6 1562 }
c28d91bf
IS
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 (cls_name, inst_meth);
1568 return objc_get_class_reference (cls_name);
d764a8e6
IS
1569}
1570
1571static tree
1572next_runtime_abi_02_receiver_is_class_object (tree receiver)
1573{
92ce0786 1574 if (VAR_P (receiver)
d764a8e6 1575 && IS_CLASS (TREE_TYPE (receiver))
9771b263 1576 && vec_safe_length (classrefs))
d764a8e6
IS
1577 {
1578 int count;
1579 ident_data_tuple *ref;
1580 /* The receiver is a variable created by build_class_reference_decl. */
9771b263 1581 FOR_EACH_VEC_ELT (*classrefs, count, ref)
d764a8e6
IS
1582 if (ref->data == receiver)
1583 return ref->ident;
1584 }
1585 return NULL_TREE;
1586}
1587
6174da1b
NF
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. */
d764a8e6
IS
1591
1592static tree
6174da1b 1593objc_copy_to_temp_side_effect_params (tree fntype, tree values)
d764a8e6 1594{
6174da1b
NF
1595 tree valtail;
1596 function_args_iterator iter;
1597
c2beaa02 1598 /* Skip over receiver and the &_msf_ref types. */
6174da1b
NF
1599 function_args_iter_init (&iter, fntype);
1600 function_args_iter_next (&iter);
1601 function_args_iter_next (&iter);
d764a8e6 1602
944fb799 1603 for (valtail = values; valtail;
6174da1b 1604 valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
d764a8e6
IS
1605 {
1606 tree value = TREE_VALUE (valtail);
6174da1b 1607 tree type = function_args_iter_cond (&iter);
d764a8e6 1608 if (type == NULL_TREE)
944fb799 1609 break;
d764a8e6
IS
1610 if (!TREE_SIDE_EFFECTS (value))
1611 continue;
c2beaa02 1612 /* To prevent re-evaluation. */
d764a8e6
IS
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:
c2beaa02 1621 (*_msg.messenger) (receiver, &_msg, ...) */
d764a8e6
IS
1622
1623static tree
3ba0afac
IS
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)
d764a8e6
IS
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);
6174da1b 1634 tree ftype = build_function_type_for_method (ret_type, method_prototype,
d764a8e6 1635 METHOD_REF, super_flag);
d764a8e6
IS
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)
6174da1b 1645 method_params = objc_copy_to_temp_side_effect_params (ftype,
d764a8e6
IS
1646 method_params);
1647
c2beaa02 1648 /* Get &message_ref_t.messenger. */
944fb799 1649 sender = build_c_cast (input_location,
d764a8e6
IS
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
1661 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1662 lookup_object = save_expr (lookup_object);
1663
1664 method_params = tree_cons (NULL_TREE, lookup_object,
1665 tree_cons (NULL_TREE, selector,
1666 method_params));
ef946258
JJ
1667 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object,
1668 build_int_cst (TREE_TYPE (lookup_object), 0));
d764a8e6
IS
1669 ret_val = build_function_call (input_location, t, method_params);
1670 if (check_for_nil)
1671 {
1672 /* receiver != nil ? ret_val : 0 */
1673 tree ftree;
1674 tree ifexp;
1675
1676 if (TREE_CODE (ret_type) == RECORD_TYPE
1677 || TREE_CODE (ret_type) == UNION_TYPE)
d2aa4e0b
IS
1678 /* An empty constructor is zero-filled by the middle end. */
1679 ftree = objc_build_constructor (ret_type, NULL);
d764a8e6
IS
1680 else
1681 ftree = fold_convert (ret_type, integer_zero_node);
1682
944fb799
MS
1683 ifexp = build_binary_op (input_location, NE_EXPR,
1684 lookup_object,
d764a8e6
IS
1685 fold_convert (rcv_p, integer_zero_node), 1);
1686
1687#ifdef OBJCPLUS
5951f9df
PC
1688 ret_val = build_conditional_expr (input_location,
1689 ifexp, ret_val, ftree,
1690 tf_warning_or_error);
d764a8e6 1691#else
944fb799 1692 ret_val = build_conditional_expr (input_location,
d2aa4e0b 1693 ifexp, 0,
a32c8316
MP
1694 ret_val, NULL_TREE, input_location,
1695 ftree, NULL_TREE, input_location);
d2aa4e0b 1696 ret_val = fold_convert (ret_type, ret_val);
944fb799 1697#endif
d764a8e6
IS
1698 }
1699 return ret_val;
1700}
1701
3ba0afac
IS
1702static tree
1703build_v2_build_objc_method_call (int super, tree method_prototype,
1704 tree lookup_object, tree selector,
1705 tree method_params, location_t loc,
1706 bool check_for_nil, bool rx_is_id)
1707{
1708 tree sender, sender_cast, method, t;
1709 tree rcv_p = (super ? objc_super_type : objc_object_type);
1710 vec<tree, va_gc> *parms;
1711 unsigned nparm = (method_params ? list_length (method_params) : 0);
1712
1713 /* If a prototype for the method to be called exists, then cast
1714 the sender's return type and arguments to match that of the method.
1715 Otherwise, leave sender as is. */
1716 tree ret_type
1717 = (method_prototype
1718 ? TREE_VALUE (TREE_TYPE (method_prototype))
1719 : objc_object_type);
1720 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1721 METHOD_REF, super);
1722
1723 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1724 ftype = build_type_attribute_variant (ftype,
1725 METHOD_TYPE_ATTRIBUTES
1726 (method_prototype));
1727
1728 sender_cast = build_pointer_type (ftype);
1729
1730 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
1731
85e930ac
AP
1732 if (error_operand_p (lookup_object))
1733 return error_mark_node;
1734
3ba0afac
IS
1735 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1736 lookup_object = save_expr (lookup_object);
1737
1738 /* Param list + 2 slots for object and selector. */
1739 vec_alloc (parms, nparm + 2);
1740
1cef3039
IS
1741 /* If we are returning an item that must be returned in memory, and the
1742 target ABI does this by an invisible pointer provided as the first arg,
1743 we need to adjust the message signature to include this. The second
1744 part of this excludes targets that provide some alternate scheme for
1745 structure returns. */
1746 if (ret_type && !VOID_TYPE_P (ret_type)
1747 && targetm.calls.return_in_memory (ret_type, 0)
1748 && !(targetm.calls.struct_value_rtx (0, 0)
1749 && (TREE_CODE (ret_type) == RECORD_TYPE
1750 || TREE_CODE (ret_type) == UNION_TYPE)))
3ba0afac
IS
1751 {
1752 if (super)
1753 sender = umsg_id_super2_stret_fixup_decl;
1754 else
1755 sender = rx_is_id ? umsg_id_stret_fixup_decl
1756 : umsg_stret_fixup_decl;
1757 }
1758 else
1759 {
1760 if (super)
1761 sender = umsg_id_super2_fixup_decl;
1762 else
1763 sender = rx_is_id ? umsg_id_fixup_decl
1764 : umsg_fixup_decl;
1765 }
1766
1767 method = build_fold_addr_expr_loc (loc, sender);
1768
1769 /* Pass the object to the method. */
1770 parms->quick_push (lookup_object);
1771 /* Pass the selector to the method. */
1772 parms->quick_push (selector);
1773 /* Now append the remainder of the parms. */
1774 if (nparm)
1775 for (; method_params; method_params = TREE_CHAIN (method_params))
1776 parms->quick_push (TREE_VALUE (method_params));
1777
1778 /* Build an obj_type_ref, with the correct cast for the method call. */
1779 t = build3 (OBJ_TYPE_REF, sender_cast, method,
ef946258 1780 lookup_object, build_int_cst (TREE_TYPE (lookup_object), 0));
3ba0afac
IS
1781 tree ret_val = build_function_call_vec (loc, vNULL, t, parms, NULL);
1782 vec_free (parms);
1783 if (check_for_nil)
1784 {
1785 /* receiver != nil ? ret_val : 0 */
1786 tree ftree;
1787 tree ifexp;
1788
1789 if (TREE_CODE (ret_type) == RECORD_TYPE
1790 || TREE_CODE (ret_type) == UNION_TYPE)
1791 {
d2aa4e0b
IS
1792 /* An empty constructor is zero-filled by the middle end. */
1793 ftree = objc_build_constructor (ret_type, NULL);
3ba0afac
IS
1794 }
1795 else
1796 ftree = fold_convert (ret_type, integer_zero_node);
1797
1798 ifexp = build_binary_op (loc, NE_EXPR,
1799 lookup_object,
1800 fold_convert (rcv_p, integer_zero_node), 1);
1801
1802#ifdef OBJCPLUS
1803 ret_val = build_conditional_expr (loc, ifexp, ret_val, ftree,
1804 tf_warning_or_error);
1805#else
3ba0afac
IS
1806 ret_val = build_conditional_expr (loc, ifexp, 1,
1807 ret_val, NULL_TREE, loc,
1808 ftree, NULL_TREE, loc);
d2aa4e0b 1809 ret_val = fold_convert (ret_type, ret_val);
3ba0afac
IS
1810#endif
1811 }
1812 return ret_val;
1813}
1814
d764a8e6
IS
1815static tree
1816next_runtime_abi_02_build_objc_method_call (location_t loc,
1817 tree method_prototype,
1818 tree receiver,
1819 tree rtype,
1820 tree sel_name,
1821 tree method_params,
1822 int super)
1823{
d764a8e6 1824 /* Do we need to check for nil receivers ? */
c2beaa02
NP
1825 /* For now, message sent to classes need no nil check. In the
1826 future, class declaration marked as weak_import must be nil
1827 checked. */
3ba0afac 1828 bool check_for_nil = flag_objc_nilcheck;
944fb799 1829 if (super
92ce0786 1830 || (VAR_P (receiver)
d764a8e6
IS
1831 && TREE_TYPE (receiver) == objc_class_type))
1832 check_for_nil = false;
1833
8703bf5d 1834 if (flag_next_runtime >= USE_FIXUP_BEFORE)
3ba0afac
IS
1835 {
1836 tree selector
1837 = next_runtime_abi_02_build_selector_reference (loc, sel_name,
1838 method_prototype);
1839 return build_v2_build_objc_method_call (super, method_prototype,
1840 receiver, selector,
1841 method_params, loc,
1842 check_for_nil,
1843 objc_is_id (rtype));
1844 }
1845
1846 /* else we have to build a pair of the function and selector. */
1847 tree message_func_decl;
1848 tree ret_type = method_prototype
1849 ? TREE_VALUE (TREE_TYPE (method_prototype))
1850 : objc_object_type;
1851
1cef3039
IS
1852 /* See comment for the fixup version above. */
1853 if (ret_type && !VOID_TYPE_P (ret_type)
1854 && targetm.calls.return_in_memory (ret_type, 0)
1855 && !(targetm.calls.struct_value_rtx (0, 0)
1856 && (TREE_CODE (ret_type) == RECORD_TYPE
1857 || TREE_CODE (ret_type) == UNION_TYPE)))
d764a8e6
IS
1858 {
1859 if (super)
1860 message_func_decl = umsg_id_super2_stret_fixup_decl;
1861 else
944fb799
MS
1862 message_func_decl = objc_is_id (rtype)
1863 ? umsg_id_stret_fixup_decl
1864 : umsg_stret_fixup_decl;
d764a8e6
IS
1865 }
1866 else
1867 {
1868 if (super)
1869 message_func_decl = umsg_id_super2_fixup_decl;
1870 else
944fb799
MS
1871 message_func_decl = objc_is_id (rtype)
1872 ? umsg_id_fixup_decl
1873 : umsg_fixup_decl;
d764a8e6
IS
1874 }
1875
3ba0afac 1876 tree selector = build_v2_selector_messenger_reference (sel_name,
d764a8e6
IS
1877 message_func_decl);
1878
1879 /* selector = &_msg; */
1880 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
944fb799
MS
1881
1882 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
d764a8e6
IS
1883 : objc_v2_selector_type),
1884 selector);
1885
1886 /* (*_msg.messenger) (receiver, &_msg, ...); */
3ba0afac
IS
1887 return build_v2_objc_method_fixup_call (super, method_prototype, receiver,
1888 selector, method_params,
1889 check_for_nil);
d764a8e6
IS
1890}
1891
1892/* NOTE --- Constant String Class Stuff --- */
1893
1894static bool
1895next_runtime_abi_02_setup_const_string_class_decl (void)
1896{
1897 if (!constant_string_global_id)
1898 {
1899 /* Hopefully, this should not represent a serious limitation. */
1900 char buf[BUFSIZE];
1901 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1902 constant_string_global_id = get_identifier (buf);
1903 }
1904
1905 string_class_decl = lookup_name (constant_string_global_id);
1906
c2beaa02
NP
1907 /* In OBJC2 abi, constant string class reference refers to class
1908 name for NSConstantString class. This declaration may not be
1909 available yet (in fact it is not in most cases). So, declare an
1910 extern OBJC_CLASS_$_NSConstantString in its place. */
d764a8e6 1911 if (!string_class_decl)
944fb799 1912 string_class_decl =
d764a8e6
IS
1913 create_extern_decl (objc_v2_class_template,
1914 IDENTIFIER_POINTER (constant_string_global_id));
1915
1916 return (string_class_decl != NULL_TREE);
1917}
1918
1919static tree
1920next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1921 int length)
1922{
1923 tree constructor, fields, var;
9771b263 1924 vec<constructor_elt, va_gc> *v = NULL;
d764a8e6 1925
c2beaa02 1926 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
d764a8e6
IS
1927 fields = TYPE_FIELDS (internal_const_str_type);
1928 CONSTRUCTOR_APPEND_ELT (v, fields,
1929 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1930
1931 fields = DECL_CHAIN (fields);
1932 CONSTRUCTOR_APPEND_ELT (v, fields,
1933 build_unary_op (loc, ADDR_EXPR, string, 1));
1934
1935 /* ??? check if this should be long. */
1936 fields = DECL_CHAIN (fields);
1937 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1938 constructor = objc_build_constructor (internal_const_str_type, v);
1939
1940 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1941 DECL_INITIAL (var) = constructor;
1942 TREE_STATIC (var) = 1;
1943 DECL_CONTEXT (var) = NULL;
1944 OBJCMETA (var, objc_meta, meta_const_str);
1945 return var;
1946}
1947
1948/* NOTE --- NeXT V2 Metadata templates --- */
1949
1950/* This routine builds the following type:
c2beaa02
NP
1951 struct _prop_t
1952 {
d764a8e6 1953 const char * const name; // property name
944fb799 1954 const char * const attributes; // comma-delimited, encoded,
d764a8e6
IS
1955 // property attributes
1956 };
1957*/
1958
1959static tree
1960build_v2_property_template (void)
1961{
1962 tree prop_record;
1963 tree decls, *chain = NULL;
1964
1965 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1966 /* const char * name */
1967 decls = add_field_decl (string_type_node, "name", &chain);
1968
1969 /* const char * attribute */
1970 add_field_decl (string_type_node, "attribute", &chain);
1971
1972 objc_finish_struct (prop_record, decls);
1973 return prop_record;
1974}
1975
c2beaa02
NP
1976/* struct ivar_t
1977 {
d764a8e6
IS
1978 unsigned long int *offset;
1979 char *name;
1980 char *type;
1981 uint32_t alignment;
1982 uint32_t size;
1983 };
1984*/
1985
1986static tree
1987build_v2_ivar_t_template (void)
1988{
1989 tree objc_ivar_id, objc_ivar_record;
1990 tree decls, *chain = NULL;
1991
1992 objc_ivar_id = get_identifier ("_ivar_t");
1993 objc_ivar_record = objc_start_struct (objc_ivar_id);
1994
c2beaa02 1995 /* unsigned long int *offset; */
944fb799 1996 decls = add_field_decl (build_pointer_type
d764a8e6
IS
1997 (TREE_TYPE (size_zero_node)), "offset", &chain);
1998
1999 /* char *name; */
2000 add_field_decl (string_type_node, "name", &chain);
2001
2002 /* char *type; */
2003 add_field_decl (string_type_node, "type", &chain);
2004
2005 /* uint32_t alignment; */
2006 add_field_decl (integer_type_node, "alignment", &chain);
2007
2008 /* uint32_t size; */
2009 add_field_decl (integer_type_node, "size", &chain);
2010
2011 objc_finish_struct (objc_ivar_record, decls);
2012 return objc_ivar_record;
2013}
2014
2015static void
2016build_metadata_templates (void)
2017{
2018
2019 if (!objc_method_template)
2020 objc_method_template = build_method_template ();
2021
2022 if (!objc_v2_property_template)
944fb799 2023 objc_v2_property_template = build_v2_property_template ();
d764a8e6
IS
2024
2025 if (!objc_v2_ivar_template)
2026 objc_v2_ivar_template = build_v2_ivar_t_template ();
2027
2028}
2029
2030/* NOTE --- Output NeXT V2 Metadata --- */
2031
2032/* Routine builds name of Interface's main meta-data of type class_t. */
2033
2034static char *
2035objc_build_internal_classname (tree ident, bool metaclass)
2036{
2037 static char string[512];
944fb799
MS
2038 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
2039 : "OBJC_CLASS_$",
d764a8e6
IS
2040 IDENTIFIER_POINTER (ident));
2041 return string;
2042}
2043
2044/* Build the name for object of type struct class_ro_t */
2045
2046static const char *
2047newabi_append_ro (const char *name)
2048{
e6e9475b 2049 const char *dollar;
d764a8e6
IS
2050 char *p;
2051 static char string[BUFSIZE];
2052 dollar = strchr (name, '$');
2053 gcc_assert (dollar);
2054 p = string;
2055 *p = '_'; p++;
2056 strncpy (p, name, (int)(dollar - name));
2057 p += (int)(dollar - name);
2058 sprintf (p, "RO_%s", dollar);
2059 return string;
2060}
2061
944fb799
MS
2062/* Build the struct message_ref_t msg =
2063 {objc_msgSend_fixup_xxx, @selector(func)}
c2beaa02 2064 table. */
d764a8e6 2065
944fb799 2066static
d764a8e6
IS
2067void build_v2_message_ref_translation_table (void)
2068{
2069 int count;
2070 msgref_entry *ref;
2071
9771b263 2072 if (!vec_safe_length (msgrefs))
d764a8e6
IS
2073 return;
2074
9771b263 2075 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
d764a8e6 2076 {
9771b263 2077 vec<constructor_elt, va_gc> *initializer;
d764a8e6
IS
2078 tree expr, constructor;
2079 tree struct_type = TREE_TYPE (ref->refdecl);
2080 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
2081
2082 initializer = NULL;
c2beaa02 2083 /* First 'IMP messenger' field... */
d764a8e6
IS
2084 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
2085 expr = convert (objc_v2_imp_type, expr);
2086 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2087
c2beaa02 2088 /* ... then 'SEL name' field. */
d764a8e6
IS
2089 expr = build_selector (ref->selname);
2090 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2091 constructor = objc_build_constructor (struct_type, initializer);
944fb799 2092 finish_var_decl (ref->refdecl, constructor);
d764a8e6
IS
2093 }
2094}
2095
c2beaa02
NP
2096/* Build decl = initializer; for each externally visible class
2097 reference. */
d764a8e6
IS
2098
2099static void
2100build_v2_classrefs_table (void)
2101{
2102 int count;
2103 ident_data_tuple *ref;
2104
9771b263 2105 if (!vec_safe_length (classrefs))
d764a8e6
IS
2106 return;
2107
9771b263 2108 FOR_EACH_VEC_ELT (*classrefs, count, ref)
d764a8e6
IS
2109 {
2110 tree expr = ref->ident;
2111 tree decl = ref->data;
c2beaa02
NP
2112 /* Interface with no implementation and yet one of its messages
2113 has been used. Need to generate a full address-of tree for it
2114 here. */
d764a8e6
IS
2115 if (TREE_CODE (expr) == IDENTIFIER_NODE)
2116 {
2117 const char *name = objc_build_internal_classname (expr, false);
2118 expr = create_extern_decl (objc_v2_class_template, name);
2119 expr = convert (objc_class_type, build_fold_addr_expr (expr));
2120 }
2121 /* The runtime wants this, even if it appears unused, so we must force the
ecd5727c
IS
2122 output. */
2123 DECL_PRESERVE_P (decl) = 1;
d764a8e6
IS
2124 finish_var_decl (decl, expr);
2125 }
2126}
2127
c2beaa02
NP
2128/* Build decl = initializer; for each externally visible super class
2129 reference. */
d764a8e6
IS
2130
2131static void
2132build_v2_super_classrefs_table (bool metaclass)
2133{
2134 int count;
2135 ident_data_tuple *ref;
9771b263 2136 vec<ident_data_tuple, va_gc> *list = metaclass ? metaclass_super_refs
d764a8e6
IS
2137 : class_super_refs;
2138
9771b263 2139 if (!vec_safe_length (list))
d764a8e6
IS
2140 return;
2141
9771b263 2142 FOR_EACH_VEC_ELT (*list, count, ref)
d764a8e6
IS
2143 {
2144 tree expr = ref->ident;
2145 tree decl = ref->data;
c2beaa02
NP
2146 /* Interface with no implementation and yet one of its messages
2147 has been used. Need to generate a full address-of tree for it
2148 here. */
d764a8e6
IS
2149 if (TREE_CODE (expr) == IDENTIFIER_NODE)
2150 {
2151 const char * name = objc_build_internal_classname (expr, metaclass);
2152 expr = create_extern_decl (objc_v2_class_template, name);
2153 expr = convert (objc_class_type, build_fold_addr_expr (expr));
2154 }
2155 finish_var_decl (decl, expr);
2156 }
2157}
2158
c2beaa02
NP
2159/* Add the global class meta-data declaration to the list which later
2160 on ends up in the __class_list section. */
d764a8e6 2161
9771b263 2162static GTY(()) vec<tree, va_gc> *class_list;
d764a8e6 2163
944fb799 2164static void
d764a8e6
IS
2165objc_v2_add_to_class_list (tree global_class_decl)
2166{
9771b263 2167 vec_safe_push (class_list, global_class_decl);
d764a8e6
IS
2168}
2169
9771b263 2170static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
d764a8e6 2171
c2beaa02
NP
2172/* Add the global class meta-data declaration to the list which later
2173 on ends up in the __nonlazy_class section. */
d764a8e6 2174
944fb799 2175static void
d764a8e6
IS
2176objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2177{
9771b263 2178 vec_safe_push (nonlazy_class_list, global_class_decl);
d764a8e6
IS
2179}
2180
9771b263 2181static GTY(()) vec<tree, va_gc> *category_list;
d764a8e6 2182
c2beaa02
NP
2183/* Add the category meta-data declaration to the list which later on
2184 ends up in the __nonlazy_category section. */
d764a8e6 2185
944fb799 2186static void
d764a8e6
IS
2187objc_v2_add_to_category_list (tree decl)
2188{
9771b263 2189 vec_safe_push (category_list, decl);
d764a8e6
IS
2190}
2191
9771b263 2192static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
d764a8e6 2193
c2beaa02
NP
2194/* Add the category meta-data declaration to the list which later on
2195 ends up in the __category_list section. */
d764a8e6 2196
944fb799 2197static void
d764a8e6
IS
2198objc_v2_add_to_nonlazy_category_list (tree decl)
2199{
9771b263 2200 vec_safe_push (nonlazy_category_list, decl);
d764a8e6
IS
2201}
2202
2203static bool
2204has_load_impl (tree clsmeth)
2205{
2206 while (clsmeth)
2207 {
2208 tree id = METHOD_SEL_NAME (clsmeth);
2209 if (IDENTIFIER_LENGTH (id) == 4
6ba3079d 2210 && startswith (IDENTIFIER_POINTER (id), "load"))
d764a8e6
IS
2211 return true;
2212 clsmeth = DECL_CHAIN (clsmeth);
2213 }
2214
2215 return false;
2216}
2217
c2beaa02
NP
2218/* Build a __{class,category}_list section table containing address of
2219 all @implemented {class,category} meta-data. */
d764a8e6
IS
2220
2221static void
9771b263 2222build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
d764a8e6
IS
2223{
2224 int count=0;
2225 tree type, decl, expr;
9771b263 2226 vec<constructor_elt, va_gc> *initlist = NULL;
d764a8e6 2227
9771b263 2228 if (!vec_safe_length (src))
d764a8e6
IS
2229 return;
2230
9771b263 2231 FOR_EACH_VEC_ELT (*src, count, decl)
d764a8e6
IS
2232 {
2233#ifndef OBJCPLUS
2234 tree purpose = build_int_cst (NULL_TREE, count);
2235#else
2236 tree purpose = NULL_TREE;
2237#endif
2238 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2239 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2240 }
2241 gcc_assert (count > 0);
944fb799 2242 type = build_array_type (objc_class_type,
d764a8e6
IS
2243 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2244 decl = start_var_decl (type, nam);
c2beaa02
NP
2245 /* The runtime wants this, even if it appears unused, so we must
2246 force the output. */
d764a8e6
IS
2247 DECL_PRESERVE_P (decl) = 1;
2248 expr = objc_build_constructor (type, initlist);
2249 OBJCMETA (decl, objc_meta, attr);
2250 finish_var_decl (decl, expr);
2251}
2252
c2beaa02
NP
2253/* Build decl = initializer; for each protocol referenced in
2254 @protocol(MyProt) expression. Refs as built in the entry section
2255 above. */
d764a8e6
IS
2256
2257static void
2258build_v2_protocol_list_translation_table (void)
2259{
2260 int count;
2261 prot_list_entry *ref;
944fb799 2262
d764a8e6
IS
2263 if (!protrefs)
2264 return;
2265
9771b263 2266 FOR_EACH_VEC_ELT (*protrefs, count, ref)
d764a8e6
IS
2267 {
2268 char buf[BUFSIZE];
2269 tree expr;
2270 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
944fb799 2271 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
d764a8e6
IS
2272 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2273 expr = start_var_decl (objc_v2_protocol_template, buf);
2274 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2275 finish_var_decl (ref->refdecl, expr);
2276 }
2277 /* TODO: Maybe we could explicitly delete the vec. now? */
2278}
2279
9771b263 2280static GTY (()) vec<prot_list_entry, va_gc> *protlist;
d764a8e6 2281
c2beaa02
NP
2282/* Add the local protocol meta-data declaration to the list which
2283 later on ends up in the __protocol_list section. */
d764a8e6
IS
2284
2285static void
2286objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2287{
2288 prot_list_entry e;
2289 if (!protlist)
2290 /* Arbitrary init count. */
9771b263 2291 vec_alloc (protlist, 32);
d764a8e6
IS
2292 e.id = protocol_interface_decl;
2293 e.refdecl = protocol_decl;
9771b263 2294 vec_safe_push (protlist, e);
d764a8e6
IS
2295}
2296
c2beaa02
NP
2297/* Build the __protocol_list section table containing address of all
2298 generate protocol_t meta-data. */
d764a8e6
IS
2299
2300static void
2301build_v2_protocol_list_address_table (void)
2302{
2303 int count;
2304 prot_list_entry *ref;
9771b263 2305 if (!vec_safe_length (protlist))
d764a8e6
IS
2306 return;
2307
9771b263 2308 FOR_EACH_VEC_ELT (*protlist, count, ref)
d764a8e6
IS
2309 {
2310 tree decl, expr;
2311 char buf[BUFSIZE];
2312 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2313 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2314 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
07c7498d
IS
2315 if (flag_next_runtime >= USE_FIXUP_BEFORE)
2316 {
2317 decl = create_hidden_decl (objc_protocol_type, buf, /*is def=*/true);
2318 DECL_WEAK (decl) = true;
2319 }
2320 else
2321 decl = create_global_decl (objc_protocol_type, buf, /*is def=*/true);
d764a8e6
IS
2322 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2323 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2324 finish_var_decl (decl, expr);
ecd5727c 2325 DECL_PRESERVE_P (decl) = 1;
d764a8e6
IS
2326 }
2327
2328 /* TODO: delete the vec. */
dd5a833e 2329 /* TODO: upgrade to the clang/llvm hidden version. */
d764a8e6
IS
2330}
2331
c2beaa02
NP
2332/* This routine declares a variable to hold meta data for 'struct
2333 protocol_list_t'. */
d764a8e6
IS
2334
2335static tree
2336generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2337{
2338 tree refs_decl, lproto, e, plist, ptempl_p_t;
2339 int size = 0;
9771b263 2340 vec<constructor_elt, va_gc> *initlist = NULL;
d764a8e6
IS
2341 char buf[BUFSIZE];
2342
2343 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2344 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2345 plist = CLASS_PROTOCOL_LIST (i_or_p);
2346 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2347 plist = PROTOCOL_LIST (i_or_p);
2348 else
2349 gcc_unreachable ();
2350
2351 /* Compute size. */
2352 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2353 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2354 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2355 size++;
2356
2357 /* Build initializer. */
2358
2359 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2360 e = build_int_cst (ptempl_p_t, size);
2361 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2362
2363 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2364 {
2365 tree pval = TREE_VALUE (lproto);
2366
2367 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2368 && PROTOCOL_FORWARD_DECL (pval))
2369 {
2370 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2371 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2372 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2373 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2374 }
2375 }
2376
2377 /* static struct protocol_list_t *list[size]; */
2378
2379 switch (TREE_CODE (i_or_p))
2380 {
2381 case PROTOCOL_INTERFACE_TYPE:
944fb799 2382 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
d764a8e6
IS
2383 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2384 break;
2385 case CLASS_INTERFACE_TYPE:
944fb799 2386 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
d764a8e6
IS
2387 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2388 break;
2389 case CATEGORY_INTERFACE_TYPE:
944fb799 2390 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
d764a8e6
IS
2391 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2392 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2393 break;
2394 default:
2395 gcc_unreachable ();
2396 }
2397
2398 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2399 buf);
2400 /* ObjC2 puts all these in the base section. */
2401 OBJCMETA (refs_decl, objc_meta, meta_base);
2402 DECL_PRESERVE_P (refs_decl) = 1;
944fb799 2403 finish_var_decl (refs_decl,
d764a8e6
IS
2404 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2405 return refs_decl;
2406}
2407
c2beaa02
NP
2408/* This routine builds one 'struct method_t' initializer list. Note
2409 that the old ABI is supposed to build 'struct objc_method' which
2410 has 3 fields, but it does not build the initialization expression
2411 for 'method_imp' which for protocols is NULL any way. To be
587ae1e3 2412 consistent with declaration of 'struct method_t', in the new ABI we
c2beaa02 2413 set the method_t.imp to NULL. */
d764a8e6
IS
2414
2415static tree
2416build_v2_descriptor_table_initializer (tree type, tree entries)
2417{
9771b263 2418 vec<constructor_elt, va_gc> *initlist = NULL;
d764a8e6
IS
2419 do
2420 {
9771b263 2421 vec<constructor_elt, va_gc> *eltlist = NULL;
944fb799 2422 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
d764a8e6 2423 build_selector (METHOD_SEL_NAME (entries)));
944fb799 2424 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
d764a8e6
IS
2425 add_objc_string (METHOD_ENCODING (entries),
2426 meth_var_types));
2427 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2428
944fb799 2429 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
d764a8e6
IS
2430 objc_build_constructor (type, eltlist));
2431 entries = TREE_CHAIN (entries);
2432 }
2433 while (entries);
2434
2435 return objc_build_constructor (build_array_type (type, 0), initlist);
2436}
2437
c2beaa02
NP
2438/* struct method_list_t
2439 {
d764a8e6
IS
2440 uint32_t entsize;
2441 uint32_t method_count;
2442 struct objc_method method_list[method_count];
c2beaa02 2443 }; */
d764a8e6
IS
2444
2445static tree
2446build_v2_method_list_template (tree list_type, int size)
2447{
2448 tree method_list_t_record;
2449 tree array_type, decls, *chain = NULL;
2450
2451 method_list_t_record = objc_start_struct (NULL_TREE);
944fb799 2452
c2beaa02 2453 /* uint32_t const entsize; */
d764a8e6
IS
2454 decls = add_field_decl (integer_type_node, "entsize", &chain);
2455
2456 /* int method_count; */
2457 add_field_decl (integer_type_node, "method_count", &chain);
2458
2459 /* struct objc_method method_list[]; */
2460 array_type = build_sized_array_type (list_type, size);
2461 add_field_decl (array_type, "method_list", &chain);
2462
2463 objc_finish_struct (method_list_t_record, decls);
2464 return method_list_t_record;
2465}
2466
c2beaa02
NP
2467/* Note, as above that we are building to the objc_method_template
2468 which has the *imp field. ABI0/1 build with
2469 objc_method_prototype_template which is missing this field. */
944fb799 2470static tree
d764a8e6 2471generate_v2_meth_descriptor_table (tree chain, tree protocol,
6224a8aa
IS
2472 const char *prefix, tree attr,
2473 vec<tree>& all_meths)
d764a8e6 2474{
6224a8aa 2475 tree method_list_template, initlist, decl;
d764a8e6 2476 int size, entsize;
9771b263 2477 vec<constructor_elt, va_gc> *v = NULL;
d764a8e6
IS
2478 char buf[BUFSIZE];
2479
2480 if (!chain || !prefix)
2481 return NULL_TREE;
2482
6224a8aa 2483 tree method = chain;
d764a8e6 2484 size = 0;
6224a8aa 2485 while (method)
d764a8e6 2486 {
6224a8aa
IS
2487 if (! METHOD_ENCODING (method))
2488 METHOD_ENCODING (method) = encode_method_prototype (method);
2489 all_meths.safe_push (method);
2490 method = TREE_CHAIN (method);
d764a8e6
IS
2491 size++;
2492 }
2493
2494 gcc_assert (size);
2495 method_list_template = build_v2_method_list_template (objc_method_template,
2496 size);
944fb799 2497 snprintf (buf, BUFSIZE, "%s_%s", prefix,
d764a8e6
IS
2498 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2499
2500 decl = start_var_decl (method_list_template, buf);
2501
2502 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2503 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2504 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
944fb799 2505 initlist =
d764a8e6
IS
2506 build_v2_descriptor_table_initializer (objc_method_template,
2507 chain);
2508 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2509 /* Get into the right section. */
2510 OBJCMETA (decl, objc_meta, attr);
2511 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2512 return decl;
2513}
2514
6224a8aa
IS
2515static tree
2516generate_v2_meth_type_list (vec<tree>& all_meths, tree protocol,
2517 const char *prefix)
2518{
2519 if (all_meths.is_empty () || !prefix)
2520 return NULL_TREE;
2521
2522 unsigned size = all_meths.length ();
2523 tree list_type = build_sized_array_type (string_type_node, size);
2524 char *nam;
2525 asprintf (&nam, "%s_%s", prefix,
2526 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2527 tree decl = start_var_decl (list_type, nam);
2528 free (nam);
2529 OBJCMETA (decl, objc_meta, meta_base);
2530 vec<constructor_elt, va_gc> *v = NULL;
2531
2532 for (unsigned i = 0; i < size; ++i)
2533 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2534 add_objc_string (METHOD_ENCODING (all_meths[i]),
2535 meth_var_types));
2536 finish_var_decl (decl, objc_build_constructor (list_type, v));
2537 return decl;
2538}
2539
c2beaa02
NP
2540/* This routine builds the initializer list to initialize the 'struct
2541 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
d764a8e6
IS
2542
2543static tree
2544build_v2_property_table_initializer (tree type, tree context)
2545{
2546 tree x;
9771b263 2547 vec<constructor_elt, va_gc> *inits = NULL;
d764a8e6
IS
2548 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2549 x = CLASS_PROPERTY_DECL (context);
2550 else
2551 x = IMPL_PROPERTY_DECL (context);
2552
2553 for (; x; x = TREE_CHAIN (x))
2554 {
9771b263 2555 vec<constructor_elt, va_gc> *elemlist = NULL;
c2beaa02
NP
2556 /* NOTE! sections where property name/attribute go MUST change
2557 later. */
d764a8e6
IS
2558 tree attribute, name_ident = PROPERTY_NAME (x);
2559
944fb799 2560 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
d764a8e6
IS
2561 add_objc_string (name_ident, prop_names_attr));
2562
2563 attribute = objc_v2_encode_prop_attr (x);
944fb799 2564 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
d764a8e6
IS
2565 add_objc_string (attribute, prop_names_attr));
2566
2567 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2568 objc_build_constructor (type, elemlist));
2569 }
2570
2571 return objc_build_constructor (build_array_type (type, 0),inits);
2572}
2573
2574/* This routine builds the following type:
c2beaa02
NP
2575 struct _prop_list_t
2576 {
d764a8e6
IS
2577 uint32_t entsize; // sizeof (struct _prop_t)
2578 uint32_t prop_count;
2579 struct _prop_t prop_list [prop_count];
2580 }
2581*/
2582
2583static tree
2584build_v2_property_list_template (tree list_type, int size)
2585{
2586 tree property_list_t_record;
2587 tree array_type, decls, *chain = NULL;
2588
2589 /* anonymous. */
2590 property_list_t_record = objc_start_struct (NULL_TREE);
944fb799 2591
c2beaa02 2592 /* uint32_t const entsize; */
d764a8e6
IS
2593 decls = add_field_decl (integer_type_node, "entsize", &chain);
2594
c2beaa02 2595 /* int prop_count; */
d764a8e6
IS
2596 add_field_decl (integer_type_node, "prop_count", &chain);
2597
2598 /* struct _prop_t prop_list[]; */
2599 array_type = build_sized_array_type (list_type, size);
2600 add_field_decl (array_type, "prop_list", &chain);
2601
2602 objc_finish_struct (property_list_t_record, decls);
2603 return property_list_t_record;
2604}
2605
c2beaa02
NP
2606/* Top-level routine to generate property tables for each
2607 implementation. */
d764a8e6
IS
2608
2609static tree
2610generate_v2_property_table (tree context, tree klass_ctxt)
2611{
2612 tree x, decl, initlist, property_list_template;
2613 bool is_proto = false;
9771b263 2614 vec<constructor_elt, va_gc> *inits = NULL;
d764a8e6
IS
2615 int init_val, size = 0;
2616 char buf[BUFSIZE];
2617
2618 if (context)
2619 {
2620 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2621 x = CLASS_PROPERTY_DECL (context);
2622 is_proto = true;
2623 }
2624 else
2625 x = IMPL_PROPERTY_DECL (klass_ctxt);
2626
2627 for (; x; x = TREE_CHAIN (x))
2628 size++;
2629
2630 if (size == 0)
2631 return NULL_TREE;
2632
944fb799
MS
2633 property_list_template =
2634 build_v2_property_list_template (objc_v2_property_template,
d764a8e6
IS
2635 size);
2636
2637 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2638 is_proto ? context
2639 : klass_ctxt);
2640
2641 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2642 if (is_proto)
2643 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2644 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2645 else
2646 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2647 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2648
2649 decl = start_var_decl (property_list_template, buf);
2650
944fb799 2651 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
d764a8e6 2652 build_int_cst (NULL_TREE, init_val));
944fb799 2653 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
d764a8e6
IS
2654 build_int_cst (NULL_TREE, size));
2655 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2656
2657 OBJCMETA (decl, objc_meta, meta_base);
2658 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2659 return decl;
2660}
2661
2662static tree
2663build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
944fb799 2664 tree inst_methods, tree class_methods,
d764a8e6 2665 tree opt_ins_meth, tree opt_cls_meth,
6224a8aa
IS
2666 tree property_list, tree ext_meth_types,
2667 tree demangled_name, tree class_prop_list)
d764a8e6
IS
2668{
2669 tree expr, ttyp;
2670 location_t loc;
9771b263 2671 vec<constructor_elt, va_gc> *inits = NULL;
d764a8e6
IS
2672
2673 /* TODO: find a better representation of location from the inputs. */
2674 loc = UNKNOWN_LOCATION;
2675
2676 /* This is NULL for the new ABI. */
944fb799 2677 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
d764a8e6
IS
2678 convert (objc_object_type, null_pointer_node));
2679
2680 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2681 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2682
2683 ttyp = objc_method_proto_list_ptr;
2684 if (inst_methods)
2685 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2686 else
2687 expr = convert (ttyp, null_pointer_node);
2688 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2689
2690 if (class_methods)
2691 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2692 else
2693 expr = convert (ttyp, null_pointer_node);
2694 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2695
2696 if (opt_ins_meth)
2697 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2698 else
2699 expr = convert (ttyp, null_pointer_node);
2700 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2701
2702 if (opt_cls_meth)
2703 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2704 else
2705 expr = convert (ttyp, null_pointer_node);
2706 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2707
2708 ttyp = objc_prop_list_ptr;
2709 if (property_list)
2710 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2711 else
2712 expr = convert (ttyp, null_pointer_node);
2713 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2714
2715 /* const uint32_t size; = sizeof(struct protocol_t) */
944fb799 2716 expr = build_int_cst (integer_type_node,
d764a8e6
IS
2717 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2718 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2719 /* const uint32_t flags; = 0 */
2720 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2721
6224a8aa
IS
2722 ttyp = build_pointer_type (string_type_node);
2723 if (ext_meth_types)
2724 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, ext_meth_types, 0));
2725 else
2726 expr = convert (ttyp, null_pointer_node);
2727 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2728
2729 ttyp = string_type_node;
2730 if (demangled_name)
2731 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, demangled_name, 0));
2732 else
2733 expr = convert (ttyp, null_pointer_node);
2734 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2735
2736 ttyp = objc_prop_list_ptr;
2737 if (class_prop_list)
2738 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_prop_list, 0));
2739 else
2740 expr = convert (ttyp, null_pointer_node);
2741 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2742
2743 return objc_build_constructor (type, inits);
d764a8e6
IS
2744}
2745
c2beaa02
NP
2746/* Main routine to build all meta data for all protocols used in a
2747 translation unit. */
d764a8e6
IS
2748
2749static void
2750generate_v2_protocols (void)
2751{
2752 tree p ;
2753 bool some = false;
2754
2755 if (!protocol_chain)
2756 return ;
2757
c2beaa02
NP
2758 /* If a protocol was directly referenced, pull in indirect
2759 references. */
d764a8e6
IS
2760 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2761 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2762 generate_protocol_references (PROTOCOL_LIST (p));
2763
2764 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2765 {
2766 location_t loc;
2767 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2768 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2769
2770 /* If protocol wasn't referenced, don't generate any code. */
2771 decl = PROTOCOL_FORWARD_DECL (p);
2772
2773 if (!decl)
2774 continue;
2775
2776 loc = DECL_SOURCE_LOCATION (decl);
2777 some = true;
2778
6224a8aa 2779 vec<tree> all_meths = vNULL;
944fb799 2780 inst_meth =
d764a8e6
IS
2781 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2782 "_OBJC_ProtocolInstanceMethods",
6224a8aa 2783 meta_proto_nst_meth, all_meths);
d764a8e6 2784
944fb799 2785 class_meth =
d764a8e6
IS
2786 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2787 "_OBJC_ProtocolClassMethods",
6224a8aa 2788 meta_proto_cls_meth, all_meths);
d764a8e6
IS
2789
2790 opt_inst_meth =
2791 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
6224a8aa
IS
2792 "_OBJC_ProtocolOptInstMethods",
2793 meta_proto_nst_meth, all_meths);
d764a8e6 2794
944fb799 2795 opt_class_meth =
d764a8e6 2796 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
6224a8aa
IS
2797 "_OBJC_ProtocolOptClassMethods",
2798 meta_proto_cls_meth, all_meths);
d764a8e6
IS
2799
2800 if (PROTOCOL_LIST (p))
2801 refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2802 else
2803 refs_decl = 0;
2804
2805 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2806 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2807
2808 if (refs_decl)
2809 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2810 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2811 else
2812 refs_expr = build_int_cst (NULL_TREE, 0);
2813
2814 props = generate_v2_property_table (p, NULL_TREE);
2815
6224a8aa
IS
2816 tree ext_meth_types
2817 = generate_v2_meth_type_list (all_meths, p,
2818 "_OBJC_ProtocolMethodTypes");
2819 tree demangled_name = NULL_TREE;
2820 tree class_prop_list = NULL_TREE;
2821
d764a8e6
IS
2822 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2823 protocol_name_expr, refs_expr,
2824 inst_meth, class_meth,
2825 opt_inst_meth, opt_class_meth,
6224a8aa
IS
2826 props, ext_meth_types,
2827 demangled_name,class_prop_list);
d764a8e6
IS
2828 finish_var_decl (decl, initlist);
2829 objc_add_to_protocol_list (p, decl);
6224a8aa 2830 all_meths.truncate (0);
d764a8e6
IS
2831 }
2832
2833 if (some)
2834 {
c2beaa02
NP
2835 /* Make sure we get the Protocol class linked in - reference
2836 it... */
d764a8e6 2837 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
c2beaa02
NP
2838 /* ... but since we don't specifically use the reference... we
2839 need to force it. */
d764a8e6
IS
2840 DECL_PRESERVE_P (p) = 1;
2841 }
2842}
2843
2844static tree
2845generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2846{
2847 tree decl, method_list_template, initlist;
9771b263 2848 vec<constructor_elt, va_gc> *v = NULL;
d764a8e6
IS
2849 int size, init_val;
2850
2851 if (!chain || !name || !(size = list_length (chain)))
2852 return NULL_TREE;
2853
2854 method_list_template
2855 = build_v2_method_list_template (objc_method_template, size);
2856 initlist
2857 = build_dispatch_table_initializer (objc_method_template, chain);
2858
2859 decl = start_var_decl (method_list_template, name);
2860
2861 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
944fb799 2862 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
d764a8e6 2863 build_int_cst (integer_type_node, init_val));
944fb799 2864 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
d764a8e6
IS
2865 build_int_cst (integer_type_node, size));
2866 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2867
2868 OBJCMETA (decl, objc_meta, attr);
2869 finish_var_decl (decl,
2870 objc_build_constructor (TREE_TYPE (decl), v));
2871 return decl;
2872}
2873
2874/* Init a category. */
2875static tree
2876build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2877 tree inst_methods, tree class_methods,
2878 tree protocol_list, tree property_list,
2879 location_t loc)
2880{
2881 tree expr, ltyp;
9771b263 2882 vec<constructor_elt, va_gc> *v = NULL;
d764a8e6
IS
2883
2884 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2885 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2886
2887 ltyp = objc_method_list_ptr;
2888 if (inst_methods)
2889 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2890 else
2891 expr = convert (ltyp, null_pointer_node);
2892 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2893
2894 if (class_methods)
2895 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2896 else
2897 expr = convert (ltyp, null_pointer_node);
2898 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2899
2900 /* protocol_list = */
2901 ltyp = build_pointer_type (objc_v2_protocol_template);
2902 if (protocol_list)
2903 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2904 else
2905 expr = convert (ltyp, null_pointer_node);
2906 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2907
2908 ltyp = objc_prop_list_ptr;
2909 if (property_list)
2910 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2911 else
2912 expr = convert (ltyp, null_pointer_node);
2913 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2914
2915 return objc_build_constructor (type, v);
2916}
2917
c2beaa02 2918/* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
d764a8e6
IS
2919
2920static void
2921generate_v2_category (struct imp_entry *impent)
2922{
2923 tree initlist, cat_name_expr, class_name_expr;
2924 tree protocol_decl, category, props, t;
2925 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2926 tree cat = impent->imp_context;
2927 tree cat_decl = impent->class_decl;
2928 location_t loc;
2929 char buf[BUFSIZE];
944fb799 2930
d764a8e6
IS
2931 loc = DECL_SOURCE_LOCATION (cat_decl);
2932
2933 /* ??? not sure this is really necessary, the following references should
944fb799 2934 force appropriate linkage linkage...
d764a8e6
IS
2935 -- but ... ensure a reference to the class... */
2936 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2937 /* ... which we ignore so force it out.. */
2938 DECL_PRESERVE_P (t) = 1;
2939
2940 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2941 class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2942 class_name_expr = build_fold_addr_expr (class_name_expr);
2943
2944 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2945 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2946
2947 if (category && CLASS_PROTOCOL_LIST (category))
2948 {
2949 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2950 protocol_decl = generate_v2_protocol_list (category, cat);
2951 }
2952 else
2953 protocol_decl = NULL_TREE;
2954
c2beaa02 2955/* decl = update_var_decl(impent->class_decl); */
d764a8e6
IS
2956
2957 props = generate_v2_property_table (NULL_TREE, cat);
2958
2959 if (CLASS_NST_METHODS (cat))
2960 {
2961 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2962 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2963 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2964 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2965 meta_cati_meth);
2966 }
2967
2968 if (CLASS_CLS_METHODS (cat))
2969 {
2970 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2971 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2972 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2973 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2974 meta_catc_meth);
2975 }
2976
2977 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2978 cat_name_expr, class_name_expr,
2979 inst_methods, class_methods,
2980 protocol_decl, props, loc);
2981
2982 finish_var_decl (cat_decl, initlist);
2983 impent->class_decl = cat_decl;
2984
c2beaa02 2985 /* Add to list of pointers in __category_list section. */
d764a8e6
IS
2986 objc_v2_add_to_category_list (cat_decl);
2987 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2988 objc_v2_add_to_nonlazy_category_list (cat_decl);
2989}
2990
c2beaa02
NP
2991/* This routine declares a variable to hold the offset for ivar
2992 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
d764a8e6 2993
a79683d5 2994struct GTY(()) ivarref_entry
c2beaa02 2995{
d764a8e6
IS
2996 tree decl;
2997 tree offset;
a79683d5 2998};
d764a8e6 2999
9771b263 3000static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
d764a8e6
IS
3001
3002static tree
3003ivar_offset_ref (tree class_name, tree field_decl)
3004{
3005 tree decl, field_decl_id;
3006 ivarref_entry e;
3007 bool global_var;
3008 char buf[512];
3009
3010 create_ivar_offset_name (buf, class_name, field_decl);
3011 field_decl_id = get_identifier (buf);
3012
3013 if (ivar_offset_refs)
3014 {
3015 int count;
3016 ivarref_entry *ref;
9771b263 3017 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
d764a8e6
IS
3018 if (DECL_NAME (ref->decl) == field_decl_id)
3019 return ref->decl;
3020 }
3021 else
3022 /* Somewhat arbitrary initial provision. */
9771b263 3023 vec_alloc (ivar_offset_refs, 32);
d764a8e6
IS
3024
3025 /* We come here if we don't find a match or at the start. */
3026 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
3027 if (global_var)
3028 decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
3029 else
3030 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
3031
eb870e5e
IS
3032 /* Identify so that we can indirect these where the ABI requires. */
3033 OBJCMETA (decl, objc_meta, meta_ivar_ref);
d764a8e6
IS
3034
3035 e.decl = decl;
3036 e.offset = byte_position (field_decl);
9771b263 3037 vec_safe_push (ivar_offset_refs, e);
d764a8e6
IS
3038 return decl;
3039}
3040
c2beaa02
NP
3041/* This routine builds initializer-list needed to initialize 'struct
3042 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
3043 'struct ivar_t' and FIELD_DECL is list of ivars for the target
3044 class. */
d764a8e6
IS
3045
3046static tree
3047build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
3048{
9771b263 3049 vec<constructor_elt, va_gc> *inits = NULL;
d764a8e6 3050
944fb799 3051 do
d764a8e6 3052 {
9771b263 3053 vec<constructor_elt, va_gc> *ivar = NULL;
d764a8e6
IS
3054 int val;
3055 tree id;
3056
c2beaa02 3057 /* Unnamed bitfields are ignored. */
d764a8e6
IS
3058 if (!DECL_NAME (field_decl))
3059 {
3060 field_decl = DECL_CHAIN (field_decl);
3061 continue;
3062 }
3063
c2beaa02 3064 /* Set offset. */
d764a8e6
IS
3065 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3066 build_unary_op (input_location,
944fb799
MS
3067 ADDR_EXPR,
3068 ivar_offset_ref (class_name,
d764a8e6
IS
3069 field_decl), 0));
3070
c2beaa02 3071 /* Set name. */
d764a8e6
IS
3072 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3073 add_objc_string (DECL_NAME (field_decl),
3074 meth_var_names));
3075
c2beaa02 3076 /* Set type. */
a8f18c40 3077 id = add_objc_string (encode_field_decl (field_decl),
d764a8e6
IS
3078 meth_var_types);
3079 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
d764a8e6 3080
c2beaa02 3081 /* Set alignment. */
d764a8e6
IS
3082 val = DECL_ALIGN_UNIT (field_decl);
3083 val = exact_log2 (val);
944fb799 3084 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
d764a8e6 3085 build_int_cst (integer_type_node, val));
944fb799 3086
c2beaa02 3087 /* Set size. */
d764a8e6 3088 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
944fb799 3089 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
d764a8e6
IS
3090 build_int_cst (integer_type_node, val));
3091
3092 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3093 objc_build_constructor (type, ivar));
3094
3095 do
3096 field_decl = DECL_CHAIN (field_decl);
3097 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
3098 }
3099 while (field_decl);
3100
3101 return objc_build_constructor (build_array_type (type, 0), inits);
3102}
3103
3104/*
c2beaa02
NP
3105 struct ivar_list_t
3106 {
d764a8e6
IS
3107 uint32 entsize;
3108 uint32 count;
3109 struct iver_t list[count];
3110 };
3111*/
3112
3113static tree
3114build_v2_ivar_list_t_template (tree list_type, int size)
3115{
3116 tree objc_ivar_list_record;
3117 tree decls, *chain = NULL;
3118
c2beaa02 3119 /* Anonymous. */
d764a8e6
IS
3120 objc_ivar_list_record = objc_start_struct (NULL_TREE);
3121
3122 /* uint32 entsize; */
3123 decls = add_field_decl (integer_type_node, "entsize", &chain);
3124
3125 /* uint32 count; */
3126 add_field_decl (integer_type_node, "count", &chain);
3127
3128 /* struct objc_ivar ivar_list[]; */
3129 add_field_decl (build_sized_array_type (list_type, size),
3130 "list", &chain);
3131
3132 objc_finish_struct (objc_ivar_list_record, decls);
3133 return objc_ivar_list_record;
3134}
3135
c2beaa02
NP
3136/* This routine declares a static variable of type 'struct
3137 ivar_list_t' and initializes it. chain is the source of the data,
3138 name is the name for the var. attr is the meta-data section tag
3139 attribute. templ is the implementation template for the class. */
d764a8e6
IS
3140
3141static tree
3142generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
3143{
3144 tree decl, initlist, ivar_list_template;
9771b263 3145 vec<constructor_elt, va_gc> *inits = NULL;
d764a8e6 3146 int size, ivar_t_size;
944fb799 3147
d764a8e6
IS
3148 if (!chain || !name || !(size = ivar_list_length (chain)))
3149 return NULL_TREE;
3150
3151 generating_instance_variables = 1;
3152 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
3153 size);
944fb799 3154
d764a8e6
IS
3155 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
3156 objc_v2_ivar_template, chain);
3157 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
944fb799 3158
d764a8e6 3159 decl = start_var_decl (ivar_list_template, name);
944fb799 3160 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
d764a8e6
IS
3161 build_int_cst (integer_type_node, ivar_t_size));
3162 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3163 build_int_cst (integer_type_node, size));
3164 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
3165 OBJCMETA (decl, objc_meta, attr);
3166 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
3167 generating_instance_variables = 0;
3168 return decl;
3169}
3170
c2beaa02
NP
3171/* Routine to build initializer list to initialize objects of type
3172 struct class_t; */
d764a8e6
IS
3173
3174static tree
3175build_v2_class_t_initializer (tree type, tree isa, tree superclass,
3176 tree ro, tree cache, tree vtable)
3177{
9771b263 3178 vec<constructor_elt, va_gc> *initlist = NULL;
d764a8e6
IS
3179
3180 /* isa */
3181 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
3182
3183 /* superclass */
3184 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
3185
3186 /* cache */
3187 if (cache)
3188 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
3189 else
3190 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3191
3192 /* vtable */
3193 if (vtable)
3194 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
3195 else
3196 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3197
3198 /* ro */
3199 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
3200
3201 return objc_build_constructor (type, initlist);
3202}
3203
c2beaa02 3204/* Routine to build object of struct class_ro_t { ... }; */
d764a8e6
IS
3205
3206static tree
944fb799 3207build_v2_class_ro_t_initializer (tree type, tree name,
d764a8e6 3208 unsigned int flags, unsigned int instanceStart,
944fb799
MS
3209 unsigned int instanceSize,
3210 tree ivarLayout,
3211 tree baseMethods, tree baseProtocols,
d764a8e6
IS
3212 tree ivars, tree property_list)
3213{
3214 tree expr, unsigned_char_star, ltyp;
3215 location_t loc;
9771b263 3216 vec<constructor_elt, va_gc> *initlist = NULL;
d764a8e6
IS
3217
3218 /* TODO: fish out the real location from somewhere. */
3219 loc = UNKNOWN_LOCATION;
3220
3221 /* flags */
944fb799 3222 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
d764a8e6
IS
3223 build_int_cst (integer_type_node, flags));
3224
3225 /* instanceStart */
944fb799 3226 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
d764a8e6
IS
3227 build_int_cst (integer_type_node, instanceStart));
3228
3229 /* instanceSize */
944fb799 3230 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
d764a8e6
IS
3231 build_int_cst (integer_type_node, instanceSize));
3232
c2beaa02
NP
3233 /* This ABI is currently only used on m64 NeXT. We always
3234 explicitly declare the alignment padding. */
3235 /* reserved, pads alignment. */
944fb799 3236 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
d764a8e6
IS
3237 build_int_cst (integer_type_node, 0));
3238
3239 /* ivarLayout */
3240 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3241 if (ivarLayout)
3242 expr = ivarLayout;
3243 else
3244 expr = convert (unsigned_char_star, null_pointer_node);
3245 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3246
3247 /* name */
3248 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3249
3250 /* baseMethods */
3251 ltyp = objc_method_list_ptr;
3252 if (baseMethods)
3253 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3254 else
3255 expr = convert (ltyp, null_pointer_node);
3256 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3257
3258 /* baseProtocols */
944fb799 3259 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
d764a8e6
IS
3260 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3261 if (baseProtocols)
3262 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3263 else
3264 expr = convert (ltyp, null_pointer_node);
3265 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3266
3267 /* ivars */
3268 ltyp = objc_v2_ivar_list_ptr;
3269 if (ivars)
3270 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3271 else
3272 expr = convert (ltyp, null_pointer_node);
3273 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3274
3275 /* TODO: We don't yet have the weak/strong stuff... */
3276 /* weakIvarLayout */
944fb799 3277 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
d764a8e6
IS
3278 convert (unsigned_char_star, null_pointer_node));
3279
3280 /* property list */
3281 ltyp = objc_prop_list_ptr;
3282 if (property_list)
3283 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3284 else
3285 expr = convert (ltyp, null_pointer_node);
3286 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3287 return objc_build_constructor (type, initlist);
3288}
3289
9771b263 3290static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
d764a8e6
IS
3291
3292/* Record a name as needing a catcher. */
3293static void
3294objc_v2_add_to_ehtype_list (tree name)
3295{
3296 ident_data_tuple e;
3297 if (ehtype_list)
3298 {
3299 int count = 0;
3300 ident_data_tuple *ref;
3301
9771b263 3302 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
d764a8e6
IS
3303 if (ref->ident == name)
3304 return; /* Already entered. */
3305 }
3306 else
3307 /* Arbitrary initial count. */
9771b263 3308 vec_alloc (ehtype_list, 8);
c2beaa02 3309
d764a8e6
IS
3310 /* Not found, or new list. */
3311 e.ident = name;
3312 e.data = NULL_TREE;
9771b263 3313 vec_safe_push (ehtype_list, e);
d764a8e6
IS
3314}
3315
3316static void
3317generate_v2_class_structs (struct imp_entry *impent)
3318{
3319 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3320 tree field, firstIvar, chain;
3321 tree class_superclass_expr, metaclass_superclass_expr, props;
3322 /* TODO: figure out how to compute this. */
3323 tree ivarLayout = NULL_TREE;
3324 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3325 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3326 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3327 location_t loc;
3328 char buf[BUFSIZE];
3329 unsigned int instanceStart, instanceSize;
3330 unsigned int flags = 0x01; /* RO_META */
3331 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3332 : 0 ;
3333
3334 class_decl = impent->class_decl;
3335 metaclass_decl = impent->meta_decl;
3336 loc = DECL_SOURCE_LOCATION (class_decl);
3337
3338 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3339 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3340#ifdef OBJCPLUS
3341 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3342 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3343#endif
3344
c2beaa02 3345 /* Generation of data for meta class. */
d764a8e6
IS
3346 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3347 if (my_super_id)
3348 {
c2beaa02
NP
3349 /* Compute reference to root's name. For a meta class, "isa" is
3350 a reference to the root class name. */
d764a8e6
IS
3351 tree my_root_id = my_super_id;
3352 tree my_root_int, interface;
3353 do
3354 {
3355 my_root_int = lookup_interface (my_root_id);
3356
3357 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3358 my_root_id = CLASS_SUPER_NAME (my_root_int);
3359 else
3360 break;
3361 }
3362 while (1);
3363
944fb799 3364 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
d764a8e6 3365 create extern if not already declared. */
944fb799 3366 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
d764a8e6
IS
3367 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3368 root_expr = create_extern_decl (objc_v2_class_template, buf);
3369 root_expr = build_fold_addr_expr (root_expr);
3370
3371 /* Install class `isa' and `super' pointers at runtime. */
3372 interface = lookup_interface (my_super_id);
3373 gcc_assert (interface);
c2beaa02 3374 /* Similarly, for OBJC_CLASS_$_<interface>... */
944fb799 3375 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
d764a8e6
IS
3376 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3377 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3378 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
c2beaa02 3379 /* ... and for OBJC_METACLASS_$_<interface>. */
944fb799 3380 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
d764a8e6
IS
3381 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3382 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3383 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3384 }
3385 else
3386 {
c2beaa02 3387 /* Root class. */
d764a8e6
IS
3388 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3389 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3390 class_superclass_expr = build_int_cst (NULL_TREE, 0);
c2beaa02 3391 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */
d764a8e6
IS
3392 }
3393
3394 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3395 {
3396 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3397 protocol_decl = generate_v2_protocol_list (impent->imp_template,
3398 impent->imp_context);
3399 }
3400 else
3401 protocol_decl = 0;
3402
3403 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3404 class_names);
3405
3406 if (CLASS_CLS_METHODS (impent->imp_context))
3407 {
3408 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3409 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
944fb799 3410 class_methods =
d764a8e6
IS
3411 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3412 buf, meta_clac_meth);
3413 }
3414
3415 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3416
c2beaa02
NP
3417 /* Currently there are no class ivars and generation of class
3418 variables for the root of the inheritance has been removed. It
3419 causes multiple defines if there are two root classes in the
3420 link, because each will define its own identically-named offset
3421 variable. */
d764a8e6
IS
3422
3423 class_ivars = NULL_TREE;
3424 /* TODO: Add total size of class variables when implemented. */
944fb799 3425 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
d764a8e6
IS
3426
3427 /* So now build the META CLASS structs. */
3428 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3429
3430 decl = start_var_decl (objc_v2_class_ro_template,
3431 newabi_append_ro (IDENTIFIER_POINTER
3432 (DECL_NAME (metaclass_decl))));
3433
c2beaa02 3434 /* TODO: ivarLayout needs t be built. */
944fb799 3435 initlist =
d764a8e6
IS
3436 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3437 (flags | cls_flags), instanceStart,
944fb799 3438 instanceSize, ivarLayout,
d764a8e6
IS
3439 class_methods, protocol_decl,
3440 class_ivars, NULL_TREE);
3441 /* The ROs sit in the default const section. */
3442 OBJCMETA (decl, objc_meta, meta_base);
3443 finish_var_decl (decl, initlist);
3444
3445 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
944fb799 3446 initlist =
d764a8e6
IS
3447 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3448 root_expr,
3449 metaclass_superclass_expr,
3450 build_fold_addr_expr (decl),
944fb799 3451 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
d764a8e6
IS
3452 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3453 /* The class section attributes are set when they are created. */
3454 finish_var_decl (metaclass_decl, initlist);
3455 impent->meta_decl = metaclass_decl;
3456
3457 /* So now build the CLASS structs. */
3458
3459 flags = 0x0; /* ... */
3460 if (!my_super_id)
3461 flags |= 0x02; /* RO_ROOT: this is a root class */
3462
3463 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3464 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3465
3466 if (objc2_objc_exception_attr (impent->imp_template))
3467 flags |= 0x20; /* RO_EXCEPTION */
3468
3469 if (CLASS_NST_METHODS (impent->imp_context))
3470 {
3471 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3472 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
944fb799 3473 inst_methods =
d764a8e6
IS
3474 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3475 buf, meta_clai_meth);
3476 }
3477
3478 /* Sort out the ivars before we try to compute the class sizes. */
3479 if ((chain = CLASS_IVARS (impent->imp_template)))
3480 {
3481 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3482 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
944fb799 3483 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
d764a8e6
IS
3484 impent->imp_template);
3485 }
3486
c2beaa02 3487 /* Compute instanceStart. */
d764a8e6
IS
3488 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3489 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3490 if (my_super_id && field && TREE_CHAIN (field))
3491 field = TREE_CHAIN (field);
3492
3493 firstIvar = field;
3494
3495 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3496 firstIvar = TREE_CHAIN (firstIvar);
3497
3498 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3499
c2beaa02 3500 /* Compute instanceSize. */
d764a8e6
IS
3501 while (field && TREE_CHAIN (field)
3502 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3503 field = TREE_CHAIN (field);
944fb799 3504
d764a8e6 3505 if (field && TREE_CODE (field) == FIELD_DECL)
944fb799 3506 instanceSize = int_byte_position (field) * BITS_PER_UNIT
9439e9a1 3507 + tree_to_shwi (DECL_SIZE (field));
d764a8e6
IS
3508 else
3509 instanceSize = 0;
3510 instanceSize /= BITS_PER_UNIT;
3511
3512 props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3513
c2beaa02
NP
3514 /* If the class has no ivars, instanceStart should be set to the
3515 superclass's instanceSize. */
944fb799
MS
3516 instanceStart =
3517 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
d764a8e6
IS
3518 : instanceSize;
3519
3520 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
944fb799 3521 decl = start_var_decl (objc_v2_class_ro_template,
d764a8e6 3522 newabi_append_ro (IDENTIFIER_POINTER
944fb799 3523 (DECL_NAME (class_decl))));
d764a8e6 3524
944fb799 3525 initlist =
d764a8e6
IS
3526 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3527 (flags | cls_flags), instanceStart,
944fb799 3528 instanceSize, ivarLayout,
d764a8e6
IS
3529 inst_methods, protocol_decl,
3530 inst_ivars, props);
3531 /* The ROs sit in the default const section. */
3532 OBJCMETA (decl, objc_meta, meta_base);
3533 finish_var_decl (decl, initlist);
3534
3535 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3536 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3537 build_fold_addr_expr (metaclass_decl),
3538 class_superclass_expr,
3539 build_fold_addr_expr (decl),
944fb799
MS
3540 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3541 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
d764a8e6
IS
3542
3543 /* The class section attributes are set when they are created. */
3544 finish_var_decl (class_decl, initlist);
3545 impent->class_decl = class_decl;
3546
3547 objc_v2_add_to_class_list (class_decl);
3548 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3549 objc_v2_add_to_nonlazy_class_list (class_decl);
3550
3551 if (flags & 0x20) /* RO_EXCEPTION */
3552 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3553}
3554
c2beaa02
NP
3555/* This routine outputs the (ivar_reference_offset, offset)
3556 tuples. */
d764a8e6
IS
3557
3558static void
3559build_v2_ivar_offset_ref_table (void)
3560{
3561 int count;
3562 ivarref_entry *ref;
3563
9771b263 3564 if (!vec_safe_length (ivar_offset_refs))
d764a8e6
IS
3565 return;
3566
9771b263 3567 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
d764a8e6
IS
3568 finish_var_decl (ref->decl, ref->offset);
3569}
3570
d764a8e6
IS
3571static void
3572objc_generate_v2_next_metadata (void)
3573{
3574 struct imp_entry *impent;
3575
c2beaa02
NP
3576 /* FIXME: Make sure that we generate no metadata if there is nothing
3577 to put into it. */
3578
d764a8e6
IS
3579 gcc_assert (!objc_static_instances); /* Not for NeXT */
3580
3581 build_metadata_templates ();
3582
3583 for (impent = imp_list; impent; impent = impent->next)
3584 {
3585 /* If -gen-decls is present, Dump the @interface of each class.
c2beaa02
NP
3586 TODO: Dump the classes in the order they were found, rather
3587 than in reverse order as we are doing now. */
d764a8e6
IS
3588 if (flag_gen_declaration)
3589 dump_interface (gen_declaration_file, impent->imp_context);
3590
3591 /* all of the following reference the string pool... */
3592 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3593 generate_v2_class_structs (impent);
3594 else
3595 generate_v2_category (impent);
3596 }
3597
3598 build_next_selector_translation_table ();
3599 build_v2_message_ref_translation_table ();
3600
3601 /* This will add "Protocol" to the class refs. */
3602 generate_v2_protocols ();
3603
3604 build_v2_classrefs_table ();
3605 build_v2_super_classrefs_table (/*metaclass= */false);
3606 build_v2_super_classrefs_table (/*metaclass= */true);
3607
3608 build_v2_ivar_offset_ref_table ();
3609
3610 build_v2_protocol_list_translation_table ();
3611 build_v2_protocol_list_address_table ();
3612
944fb799 3613 build_v2_address_table (class_list, "_OBJC_ClassList$",
d764a8e6 3614 meta_label_classlist);
944fb799 3615 build_v2_address_table (category_list, "_OBJC_CategoryList$",
d764a8e6 3616 meta_label_categorylist);
944fb799 3617 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
d764a8e6 3618 meta_label_nonlazy_classlist);
944fb799 3619 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
d764a8e6
IS
3620 meta_label_nonlazy_categorylist);
3621
d764a8e6
IS
3622 /* Generate catch objects for eh, if any are needed. */
3623 build_v2_eh_catch_objects ();
3624
3625 /* Emit the string table last. */
3626 generate_strings ();
3627}
3628
3629/* NOTE --- Output NeXT V2 Exceptions --- */
3630
3631static GTY(()) tree objc_v2_ehtype_template;
3632static GTY(()) tree next_v2_ehvtable_decl;
3633static GTY(()) tree next_v2_EHTYPE_id_decl;
3634
3635static void
3636build_v2_ehtype_template (void)
3637{
3638 tree decls, *chain = NULL;
3639 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3640
3641 /* void *_objc_ehtype_vtable; */
3642 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3643
3644 /* const char *className; */
3645 add_field_decl (string_type_node, "className", &chain);
3646
3647 /* struct class_t *const cls; */
3648 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3649
3650 objc_finish_struct (objc_v2_ehtype_template, decls);
3651}
3652
c2beaa02
NP
3653/* Template for the Objective-C family typeinfo type for ABI=2. This
3654 starts off the same as the gxx/cxx eh typeinfo.
d764a8e6 3655
c2beaa02
NP
3656 struct _objc_ehtype_t
3657 {
d764a8e6
IS
3658 void *_objc_ehtype_vtable_ptr; - as per c++
3659 const char *className; - as per c++
3660 struct class_t *const cls;
3661 }
3662*/
3663
3664/* This routine builds initializer list for object of type struct _objc_ehtype_t.
3665*/
3666
3667static tree
3668objc2_build_ehtype_initializer (tree name, tree cls)
3669{
9771b263 3670 vec<constructor_elt, va_gc> *initlist = NULL;
d764a8e6
IS
3671 tree addr, offs;
3672
c2beaa02
NP
3673 /* This is done the same way as c++, missing the two first entries
3674 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3675 runtime source about this so, perhaps, this will change at some
3676 point. */
d764a8e6
IS
3677 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3678 if (!next_v2_ehvtable_decl)
3679 {
3680 next_v2_ehvtable_decl =
3681 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3682 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3683 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3684 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3685 }
3686 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3687 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
5d49b6a7 3688 addr = fold_build_pointer_plus (addr, offs);
d764a8e6
IS
3689
3690 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3691
3692 /* className */
3693 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3694
3695 /* cls */
3696 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3697
3698 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3699}
3700
3701static tree
3702build_ehtype (tree name, const char *eh_name, bool weak)
3703{
3704 tree name_expr, class_name_expr, ehtype_decl, inits;
3705
3706 name_expr = add_objc_string (name, class_names);
c2beaa02
NP
3707 /* Extern ref. for the class. ??? Maybe we can look this up
3708 somewhere. */
944fb799 3709 class_name_expr =
d764a8e6
IS
3710 create_extern_decl (objc_v2_class_template,
3711 objc_build_internal_classname (name, false));
3712 class_name_expr = build_fold_addr_expr (class_name_expr);
3713 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3714 if (weak)
3715 DECL_WEAK (ehtype_decl) = 1;
3716 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3717 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3718 finish_var_decl (ehtype_decl, inits);
3719 return ehtype_decl;
3720}
3721
3722/* This routine returns TRUE if CLS or any of its super classes has
c2beaa02 3723 __attribute__ ((objc_exception)). */
d764a8e6
IS
3724
3725static bool
3726objc2_objc_exception_attr (tree cls)
3727{
3728 while (cls)
3729 {
3730 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3731 return true;
3732 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3733 }
3734
944fb799 3735 return false;
d764a8e6
IS
3736}
3737
944fb799 3738static bool
d764a8e6
IS
3739is_implemented (tree name)
3740{
3741 struct imp_entry *t;
3742 for (t = imp_list; t; t = t->next)
3743 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3744 && CLASS_NAME (t->imp_template) == name)
3745 return true;
3746
3747 return false;
3748}
3749
3750/* We will build catch objects:
3751 for any type implemented here.
3752 for any type used in a catch that has no exception attribute. */
3753static void build_v2_eh_catch_objects (void)
3754{
3755 int count=0;
3756 ident_data_tuple *ref;
3757
9771b263 3758 if (!vec_safe_length (ehtype_list))
d764a8e6
IS
3759 return;
3760
9771b263 3761 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
d764a8e6
IS
3762 {
3763 char buf[BUFSIZE];
3764 bool impl = is_implemented (ref->ident);
3765 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3766 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3767 if (!impl && excpt)
3768 /* The User says this class has a catcher already. */
3769 ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3770 else
3771 /* Create a catcher, weak if it wasn't marked. */
3772 ref->data = build_ehtype (ref->ident, buf, !excpt);
3773 }
3774}
3775
3776static tree
3777lookup_ehtype_ref (tree id)
3778{
3779 int count=0;
3780 ident_data_tuple *ref;
3781
9771b263 3782 if (!vec_safe_length (ehtype_list))
d764a8e6
IS
3783 return NULL_TREE;
3784
9771b263 3785 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
d764a8e6
IS
3786 if (ref->ident == id)
3787 return ref->data;
3788 return NULL_TREE;
3789}
3790
c2beaa02
NP
3791/* This hook, called via lang_eh_runtime_type, generates a runtime
3792 object which is either the address of the 'OBJC_EHTYPE_$_class'
3793 object or address of external OBJC_EHTYPE_id object. */
d764a8e6
IS
3794static tree
3795next_runtime_02_eh_type (tree type)
3796{
3797 tree t;
3798
3799 if (type == error_mark_node
3800 /*|| errorcount || sorrycount*/)
3801 goto err_mark_in;
3802
3803 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3804 {
3805 if (!next_v2_EHTYPE_id_decl)
3806 {
c2beaa02
NP
3807 /* This is provided by the Apple/NeXT libobjc.dylib so we
3808 need only to reference it. */
944fb799 3809 next_v2_EHTYPE_id_decl =
d764a8e6
IS
3810 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3811 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3812 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3813 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3814 }
3815 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3816 }
3817
3818 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3819 {
3820#ifdef OBJCPLUS
c2beaa02
NP
3821 /* This routine is also called for c++'s catch clause; in which
3822 case, we use c++'s typeinfo decl. */
d764a8e6
IS
3823 return build_eh_type_type (type);
3824#else
0f2c4a8f 3825 error ("non-objective-c type %qT cannot be caught", type);
d764a8e6
IS
3826 goto err_mark_in;
3827#endif
3828 }
944fb799 3829 else
d764a8e6 3830 t = OBJC_TYPE_NAME (TREE_TYPE (type));
944fb799 3831
c2beaa02 3832 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
d764a8e6
IS
3833 t = lookup_ehtype_ref (t);
3834 if (!t)
3835 goto err_mark_in;
3836
3837 return build_fold_addr_expr (t);
3838
3839err_mark_in:
3840 return error_mark_node;
3841}
3842
3843static GTY(()) tree objc_eh_personality_decl;
3844
3845static tree
3846objc_eh_personality (void)
3847{
3848 if (!objc_eh_personality_decl)
3849 objc_eh_personality_decl = build_personality_function ("objc");
3850 return objc_eh_personality_decl;
3851}
3852
3853/* NOTE --- interfaces --- */
3854
3855static tree
3856build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3857{
3858 tree t;
3859 if (rethrown)
3860 /* We have a separate re-throw entry. */
81e5eca8
MP
3861 t = build_function_call_vec (loc, vNULL, objc_rethrow_exception_decl,
3862 NULL, NULL);
d764a8e6
IS
3863 else
3864 {
c2beaa02 3865 /* Throw like the others... */
9771b263
DN
3866 vec<tree, va_gc> *parms;
3867 vec_alloc (parms, 1);
3868 parms->quick_push (throw_expr);
81e5eca8
MP
3869 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl,
3870 parms, 0);
9771b263 3871 vec_free (parms);
d764a8e6
IS
3872 }
3873 return add_stmt (t);
3874}
3875
3876/* Build __builtin_eh_pointer. */
3877
3878static tree
3879objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3880{
3881 tree t;
e79983f4 3882 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
d764a8e6
IS
3883 t = build_call_expr (t, 1, integer_zero_node);
3884 return fold_convert (objc_object_type, t);
3885}
3886
3887static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3888 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3889{
3890 tree t;
3891
3892 /* Record the data for the catch in the try context so that we can
3893 finalize it later. Ellipsis is signalled by a NULL entry. */
3894 if (ellipsis)
3895 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3896 else
3897 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3898 (*cur_try_context)->current_catch = t;
3899
3900 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3901 t = objc_build_exc_ptr (cur_try_context);
3902 t = convert (TREE_TYPE (decl), t);
c2beaa02 3903 /* FIXME: location. */
d764a8e6
IS
3904 if (type && type != error_mark_node)
3905 {
3906 t = build1(NOP_EXPR, ptr_type_node, t);
3907 t = build_function_call (input_location, objc2_begin_catch_decl,
3908 tree_cons (NULL_TREE, t, NULL_TREE));
3909
c2beaa02
NP
3910 /* We might want to build a catch object for this (if it's not
3911 id). */
d764a8e6
IS
3912 if (POINTER_TYPE_P (type)
3913 && !objc_is_object_id (TREE_TYPE (type))
3914 && TYPED_OBJECT (TREE_TYPE (type)))
3915 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3916 }
3917 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3918}
3919
3920/* try { catch-body } finally { objc_end_catch (); } */
944fb799 3921static void
d764a8e6
IS
3922finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3923{
3924 struct objc_try_context *ct;
3925 tree try_exp, func, *l, t ;
3926 location_t loc = (*cur_try_context)->try_locus;
3927
3928 if (!curr_catch || curr_catch == error_mark_node)
3929 return;
3930
3931 t = CATCH_BODY (curr_catch);
3932 if (TREE_CODE (t) == BIND_EXPR)
3933 {
c2beaa02 3934 /* Usual case of @catch (objc-expr). */
d764a8e6
IS
3935 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3936 BIND_EXPR_BODY (t) = NULL_TREE;
3937 l = &BIND_EXPR_BODY (t);
3938 }
3939 else
3940 {
c2beaa02 3941 /* NULL entry, meaning @catch (...). */
d764a8e6
IS
3942 objc_begin_try_stmt (loc, t);
3943 CATCH_BODY (curr_catch) = NULL_TREE;
3944 l = &CATCH_BODY (curr_catch);
3945 }
3946
c2beaa02 3947 /* Pick up the new context we made in begin_try above... */
944fb799 3948 ct = *cur_try_context;
81e5eca8
MP
3949 func = build_function_call_vec (loc, vNULL, objc2_end_catch_decl, NULL,
3950 NULL);
d764a8e6
IS
3951 append_to_statement_list (func, &ct->finally_body);
3952 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3953 *cur_try_context = ct->outer;
3954 free (ct);
3955 append_to_statement_list (try_exp, l);
3956 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3957}
3958
944fb799 3959static tree
d764a8e6
IS
3960finish_try_stmt (struct objc_try_context **cur_try_context)
3961{
3962 struct objc_try_context *c = *cur_try_context;
3963 tree stmt = c->try_body;
3964 if (c->catch_list)
3965 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3966 if (c->finally_body)
3967 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3968 return stmt;
3969}
3970
3971#include "gt-objc-objc-next-runtime-abi-02.h"