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