comparison gcc/objc/objc-next-runtime-abi-01.c @ 111:04ced10e8804

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