1 /* Next Runtime (ABI-0/1) private.
2 Copyright (C) 2011-2023 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)
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). */
28 #include "coretypes.h"
30 #include "stringpool.h"
34 #include "cp/cp-tree.h"
39 #include "langhooks.h"
40 #include "c-family/c-objc.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. */
48 #define OBJCP_REMAP_FUNCTIONS
49 #include "objcp-decl.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
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
> **,
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
**);
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
;
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
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. */
199 next_runtime_abi_01_init_metadata_attributes (void)
202 objc_meta
= get_identifier ("OBJC1META");
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)
254 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
256 if (!OPTION_SET_P (flag_objc_call_cxx_cdtors
))
257 global_options
.x_flag_objc_call_cxx_cdtors
= 1;
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
270 /* `struct objc_selector *' */
271 objc_selector_type
= build_pointer_type (xref_tag (RECORD_TYPE
,
272 get_identifier (TAG_SELECTOR
)));
275 type
= lang_hooks
.decls
.pushdecl (build_decl (input_location
,
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
,
300 umsg_decl
= add_builtin_function (TAG_MSGSEND
,
301 type
, 0, NOT_BUILT_IN
,
304 umsg_nonnil_decl
= add_builtin_function (TAG_MSGSEND_NONNIL
,
305 type
, 0, NOT_BUILT_IN
,
308 umsg_stret_decl
= add_builtin_function (TAG_MSGSEND_STRET
,
309 type
, 0, NOT_BUILT_IN
,
312 umsg_nonnil_stret_decl
= add_builtin_function (TAG_MSGSEND_NONNIL_STRET
,
313 type
, 0, NOT_BUILT_IN
,
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
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
,
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
),
336 /* No direct dispatch available. */
337 umsg_fast_decl
= umsg_decl
;
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
,
346 umsg_super_decl
= add_builtin_function (TAG_MSGSENDSUPER
,
347 type
, 0, NOT_BUILT_IN
,
349 umsg_super_stret_decl
= add_builtin_function (TAG_MSGSENDSUPER_STRET
,
350 type
, 0, NOT_BUILT_IN
, 0,
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
,
359 /* id objc_getClass (const char *); */
361 = add_builtin_function (TAG_GETCLASS
, type
, 0, NOT_BUILT_IN
,
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
,
377 /* Declare the following function:
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
,
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;
405 struct _objc_ivar_list *ivars;
406 struct _objc_method_list *methods;
407 struct objc_cache *cache;
408 struct _objc_protocol_list *protocols;
410 const char *ivar_layout;
411 struct _objc_class_ext *ext;
414 void *gc_object_type;
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
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
),
433 /* struct _objc_class *super_class; */
434 add_field_decl (build_pointer_type (objc_class_template
),
435 "super_class", &chain
);
438 add_field_decl (string_type_node
, "name", &chain
);
441 add_field_decl (long_integer_type_node
, "version", &chain
);
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
);
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",
485 objc_finish_struct (objc_class_template
, decls
);
488 /* struct _objc_category
492 struct _objc_method_list *instance_methods;
493 struct _objc_method_list *class_methods;
494 struct _objc_protocol_list *protocols;
496 uint32_t size; // sizeof (struct _objc_category)
497 struct _objc_property_list *instance_properties; // category's own @property decl.
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
544 struct _objc_protocol_extension *isa;
546 struct _objc_class *isa;
550 struct _objc_protocol **protocol_list;
551 struct _objc__method_prototype_list *instance_methods;
552 struct _objc__method_prototype_list *class_methods;
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
)));
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 --- */
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
;
600 next_runtime_abi_01_class_decl (tree klass
)
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
);
612 next_runtime_abi_01_metaclass_decl (tree klass
)
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
);
624 next_runtime_abi_01_category_decl (tree klass
)
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
);
637 next_runtime_abi_01_protocol_decl (tree p
)
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
);
652 next_runtime_abi_01_string_decl (tree type
, const char *name
, string_section where
)
654 tree var
= start_var_decl (type
, name
);
658 OBJCMETA (var
, objc_meta
, meta_class_name
);
661 OBJCMETA (var
, objc_meta
, meta_meth_name
);
664 OBJCMETA (var
, objc_meta
, meta_meth_type
);
666 case prop_names_attr
:
667 OBJCMETA (var
, objc_meta
, meta_prop_name_attr
);
670 OBJCMETA (var
, objc_meta
, meta_base
);
678 static GTY(()) int class_reference_idx
;
681 build_class_reference_decl (void)
686 sprintf (buf
, "_OBJC_ClassRefs_%d", class_reference_idx
++);
687 decl
= start_var_decl (objc_class_type
, buf
);
693 next_runtime_abi_01_get_class_reference (tree ident
)
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
);
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
736 next_runtime_abi_01_get_arg_type_list_base (vec
<tree
, va_gc
> **argtypes
,
737 tree meth
, int context
,
743 receiver_type
= objc_super_type
;
744 else if (context
== METHOD_DEF
&& TREE_CODE (meth
) == INSTANCE_METHOD_DECL
)
745 receiver_type
= objc_instance_type
;
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
);
755 next_runtime_abi_01_receiver_is_class_object (tree 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
);
771 build_selector_reference_decl (tree ident
)
774 char *t
, buf
[BUFSIZE
];
776 snprintf (buf
, BUFSIZE
, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident
));
781 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
784 decl
= start_var_decl (objc_selector_type
, buf
);
785 OBJCMETA (decl
, objc_meta
, meta_sel_refs
);
790 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED
,
792 tree proto ATTRIBUTE_UNUSED
)
794 tree
*chain
= &sel_ref_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
);
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. */
821 build_objc_method_call (location_t loc
, int super_flag
, tree method_prototype
,
822 tree lookup_object
, tree selector
,
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. */
835 ? TREE_VALUE (TREE_TYPE (method_prototype
))
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
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
);
871 sender
= (super_flag
? umsg_super_decl
872 : (flag_nil_receivers
? (flag_objc_direct_dispatch
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. */
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
);
896 next_runtime_abi_01_build_objc_method_call (location_t loc
,
897 tree method_prototype
,
899 tree rtype ATTRIBUTE_UNUSED
,
904 tree selector
= next_runtime_abi_01_build_selector_reference (loc
, sel_name
,
907 return build_objc_method_call (loc
, super
, method_prototype
,
908 receiver
, selector
, method_params
);
912 next_runtime_abi_01_get_protocol_reference (location_t loc
, tree p
)
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. */
926 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED
,
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). */
936 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED
,
937 struct imp_entry
*imp
, bool inst_meth
)
943 objc_build_component_ref (imp
->class_decl
,
944 get_identifier ("super_class"));
945 return ucls_super_ref
;
949 if (!uucls_super_ref
)
951 objc_build_component_ref (imp
->meta_decl
,
952 get_identifier ("super_class"));
953 return uucls_super_ref
;
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
);
966 super_class
= objc_get_class_reference (super_name
);
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). */
975 build_indirect_ref (input_location
,
976 build_c_cast (input_location
,
977 build_pointer_type (objc_class_type
),
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
,
991 build_tree_list (NULL_TREE
, super_name
));
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. */
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
);
1011 next_runtime_abi_01_build_const_string_constructor (location_t loc
, tree string
,
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
);
1039 /* --- metadata templates --- */
1041 /* This routine builds the following type:
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
;
1052 build_v1_property_template (void)
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
);
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
;
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
;
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
);
1137 build_metadata_templates (void)
1140 if (!objc_method_template
)
1141 objc_method_template
= build_method_template ();
1147 /* --- emit metadata --- */
1150 generate_v1_meth_descriptor_table (tree chain
, tree protocol
,
1151 const char *prefix
, tree attr
)
1153 tree method_list_template
, initlist
, decl
;
1155 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1158 if (!chain
|| !prefix
)
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
,
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
));
1175 build_descriptor_table_initializer (objc_method_prototype_template
,
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
));
1184 /* Build protocol ext =
1185 {size, opt_instance_meth, opt_class_meth, instance_props};
1186 or NULL_TREE if none are present. */
1189 generate_v1_objc_protocol_extension (tree proto_interface
,
1190 tree opt_instance_meth
,
1191 tree opt_class_meth
,
1192 tree instance_props
)
1196 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1200 /* If there are no extensions, then don't bother... */
1201 if (!opt_instance_meth
&& !opt_class_meth
&& !instance_props
)
1204 if (!objc_protocol_extension_template
)
1205 build_v1_objc_protocol_extension_template ();
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));
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; */
1225 expr
= convert (objc_method_list_ptr
,
1226 build_unary_op (loc
, ADDR_EXPR
, opt_class_meth
, 0));
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; */
1233 expr
= convert (objc_prop_list_ptr
,
1234 build_unary_op (loc
, ADDR_EXPR
, instance_props
, 0));
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
);
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];
1258 build_v1_property_list_template (tree list_type
, int size
)
1260 tree property_list_t_record
;
1261 tree array_type
, decls
, *chain
= NULL
;
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. */
1284 build_v1_property_table_initializer (tree type
, tree context
)
1287 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
1289 if (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
)
1290 x
= CLASS_PROPERTY_DECL (context
);
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. */
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;
1329 gcc_assert (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
);
1330 x
= CLASS_PROPERTY_DECL (context
);
1334 x
= IMPL_PROPERTY_DECL (klass_ctxt
);
1336 for (; x
; x
= TREE_CHAIN (x
))
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
,
1348 initlist
= build_v1_property_table_initializer (objc_v1_property_template
,
1352 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template
));
1354 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolPropList_%s",
1355 IDENTIFIER_POINTER (PROTOCOL_NAME (context
)));
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
);
1371 generate_v1_protocol_list (tree i_or_p
, tree klass_ctxt
)
1373 tree array_type
, ptype
, refs_decl
, lproto
, e
, plist
, attr
;
1375 vec
<constructor_elt
, va_gc
> *v
= NULL
;
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
);
1384 case PROTOCOL_INTERFACE_TYPE
:
1385 plist
= PROTOCOL_LIST (i_or_p
);
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
)))
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
;
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
;
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
;
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
));
1451 build_v1_protocol_initializer (tree type
, tree protocol_name
, tree protocol_list
,
1452 tree inst_methods
, tree class_methods
,
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. */
1468 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_ext
, 0));
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
;
1478 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
1480 expr
= convert (ttyp
, null_pointer_node
);
1481 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1484 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
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
;
1524 generate_v1_protocols (void)
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
;
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
);
1547 /* Make sure we link in the Protocol class. */
1548 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME
));
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
);
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
);
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
);
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
);
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
;
1626 build_pointer_type (build_pointer_type (objc_protocol_template
));
1628 refs_expr
= convert (refs_type
,
1629 build_unary_op (loc
, ADDR_EXPR
, refs_decl
, 0));
1631 refs_expr
= convert (refs_type
, null_pointer_node
);
1633 if (flag_objc_abi
< 1)
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
);
1645 /* else - V1 extensions. */
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
,
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
);
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
;
1672 if (!chain
|| !name
|| !(size
= list_length (chain
)))
1675 if (!objc_method_template
)
1676 objc_method_template
= build_method_template ();
1678 method_list_template
= build_method_list_template (objc_method_template
,
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
));
1696 /* Init a category. */
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
,
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
;
1711 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
1713 expr
= convert (ltyp
, null_pointer_node
);
1714 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1717 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
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
));
1725 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
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
;
1737 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
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. */
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
;
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
);
1775 if (flag_objc_abi
>= 1)
1776 V1_Property_decl
= generate_v1_property_table (NULL_TREE
, cat
);
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
,
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
,
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
,
1804 finish_var_decl (cat_decl
, initlist
);
1805 impent
->class_decl
= cat_decl
;
1808 /* This routine builds the class extension used by v1 NeXT. */
1811 generate_objc_class_ext (tree property_list
, tree context
)
1813 tree decl
, expr
, ltyp
;
1814 tree weak_ivar_layout_tree
;
1817 vec
<constructor_elt
, va_gc
> *v
= NULL
;
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
)
1830 if (!objc_class_ext_template
)
1831 build_objc_class_ext_template ();
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
);
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
;
1847 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
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
);
1861 /* struct _objc_class {
1862 struct objc_class *isa;
1863 struct objc_class *super_class;
1868 struct objc_ivar_list *ivars;
1869 struct objc_method_list *methods;
1870 struct objc_cache *cache;
1871 struct objc_protocol_list *protocols;
1873 const char *ivar_layout;
1874 struct _objc_class_ext *ext;
1877 void *gc_object_type;
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
)
1889 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1891 /* TODO: fish the location out of the input data. */
1892 loc
= UNKNOWN_LOCATION
;
1895 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, isa
);
1898 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, super
);
1901 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, default_conversion (name
));
1904 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1905 build_int_cst (long_integer_type_node
, 0));
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
;
1918 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, ivar_list
, 0));
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
;
1926 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, dispatch_table
, 0));
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
));
1939 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
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
);
1953 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_ext
, 0));
1955 expr
= convert (ltyp
, null_pointer_node
);
1956 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
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
);
1970 generate_ivars_list (tree chain
, const char *name
, tree attr
)
1972 tree initlist
, ivar_list_template
, decl
;
1974 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
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
));
2001 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
2002 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
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
;
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
);
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
);
2051 super_expr
= add_objc_string (my_super_id
, class_names
);
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
);
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. */
2143 init_def_list (tree type
)
2147 struct imp_entry
*impent
;
2148 vec
<constructor_elt
, va_gc
> *v
= NULL
;
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
);
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:
2187 void *defs[cls_def_cnt + cat_def_cnt];
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
);
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. */
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. */
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. */
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
);
2298 handle_next_impent (struct imp_entry
*impent ATTRIBUTE_UNUSED
)
2300 if (targetcm
.objc_declare_class_definition
)
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
)));
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
)));
2318 targetcm
.objc_declare_class_definition (buf
);
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
);
2342 objc_generate_v1_next_metadata (void)
2344 struct imp_entry
*impent
;
2348 /* FIXME: Make sure that we generate no metadata if there is nothing
2351 if (objc_static_instances
)
2352 gcc_unreachable (); /* Not for NeXT */
2354 build_metadata_templates ();
2355 objc_implementation_context
=
2356 implementation_template
=
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
);
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 ();
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
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];
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. */
2423 #define OBJC_JBLEN 18
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
);
2451 = add_builtin_function (TAG_SETJMP
, temp_type
, 0, NOT_BUILT_IN
, NULL
, NULL_TREE
);
2453 /* id objc_exception_extract(struct _objc_exception_data *); */
2455 = build_function_type_list (objc_object_type
,
2456 build_pointer_type (objc_exception_data_template
),
2458 objc_exception_extract_decl
2459 = add_builtin_function (TAG_EXCEPTIONEXTRACT
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2461 /* void objc_exception_try_enter(struct _objc_exception_data *); */
2462 /* void objc_exception_try_exit(struct _objc_exception_data *); */
2464 = build_function_type_list (void_type_node
,
2465 build_pointer_type (objc_exception_data_template
),
2467 objc_exception_try_enter_decl
2468 = add_builtin_function (TAG_EXCEPTIONTRYENTER
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2470 objc_exception_try_exit_decl
2471 = add_builtin_function (TAG_EXCEPTIONTRYEXIT
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2474 /* int objc_exception_match(id, id); */
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
,
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))); */
2486 = build_function_type_list (objc_object_type
,
2491 objc_assign_ivar_decl
2492 = add_builtin_function (TAG_ASSIGNIVAR
, temp_type
, 0, NOT_BUILT_IN
,
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
),
2503 /* Default to slower ivar method. */
2504 objc_assign_ivar_fast_decl
= objc_assign_ivar_decl
;
2507 /* id objc_assign_global (id, id *); */
2508 /* id objc_assign_strongCast (id, id *); */
2509 temp_type
= build_function_type_list (objc_object_type
,
2511 build_pointer_type (objc_object_type
),
2513 objc_assign_global_decl
2514 = add_builtin_function (TAG_ASSIGNGLOBAL
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2516 objc_assign_strong_cast_decl
2517 = add_builtin_function (TAG_ASSIGNSTRONGCAST
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2521 /* --- NeXT V1 SJLJ Exceptions --- */
2523 /* Build "objc_exception_try_exit(&_stack)". */
2526 next_sjlj_build_try_exit (struct objc_try_context
**ctcp
)
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
);
2537 objc_exception_try_enter (&_stack);
2538 if (_setjmp(&_stack.buf))
2542 Return the COND_EXPR. Note that the THEN and ELSE fields are left
2543 empty, ready for the caller to fill them in. */
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
);
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
);
2563 t
= convert (ptr_type_node
, t
);
2565 t
= convert (ptr_type_node
, t
);
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
);
2579 DECL = objc_exception_extract(&_stack); */
2582 next_sjlj_build_exc_extract (struct objc_try_context
**ctcp
, tree decl
)
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
);
2597 if (objc_exception_match(obj_get_class(TYPE), _caught)
2604 objc_exception_try_exit(&_stack);
2606 from the sequence of CATCH_EXPRs in the current try context. */
2609 next_sjlj_build_catch_list (struct objc_try_context
**ctcp
)
2611 tree_stmt_iterator i
= tsi_start ((*ctcp
)->catch_list
);
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
)))
2633 if (type
== error_mark_node
)
2634 cond
= error_mark_node
;
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
));
2648 last
= &COND_EXPR_ELSE (t
);
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
);
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;
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);
2691 objc_exception_try_exit(&_stack);
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. */
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
));
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
),
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
,
2781 SET_EXPR_LOCATION (t
, cur_try_context
->end_finally_locus
);
2782 append_to_statement_list (t
, &TREE_OPERAND (try_fin
, 1));
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
;
2794 objc_eh_runtime_type (tree type
)
2796 tree ident
, eh_id
, decl
, str
;
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
)))
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
);
2822 error ("non-objective-c type %qT cannot be caught", type
);
2823 ident
= get_identifier ("ErrorMarkNode");
2824 goto make_err_class
;
2828 ident
= OBJC_TYPE_NAME (TREE_TYPE (type
));
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
);
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
);
2848 /* For NeXT ABI 0 and 1, the personality routines are just those of the
2849 underlying language. */
2852 objc_eh_personality (void)
2854 if (!objc_eh_personality_decl
)
2856 objc_eh_personality_decl
= build_personality_function ("gcc");
2858 objc_eh_personality_decl
= build_personality_function ("gxx");
2860 return objc_eh_personality_decl
;
2863 /* --- interfaces --- */
2866 build_throw_stmt (location_t loc
, tree throw_expr
, bool rethrown ATTRIBUTE_UNUSED
)
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
,
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. */
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
;
2892 var
= objc_create_temporary_var (objc_object_type
, NULL
);
2893 (*cur_try_context
)->caught_decl
= var
;
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
);
2907 begin_catch (struct objc_try_context
**cur_try_context
, tree type
,
2908 tree decl
, tree compound
, bool ellipsis ATTRIBUTE_UNUSED
)
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
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
);
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
));
2930 finish_try_stmt (struct objc_try_context
**cur_try_context
)
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
;
2948 /* This doesn't happen at the moment... but maybe one day... */
2950 /* Otherwise, nest the CATCH inside a FINALLY. */
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
);
2960 #include "gt-objc-objc-next-runtime-abi-01.h"