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