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