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