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