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