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