]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/objc/objc-next-runtime-abi-01.c
2015-06-17 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / objc / objc-next-runtime-abi-01.c
CommitLineData
267785bc 1/* Next Runtime (ABI-0/1) private.
d353bf18 2 Copyright (C) 2011-2015 Free Software Foundation, Inc.
267785bc 3 Contributed by Iain Sandoe (split from objc-act.c)
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
dca79b12 21/* This implements the original NeXT ABI (0) used for m32 code and
22 indicated by module version 6. It also implements the small number
23 of additions made for properties and optional protocol methods as
24 ABI=1 (module version 7). */
267785bc 25
26#include "config.h"
27#include "system.h"
28#include "coretypes.h"
b20a8bb4 29#include "alias.h"
30#include "symtab.h"
31#include "options.h"
267785bc 32#include "tree.h"
b20a8bb4 33#include "fold-const.h"
9ed99284 34#include "stringpool.h"
267785bc 35
36#ifdef OBJCPLUS
e53d55e7 37#include "cp/cp-tree.h"
267785bc 38#else
e53d55e7 39#include "c/c-tree.h"
40#include "c/c-lang.h"
267785bc 41#endif
42#include "langhooks.h"
43#include "c-family/c-objc.h"
44#include "objc-act.h"
45
dca79b12 46/* When building Objective-C++, we are not linking against the C
47 front-end and so need to replicate the C tree-construction
48 functions in some way. */
267785bc 49#ifdef OBJCPLUS
50#define OBJCP_REMAP_FUNCTIONS
51#include "objcp-decl.h"
52#endif /* OBJCPLUS */
53
267785bc 54#include "target.h"
ff6624bc 55#include "c-family/c-target.h"
267785bc 56#include "tree-iterator.h"
57
58#include "objc-runtime-hooks.h"
59#include "objc-runtime-shared-support.h"
f572c7ba 60#include "objc-encoding.h"
267785bc 61
62/* NeXT ABI 0 and 1 private definitions. */
63#define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
64
65#define TAG_GETCLASS "objc_getClass"
66#define TAG_GETMETACLASS "objc_getMetaClass"
67
68#define TAG_MSGSEND "objc_msgSend"
69#define TAG_MSGSENDSUPER "objc_msgSendSuper"
70#define TAG_MSGSEND_STRET "objc_msgSend_stret"
71#define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
72
73/* NeXT-specific tags. */
74
75#define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
76#define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
77#define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
78#define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
79#define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
80#define TAG_EXCEPTIONMATCH "objc_exception_match"
81#define TAG_SETJMP "_setjmp"
82
83#define TAG_ASSIGNIVAR "objc_assign_ivar"
84#define TAG_ASSIGNGLOBAL "objc_assign_global"
85#define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
86
87/* Branch entry points. All that matters here are the addresses;
88 functions with these names do not really exist in libobjc. */
89
90#define TAG_MSGSEND_FAST "objc_msgSend_Fast"
91#define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
92
dca79b12 93/* The version identifies which language generation and runtime the
94 module (file) was compiled for, and is recorded in the module
95 descriptor. */
267785bc 96#define OBJC_VERSION (flag_objc_abi >= 1 ? 7 : 6)
97
98#define UTAG_CLASS_EXT "_objc_class_ext"
99#define UTAG_PROPERTY_LIST "_prop_list_t"
100#define UTAG_PROTOCOL_EXT "_objc_protocol_extension"
101
102#define CLS_HAS_CXX_STRUCTORS 0x2000L
103
dca79b12 104/* rt_trees identifiers - shared between NeXT implementations. These
105 allow the FE to tag meta-data in a manner that survives LTO and can
106 be used when the runtime requires that certain meta-data items
107 appear in particular named sections. */
267785bc 108
109#include "objc-next-metadata-tags.h"
110extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
111
112static void next_runtime_01_initialize (void);
113
114static tree next_runtime_abi_01_super_superclassfield_id (void);
115
116static tree next_runtime_abi_01_class_decl (tree);
117static tree next_runtime_abi_01_metaclass_decl (tree);
118static tree next_runtime_abi_01_category_decl (tree);
119static tree next_runtime_abi_01_protocol_decl (tree);
120static tree next_runtime_abi_01_string_decl (tree, const char *, string_section);
121
122static tree next_runtime_abi_01_get_class_reference (tree);
123static tree next_runtime_abi_01_build_selector_reference (location_t, tree, tree);
124static tree next_runtime_abi_01_get_protocol_reference (location_t, tree);
125static tree next_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
126static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
127static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
128
129static tree next_runtime_abi_01_receiver_is_class_object (tree);
f1f41a6c 130static void next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **,
131 tree, int, int);
267785bc 132static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
133 tree, tree, tree, int);
134static bool next_runtime_abi_01_setup_const_string_class_decl (void);
135static tree next_runtime_abi_01_build_const_string_constructor (location_t, tree, int);
136
137static void objc_generate_v1_next_metadata (void);
138
139static void build_next_objc_exception_stuff (void);
140static tree objc_eh_runtime_type (tree type);
141static tree objc_eh_personality (void);
142static tree build_throw_stmt (location_t, tree, bool);
143static tree objc_build_exc_ptr (struct objc_try_context **);
144static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
145static void finish_catch (struct objc_try_context **, tree);
146static tree finish_try_stmt (struct objc_try_context **);
147
6bbb4715 148bool
267785bc 149objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks)
150{
6bbb4715 151 if (flag_objc_exceptions
267785bc 152 && !flag_objc_sjlj_exceptions)
153 {
6bbb4715 154 warning_at (UNKNOWN_LOCATION, OPT_Wall,
267785bc 155 "%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
156 "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2");
157 }
158
159 rthooks->initialize = next_runtime_01_initialize;
160 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
161 rthooks->tag_getclass = TAG_GETCLASS;
162 rthooks->super_superclassfield_ident = next_runtime_abi_01_super_superclassfield_id;
163
164 rthooks->class_decl = next_runtime_abi_01_class_decl;
165 rthooks->metaclass_decl = next_runtime_abi_01_metaclass_decl;
166 rthooks->category_decl = next_runtime_abi_01_category_decl;
167 rthooks->protocol_decl = next_runtime_abi_01_protocol_decl;
168 rthooks->string_decl = next_runtime_abi_01_string_decl;
169
170 rthooks->get_class_reference = next_runtime_abi_01_get_class_reference;
171 rthooks->build_selector_reference = next_runtime_abi_01_build_selector_reference;
172 rthooks->get_protocol_reference = next_runtime_abi_01_get_protocol_reference;
173 rthooks->build_ivar_reference = next_runtime_abi_01_build_ivar_ref;
174 rthooks->get_class_super_ref = next_runtime_abi_01_get_class_super_ref;
175 rthooks->get_category_super_ref = next_runtime_abi_01_get_category_super_ref;
176
177 rthooks->receiver_is_class_object = next_runtime_abi_01_receiver_is_class_object;
178 rthooks->get_arg_type_list_base = next_runtime_abi_01_get_arg_type_list_base;
179 rthooks->build_objc_method_call = next_runtime_abi_01_build_objc_method_call;
180
181 rthooks->setup_const_string_class_decl =
182 next_runtime_abi_01_setup_const_string_class_decl;
183 rthooks->build_const_string_constructor =
184 next_runtime_abi_01_build_const_string_constructor;
185
186 rthooks->build_throw_stmt = build_throw_stmt;
187 rthooks->build_exc_ptr = objc_build_exc_ptr;
188 rthooks->begin_catch = begin_catch;
189 rthooks->finish_catch = finish_catch;
190 rthooks->finish_try_stmt = finish_try_stmt;
191
192 rthooks->generate_metadata = objc_generate_v1_next_metadata;
193 return true;
194}
195
dca79b12 196/* We need a way to convey what kind of meta-data are represented by a
197 given variable, since each type is expected (by the runtime) to be
198 found in a specific named section. The solution must be usable
199 with LTO.
6bbb4715 200
dca79b12 201 The scheme used for NeXT ABI 0/1 (partial matching of variable
202 names) is not satisfactory for LTO & ABI-2. We now tag ObjC
203 meta-data with identification attributes in the front end. The
204 back-end may choose to act on these as it requires. */
267785bc 205
206static void
207next_runtime_abi_01_init_metadata_attributes (void)
208{
209 if (!objc_meta)
210 objc_meta = get_identifier ("OBJC1META");
211
212 if (!meta_base)
213 meta_base = get_identifier ("V1_BASE");
214
215 meta_class = get_identifier ("V1_CLAS");
216 meta_metaclass = get_identifier ("V1_META");
217 meta_category = get_identifier ("V1_CATG");
218 meta_protocol = get_identifier ("V1_PROT");
219
220 meta_clac_vars = get_identifier ("V1_CLCV");
221 meta_clai_vars = get_identifier ("V1_CLIV");
222
223 meta_clac_meth = get_identifier ("V1_CLCM");
224 meta_clai_meth = get_identifier ("V1_CLIM");
225 meta_catc_meth = get_identifier ("V1_CACM");
226 meta_cati_meth = get_identifier ("V1_CAIM");
227 meta_proto_cls_meth = get_identifier ("V1_PCLM");
228 meta_proto_nst_meth = get_identifier ("V1_PNSM");
229
230 meta_clas_prot = get_identifier ("V1_CLPR");
231 meta_catg_prot = get_identifier ("V1_CAPR");
232
233 meta_class_reference = get_identifier ("V1_CLRF");
234 meta_proto_ref = get_identifier ("V1_PRFS");
235 meta_sel_refs = get_identifier ("V1_SRFS");
236
237 meta_class_name = get_identifier ("V1_CLSN");
238 meta_meth_name = get_identifier ("V1_METN");
239 meta_meth_type = get_identifier ("V1_METT");
240 meta_prop_name_attr = get_identifier ("V1_STRG");
6bbb4715 241
267785bc 242 meta_modules = get_identifier ("V1_MODU");
243 meta_symtab = get_identifier ("V1_SYMT");
244 meta_info = get_identifier ("V1_INFO");
6bbb4715 245
267785bc 246 meta_proplist = get_identifier ("V1_PLST");
247 meta_protocol_extension = get_identifier ("V1_PEXT");
248 meta_class_extension = get_identifier ("V1_CEXT");
6bbb4715 249
267785bc 250 meta_const_str = get_identifier ("V1_CSTR");
251}
252
253static void build_v1_class_template (void);
254static void build_v1_category_template (void);
255static void build_v1_protocol_template (void);
256
257static void next_runtime_01_initialize (void)
258{
259 tree type;
260
261#ifdef OBJCPLUS
dca79b12 262 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
263 default. */
264 if (!global_options_set.x_flag_objc_call_cxx_cdtors)
265 global_options.x_flag_objc_call_cxx_cdtors = 1;
267785bc 266#endif
267
268 /* Set up attributes to be attached to the meta-data so that they
269 will be placed in the correct sections. */
270 next_runtime_abi_01_init_metadata_attributes ();
271
272 if (flag_objc_abi >= 1)
273 objc_prop_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE,
274 get_identifier ("_prop_list_t")));
275
dca79b12 276 /* Declare type of selector-objects that represent an operation
277 name. */
267785bc 278 /* `struct objc_selector *' */
279 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
280 get_identifier (TAG_SELECTOR)));
281
282 build_v1_class_template ();
283 build_super_template ();
284 build_v1_protocol_template ();
285 build_v1_category_template ();
286
287 /* NB: In order to call one of the ..._stret (struct-returning)
288 functions, the function *MUST* first be cast to a signature that
289 corresponds to the actual ObjC method being invoked. This is
290 what is done by the build_objc_method_call() routine below. */
291
292 /* id objc_msgSend (id, SEL, ...); */
293 /* id objc_msgSendNonNil (id, SEL, ...); */
294 /* id objc_msgSend_stret (id, SEL, ...); */
295 /* id objc_msgSendNonNil_stret (id, SEL, ...); */
296 type = build_varargs_function_type_list (objc_object_type,
297 objc_object_type,
298 objc_selector_type,
299 NULL_TREE);
300
301 umsg_decl = add_builtin_function (TAG_MSGSEND,
302 type, 0, NOT_BUILT_IN,
303 NULL, NULL_TREE);
304
305 umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL,
306 type, 0, NOT_BUILT_IN,
307 NULL, NULL_TREE);
308
309 umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET,
310 type, 0, NOT_BUILT_IN,
311 NULL, NULL_TREE);
312
313 umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET,
314 type, 0, NOT_BUILT_IN,
315 NULL, NULL_TREE);
316
317 /* These can throw, because the function that gets called can throw
dca79b12 318 in Obj-C++, or could itself call something that can throw even in
319 Obj-C. */
267785bc 320 TREE_NOTHROW (umsg_decl) = 0;
321 TREE_NOTHROW (umsg_nonnil_decl) = 0;
322 TREE_NOTHROW (umsg_stret_decl) = 0;
323 TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
324
325 /* id objc_msgSend_Fast (id, SEL, ...)
326 __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
327#ifdef OFFS_MSGSEND_FAST
328 umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST,
329 type, 0, NOT_BUILT_IN,
330 NULL, NULL_TREE);
331 TREE_NOTHROW (umsg_fast_decl) = 0;
332 DECL_ATTRIBUTES (umsg_fast_decl)
333 = tree_cons (get_identifier ("hard_coded_address"),
334 build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
335 NULL_TREE);
336#else
337 /* No direct dispatch available. */
338 umsg_fast_decl = umsg_decl;
339#endif
340
341 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
342 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
343 type = build_varargs_function_type_list (objc_object_type,
344 objc_super_type,
345 objc_selector_type,
346 NULL_TREE);
347 umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
348 type, 0, NOT_BUILT_IN,
349 NULL, NULL_TREE);
350 umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET,
351 type, 0, NOT_BUILT_IN, 0,
352 NULL_TREE);
353 TREE_NOTHROW (umsg_super_decl) = 0;
354 TREE_NOTHROW (umsg_super_stret_decl) = 0;
355
356 type = build_function_type_list (objc_object_type,
357 const_string_type_node,
358 NULL_TREE);
359
360 /* id objc_getClass (const char *); */
361 objc_get_class_decl
362 = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
363 NULL, NULL_TREE);
364
365 /* id objc_getMetaClass (const char *); */
366 objc_get_meta_class_decl
367 = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
368
dca79b12 369 /* This is the type of all of the following functions
370 objc_copyStruct(). */
267785bc 371 type = build_function_type_list (void_type_node,
372 ptr_type_node,
373 const_ptr_type_node,
6bbb4715 374 ptrdiff_type_node,
267785bc 375 boolean_type_node,
376 boolean_type_node,
377 NULL_TREE);
378 /* Declare the following function:
379 void
6bbb4715 380 objc_copyStruct (void *destination, const void *source,
dca79b12 381 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
267785bc 382 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
383 type, 0, NOT_BUILT_IN,
384 NULL, NULL_TREE);
385 TREE_NOTHROW (objc_copyStruct_decl) = 0;
386 objc_getPropertyStruct_decl = NULL_TREE;
387 objc_setPropertyStruct_decl = NULL_TREE;
388
389 build_next_objc_exception_stuff ();
390 if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
391 using_eh_for_cleanups ();
392 lang_hooks.eh_runtime_type = objc_eh_runtime_type;
393 lang_hooks.eh_personality = objc_eh_personality;
394}
395
396/* --- templates --- */
397
6bbb4715 398/* struct _objc_class
dca79b12 399 {
267785bc 400 struct _objc_class *isa;
401 struct _objc_class *super_class;
402 char *name;
403 long version;
404 long info;
405 long instance_size;
406 struct _objc_ivar_list *ivars;
407 struct _objc_method_list *methods;
408 struct objc_cache *cache;
409 struct _objc_protocol_list *protocols;
410 #if ABI=1
411 const char *ivar_layout;
412 struct _objc_class_ext *ext;
413 #else
414 void *sel_id;
415 void *gc_object_type;
416 #endif
dca79b12 417 }; */
267785bc 418
dca79b12 419/* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT
420 runtime. We generate them for ABI==0 to maintain backward binary
421 compatibility. */
267785bc 422
423static void
424build_v1_class_template (void)
425{
426 tree ptype, decls, *chain = NULL;
427
428 objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
429
430 /* struct _objc_class *isa; */
431 decls = add_field_decl (build_pointer_type (objc_class_template),
432 "isa", &chain);
433
434 /* struct _objc_class *super_class; */
435 add_field_decl (build_pointer_type (objc_class_template),
436 "super_class", &chain);
437
438 /* char *name; */
439 add_field_decl (string_type_node, "name", &chain);
440
441 /* long version; */
442 add_field_decl (long_integer_type_node, "version", &chain);
443
444 /* long info; */
445 add_field_decl (long_integer_type_node, "info", &chain);
446
447 /* long instance_size; */
448 add_field_decl (long_integer_type_node, "instance_size", &chain);
449
450 /* struct _objc_ivar_list *ivars; */
451 add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
452
453 /* struct _objc_method_list *methods; */
454 add_field_decl (objc_method_list_ptr, "methods", &chain);
455
456 /* struct objc_cache *cache; */
457 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
458 get_identifier ("objc_cache")));
459 add_field_decl (ptype, "cache", &chain);
460
461 /* struct _objc_protocol **protocol_list; */
462 ptype = build_pointer_type (build_pointer_type
463 (xref_tag (RECORD_TYPE,
464 get_identifier (UTAG_PROTOCOL))));
465 add_field_decl (ptype, "protocol_list", &chain);
466
467 if (flag_objc_abi >= 1)
468 {
469 /* const char *ivar_layout; */
470 add_field_decl (const_string_type_node, "ivar_layout", &chain);
471
472 /* struct _objc_class_ext *ext; */
473 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
474 get_identifier (UTAG_CLASS_EXT)));
475 add_field_decl (ptype, "ext", &chain);
476 }
477 else
478 {
479 /* void *sel_id; */
480 add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain);
481 /* void *gc_object_type; */
482 add_field_decl (build_pointer_type (void_type_node), "gc_object_type",
483 &chain);
484 }
485
486 objc_finish_struct (objc_class_template, decls);
487}
488
dca79b12 489/* struct _objc_category
490 {
267785bc 491 char *category_name;
492 char *class_name;
493 struct _objc_method_list *instance_methods;
494 struct _objc_method_list *class_methods;
495 struct _objc_protocol_list *protocols;
dca79b12 496 #if ABI=1
267785bc 497 uint32_t size; // sizeof (struct _objc_category)
498 struct _objc_property_list *instance_properties; // category's own @property decl.
dca79b12 499 #endif
267785bc 500 }; */
501
502static void
503build_v1_category_template (void)
504{
505 tree ptype, decls, *chain = NULL;
506
507 objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
508
509 /* char *category_name; */
510 decls = add_field_decl (string_type_node, "category_name", &chain);
511
512 /* char *class_name; */
513 add_field_decl (string_type_node, "class_name", &chain);
514
515 /* struct _objc_method_list *instance_methods; */
516 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
517
518 /* struct _objc_method_list *class_methods; */
519 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
520
521 /* struct _objc_protocol **protocol_list; */
522 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
523 add_field_decl (ptype, "protocol_list", &chain);
524
525 if (flag_objc_abi >= 1)
526 {
527 add_field_decl (integer_type_node, "size", &chain);
6bbb4715 528
267785bc 529 /* struct _objc_property_list *instance_properties;
530 This field describes a category's @property declarations.
dca79b12 531 Properties from inherited protocols are not included. */
6bbb4715 532 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
267785bc 533 get_identifier (UTAG_PROPERTY_LIST)));
534 add_field_decl (ptype, "instance_properties", &chain);
535 }
536 objc_finish_struct (objc_category_template, decls);
537}
538
dca79b12 539/* Begin code generation for protocols...
267785bc 540 Modified for ObjC #1 extensions. */
541
dca79b12 542/* struct _objc_protocol
543 {
544 #if ABI=1
267785bc 545 struct _objc_protocol_extension *isa;
dca79b12 546 #else
267785bc 547 struct _objc_class *isa;
6bbb4715 548 #endif
dca79b12 549
267785bc 550 char *protocol_name;
551 struct _objc_protocol **protocol_list;
552 struct _objc__method_prototype_list *instance_methods;
553 struct _objc__method_prototype_list *class_methods;
dca79b12 554 }; */
267785bc 555
556static void
557build_v1_protocol_template (void)
558{
559 tree ptype, decls, *chain = NULL;
560
561 objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
562
563 if (flag_objc_abi >= 1)
564 /* struct _objc_protocol_extension *isa; */
565 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
566 get_identifier (UTAG_PROTOCOL_EXT)));
567 else
dca79b12 568 /* struct _objc_class *isa; */
267785bc 569 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
570 get_identifier (UTAG_CLASS)));
571
572 decls = add_field_decl (ptype, "isa", &chain);
573
574 /* char *protocol_name; */
575 add_field_decl (string_type_node, "protocol_name", &chain);
576
577 /* struct _objc_protocol **protocol_list; */
578 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
579 add_field_decl (ptype, "protocol_list", &chain);
580
581 /* struct _objc__method_prototype_list *instance_methods; */
582 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
583
584 /* struct _objc__method_prototype_list *class_methods; */
585 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
586
587 objc_finish_struct (objc_protocol_template, decls);
588}
589
86d30f03 590/* --- names, decls identifiers --- */
267785bc 591
592static tree
593next_runtime_abi_01_super_superclassfield_id (void)
594{
595 if (!super_superclassfield_id)
596 super_superclassfield_id = get_identifier ("super_class");
597 return super_superclassfield_id;
598}
599
600static tree
601next_runtime_abi_01_class_decl (tree klass)
602{
603 tree decl;
604 char buf[BUFSIZE];
6bbb4715 605 snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
267785bc 606 IDENTIFIER_POINTER (CLASS_NAME (klass)));
607 decl = start_var_decl (objc_class_template, buf);
608 OBJCMETA (decl, objc_meta, meta_class);
609 return decl;
610}
611
612static tree
613next_runtime_abi_01_metaclass_decl (tree klass)
614{
615 tree decl;
616 char buf[BUFSIZE];
6bbb4715 617 snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
267785bc 618 IDENTIFIER_POINTER (CLASS_NAME (klass)));
619 decl = start_var_decl (objc_class_template, buf);
620 OBJCMETA (decl, objc_meta, meta_metaclass);
621 return decl;
622}
623
624static tree
625next_runtime_abi_01_category_decl (tree klass)
626{
627 tree decl;
628 char buf[BUFSIZE];
6bbb4715 629 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
267785bc 630 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
631 IDENTIFIER_POINTER (CLASS_NAME (klass)));
632 decl = start_var_decl (objc_category_template, buf);
633 OBJCMETA (decl, objc_meta, meta_category);
634 return decl;
635}
636
637static tree
638next_runtime_abi_01_protocol_decl (tree p)
639{
640 tree decl;
641 char buf[BUFSIZE];
642
643 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
644
645 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
646 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
647 decl = start_var_decl (objc_protocol_template, buf);
648 OBJCMETA (decl, objc_meta, meta_protocol);
649 return decl;
650}
651
652static tree
653next_runtime_abi_01_string_decl (tree type, const char *name, string_section where)
654{
655 tree var = start_var_decl (type, name);
656 switch (where)
657 {
658 case class_names:
659 OBJCMETA (var, objc_meta, meta_class_name);
660 break;
661 case meth_var_names:
662 OBJCMETA (var, objc_meta, meta_meth_name);
663 break;
664 case meth_var_types:
665 OBJCMETA (var, objc_meta, meta_meth_type);
666 break;
667 case prop_names_attr:
668 OBJCMETA (var, objc_meta, meta_prop_name_attr);
669 break;
6bbb4715 670 default:
267785bc 671 OBJCMETA (var, objc_meta, meta_base);
672 break;
673 }
674 return var;
675}
676
677/* --- entry --- */
678
679static GTY(()) int class_reference_idx;
680
681static tree
682build_class_reference_decl (void)
683{
684 tree decl;
685 char buf[BUFSIZE];
686
687 sprintf (buf, "_OBJC_ClassRefs_%d", class_reference_idx++);
688 decl = start_var_decl (objc_class_type, buf);
689
690 return decl;
691}
692
693static tree
694next_runtime_abi_01_get_class_reference (tree ident)
695{
696 if (!flag_zero_link)
697 {
698 tree *chain;
699 tree decl;
700
701 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
702 if (TREE_VALUE (*chain) == ident)
703 {
704 if (! TREE_PURPOSE (*chain))
705 TREE_PURPOSE (*chain) = build_class_reference_decl ();
706
707 return TREE_PURPOSE (*chain);
708 }
709
710 decl = build_class_reference_decl ();
711 *chain = tree_cons (decl, ident, NULL_TREE);
712 return decl;
713 }
714 else
715 {
716 tree params;
717
718 add_class_reference (ident);
719
720 params = build_tree_list (NULL_TREE,
721 my_build_string_pointer
722 (IDENTIFIER_LENGTH (ident) + 1,
723 IDENTIFIER_POINTER (ident)));
724
725 return build_function_call (input_location, objc_get_class_decl, params);
726 }
727}
728
5318d5a9 729/* Used by build_function_type_for_method. Append the types for
730 receiver & _cmd at the start of a method argument list to ARGTYPES.
731 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
732 trying to define a method or call one. SUPERFLAG says this is for a
733 send to super. METH may be NULL, in the case that there is no
734 prototype. */
267785bc 735
5318d5a9 736static void
f1f41a6c 737next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
738 tree meth, int context,
739 int superflag)
267785bc 740{
5318d5a9 741 tree receiver_type;
267785bc 742
267785bc 743 if (superflag)
5318d5a9 744 receiver_type = objc_super_type;
267785bc 745 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
5318d5a9 746 receiver_type = objc_instance_type;
267785bc 747 else
5318d5a9 748 receiver_type = objc_object_type;
267785bc 749
f1f41a6c 750 vec_safe_push (*argtypes, receiver_type);
267785bc 751 /* Selector type - will eventually change to `int'. */
f1f41a6c 752 vec_safe_push (*argtypes, objc_selector_type);
267785bc 753}
754
755static tree
756next_runtime_abi_01_receiver_is_class_object (tree receiver)
757{
758 if (TREE_CODE (receiver) == VAR_DECL
759 && IS_CLASS (TREE_TYPE (receiver)))
760 {
761 /* The receiver is a variable created by build_class_reference_decl. */
762 tree chain = cls_ref_chain ;
763 /* Look up the identifier in the relevant chain. */
764 for (; chain; chain = TREE_CHAIN (chain))
765 if (TREE_PURPOSE (chain) == receiver)
766 return TREE_VALUE (chain);
767 }
768 return NULL_TREE;
769}
770
771static tree
772build_selector_reference_decl (tree ident)
773{
774 tree decl;
775 char *t, buf[BUFSIZE];
776
777 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
778 t = buf;
779 while (*t)
780 {
6bbb4715 781 if (*t==':')
267785bc 782 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
783 t++;
784 }
785 decl = start_var_decl (objc_selector_type, buf);
786 OBJCMETA (decl, objc_meta, meta_sel_refs);
787 return decl;
788}
789
790static tree
791next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
792 tree ident,
793 tree proto ATTRIBUTE_UNUSED)
794{
795 tree *chain = &sel_ref_chain;
796 tree expr;
797
798 while (*chain)
799 {
800 if (TREE_VALUE (*chain) == ident)
801 return TREE_PURPOSE (*chain);
802
803 chain = &TREE_CHAIN (*chain);
804 }
805
806 expr = build_selector_reference_decl (ident);
807
808 *chain = tree_cons (expr, ident, NULL_TREE);
809
810 return expr;
811}
812
813/* Build a tree expression to send OBJECT the operation SELECTOR,
814 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
815 assuming the method has prototype METHOD_PROTOTYPE.
816 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
817 LOC is the location of the expression to build.
818 Use METHOD_PARAMS as list of args to pass to the method.
819 If SUPER_FLAG is nonzero, we look up the superclass's method. */
820
821static tree
822build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
823 tree lookup_object, tree selector,
824 tree method_params)
825{
826 tree sender, sender_cast, method, t;
827 tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
f1f41a6c 828 vec<tree, va_gc> *parms;
267785bc 829 unsigned nparm = (method_params ? list_length (method_params) : 0);
830
831 /* If a prototype for the method to be called exists, then cast
832 the sender's return type and arguments to match that of the method.
833 Otherwise, leave sender as is. */
834 tree ret_type
835 = (method_prototype
836 ? TREE_VALUE (TREE_TYPE (method_prototype))
837 : objc_object_type);
5318d5a9 838 tree ftype = build_function_type_for_method (ret_type, method_prototype,
839 METHOD_REF, super_flag);
267785bc 840
841 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
6bbb4715 842 ftype = build_type_attribute_variant (ftype,
843 METHOD_TYPE_ATTRIBUTES
267785bc 844 (method_prototype));
845
846 sender_cast = build_pointer_type (ftype);
847
848 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
849
850 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
851 lookup_object = save_expr (lookup_object);
852
853 /* Param list + 2 slots for object and selector. */
f1f41a6c 854 vec_alloc (parms, nparm + 2);
267785bc 855
856 /* If we are returning a struct in memory, and the address
857 of that memory location is passed as a hidden first
858 argument, then change which messenger entry point this
859 expr will call. NB: Note that sender_cast remains
860 unchanged (it already has a struct return type). */
861 if (!targetm.calls.struct_value_rtx (0, 0)
862 && (TREE_CODE (ret_type) == RECORD_TYPE
863 || TREE_CODE (ret_type) == UNION_TYPE)
864 && targetm.calls.return_in_memory (ret_type, 0))
865 sender = (super_flag ? umsg_super_stret_decl
6bbb4715 866 : flag_nil_receivers ? umsg_stret_decl
267785bc 867 : umsg_nonnil_stret_decl);
868 else
6bbb4715 869 sender = (super_flag ? umsg_super_decl
870 : (flag_nil_receivers ? (flag_objc_direct_dispatch
267785bc 871 ? umsg_fast_decl
872 : umsg_decl)
873 : umsg_nonnil_decl));
874 method = build_fold_addr_expr_loc (loc, sender);
875
876 /* Pass the object to the method. */
f1f41a6c 877 parms->quick_push (lookup_object);
267785bc 878 /* Pass the selector to the method. */
f1f41a6c 879 parms->quick_push (selector);
267785bc 880 /* Now append the remainder of the parms. */
881 if (nparm)
882 for (; method_params; method_params = TREE_CHAIN (method_params))
f1f41a6c 883 parms->quick_push (TREE_VALUE (method_params));
267785bc 884
885 /* Build an obj_type_ref, with the correct cast for the method call. */
6bbb4715 886 t = build3 (OBJ_TYPE_REF, sender_cast, method,
267785bc 887 lookup_object, size_zero_node);
ec761d5a 888 t = build_function_call_vec (loc, vNULL, t, parms, NULL);
f1f41a6c 889 vec_free (parms);
267785bc 890 return t;
891}
892
893static tree
894next_runtime_abi_01_build_objc_method_call (location_t loc,
895 tree method_prototype,
896 tree receiver,
897 tree rtype ATTRIBUTE_UNUSED,
898 tree sel_name,
899 tree method_params,
900 int super)
901{
902 tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name,
903 NULL_TREE);
904
905 return build_objc_method_call (loc, super, method_prototype,
906 receiver, selector, method_params);
907}
908
909static tree
910next_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
911{
912 tree expr;
913
914 if (!PROTOCOL_FORWARD_DECL (p))
915 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p);
916
917 expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
918 return convert (objc_protocol_type, expr);
919}
920
921/* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
922
923static tree
6bbb4715 924next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
267785bc 925 tree base, tree id)
926{
927 return objc_build_component_ref (base, id);
928}
929
930/* We build super class references as we need them (but keep them once
931 built for the sake of efficiency). */
932
933static tree
934next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
935 struct imp_entry *imp, bool inst_meth)
936{
937 if (inst_meth)
938 {
939 if (!ucls_super_ref)
6bbb4715 940 ucls_super_ref =
941 objc_build_component_ref (imp->class_decl,
267785bc 942 get_identifier ("super_class"));
943 return ucls_super_ref;
944 }
945 else
946 {
947 if (!uucls_super_ref)
6bbb4715 948 uucls_super_ref =
949 objc_build_component_ref (imp->meta_decl,
267785bc 950 get_identifier ("super_class"));
951 return uucls_super_ref;
952 }
953}
954
955static tree
6bbb4715 956next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
267785bc 957 struct imp_entry *imp, bool inst_meth)
958{
959 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
960 tree super_class;
961
962 if (!flag_zero_link)
963 {
964 super_class = objc_get_class_reference (super_name);
965
966 if (!inst_meth)
6bbb4715 967
267785bc 968 /* If we are in a class method, we must retrieve the
969 _metaclass_ for the current class, pointed at by
970 the class's "isa" pointer. The following assumes that
971 "isa" is the first ivar in a class (which it must be). */
6bbb4715 972 super_class =
267785bc 973 build_indirect_ref (input_location,
974 build_c_cast (input_location,
975 build_pointer_type (objc_class_type),
6bbb4715 976 super_class),
267785bc 977 RO_UNARY_STAR);
978 return super_class;
979 }
980
981 /* else do it the slow way. */
982 add_class_reference (super_name);
983 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
267785bc 984 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
985 IDENTIFIER_POINTER (super_name));
dca79b12 986 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
267785bc 987 return build_function_call (input_location,
988 super_class,
989 build_tree_list (NULL_TREE, super_name));
990}
991
992static bool
993next_runtime_abi_01_setup_const_string_class_decl (void)
994{
995 if (!constant_string_global_id)
996 {
997 /* Hopefully, this should not represent a serious limitation. */
998 char buf[BUFSIZE];
999 snprintf (buf, BUFSIZE, "_%sClassReference", constant_string_class_name);
1000 constant_string_global_id = get_identifier (buf);
1001 }
1002
1003 string_class_decl = lookup_name (constant_string_global_id);
1004
1005 return (string_class_decl != NULL_TREE);
1006}
1007
1008static tree
1009next_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
1010 int length)
1011{
1012 tree constructor, fields, var;
f1f41a6c 1013 vec<constructor_elt, va_gc> *v = NULL;
267785bc 1014
1015 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1016 fields = TYPE_FIELDS (internal_const_str_type);
1017 CONSTRUCTOR_APPEND_ELT (v, fields,
1018 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1019
1020 fields = DECL_CHAIN (fields);
1021 CONSTRUCTOR_APPEND_ELT (v, fields,
1022 build_unary_op (loc, ADDR_EXPR, string, 1));
1023
1024 /* ??? check if this should be long. */
1025 fields = DECL_CHAIN (fields);
1026 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1027 constructor = objc_build_constructor (internal_const_str_type, v);
1028
1029 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1030 DECL_INITIAL (var) = constructor;
1031 TREE_STATIC (var) = 1;
1032 DECL_CONTEXT (var) = NULL;
1033 OBJCMETA (var, objc_meta, meta_const_str);
1034 return var;
1035}
1036
1037/* --- metadata templates --- */
1038
1039/* This routine builds the following type:
1040 struct _prop_t {
1041 const char * const name; // property name
6bbb4715 1042 const char * const attributes; // comma-delimited, encoded,
267785bc 1043 // property attributes
1044 };
1045*/
1046
1047static GTY(()) tree objc_v1_property_template;
1048
1049static tree
1050build_v1_property_template (void)
1051{
1052 tree prop_record;
1053 tree decls, *chain = NULL;
1054
1055 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1056 /* const char * name */
1057 decls = add_field_decl (string_type_node, "name", &chain);
1058
1059 /* const char * attribute */
1060 add_field_decl (string_type_node, "attribute", &chain);
1061
1062 objc_finish_struct (prop_record, decls);
1063 return prop_record;
1064}
1065
1066/* Build the following type:
1067
1068 struct _objc_protocol_extension
1069 {
1070 uint32_t size; // sizeof (struct _objc_protocol_extension)
1071 struct objc_method_list *optional_instance_methods;
1072 struct objc_method_list *optional_class_methods;
1073 struct objc_prop_list *instance_properties;
1074 }
1075*/
1076
1077static GTY(()) tree objc_protocol_extension_template;
1078
6bbb4715 1079static void
267785bc 1080build_v1_objc_protocol_extension_template (void)
1081{
1082 tree decls, *chain = NULL;
6bbb4715 1083
1084 objc_protocol_extension_template =
267785bc 1085 objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT));
1086
1087 /* uint32_t size; */
1088 decls = add_field_decl (integer_type_node, "size", &chain);
1089
1090 /* struct objc_method_list *optional_instance_methods; */
1091 add_field_decl (objc_method_list_ptr, "optional_instance_methods", &chain);
1092
1093 /* struct objc_method_list *optional_class_methods; */
1094 add_field_decl (objc_method_list_ptr, "optional_class_methods", &chain);
1095
1096 /* struct objc_prop_list *instance_properties; */
1097 add_field_decl (objc_prop_list_ptr, "instance_properties", &chain);
1098
1099 objc_finish_struct (objc_protocol_extension_template, decls);
1100}
1101
1102/* This routine build following struct type:
6bbb4715 1103 struct _objc_class_ext
267785bc 1104 {
1105 uint32_t size; // sizeof(struct _objc_class_ext)
1106 const char *weak_ivar_layout;
1107 struct _prop_list_t *properties;
1108 }
1109*/
1110
1111static GTY(()) tree objc_class_ext_template;
1112
1113static void
1114build_objc_class_ext_template (void)
1115{
1116 tree ptrt, decls, *chain = NULL;
1117
1118 objc_class_ext_template = objc_start_struct (get_identifier (UTAG_CLASS_EXT));
1119
1120 /* uint32_t size; */
1121 decls = add_field_decl (integer_type_node, "size", &chain);
1122
1123 /* const char *weak_ivar_layout; */
1124 add_field_decl (const_string_type_node, "weak_ivar_layout", &chain);
1125
1126 /* struct _prop_list_t *properties; */
1127 ptrt = build_pointer_type (xref_tag (RECORD_TYPE,
1128 get_identifier(UTAG_PROPERTY_LIST)));
1129 add_field_decl (ptrt, "properties", &chain);
1130
1131 objc_finish_struct (objc_class_ext_template, decls);
1132}
1133
1134static void
1135build_metadata_templates (void)
1136{
1137
1138 if (!objc_method_template)
1139 objc_method_template = build_method_template ();
1140
1141
1142
1143}
1144
1145/* --- emit metadata --- */
1146
6bbb4715 1147static tree
267785bc 1148generate_v1_meth_descriptor_table (tree chain, tree protocol,
1149 const char *prefix, tree attr)
1150{
1151 tree method_list_template, initlist, decl;
1152 int size;
f1f41a6c 1153 vec<constructor_elt, va_gc> *v = NULL;
267785bc 1154 char buf[BUFSIZE];
1155
1156 if (!chain || !prefix)
1157 return NULL_TREE;
1158
1159 if (!objc_method_prototype_template)
1160 objc_method_prototype_template = build_method_prototype_template ();
6bbb4715 1161
267785bc 1162 size = list_length (chain);
6bbb4715 1163 method_list_template =
267785bc 1164 build_method_prototype_list_template (objc_method_prototype_template,
1165 size);
6bbb4715 1166 snprintf (buf, BUFSIZE, "%s_%s", prefix,
267785bc 1167 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1168
1169 decl = start_var_decl (method_list_template, buf);
1170
1171 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
6bbb4715 1172 initlist =
267785bc 1173 build_descriptor_table_initializer (objc_method_prototype_template,
1174 chain);
1175 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1176 /* Get into the right section. */
1177 OBJCMETA (decl, objc_meta, attr);
1178 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1179 return decl;
1180}
1181
1182/* Build protocol ext =
1183 {size, opt_instance_meth, opt_class_meth, instance_props};
1184 or NULL_TREE if none are present. */
1185
1186static tree
6bbb4715 1187generate_v1_objc_protocol_extension (tree proto_interface,
267785bc 1188 tree opt_instance_meth,
1189 tree opt_class_meth,
1190 tree instance_props)
1191{
1192 int size;
1193 location_t loc;
f1f41a6c 1194 vec<constructor_elt, va_gc> *v = NULL;
267785bc 1195 tree decl, expr;
1196 char buf[BUFSIZE];
1197
1198 /* If there are no extensions, then don't bother... */
1199 if (!opt_instance_meth && !opt_class_meth && !instance_props)
1200 return NULL_TREE;
1201
1202 if (!objc_protocol_extension_template)
6bbb4715 1203 build_v1_objc_protocol_extension_template ();
267785bc 1204
1205 /* uint32_t size */
1206 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template));
1207 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1208
1209 /* Try for meaningful diagnostics. */
1210 loc = DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface));
6bbb4715 1211
267785bc 1212 /* struct objc_method_list *optional_instance_methods; */
1213 if (opt_instance_meth)
6bbb4715 1214 expr = convert (objc_method_list_ptr,
267785bc 1215 build_unary_op (loc, ADDR_EXPR, opt_instance_meth, 0));
1216 else
1217 expr = convert (objc_method_list_ptr, null_pointer_node);
1218
1219 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1220
1221 /* struct objc_method_list *optional_class_methods; */
1222 if (opt_class_meth)
6bbb4715 1223 expr = convert (objc_method_list_ptr,
267785bc 1224 build_unary_op (loc, ADDR_EXPR, opt_class_meth, 0));
1225 else
1226 expr = convert (objc_method_list_ptr, null_pointer_node);
1227
1228 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1229 /* struct objc_prop_list *instance_properties; */
1230 if (instance_props)
6bbb4715 1231 expr = convert (objc_prop_list_ptr,
267785bc 1232 build_unary_op (loc, ADDR_EXPR, instance_props, 0));
1233 else
1234 expr = convert (objc_prop_list_ptr, null_pointer_node);
1235
1236 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1237 snprintf (buf, BUFSIZE, "_OBJC_ProtocolExt_%s",
1238 IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface)));
1239
1240 decl = start_var_decl (objc_protocol_extension_template, buf);
1241 expr = objc_build_constructor (TREE_TYPE (decl), v);
1242 OBJCMETA (decl, objc_meta, meta_protocol_extension);
1243 finish_var_decl (decl, expr);
1244 return decl;
1245}
1246
1247/* This routine builds the following type:
1248 struct _prop_list_t {
1249 uint32_t entsize; // sizeof (struct _prop_t)
1250 uint32_t prop_count;
1251 struct _prop_t prop_list [prop_count];
1252 }
1253*/
1254
1255static tree
1256build_v1_property_list_template (tree list_type, int size)
1257{
1258 tree property_list_t_record;
1259 tree array_type, decls, *chain = NULL;
1260
1261 /* anonymous. */
1262 property_list_t_record = objc_start_struct (NULL_TREE);
6bbb4715 1263
267785bc 1264 /* uint32_t const entsize */
1265 decls = add_field_decl (integer_type_node, "entsize", &chain);
1266
1267 /* int prop_count */
1268 add_field_decl (integer_type_node, "prop_count", &chain);
1269
1270 /* struct _prop_t prop_list[]; */
1271 array_type = build_sized_array_type (list_type, size);
1272 add_field_decl (array_type, "prop_list", &chain);
1273
1274 objc_finish_struct (property_list_t_record, decls);
1275 return property_list_t_record;
1276}
1277
1278/* This routine builds the initializer list to initialize the
1279 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
1280
1281static tree
1282build_v1_property_table_initializer (tree type, tree context)
1283{
1284 tree x;
f1f41a6c 1285 vec<constructor_elt, va_gc> *inits = NULL;
267785bc 1286
1287 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
1288 x = CLASS_PROPERTY_DECL (context);
1289 else
1290 x = IMPL_PROPERTY_DECL (context);
1291
1292 for (; x; x = TREE_CHAIN (x))
1293 {
f1f41a6c 1294 vec<constructor_elt, va_gc> *elemlist = NULL;
267785bc 1295 tree attribute, name_ident = PROPERTY_NAME (x);
1296
6bbb4715 1297 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
267785bc 1298 add_objc_string (name_ident, prop_names_attr));
1299
1300 attribute = objc_v2_encode_prop_attr (x);
6bbb4715 1301 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
267785bc 1302 add_objc_string (attribute, prop_names_attr));
1303
1304 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
1305 objc_build_constructor (type, elemlist));
1306 }
1307
1308 return objc_build_constructor (build_array_type (type, 0),inits);
1309}
1310
1311/* This routine builds the 'struct _prop_list_t' variable declaration and
1312 initializes it with its initializer list. TYPE is 'struct _prop_list_t',
1313 NAME is the internal name of this variable, SIZE is number of properties
1314 for this class and LIST is the initializer list for its 'prop_list' field. */
1315
1316static tree
1317generate_v1_property_table (tree context, tree klass_ctxt)
1318{
1319 tree x, decl, initlist, property_list_template;
1320 bool is_proto = false;
f1f41a6c 1321 vec<constructor_elt, va_gc> *inits = NULL;
267785bc 1322 int init_val, size = 0;
1323 char buf[BUFSIZE];
6bbb4715 1324
267785bc 1325 if (context)
1326 {
1327 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
1328 x = CLASS_PROPERTY_DECL (context);
1329 is_proto = true;
1330 }
1331 else
1332 x = IMPL_PROPERTY_DECL (klass_ctxt);
1333
1334 for (; x; x = TREE_CHAIN (x))
1335 size++;
1336
1337 if (size == 0)
1338 return NULL_TREE;
1339
1340 if (!objc_v1_property_template)
6bbb4715 1341 objc_v1_property_template = build_v1_property_template ();
267785bc 1342
6bbb4715 1343 property_list_template =
1344 build_v1_property_list_template (objc_v1_property_template,
267785bc 1345 size);
1346 initlist = build_v1_property_table_initializer (objc_v1_property_template,
1347 is_proto ? context
1348 : klass_ctxt);
1349
1350 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template));
1351 if (is_proto)
1352 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
1353 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
1354 else
1355 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
1356 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
1357
1358 decl = start_var_decl (property_list_template, buf);
1359 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, init_val));
1360 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1361 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1362 x = objc_build_constructor (TREE_TYPE (decl), inits);
1363 OBJCMETA (decl, objc_meta, meta_proplist);
1364 finish_var_decl (decl, x);
1365 return decl;
1366}
1367
1368static tree
1369generate_v1_protocol_list (tree i_or_p, tree klass_ctxt)
1370{
1371 tree array_type, ptype, refs_decl, lproto, e, plist, attr;
1372 int size = 0;
f1f41a6c 1373 vec<constructor_elt, va_gc> *v = NULL;
267785bc 1374 char buf[BUFSIZE];
1375
1376 switch (TREE_CODE (i_or_p))
1377 {
1378 case CLASS_INTERFACE_TYPE:
1379 case CATEGORY_INTERFACE_TYPE:
1380 plist = CLASS_PROTOCOL_LIST (i_or_p);
1381 break;
1382 case PROTOCOL_INTERFACE_TYPE:
1383 plist = PROTOCOL_LIST (i_or_p);
1384 break;
1385 default:
1386 gcc_unreachable ();
1387 }
1388
1389 /* Compute size. */
1390 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1391 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1392 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1393 size++;
1394
1395 /* Build initializer. */
1396 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1397 e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1398 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1399
1400 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1401 {
1402 tree pval = TREE_VALUE (lproto);
1403
1404 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1405 && PROTOCOL_FORWARD_DECL (pval))
1406 {
1407 tree fwref = PROTOCOL_FORWARD_DECL (pval);
1408 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1409 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1410 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1411 }
1412 }
1413
1414 /* static struct objc_protocol *refs[n]; */
1415 switch (TREE_CODE (i_or_p))
1416 {
1417 case PROTOCOL_INTERFACE_TYPE:
6bbb4715 1418 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
267785bc 1419 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1420 attr = meta_proto_ref;
1421 break;
1422 case CLASS_INTERFACE_TYPE:
6bbb4715 1423 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
267785bc 1424 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1425 attr = meta_clas_prot;
1426 break;
1427 case CATEGORY_INTERFACE_TYPE:
6bbb4715 1428 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
267785bc 1429 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1430 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1431 attr = meta_catg_prot;
1432 break;
1433 default:
1434 gcc_unreachable ();
1435 }
1436
1437 ptype = build_pointer_type (objc_protocol_template);
1438 array_type = build_sized_array_type (ptype, size + 3);
1439 refs_decl = start_var_decl (array_type, buf);
1440
1441 OBJCMETA (refs_decl, objc_meta, attr);
1442 finish_var_decl (refs_decl,
1443 objc_build_constructor (TREE_TYPE (refs_decl), v));
1444
1445 return refs_decl;
1446}
1447
1448static tree
1449build_v1_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1450 tree inst_methods, tree class_methods,
1451 tree protocol_ext)
1452{
1453 tree expr, ttyp;
1454 location_t loc;
f1f41a6c 1455 vec<constructor_elt, va_gc> *inits = NULL;
6bbb4715 1456
267785bc 1457 if (!objc_protocol_extension_template)
6bbb4715 1458 build_v1_objc_protocol_extension_template ();
267785bc 1459
1460 /* TODO: find a better representation of location from the inputs. */
1461 loc = UNKNOWN_LOCATION;
1462 ttyp = build_pointer_type (objc_protocol_extension_template);
1463 /* Instead of jamming the protocol version number into the isa, we pass
1464 either a pointer to the protocol extension - or NULL. */
1465 if (protocol_ext)
1466 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, protocol_ext, 0));
1467 else
1468 expr = convert (ttyp, null_pointer_node);
1469
1470 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1471 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1472 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1473
1474 ttyp = objc_method_proto_list_ptr;
1475 if (inst_methods)
1476 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1477 else
1478 expr = convert (ttyp, null_pointer_node);
1479 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1480
1481 if (class_methods)
1482 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1483 else
1484 expr = convert (ttyp, null_pointer_node);
1485 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1486
1487 return objc_build_constructor (type, inits);
1488}
1489
6bbb4715 1490/* An updated version of generate_protocols () that emit the protocol
267785bc 1491 extension for ABI=1. */
1492
1493/* For each protocol which was referenced either from a @protocol()
1494 expression, or because a class/category implements it (then a
1495 pointer to the protocol is stored in the struct describing the
1496 class/category), we create a statically allocated instance of the
1497 Protocol class. The code is written in such a way as to generate
1498 as few Protocol objects as possible; we generate a unique Protocol
1499 instance for each protocol, and we don't generate a Protocol
1500 instance if the protocol is never referenced (either from a
1501 @protocol() or from a class/category implementation). These
1502 statically allocated objects can be referred to via the static
1503 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1504
1505 The statically allocated Protocol objects that we generate here
1506 need to be fixed up at runtime in order to be used: the 'isa'
1507 pointer of the objects need to be set up to point to the 'Protocol'
1508 class, as known at runtime.
1509
1510 The NeXT runtime fixes up all protocols at program startup time,
1511 before main() is entered. It uses a low-level trick to look up all
1512 those symbols, then loops on them and fixes them up. */
1513
1514/* TODO: finish getting rid of passing stuff around in globals. */
1515
1516static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl;
1517static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl;
1518static GTY(()) tree V1_ProtocolExt_decl;
1519static GTY(()) tree V1_Property_decl;
1520
1521static void
1522generate_v1_protocols (void)
1523{
1524 tree p;
1525
1526 /* If a protocol was directly referenced, pull in indirect references. */
1527 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1528 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1529 generate_protocol_references (PROTOCOL_LIST (p));
1530
1531 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1532 {
1533 tree decl, encoding, initlist, protocol_name_expr;
1534 tree refs_type, refs_decl, refs_expr;
1535 location_t loc;
1536 tree nst_methods = PROTOCOL_NST_METHODS (p);
1537 tree cls_methods = PROTOCOL_CLS_METHODS (p);
1538
1539 /* If protocol wasn't referenced, don't generate any code. */
1540 decl = PROTOCOL_FORWARD_DECL (p);
1541
1542 if (!decl)
1543 continue;
1544
1545 /* Make sure we link in the Protocol class. */
1546 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1547
1548 while (nst_methods)
1549 {
1550 if (! METHOD_ENCODING (nst_methods))
1551 {
1552 encoding = encode_method_prototype (nst_methods);
1553 METHOD_ENCODING (nst_methods) = encoding;
1554 }
1555 nst_methods = TREE_CHAIN (nst_methods);
1556 }
1557
6bbb4715 1558 UOBJC_INSTANCE_METHODS_decl =
267785bc 1559 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1560 "_OBJC_ProtocolInstanceMethods",
1561 meta_proto_nst_meth);
1562
1563 while (cls_methods)
1564 {
1565 if (! METHOD_ENCODING (cls_methods))
1566 {
1567 encoding = encode_method_prototype (cls_methods);
1568 METHOD_ENCODING (cls_methods) = encoding;
1569 }
1570
1571 cls_methods = TREE_CHAIN (cls_methods);
1572 }
1573
6bbb4715 1574 UOBJC_CLASS_METHODS_decl =
267785bc 1575 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1576 "_OBJC_ProtocolClassMethods",
1577 meta_proto_cls_meth);
1578
6bbb4715 1579 /* There should be no optional methods for ABI-0 - but we need to
267785bc 1580 check all this here before the lists are made. */
1581 nst_methods = PROTOCOL_OPTIONAL_NST_METHODS (p);
1582 while (nst_methods)
1583 {
1584 if (! METHOD_ENCODING (nst_methods))
6bbb4715 1585 {
267785bc 1586 encoding = encode_method_prototype (nst_methods);
1587 METHOD_ENCODING (nst_methods) = encoding;
1588 }
1589 nst_methods = TREE_CHAIN (nst_methods);
1590 }
1591
1592 V1_Protocol_OPT_NST_METHODS_decl =
1593 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
1594 "_OBJC_OptionalProtocolInstanceMethods",
1595 meta_proto_nst_meth);
1596
1597 cls_methods = PROTOCOL_OPTIONAL_CLS_METHODS (p);
6bbb4715 1598 while (cls_methods)
267785bc 1599 {
1600 if (! METHOD_ENCODING (cls_methods))
1601 {
1602 encoding = encode_method_prototype (cls_methods);
1603 METHOD_ENCODING (cls_methods) = encoding;
1604 }
1605
1606 cls_methods = TREE_CHAIN (cls_methods);
1607 }
1608
6bbb4715 1609 V1_Protocol_OPT_CLS_METHODS_decl =
267785bc 1610 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
1611 "_OBJC_OptionalProtocolClassMethods",
1612 meta_proto_cls_meth);
1613
1614 if (PROTOCOL_LIST (p))
1615 refs_decl = generate_v1_protocol_list (p, objc_implementation_context);
1616 else
1617 refs_decl = 0;
1618
1619 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1620 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1621 /* TODO: more locations to be fixed up... */
1622 loc = UNKNOWN_LOCATION;
1623 refs_type =
1624 build_pointer_type (build_pointer_type (objc_protocol_template));
1625 if (refs_decl)
1626 refs_expr = convert (refs_type,
1627 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
1628 else
1629 refs_expr = convert (refs_type, null_pointer_node);
6bbb4715 1630
267785bc 1631 if (flag_objc_abi < 1)
1632 {
1633 /* Original ABI. */
6bbb4715 1634 initlist =
267785bc 1635 build_protocol_initializer (TREE_TYPE (decl),
1636 protocol_name_expr, refs_expr,
1637 UOBJC_INSTANCE_METHODS_decl,
1638 UOBJC_CLASS_METHODS_decl);
1639 finish_var_decl (decl, initlist);
1640 continue;
1641 }
1642
1643 /* else - V1 extensions. */
1644
6bbb4715 1645 V1_Property_decl =
267785bc 1646 generate_v1_property_table (p, NULL_TREE);
1647
6bbb4715 1648 V1_ProtocolExt_decl =
1649 generate_v1_objc_protocol_extension (p,
267785bc 1650 V1_Protocol_OPT_NST_METHODS_decl,
6bbb4715 1651 V1_Protocol_OPT_CLS_METHODS_decl,
267785bc 1652 V1_Property_decl);
1653
1654 initlist = build_v1_protocol_initializer (TREE_TYPE (decl),
1655 protocol_name_expr, refs_expr,
1656 UOBJC_INSTANCE_METHODS_decl,
1657 UOBJC_CLASS_METHODS_decl,
1658 V1_ProtocolExt_decl);
1659 finish_var_decl (decl, initlist);
1660 }
1661}
1662
1663static tree
1664generate_dispatch_table (tree chain, const char *name, tree attr)
1665{
1666 tree decl, method_list_template, initlist;
f1f41a6c 1667 vec<constructor_elt, va_gc> *v = NULL;
267785bc 1668 int size;;
1669
1670 if (!chain || !name || !(size = list_length (chain)))
1671 return NULL_TREE;
1672
1673 if (!objc_method_template)
1674 objc_method_template = build_method_template ();
1675
1676 method_list_template = build_method_list_template (objc_method_template,
1677 size);
1678 initlist = build_dispatch_table_initializer (objc_method_template, chain);
1679
1680 decl = start_var_decl (method_list_template, name);
1681
1682 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
6bbb4715 1683 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
267785bc 1684 build_int_cst (integer_type_node, size));
1685 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1686
1687 OBJCMETA (decl, objc_meta, attr);
1688 finish_var_decl (decl,
1689 objc_build_constructor (TREE_TYPE (decl), v));
1690
1691 return decl;
1692}
1693
1694/* Init a category. */
1695static tree
1696build_v1_category_initializer (tree type, tree cat_name, tree class_name,
1697 tree inst_methods, tree class_methods,
1698 tree protocol_list, tree property_list,
1699 location_t loc)
1700{
1701 tree expr, ltyp;
f1f41a6c 1702 vec<constructor_elt, va_gc> *v = NULL;
267785bc 1703
1704 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1705 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1706
1707 ltyp = objc_method_list_ptr;
1708 if (inst_methods)
1709 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1710 else
1711 expr = convert (ltyp, null_pointer_node);
1712 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1713
1714 if (class_methods)
1715 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1716 else
1717 expr = convert (ltyp, null_pointer_node);
1718 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1719
1720 /* protocol_list = */
1721 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1722 if (protocol_list)
1723 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1724 else
1725 expr = convert (ltyp, null_pointer_node);
1726 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1727
1728 if (flag_objc_abi >= 1)
1729 {
1730 int val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template));
1731 expr = build_int_cst (NULL_TREE, val);
1732 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1733 ltyp = objc_prop_list_ptr;
1734 if (property_list)
1735 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
1736 else
1737 expr = convert (ltyp, null_pointer_node);
1738 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1739 }
1740
1741 return objc_build_constructor (type, v);
1742}
1743
dca79b12 1744/* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
267785bc 1745/* TODO: get rid of passing stuff around in globals. */
1746static void
1747generate_v1_category (struct imp_entry *impent)
1748{
1749 tree initlist, cat_name_expr, class_name_expr;
1750 tree protocol_decl, category, cat_decl;
1751 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1752 tree cat = impent->imp_context;
1753 location_t loc;
1754 char buf[BUFSIZE];
1755
1756 cat_decl = impent->class_decl;
1757 loc = DECL_SOURCE_LOCATION (cat_decl);
1758
1759 add_class_reference (CLASS_NAME (cat));
1760 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1761 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1762
1763 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1764
1765 if (category && CLASS_PROTOCOL_LIST (category))
1766 {
1767 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1768 protocol_decl = generate_v1_protocol_list (category, cat);
1769 }
1770 else
1771 protocol_decl = 0;
1772
1773 if (flag_objc_abi >= 1)
1774 V1_Property_decl = generate_v1_property_table (NULL_TREE, cat);
1775 else
1776 V1_Property_decl = NULL_TREE;
1777
1778 if (CLASS_NST_METHODS (cat))
1779 {
1780 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1781 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1782 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1783 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf,
1784 meta_cati_meth);
1785 }
1786
1787 if (CLASS_CLS_METHODS (cat))
1788 {
1789 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1790 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1791 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1792 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf,
1793 meta_catc_meth);
1794 }
1795
1796 initlist = build_v1_category_initializer (TREE_TYPE (cat_decl),
1797 cat_name_expr, class_name_expr,
1798 inst_methods, class_methods,
1799 protocol_decl, V1_Property_decl,
1800 loc);
1801
1802 finish_var_decl (cat_decl, initlist);
1803 impent->class_decl = cat_decl;
1804}
1805
dca79b12 1806/* This routine builds the class extension used by v1 NeXT. */
267785bc 1807
1808static tree
1809generate_objc_class_ext (tree property_list, tree context)
1810{
1811 tree decl, expr, ltyp;
1812 tree weak_ivar_layout_tree;
1813 int size;
1814 location_t loc;
f1f41a6c 1815 vec<constructor_elt, va_gc> *v = NULL;
267785bc 1816 char buf[BUFSIZE];
1817
1818 /* TODO: pass the loc in or find it from args. */
1819 loc = UNKNOWN_LOCATION;
1820
6bbb4715 1821 /* const char *weak_ivar_layout
267785bc 1822 TODO: Figure the ivar layouts out... */
1823 weak_ivar_layout_tree = NULL_TREE;
1824
1825 if (!property_list && !weak_ivar_layout_tree)
1826 return NULL_TREE;
1827
1828 if (!objc_class_ext_template)
1829 build_objc_class_ext_template ();
1830
1831 /* uint32_t size */
1832 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template));
1833 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1834
1835 ltyp = const_string_type_node;
1836 if (weak_ivar_layout_tree)
1837 expr = convert (ltyp, weak_ivar_layout_tree);
1838 else
1839 expr = convert (ltyp, null_pointer_node);
1840 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
6bbb4715 1841
267785bc 1842 /* struct _prop_list_t *properties; */
1843 ltyp = objc_prop_list_ptr;
1844 if (property_list)
1845 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
1846 else
1847 expr = convert (ltyp, null_pointer_node);
1848 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1849
1850 snprintf (buf, BUFSIZE, "_OBJC_ClassExt_%s",
1851 IDENTIFIER_POINTER (CLASS_NAME (context)));
1852 decl = start_var_decl (objc_class_ext_template, buf);
1853 expr = objc_build_constructor (TREE_TYPE (decl), v);
1854 OBJCMETA (decl, objc_meta, meta_class_extension);
1855 finish_var_decl (decl, expr);
1856 return decl;
1857}
1858
1859/* struct _objc_class {
1860 struct objc_class *isa;
1861 struct objc_class *super_class;
1862 char *name;
1863 long version;
1864 long info;
1865 long instance_size;
1866 struct objc_ivar_list *ivars;
1867 struct objc_method_list *methods;
1868 struct objc_cache *cache;
1869 struct objc_protocol_list *protocols;
1870 #if ABI >= 1
1871 const char *ivar_layout;
1872 struct _objc_class_ext *ext;
1873 #else
1874 void *sel_id;
1875 void *gc_object_type;
1876 #endif
dca79b12 1877 }; */
267785bc 1878
1879static tree
1880build_v1_shared_structure_initializer (tree type, tree isa, tree super,
1881 tree name, tree size, int status,
1882 tree dispatch_table, tree ivar_list,
1883 tree protocol_list, tree class_ext)
1884{
1885 tree expr, ltyp;
1886 location_t loc;
f1f41a6c 1887 vec<constructor_elt, va_gc> *v = NULL;
267785bc 1888
1889 /* TODO: fish the location out of the input data. */
1890 loc = UNKNOWN_LOCATION;
1891
1892 /* isa = */
1893 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1894
1895 /* super_class = */
1896 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1897
1898 /* name = */
1899 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1900
1901 /* version = */
1902 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1903 build_int_cst (long_integer_type_node, 0));
1904
1905 /* info = */
1906 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1907 build_int_cst (long_integer_type_node, status));
1908
1909 /* instance_size = */
1910 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1911 convert (long_integer_type_node, size));
1912
1913 /* objc_ivar_list = */
1914 ltyp = objc_ivar_list_ptr;
1915 if (ivar_list)
1916 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivar_list, 0));
1917 else
1918 expr = convert (ltyp, null_pointer_node);
1919 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1920
1921 /* objc_method_list = */
1922 ltyp = objc_method_list_ptr;
1923 if (dispatch_table)
1924 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, dispatch_table, 0));
1925 else
1926 expr = convert (ltyp, null_pointer_node);
1927 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1928
6bbb4715 1929 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
267785bc 1930 get_identifier ("objc_cache")));
1931 /* method_cache = */
1932 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
1933
1934 /* protocol_list = */
1935 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1936 if (protocol_list)
1937 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1938 else
1939 expr = convert (ltyp, null_pointer_node);
1940 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1941
1942 if (flag_objc_abi >= 1)
1943 {
1944 /* TODO: figure out the ivar_layout stuff. */
1945 expr = convert (const_string_type_node, null_pointer_node);
1946 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1947 if (!objc_class_ext_template)
1948 build_objc_class_ext_template ();
1949 ltyp = build_pointer_type (objc_class_ext_template);
1950 if (class_ext)
1951 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_ext, 0));
1952 else
1953 expr = convert (ltyp, null_pointer_node);
1954 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1955 }
1956 else
1957 {
1958 /* sel_id = NULL */
1959 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
1960
1961 /* gc_object_type = NULL */
1962 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
1963 }
1964 return objc_build_constructor (type, v);
1965}
1966
1967static tree
1968generate_ivars_list (tree chain, const char *name, tree attr)
1969{
1970 tree initlist, ivar_list_template, decl;
1971 int size;
f1f41a6c 1972 vec<constructor_elt, va_gc> *inits = NULL;
267785bc 1973
1974 if (!chain)
1975 return NULL_TREE;
1976
1977 if (!objc_ivar_template)
1978 objc_ivar_template = build_ivar_template ();
1979
1980 size = ivar_list_length (chain);
1981
1982 generating_instance_variables = 1;
1983 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1984 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1985 generating_instance_variables = 0;
1986
1987 decl = start_var_decl (ivar_list_template, name);
1988
1989 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1990 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1991
1992 OBJCMETA (decl, objc_meta, attr);
1993 finish_var_decl (decl,
1994 objc_build_constructor (TREE_TYPE (decl), inits));
1995
1996 return decl;
1997}
1998
1999/* static struct objc_class _OBJC_METACLASS_Foo={ ... };
dca79b12 2000 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
267785bc 2001
2002static void
2003generate_v1_class_structs (struct imp_entry *impent)
2004{
2005 tree name_expr, super_expr, root_expr, class_decl, meta_decl;
2006 tree my_root_id, my_super_id;
2007 tree cast_type, initlist, protocol_decl;
2008 tree class_ext_decl = NULL_TREE, props = NULL_TREE;
2009 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2010 tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
2011 int cls_flags;
2012 location_t loc;
2013 char buf[BUFSIZE];
6bbb4715 2014
267785bc 2015/* objc_implementation_context = impent->imp_context;
2016 implementation_template = impent->imp_template;*/
2017 class_decl = impent->class_decl;
2018 meta_decl = impent->meta_decl;
2019 cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
6bbb4715 2020
267785bc 2021 loc = DECL_SOURCE_LOCATION (impent->class_decl);
6bbb4715 2022
267785bc 2023 if (flag_objc_abi >= 1)
2024 {
2025 /* ABI=1 additions. */
2026 props = generate_v1_property_table (NULL_TREE, impent->imp_context);
2027 class_ext_decl = generate_objc_class_ext (props, impent->imp_context);
2028 }
2029
2030 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
2031 if (my_super_id)
2032 {
2033 add_class_reference (my_super_id);
2034
2035 /* Compute "my_root_id" - this is required for code generation.
2036 the "isa" for all meta class structures points to the root of
2037 the inheritance hierarchy (e.g. "__Object")... */
2038 my_root_id = my_super_id;
2039 do
2040 {
2041 tree my_root_int = lookup_interface (my_root_id);
2042
2043 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
2044 my_root_id = CLASS_SUPER_NAME (my_root_int);
2045 else
2046 break;
2047 }
2048 while (1);
2049 super_expr = add_objc_string (my_super_id, class_names);
2050 }
2051 else
2052 {
2053 /* No super class. */
2054 my_root_id = CLASS_NAME (impent->imp_template);
2055 super_expr = null_pointer_node;
2056 }
2057
2058 /* Install class `isa' and `super' pointers at runtime. */
2059 cast_type = build_pointer_type (objc_class_template);
2060 super_expr = build_c_cast (loc, cast_type, super_expr);
2061
2062 root_expr = add_objc_string (my_root_id, class_names);
2063 root_expr = build_c_cast (loc, cast_type, root_expr);
2064
2065 if (CLASS_PROTOCOL_LIST (impent->imp_template))
2066 {
2067 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
2068 protocol_decl = generate_v1_protocol_list (impent->imp_template,
2069 impent->imp_context);
2070 }
2071 else
2072 protocol_decl = NULL_TREE;
2073
2074 if (CLASS_CLS_METHODS (impent->imp_context))
2075 {
2076 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
2077 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2078 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
2079 buf, meta_clac_meth);
2080 }
2081
2082 if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
2083 && (chain = TYPE_FIELDS (objc_class_template)))
2084 {
2085 snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
2086 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2087 class_ivars = generate_ivars_list (chain, buf, meta_clac_vars);
2088 }
2089 /* TODO: get rid of hidden passing of stuff in globals. */
2090 /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */
2091
2092 name_expr = add_objc_string (CLASS_NAME (impent->imp_template), class_names);
2093
2094 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2095
6bbb4715 2096 initlist = build_v1_shared_structure_initializer
267785bc 2097 (TREE_TYPE (meta_decl),
2098 root_expr, super_expr, name_expr,
2099 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
2100 CLS_META, class_methods, class_ivars,
2101 protocol_decl, NULL_TREE);
2102
2103 finish_var_decl (meta_decl, initlist);
2104 impent->meta_decl = meta_decl;
2105
2106 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2107 if (CLASS_NST_METHODS (impent->imp_context))
2108 {
2109 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
2110 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2111 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
2112 buf, meta_clai_meth);
2113 }
2114
2115 if ((chain = CLASS_IVARS (impent->imp_template)))
2116 {
2117 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
2118 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2119 inst_ivars = generate_ivars_list (chain, buf, meta_clai_vars);
2120 }
2121
2122 initlist = build_v1_shared_structure_initializer
2123 (TREE_TYPE (class_decl),
2124 build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
2125 super_expr, name_expr,
6bbb4715 2126 convert (integer_type_node,
267785bc 2127 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent->imp_template))),
2128 CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
2129 protocol_decl, class_ext_decl);
2130
2131 finish_var_decl (class_decl, initlist);
2132 impent->class_decl = class_decl;
2133}
2134
2135/* --- Output NeXT V1 Metadata --- */
2136
2137/* Create the initial value for the `defs' field of _objc_symtab.
2138 This is a CONSTRUCTOR. */
2139
2140static tree
2141init_def_list (tree type)
2142{
2143 tree expr;
2144 location_t loc;
2145 struct imp_entry *impent;
f1f41a6c 2146 vec<constructor_elt, va_gc> *v = NULL;
267785bc 2147
2148 if (imp_count)
2149 for (impent = imp_list; impent; impent = impent->next)
2150 {
2151 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2152 {
2153 loc = DECL_SOURCE_LOCATION (impent->class_decl);
2154 expr = build_unary_op (loc,
2155 ADDR_EXPR, impent->class_decl, 0);
2156 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2157 }
2158 }
2159
2160 if (cat_count)
2161 for (impent = imp_list; impent; impent = impent->next)
2162 {
2163 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2164 {
2165 loc = DECL_SOURCE_LOCATION (impent->class_decl);
2166 expr = build_unary_op (loc,
2167 ADDR_EXPR, impent->class_decl, 0);
2168 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2169 }
2170 }
2171
2172 return objc_build_constructor (type, v);
2173}
2174
2175/* Take care of defining and initializing _OBJC_SYMBOLS. */
2176
2177/* Predefine the following data type:
2178
2179 struct _objc_symtab
2180 {
2181 long sel_ref_cnt;
2182 SEL *refs;
2183 short cls_def_cnt;
2184 short cat_def_cnt;
2185 void *defs[cls_def_cnt + cat_def_cnt];
2186 }; */
2187
2188static void
2189build_objc_symtab_template (void)
2190{
2191 tree fields, *chain = NULL;
2192
2193 objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
2194
2195 /* long sel_ref_cnt; */
2196 fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
2197
2198 /* SEL *refs; */
2199 add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
2200
2201 /* short cls_def_cnt; */
2202 add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
2203
2204 /* short cat_def_cnt; */
2205 add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
2206
2207 if (imp_count || cat_count)
2208 {
2209 /* void *defs[imp_count + cat_count (+ 1)]; */
2210 /* NB: The index is one less than the size of the array. */
2211 int index = imp_count + cat_count;
2212 tree array_type = build_sized_array_type (ptr_type_node, index);
2213 add_field_decl (array_type, "defs", &chain);
2214 }
2215
2216 objc_finish_struct (objc_symtab_template, fields);
2217}
2218/* Construct the initial value for all of _objc_symtab. */
2219
2220static tree
2221init_objc_symtab (tree type)
2222{
f1f41a6c 2223 vec<constructor_elt, va_gc> *v = NULL;
267785bc 2224
2225 /* sel_ref_cnt = { ..., 5, ... } */
2226
2227 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2228 build_int_cst (long_integer_type_node, 0));
2229
2230 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2231
6bbb4715 2232 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
267785bc 2233 convert (build_pointer_type (objc_selector_type),
2234 integer_zero_node));
2235
2236 /* cls_def_cnt = { ..., 5, ... } */
2237
6bbb4715 2238 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
267785bc 2239 build_int_cst (short_integer_type_node, imp_count));
2240
2241 /* cat_def_cnt = { ..., 5, ... } */
2242
6bbb4715 2243 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
267785bc 2244 build_int_cst (short_integer_type_node, cat_count));
2245
2246 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2247
2248 if (imp_count || cat_count)
2249 {
2250 tree field = TYPE_FIELDS (type);
2251 field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2252
2253 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2254 }
2255
2256 return objc_build_constructor (type, v);
2257}
2258
2259/* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2260 and initialized appropriately. */
2261
2262static void
2263generate_objc_symtab_decl (void)
2264{
2265 build_objc_symtab_template ();
2266 UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_Symbols");
2267 /* Allow the runtime to mark meta-data such that it can be assigned to target
2268 specific sections by the back-end. */
2269 OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_symtab);
2270 finish_var_decl (UOBJC_SYMBOLS_decl,
2271 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2272}
2273
ff6624bc 2274/* Any target implementing NeXT ObjC m32 ABI has to ensure that objects
2275 refer to, and define, symbols that enforce linkage of classes into the
2276 executable image, preserving unix archive semantics.
2277
2278 At present (4.8), the only targets implementing this are Darwin; these
2279 use top level asms to implement a scheme (see config/darwin-c.c). The
2280 latter method is a hack, but compatible with LTO see also PR48109 for
2281 further discussion and other possible methods. */
267785bc 2282
2283static void
ff6624bc 2284handle_next_class_ref (tree chain ATTRIBUTE_UNUSED)
267785bc 2285{
ff6624bc 2286 if (targetcm.objc_declare_unresolved_class_reference)
2287 {
2288 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
2289 char *string = (char *) alloca (strlen (name) + 30);
2290 sprintf (string, ".objc_class_name_%s", name);
2291 targetcm.objc_declare_unresolved_class_reference (string);
2292 }
267785bc 2293}
2294
2295static void
ff6624bc 2296handle_next_impent (struct imp_entry *impent ATTRIBUTE_UNUSED)
267785bc 2297{
ff6624bc 2298 if (targetcm.objc_declare_class_definition)
267785bc 2299 {
ff6624bc 2300 char buf[BUFSIZE];
267785bc 2301
ff6624bc 2302 switch (TREE_CODE (impent->imp_context))
2303 {
2304 case CLASS_IMPLEMENTATION_TYPE:
2305 snprintf (buf, BUFSIZE, ".objc_class_name_%s",
2306 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2307 break;
2308 case CATEGORY_IMPLEMENTATION_TYPE:
2309 snprintf (buf, BUFSIZE, "*.objc_category_name_%s_%s",
2310 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
2311 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
2312 break;
2313 default:
2314 return;
2315 }
2316 targetcm.objc_declare_class_definition (buf);
2317 }
267785bc 2318}
2319
2320static void
2321generate_classref_translation_entry (tree chain)
2322{
2323 tree expr, decl, type;
2324
2325 decl = TREE_PURPOSE (chain);
2326 type = TREE_TYPE (decl);
2327
2328 expr = add_objc_string (TREE_VALUE (chain), class_names);
2329 expr = convert (type, expr); /* cast! */
2330
2331 /* This is a class reference. It is re-written by the runtime,
2332 but will be optimized away unless we force it. */
2333 DECL_PRESERVE_P (decl) = 1;
2334 OBJCMETA (decl, objc_meta, meta_class_reference);
2335 finish_var_decl (decl, expr);
2336 return;
2337}
2338
267785bc 2339static void
2340objc_generate_v1_next_metadata (void)
2341{
2342 struct imp_entry *impent;
2343 tree chain, attr;
2344 long vers;
2345
dca79b12 2346 /* FIXME: Make sure that we generate no metadata if there is nothing
2347 to put into it. */
2348
267785bc 2349 if (objc_static_instances)
2350 gcc_unreachable (); /* Not for NeXT */
2351
2352 build_metadata_templates ();
2353 objc_implementation_context =
2354 implementation_template =
2355 UOBJC_CLASS_decl =
2356 UOBJC_METACLASS_decl = NULL_TREE;
2357
2358 for (impent = imp_list; impent; impent = impent->next)
2359 {
2360
2361 /* If -gen-decls is present, Dump the @interface of each class.
2362 TODO: Dump the classes in the order they were found, rather than in
2363 reverse order as we are doing now. */
2364 if (flag_gen_declaration)
2365 dump_interface (gen_declaration_file, impent->imp_context);
2366
2367 /* all of the following reference the string pool... */
2368 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2369 generate_v1_class_structs (impent);
2370 else
2371 generate_v1_category (impent);
2372 }
2373
2374 /* If we are using an array of selectors, we must always
2375 finish up the array decl even if no selectors were used. */
2376 build_next_selector_translation_table ();
2377
2378 if (protocol_chain)
2379 generate_v1_protocols ();
2380
2381 /* Pass summary information to the runtime. */
2382 if (imp_count || cat_count)
2383 generate_objc_symtab_decl ();
2384
2385 vers = OBJC_VERSION;
2386 attr = build_tree_list (objc_meta, meta_modules);
2387 build_module_descriptor (vers, attr);
2388
267785bc 2389 /* Dump the class references. This forces the appropriate classes
2390 to be linked into the executable image, preserving unix archive
ff6624bc 2391 semantics. */
267785bc 2392 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2393 {
2394 handle_next_class_ref (chain);
2395 if (TREE_PURPOSE (chain))
2396 generate_classref_translation_entry (chain);
2397 }
2398
2399 for (impent = imp_list; impent; impent = impent->next)
2400 handle_next_impent (impent);
2401
2402 /* Emit the strings tables. */
2403 generate_strings ();
2404}
2405
2406/* --- exceptions stuff --- */
2407
2408/* Predefine the following data type:
2409
2410 struct _objc_exception_data
2411 {
2412 int buf[OBJC_JBLEN];
2413 void *pointers[4];
2414 }; */
2415
2416/* The following yuckiness should prevent users from having to #include
2417 <setjmp.h> in their code... */
2418
2419/* Define to a harmless positive value so the below code doesn't die. */
2420#ifndef OBJC_JBLEN
2421#define OBJC_JBLEN 18
2422#endif
2423
2424static void
2425build_next_objc_exception_stuff (void)
2426{
2427 tree decls, temp_type, *chain = NULL;
2428
2429 objc_exception_data_template
2430 = objc_start_struct (get_identifier (UTAG_EXCDATA));
2431
2432 /* int buf[OBJC_JBLEN]; */
2433
2434 temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
2435 decls = add_field_decl (temp_type, "buf", &chain);
2436
2437 /* void *pointers[4]; */
2438
2439 temp_type = build_sized_array_type (ptr_type_node, 4);
2440 add_field_decl (temp_type, "pointers", &chain);
2441
2442 objc_finish_struct (objc_exception_data_template, decls);
2443
2444 /* int _setjmp(...); */
2445 /* If the user includes <setjmp.h>, this shall be superseded by
2446 'int _setjmp(jmp_buf);' */
2447 temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
2448 objc_setjmp_decl
2449 = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
2450
2451 /* id objc_exception_extract(struct _objc_exception_data *); */
2452 temp_type
2453 = build_function_type_list (objc_object_type,
2454 build_pointer_type (objc_exception_data_template),
2455 NULL_TREE);
2456 objc_exception_extract_decl
2457 = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
2458 NULL_TREE);
2459 /* void objc_exception_try_enter(struct _objc_exception_data *); */
2460 /* void objc_exception_try_exit(struct _objc_exception_data *); */
2461 temp_type
2462 = build_function_type_list (void_type_node,
2463 build_pointer_type (objc_exception_data_template),
2464 NULL_TREE);
2465 objc_exception_try_enter_decl
2466 = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
2467 NULL_TREE);
2468 objc_exception_try_exit_decl
2469 = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
2470 NULL_TREE);
2471
2472 /* int objc_exception_match(id, id); */
2473 temp_type
2474 = build_function_type_list (integer_type_node,
2475 objc_object_type, objc_object_type, NULL_TREE);
2476 objc_exception_match_decl
2477 = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
2478 NULL_TREE);
2479
2480 /* id objc_assign_ivar (id, id, unsigned int); */
2481 /* id objc_assign_ivar_Fast (id, id, unsigned int)
2482 __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2483 temp_type
2484 = build_function_type_list (objc_object_type,
2485 objc_object_type,
2486 objc_object_type,
2487 unsigned_type_node,
2488 NULL_TREE);
2489 objc_assign_ivar_decl
2490 = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
2491 NULL, NULL_TREE);
2492#ifdef OFFS_ASSIGNIVAR_FAST
2493 objc_assign_ivar_fast_decl
2494 = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
2495 NOT_BUILT_IN, NULL, NULL_TREE);
2496 DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
2497 = tree_cons (get_identifier ("hard_coded_address"),
2498 build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
2499 NULL_TREE);
2500#else
2501 /* Default to slower ivar method. */
2502 objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
2503#endif
2504
2505 /* id objc_assign_global (id, id *); */
2506 /* id objc_assign_strongCast (id, id *); */
2507 temp_type = build_function_type_list (objc_object_type,
2508 objc_object_type,
2509 build_pointer_type (objc_object_type),
2510 NULL_TREE);
2511 objc_assign_global_decl
2512 = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
2513 NULL_TREE);
2514 objc_assign_strong_cast_decl
2515 = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
2516 NULL_TREE);
2517}
2518
2519/* --- NeXT V1 SJLJ Exceptions --- */
2520
2521/* Build "objc_exception_try_exit(&_stack)". */
2522
2523static tree
2524next_sjlj_build_try_exit (struct objc_try_context **ctcp)
2525{
2526 tree t;
2527 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2528 t = tree_cons (NULL, t, NULL);
2529 t = build_function_call (input_location,
2530 objc_exception_try_exit_decl, t);
2531 return t;
2532}
2533
2534/* Build
2535 objc_exception_try_enter (&_stack);
2536 if (_setjmp(&_stack.buf))
2537 ;
2538 else
2539 ;
2540 Return the COND_EXPR. Note that the THEN and ELSE fields are left
2541 empty, ready for the caller to fill them in. */
2542
2543static tree
2544next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp)
2545{
2546 tree t, enter, sj, cond;
2547
2548 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2549 t = tree_cons (NULL, t, NULL);
2550 enter = build_function_call (input_location,
2551 objc_exception_try_enter_decl, t);
2552
2553 t = objc_build_component_ref ((*ctcp)->stack_decl,
2554 get_identifier ("buf"));
2555 t = build_fold_addr_expr_loc (input_location, t);
2556#ifdef OBJCPLUS
2557 /* Convert _setjmp argument to type that is expected. */
2558 if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
2559 t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
2560 else
2561 t = convert (ptr_type_node, t);
2562#else
2563 t = convert (ptr_type_node, t);
2564#endif
2565 t = tree_cons (NULL, t, NULL);
2566 sj = build_function_call (input_location,
2567 objc_setjmp_decl, t);
2568
2569 cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
2570 cond = c_common_truthvalue_conversion (input_location, cond);
2571
2572 return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
2573}
2574
2575/* Build:
2576
dca79b12 2577 DECL = objc_exception_extract(&_stack); */
267785bc 2578
2579static tree
2580next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl)
2581{
2582 tree t;
2583
2584 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2585 t = tree_cons (NULL, t, NULL);
2586 t = build_function_call (input_location,
2587 objc_exception_extract_decl, t);
2588 t = convert (TREE_TYPE (decl), t);
2589 t = build2 (MODIFY_EXPR, void_type_node, decl, t);
2590
2591 return t;
2592}
2593
2594/* Build
2595 if (objc_exception_match(obj_get_class(TYPE), _caught)
2596 BODY
2597 else if (...)
2598 ...
2599 else
2600 {
2601 _rethrow = _caught;
2602 objc_exception_try_exit(&_stack);
2603 }
2604 from the sequence of CATCH_EXPRs in the current try context. */
2605
2606static tree
2607next_sjlj_build_catch_list (struct objc_try_context **ctcp)
2608{
2609 tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list);
2610 tree catch_seq, t;
2611 tree *last = &catch_seq;
2612 bool saw_id = false;
2613
2614 for (; !tsi_end_p (i); tsi_next (&i))
2615 {
2616 tree stmt = tsi_stmt (i);
2617 tree type = CATCH_TYPES (stmt);
2618 tree body = CATCH_BODY (stmt);
2619
2620 if (type != error_mark_node
2621 && objc_is_object_id (TREE_TYPE (type)))
2622 {
2623 *last = body;
2624 saw_id = true;
2625 break;
2626 }
2627 else
2628 {
2629 tree args, cond;
2630
2631 if (type == error_mark_node)
2632 cond = error_mark_node;
2633 else
2634 {
2635 args = tree_cons (NULL, (*ctcp)->caught_decl, NULL);
2636 t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
2637 args = tree_cons (NULL, t, args);
2638 t = build_function_call (input_location,
2639 objc_exception_match_decl, args);
2640 cond = c_common_truthvalue_conversion (input_location, t);
2641 }
2642 t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
2643 SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
2644
2645 *last = t;
2646 last = &COND_EXPR_ELSE (t);
2647 }
2648 }
2649
2650 if (!saw_id)
2651 {
2652 t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl,
2653 (*ctcp)->caught_decl);
2654 SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2655 append_to_statement_list (t, last);
2656
2657 t = next_sjlj_build_try_exit (ctcp);
2658 SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2659 append_to_statement_list (t, last);
2660 }
2661
2662 return catch_seq;
2663}
2664
2665/* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2666 exception handling. We aim to build:
2667
2668 {
2669 struct _objc_exception_data _stack;
2670 id _rethrow = 0;
2671 try
2672 {
2673 objc_exception_try_enter (&_stack);
2674 if (_setjmp(&_stack.buf))
2675 {
2676 id _caught = objc_exception_extract(&_stack);
2677 objc_exception_try_enter (&_stack);
2678 if (_setjmp(&_stack.buf))
2679 _rethrow = objc_exception_extract(&_stack);
2680 else
2681 CATCH-LIST
2682 }
2683 else
2684 TRY-BLOCK
2685 }
2686 finally
2687 {
2688 if (!_rethrow)
2689 objc_exception_try_exit(&_stack);
2690 FINALLY-BLOCK
2691 if (_rethrow)
2692 objc_exception_throw(_rethrow);
2693 }
2694 }
2695
2696 If CATCH-LIST is empty, we can omit all of the block containing
2697 "_caught" except for the setting of _rethrow. Note the use of
2698 a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2699 but handles goto and other exits from the block. */
2700
2701static tree
2702next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp)
2703{
2704 tree rethrow_decl, stack_decl, t;
2705 tree catch_seq, try_fin, bind;
2706 struct objc_try_context *cur_try_context = *ctcp;
2707
2708 /* Create the declarations involved. */
2709 t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
2710 stack_decl = objc_create_temporary_var (t, NULL);
2711 cur_try_context->stack_decl = stack_decl;
2712
2713 rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
2714 cur_try_context->rethrow_decl = rethrow_decl;
2715 TREE_CHAIN (rethrow_decl) = stack_decl;
2716
2717 /* Build the outermost variable binding level. */
2718 bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
2719 SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
2720 TREE_SIDE_EFFECTS (bind) = 1;
2721
2722 /* Initialize rethrow_decl. */
2723 t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
2724 convert (objc_object_type, null_pointer_node));
2725 SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2726 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
2727
2728 /* Build the outermost TRY_FINALLY_EXPR. */
2729 try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
2730 SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
2731 TREE_SIDE_EFFECTS (try_fin) = 1;
2732 append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
2733
2734 /* Create the complete catch sequence. */
2735 if (cur_try_context->catch_list)
2736 {
2737 tree caught_decl = objc_build_exc_ptr (ctcp);
2738 catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
2739 TREE_SIDE_EFFECTS (catch_seq) = 1;
2740
2741 t = next_sjlj_build_exc_extract (ctcp, caught_decl);
2742 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2743
2744 t = next_sjlj_build_enter_and_setjmp (ctcp);
2745 COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2746 COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp);
2747 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2748 }
2749 else
2750 catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2751 SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
2752
2753 /* Build the main register-and-try if statement. */
2754 t = next_sjlj_build_enter_and_setjmp (ctcp);
2755 SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2756 COND_EXPR_THEN (t) = catch_seq;
2757 COND_EXPR_ELSE (t) = cur_try_context->try_body;
2758 TREE_OPERAND (try_fin, 0) = t;
2759
2760 /* Build the complete FINALLY statement list. */
2761 t = next_sjlj_build_try_exit (ctcp);
2762 t = build_stmt (input_location, COND_EXPR,
6bbb4715 2763 c_common_truthvalue_conversion
267785bc 2764 (input_location, rethrow_decl),
2765 NULL, t);
2766 SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
2767 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2768
2769 append_to_statement_list (cur_try_context->finally_body,
2770 &TREE_OPERAND (try_fin, 1));
2771
2772 t = tree_cons (NULL, rethrow_decl, NULL);
2773 t = build_function_call (input_location,
2774 objc_exception_throw_decl, t);
2775 t = build_stmt (input_location, COND_EXPR,
6bbb4715 2776 c_common_truthvalue_conversion (input_location,
267785bc 2777 rethrow_decl),
2778 t, NULL);
2779 SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
2780 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2781
2782 return bind;
2783}
2784
2785/* We do not expect this to be used at the moment.
2786 If (a) it is possible to implement unwinder exceptions.
2787 (b) we do it... then it might be possibly useful.
2788*/
2789static GTY(()) tree objc_eh_personality_decl;
2790
2791static tree
2792objc_eh_runtime_type (tree type)
2793{
2794 tree ident, eh_id, decl, str;
2795
2796 gcc_unreachable ();
2797 if (type == error_mark_node)
2798 {
2799 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2800 to prevent an ICE. Note that we know that the compiler will
2801 terminate with an error and this 'ErrorMarkNode' class name will
2802 never be actually used. */
2803 ident = get_identifier ("ErrorMarkNode");
2804 goto make_err_class;
2805 }
2806
2807 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2808 {
2809 ident = get_identifier ("id");
2810 goto make_err_class;
2811 }
2812
2813 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2814 {
2815#ifdef OBJCPLUS
2816 /* This routine is also called for c++'s catch clause; in which case,
2817 we use c++'s typeinfo decl. */
2818 return build_eh_type_type (type);
2819#else
2820 error ("non-objective-c type '%T' cannot be caught", type);
2821 ident = get_identifier ("ErrorMarkNode");
2822 goto make_err_class;
2823#endif
2824 }
2825 else
2826 ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2827
2828make_err_class:
2829 /* If this class was already referenced, then it will be output during
2830 meta-data emission, so we don't need to do it here. */
2831 decl = get_objc_string_decl (ident, class_names);
2832 eh_id = add_objc_string (ident, class_names);
2833 if (!decl)
2834 {
2835 /* Not found ... so we need to build it - from the freshly-entered id. */
2836 decl = get_objc_string_decl (ident, class_names);
2837 str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2838 IDENTIFIER_POINTER (ident));
2839 /* We have to finalize this var here, because this might be called after
2840 all the other metadata strings have been emitted. */
2841 finish_var_decl (decl, str);
2842 }
2843 return eh_id;
2844}
2845
1583f3af 2846/* For NeXT ABI 0 and 1, the personality routines are just those of the
2847 underlying language. */
2848
267785bc 2849static tree
2850objc_eh_personality (void)
2851{
2852 if (!objc_eh_personality_decl)
2853#ifndef OBJCPLUS
1583f3af 2854 objc_eh_personality_decl = build_personality_function ("gcc");
267785bc 2855#else
2856 objc_eh_personality_decl = build_personality_function ("gxx");
2857#endif
2858 return objc_eh_personality_decl;
2859}
2860
2861/* --- interfaces --- */
2862
2863static tree
2864build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2865{
2866 tree t;
f1f41a6c 2867 vec<tree, va_gc> *parms;
2868 vec_alloc (parms, 1);
267785bc 2869 /* A throw is just a call to the runtime throw function with the
2870 object as a parameter. */
f1f41a6c 2871 parms->quick_push (throw_expr);
ec761d5a 2872 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms,
2873 NULL);
f1f41a6c 2874 vec_free (parms);
267785bc 2875 return add_stmt (t);
2876}
2877
2878/* Build __builtin_eh_pointer, or the moral equivalent. In the case
2879 of Darwin, we'll arrange for it to be initialized (and associated
2880 with a binding) later. */
2881
2882static tree
2883objc_build_exc_ptr (struct objc_try_context **cur_try_context)
2884{
2885 if (flag_objc_sjlj_exceptions)
2886 {
2887 tree var = (*cur_try_context)->caught_decl;
2888 if (!var)
2889 {
2890 var = objc_create_temporary_var (objc_object_type, NULL);
2891 (*cur_try_context)->caught_decl = var;
2892 }
2893 return var;
2894 }
2895 else
2896 {
2897 tree t;
b9a16870 2898 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
267785bc 2899 t = build_call_expr (t, 1, integer_zero_node);
2900 return fold_convert (objc_object_type, t);
2901 }
2902}
2903
6bbb4715 2904static tree
267785bc 2905begin_catch (struct objc_try_context **cur_try_context, tree type,
2906 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2907{
2908 tree t;
2909 /* Record the data for the catch in the try context so that we can
2910 finalize it later. We treat ellipsis the same way as catching
2911 with 'id xyz'. */
2912 t = build_stmt (input_location, CATCH_EXPR, type, compound);
2913 (*cur_try_context)->current_catch = t;
2914
2915 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
2916 t = objc_build_exc_ptr (cur_try_context);
2917 t = convert (TREE_TYPE (decl), t);
2918 return build2 (MODIFY_EXPR, void_type_node, decl, t);
2919}
2920
6bbb4715 2921static void
267785bc 2922finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2923{
2924 append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2925}
2926
6bbb4715 2927static tree
267785bc 2928finish_try_stmt (struct objc_try_context **cur_try_context)
2929{
2930 tree stmt;
2931 struct objc_try_context *c = *cur_try_context;
2932 /* If we're doing Darwin setjmp exceptions, build the big nasty. */
2933 if (flag_objc_sjlj_exceptions)
2934 {
2935 bool save = in_late_binary_op;
2936 in_late_binary_op = true;
2937 if (!c->finally_body)
2938 {
2939 c->finally_locus = input_location;
2940 c->end_finally_locus = input_location;
2941 }
2942 stmt = next_sjlj_build_try_catch_finally (cur_try_context);
2943 in_late_binary_op = save;
2944 }
2945 else
2946 /* This doesn't happen at the moment... but maybe one day... */
2947 {
2948 /* Otherwise, nest the CATCH inside a FINALLY. */
2949 stmt = c->try_body;
2950 if (c->catch_list)
2951 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2952 if (c->finally_body)
2953 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2954 }
2955 return stmt;
2956}
2957
2958#include "gt-objc-objc-next-runtime-abi-01.h"