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