1 /* Next Runtime (ABI-0/1) private.
2 Copyright (C) 2011-2015 Free Software Foundation, Inc.
3 Contributed by Iain Sandoe (split from objc-act.c)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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"
37 #include "fold-const.h"
38 #include "stringpool.h"
41 #include "cp/cp-tree.h"
46 #include "langhooks.h"
47 #include "c-family/c-objc.h"
50 /* When building Objective-C++, we are not linking against the C
51 front-end and so need to replicate the C tree-construction
52 functions in some way. */
54 #define OBJCP_REMAP_FUNCTIONS
55 #include "objcp-decl.h"
60 #include "c-family/c-target.h"
61 #include "tree-iterator.h"
63 #include "objc-runtime-hooks.h"
64 #include "objc-runtime-shared-support.h"
65 #include "objc-encoding.h"
67 /* NeXT ABI 0 and 1 private definitions. */
68 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
70 #define TAG_GETCLASS "objc_getClass"
71 #define TAG_GETMETACLASS "objc_getMetaClass"
73 #define TAG_MSGSEND "objc_msgSend"
74 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
75 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
76 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
78 /* NeXT-specific tags. */
80 #define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
81 #define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
82 #define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
83 #define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
84 #define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
85 #define TAG_EXCEPTIONMATCH "objc_exception_match"
86 #define TAG_SETJMP "_setjmp"
88 #define TAG_ASSIGNIVAR "objc_assign_ivar"
89 #define TAG_ASSIGNGLOBAL "objc_assign_global"
90 #define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
92 /* Branch entry points. All that matters here are the addresses;
93 functions with these names do not really exist in libobjc. */
95 #define TAG_MSGSEND_FAST "objc_msgSend_Fast"
96 #define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
98 /* The version identifies which language generation and runtime the
99 module (file) was compiled for, and is recorded in the module
101 #define OBJC_VERSION (flag_objc_abi >= 1 ? 7 : 6)
103 #define UTAG_CLASS_EXT "_objc_class_ext"
104 #define UTAG_PROPERTY_LIST "_prop_list_t"
105 #define UTAG_PROTOCOL_EXT "_objc_protocol_extension"
107 #define CLS_HAS_CXX_STRUCTORS 0x2000L
109 /* rt_trees identifiers - shared between NeXT implementations. These
110 allow the FE to tag meta-data in a manner that survives LTO and can
111 be used when the runtime requires that certain meta-data items
112 appear in particular named sections. */
114 #include "objc-next-metadata-tags.h"
115 extern GTY(()) tree objc_rt_trees
[OCTI_RT_META_MAX
];
117 static void next_runtime_01_initialize (void);
119 static tree
next_runtime_abi_01_super_superclassfield_id (void);
121 static tree
next_runtime_abi_01_class_decl (tree
);
122 static tree
next_runtime_abi_01_metaclass_decl (tree
);
123 static tree
next_runtime_abi_01_category_decl (tree
);
124 static tree
next_runtime_abi_01_protocol_decl (tree
);
125 static tree
next_runtime_abi_01_string_decl (tree
, const char *, string_section
);
127 static tree
next_runtime_abi_01_get_class_reference (tree
);
128 static tree
next_runtime_abi_01_build_selector_reference (location_t
, tree
, tree
);
129 static tree
next_runtime_abi_01_get_protocol_reference (location_t
, tree
);
130 static tree
next_runtime_abi_01_build_ivar_ref (location_t
, tree
, tree
);
131 static tree
next_runtime_abi_01_get_class_super_ref (location_t
, struct imp_entry
*, bool);
132 static tree
next_runtime_abi_01_get_category_super_ref (location_t
, struct imp_entry
*, bool);
134 static tree
next_runtime_abi_01_receiver_is_class_object (tree
);
135 static void next_runtime_abi_01_get_arg_type_list_base (vec
<tree
, va_gc
> **,
137 static tree
next_runtime_abi_01_build_objc_method_call (location_t
, tree
, tree
,
138 tree
, tree
, tree
, int);
139 static bool next_runtime_abi_01_setup_const_string_class_decl (void);
140 static tree
next_runtime_abi_01_build_const_string_constructor (location_t
, tree
, int);
142 static void objc_generate_v1_next_metadata (void);
144 static void build_next_objc_exception_stuff (void);
145 static tree
objc_eh_runtime_type (tree type
);
146 static tree
objc_eh_personality (void);
147 static tree
build_throw_stmt (location_t
, tree
, bool);
148 static tree
objc_build_exc_ptr (struct objc_try_context
**);
149 static tree
begin_catch (struct objc_try_context
**, tree
, tree
, tree
, bool);
150 static void finish_catch (struct objc_try_context
**, tree
);
151 static tree
finish_try_stmt (struct objc_try_context
**);
154 objc_next_runtime_abi_01_init (objc_runtime_hooks
*rthooks
)
156 if (flag_objc_exceptions
157 && !flag_objc_sjlj_exceptions
)
159 warning_at (UNKNOWN_LOCATION
, OPT_Wall
,
160 "%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
161 "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2");
164 rthooks
->initialize
= next_runtime_01_initialize
;
165 rthooks
->default_constant_string_class_name
= DEF_CONSTANT_STRING_CLASS_NAME
;
166 rthooks
->tag_getclass
= TAG_GETCLASS
;
167 rthooks
->super_superclassfield_ident
= next_runtime_abi_01_super_superclassfield_id
;
169 rthooks
->class_decl
= next_runtime_abi_01_class_decl
;
170 rthooks
->metaclass_decl
= next_runtime_abi_01_metaclass_decl
;
171 rthooks
->category_decl
= next_runtime_abi_01_category_decl
;
172 rthooks
->protocol_decl
= next_runtime_abi_01_protocol_decl
;
173 rthooks
->string_decl
= next_runtime_abi_01_string_decl
;
175 rthooks
->get_class_reference
= next_runtime_abi_01_get_class_reference
;
176 rthooks
->build_selector_reference
= next_runtime_abi_01_build_selector_reference
;
177 rthooks
->get_protocol_reference
= next_runtime_abi_01_get_protocol_reference
;
178 rthooks
->build_ivar_reference
= next_runtime_abi_01_build_ivar_ref
;
179 rthooks
->get_class_super_ref
= next_runtime_abi_01_get_class_super_ref
;
180 rthooks
->get_category_super_ref
= next_runtime_abi_01_get_category_super_ref
;
182 rthooks
->receiver_is_class_object
= next_runtime_abi_01_receiver_is_class_object
;
183 rthooks
->get_arg_type_list_base
= next_runtime_abi_01_get_arg_type_list_base
;
184 rthooks
->build_objc_method_call
= next_runtime_abi_01_build_objc_method_call
;
186 rthooks
->setup_const_string_class_decl
=
187 next_runtime_abi_01_setup_const_string_class_decl
;
188 rthooks
->build_const_string_constructor
=
189 next_runtime_abi_01_build_const_string_constructor
;
191 rthooks
->build_throw_stmt
= build_throw_stmt
;
192 rthooks
->build_exc_ptr
= objc_build_exc_ptr
;
193 rthooks
->begin_catch
= begin_catch
;
194 rthooks
->finish_catch
= finish_catch
;
195 rthooks
->finish_try_stmt
= finish_try_stmt
;
197 rthooks
->generate_metadata
= objc_generate_v1_next_metadata
;
201 /* We need a way to convey what kind of meta-data are represented by a
202 given variable, since each type is expected (by the runtime) to be
203 found in a specific named section. The solution must be usable
206 The scheme used for NeXT ABI 0/1 (partial matching of variable
207 names) is not satisfactory for LTO & ABI-2. We now tag ObjC
208 meta-data with identification attributes in the front end. The
209 back-end may choose to act on these as it requires. */
212 next_runtime_abi_01_init_metadata_attributes (void)
215 objc_meta
= get_identifier ("OBJC1META");
218 meta_base
= get_identifier ("V1_BASE");
220 meta_class
= get_identifier ("V1_CLAS");
221 meta_metaclass
= get_identifier ("V1_META");
222 meta_category
= get_identifier ("V1_CATG");
223 meta_protocol
= get_identifier ("V1_PROT");
225 meta_clac_vars
= get_identifier ("V1_CLCV");
226 meta_clai_vars
= get_identifier ("V1_CLIV");
228 meta_clac_meth
= get_identifier ("V1_CLCM");
229 meta_clai_meth
= get_identifier ("V1_CLIM");
230 meta_catc_meth
= get_identifier ("V1_CACM");
231 meta_cati_meth
= get_identifier ("V1_CAIM");
232 meta_proto_cls_meth
= get_identifier ("V1_PCLM");
233 meta_proto_nst_meth
= get_identifier ("V1_PNSM");
235 meta_clas_prot
= get_identifier ("V1_CLPR");
236 meta_catg_prot
= get_identifier ("V1_CAPR");
238 meta_class_reference
= get_identifier ("V1_CLRF");
239 meta_proto_ref
= get_identifier ("V1_PRFS");
240 meta_sel_refs
= get_identifier ("V1_SRFS");
242 meta_class_name
= get_identifier ("V1_CLSN");
243 meta_meth_name
= get_identifier ("V1_METN");
244 meta_meth_type
= get_identifier ("V1_METT");
245 meta_prop_name_attr
= get_identifier ("V1_STRG");
247 meta_modules
= get_identifier ("V1_MODU");
248 meta_symtab
= get_identifier ("V1_SYMT");
249 meta_info
= get_identifier ("V1_INFO");
251 meta_proplist
= get_identifier ("V1_PLST");
252 meta_protocol_extension
= get_identifier ("V1_PEXT");
253 meta_class_extension
= get_identifier ("V1_CEXT");
255 meta_const_str
= get_identifier ("V1_CSTR");
258 static void build_v1_class_template (void);
259 static void build_v1_category_template (void);
260 static void build_v1_protocol_template (void);
262 static void next_runtime_01_initialize (void)
267 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
269 if (!global_options_set
.x_flag_objc_call_cxx_cdtors
)
270 global_options
.x_flag_objc_call_cxx_cdtors
= 1;
273 /* Set up attributes to be attached to the meta-data so that they
274 will be placed in the correct sections. */
275 next_runtime_abi_01_init_metadata_attributes ();
277 if (flag_objc_abi
>= 1)
278 objc_prop_list_ptr
= build_pointer_type (xref_tag (RECORD_TYPE
,
279 get_identifier ("_prop_list_t")));
281 /* Declare type of selector-objects that represent an operation
283 /* `struct objc_selector *' */
284 objc_selector_type
= build_pointer_type (xref_tag (RECORD_TYPE
,
285 get_identifier (TAG_SELECTOR
)));
287 build_v1_class_template ();
288 build_super_template ();
289 build_v1_protocol_template ();
290 build_v1_category_template ();
292 /* NB: In order to call one of the ..._stret (struct-returning)
293 functions, the function *MUST* first be cast to a signature that
294 corresponds to the actual ObjC method being invoked. This is
295 what is done by the build_objc_method_call() routine below. */
297 /* id objc_msgSend (id, SEL, ...); */
298 /* id objc_msgSendNonNil (id, SEL, ...); */
299 /* id objc_msgSend_stret (id, SEL, ...); */
300 /* id objc_msgSendNonNil_stret (id, SEL, ...); */
301 type
= build_varargs_function_type_list (objc_object_type
,
306 umsg_decl
= add_builtin_function (TAG_MSGSEND
,
307 type
, 0, NOT_BUILT_IN
,
310 umsg_nonnil_decl
= add_builtin_function (TAG_MSGSEND_NONNIL
,
311 type
, 0, NOT_BUILT_IN
,
314 umsg_stret_decl
= add_builtin_function (TAG_MSGSEND_STRET
,
315 type
, 0, NOT_BUILT_IN
,
318 umsg_nonnil_stret_decl
= add_builtin_function (TAG_MSGSEND_NONNIL_STRET
,
319 type
, 0, NOT_BUILT_IN
,
322 /* These can throw, because the function that gets called can throw
323 in Obj-C++, or could itself call something that can throw even in
325 TREE_NOTHROW (umsg_decl
) = 0;
326 TREE_NOTHROW (umsg_nonnil_decl
) = 0;
327 TREE_NOTHROW (umsg_stret_decl
) = 0;
328 TREE_NOTHROW (umsg_nonnil_stret_decl
) = 0;
330 /* id objc_msgSend_Fast (id, SEL, ...)
331 __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
332 #ifdef OFFS_MSGSEND_FAST
333 umsg_fast_decl
= add_builtin_function (TAG_MSGSEND_FAST
,
334 type
, 0, NOT_BUILT_IN
,
336 TREE_NOTHROW (umsg_fast_decl
) = 0;
337 DECL_ATTRIBUTES (umsg_fast_decl
)
338 = tree_cons (get_identifier ("hard_coded_address"),
339 build_int_cst (NULL_TREE
, OFFS_MSGSEND_FAST
),
342 /* No direct dispatch available. */
343 umsg_fast_decl
= umsg_decl
;
346 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
347 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
348 type
= build_varargs_function_type_list (objc_object_type
,
352 umsg_super_decl
= add_builtin_function (TAG_MSGSENDSUPER
,
353 type
, 0, NOT_BUILT_IN
,
355 umsg_super_stret_decl
= add_builtin_function (TAG_MSGSENDSUPER_STRET
,
356 type
, 0, NOT_BUILT_IN
, 0,
358 TREE_NOTHROW (umsg_super_decl
) = 0;
359 TREE_NOTHROW (umsg_super_stret_decl
) = 0;
361 type
= build_function_type_list (objc_object_type
,
362 const_string_type_node
,
365 /* id objc_getClass (const char *); */
367 = add_builtin_function (TAG_GETCLASS
, type
, 0, NOT_BUILT_IN
,
370 /* id objc_getMetaClass (const char *); */
371 objc_get_meta_class_decl
372 = add_builtin_function (TAG_GETMETACLASS
, type
, 0, NOT_BUILT_IN
, NULL
, NULL_TREE
);
374 /* This is the type of all of the following functions
375 objc_copyStruct(). */
376 type
= build_function_type_list (void_type_node
,
383 /* Declare the following function:
385 objc_copyStruct (void *destination, const void *source,
386 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
387 objc_copyStruct_decl
= add_builtin_function ("objc_copyStruct",
388 type
, 0, NOT_BUILT_IN
,
390 TREE_NOTHROW (objc_copyStruct_decl
) = 0;
391 objc_getPropertyStruct_decl
= NULL_TREE
;
392 objc_setPropertyStruct_decl
= NULL_TREE
;
394 build_next_objc_exception_stuff ();
395 if (flag_objc_exceptions
&& !flag_objc_sjlj_exceptions
)
396 using_eh_for_cleanups ();
397 lang_hooks
.eh_runtime_type
= objc_eh_runtime_type
;
398 lang_hooks
.eh_personality
= objc_eh_personality
;
401 /* --- templates --- */
403 /* struct _objc_class
405 struct _objc_class *isa;
406 struct _objc_class *super_class;
411 struct _objc_ivar_list *ivars;
412 struct _objc_method_list *methods;
413 struct objc_cache *cache;
414 struct _objc_protocol_list *protocols;
416 const char *ivar_layout;
417 struct _objc_class_ext *ext;
420 void *gc_object_type;
424 /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT
425 runtime. We generate them for ABI==0 to maintain backward binary
429 build_v1_class_template (void)
431 tree ptype
, decls
, *chain
= NULL
;
433 objc_class_template
= objc_start_struct (get_identifier (UTAG_CLASS
));
435 /* struct _objc_class *isa; */
436 decls
= add_field_decl (build_pointer_type (objc_class_template
),
439 /* struct _objc_class *super_class; */
440 add_field_decl (build_pointer_type (objc_class_template
),
441 "super_class", &chain
);
444 add_field_decl (string_type_node
, "name", &chain
);
447 add_field_decl (long_integer_type_node
, "version", &chain
);
450 add_field_decl (long_integer_type_node
, "info", &chain
);
452 /* long instance_size; */
453 add_field_decl (long_integer_type_node
, "instance_size", &chain
);
455 /* struct _objc_ivar_list *ivars; */
456 add_field_decl (objc_ivar_list_ptr
,"ivars", &chain
);
458 /* struct _objc_method_list *methods; */
459 add_field_decl (objc_method_list_ptr
, "methods", &chain
);
461 /* struct objc_cache *cache; */
462 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
463 get_identifier ("objc_cache")));
464 add_field_decl (ptype
, "cache", &chain
);
466 /* struct _objc_protocol **protocol_list; */
467 ptype
= build_pointer_type (build_pointer_type
468 (xref_tag (RECORD_TYPE
,
469 get_identifier (UTAG_PROTOCOL
))));
470 add_field_decl (ptype
, "protocol_list", &chain
);
472 if (flag_objc_abi
>= 1)
474 /* const char *ivar_layout; */
475 add_field_decl (const_string_type_node
, "ivar_layout", &chain
);
477 /* struct _objc_class_ext *ext; */
478 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
479 get_identifier (UTAG_CLASS_EXT
)));
480 add_field_decl (ptype
, "ext", &chain
);
485 add_field_decl (build_pointer_type (void_type_node
), "sel_id", &chain
);
486 /* void *gc_object_type; */
487 add_field_decl (build_pointer_type (void_type_node
), "gc_object_type",
491 objc_finish_struct (objc_class_template
, decls
);
494 /* struct _objc_category
498 struct _objc_method_list *instance_methods;
499 struct _objc_method_list *class_methods;
500 struct _objc_protocol_list *protocols;
502 uint32_t size; // sizeof (struct _objc_category)
503 struct _objc_property_list *instance_properties; // category's own @property decl.
508 build_v1_category_template (void)
510 tree ptype
, decls
, *chain
= NULL
;
512 objc_category_template
= objc_start_struct (get_identifier (UTAG_CATEGORY
));
514 /* char *category_name; */
515 decls
= add_field_decl (string_type_node
, "category_name", &chain
);
517 /* char *class_name; */
518 add_field_decl (string_type_node
, "class_name", &chain
);
520 /* struct _objc_method_list *instance_methods; */
521 add_field_decl (objc_method_list_ptr
, "instance_methods", &chain
);
523 /* struct _objc_method_list *class_methods; */
524 add_field_decl (objc_method_list_ptr
, "class_methods", &chain
);
526 /* struct _objc_protocol **protocol_list; */
527 ptype
= build_pointer_type (build_pointer_type (objc_protocol_template
));
528 add_field_decl (ptype
, "protocol_list", &chain
);
530 if (flag_objc_abi
>= 1)
532 add_field_decl (integer_type_node
, "size", &chain
);
534 /* struct _objc_property_list *instance_properties;
535 This field describes a category's @property declarations.
536 Properties from inherited protocols are not included. */
537 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
538 get_identifier (UTAG_PROPERTY_LIST
)));
539 add_field_decl (ptype
, "instance_properties", &chain
);
541 objc_finish_struct (objc_category_template
, decls
);
544 /* Begin code generation for protocols...
545 Modified for ObjC #1 extensions. */
547 /* struct _objc_protocol
550 struct _objc_protocol_extension *isa;
552 struct _objc_class *isa;
556 struct _objc_protocol **protocol_list;
557 struct _objc__method_prototype_list *instance_methods;
558 struct _objc__method_prototype_list *class_methods;
562 build_v1_protocol_template (void)
564 tree ptype
, decls
, *chain
= NULL
;
566 objc_protocol_template
= objc_start_struct (get_identifier (UTAG_PROTOCOL
));
568 if (flag_objc_abi
>= 1)
569 /* struct _objc_protocol_extension *isa; */
570 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
571 get_identifier (UTAG_PROTOCOL_EXT
)));
573 /* struct _objc_class *isa; */
574 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
575 get_identifier (UTAG_CLASS
)));
577 decls
= add_field_decl (ptype
, "isa", &chain
);
579 /* char *protocol_name; */
580 add_field_decl (string_type_node
, "protocol_name", &chain
);
582 /* struct _objc_protocol **protocol_list; */
583 ptype
= build_pointer_type (build_pointer_type (objc_protocol_template
));
584 add_field_decl (ptype
, "protocol_list", &chain
);
586 /* struct _objc__method_prototype_list *instance_methods; */
587 add_field_decl (objc_method_proto_list_ptr
, "instance_methods", &chain
);
589 /* struct _objc__method_prototype_list *class_methods; */
590 add_field_decl (objc_method_proto_list_ptr
, "class_methods", &chain
);
592 objc_finish_struct (objc_protocol_template
, decls
);
595 /* --- names, decls identifiers --- */
598 next_runtime_abi_01_super_superclassfield_id (void)
600 if (!super_superclassfield_id
)
601 super_superclassfield_id
= get_identifier ("super_class");
602 return super_superclassfield_id
;
606 next_runtime_abi_01_class_decl (tree klass
)
610 snprintf (buf
, BUFSIZE
, "_OBJC_Class_%s",
611 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
612 decl
= start_var_decl (objc_class_template
, buf
);
613 OBJCMETA (decl
, objc_meta
, meta_class
);
618 next_runtime_abi_01_metaclass_decl (tree klass
)
622 snprintf (buf
, BUFSIZE
, "_OBJC_MetaClass_%s",
623 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
624 decl
= start_var_decl (objc_class_template
, buf
);
625 OBJCMETA (decl
, objc_meta
, meta_metaclass
);
630 next_runtime_abi_01_category_decl (tree klass
)
634 snprintf (buf
, BUFSIZE
, "_OBJC_Category_%s_on_%s",
635 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass
)),
636 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
637 decl
= start_var_decl (objc_category_template
, buf
);
638 OBJCMETA (decl
, objc_meta
, meta_category
);
643 next_runtime_abi_01_protocol_decl (tree p
)
648 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
650 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
651 IDENTIFIER_POINTER (PROTOCOL_NAME (p
)));
652 decl
= start_var_decl (objc_protocol_template
, buf
);
653 OBJCMETA (decl
, objc_meta
, meta_protocol
);
658 next_runtime_abi_01_string_decl (tree type
, const char *name
, string_section where
)
660 tree var
= start_var_decl (type
, name
);
664 OBJCMETA (var
, objc_meta
, meta_class_name
);
667 OBJCMETA (var
, objc_meta
, meta_meth_name
);
670 OBJCMETA (var
, objc_meta
, meta_meth_type
);
672 case prop_names_attr
:
673 OBJCMETA (var
, objc_meta
, meta_prop_name_attr
);
676 OBJCMETA (var
, objc_meta
, meta_base
);
684 static GTY(()) int class_reference_idx
;
687 build_class_reference_decl (void)
692 sprintf (buf
, "_OBJC_ClassRefs_%d", class_reference_idx
++);
693 decl
= start_var_decl (objc_class_type
, buf
);
699 next_runtime_abi_01_get_class_reference (tree ident
)
706 for (chain
= &cls_ref_chain
; *chain
; chain
= &TREE_CHAIN (*chain
))
707 if (TREE_VALUE (*chain
) == ident
)
709 if (! TREE_PURPOSE (*chain
))
710 TREE_PURPOSE (*chain
) = build_class_reference_decl ();
712 return TREE_PURPOSE (*chain
);
715 decl
= build_class_reference_decl ();
716 *chain
= tree_cons (decl
, ident
, NULL_TREE
);
723 add_class_reference (ident
);
725 params
= build_tree_list (NULL_TREE
,
726 my_build_string_pointer
727 (IDENTIFIER_LENGTH (ident
) + 1,
728 IDENTIFIER_POINTER (ident
)));
730 return build_function_call (input_location
, objc_get_class_decl
, params
);
734 /* Used by build_function_type_for_method. Append the types for
735 receiver & _cmd at the start of a method argument list to ARGTYPES.
736 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
737 trying to define a method or call one. SUPERFLAG says this is for a
738 send to super. METH may be NULL, in the case that there is no
742 next_runtime_abi_01_get_arg_type_list_base (vec
<tree
, va_gc
> **argtypes
,
743 tree meth
, int context
,
749 receiver_type
= objc_super_type
;
750 else if (context
== METHOD_DEF
&& TREE_CODE (meth
) == INSTANCE_METHOD_DECL
)
751 receiver_type
= objc_instance_type
;
753 receiver_type
= objc_object_type
;
755 vec_safe_push (*argtypes
, receiver_type
);
756 /* Selector type - will eventually change to `int'. */
757 vec_safe_push (*argtypes
, objc_selector_type
);
761 next_runtime_abi_01_receiver_is_class_object (tree receiver
)
763 if (TREE_CODE (receiver
) == VAR_DECL
764 && IS_CLASS (TREE_TYPE (receiver
)))
766 /* The receiver is a variable created by build_class_reference_decl. */
767 tree chain
= cls_ref_chain
;
768 /* Look up the identifier in the relevant chain. */
769 for (; chain
; chain
= TREE_CHAIN (chain
))
770 if (TREE_PURPOSE (chain
) == receiver
)
771 return TREE_VALUE (chain
);
777 build_selector_reference_decl (tree ident
)
780 char *t
, buf
[BUFSIZE
];
782 snprintf (buf
, BUFSIZE
, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident
));
787 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
790 decl
= start_var_decl (objc_selector_type
, buf
);
791 OBJCMETA (decl
, objc_meta
, meta_sel_refs
);
796 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED
,
798 tree proto ATTRIBUTE_UNUSED
)
800 tree
*chain
= &sel_ref_chain
;
805 if (TREE_VALUE (*chain
) == ident
)
806 return TREE_PURPOSE (*chain
);
808 chain
= &TREE_CHAIN (*chain
);
811 expr
= build_selector_reference_decl (ident
);
813 *chain
= tree_cons (expr
, ident
, NULL_TREE
);
818 /* Build a tree expression to send OBJECT the operation SELECTOR,
819 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
820 assuming the method has prototype METHOD_PROTOTYPE.
821 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
822 LOC is the location of the expression to build.
823 Use METHOD_PARAMS as list of args to pass to the method.
824 If SUPER_FLAG is nonzero, we look up the superclass's method. */
827 build_objc_method_call (location_t loc
, int super_flag
, tree method_prototype
,
828 tree lookup_object
, tree selector
,
831 tree sender
, sender_cast
, method
, t
;
832 tree rcv_p
= (super_flag
? objc_super_type
: objc_object_type
);
833 vec
<tree
, va_gc
> *parms
;
834 unsigned nparm
= (method_params
? list_length (method_params
) : 0);
836 /* If a prototype for the method to be called exists, then cast
837 the sender's return type and arguments to match that of the method.
838 Otherwise, leave sender as is. */
841 ? TREE_VALUE (TREE_TYPE (method_prototype
))
843 tree ftype
= build_function_type_for_method (ret_type
, method_prototype
,
844 METHOD_REF
, super_flag
);
846 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
847 ftype
= build_type_attribute_variant (ftype
,
848 METHOD_TYPE_ATTRIBUTES
851 sender_cast
= build_pointer_type (ftype
);
853 lookup_object
= build_c_cast (loc
, rcv_p
, lookup_object
);
855 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
856 lookup_object
= save_expr (lookup_object
);
858 /* Param list + 2 slots for object and selector. */
859 vec_alloc (parms
, nparm
+ 2);
861 /* If we are returning a struct in memory, and the address
862 of that memory location is passed as a hidden first
863 argument, then change which messenger entry point this
864 expr will call. NB: Note that sender_cast remains
865 unchanged (it already has a struct return type). */
866 if (!targetm
.calls
.struct_value_rtx (0, 0)
867 && (TREE_CODE (ret_type
) == RECORD_TYPE
868 || TREE_CODE (ret_type
) == UNION_TYPE
)
869 && targetm
.calls
.return_in_memory (ret_type
, 0))
870 sender
= (super_flag
? umsg_super_stret_decl
871 : flag_nil_receivers
? umsg_stret_decl
872 : umsg_nonnil_stret_decl
);
874 sender
= (super_flag
? umsg_super_decl
875 : (flag_nil_receivers
? (flag_objc_direct_dispatch
878 : umsg_nonnil_decl
));
879 method
= build_fold_addr_expr_loc (loc
, sender
);
881 /* Pass the object to the method. */
882 parms
->quick_push (lookup_object
);
883 /* Pass the selector to the method. */
884 parms
->quick_push (selector
);
885 /* Now append the remainder of the parms. */
887 for (; method_params
; method_params
= TREE_CHAIN (method_params
))
888 parms
->quick_push (TREE_VALUE (method_params
));
890 /* Build an obj_type_ref, with the correct cast for the method call. */
891 t
= build3 (OBJ_TYPE_REF
, sender_cast
, method
,
892 lookup_object
, size_zero_node
);
893 t
= build_function_call_vec (loc
, vNULL
, t
, parms
, NULL
);
899 next_runtime_abi_01_build_objc_method_call (location_t loc
,
900 tree method_prototype
,
902 tree rtype ATTRIBUTE_UNUSED
,
907 tree selector
= next_runtime_abi_01_build_selector_reference (loc
, sel_name
,
910 return build_objc_method_call (loc
, super
, method_prototype
,
911 receiver
, selector
, method_params
);
915 next_runtime_abi_01_get_protocol_reference (location_t loc
, tree p
)
919 if (!PROTOCOL_FORWARD_DECL (p
))
920 PROTOCOL_FORWARD_DECL (p
) = next_runtime_abi_01_protocol_decl (p
);
922 expr
= build_unary_op (loc
, ADDR_EXPR
, PROTOCOL_FORWARD_DECL (p
), 0);
923 return convert (objc_protocol_type
, expr
);
926 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
929 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED
,
932 return objc_build_component_ref (base
, id
);
935 /* We build super class references as we need them (but keep them once
936 built for the sake of efficiency). */
939 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED
,
940 struct imp_entry
*imp
, bool inst_meth
)
946 objc_build_component_ref (imp
->class_decl
,
947 get_identifier ("super_class"));
948 return ucls_super_ref
;
952 if (!uucls_super_ref
)
954 objc_build_component_ref (imp
->meta_decl
,
955 get_identifier ("super_class"));
956 return uucls_super_ref
;
961 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED
,
962 struct imp_entry
*imp
, bool inst_meth
)
964 tree super_name
= CLASS_SUPER_NAME (imp
->imp_template
);
969 super_class
= objc_get_class_reference (super_name
);
973 /* If we are in a class method, we must retrieve the
974 _metaclass_ for the current class, pointed at by
975 the class's "isa" pointer. The following assumes that
976 "isa" is the first ivar in a class (which it must be). */
978 build_indirect_ref (input_location
,
979 build_c_cast (input_location
,
980 build_pointer_type (objc_class_type
),
986 /* else do it the slow way. */
987 add_class_reference (super_name
);
988 super_class
= (inst_meth
? objc_get_class_decl
: objc_get_meta_class_decl
);
989 super_name
= my_build_string_pointer (IDENTIFIER_LENGTH (super_name
) + 1,
990 IDENTIFIER_POINTER (super_name
));
991 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
992 return build_function_call (input_location
,
994 build_tree_list (NULL_TREE
, super_name
));
998 next_runtime_abi_01_setup_const_string_class_decl (void)
1000 if (!constant_string_global_id
)
1002 /* Hopefully, this should not represent a serious limitation. */
1004 snprintf (buf
, BUFSIZE
, "_%sClassReference", constant_string_class_name
);
1005 constant_string_global_id
= get_identifier (buf
);
1008 string_class_decl
= lookup_name (constant_string_global_id
);
1010 return (string_class_decl
!= NULL_TREE
);
1014 next_runtime_abi_01_build_const_string_constructor (location_t loc
, tree string
,
1017 tree constructor
, fields
, var
;
1018 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1020 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1021 fields
= TYPE_FIELDS (internal_const_str_type
);
1022 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1023 build_unary_op (loc
, ADDR_EXPR
, string_class_decl
, 0));
1025 fields
= DECL_CHAIN (fields
);
1026 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1027 build_unary_op (loc
, ADDR_EXPR
, string
, 1));
1029 /* ??? check if this should be long. */
1030 fields
= DECL_CHAIN (fields
);
1031 CONSTRUCTOR_APPEND_ELT (v
, fields
, build_int_cst (NULL_TREE
, length
));
1032 constructor
= objc_build_constructor (internal_const_str_type
, v
);
1034 var
= build_decl (input_location
, CONST_DECL
, NULL
, TREE_TYPE (constructor
));
1035 DECL_INITIAL (var
) = constructor
;
1036 TREE_STATIC (var
) = 1;
1037 DECL_CONTEXT (var
) = NULL
;
1038 OBJCMETA (var
, objc_meta
, meta_const_str
);
1042 /* --- metadata templates --- */
1044 /* This routine builds the following type:
1046 const char * const name; // property name
1047 const char * const attributes; // comma-delimited, encoded,
1048 // property attributes
1052 static GTY(()) tree objc_v1_property_template
;
1055 build_v1_property_template (void)
1058 tree decls
, *chain
= NULL
;
1060 prop_record
= objc_start_struct (get_identifier ("_prop_t"));
1061 /* const char * name */
1062 decls
= add_field_decl (string_type_node
, "name", &chain
);
1064 /* const char * attribute */
1065 add_field_decl (string_type_node
, "attribute", &chain
);
1067 objc_finish_struct (prop_record
, decls
);
1071 /* Build the following type:
1073 struct _objc_protocol_extension
1075 uint32_t size; // sizeof (struct _objc_protocol_extension)
1076 struct objc_method_list *optional_instance_methods;
1077 struct objc_method_list *optional_class_methods;
1078 struct objc_prop_list *instance_properties;
1082 static GTY(()) tree objc_protocol_extension_template
;
1085 build_v1_objc_protocol_extension_template (void)
1087 tree decls
, *chain
= NULL
;
1089 objc_protocol_extension_template
=
1090 objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT
));
1092 /* uint32_t size; */
1093 decls
= add_field_decl (integer_type_node
, "size", &chain
);
1095 /* struct objc_method_list *optional_instance_methods; */
1096 add_field_decl (objc_method_list_ptr
, "optional_instance_methods", &chain
);
1098 /* struct objc_method_list *optional_class_methods; */
1099 add_field_decl (objc_method_list_ptr
, "optional_class_methods", &chain
);
1101 /* struct objc_prop_list *instance_properties; */
1102 add_field_decl (objc_prop_list_ptr
, "instance_properties", &chain
);
1104 objc_finish_struct (objc_protocol_extension_template
, decls
);
1107 /* This routine build following struct type:
1108 struct _objc_class_ext
1110 uint32_t size; // sizeof(struct _objc_class_ext)
1111 const char *weak_ivar_layout;
1112 struct _prop_list_t *properties;
1116 static GTY(()) tree objc_class_ext_template
;
1119 build_objc_class_ext_template (void)
1121 tree ptrt
, decls
, *chain
= NULL
;
1123 objc_class_ext_template
= objc_start_struct (get_identifier (UTAG_CLASS_EXT
));
1125 /* uint32_t size; */
1126 decls
= add_field_decl (integer_type_node
, "size", &chain
);
1128 /* const char *weak_ivar_layout; */
1129 add_field_decl (const_string_type_node
, "weak_ivar_layout", &chain
);
1131 /* struct _prop_list_t *properties; */
1132 ptrt
= build_pointer_type (xref_tag (RECORD_TYPE
,
1133 get_identifier(UTAG_PROPERTY_LIST
)));
1134 add_field_decl (ptrt
, "properties", &chain
);
1136 objc_finish_struct (objc_class_ext_template
, decls
);
1140 build_metadata_templates (void)
1143 if (!objc_method_template
)
1144 objc_method_template
= build_method_template ();
1150 /* --- emit metadata --- */
1153 generate_v1_meth_descriptor_table (tree chain
, tree protocol
,
1154 const char *prefix
, tree attr
)
1156 tree method_list_template
, initlist
, decl
;
1158 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1161 if (!chain
|| !prefix
)
1164 if (!objc_method_prototype_template
)
1165 objc_method_prototype_template
= build_method_prototype_template ();
1167 size
= list_length (chain
);
1168 method_list_template
=
1169 build_method_prototype_list_template (objc_method_prototype_template
,
1171 snprintf (buf
, BUFSIZE
, "%s_%s", prefix
,
1172 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
1174 decl
= start_var_decl (method_list_template
, buf
);
1176 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1178 build_descriptor_table_initializer (objc_method_prototype_template
,
1180 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
1181 /* Get into the right section. */
1182 OBJCMETA (decl
, objc_meta
, attr
);
1183 finish_var_decl (decl
, objc_build_constructor (method_list_template
, v
));
1187 /* Build protocol ext =
1188 {size, opt_instance_meth, opt_class_meth, instance_props};
1189 or NULL_TREE if none are present. */
1192 generate_v1_objc_protocol_extension (tree proto_interface
,
1193 tree opt_instance_meth
,
1194 tree opt_class_meth
,
1195 tree instance_props
)
1199 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1203 /* If there are no extensions, then don't bother... */
1204 if (!opt_instance_meth
&& !opt_class_meth
&& !instance_props
)
1207 if (!objc_protocol_extension_template
)
1208 build_v1_objc_protocol_extension_template ();
1211 size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template
));
1212 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1214 /* Try for meaningful diagnostics. */
1215 loc
= DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface
));
1217 /* struct objc_method_list *optional_instance_methods; */
1218 if (opt_instance_meth
)
1219 expr
= convert (objc_method_list_ptr
,
1220 build_unary_op (loc
, ADDR_EXPR
, opt_instance_meth
, 0));
1222 expr
= convert (objc_method_list_ptr
, null_pointer_node
);
1224 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1226 /* struct objc_method_list *optional_class_methods; */
1228 expr
= convert (objc_method_list_ptr
,
1229 build_unary_op (loc
, ADDR_EXPR
, opt_class_meth
, 0));
1231 expr
= convert (objc_method_list_ptr
, null_pointer_node
);
1233 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1234 /* struct objc_prop_list *instance_properties; */
1236 expr
= convert (objc_prop_list_ptr
,
1237 build_unary_op (loc
, ADDR_EXPR
, instance_props
, 0));
1239 expr
= convert (objc_prop_list_ptr
, null_pointer_node
);
1241 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1242 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolExt_%s",
1243 IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface
)));
1245 decl
= start_var_decl (objc_protocol_extension_template
, buf
);
1246 expr
= objc_build_constructor (TREE_TYPE (decl
), v
);
1247 OBJCMETA (decl
, objc_meta
, meta_protocol_extension
);
1248 finish_var_decl (decl
, expr
);
1252 /* This routine builds the following type:
1253 struct _prop_list_t {
1254 uint32_t entsize; // sizeof (struct _prop_t)
1255 uint32_t prop_count;
1256 struct _prop_t prop_list [prop_count];
1261 build_v1_property_list_template (tree list_type
, int size
)
1263 tree property_list_t_record
;
1264 tree array_type
, decls
, *chain
= NULL
;
1267 property_list_t_record
= objc_start_struct (NULL_TREE
);
1269 /* uint32_t const entsize */
1270 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
1272 /* int prop_count */
1273 add_field_decl (integer_type_node
, "prop_count", &chain
);
1275 /* struct _prop_t prop_list[]; */
1276 array_type
= build_sized_array_type (list_type
, size
);
1277 add_field_decl (array_type
, "prop_list", &chain
);
1279 objc_finish_struct (property_list_t_record
, decls
);
1280 return property_list_t_record
;
1283 /* This routine builds the initializer list to initialize the
1284 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
1287 build_v1_property_table_initializer (tree type
, tree context
)
1290 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
1292 if (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
)
1293 x
= CLASS_PROPERTY_DECL (context
);
1295 x
= IMPL_PROPERTY_DECL (context
);
1297 for (; x
; x
= TREE_CHAIN (x
))
1299 vec
<constructor_elt
, va_gc
> *elemlist
= NULL
;
1300 tree attribute
, name_ident
= PROPERTY_NAME (x
);
1302 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
1303 add_objc_string (name_ident
, prop_names_attr
));
1305 attribute
= objc_v2_encode_prop_attr (x
);
1306 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
1307 add_objc_string (attribute
, prop_names_attr
));
1309 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
1310 objc_build_constructor (type
, elemlist
));
1313 return objc_build_constructor (build_array_type (type
, 0),inits
);
1316 /* This routine builds the 'struct _prop_list_t' variable declaration and
1317 initializes it with its initializer list. TYPE is 'struct _prop_list_t',
1318 NAME is the internal name of this variable, SIZE is number of properties
1319 for this class and LIST is the initializer list for its 'prop_list' field. */
1322 generate_v1_property_table (tree context
, tree klass_ctxt
)
1324 tree x
, decl
, initlist
, property_list_template
;
1325 bool is_proto
= false;
1326 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
1327 int init_val
, size
= 0;
1332 gcc_assert (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
);
1333 x
= CLASS_PROPERTY_DECL (context
);
1337 x
= IMPL_PROPERTY_DECL (klass_ctxt
);
1339 for (; x
; x
= TREE_CHAIN (x
))
1345 if (!objc_v1_property_template
)
1346 objc_v1_property_template
= build_v1_property_template ();
1348 property_list_template
=
1349 build_v1_property_list_template (objc_v1_property_template
,
1351 initlist
= build_v1_property_table_initializer (objc_v1_property_template
,
1355 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template
));
1357 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolPropList_%s",
1358 IDENTIFIER_POINTER (PROTOCOL_NAME (context
)));
1360 snprintf (buf
, BUFSIZE
, "_OBJC_ClassPropList_%s",
1361 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)));
1363 decl
= start_var_decl (property_list_template
, buf
);
1364 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, init_val
));
1365 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1366 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
1367 x
= objc_build_constructor (TREE_TYPE (decl
), inits
);
1368 OBJCMETA (decl
, objc_meta
, meta_proplist
);
1369 finish_var_decl (decl
, x
);
1374 generate_v1_protocol_list (tree i_or_p
, tree klass_ctxt
)
1376 tree array_type
, ptype
, refs_decl
, lproto
, e
, plist
, attr
;
1378 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1381 switch (TREE_CODE (i_or_p
))
1383 case CLASS_INTERFACE_TYPE
:
1384 case CATEGORY_INTERFACE_TYPE
:
1385 plist
= CLASS_PROTOCOL_LIST (i_or_p
);
1387 case PROTOCOL_INTERFACE_TYPE
:
1388 plist
= PROTOCOL_LIST (i_or_p
);
1395 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
1396 if (TREE_CODE (TREE_VALUE (lproto
)) == PROTOCOL_INTERFACE_TYPE
1397 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto
)))
1400 /* Build initializer. */
1401 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, 0));
1402 e
= build_int_cst (build_pointer_type (objc_protocol_template
), size
);
1403 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, e
);
1405 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
1407 tree pval
= TREE_VALUE (lproto
);
1409 if (TREE_CODE (pval
) == PROTOCOL_INTERFACE_TYPE
1410 && PROTOCOL_FORWARD_DECL (pval
))
1412 tree fwref
= PROTOCOL_FORWARD_DECL (pval
);
1413 location_t loc
= DECL_SOURCE_LOCATION (fwref
) ;
1414 e
= build_unary_op (loc
, ADDR_EXPR
, fwref
, 0);
1415 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, e
);
1419 /* static struct objc_protocol *refs[n]; */
1420 switch (TREE_CODE (i_or_p
))
1422 case PROTOCOL_INTERFACE_TYPE
:
1423 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRefs_%s",
1424 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p
)));
1425 attr
= meta_proto_ref
;
1427 case CLASS_INTERFACE_TYPE
:
1428 snprintf (buf
, BUFSIZE
, "_OBJC_ClassProtocols_%s",
1429 IDENTIFIER_POINTER (CLASS_NAME (i_or_p
)));
1430 attr
= meta_clas_prot
;
1432 case CATEGORY_INTERFACE_TYPE
:
1433 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryProtocols_%s_%s",
1434 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)),
1435 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt
)));
1436 attr
= meta_catg_prot
;
1442 ptype
= build_pointer_type (objc_protocol_template
);
1443 array_type
= build_sized_array_type (ptype
, size
+ 3);
1444 refs_decl
= start_var_decl (array_type
, buf
);
1446 OBJCMETA (refs_decl
, objc_meta
, attr
);
1447 finish_var_decl (refs_decl
,
1448 objc_build_constructor (TREE_TYPE (refs_decl
), v
));
1454 build_v1_protocol_initializer (tree type
, tree protocol_name
, tree protocol_list
,
1455 tree inst_methods
, tree class_methods
,
1460 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
1462 if (!objc_protocol_extension_template
)
1463 build_v1_objc_protocol_extension_template ();
1465 /* TODO: find a better representation of location from the inputs. */
1466 loc
= UNKNOWN_LOCATION
;
1467 ttyp
= build_pointer_type (objc_protocol_extension_template
);
1468 /* Instead of jamming the protocol version number into the isa, we pass
1469 either a pointer to the protocol extension - or NULL. */
1471 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_ext
, 0));
1473 expr
= convert (ttyp
, null_pointer_node
);
1475 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1476 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_name
);
1477 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_list
);
1479 ttyp
= objc_method_proto_list_ptr
;
1481 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
1483 expr
= convert (ttyp
, null_pointer_node
);
1484 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1487 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
1489 expr
= convert (ttyp
, null_pointer_node
);
1490 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1492 return objc_build_constructor (type
, inits
);
1495 /* An updated version of generate_protocols () that emit the protocol
1496 extension for ABI=1. */
1498 /* For each protocol which was referenced either from a @protocol()
1499 expression, or because a class/category implements it (then a
1500 pointer to the protocol is stored in the struct describing the
1501 class/category), we create a statically allocated instance of the
1502 Protocol class. The code is written in such a way as to generate
1503 as few Protocol objects as possible; we generate a unique Protocol
1504 instance for each protocol, and we don't generate a Protocol
1505 instance if the protocol is never referenced (either from a
1506 @protocol() or from a class/category implementation). These
1507 statically allocated objects can be referred to via the static
1508 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1510 The statically allocated Protocol objects that we generate here
1511 need to be fixed up at runtime in order to be used: the 'isa'
1512 pointer of the objects need to be set up to point to the 'Protocol'
1513 class, as known at runtime.
1515 The NeXT runtime fixes up all protocols at program startup time,
1516 before main() is entered. It uses a low-level trick to look up all
1517 those symbols, then loops on them and fixes them up. */
1519 /* TODO: finish getting rid of passing stuff around in globals. */
1521 static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl
;
1522 static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl
;
1523 static GTY(()) tree V1_ProtocolExt_decl
;
1524 static GTY(()) tree V1_Property_decl
;
1527 generate_v1_protocols (void)
1531 /* If a protocol was directly referenced, pull in indirect references. */
1532 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
1533 if (PROTOCOL_FORWARD_DECL (p
) && PROTOCOL_LIST (p
))
1534 generate_protocol_references (PROTOCOL_LIST (p
));
1536 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
1538 tree decl
, encoding
, initlist
, protocol_name_expr
;
1539 tree refs_type
, refs_decl
, refs_expr
;
1541 tree nst_methods
= PROTOCOL_NST_METHODS (p
);
1542 tree cls_methods
= PROTOCOL_CLS_METHODS (p
);
1544 /* If protocol wasn't referenced, don't generate any code. */
1545 decl
= PROTOCOL_FORWARD_DECL (p
);
1550 /* Make sure we link in the Protocol class. */
1551 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME
));
1555 if (! METHOD_ENCODING (nst_methods
))
1557 encoding
= encode_method_prototype (nst_methods
);
1558 METHOD_ENCODING (nst_methods
) = encoding
;
1560 nst_methods
= TREE_CHAIN (nst_methods
);
1563 UOBJC_INSTANCE_METHODS_decl
=
1564 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p
), p
,
1565 "_OBJC_ProtocolInstanceMethods",
1566 meta_proto_nst_meth
);
1570 if (! METHOD_ENCODING (cls_methods
))
1572 encoding
= encode_method_prototype (cls_methods
);
1573 METHOD_ENCODING (cls_methods
) = encoding
;
1576 cls_methods
= TREE_CHAIN (cls_methods
);
1579 UOBJC_CLASS_METHODS_decl
=
1580 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p
), p
,
1581 "_OBJC_ProtocolClassMethods",
1582 meta_proto_cls_meth
);
1584 /* There should be no optional methods for ABI-0 - but we need to
1585 check all this here before the lists are made. */
1586 nst_methods
= PROTOCOL_OPTIONAL_NST_METHODS (p
);
1589 if (! METHOD_ENCODING (nst_methods
))
1591 encoding
= encode_method_prototype (nst_methods
);
1592 METHOD_ENCODING (nst_methods
) = encoding
;
1594 nst_methods
= TREE_CHAIN (nst_methods
);
1597 V1_Protocol_OPT_NST_METHODS_decl
=
1598 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p
), p
,
1599 "_OBJC_OptionalProtocolInstanceMethods",
1600 meta_proto_nst_meth
);
1602 cls_methods
= PROTOCOL_OPTIONAL_CLS_METHODS (p
);
1605 if (! METHOD_ENCODING (cls_methods
))
1607 encoding
= encode_method_prototype (cls_methods
);
1608 METHOD_ENCODING (cls_methods
) = encoding
;
1611 cls_methods
= TREE_CHAIN (cls_methods
);
1614 V1_Protocol_OPT_CLS_METHODS_decl
=
1615 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p
), p
,
1616 "_OBJC_OptionalProtocolClassMethods",
1617 meta_proto_cls_meth
);
1619 if (PROTOCOL_LIST (p
))
1620 refs_decl
= generate_v1_protocol_list (p
, objc_implementation_context
);
1624 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1625 protocol_name_expr
= add_objc_string (PROTOCOL_NAME (p
), class_names
);
1626 /* TODO: more locations to be fixed up... */
1627 loc
= UNKNOWN_LOCATION
;
1629 build_pointer_type (build_pointer_type (objc_protocol_template
));
1631 refs_expr
= convert (refs_type
,
1632 build_unary_op (loc
, ADDR_EXPR
, refs_decl
, 0));
1634 refs_expr
= convert (refs_type
, null_pointer_node
);
1636 if (flag_objc_abi
< 1)
1640 build_protocol_initializer (TREE_TYPE (decl
),
1641 protocol_name_expr
, refs_expr
,
1642 UOBJC_INSTANCE_METHODS_decl
,
1643 UOBJC_CLASS_METHODS_decl
);
1644 finish_var_decl (decl
, initlist
);
1648 /* else - V1 extensions. */
1651 generate_v1_property_table (p
, NULL_TREE
);
1653 V1_ProtocolExt_decl
=
1654 generate_v1_objc_protocol_extension (p
,
1655 V1_Protocol_OPT_NST_METHODS_decl
,
1656 V1_Protocol_OPT_CLS_METHODS_decl
,
1659 initlist
= build_v1_protocol_initializer (TREE_TYPE (decl
),
1660 protocol_name_expr
, refs_expr
,
1661 UOBJC_INSTANCE_METHODS_decl
,
1662 UOBJC_CLASS_METHODS_decl
,
1663 V1_ProtocolExt_decl
);
1664 finish_var_decl (decl
, initlist
);
1669 generate_dispatch_table (tree chain
, const char *name
, tree attr
)
1671 tree decl
, method_list_template
, initlist
;
1672 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1675 if (!chain
|| !name
|| !(size
= list_length (chain
)))
1678 if (!objc_method_template
)
1679 objc_method_template
= build_method_template ();
1681 method_list_template
= build_method_list_template (objc_method_template
,
1683 initlist
= build_dispatch_table_initializer (objc_method_template
, chain
);
1685 decl
= start_var_decl (method_list_template
, name
);
1687 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, integer_zero_node
);
1688 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1689 build_int_cst (integer_type_node
, size
));
1690 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
1692 OBJCMETA (decl
, objc_meta
, attr
);
1693 finish_var_decl (decl
,
1694 objc_build_constructor (TREE_TYPE (decl
), v
));
1699 /* Init a category. */
1701 build_v1_category_initializer (tree type
, tree cat_name
, tree class_name
,
1702 tree inst_methods
, tree class_methods
,
1703 tree protocol_list
, tree property_list
,
1707 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1709 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, cat_name
);
1710 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, class_name
);
1712 ltyp
= objc_method_list_ptr
;
1714 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
1716 expr
= convert (ltyp
, null_pointer_node
);
1717 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1720 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
1722 expr
= convert (ltyp
, null_pointer_node
);
1723 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1725 /* protocol_list = */
1726 ltyp
= build_pointer_type (build_pointer_type (objc_protocol_template
));
1728 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
1730 expr
= convert (ltyp
, null_pointer_node
);
1731 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1733 if (flag_objc_abi
>= 1)
1735 int val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template
));
1736 expr
= build_int_cst (NULL_TREE
, val
);
1737 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1738 ltyp
= objc_prop_list_ptr
;
1740 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
1742 expr
= convert (ltyp
, null_pointer_node
);
1743 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1746 return objc_build_constructor (type
, v
);
1749 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1750 /* TODO: get rid of passing stuff around in globals. */
1752 generate_v1_category (struct imp_entry
*impent
)
1754 tree initlist
, cat_name_expr
, class_name_expr
;
1755 tree protocol_decl
, category
, cat_decl
;
1756 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
1757 tree cat
= impent
->imp_context
;
1761 cat_decl
= impent
->class_decl
;
1762 loc
= DECL_SOURCE_LOCATION (cat_decl
);
1764 add_class_reference (CLASS_NAME (cat
));
1765 cat_name_expr
= add_objc_string (CLASS_SUPER_NAME (cat
), class_names
);
1766 class_name_expr
= add_objc_string (CLASS_NAME (cat
), class_names
);
1768 category
= lookup_category (impent
->imp_template
, CLASS_SUPER_NAME (cat
));
1770 if (category
&& CLASS_PROTOCOL_LIST (category
))
1772 generate_protocol_references (CLASS_PROTOCOL_LIST (category
));
1773 protocol_decl
= generate_v1_protocol_list (category
, cat
);
1778 if (flag_objc_abi
>= 1)
1779 V1_Property_decl
= generate_v1_property_table (NULL_TREE
, cat
);
1781 V1_Property_decl
= NULL_TREE
;
1783 if (CLASS_NST_METHODS (cat
))
1785 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryInstanceMethods_%s_%s",
1786 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
1787 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
1788 inst_methods
= generate_dispatch_table (CLASS_NST_METHODS (cat
), buf
,
1792 if (CLASS_CLS_METHODS (cat
))
1794 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryClassMethods_%s_%s",
1795 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
1796 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
1797 class_methods
= generate_dispatch_table (CLASS_CLS_METHODS (cat
), buf
,
1801 initlist
= build_v1_category_initializer (TREE_TYPE (cat_decl
),
1802 cat_name_expr
, class_name_expr
,
1803 inst_methods
, class_methods
,
1804 protocol_decl
, V1_Property_decl
,
1807 finish_var_decl (cat_decl
, initlist
);
1808 impent
->class_decl
= cat_decl
;
1811 /* This routine builds the class extension used by v1 NeXT. */
1814 generate_objc_class_ext (tree property_list
, tree context
)
1816 tree decl
, expr
, ltyp
;
1817 tree weak_ivar_layout_tree
;
1820 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1823 /* TODO: pass the loc in or find it from args. */
1824 loc
= UNKNOWN_LOCATION
;
1826 /* const char *weak_ivar_layout
1827 TODO: Figure the ivar layouts out... */
1828 weak_ivar_layout_tree
= NULL_TREE
;
1830 if (!property_list
&& !weak_ivar_layout_tree
)
1833 if (!objc_class_ext_template
)
1834 build_objc_class_ext_template ();
1837 size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template
));
1838 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1840 ltyp
= const_string_type_node
;
1841 if (weak_ivar_layout_tree
)
1842 expr
= convert (ltyp
, weak_ivar_layout_tree
);
1844 expr
= convert (ltyp
, null_pointer_node
);
1845 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1847 /* struct _prop_list_t *properties; */
1848 ltyp
= objc_prop_list_ptr
;
1850 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
1852 expr
= convert (ltyp
, null_pointer_node
);
1853 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1855 snprintf (buf
, BUFSIZE
, "_OBJC_ClassExt_%s",
1856 IDENTIFIER_POINTER (CLASS_NAME (context
)));
1857 decl
= start_var_decl (objc_class_ext_template
, buf
);
1858 expr
= objc_build_constructor (TREE_TYPE (decl
), v
);
1859 OBJCMETA (decl
, objc_meta
, meta_class_extension
);
1860 finish_var_decl (decl
, expr
);
1864 /* struct _objc_class {
1865 struct objc_class *isa;
1866 struct objc_class *super_class;
1871 struct objc_ivar_list *ivars;
1872 struct objc_method_list *methods;
1873 struct objc_cache *cache;
1874 struct objc_protocol_list *protocols;
1876 const char *ivar_layout;
1877 struct _objc_class_ext *ext;
1880 void *gc_object_type;
1885 build_v1_shared_structure_initializer (tree type
, tree isa
, tree super
,
1886 tree name
, tree size
, int status
,
1887 tree dispatch_table
, tree ivar_list
,
1888 tree protocol_list
, tree class_ext
)
1892 vec
<constructor_elt
, va_gc
> *v
= NULL
;
1894 /* TODO: fish the location out of the input data. */
1895 loc
= UNKNOWN_LOCATION
;
1898 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, isa
);
1901 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, super
);
1904 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, default_conversion (name
));
1907 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1908 build_int_cst (long_integer_type_node
, 0));
1911 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1912 build_int_cst (long_integer_type_node
, status
));
1914 /* instance_size = */
1915 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1916 convert (long_integer_type_node
, size
));
1918 /* objc_ivar_list = */
1919 ltyp
= objc_ivar_list_ptr
;
1921 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, ivar_list
, 0));
1923 expr
= convert (ltyp
, null_pointer_node
);
1924 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1926 /* objc_method_list = */
1927 ltyp
= objc_method_list_ptr
;
1929 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, dispatch_table
, 0));
1931 expr
= convert (ltyp
, null_pointer_node
);
1932 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1934 ltyp
= build_pointer_type (xref_tag (RECORD_TYPE
,
1935 get_identifier ("objc_cache")));
1936 /* method_cache = */
1937 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, convert (ltyp
, null_pointer_node
));
1939 /* protocol_list = */
1940 ltyp
= build_pointer_type (build_pointer_type (objc_protocol_template
));
1942 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
1944 expr
= convert (ltyp
, null_pointer_node
);
1945 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1947 if (flag_objc_abi
>= 1)
1949 /* TODO: figure out the ivar_layout stuff. */
1950 expr
= convert (const_string_type_node
, null_pointer_node
);
1951 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1952 if (!objc_class_ext_template
)
1953 build_objc_class_ext_template ();
1954 ltyp
= build_pointer_type (objc_class_ext_template
);
1956 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_ext
, 0));
1958 expr
= convert (ltyp
, null_pointer_node
);
1959 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1964 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, null_pointer_node
);
1966 /* gc_object_type = NULL */
1967 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, null_pointer_node
);
1969 return objc_build_constructor (type
, v
);
1973 generate_ivars_list (tree chain
, const char *name
, tree attr
)
1975 tree initlist
, ivar_list_template
, decl
;
1977 vec
<constructor_elt
, va_gc
> *inits
= NULL
;
1982 if (!objc_ivar_template
)
1983 objc_ivar_template
= build_ivar_template ();
1985 size
= ivar_list_length (chain
);
1987 generating_instance_variables
= 1;
1988 ivar_list_template
= build_ivar_list_template (objc_ivar_template
, size
);
1989 initlist
= build_ivar_list_initializer (objc_ivar_template
, chain
);
1990 generating_instance_variables
= 0;
1992 decl
= start_var_decl (ivar_list_template
, name
);
1994 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1995 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
1997 OBJCMETA (decl
, objc_meta
, attr
);
1998 finish_var_decl (decl
,
1999 objc_build_constructor (TREE_TYPE (decl
), inits
));
2004 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
2005 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2008 generate_v1_class_structs (struct imp_entry
*impent
)
2010 tree name_expr
, super_expr
, root_expr
, class_decl
, meta_decl
;
2011 tree my_root_id
, my_super_id
;
2012 tree cast_type
, initlist
, protocol_decl
;
2013 tree class_ext_decl
= NULL_TREE
, props
= NULL_TREE
;
2014 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
2015 tree chain
, inst_ivars
= NULL_TREE
, class_ivars
= NULL_TREE
;
2020 /* objc_implementation_context = impent->imp_context;
2021 implementation_template = impent->imp_template;*/
2022 class_decl
= impent
->class_decl
;
2023 meta_decl
= impent
->meta_decl
;
2024 cls_flags
= impent
->has_cxx_cdtors
? CLS_HAS_CXX_STRUCTORS
: 0 ;
2026 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2028 if (flag_objc_abi
>= 1)
2030 /* ABI=1 additions. */
2031 props
= generate_v1_property_table (NULL_TREE
, impent
->imp_context
);
2032 class_ext_decl
= generate_objc_class_ext (props
, impent
->imp_context
);
2035 my_super_id
= CLASS_SUPER_NAME (impent
->imp_template
);
2038 add_class_reference (my_super_id
);
2040 /* Compute "my_root_id" - this is required for code generation.
2041 the "isa" for all meta class structures points to the root of
2042 the inheritance hierarchy (e.g. "__Object")... */
2043 my_root_id
= my_super_id
;
2046 tree my_root_int
= lookup_interface (my_root_id
);
2048 if (my_root_int
&& CLASS_SUPER_NAME (my_root_int
))
2049 my_root_id
= CLASS_SUPER_NAME (my_root_int
);
2054 super_expr
= add_objc_string (my_super_id
, class_names
);
2058 /* No super class. */
2059 my_root_id
= CLASS_NAME (impent
->imp_template
);
2060 super_expr
= null_pointer_node
;
2063 /* Install class `isa' and `super' pointers at runtime. */
2064 cast_type
= build_pointer_type (objc_class_template
);
2065 super_expr
= build_c_cast (loc
, cast_type
, super_expr
);
2067 root_expr
= add_objc_string (my_root_id
, class_names
);
2068 root_expr
= build_c_cast (loc
, cast_type
, root_expr
);
2070 if (CLASS_PROTOCOL_LIST (impent
->imp_template
))
2072 generate_protocol_references (CLASS_PROTOCOL_LIST (impent
->imp_template
));
2073 protocol_decl
= generate_v1_protocol_list (impent
->imp_template
,
2074 impent
->imp_context
);
2077 protocol_decl
= NULL_TREE
;
2079 if (CLASS_CLS_METHODS (impent
->imp_context
))
2081 snprintf (buf
, BUFSIZE
, "_OBJC_ClassMethods_%s",
2082 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2083 class_methods
= generate_dispatch_table (CLASS_CLS_METHODS (impent
->imp_context
),
2084 buf
, meta_clac_meth
);
2087 if (CLASS_SUPER_NAME (impent
->imp_template
) == NULL_TREE
2088 && (chain
= TYPE_FIELDS (objc_class_template
)))
2090 snprintf (buf
, BUFSIZE
, "_OBJC_ClassIvars_%s",
2091 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2092 class_ivars
= generate_ivars_list (chain
, buf
, meta_clac_vars
);
2094 /* TODO: get rid of hidden passing of stuff in globals. */
2095 /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */
2097 name_expr
= add_objc_string (CLASS_NAME (impent
->imp_template
), class_names
);
2099 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2101 initlist
= build_v1_shared_structure_initializer
2102 (TREE_TYPE (meta_decl
),
2103 root_expr
, super_expr
, name_expr
,
2104 convert (integer_type_node
, TYPE_SIZE_UNIT (objc_class_template
)),
2105 CLS_META
, class_methods
, class_ivars
,
2106 protocol_decl
, NULL_TREE
);
2108 finish_var_decl (meta_decl
, initlist
);
2109 impent
->meta_decl
= meta_decl
;
2111 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2112 if (CLASS_NST_METHODS (impent
->imp_context
))
2114 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceMethods_%s",
2115 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2116 inst_methods
= generate_dispatch_table (CLASS_NST_METHODS (impent
->imp_context
),
2117 buf
, meta_clai_meth
);
2120 if ((chain
= CLASS_IVARS (impent
->imp_template
)))
2122 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceIvars_%s",
2123 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2124 inst_ivars
= generate_ivars_list (chain
, buf
, meta_clai_vars
);
2127 initlist
= build_v1_shared_structure_initializer
2128 (TREE_TYPE (class_decl
),
2129 build_unary_op (loc
, ADDR_EXPR
, meta_decl
, 0),
2130 super_expr
, name_expr
,
2131 convert (integer_type_node
,
2132 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent
->imp_template
))),
2133 CLS_FACTORY
| cls_flags
, inst_methods
, inst_ivars
,
2134 protocol_decl
, class_ext_decl
);
2136 finish_var_decl (class_decl
, initlist
);
2137 impent
->class_decl
= class_decl
;
2140 /* --- Output NeXT V1 Metadata --- */
2142 /* Create the initial value for the `defs' field of _objc_symtab.
2143 This is a CONSTRUCTOR. */
2146 init_def_list (tree type
)
2150 struct imp_entry
*impent
;
2151 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2154 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2156 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
2158 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2159 expr
= build_unary_op (loc
,
2160 ADDR_EXPR
, impent
->class_decl
, 0);
2161 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2166 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2168 if (TREE_CODE (impent
->imp_context
) == CATEGORY_IMPLEMENTATION_TYPE
)
2170 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2171 expr
= build_unary_op (loc
,
2172 ADDR_EXPR
, impent
->class_decl
, 0);
2173 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2177 return objc_build_constructor (type
, v
);
2180 /* Take care of defining and initializing _OBJC_SYMBOLS. */
2182 /* Predefine the following data type:
2190 void *defs[cls_def_cnt + cat_def_cnt];
2194 build_objc_symtab_template (void)
2196 tree fields
, *chain
= NULL
;
2198 objc_symtab_template
= objc_start_struct (get_identifier (UTAG_SYMTAB
));
2200 /* long sel_ref_cnt; */
2201 fields
= add_field_decl (long_integer_type_node
, "sel_ref_cnt", &chain
);
2204 add_field_decl (build_pointer_type (objc_selector_type
), "refs", &chain
);
2206 /* short cls_def_cnt; */
2207 add_field_decl (short_integer_type_node
, "cls_def_cnt", &chain
);
2209 /* short cat_def_cnt; */
2210 add_field_decl (short_integer_type_node
, "cat_def_cnt", &chain
);
2212 if (imp_count
|| cat_count
)
2214 /* void *defs[imp_count + cat_count (+ 1)]; */
2215 /* NB: The index is one less than the size of the array. */
2216 int index
= imp_count
+ cat_count
;
2217 tree array_type
= build_sized_array_type (ptr_type_node
, index
);
2218 add_field_decl (array_type
, "defs", &chain
);
2221 objc_finish_struct (objc_symtab_template
, fields
);
2223 /* Construct the initial value for all of _objc_symtab. */
2226 init_objc_symtab (tree type
)
2228 vec
<constructor_elt
, va_gc
> *v
= NULL
;
2230 /* sel_ref_cnt = { ..., 5, ... } */
2232 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2233 build_int_cst (long_integer_type_node
, 0));
2235 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2237 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2238 convert (build_pointer_type (objc_selector_type
),
2239 integer_zero_node
));
2241 /* cls_def_cnt = { ..., 5, ... } */
2243 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2244 build_int_cst (short_integer_type_node
, imp_count
));
2246 /* cat_def_cnt = { ..., 5, ... } */
2248 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2249 build_int_cst (short_integer_type_node
, cat_count
));
2251 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2253 if (imp_count
|| cat_count
)
2255 tree field
= TYPE_FIELDS (type
);
2256 field
= DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field
))));
2258 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, init_def_list (TREE_TYPE (field
)));
2261 return objc_build_constructor (type
, v
);
2264 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2265 and initialized appropriately. */
2268 generate_objc_symtab_decl (void)
2270 build_objc_symtab_template ();
2271 UOBJC_SYMBOLS_decl
= start_var_decl (objc_symtab_template
, "_OBJC_Symbols");
2272 /* Allow the runtime to mark meta-data such that it can be assigned to target
2273 specific sections by the back-end. */
2274 OBJCMETA (UOBJC_SYMBOLS_decl
, objc_meta
, meta_symtab
);
2275 finish_var_decl (UOBJC_SYMBOLS_decl
,
2276 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl
)));
2279 /* Any target implementing NeXT ObjC m32 ABI has to ensure that objects
2280 refer to, and define, symbols that enforce linkage of classes into the
2281 executable image, preserving unix archive semantics.
2283 At present (4.8), the only targets implementing this are Darwin; these
2284 use top level asms to implement a scheme (see config/darwin-c.c). The
2285 latter method is a hack, but compatible with LTO see also PR48109 for
2286 further discussion and other possible methods. */
2289 handle_next_class_ref (tree chain ATTRIBUTE_UNUSED
)
2291 if (targetcm
.objc_declare_unresolved_class_reference
)
2293 const char *name
= IDENTIFIER_POINTER (TREE_VALUE (chain
));
2294 char *string
= (char *) alloca (strlen (name
) + 30);
2295 sprintf (string
, ".objc_class_name_%s", name
);
2296 targetcm
.objc_declare_unresolved_class_reference (string
);
2301 handle_next_impent (struct imp_entry
*impent ATTRIBUTE_UNUSED
)
2303 if (targetcm
.objc_declare_class_definition
)
2307 switch (TREE_CODE (impent
->imp_context
))
2309 case CLASS_IMPLEMENTATION_TYPE
:
2310 snprintf (buf
, BUFSIZE
, ".objc_class_name_%s",
2311 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2313 case CATEGORY_IMPLEMENTATION_TYPE
:
2314 snprintf (buf
, BUFSIZE
, "*.objc_category_name_%s_%s",
2315 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)),
2316 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent
->imp_context
)));
2321 targetcm
.objc_declare_class_definition (buf
);
2326 generate_classref_translation_entry (tree chain
)
2328 tree expr
, decl
, type
;
2330 decl
= TREE_PURPOSE (chain
);
2331 type
= TREE_TYPE (decl
);
2333 expr
= add_objc_string (TREE_VALUE (chain
), class_names
);
2334 expr
= convert (type
, expr
); /* cast! */
2336 /* This is a class reference. It is re-written by the runtime,
2337 but will be optimized away unless we force it. */
2338 DECL_PRESERVE_P (decl
) = 1;
2339 OBJCMETA (decl
, objc_meta
, meta_class_reference
);
2340 finish_var_decl (decl
, expr
);
2345 objc_generate_v1_next_metadata (void)
2347 struct imp_entry
*impent
;
2351 /* FIXME: Make sure that we generate no metadata if there is nothing
2354 if (objc_static_instances
)
2355 gcc_unreachable (); /* Not for NeXT */
2357 build_metadata_templates ();
2358 objc_implementation_context
=
2359 implementation_template
=
2361 UOBJC_METACLASS_decl
= NULL_TREE
;
2363 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2366 /* If -gen-decls is present, Dump the @interface of each class.
2367 TODO: Dump the classes in the order they were found, rather than in
2368 reverse order as we are doing now. */
2369 if (flag_gen_declaration
)
2370 dump_interface (gen_declaration_file
, impent
->imp_context
);
2372 /* all of the following reference the string pool... */
2373 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
2374 generate_v1_class_structs (impent
);
2376 generate_v1_category (impent
);
2379 /* If we are using an array of selectors, we must always
2380 finish up the array decl even if no selectors were used. */
2381 build_next_selector_translation_table ();
2384 generate_v1_protocols ();
2386 /* Pass summary information to the runtime. */
2387 if (imp_count
|| cat_count
)
2388 generate_objc_symtab_decl ();
2390 vers
= OBJC_VERSION
;
2391 attr
= build_tree_list (objc_meta
, meta_modules
);
2392 build_module_descriptor (vers
, attr
);
2394 /* Dump the class references. This forces the appropriate classes
2395 to be linked into the executable image, preserving unix archive
2397 for (chain
= cls_ref_chain
; chain
; chain
= TREE_CHAIN (chain
))
2399 handle_next_class_ref (chain
);
2400 if (TREE_PURPOSE (chain
))
2401 generate_classref_translation_entry (chain
);
2404 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2405 handle_next_impent (impent
);
2407 /* Emit the strings tables. */
2408 generate_strings ();
2411 /* --- exceptions stuff --- */
2413 /* Predefine the following data type:
2415 struct _objc_exception_data
2417 int buf[OBJC_JBLEN];
2421 /* The following yuckiness should prevent users from having to #include
2422 <setjmp.h> in their code... */
2424 /* Define to a harmless positive value so the below code doesn't die. */
2426 #define OBJC_JBLEN 18
2430 build_next_objc_exception_stuff (void)
2432 tree decls
, temp_type
, *chain
= NULL
;
2434 objc_exception_data_template
2435 = objc_start_struct (get_identifier (UTAG_EXCDATA
));
2437 /* int buf[OBJC_JBLEN]; */
2439 temp_type
= build_sized_array_type (integer_type_node
, OBJC_JBLEN
);
2440 decls
= add_field_decl (temp_type
, "buf", &chain
);
2442 /* void *pointers[4]; */
2444 temp_type
= build_sized_array_type (ptr_type_node
, 4);
2445 add_field_decl (temp_type
, "pointers", &chain
);
2447 objc_finish_struct (objc_exception_data_template
, decls
);
2449 /* int _setjmp(...); */
2450 /* If the user includes <setjmp.h>, this shall be superseded by
2451 'int _setjmp(jmp_buf);' */
2452 temp_type
= build_varargs_function_type_list (integer_type_node
, NULL_TREE
);
2454 = add_builtin_function (TAG_SETJMP
, temp_type
, 0, NOT_BUILT_IN
, NULL
, NULL_TREE
);
2456 /* id objc_exception_extract(struct _objc_exception_data *); */
2458 = build_function_type_list (objc_object_type
,
2459 build_pointer_type (objc_exception_data_template
),
2461 objc_exception_extract_decl
2462 = add_builtin_function (TAG_EXCEPTIONEXTRACT
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2464 /* void objc_exception_try_enter(struct _objc_exception_data *); */
2465 /* void objc_exception_try_exit(struct _objc_exception_data *); */
2467 = build_function_type_list (void_type_node
,
2468 build_pointer_type (objc_exception_data_template
),
2470 objc_exception_try_enter_decl
2471 = add_builtin_function (TAG_EXCEPTIONTRYENTER
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2473 objc_exception_try_exit_decl
2474 = add_builtin_function (TAG_EXCEPTIONTRYEXIT
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2477 /* int objc_exception_match(id, id); */
2479 = build_function_type_list (integer_type_node
,
2480 objc_object_type
, objc_object_type
, NULL_TREE
);
2481 objc_exception_match_decl
2482 = add_builtin_function (TAG_EXCEPTIONMATCH
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2485 /* id objc_assign_ivar (id, id, unsigned int); */
2486 /* id objc_assign_ivar_Fast (id, id, unsigned int)
2487 __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2489 = build_function_type_list (objc_object_type
,
2494 objc_assign_ivar_decl
2495 = add_builtin_function (TAG_ASSIGNIVAR
, temp_type
, 0, NOT_BUILT_IN
,
2497 #ifdef OFFS_ASSIGNIVAR_FAST
2498 objc_assign_ivar_fast_decl
2499 = add_builtin_function (TAG_ASSIGNIVAR_FAST
, temp_type
, 0,
2500 NOT_BUILT_IN
, NULL
, NULL_TREE
);
2501 DECL_ATTRIBUTES (objc_assign_ivar_fast_decl
)
2502 = tree_cons (get_identifier ("hard_coded_address"),
2503 build_int_cst (NULL_TREE
, OFFS_ASSIGNIVAR_FAST
),
2506 /* Default to slower ivar method. */
2507 objc_assign_ivar_fast_decl
= objc_assign_ivar_decl
;
2510 /* id objc_assign_global (id, id *); */
2511 /* id objc_assign_strongCast (id, id *); */
2512 temp_type
= build_function_type_list (objc_object_type
,
2514 build_pointer_type (objc_object_type
),
2516 objc_assign_global_decl
2517 = add_builtin_function (TAG_ASSIGNGLOBAL
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2519 objc_assign_strong_cast_decl
2520 = add_builtin_function (TAG_ASSIGNSTRONGCAST
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2524 /* --- NeXT V1 SJLJ Exceptions --- */
2526 /* Build "objc_exception_try_exit(&_stack)". */
2529 next_sjlj_build_try_exit (struct objc_try_context
**ctcp
)
2532 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2533 t
= tree_cons (NULL
, t
, NULL
);
2534 t
= build_function_call (input_location
,
2535 objc_exception_try_exit_decl
, t
);
2540 objc_exception_try_enter (&_stack);
2541 if (_setjmp(&_stack.buf))
2545 Return the COND_EXPR. Note that the THEN and ELSE fields are left
2546 empty, ready for the caller to fill them in. */
2549 next_sjlj_build_enter_and_setjmp (struct objc_try_context
**ctcp
)
2551 tree t
, enter
, sj
, cond
;
2553 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2554 t
= tree_cons (NULL
, t
, NULL
);
2555 enter
= build_function_call (input_location
,
2556 objc_exception_try_enter_decl
, t
);
2558 t
= objc_build_component_ref ((*ctcp
)->stack_decl
,
2559 get_identifier ("buf"));
2560 t
= build_fold_addr_expr_loc (input_location
, t
);
2562 /* Convert _setjmp argument to type that is expected. */
2563 if (prototype_p (TREE_TYPE (objc_setjmp_decl
)))
2564 t
= convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl
))), t
);
2566 t
= convert (ptr_type_node
, t
);
2568 t
= convert (ptr_type_node
, t
);
2570 t
= tree_cons (NULL
, t
, NULL
);
2571 sj
= build_function_call (input_location
,
2572 objc_setjmp_decl
, t
);
2574 cond
= build2 (COMPOUND_EXPR
, TREE_TYPE (sj
), enter
, sj
);
2575 cond
= c_common_truthvalue_conversion (input_location
, cond
);
2577 return build3 (COND_EXPR
, void_type_node
, cond
, NULL
, NULL
);
2582 DECL = objc_exception_extract(&_stack); */
2585 next_sjlj_build_exc_extract (struct objc_try_context
**ctcp
, tree decl
)
2589 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2590 t
= tree_cons (NULL
, t
, NULL
);
2591 t
= build_function_call (input_location
,
2592 objc_exception_extract_decl
, t
);
2593 t
= convert (TREE_TYPE (decl
), t
);
2594 t
= build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
2600 if (objc_exception_match(obj_get_class(TYPE), _caught)
2607 objc_exception_try_exit(&_stack);
2609 from the sequence of CATCH_EXPRs in the current try context. */
2612 next_sjlj_build_catch_list (struct objc_try_context
**ctcp
)
2614 tree_stmt_iterator i
= tsi_start ((*ctcp
)->catch_list
);
2616 tree
*last
= &catch_seq
;
2617 bool saw_id
= false;
2619 for (; !tsi_end_p (i
); tsi_next (&i
))
2621 tree stmt
= tsi_stmt (i
);
2622 tree type
= CATCH_TYPES (stmt
);
2623 tree body
= CATCH_BODY (stmt
);
2625 if (type
!= error_mark_node
2626 && objc_is_object_id (TREE_TYPE (type
)))
2636 if (type
== error_mark_node
)
2637 cond
= error_mark_node
;
2640 args
= tree_cons (NULL
, (*ctcp
)->caught_decl
, NULL
);
2641 t
= objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type
)));
2642 args
= tree_cons (NULL
, t
, args
);
2643 t
= build_function_call (input_location
,
2644 objc_exception_match_decl
, args
);
2645 cond
= c_common_truthvalue_conversion (input_location
, t
);
2647 t
= build3 (COND_EXPR
, void_type_node
, cond
, body
, NULL
);
2648 SET_EXPR_LOCATION (t
, EXPR_LOCATION (stmt
));
2651 last
= &COND_EXPR_ELSE (t
);
2657 t
= build2 (MODIFY_EXPR
, void_type_node
, (*ctcp
)->rethrow_decl
,
2658 (*ctcp
)->caught_decl
);
2659 SET_EXPR_LOCATION (t
, (*ctcp
)->end_catch_locus
);
2660 append_to_statement_list (t
, last
);
2662 t
= next_sjlj_build_try_exit (ctcp
);
2663 SET_EXPR_LOCATION (t
, (*ctcp
)->end_catch_locus
);
2664 append_to_statement_list (t
, last
);
2670 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2671 exception handling. We aim to build:
2674 struct _objc_exception_data _stack;
2678 objc_exception_try_enter (&_stack);
2679 if (_setjmp(&_stack.buf))
2681 id _caught = objc_exception_extract(&_stack);
2682 objc_exception_try_enter (&_stack);
2683 if (_setjmp(&_stack.buf))
2684 _rethrow = objc_exception_extract(&_stack);
2694 objc_exception_try_exit(&_stack);
2697 objc_exception_throw(_rethrow);
2701 If CATCH-LIST is empty, we can omit all of the block containing
2702 "_caught" except for the setting of _rethrow. Note the use of
2703 a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2704 but handles goto and other exits from the block. */
2707 next_sjlj_build_try_catch_finally (struct objc_try_context
**ctcp
)
2709 tree rethrow_decl
, stack_decl
, t
;
2710 tree catch_seq
, try_fin
, bind
;
2711 struct objc_try_context
*cur_try_context
= *ctcp
;
2713 /* Create the declarations involved. */
2714 t
= xref_tag (RECORD_TYPE
, get_identifier (UTAG_EXCDATA
));
2715 stack_decl
= objc_create_temporary_var (t
, NULL
);
2716 cur_try_context
->stack_decl
= stack_decl
;
2718 rethrow_decl
= objc_create_temporary_var (objc_object_type
, NULL
);
2719 cur_try_context
->rethrow_decl
= rethrow_decl
;
2720 TREE_CHAIN (rethrow_decl
) = stack_decl
;
2722 /* Build the outermost variable binding level. */
2723 bind
= build3 (BIND_EXPR
, void_type_node
, rethrow_decl
, NULL
, NULL
);
2724 SET_EXPR_LOCATION (bind
, cur_try_context
->try_locus
);
2725 TREE_SIDE_EFFECTS (bind
) = 1;
2727 /* Initialize rethrow_decl. */
2728 t
= build2 (MODIFY_EXPR
, void_type_node
, rethrow_decl
,
2729 convert (objc_object_type
, null_pointer_node
));
2730 SET_EXPR_LOCATION (t
, cur_try_context
->try_locus
);
2731 append_to_statement_list (t
, &BIND_EXPR_BODY (bind
));
2733 /* Build the outermost TRY_FINALLY_EXPR. */
2734 try_fin
= build2 (TRY_FINALLY_EXPR
, void_type_node
, NULL
, NULL
);
2735 SET_EXPR_LOCATION (try_fin
, cur_try_context
->try_locus
);
2736 TREE_SIDE_EFFECTS (try_fin
) = 1;
2737 append_to_statement_list (try_fin
, &BIND_EXPR_BODY (bind
));
2739 /* Create the complete catch sequence. */
2740 if (cur_try_context
->catch_list
)
2742 tree caught_decl
= objc_build_exc_ptr (ctcp
);
2743 catch_seq
= build_stmt (input_location
, BIND_EXPR
, caught_decl
, NULL
, NULL
);
2744 TREE_SIDE_EFFECTS (catch_seq
) = 1;
2746 t
= next_sjlj_build_exc_extract (ctcp
, caught_decl
);
2747 append_to_statement_list (t
, &BIND_EXPR_BODY (catch_seq
));
2749 t
= next_sjlj_build_enter_and_setjmp (ctcp
);
2750 COND_EXPR_THEN (t
) = next_sjlj_build_exc_extract (ctcp
, rethrow_decl
);
2751 COND_EXPR_ELSE (t
) = next_sjlj_build_catch_list (ctcp
);
2752 append_to_statement_list (t
, &BIND_EXPR_BODY (catch_seq
));
2755 catch_seq
= next_sjlj_build_exc_extract (ctcp
, rethrow_decl
);
2756 SET_EXPR_LOCATION (catch_seq
, cur_try_context
->end_try_locus
);
2758 /* Build the main register-and-try if statement. */
2759 t
= next_sjlj_build_enter_and_setjmp (ctcp
);
2760 SET_EXPR_LOCATION (t
, cur_try_context
->try_locus
);
2761 COND_EXPR_THEN (t
) = catch_seq
;
2762 COND_EXPR_ELSE (t
) = cur_try_context
->try_body
;
2763 TREE_OPERAND (try_fin
, 0) = t
;
2765 /* Build the complete FINALLY statement list. */
2766 t
= next_sjlj_build_try_exit (ctcp
);
2767 t
= build_stmt (input_location
, COND_EXPR
,
2768 c_common_truthvalue_conversion
2769 (input_location
, rethrow_decl
),
2771 SET_EXPR_LOCATION (t
, cur_try_context
->finally_locus
);
2772 append_to_statement_list (t
, &TREE_OPERAND (try_fin
, 1));
2774 append_to_statement_list (cur_try_context
->finally_body
,
2775 &TREE_OPERAND (try_fin
, 1));
2777 t
= tree_cons (NULL
, rethrow_decl
, NULL
);
2778 t
= build_function_call (input_location
,
2779 objc_exception_throw_decl
, t
);
2780 t
= build_stmt (input_location
, COND_EXPR
,
2781 c_common_truthvalue_conversion (input_location
,
2784 SET_EXPR_LOCATION (t
, cur_try_context
->end_finally_locus
);
2785 append_to_statement_list (t
, &TREE_OPERAND (try_fin
, 1));
2790 /* We do not expect this to be used at the moment.
2791 If (a) it is possible to implement unwinder exceptions.
2792 (b) we do it... then it might be possibly useful.
2794 static GTY(()) tree objc_eh_personality_decl
;
2797 objc_eh_runtime_type (tree type
)
2799 tree ident
, eh_id
, decl
, str
;
2802 if (type
== error_mark_node
)
2804 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2805 to prevent an ICE. Note that we know that the compiler will
2806 terminate with an error and this 'ErrorMarkNode' class name will
2807 never be actually used. */
2808 ident
= get_identifier ("ErrorMarkNode");
2809 goto make_err_class
;
2812 if (POINTER_TYPE_P (type
) && objc_is_object_id (TREE_TYPE (type
)))
2814 ident
= get_identifier ("id");
2815 goto make_err_class
;
2818 if (!POINTER_TYPE_P (type
) || !TYPED_OBJECT (TREE_TYPE (type
)))
2821 /* This routine is also called for c++'s catch clause; in which case,
2822 we use c++'s typeinfo decl. */
2823 return build_eh_type_type (type
);
2825 error ("non-objective-c type '%T' cannot be caught", type
);
2826 ident
= get_identifier ("ErrorMarkNode");
2827 goto make_err_class
;
2831 ident
= OBJC_TYPE_NAME (TREE_TYPE (type
));
2834 /* If this class was already referenced, then it will be output during
2835 meta-data emission, so we don't need to do it here. */
2836 decl
= get_objc_string_decl (ident
, class_names
);
2837 eh_id
= add_objc_string (ident
, class_names
);
2840 /* Not found ... so we need to build it - from the freshly-entered id. */
2841 decl
= get_objc_string_decl (ident
, class_names
);
2842 str
= my_build_string (IDENTIFIER_LENGTH (ident
) + 1,
2843 IDENTIFIER_POINTER (ident
));
2844 /* We have to finalize this var here, because this might be called after
2845 all the other metadata strings have been emitted. */
2846 finish_var_decl (decl
, str
);
2851 /* For NeXT ABI 0 and 1, the personality routines are just those of the
2852 underlying language. */
2855 objc_eh_personality (void)
2857 if (!objc_eh_personality_decl
)
2859 objc_eh_personality_decl
= build_personality_function ("gcc");
2861 objc_eh_personality_decl
= build_personality_function ("gxx");
2863 return objc_eh_personality_decl
;
2866 /* --- interfaces --- */
2869 build_throw_stmt (location_t loc
, tree throw_expr
, bool rethrown ATTRIBUTE_UNUSED
)
2872 vec
<tree
, va_gc
> *parms
;
2873 vec_alloc (parms
, 1);
2874 /* A throw is just a call to the runtime throw function with the
2875 object as a parameter. */
2876 parms
->quick_push (throw_expr
);
2877 t
= build_function_call_vec (loc
, vNULL
, objc_exception_throw_decl
, parms
,
2880 return add_stmt (t
);
2883 /* Build __builtin_eh_pointer, or the moral equivalent. In the case
2884 of Darwin, we'll arrange for it to be initialized (and associated
2885 with a binding) later. */
2888 objc_build_exc_ptr (struct objc_try_context
**cur_try_context
)
2890 if (flag_objc_sjlj_exceptions
)
2892 tree var
= (*cur_try_context
)->caught_decl
;
2895 var
= objc_create_temporary_var (objc_object_type
, NULL
);
2896 (*cur_try_context
)->caught_decl
= var
;
2903 t
= builtin_decl_explicit (BUILT_IN_EH_POINTER
);
2904 t
= build_call_expr (t
, 1, integer_zero_node
);
2905 return fold_convert (objc_object_type
, t
);
2910 begin_catch (struct objc_try_context
**cur_try_context
, tree type
,
2911 tree decl
, tree compound
, bool ellipsis ATTRIBUTE_UNUSED
)
2914 /* Record the data for the catch in the try context so that we can
2915 finalize it later. We treat ellipsis the same way as catching
2917 t
= build_stmt (input_location
, CATCH_EXPR
, type
, compound
);
2918 (*cur_try_context
)->current_catch
= t
;
2920 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
2921 t
= objc_build_exc_ptr (cur_try_context
);
2922 t
= convert (TREE_TYPE (decl
), t
);
2923 return build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
2927 finish_catch (struct objc_try_context
**cur_try_context
, tree current_catch
)
2929 append_to_statement_list (current_catch
, &((*cur_try_context
)->catch_list
));
2933 finish_try_stmt (struct objc_try_context
**cur_try_context
)
2936 struct objc_try_context
*c
= *cur_try_context
;
2937 /* If we're doing Darwin setjmp exceptions, build the big nasty. */
2938 if (flag_objc_sjlj_exceptions
)
2940 bool save
= in_late_binary_op
;
2941 in_late_binary_op
= true;
2942 if (!c
->finally_body
)
2944 c
->finally_locus
= input_location
;
2945 c
->end_finally_locus
= input_location
;
2947 stmt
= next_sjlj_build_try_catch_finally (cur_try_context
);
2948 in_late_binary_op
= save
;
2951 /* This doesn't happen at the moment... but maybe one day... */
2953 /* Otherwise, nest the CATCH inside a FINALLY. */
2956 stmt
= build_stmt (c
->try_locus
, TRY_CATCH_EXPR
, stmt
, c
->catch_list
);
2957 if (c
->finally_body
)
2958 stmt
= build_stmt (c
->try_locus
, TRY_FINALLY_EXPR
, stmt
, c
->finally_body
);
2963 #include "gt-objc-objc-next-runtime-abi-01.h"