]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/objc/objc-next-runtime-abi-02.c
re PR target/48094 (ld: warning: section has unexpectedly large size errors in objc...
[thirdparty/gcc.git] / gcc / objc / objc-next-runtime-abi-02.c
1 /* Next Runtime (ABI-2) private.
2 Copyright (C) 2011-2013 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, va_gc> **,
212 tree, 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
1019 /* This routine creates a file scope static variable of type 'Class'
1020 to hold the address of a class. */
1021
1022 static tree
1023 build_v2_class_reference_decl (tree ident)
1024 {
1025 tree decl;
1026 char buf[BUFSIZE];
1027
1028 snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1029 decl = start_var_decl (objc_class_type, buf);
1030 OBJCMETA (decl, objc_meta, meta_class_ref);
1031 return decl;
1032 }
1033
1034 /* This routine builds a class refs entry for each class name used.
1035 Initially, a (static-ref, IDENT) tuple is added to the list. The
1036 ident is replaced with address of the class metadata (of type
1037 'Class') in the output routine. */
1038
1039 static GTY (()) vec<ident_data_tuple, va_gc> *classrefs;
1040
1041 static tree
1042 objc_v2_get_class_reference (tree ident)
1043 {
1044 tree decl;
1045 ident_data_tuple e;
1046 if (classrefs)
1047 {
1048 int count;
1049 ident_data_tuple *ref;
1050 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1051 {
1052 if (ref->ident == ident)
1053 {
1054 if (!ref->data)
1055 ref->data = build_v2_class_reference_decl (ident);
1056 return ref->data;
1057 }
1058 }
1059 }
1060 else
1061 /* Somewhat arbitrary initial provision. */
1062 vec_alloc (classrefs, 16);
1063
1064 /* We come here if we don't find the entry - or if the table was yet
1065 to be created. */
1066 decl = build_v2_class_reference_decl (ident);
1067 e.ident = ident;
1068 e.data = decl;
1069 vec_safe_push (classrefs, e);
1070 return decl;
1071 }
1072
1073 static tree
1074 next_runtime_abi_02_get_class_reference (tree ident)
1075 {
1076 if (!flag_zero_link)
1077 return objc_v2_get_class_reference (ident);
1078 else
1079 {
1080 /* We fall back to using objc_getClass (). */
1081 vec<tree, va_gc> *v;
1082 vec_alloc (v, 1);
1083 tree t;
1084 /* ??? add_class_reference (ident); - is pointless, since the
1085 system lib does not export the equivalent symbols. Maybe we
1086 need to build a class ref anyway. */
1087 t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1088 IDENTIFIER_POINTER (ident));
1089 v->quick_push (t);
1090 t = build_function_call_vec (input_location, objc_get_class_decl, v, 0);
1091 vec_free (v);
1092 return t;
1093 }
1094 }
1095
1096 /* Used by build_function_type_for_method. Append the types for
1097 receiver & _cmd at the start of a method argument list to ARGTYPES.
1098 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1099 trying to define a method or call one. SUPERFLAG says this is for a
1100 send to super. METH may be NULL, in the case that there is no
1101 prototype. */
1102
1103 static void
1104 next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1105 tree meth, int context,
1106 int superflag)
1107 {
1108 tree receiver_type;
1109
1110 if (superflag)
1111 receiver_type = objc_super_type;
1112 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1113 receiver_type = objc_instance_type;
1114 else
1115 receiver_type = objc_object_type;
1116
1117 vec_safe_push (*argtypes, receiver_type);
1118 /* Selector type - will eventually change to `int'. */
1119 vec_safe_push (*argtypes,
1120 superflag ? objc_v2_super_selector_type
1121 : objc_v2_selector_type);
1122 }
1123
1124 /* TODO: Merge this with the message refs. */
1125 static tree
1126 build_selector_reference_decl (tree ident)
1127 {
1128 tree decl;
1129 char *t, buf[BUFSIZE];
1130
1131 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1132 t = buf;
1133 while (*t)
1134 {
1135 if (*t==':')
1136 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1137 t++;
1138 }
1139 decl = start_var_decl (objc_selector_type, buf);
1140 OBJCMETA (decl, objc_meta, meta_sel_refs);
1141 return decl;
1142 }
1143
1144 static tree
1145 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1146 tree ident,
1147 tree proto ATTRIBUTE_UNUSED)
1148 {
1149 tree *chain = &sel_ref_chain;
1150 tree expr;
1151
1152 while (*chain)
1153 {
1154 if (TREE_VALUE (*chain) == ident)
1155 return TREE_PURPOSE (*chain);
1156
1157 chain = &TREE_CHAIN (*chain);
1158 }
1159
1160 expr = build_selector_reference_decl (ident);
1161 *chain = tree_cons (expr, ident, NULL_TREE);
1162
1163 return expr;
1164 }
1165
1166 /* Declare a variable of type 'struct message_ref_t'. */
1167 /* This will be finished in build_v2_message_ref_translation_table ().
1168 We take an idea from LLVM in making the names a bit more connected
1169 and thus the asm more readable. */
1170
1171 static tree
1172 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1173 {
1174 tree decl;
1175 char buf[BUFSIZE], *t;
1176 int offset = 12;
1177
1178 /* Skip past the objc_msgSend it's the same for all... */
1179 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1180 offset++;
1181
1182 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1183 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1184 IDENTIFIER_POINTER (sel_name));
1185 t = buf;
1186 while (*t)
1187 {
1188 if (*t==':')
1189 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1190 t++;
1191 }
1192 decl = start_var_decl (objc_v2_message_ref_template, buf);
1193 OBJCMETA (decl, objc_meta, meta_mref);
1194 return decl;
1195 }
1196
1197 typedef struct GTY(()) msgref_entry {
1198 tree func;
1199 tree selname;
1200 tree refdecl;
1201 } msgref_entry;
1202
1203 static GTY (()) vec<msgref_entry, va_gc> *msgrefs;
1204
1205 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1206 later on to initialize the table of 'struct message_ref_t'
1207 elements. */
1208
1209 static tree
1210 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1211 {
1212 tree decl;
1213 msgref_entry e;
1214 if (msgrefs)
1215 {
1216 int count;
1217 msgref_entry *ref;
1218 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1219 if (ref->func == message_func_decl && ref->selname == sel_name)
1220 return ref->refdecl;
1221 }
1222 else
1223 /* Somewhat arbitrary initial provision. */
1224 vec_alloc (msgrefs, 32);
1225
1226 /* We come here if we don't find a match or at the start. */
1227 decl = build_v2_message_reference_decl (sel_name,
1228 DECL_NAME (message_func_decl));
1229 e.func = message_func_decl;
1230 e.selname = sel_name;
1231 e.refdecl = decl;
1232 vec_safe_push (msgrefs, e);
1233 return decl;
1234 }
1235
1236 static tree
1237 build_v2_protocollist_ref_decl (tree protocol)
1238 {
1239 tree decl;
1240 tree protocol_ident = PROTOCOL_NAME (protocol);
1241 char buf[BUFSIZE];
1242
1243 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1244 IDENTIFIER_POINTER (protocol_ident));
1245 /* TODO: other compiler versions make these hidden & weak. */
1246 decl = create_global_decl (objc_protocol_type, buf);
1247 /* Let optimizer know that this decl is not removable. */
1248 DECL_PRESERVE_P (decl) = 1;
1249 OBJCMETA (decl, objc_meta, meta_proto_ref);
1250 return decl;
1251 }
1252
1253 typedef struct GTY(()) prot_list_entry {
1254 tree id;
1255 tree refdecl;
1256 } prot_list_entry;
1257 static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
1258
1259 static tree
1260 objc_v2_get_protocol_reference (tree ident)
1261 {
1262 tree decl;
1263 prot_list_entry e;
1264 if (protrefs)
1265 {
1266 int count;
1267 prot_list_entry *ref;
1268 FOR_EACH_VEC_ELT (*protrefs, count, ref)
1269 {
1270 if (ref->id == ident)
1271 {
1272 if (!ref->refdecl)
1273 ref->refdecl = build_v2_protocollist_ref_decl (ident);
1274 return ref->refdecl;
1275 }
1276 }
1277 }
1278 else
1279 /* Somewhat arbitrary initial provision. */
1280 vec_alloc (protrefs, 32);
1281
1282 /* We come here if we don't find the entry - or if the table was yet
1283 to be created. */
1284 decl = build_v2_protocollist_ref_decl (ident);
1285 e.id = ident;
1286 e.refdecl = decl;
1287 vec_safe_push (protrefs, e);
1288 return decl;
1289 }
1290
1291 static tree
1292 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1293 tree p)
1294 {
1295 if (!PROTOCOL_FORWARD_DECL (p))
1296 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1297
1298 return objc_v2_get_protocol_reference (p);
1299 }
1300
1301 /* This routine returns the ivar declaration, if component is a valid
1302 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1303 returns the class name in CLASS. */
1304
1305 static tree
1306 objc_is_ivar (tree expr, tree component, tree *klass)
1307 {
1308 tree field = NULL_TREE;
1309 tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1310
1311 if (TREE_CODE (basetype) == RECORD_TYPE
1312 && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1313 {
1314 *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1315 if (*klass)
1316 {
1317 do
1318 {
1319 tree ivar_chain = CLASS_RAW_IVARS (*klass);
1320 if (ivar_chain)
1321 {
1322 field = is_ivar (ivar_chain, component);
1323 if (field != NULL_TREE)
1324 break;
1325 }
1326 *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1327 }
1328 while (*klass);
1329 }
1330 }
1331 return field;
1332 }
1333
1334 static void
1335 create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1336 {
1337 tree fname = DECL_NAME (field_decl);
1338
1339 sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1340 IDENTIFIER_POINTER (fname));
1341 return;
1342 }
1343
1344 /* This routine generates new abi's ivar reference tree. It amounts
1345 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1346 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1347 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1348
1349 static tree
1350 objc_v2_build_ivar_ref (tree datum, tree component)
1351 {
1352 tree field, ref, class_name, offset, ftype, expr;
1353 char var_offset_name[512];
1354
1355 field = objc_is_ivar (datum, component, &class_name);
1356 if (!field)
1357 return NULL_TREE;
1358
1359 /* This routine only handles non-bitfield fields */
1360 /* DECL_INITIAL macro is set to width of bitfield and can be relied
1361 on to check for bitfield ivars. Note that I cannot rely on
1362 DECL_BIT_FIELD macro because it is only set when the whole struct
1363 is seen (at finish_struct) and not when the ivar chain is
1364 built. */
1365 if (DECL_INITIAL (field))
1366 return NULL_TREE;
1367
1368 create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field);
1369
1370 offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1371
1372 ftype = TREE_TYPE (field);
1373
1374 /* (char*)datum */
1375 expr = build_c_cast (input_location,
1376 string_type_node, build_fold_addr_expr (datum));
1377
1378 /* (char*)datum + offset */
1379 expr = fold_build_pointer_plus_loc (input_location, expr, offset);
1380
1381 /* (ftype*)((char*)datum + offset) */
1382 expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1383
1384 /* Finally: *(ftype*)((char*)datum + offset) */
1385 ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1386
1387 /* We must set type of the resulting expression to be the same as
1388 the field type. This is because, build_indirect_ref (...)
1389 rebuilds the type which may result in lost information; as in the
1390 case of protocol-qualified types (id <protocol> ). */
1391 TREE_TYPE (ref) = ftype;
1392
1393 if (TREE_READONLY (datum) || TREE_READONLY (field))
1394 TREE_READONLY (ref) = 1;
1395
1396 if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1397 TREE_THIS_VOLATILE (ref) = 1;
1398
1399 if (TREE_DEPRECATED (field))
1400 warn_deprecated_use (field, NULL_TREE);
1401
1402 return ref;
1403 }
1404
1405 /* IVAR refs are made via an externally referenceable offset and built
1406 on the fly. That is, unless they refer to (private) fields in the
1407 class structure. */
1408 static tree
1409 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1410 tree base, tree id)
1411 {
1412 tree ivar;
1413 if ((ivar = objc_v2_build_ivar_ref (base, id)))
1414 return ivar;
1415 return objc_build_component_ref (base, id);
1416 }
1417
1418 /* [super ...] references are listed here (and built into a table at
1419 meta -data emit time). */
1420 static tree
1421 build_v2_superclass_ref_decl (tree ident, bool inst)
1422 {
1423 tree decl;
1424 char buf[BUFSIZE];
1425
1426 snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1427 IDENTIFIER_POINTER (ident));
1428 decl = start_var_decl (objc_class_type, buf);
1429 OBJCMETA (decl, objc_meta, meta_superclass_ref);
1430 return decl;
1431 }
1432
1433 static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs;
1434 static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs;
1435
1436 static tree
1437 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1438 struct imp_entry *imp, bool inst_meth)
1439 {
1440 tree decl;
1441 ident_data_tuple e;
1442 tree id = CLASS_NAME (imp->imp_context);
1443 vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs
1444 : metaclass_super_refs;
1445
1446 if (list)
1447 {
1448 int count;
1449 ident_data_tuple *ref;
1450 FOR_EACH_VEC_ELT (*list, count, ref)
1451 {
1452 if (ref->ident == id)
1453 {
1454 if (!ref->data)
1455 ref->data = build_v2_superclass_ref_decl (id, inst_meth);
1456 return ref->data;
1457 }
1458 }
1459 }
1460 else
1461 {
1462 /* Somewhat arbitrary initial provision. */
1463 if (inst_meth)
1464 {
1465 vec_alloc (class_super_refs, 16);
1466 list = class_super_refs;
1467 }
1468 else
1469 {
1470 vec_alloc (metaclass_super_refs, 16);
1471 list = metaclass_super_refs;
1472 }
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 (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 && vec_safe_length (classrefs))
1526 {
1527 int count;
1528 ident_data_tuple *ref;
1529 /* The receiver is a variable created by build_class_reference_decl. */
1530 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1531 if (ref->data == receiver)
1532 return ref->ident;
1533 }
1534 return NULL_TREE;
1535 }
1536
1537 /* Assign all arguments in VALUES which have side-effect to a temporary
1538 and replaced that argument in VALUES list with the temporary. The
1539 arguments will be passed to a function with FNTYPE. */
1540
1541 static tree
1542 objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1543 {
1544 tree valtail;
1545 function_args_iterator iter;
1546
1547 /* Skip over receiver and the &_msf_ref types. */
1548 function_args_iter_init (&iter, fntype);
1549 function_args_iter_next (&iter);
1550 function_args_iter_next (&iter);
1551
1552 for (valtail = values; valtail;
1553 valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
1554 {
1555 tree value = TREE_VALUE (valtail);
1556 tree type = function_args_iter_cond (&iter);
1557 if (type == NULL_TREE)
1558 break;
1559 if (!TREE_SIDE_EFFECTS (value))
1560 continue;
1561 /* To prevent re-evaluation. */
1562 value = save_expr (value);
1563 add_stmt (value);
1564 TREE_VALUE (valtail) = value;
1565 }
1566 return values;
1567 }
1568
1569 /* Build the new abi's messaging library call. It looks like:
1570 (*_msg.messenger) (receiver, &_msg, ...) */
1571
1572 static tree
1573 build_v2_build_objc_method_call (int super_flag, tree method_prototype,
1574 tree lookup_object, tree selector,
1575 tree method_params,
1576 bool check_for_nil)
1577 {
1578 tree ret_val;
1579 tree sender, rcv_p, t;
1580 tree ret_type
1581 = (method_prototype
1582 ? TREE_VALUE (TREE_TYPE (method_prototype))
1583 : objc_object_type);
1584 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1585 METHOD_REF, super_flag);
1586 tree sender_cast;
1587
1588 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1589 ftype = build_type_attribute_variant (
1590 ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1591
1592 sender_cast = build_pointer_type (ftype);
1593
1594 if (check_for_nil)
1595 method_params = objc_copy_to_temp_side_effect_params (ftype,
1596 method_params);
1597
1598 /* Get &message_ref_t.messenger. */
1599 sender = build_c_cast (input_location,
1600 build_pointer_type (super_flag
1601 ? objc_v2_super_imp_type
1602 : objc_v2_imp_type),
1603 selector);
1604
1605 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1606
1607 rcv_p = (super_flag ? objc_super_type : objc_object_type);
1608
1609 lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1610
1611 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1612 lookup_object = save_expr (lookup_object);
1613
1614 method_params = tree_cons (NULL_TREE, lookup_object,
1615 tree_cons (NULL_TREE, selector,
1616 method_params));
1617 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
1618 ret_val = build_function_call (input_location, t, method_params);
1619 if (check_for_nil)
1620 {
1621 /* receiver != nil ? ret_val : 0 */
1622 tree ftree;
1623 tree ifexp;
1624
1625 if (TREE_CODE (ret_type) == RECORD_TYPE
1626 || TREE_CODE (ret_type) == UNION_TYPE)
1627 {
1628 vec<constructor_elt, va_gc> *rtt = NULL;
1629 /* ??? CHECKME. hmmm..... think we need something more
1630 here. */
1631 CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE);
1632 ftree = objc_build_constructor (ret_type, rtt);
1633 }
1634 else
1635 ftree = fold_convert (ret_type, integer_zero_node);
1636
1637 ifexp = build_binary_op (input_location, NE_EXPR,
1638 lookup_object,
1639 fold_convert (rcv_p, integer_zero_node), 1);
1640
1641 #ifdef OBJCPLUS
1642 ret_val = build_conditional_expr (input_location,
1643 ifexp, ret_val, ftree,
1644 tf_warning_or_error);
1645 #else
1646 /* ??? CHECKME. */
1647 ret_val = build_conditional_expr (input_location,
1648 ifexp, 1,
1649 ret_val, NULL_TREE,
1650 ftree, NULL_TREE);
1651 #endif
1652 }
1653 return ret_val;
1654 }
1655
1656 static tree
1657 next_runtime_abi_02_build_objc_method_call (location_t loc,
1658 tree method_prototype,
1659 tree receiver,
1660 tree rtype,
1661 tree sel_name,
1662 tree method_params,
1663 int super)
1664 {
1665 tree ret_type, selector;
1666 tree message_func_decl;
1667 bool check_for_nil = flag_objc_nilcheck;
1668
1669 ret_type = method_prototype
1670 ? TREE_VALUE (TREE_TYPE (method_prototype))
1671 : objc_object_type;
1672
1673 /* Do we need to check for nil receivers ? */
1674 /* For now, message sent to classes need no nil check. In the
1675 future, class declaration marked as weak_import must be nil
1676 checked. */
1677 if (super
1678 || (TREE_CODE (receiver) == VAR_DECL
1679 && TREE_TYPE (receiver) == objc_class_type))
1680 check_for_nil = false;
1681
1682 if (!targetm.calls.struct_value_rtx (0, 0)
1683 && (TREE_CODE (ret_type) == RECORD_TYPE
1684 || TREE_CODE (ret_type) == UNION_TYPE)
1685 && targetm.calls.return_in_memory (ret_type, 0))
1686 {
1687 if (super)
1688 message_func_decl = umsg_id_super2_stret_fixup_decl;
1689 else
1690 message_func_decl = objc_is_id (rtype)
1691 ? umsg_id_stret_fixup_decl
1692 : umsg_stret_fixup_decl;
1693 }
1694 else
1695 {
1696 if (super)
1697 message_func_decl = umsg_id_super2_fixup_decl;
1698 else
1699 message_func_decl = objc_is_id (rtype)
1700 ? umsg_id_fixup_decl
1701 : umsg_fixup_decl;
1702 }
1703
1704 selector = build_v2_selector_messenger_reference (sel_name,
1705 message_func_decl);
1706
1707 /* selector = &_msg; */
1708 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1709
1710 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1711 : objc_v2_selector_type),
1712 selector);
1713
1714 /* (*_msg.messenger) (receiver, &_msg, ...); */
1715 return build_v2_build_objc_method_call (super, method_prototype,
1716 receiver, selector,
1717 method_params, check_for_nil);
1718 }
1719
1720 /* NOTE --- Constant String Class Stuff --- */
1721
1722 static bool
1723 next_runtime_abi_02_setup_const_string_class_decl (void)
1724 {
1725 if (!constant_string_global_id)
1726 {
1727 /* Hopefully, this should not represent a serious limitation. */
1728 char buf[BUFSIZE];
1729 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1730 constant_string_global_id = get_identifier (buf);
1731 }
1732
1733 string_class_decl = lookup_name (constant_string_global_id);
1734
1735 /* In OBJC2 abi, constant string class reference refers to class
1736 name for NSConstantString class. This declaration may not be
1737 available yet (in fact it is not in most cases). So, declare an
1738 extern OBJC_CLASS_$_NSConstantString in its place. */
1739 if (!string_class_decl)
1740 string_class_decl =
1741 create_extern_decl (objc_v2_class_template,
1742 IDENTIFIER_POINTER (constant_string_global_id));
1743
1744 return (string_class_decl != NULL_TREE);
1745 }
1746
1747 static tree
1748 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1749 int length)
1750 {
1751 tree constructor, fields, var;
1752 vec<constructor_elt, va_gc> *v = NULL;
1753
1754 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1755 fields = TYPE_FIELDS (internal_const_str_type);
1756 CONSTRUCTOR_APPEND_ELT (v, fields,
1757 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1758
1759 fields = DECL_CHAIN (fields);
1760 CONSTRUCTOR_APPEND_ELT (v, fields,
1761 build_unary_op (loc, ADDR_EXPR, string, 1));
1762
1763 /* ??? check if this should be long. */
1764 fields = DECL_CHAIN (fields);
1765 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1766 constructor = objc_build_constructor (internal_const_str_type, v);
1767
1768 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1769 DECL_INITIAL (var) = constructor;
1770 TREE_STATIC (var) = 1;
1771 DECL_CONTEXT (var) = NULL;
1772 OBJCMETA (var, objc_meta, meta_const_str);
1773 return var;
1774 }
1775
1776 /* NOTE --- NeXT V2 Metadata templates --- */
1777
1778 /* This routine builds the following type:
1779 struct _prop_t
1780 {
1781 const char * const name; // property name
1782 const char * const attributes; // comma-delimited, encoded,
1783 // property attributes
1784 };
1785 */
1786
1787 static tree
1788 build_v2_property_template (void)
1789 {
1790 tree prop_record;
1791 tree decls, *chain = NULL;
1792
1793 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1794 /* const char * name */
1795 decls = add_field_decl (string_type_node, "name", &chain);
1796
1797 /* const char * attribute */
1798 add_field_decl (string_type_node, "attribute", &chain);
1799
1800 objc_finish_struct (prop_record, decls);
1801 return prop_record;
1802 }
1803
1804 /* struct ivar_t
1805 {
1806 unsigned long int *offset;
1807 char *name;
1808 char *type;
1809 uint32_t alignment;
1810 uint32_t size;
1811 };
1812 */
1813
1814 static tree
1815 build_v2_ivar_t_template (void)
1816 {
1817 tree objc_ivar_id, objc_ivar_record;
1818 tree decls, *chain = NULL;
1819
1820 objc_ivar_id = get_identifier ("_ivar_t");
1821 objc_ivar_record = objc_start_struct (objc_ivar_id);
1822
1823 /* unsigned long int *offset; */
1824 decls = add_field_decl (build_pointer_type
1825 (TREE_TYPE (size_zero_node)), "offset", &chain);
1826
1827 /* char *name; */
1828 add_field_decl (string_type_node, "name", &chain);
1829
1830 /* char *type; */
1831 add_field_decl (string_type_node, "type", &chain);
1832
1833 /* uint32_t alignment; */
1834 add_field_decl (integer_type_node, "alignment", &chain);
1835
1836 /* uint32_t size; */
1837 add_field_decl (integer_type_node, "size", &chain);
1838
1839 objc_finish_struct (objc_ivar_record, decls);
1840 return objc_ivar_record;
1841 }
1842
1843 static void
1844 build_metadata_templates (void)
1845 {
1846
1847 if (!objc_method_template)
1848 objc_method_template = build_method_template ();
1849
1850 if (!objc_v2_property_template)
1851 objc_v2_property_template = build_v2_property_template ();
1852
1853 if (!objc_v2_ivar_template)
1854 objc_v2_ivar_template = build_v2_ivar_t_template ();
1855
1856 }
1857
1858 /* NOTE --- Output NeXT V2 Metadata --- */
1859
1860 /* Routine builds name of Interface's main meta-data of type class_t. */
1861
1862 static char *
1863 objc_build_internal_classname (tree ident, bool metaclass)
1864 {
1865 static char string[512];
1866 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
1867 : "OBJC_CLASS_$",
1868 IDENTIFIER_POINTER (ident));
1869 return string;
1870 }
1871
1872 /* Build the name for object of type struct class_ro_t */
1873
1874 static const char *
1875 newabi_append_ro (const char *name)
1876 {
1877 const char *dollar;
1878 char *p;
1879 static char string[BUFSIZE];
1880 dollar = strchr (name, '$');
1881 gcc_assert (dollar);
1882 p = string;
1883 *p = '_'; p++;
1884 strncpy (p, name, (int)(dollar - name));
1885 p += (int)(dollar - name);
1886 sprintf (p, "RO_%s", dollar);
1887 return string;
1888 }
1889
1890 /* Build the struct message_ref_t msg =
1891 {objc_msgSend_fixup_xxx, @selector(func)}
1892 table. */
1893
1894 static
1895 void build_v2_message_ref_translation_table (void)
1896 {
1897 int count;
1898 msgref_entry *ref;
1899
1900 if (!vec_safe_length (msgrefs))
1901 return;
1902
1903 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1904 {
1905 vec<constructor_elt, va_gc> *initializer;
1906 tree expr, constructor;
1907 tree struct_type = TREE_TYPE (ref->refdecl);
1908 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
1909
1910 initializer = NULL;
1911 /* First 'IMP messenger' field... */
1912 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
1913 expr = convert (objc_v2_imp_type, expr);
1914 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1915
1916 /* ... then 'SEL name' field. */
1917 expr = build_selector (ref->selname);
1918 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1919 constructor = objc_build_constructor (struct_type, initializer);
1920 finish_var_decl (ref->refdecl, constructor);
1921 }
1922 }
1923
1924 /* Build decl = initializer; for each externally visible class
1925 reference. */
1926
1927 static void
1928 build_v2_classrefs_table (void)
1929 {
1930 int count;
1931 ident_data_tuple *ref;
1932
1933 if (!vec_safe_length (classrefs))
1934 return;
1935
1936 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1937 {
1938 tree expr = ref->ident;
1939 tree decl = ref->data;
1940 /* Interface with no implementation and yet one of its messages
1941 has been used. Need to generate a full address-of tree for it
1942 here. */
1943 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1944 {
1945 const char *name = objc_build_internal_classname (expr, false);
1946 expr = create_extern_decl (objc_v2_class_template, name);
1947 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1948 }
1949 /* The runtime wants this, even if it appears unused, so we must force the
1950 output.
1951 DECL_PRESERVE_P (decl) = 1; */
1952 finish_var_decl (decl, expr);
1953 }
1954 }
1955
1956 /* Build decl = initializer; for each externally visible super class
1957 reference. */
1958
1959 static void
1960 build_v2_super_classrefs_table (bool metaclass)
1961 {
1962 int count;
1963 ident_data_tuple *ref;
1964 vec<ident_data_tuple, va_gc> *list = metaclass ? metaclass_super_refs
1965 : class_super_refs;
1966
1967 if (!vec_safe_length (list))
1968 return;
1969
1970 FOR_EACH_VEC_ELT (*list, count, ref)
1971 {
1972 tree expr = ref->ident;
1973 tree decl = ref->data;
1974 /* Interface with no implementation and yet one of its messages
1975 has been used. Need to generate a full address-of tree for it
1976 here. */
1977 if (TREE_CODE (expr) == IDENTIFIER_NODE)
1978 {
1979 const char * name = objc_build_internal_classname (expr, metaclass);
1980 expr = create_extern_decl (objc_v2_class_template, name);
1981 expr = convert (objc_class_type, build_fold_addr_expr (expr));
1982 }
1983 finish_var_decl (decl, expr);
1984 }
1985 }
1986
1987 /* Add the global class meta-data declaration to the list which later
1988 on ends up in the __class_list section. */
1989
1990 static GTY(()) vec<tree, va_gc> *class_list;
1991
1992 static void
1993 objc_v2_add_to_class_list (tree global_class_decl)
1994 {
1995 vec_safe_push (class_list, global_class_decl);
1996 }
1997
1998 static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
1999
2000 /* Add the global class meta-data declaration to the list which later
2001 on ends up in the __nonlazy_class section. */
2002
2003 static void
2004 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2005 {
2006 vec_safe_push (nonlazy_class_list, global_class_decl);
2007 }
2008
2009 static GTY(()) vec<tree, va_gc> *category_list;
2010
2011 /* Add the category meta-data declaration to the list which later on
2012 ends up in the __nonlazy_category section. */
2013
2014 static void
2015 objc_v2_add_to_category_list (tree decl)
2016 {
2017 vec_safe_push (category_list, decl);
2018 }
2019
2020 static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
2021
2022 /* Add the category meta-data declaration to the list which later on
2023 ends up in the __category_list section. */
2024
2025 static void
2026 objc_v2_add_to_nonlazy_category_list (tree decl)
2027 {
2028 vec_safe_push (nonlazy_category_list, decl);
2029 }
2030
2031 static bool
2032 has_load_impl (tree clsmeth)
2033 {
2034 while (clsmeth)
2035 {
2036 tree id = METHOD_SEL_NAME (clsmeth);
2037 if (IDENTIFIER_LENGTH (id) == 4
2038 && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
2039 return true;
2040 clsmeth = DECL_CHAIN (clsmeth);
2041 }
2042
2043 return false;
2044 }
2045
2046 /* Build a __{class,category}_list section table containing address of
2047 all @implemented {class,category} meta-data. */
2048
2049 static void
2050 build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
2051 {
2052 int count=0;
2053 tree type, decl, expr;
2054 vec<constructor_elt, va_gc> *initlist = NULL;
2055
2056 if (!vec_safe_length (src))
2057 return;
2058
2059 FOR_EACH_VEC_ELT (*src, count, decl)
2060 {
2061 #ifndef OBJCPLUS
2062 tree purpose = build_int_cst (NULL_TREE, count);
2063 #else
2064 tree purpose = NULL_TREE;
2065 #endif
2066 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2067 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2068 }
2069 gcc_assert (count > 0);
2070 type = build_array_type (objc_class_type,
2071 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2072 decl = start_var_decl (type, nam);
2073 /* The runtime wants this, even if it appears unused, so we must
2074 force the output. */
2075 DECL_PRESERVE_P (decl) = 1;
2076 expr = objc_build_constructor (type, initlist);
2077 OBJCMETA (decl, objc_meta, attr);
2078 finish_var_decl (decl, expr);
2079 }
2080
2081 /* Build decl = initializer; for each protocol referenced in
2082 @protocol(MyProt) expression. Refs as built in the entry section
2083 above. */
2084
2085 static void
2086 build_v2_protocol_list_translation_table (void)
2087 {
2088 int count;
2089 prot_list_entry *ref;
2090
2091 if (!protrefs)
2092 return;
2093
2094 FOR_EACH_VEC_ELT (*protrefs, count, ref)
2095 {
2096 char buf[BUFSIZE];
2097 tree expr;
2098 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2099 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2100 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2101 expr = start_var_decl (objc_v2_protocol_template, buf);
2102 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2103 finish_var_decl (ref->refdecl, expr);
2104 }
2105 /* TODO: Maybe we could explicitly delete the vec. now? */
2106 }
2107
2108 static GTY (()) vec<prot_list_entry, va_gc> *protlist;
2109
2110 /* Add the local protocol meta-data declaration to the list which
2111 later on ends up in the __protocol_list section. */
2112
2113 static void
2114 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2115 {
2116 prot_list_entry e;
2117 if (!protlist)
2118 /* Arbitrary init count. */
2119 vec_alloc (protlist, 32);
2120 e.id = protocol_interface_decl;
2121 e.refdecl = protocol_decl;
2122 vec_safe_push (protlist, e);
2123 }
2124
2125 /* Build the __protocol_list section table containing address of all
2126 generate protocol_t meta-data. */
2127
2128 static void
2129 build_v2_protocol_list_address_table (void)
2130 {
2131 int count;
2132 prot_list_entry *ref;
2133 if (!vec_safe_length (protlist))
2134 return;
2135
2136 FOR_EACH_VEC_ELT (*protlist, count, ref)
2137 {
2138 tree decl, expr;
2139 char buf[BUFSIZE];
2140 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2141 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2142 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2143 decl = create_global_decl (objc_protocol_type, buf);
2144 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2145 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2146 finish_var_decl (decl, expr);
2147 }
2148
2149 /* TODO: delete the vec. */
2150 /* TODO: upgrade to the clang/llvm hidden version. */
2151 }
2152
2153 /* This routine declares a variable to hold meta data for 'struct
2154 protocol_list_t'. */
2155
2156 static tree
2157 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2158 {
2159 tree refs_decl, lproto, e, plist, ptempl_p_t;
2160 int size = 0;
2161 vec<constructor_elt, va_gc> *initlist = NULL;
2162 char buf[BUFSIZE];
2163
2164 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2165 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2166 plist = CLASS_PROTOCOL_LIST (i_or_p);
2167 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2168 plist = PROTOCOL_LIST (i_or_p);
2169 else
2170 gcc_unreachable ();
2171
2172 /* Compute size. */
2173 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2174 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2175 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2176 size++;
2177
2178 /* Build initializer. */
2179
2180 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2181 e = build_int_cst (ptempl_p_t, size);
2182 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2183
2184 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2185 {
2186 tree pval = TREE_VALUE (lproto);
2187
2188 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2189 && PROTOCOL_FORWARD_DECL (pval))
2190 {
2191 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2192 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2193 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2194 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2195 }
2196 }
2197
2198 /* static struct protocol_list_t *list[size]; */
2199
2200 switch (TREE_CODE (i_or_p))
2201 {
2202 case PROTOCOL_INTERFACE_TYPE:
2203 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2204 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2205 break;
2206 case CLASS_INTERFACE_TYPE:
2207 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2208 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2209 break;
2210 case CATEGORY_INTERFACE_TYPE:
2211 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2212 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2213 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2214 break;
2215 default:
2216 gcc_unreachable ();
2217 }
2218
2219 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2220 buf);
2221 /* ObjC2 puts all these in the base section. */
2222 OBJCMETA (refs_decl, objc_meta, meta_base);
2223 DECL_PRESERVE_P (refs_decl) = 1;
2224 finish_var_decl (refs_decl,
2225 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2226 return refs_decl;
2227 }
2228
2229 /* This routine builds one 'struct method_t' initializer list. Note
2230 that the old ABI is supposed to build 'struct objc_method' which
2231 has 3 fields, but it does not build the initialization expression
2232 for 'method_imp' which for protocols is NULL any way. To be
2233 consistent with declaration of 'struct method_t', in the new ABI we
2234 set the method_t.imp to NULL. */
2235
2236 static tree
2237 build_v2_descriptor_table_initializer (tree type, tree entries)
2238 {
2239 vec<constructor_elt, va_gc> *initlist = NULL;
2240 do
2241 {
2242 vec<constructor_elt, va_gc> *eltlist = NULL;
2243 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2244 build_selector (METHOD_SEL_NAME (entries)));
2245 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2246 add_objc_string (METHOD_ENCODING (entries),
2247 meth_var_types));
2248 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2249
2250 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2251 objc_build_constructor (type, eltlist));
2252 entries = TREE_CHAIN (entries);
2253 }
2254 while (entries);
2255
2256 return objc_build_constructor (build_array_type (type, 0), initlist);
2257 }
2258
2259 /* struct method_list_t
2260 {
2261 uint32_t entsize;
2262 uint32_t method_count;
2263 struct objc_method method_list[method_count];
2264 }; */
2265
2266 static tree
2267 build_v2_method_list_template (tree list_type, int size)
2268 {
2269 tree method_list_t_record;
2270 tree array_type, decls, *chain = NULL;
2271
2272 method_list_t_record = objc_start_struct (NULL_TREE);
2273
2274 /* uint32_t const entsize; */
2275 decls = add_field_decl (integer_type_node, "entsize", &chain);
2276
2277 /* int method_count; */
2278 add_field_decl (integer_type_node, "method_count", &chain);
2279
2280 /* struct objc_method method_list[]; */
2281 array_type = build_sized_array_type (list_type, size);
2282 add_field_decl (array_type, "method_list", &chain);
2283
2284 objc_finish_struct (method_list_t_record, decls);
2285 return method_list_t_record;
2286 }
2287
2288 /* Note, as above that we are building to the objc_method_template
2289 which has the *imp field. ABI0/1 build with
2290 objc_method_prototype_template which is missing this field. */
2291 static tree
2292 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2293 const char *prefix, tree attr)
2294 {
2295 tree method_list_template, initlist, decl, methods;
2296 int size, entsize;
2297 vec<constructor_elt, va_gc> *v = NULL;
2298 char buf[BUFSIZE];
2299
2300 if (!chain || !prefix)
2301 return NULL_TREE;
2302
2303 methods = chain;
2304 size = 0;
2305 while (methods)
2306 {
2307 if (! METHOD_ENCODING (methods))
2308 METHOD_ENCODING (methods) = encode_method_prototype (methods);
2309 methods = TREE_CHAIN (methods);
2310 size++;
2311 }
2312
2313 gcc_assert (size);
2314 method_list_template = build_v2_method_list_template (objc_method_template,
2315 size);
2316 snprintf (buf, BUFSIZE, "%s_%s", prefix,
2317 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2318
2319 decl = start_var_decl (method_list_template, buf);
2320
2321 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2322 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2323 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2324 initlist =
2325 build_v2_descriptor_table_initializer (objc_method_template,
2326 chain);
2327 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2328 /* Get into the right section. */
2329 OBJCMETA (decl, objc_meta, attr);
2330 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2331 return decl;
2332 }
2333
2334 /* This routine builds the initializer list to initialize the 'struct
2335 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2336
2337 static tree
2338 build_v2_property_table_initializer (tree type, tree context)
2339 {
2340 tree x;
2341 vec<constructor_elt, va_gc> *inits = NULL;
2342 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2343 x = CLASS_PROPERTY_DECL (context);
2344 else
2345 x = IMPL_PROPERTY_DECL (context);
2346
2347 for (; x; x = TREE_CHAIN (x))
2348 {
2349 vec<constructor_elt, va_gc> *elemlist = NULL;
2350 /* NOTE! sections where property name/attribute go MUST change
2351 later. */
2352 tree attribute, name_ident = PROPERTY_NAME (x);
2353
2354 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2355 add_objc_string (name_ident, prop_names_attr));
2356
2357 attribute = objc_v2_encode_prop_attr (x);
2358 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2359 add_objc_string (attribute, prop_names_attr));
2360
2361 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2362 objc_build_constructor (type, elemlist));
2363 }
2364
2365 return objc_build_constructor (build_array_type (type, 0),inits);
2366 }
2367
2368 /* This routine builds the following type:
2369 struct _prop_list_t
2370 {
2371 uint32_t entsize; // sizeof (struct _prop_t)
2372 uint32_t prop_count;
2373 struct _prop_t prop_list [prop_count];
2374 }
2375 */
2376
2377 static tree
2378 build_v2_property_list_template (tree list_type, int size)
2379 {
2380 tree property_list_t_record;
2381 tree array_type, decls, *chain = NULL;
2382
2383 /* anonymous. */
2384 property_list_t_record = objc_start_struct (NULL_TREE);
2385
2386 /* uint32_t const entsize; */
2387 decls = add_field_decl (integer_type_node, "entsize", &chain);
2388
2389 /* int prop_count; */
2390 add_field_decl (integer_type_node, "prop_count", &chain);
2391
2392 /* struct _prop_t prop_list[]; */
2393 array_type = build_sized_array_type (list_type, size);
2394 add_field_decl (array_type, "prop_list", &chain);
2395
2396 objc_finish_struct (property_list_t_record, decls);
2397 return property_list_t_record;
2398 }
2399
2400 /* Top-level routine to generate property tables for each
2401 implementation. */
2402
2403 static tree
2404 generate_v2_property_table (tree context, tree klass_ctxt)
2405 {
2406 tree x, decl, initlist, property_list_template;
2407 bool is_proto = false;
2408 vec<constructor_elt, va_gc> *inits = NULL;
2409 int init_val, size = 0;
2410 char buf[BUFSIZE];
2411
2412 if (context)
2413 {
2414 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2415 x = CLASS_PROPERTY_DECL (context);
2416 is_proto = true;
2417 }
2418 else
2419 x = IMPL_PROPERTY_DECL (klass_ctxt);
2420
2421 for (; x; x = TREE_CHAIN (x))
2422 size++;
2423
2424 if (size == 0)
2425 return NULL_TREE;
2426
2427 property_list_template =
2428 build_v2_property_list_template (objc_v2_property_template,
2429 size);
2430
2431 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2432 is_proto ? context
2433 : klass_ctxt);
2434
2435 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2436 if (is_proto)
2437 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2438 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2439 else
2440 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2441 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2442
2443 decl = start_var_decl (property_list_template, buf);
2444
2445 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2446 build_int_cst (NULL_TREE, init_val));
2447 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2448 build_int_cst (NULL_TREE, size));
2449 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2450
2451 OBJCMETA (decl, objc_meta, meta_base);
2452 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2453 return decl;
2454 }
2455
2456 static tree
2457 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2458 tree inst_methods, tree class_methods,
2459 tree opt_ins_meth, tree opt_cls_meth,
2460 tree property_list)
2461 {
2462 tree expr, ttyp;
2463 location_t loc;
2464 vec<constructor_elt, va_gc> *inits = NULL;
2465
2466 /* TODO: find a better representation of location from the inputs. */
2467 loc = UNKNOWN_LOCATION;
2468
2469 /* This is NULL for the new ABI. */
2470 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2471 convert (objc_object_type, null_pointer_node));
2472
2473 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2474 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2475
2476 ttyp = objc_method_proto_list_ptr;
2477 if (inst_methods)
2478 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2479 else
2480 expr = convert (ttyp, null_pointer_node);
2481 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2482
2483 if (class_methods)
2484 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2485 else
2486 expr = convert (ttyp, null_pointer_node);
2487 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2488
2489 if (opt_ins_meth)
2490 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2491 else
2492 expr = convert (ttyp, null_pointer_node);
2493 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2494
2495 if (opt_cls_meth)
2496 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2497 else
2498 expr = convert (ttyp, null_pointer_node);
2499 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2500
2501 ttyp = objc_prop_list_ptr;
2502 if (property_list)
2503 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2504 else
2505 expr = convert (ttyp, null_pointer_node);
2506 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2507
2508 /* const uint32_t size; = sizeof(struct protocol_t) */
2509 expr = build_int_cst (integer_type_node,
2510 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2511 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2512 /* const uint32_t flags; = 0 */
2513 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2514
2515 return objc_build_constructor (type, inits);
2516 }
2517
2518 /* Main routine to build all meta data for all protocols used in a
2519 translation unit. */
2520
2521 static void
2522 generate_v2_protocols (void)
2523 {
2524 tree p ;
2525 bool some = false;
2526
2527 if (!protocol_chain)
2528 return ;
2529
2530 /* If a protocol was directly referenced, pull in indirect
2531 references. */
2532 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2533 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2534 generate_protocol_references (PROTOCOL_LIST (p));
2535
2536 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2537 {
2538 location_t loc;
2539 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2540 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2541
2542 /* If protocol wasn't referenced, don't generate any code. */
2543 decl = PROTOCOL_FORWARD_DECL (p);
2544
2545 if (!decl)
2546 continue;
2547
2548 loc = DECL_SOURCE_LOCATION (decl);
2549 some = true;
2550
2551 inst_meth =
2552 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2553 "_OBJC_ProtocolInstanceMethods",
2554 meta_proto_nst_meth);
2555
2556 class_meth =
2557 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2558 "_OBJC_ProtocolClassMethods",
2559 meta_proto_cls_meth);
2560
2561 opt_inst_meth =
2562 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2563 "_OBJC_OptProtocolInstMethods",
2564 meta_proto_nst_meth);
2565
2566 opt_class_meth =
2567 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2568 "_OBJC_OptProtocolClassMethods",
2569 meta_proto_cls_meth);
2570
2571 if (PROTOCOL_LIST (p))
2572 refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2573 else
2574 refs_decl = 0;
2575
2576 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2577 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2578
2579 if (refs_decl)
2580 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2581 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2582 else
2583 refs_expr = build_int_cst (NULL_TREE, 0);
2584
2585 props = generate_v2_property_table (p, NULL_TREE);
2586
2587 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2588 protocol_name_expr, refs_expr,
2589 inst_meth, class_meth,
2590 opt_inst_meth, opt_class_meth,
2591 props);
2592 finish_var_decl (decl, initlist);
2593 objc_add_to_protocol_list (p, decl);
2594 }
2595
2596 if (some)
2597 {
2598 /* Make sure we get the Protocol class linked in - reference
2599 it... */
2600 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2601 /* ... but since we don't specifically use the reference... we
2602 need to force it. */
2603 DECL_PRESERVE_P (p) = 1;
2604 }
2605 }
2606
2607 static tree
2608 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2609 {
2610 tree decl, method_list_template, initlist;
2611 vec<constructor_elt, va_gc> *v = NULL;
2612 int size, init_val;
2613
2614 if (!chain || !name || !(size = list_length (chain)))
2615 return NULL_TREE;
2616
2617 method_list_template
2618 = build_v2_method_list_template (objc_method_template, size);
2619 initlist
2620 = build_dispatch_table_initializer (objc_method_template, chain);
2621
2622 decl = start_var_decl (method_list_template, name);
2623
2624 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2625 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2626 build_int_cst (integer_type_node, init_val));
2627 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2628 build_int_cst (integer_type_node, size));
2629 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2630
2631 OBJCMETA (decl, objc_meta, attr);
2632 finish_var_decl (decl,
2633 objc_build_constructor (TREE_TYPE (decl), v));
2634 return decl;
2635 }
2636
2637 /* Init a category. */
2638 static tree
2639 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2640 tree inst_methods, tree class_methods,
2641 tree protocol_list, tree property_list,
2642 location_t loc)
2643 {
2644 tree expr, ltyp;
2645 vec<constructor_elt, va_gc> *v = NULL;
2646
2647 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2648 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2649
2650 ltyp = objc_method_list_ptr;
2651 if (inst_methods)
2652 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2653 else
2654 expr = convert (ltyp, null_pointer_node);
2655 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2656
2657 if (class_methods)
2658 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2659 else
2660 expr = convert (ltyp, null_pointer_node);
2661 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2662
2663 /* protocol_list = */
2664 ltyp = build_pointer_type (objc_v2_protocol_template);
2665 if (protocol_list)
2666 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2667 else
2668 expr = convert (ltyp, null_pointer_node);
2669 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2670
2671 ltyp = objc_prop_list_ptr;
2672 if (property_list)
2673 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2674 else
2675 expr = convert (ltyp, null_pointer_node);
2676 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2677
2678 return objc_build_constructor (type, v);
2679 }
2680
2681 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2682
2683 static void
2684 generate_v2_category (struct imp_entry *impent)
2685 {
2686 tree initlist, cat_name_expr, class_name_expr;
2687 tree protocol_decl, category, props, t;
2688 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2689 tree cat = impent->imp_context;
2690 tree cat_decl = impent->class_decl;
2691 location_t loc;
2692 char buf[BUFSIZE];
2693
2694 loc = DECL_SOURCE_LOCATION (cat_decl);
2695
2696 /* ??? not sure this is really necessary, the following references should
2697 force appropriate linkage linkage...
2698 -- but ... ensure a reference to the class... */
2699 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2700 /* ... which we ignore so force it out.. */
2701 DECL_PRESERVE_P (t) = 1;
2702
2703 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2704 class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2705 class_name_expr = build_fold_addr_expr (class_name_expr);
2706
2707 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2708 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2709
2710 if (category && CLASS_PROTOCOL_LIST (category))
2711 {
2712 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2713 protocol_decl = generate_v2_protocol_list (category, cat);
2714 }
2715 else
2716 protocol_decl = NULL_TREE;
2717
2718 /* decl = update_var_decl(impent->class_decl); */
2719
2720 props = generate_v2_property_table (NULL_TREE, cat);
2721
2722 if (CLASS_NST_METHODS (cat))
2723 {
2724 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2725 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2726 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2727 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2728 meta_cati_meth);
2729 }
2730
2731 if (CLASS_CLS_METHODS (cat))
2732 {
2733 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2734 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2735 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2736 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2737 meta_catc_meth);
2738 }
2739
2740 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2741 cat_name_expr, class_name_expr,
2742 inst_methods, class_methods,
2743 protocol_decl, props, loc);
2744
2745 finish_var_decl (cat_decl, initlist);
2746 impent->class_decl = cat_decl;
2747
2748 /* Add to list of pointers in __category_list section. */
2749 objc_v2_add_to_category_list (cat_decl);
2750 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2751 objc_v2_add_to_nonlazy_category_list (cat_decl);
2752 }
2753
2754 /* This routine declares a variable to hold the offset for ivar
2755 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
2756
2757 typedef struct GTY(()) ivarref_entry
2758 {
2759 tree decl;
2760 tree offset;
2761 } ivarref_entry;
2762
2763 static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
2764
2765 static tree
2766 ivar_offset_ref (tree class_name, tree field_decl)
2767 {
2768 tree decl, field_decl_id;
2769 ivarref_entry e;
2770 bool global_var;
2771 char buf[512];
2772
2773 create_ivar_offset_name (buf, class_name, field_decl);
2774 field_decl_id = get_identifier (buf);
2775
2776 if (ivar_offset_refs)
2777 {
2778 int count;
2779 ivarref_entry *ref;
2780 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
2781 if (DECL_NAME (ref->decl) == field_decl_id)
2782 return ref->decl;
2783 }
2784 else
2785 /* Somewhat arbitrary initial provision. */
2786 vec_alloc (ivar_offset_refs, 32);
2787
2788 /* We come here if we don't find a match or at the start. */
2789 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
2790 if (global_var)
2791 decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
2792 else
2793 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
2794
2795 /* Make sure it ends up in an ObjC section. */
2796 OBJCMETA (decl, objc_meta, meta_base);
2797
2798 e.decl = decl;
2799 e.offset = byte_position (field_decl);
2800 vec_safe_push (ivar_offset_refs, e);
2801 return decl;
2802 }
2803
2804 /* This routine builds initializer-list needed to initialize 'struct
2805 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
2806 'struct ivar_t' and FIELD_DECL is list of ivars for the target
2807 class. */
2808
2809 static tree
2810 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
2811 {
2812 vec<constructor_elt, va_gc> *inits = NULL;
2813
2814 do
2815 {
2816 vec<constructor_elt, va_gc> *ivar = NULL;
2817 int val;
2818 tree id;
2819
2820 /* Unnamed bitfields are ignored. */
2821 if (!DECL_NAME (field_decl))
2822 {
2823 field_decl = DECL_CHAIN (field_decl);
2824 continue;
2825 }
2826
2827 /* Set offset. */
2828 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2829 build_unary_op (input_location,
2830 ADDR_EXPR,
2831 ivar_offset_ref (class_name,
2832 field_decl), 0));
2833
2834 /* Set name. */
2835 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2836 add_objc_string (DECL_NAME (field_decl),
2837 meth_var_names));
2838
2839 /* Set type. */
2840 id = add_objc_string (encode_field_decl (field_decl),
2841 meth_var_types);
2842 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
2843
2844 /* Set alignment. */
2845 val = DECL_ALIGN_UNIT (field_decl);
2846 val = exact_log2 (val);
2847 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2848 build_int_cst (integer_type_node, val));
2849
2850 /* Set size. */
2851 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
2852 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2853 build_int_cst (integer_type_node, val));
2854
2855 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2856 objc_build_constructor (type, ivar));
2857
2858 do
2859 field_decl = DECL_CHAIN (field_decl);
2860 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
2861 }
2862 while (field_decl);
2863
2864 return objc_build_constructor (build_array_type (type, 0), inits);
2865 }
2866
2867 /*
2868 struct ivar_list_t
2869 {
2870 uint32 entsize;
2871 uint32 count;
2872 struct iver_t list[count];
2873 };
2874 */
2875
2876 static tree
2877 build_v2_ivar_list_t_template (tree list_type, int size)
2878 {
2879 tree objc_ivar_list_record;
2880 tree decls, *chain = NULL;
2881
2882 /* Anonymous. */
2883 objc_ivar_list_record = objc_start_struct (NULL_TREE);
2884
2885 /* uint32 entsize; */
2886 decls = add_field_decl (integer_type_node, "entsize", &chain);
2887
2888 /* uint32 count; */
2889 add_field_decl (integer_type_node, "count", &chain);
2890
2891 /* struct objc_ivar ivar_list[]; */
2892 add_field_decl (build_sized_array_type (list_type, size),
2893 "list", &chain);
2894
2895 objc_finish_struct (objc_ivar_list_record, decls);
2896 return objc_ivar_list_record;
2897 }
2898
2899 /* This routine declares a static variable of type 'struct
2900 ivar_list_t' and initializes it. chain is the source of the data,
2901 name is the name for the var. attr is the meta-data section tag
2902 attribute. templ is the implementation template for the class. */
2903
2904 static tree
2905 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
2906 {
2907 tree decl, initlist, ivar_list_template;
2908 vec<constructor_elt, va_gc> *inits = NULL;
2909 int size, ivar_t_size;
2910
2911 if (!chain || !name || !(size = ivar_list_length (chain)))
2912 return NULL_TREE;
2913
2914 generating_instance_variables = 1;
2915 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
2916 size);
2917
2918 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
2919 objc_v2_ivar_template, chain);
2920 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
2921
2922 decl = start_var_decl (ivar_list_template, name);
2923 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2924 build_int_cst (integer_type_node, ivar_t_size));
2925 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2926 build_int_cst (integer_type_node, size));
2927 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2928 OBJCMETA (decl, objc_meta, attr);
2929 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2930 generating_instance_variables = 0;
2931 return decl;
2932 }
2933
2934 /* Routine to build initializer list to initialize objects of type
2935 struct class_t; */
2936
2937 static tree
2938 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
2939 tree ro, tree cache, tree vtable)
2940 {
2941 vec<constructor_elt, va_gc> *initlist = NULL;
2942
2943 /* isa */
2944 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
2945
2946 /* superclass */
2947 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
2948
2949 /* cache */
2950 if (cache)
2951 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
2952 else
2953 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2954
2955 /* vtable */
2956 if (vtable)
2957 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
2958 else
2959 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2960
2961 /* ro */
2962 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
2963
2964 return objc_build_constructor (type, initlist);
2965 }
2966
2967 /* Routine to build object of struct class_ro_t { ... }; */
2968
2969 static tree
2970 build_v2_class_ro_t_initializer (tree type, tree name,
2971 unsigned int flags, unsigned int instanceStart,
2972 unsigned int instanceSize,
2973 tree ivarLayout,
2974 tree baseMethods, tree baseProtocols,
2975 tree ivars, tree property_list)
2976 {
2977 tree expr, unsigned_char_star, ltyp;
2978 location_t loc;
2979 vec<constructor_elt, va_gc> *initlist = NULL;
2980
2981 /* TODO: fish out the real location from somewhere. */
2982 loc = UNKNOWN_LOCATION;
2983
2984 /* flags */
2985 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2986 build_int_cst (integer_type_node, flags));
2987
2988 /* instanceStart */
2989 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2990 build_int_cst (integer_type_node, instanceStart));
2991
2992 /* instanceSize */
2993 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2994 build_int_cst (integer_type_node, instanceSize));
2995
2996 /* This ABI is currently only used on m64 NeXT. We always
2997 explicitly declare the alignment padding. */
2998 /* reserved, pads alignment. */
2999 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3000 build_int_cst (integer_type_node, 0));
3001
3002 /* ivarLayout */
3003 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3004 if (ivarLayout)
3005 expr = ivarLayout;
3006 else
3007 expr = convert (unsigned_char_star, null_pointer_node);
3008 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3009
3010 /* name */
3011 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3012
3013 /* baseMethods */
3014 ltyp = objc_method_list_ptr;
3015 if (baseMethods)
3016 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3017 else
3018 expr = convert (ltyp, null_pointer_node);
3019 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3020
3021 /* baseProtocols */
3022 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3023 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3024 if (baseProtocols)
3025 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3026 else
3027 expr = convert (ltyp, null_pointer_node);
3028 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3029
3030 /* ivars */
3031 ltyp = objc_v2_ivar_list_ptr;
3032 if (ivars)
3033 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3034 else
3035 expr = convert (ltyp, null_pointer_node);
3036 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3037
3038 /* TODO: We don't yet have the weak/strong stuff... */
3039 /* weakIvarLayout */
3040 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3041 convert (unsigned_char_star, null_pointer_node));
3042
3043 /* property list */
3044 ltyp = objc_prop_list_ptr;
3045 if (property_list)
3046 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3047 else
3048 expr = convert (ltyp, null_pointer_node);
3049 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3050 return objc_build_constructor (type, initlist);
3051 }
3052
3053 static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
3054
3055 /* Record a name as needing a catcher. */
3056 static void
3057 objc_v2_add_to_ehtype_list (tree name)
3058 {
3059 ident_data_tuple e;
3060 if (ehtype_list)
3061 {
3062 int count = 0;
3063 ident_data_tuple *ref;
3064
3065 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3066 if (ref->ident == name)
3067 return; /* Already entered. */
3068 }
3069 else
3070 /* Arbitrary initial count. */
3071 vec_alloc (ehtype_list, 8);
3072
3073 /* Not found, or new list. */
3074 e.ident = name;
3075 e.data = NULL_TREE;
3076 vec_safe_push (ehtype_list, e);
3077 }
3078
3079 static void
3080 generate_v2_class_structs (struct imp_entry *impent)
3081 {
3082 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3083 tree field, firstIvar, chain;
3084 tree class_superclass_expr, metaclass_superclass_expr, props;
3085 /* TODO: figure out how to compute this. */
3086 tree ivarLayout = NULL_TREE;
3087 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3088 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3089 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3090 location_t loc;
3091 char buf[BUFSIZE];
3092 unsigned int instanceStart, instanceSize;
3093 unsigned int flags = 0x01; /* RO_META */
3094 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3095 : 0 ;
3096
3097 class_decl = impent->class_decl;
3098 metaclass_decl = impent->meta_decl;
3099 loc = DECL_SOURCE_LOCATION (class_decl);
3100
3101 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3102 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3103 #ifdef OBJCPLUS
3104 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3105 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3106 #endif
3107
3108 /* Generation of data for meta class. */
3109 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3110 if (my_super_id)
3111 {
3112 /* Compute reference to root's name. For a meta class, "isa" is
3113 a reference to the root class name. */
3114 tree my_root_id = my_super_id;
3115 tree my_root_int, interface;
3116 do
3117 {
3118 my_root_int = lookup_interface (my_root_id);
3119
3120 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3121 my_root_id = CLASS_SUPER_NAME (my_root_int);
3122 else
3123 break;
3124 }
3125 while (1);
3126
3127 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3128 create extern if not already declared. */
3129 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3130 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3131 root_expr = create_extern_decl (objc_v2_class_template, buf);
3132 root_expr = build_fold_addr_expr (root_expr);
3133
3134 /* Install class `isa' and `super' pointers at runtime. */
3135 interface = lookup_interface (my_super_id);
3136 gcc_assert (interface);
3137 /* Similarly, for OBJC_CLASS_$_<interface>... */
3138 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3139 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3140 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3141 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3142 /* ... and for OBJC_METACLASS_$_<interface>. */
3143 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3144 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3145 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3146 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3147 }
3148 else
3149 {
3150 /* Root class. */
3151 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3152 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3153 class_superclass_expr = build_int_cst (NULL_TREE, 0);
3154 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */
3155 }
3156
3157 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3158 {
3159 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3160 protocol_decl = generate_v2_protocol_list (impent->imp_template,
3161 impent->imp_context);
3162 }
3163 else
3164 protocol_decl = 0;
3165
3166 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3167 class_names);
3168
3169 if (CLASS_CLS_METHODS (impent->imp_context))
3170 {
3171 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3172 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3173 class_methods =
3174 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3175 buf, meta_clac_meth);
3176 }
3177
3178 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3179
3180 /* Currently there are no class ivars and generation of class
3181 variables for the root of the inheritance has been removed. It
3182 causes multiple defines if there are two root classes in the
3183 link, because each will define its own identically-named offset
3184 variable. */
3185
3186 class_ivars = NULL_TREE;
3187 /* TODO: Add total size of class variables when implemented. */
3188 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3189
3190 /* So now build the META CLASS structs. */
3191 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3192
3193 decl = start_var_decl (objc_v2_class_ro_template,
3194 newabi_append_ro (IDENTIFIER_POINTER
3195 (DECL_NAME (metaclass_decl))));
3196
3197 /* TODO: ivarLayout needs t be built. */
3198 initlist =
3199 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3200 (flags | cls_flags), instanceStart,
3201 instanceSize, ivarLayout,
3202 class_methods, protocol_decl,
3203 class_ivars, NULL_TREE);
3204 /* The ROs sit in the default const section. */
3205 OBJCMETA (decl, objc_meta, meta_base);
3206 finish_var_decl (decl, initlist);
3207
3208 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3209 initlist =
3210 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3211 root_expr,
3212 metaclass_superclass_expr,
3213 build_fold_addr_expr (decl),
3214 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3215 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3216 /* The class section attributes are set when they are created. */
3217 finish_var_decl (metaclass_decl, initlist);
3218 impent->meta_decl = metaclass_decl;
3219
3220 /* So now build the CLASS structs. */
3221
3222 flags = 0x0; /* ... */
3223 if (!my_super_id)
3224 flags |= 0x02; /* RO_ROOT: this is a root class */
3225
3226 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3227 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3228
3229 if (objc2_objc_exception_attr (impent->imp_template))
3230 flags |= 0x20; /* RO_EXCEPTION */
3231
3232 if (CLASS_NST_METHODS (impent->imp_context))
3233 {
3234 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3235 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3236 inst_methods =
3237 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3238 buf, meta_clai_meth);
3239 }
3240
3241 /* Sort out the ivars before we try to compute the class sizes. */
3242 if ((chain = CLASS_IVARS (impent->imp_template)))
3243 {
3244 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3245 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3246 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3247 impent->imp_template);
3248 }
3249
3250 /* Compute instanceStart. */
3251 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3252 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3253 if (my_super_id && field && TREE_CHAIN (field))
3254 field = TREE_CHAIN (field);
3255
3256 firstIvar = field;
3257
3258 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3259 firstIvar = TREE_CHAIN (firstIvar);
3260
3261 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3262
3263 /* Compute instanceSize. */
3264 while (field && TREE_CHAIN (field)
3265 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3266 field = TREE_CHAIN (field);
3267
3268 if (field && TREE_CODE (field) == FIELD_DECL)
3269 instanceSize = int_byte_position (field) * BITS_PER_UNIT
3270 + tree_low_cst (DECL_SIZE (field), 0);
3271 else
3272 instanceSize = 0;
3273 instanceSize /= BITS_PER_UNIT;
3274
3275 props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3276
3277 /* If the class has no ivars, instanceStart should be set to the
3278 superclass's instanceSize. */
3279 instanceStart =
3280 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3281 : instanceSize;
3282
3283 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3284 decl = start_var_decl (objc_v2_class_ro_template,
3285 newabi_append_ro (IDENTIFIER_POINTER
3286 (DECL_NAME (class_decl))));
3287
3288 initlist =
3289 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3290 (flags | cls_flags), instanceStart,
3291 instanceSize, ivarLayout,
3292 inst_methods, protocol_decl,
3293 inst_ivars, props);
3294 /* The ROs sit in the default const section. */
3295 OBJCMETA (decl, objc_meta, meta_base);
3296 finish_var_decl (decl, initlist);
3297
3298 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3299 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3300 build_fold_addr_expr (metaclass_decl),
3301 class_superclass_expr,
3302 build_fold_addr_expr (decl),
3303 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3304 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3305
3306 /* The class section attributes are set when they are created. */
3307 finish_var_decl (class_decl, initlist);
3308 impent->class_decl = class_decl;
3309
3310 objc_v2_add_to_class_list (class_decl);
3311 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3312 objc_v2_add_to_nonlazy_class_list (class_decl);
3313
3314 if (flags & 0x20) /* RO_EXCEPTION */
3315 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3316 }
3317
3318 /* This routine outputs the (ivar_reference_offset, offset)
3319 tuples. */
3320
3321 static void
3322 build_v2_ivar_offset_ref_table (void)
3323 {
3324 int count;
3325 ivarref_entry *ref;
3326
3327 if (!vec_safe_length (ivar_offset_refs))
3328 return;
3329
3330 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3331 finish_var_decl (ref->decl, ref->offset);
3332 }
3333
3334 static void
3335 objc_generate_v2_next_metadata (void)
3336 {
3337 struct imp_entry *impent;
3338
3339 /* FIXME: Make sure that we generate no metadata if there is nothing
3340 to put into it. */
3341
3342 gcc_assert (!objc_static_instances); /* Not for NeXT */
3343
3344 build_metadata_templates ();
3345
3346 for (impent = imp_list; impent; impent = impent->next)
3347 {
3348 /* If -gen-decls is present, Dump the @interface of each class.
3349 TODO: Dump the classes in the order they were found, rather
3350 than in reverse order as we are doing now. */
3351 if (flag_gen_declaration)
3352 dump_interface (gen_declaration_file, impent->imp_context);
3353
3354 /* all of the following reference the string pool... */
3355 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3356 generate_v2_class_structs (impent);
3357 else
3358 generate_v2_category (impent);
3359 }
3360
3361 build_next_selector_translation_table ();
3362 build_v2_message_ref_translation_table ();
3363
3364 /* This will add "Protocol" to the class refs. */
3365 generate_v2_protocols ();
3366
3367 build_v2_classrefs_table ();
3368 build_v2_super_classrefs_table (/*metaclass= */false);
3369 build_v2_super_classrefs_table (/*metaclass= */true);
3370
3371 build_v2_ivar_offset_ref_table ();
3372
3373 build_v2_protocol_list_translation_table ();
3374 build_v2_protocol_list_address_table ();
3375
3376 build_v2_address_table (class_list, "_OBJC_ClassList$",
3377 meta_label_classlist);
3378 build_v2_address_table (category_list, "_OBJC_CategoryList$",
3379 meta_label_categorylist);
3380 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3381 meta_label_nonlazy_classlist);
3382 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3383 meta_label_nonlazy_categorylist);
3384
3385 /* Generate catch objects for eh, if any are needed. */
3386 build_v2_eh_catch_objects ();
3387
3388 /* Emit the string table last. */
3389 generate_strings ();
3390 }
3391
3392 /* NOTE --- Output NeXT V2 Exceptions --- */
3393
3394 static GTY(()) tree objc_v2_ehtype_template;
3395 static GTY(()) tree next_v2_ehvtable_decl;
3396 static GTY(()) tree next_v2_EHTYPE_id_decl;
3397
3398 static void
3399 build_v2_ehtype_template (void)
3400 {
3401 tree decls, *chain = NULL;
3402 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3403
3404 /* void *_objc_ehtype_vtable; */
3405 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3406
3407 /* const char *className; */
3408 add_field_decl (string_type_node, "className", &chain);
3409
3410 /* struct class_t *const cls; */
3411 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3412
3413 objc_finish_struct (objc_v2_ehtype_template, decls);
3414 }
3415
3416 /* Template for the Objective-C family typeinfo type for ABI=2. This
3417 starts off the same as the gxx/cxx eh typeinfo.
3418
3419 struct _objc_ehtype_t
3420 {
3421 void *_objc_ehtype_vtable_ptr; - as per c++
3422 const char *className; - as per c++
3423 struct class_t *const cls;
3424 }
3425 */
3426
3427 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3428 */
3429
3430 static tree
3431 objc2_build_ehtype_initializer (tree name, tree cls)
3432 {
3433 vec<constructor_elt, va_gc> *initlist = NULL;
3434 tree addr, offs;
3435
3436 /* This is done the same way as c++, missing the two first entries
3437 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3438 runtime source about this so, perhaps, this will change at some
3439 point. */
3440 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3441 if (!next_v2_ehvtable_decl)
3442 {
3443 next_v2_ehvtable_decl =
3444 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3445 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3446 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3447 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3448 }
3449 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3450 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3451 addr = fold_build_pointer_plus (addr, offs);
3452
3453 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3454
3455 /* className */
3456 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3457
3458 /* cls */
3459 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3460
3461 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3462 }
3463
3464 static tree
3465 build_ehtype (tree name, const char *eh_name, bool weak)
3466 {
3467 tree name_expr, class_name_expr, ehtype_decl, inits;
3468
3469 name_expr = add_objc_string (name, class_names);
3470 /* Extern ref. for the class. ??? Maybe we can look this up
3471 somewhere. */
3472 class_name_expr =
3473 create_extern_decl (objc_v2_class_template,
3474 objc_build_internal_classname (name, false));
3475 class_name_expr = build_fold_addr_expr (class_name_expr);
3476 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3477 if (weak)
3478 DECL_WEAK (ehtype_decl) = 1;
3479 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3480 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3481 finish_var_decl (ehtype_decl, inits);
3482 return ehtype_decl;
3483 }
3484
3485 /* This routine returns TRUE if CLS or any of its super classes has
3486 __attribute__ ((objc_exception)). */
3487
3488 static bool
3489 objc2_objc_exception_attr (tree cls)
3490 {
3491 while (cls)
3492 {
3493 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3494 return true;
3495 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3496 }
3497
3498 return false;
3499 }
3500
3501 static bool
3502 is_implemented (tree name)
3503 {
3504 struct imp_entry *t;
3505 for (t = imp_list; t; t = t->next)
3506 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3507 && CLASS_NAME (t->imp_template) == name)
3508 return true;
3509
3510 return false;
3511 }
3512
3513 /* We will build catch objects:
3514 for any type implemented here.
3515 for any type used in a catch that has no exception attribute. */
3516 static void build_v2_eh_catch_objects (void)
3517 {
3518 int count=0;
3519 ident_data_tuple *ref;
3520
3521 if (!vec_safe_length (ehtype_list))
3522 return;
3523
3524 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3525 {
3526 char buf[BUFSIZE];
3527 bool impl = is_implemented (ref->ident);
3528 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3529 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3530 if (!impl && excpt)
3531 /* The User says this class has a catcher already. */
3532 ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3533 else
3534 /* Create a catcher, weak if it wasn't marked. */
3535 ref->data = build_ehtype (ref->ident, buf, !excpt);
3536 }
3537 }
3538
3539 static tree
3540 lookup_ehtype_ref (tree id)
3541 {
3542 int count=0;
3543 ident_data_tuple *ref;
3544
3545 if (!vec_safe_length (ehtype_list))
3546 return NULL_TREE;
3547
3548 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3549 if (ref->ident == id)
3550 return ref->data;
3551 return NULL_TREE;
3552 }
3553
3554 /* This hook, called via lang_eh_runtime_type, generates a runtime
3555 object which is either the address of the 'OBJC_EHTYPE_$_class'
3556 object or address of external OBJC_EHTYPE_id object. */
3557 static tree
3558 next_runtime_02_eh_type (tree type)
3559 {
3560 tree t;
3561
3562 if (type == error_mark_node
3563 /*|| errorcount || sorrycount*/)
3564 goto err_mark_in;
3565
3566 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3567 {
3568 if (!next_v2_EHTYPE_id_decl)
3569 {
3570 /* This is provided by the Apple/NeXT libobjc.dylib so we
3571 need only to reference it. */
3572 next_v2_EHTYPE_id_decl =
3573 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3574 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3575 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3576 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3577 }
3578 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3579 }
3580
3581 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3582 {
3583 #ifdef OBJCPLUS
3584 /* This routine is also called for c++'s catch clause; in which
3585 case, we use c++'s typeinfo decl. */
3586 return build_eh_type_type (type);
3587 #else
3588 error ("non-objective-c type '%T' cannot be caught", type);
3589 goto err_mark_in;
3590 #endif
3591 }
3592 else
3593 t = OBJC_TYPE_NAME (TREE_TYPE (type));
3594
3595 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3596 t = lookup_ehtype_ref (t);
3597 if (!t)
3598 goto err_mark_in;
3599
3600 return build_fold_addr_expr (t);
3601
3602 err_mark_in:
3603 return error_mark_node;
3604 }
3605
3606 static GTY(()) tree objc_eh_personality_decl;
3607
3608 static tree
3609 objc_eh_personality (void)
3610 {
3611 if (!objc_eh_personality_decl)
3612 objc_eh_personality_decl = build_personality_function ("objc");
3613 return objc_eh_personality_decl;
3614 }
3615
3616 /* NOTE --- interfaces --- */
3617
3618 static tree
3619 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3620 {
3621 tree t;
3622 if (rethrown)
3623 /* We have a separate re-throw entry. */
3624 t = build_function_call_vec (loc, objc_rethrow_exception_decl, NULL, NULL);
3625 else
3626 {
3627 /* Throw like the others... */
3628 vec<tree, va_gc> *parms;
3629 vec_alloc (parms, 1);
3630 parms->quick_push (throw_expr);
3631 t = build_function_call_vec (loc, objc_exception_throw_decl, parms, 0);
3632 vec_free (parms);
3633 }
3634 return add_stmt (t);
3635 }
3636
3637 /* Build __builtin_eh_pointer. */
3638
3639 static tree
3640 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3641 {
3642 tree t;
3643 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3644 t = build_call_expr (t, 1, integer_zero_node);
3645 return fold_convert (objc_object_type, t);
3646 }
3647
3648 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3649 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3650 {
3651 tree t;
3652
3653 /* Record the data for the catch in the try context so that we can
3654 finalize it later. Ellipsis is signalled by a NULL entry. */
3655 if (ellipsis)
3656 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3657 else
3658 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3659 (*cur_try_context)->current_catch = t;
3660
3661 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3662 t = objc_build_exc_ptr (cur_try_context);
3663 t = convert (TREE_TYPE (decl), t);
3664 /* FIXME: location. */
3665 if (type && type != error_mark_node)
3666 {
3667 t = build1(NOP_EXPR, ptr_type_node, t);
3668 t = build_function_call (input_location, objc2_begin_catch_decl,
3669 tree_cons (NULL_TREE, t, NULL_TREE));
3670
3671 /* We might want to build a catch object for this (if it's not
3672 id). */
3673 if (POINTER_TYPE_P (type)
3674 && !objc_is_object_id (TREE_TYPE (type))
3675 && TYPED_OBJECT (TREE_TYPE (type)))
3676 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3677 }
3678 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3679 }
3680
3681 /* try { catch-body } finally { objc_end_catch (); } */
3682 static void
3683 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3684 {
3685 struct objc_try_context *ct;
3686 tree try_exp, func, *l, t ;
3687 location_t loc = (*cur_try_context)->try_locus;
3688
3689 if (!curr_catch || curr_catch == error_mark_node)
3690 return;
3691
3692 t = CATCH_BODY (curr_catch);
3693 if (TREE_CODE (t) == BIND_EXPR)
3694 {
3695 /* Usual case of @catch (objc-expr). */
3696 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3697 BIND_EXPR_BODY (t) = NULL_TREE;
3698 l = &BIND_EXPR_BODY (t);
3699 }
3700 else
3701 {
3702 /* NULL entry, meaning @catch (...). */
3703 objc_begin_try_stmt (loc, t);
3704 CATCH_BODY (curr_catch) = NULL_TREE;
3705 l = &CATCH_BODY (curr_catch);
3706 }
3707
3708 /* Pick up the new context we made in begin_try above... */
3709 ct = *cur_try_context;
3710 func = build_function_call_vec (loc, objc2_end_catch_decl, NULL, NULL);
3711 append_to_statement_list (func, &ct->finally_body);
3712 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3713 *cur_try_context = ct->outer;
3714 free (ct);
3715 append_to_statement_list (try_exp, l);
3716 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3717 }
3718
3719 static tree
3720 finish_try_stmt (struct objc_try_context **cur_try_context)
3721 {
3722 struct objc_try_context *c = *cur_try_context;
3723 tree stmt = c->try_body;
3724 if (c->catch_list)
3725 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3726 if (c->finally_body)
3727 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3728 return stmt;
3729 }
3730
3731 #include "gt-objc-objc-next-runtime-abi-02.h"