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