1 /* Next Runtime (ABI-0/1) private.
2 Copyright (C) 2011 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"
38 #include "langhooks.h"
39 #include "c-family/c-objc.h"
42 /* When building Objective-C++, we are not linking against the C
43 front-end and so need to replicate the C tree-construction
44 functions in some way. */
46 #define OBJCP_REMAP_FUNCTIONS
47 #include "objcp-decl.h"
53 #include "tree-iterator.h"
55 #include "objc-runtime-hooks.h"
56 #include "objc-runtime-shared-support.h"
58 /* NeXT ABI 0 and 1 private definitions. */
59 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
61 #define TAG_GETCLASS "objc_getClass"
62 #define TAG_GETMETACLASS "objc_getMetaClass"
64 #define TAG_MSGSEND "objc_msgSend"
65 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
66 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
67 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
69 /* NeXT-specific tags. */
71 #define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
72 #define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
73 #define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
74 #define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
75 #define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
76 #define TAG_EXCEPTIONMATCH "objc_exception_match"
77 #define TAG_SETJMP "_setjmp"
79 #define TAG_ASSIGNIVAR "objc_assign_ivar"
80 #define TAG_ASSIGNGLOBAL "objc_assign_global"
81 #define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
83 /* Branch entry points. All that matters here are the addresses;
84 functions with these names do not really exist in libobjc. */
86 #define TAG_MSGSEND_FAST "objc_msgSend_Fast"
87 #define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
89 /* The version identifies which language generation and runtime the
90 module (file) was compiled for, and is recorded in the module
92 #define OBJC_VERSION (flag_objc_abi >= 1 ? 7 : 6)
94 #define UTAG_CLASS_EXT "_objc_class_ext"
95 #define UTAG_PROPERTY_LIST "_prop_list_t"
96 #define UTAG_PROTOCOL_EXT "_objc_protocol_extension"
98 #define CLS_HAS_CXX_STRUCTORS 0x2000L
100 /* rt_trees identifiers - shared between NeXT implementations. These
101 allow the FE to tag meta-data in a manner that survives LTO and can
102 be used when the runtime requires that certain meta-data items
103 appear in particular named sections. */
105 #include "objc-next-metadata-tags.h"
106 extern GTY(()) tree objc_rt_trees
[OCTI_RT_META_MAX
];
108 static void next_runtime_01_initialize (void);
110 static tree
next_runtime_abi_01_super_superclassfield_id (void);
112 static tree
next_runtime_abi_01_class_decl (tree
);
113 static tree
next_runtime_abi_01_metaclass_decl (tree
);
114 static tree
next_runtime_abi_01_category_decl (tree
);
115 static tree
next_runtime_abi_01_protocol_decl (tree
);
116 static tree
next_runtime_abi_01_string_decl (tree
, const char *, string_section
);
118 static tree
next_runtime_abi_01_get_class_reference (tree
);
119 static tree
next_runtime_abi_01_build_selector_reference (location_t
, tree
, tree
);
120 static tree
next_runtime_abi_01_get_protocol_reference (location_t
, tree
);
121 static tree
next_runtime_abi_01_build_ivar_ref (location_t
, tree
, tree
);
122 static tree
next_runtime_abi_01_get_class_super_ref (location_t
, struct imp_entry
*, bool);
123 static tree
next_runtime_abi_01_get_category_super_ref (location_t
, struct imp_entry
*, bool);
125 static tree
next_runtime_abi_01_receiver_is_class_object (tree
);
126 static tree
next_runtime_abi_01_get_arg_type_list_base (tree
, int, int);
127 static tree
next_runtime_abi_01_build_objc_method_call (location_t
, tree
, tree
,
128 tree
, tree
, tree
, int);
129 static bool next_runtime_abi_01_setup_const_string_class_decl (void);
130 static tree
next_runtime_abi_01_build_const_string_constructor (location_t
, tree
, int);
132 static void objc_generate_v1_next_metadata (void);
134 static void build_next_objc_exception_stuff (void);
135 static tree
objc_eh_runtime_type (tree type
);
136 static tree
objc_eh_personality (void);
137 static tree
build_throw_stmt (location_t
, tree
, bool);
138 static tree
objc_build_exc_ptr (struct objc_try_context
**);
139 static tree
begin_catch (struct objc_try_context
**, tree
, tree
, tree
, bool);
140 static void finish_catch (struct objc_try_context
**, tree
);
141 static tree
finish_try_stmt (struct objc_try_context
**);
144 objc_next_runtime_abi_01_init (objc_runtime_hooks
*rthooks
)
146 if (flag_objc_exceptions
147 && !flag_objc_sjlj_exceptions
)
149 warning_at (UNKNOWN_LOCATION
, OPT_Wall
,
150 "%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
151 "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2");
154 rthooks
->initialize
= next_runtime_01_initialize
;
155 rthooks
->default_constant_string_class_name
= DEF_CONSTANT_STRING_CLASS_NAME
;
156 rthooks
->tag_getclass
= TAG_GETCLASS
;
157 rthooks
->super_superclassfield_ident
= next_runtime_abi_01_super_superclassfield_id
;
159 rthooks
->class_decl
= next_runtime_abi_01_class_decl
;
160 rthooks
->metaclass_decl
= next_runtime_abi_01_metaclass_decl
;
161 rthooks
->category_decl
= next_runtime_abi_01_category_decl
;
162 rthooks
->protocol_decl
= next_runtime_abi_01_protocol_decl
;
163 rthooks
->string_decl
= next_runtime_abi_01_string_decl
;
165 rthooks
->get_class_reference
= next_runtime_abi_01_get_class_reference
;
166 rthooks
->build_selector_reference
= next_runtime_abi_01_build_selector_reference
;
167 rthooks
->get_protocol_reference
= next_runtime_abi_01_get_protocol_reference
;
168 rthooks
->build_ivar_reference
= next_runtime_abi_01_build_ivar_ref
;
169 rthooks
->get_class_super_ref
= next_runtime_abi_01_get_class_super_ref
;
170 rthooks
->get_category_super_ref
= next_runtime_abi_01_get_category_super_ref
;
172 rthooks
->receiver_is_class_object
= next_runtime_abi_01_receiver_is_class_object
;
173 rthooks
->get_arg_type_list_base
= next_runtime_abi_01_get_arg_type_list_base
;
174 rthooks
->build_objc_method_call
= next_runtime_abi_01_build_objc_method_call
;
176 rthooks
->setup_const_string_class_decl
=
177 next_runtime_abi_01_setup_const_string_class_decl
;
178 rthooks
->build_const_string_constructor
=
179 next_runtime_abi_01_build_const_string_constructor
;
181 rthooks
->build_throw_stmt
= build_throw_stmt
;
182 rthooks
->build_exc_ptr
= objc_build_exc_ptr
;
183 rthooks
->begin_catch
= begin_catch
;
184 rthooks
->finish_catch
= finish_catch
;
185 rthooks
->finish_try_stmt
= finish_try_stmt
;
187 rthooks
->generate_metadata
= objc_generate_v1_next_metadata
;
191 /* We need a way to convey what kind of meta-data are represented by a
192 given variable, since each type is expected (by the runtime) to be
193 found in a specific named section. The solution must be usable
196 The scheme used for NeXT ABI 0/1 (partial matching of variable
197 names) is not satisfactory for LTO & ABI-2. We now tag ObjC
198 meta-data with identification attributes in the front end. The
199 back-end may choose to act on these as it requires. */
202 next_runtime_abi_01_init_metadata_attributes (void)
205 objc_meta
= get_identifier ("OBJC1META");
208 meta_base
= get_identifier ("V1_BASE");
210 meta_class
= get_identifier ("V1_CLAS");
211 meta_metaclass
= get_identifier ("V1_META");
212 meta_category
= get_identifier ("V1_CATG");
213 meta_protocol
= get_identifier ("V1_PROT");
215 meta_clac_vars
= get_identifier ("V1_CLCV");
216 meta_clai_vars
= get_identifier ("V1_CLIV");
218 meta_clac_meth
= get_identifier ("V1_CLCM");
219 meta_clai_meth
= get_identifier ("V1_CLIM");
220 meta_catc_meth
= get_identifier ("V1_CACM");
221 meta_cati_meth
= get_identifier ("V1_CAIM");
222 meta_proto_cls_meth
= get_identifier ("V1_PCLM");
223 meta_proto_nst_meth
= get_identifier ("V1_PNSM");
225 meta_clas_prot
= get_identifier ("V1_CLPR");
226 meta_catg_prot
= get_identifier ("V1_CAPR");
228 meta_class_reference
= get_identifier ("V1_CLRF");
229 meta_proto_ref
= get_identifier ("V1_PRFS");
230 meta_sel_refs
= get_identifier ("V1_SRFS");
232 meta_class_name
= get_identifier ("V1_CLSN");
233 meta_meth_name
= get_identifier ("V1_METN");
234 meta_meth_type
= get_identifier ("V1_METT");
235 meta_prop_name_attr
= get_identifier ("V1_STRG");
237 meta_modules
= get_identifier ("V1_MODU");
238 meta_symtab
= get_identifier ("V1_SYMT");
239 meta_info
= get_identifier ("V1_INFO");
241 meta_proplist
= get_identifier ("V1_PLST");
242 meta_protocol_extension
= get_identifier ("V1_PEXT");
243 meta_class_extension
= get_identifier ("V1_CEXT");
245 meta_const_str
= get_identifier ("V1_CSTR");
248 static void build_v1_class_template (void);
249 static void build_v1_category_template (void);
250 static void build_v1_protocol_template (void);
252 static void next_runtime_01_initialize (void)
257 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
259 if (!global_options_set
.x_flag_objc_call_cxx_cdtors
)
260 global_options
.x_flag_objc_call_cxx_cdtors
= 1;
263 /* Set up attributes to be attached to the meta-data so that they
264 will be placed in the correct sections. */
265 next_runtime_abi_01_init_metadata_attributes ();
267 if (flag_objc_abi
>= 1)
268 objc_prop_list_ptr
= build_pointer_type (xref_tag (RECORD_TYPE
,
269 get_identifier ("_prop_list_t")));
271 /* Declare type of selector-objects that represent an operation
273 /* `struct objc_selector *' */
274 objc_selector_type
= build_pointer_type (xref_tag (RECORD_TYPE
,
275 get_identifier (TAG_SELECTOR
)));
277 build_v1_class_template ();
278 build_super_template ();
279 build_v1_protocol_template ();
280 build_v1_category_template ();
282 /* NB: In order to call one of the ..._stret (struct-returning)
283 functions, the function *MUST* first be cast to a signature that
284 corresponds to the actual ObjC method being invoked. This is
285 what is done by the build_objc_method_call() routine below. */
287 /* id objc_msgSend (id, SEL, ...); */
288 /* id objc_msgSendNonNil (id, SEL, ...); */
289 /* id objc_msgSend_stret (id, SEL, ...); */
290 /* id objc_msgSendNonNil_stret (id, SEL, ...); */
291 type
= build_varargs_function_type_list (objc_object_type
,
296 umsg_decl
= add_builtin_function (TAG_MSGSEND
,
297 type
, 0, NOT_BUILT_IN
,
300 umsg_nonnil_decl
= add_builtin_function (TAG_MSGSEND_NONNIL
,
301 type
, 0, NOT_BUILT_IN
,
304 umsg_stret_decl
= add_builtin_function (TAG_MSGSEND_STRET
,
305 type
, 0, NOT_BUILT_IN
,
308 umsg_nonnil_stret_decl
= add_builtin_function (TAG_MSGSEND_NONNIL_STRET
,
309 type
, 0, NOT_BUILT_IN
,
312 /* These can throw, because the function that gets called can throw
313 in Obj-C++, or could itself call something that can throw even in
315 TREE_NOTHROW (umsg_decl
) = 0;
316 TREE_NOTHROW (umsg_nonnil_decl
) = 0;
317 TREE_NOTHROW (umsg_stret_decl
) = 0;
318 TREE_NOTHROW (umsg_nonnil_stret_decl
) = 0;
320 /* id objc_msgSend_Fast (id, SEL, ...)
321 __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
322 #ifdef OFFS_MSGSEND_FAST
323 umsg_fast_decl
= add_builtin_function (TAG_MSGSEND_FAST
,
324 type
, 0, NOT_BUILT_IN
,
326 TREE_NOTHROW (umsg_fast_decl
) = 0;
327 DECL_ATTRIBUTES (umsg_fast_decl
)
328 = tree_cons (get_identifier ("hard_coded_address"),
329 build_int_cst (NULL_TREE
, OFFS_MSGSEND_FAST
),
332 /* No direct dispatch available. */
333 umsg_fast_decl
= umsg_decl
;
336 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
337 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
338 type
= build_varargs_function_type_list (objc_object_type
,
342 umsg_super_decl
= add_builtin_function (TAG_MSGSENDSUPER
,
343 type
, 0, NOT_BUILT_IN
,
345 umsg_super_stret_decl
= add_builtin_function (TAG_MSGSENDSUPER_STRET
,
346 type
, 0, NOT_BUILT_IN
, 0,
348 TREE_NOTHROW (umsg_super_decl
) = 0;
349 TREE_NOTHROW (umsg_super_stret_decl
) = 0;
351 type
= build_function_type_list (objc_object_type
,
352 const_string_type_node
,
355 /* id objc_getClass (const char *); */
357 = add_builtin_function (TAG_GETCLASS
, type
, 0, NOT_BUILT_IN
,
360 /* id objc_getMetaClass (const char *); */
361 objc_get_meta_class_decl
362 = add_builtin_function (TAG_GETMETACLASS
, type
, 0, NOT_BUILT_IN
, NULL
, NULL_TREE
);
364 /* This is the type of all of the following functions
365 objc_copyStruct(). */
366 type
= build_function_type_list (void_type_node
,
373 /* Declare the following function:
375 objc_copyStruct (void *destination, const void *source,
376 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
377 objc_copyStruct_decl
= add_builtin_function ("objc_copyStruct",
378 type
, 0, NOT_BUILT_IN
,
380 TREE_NOTHROW (objc_copyStruct_decl
) = 0;
381 objc_getPropertyStruct_decl
= NULL_TREE
;
382 objc_setPropertyStruct_decl
= NULL_TREE
;
384 build_next_objc_exception_stuff ();
385 if (flag_objc_exceptions
&& !flag_objc_sjlj_exceptions
)
386 using_eh_for_cleanups ();
387 lang_hooks
.eh_runtime_type
= objc_eh_runtime_type
;
388 lang_hooks
.eh_personality
= objc_eh_personality
;
391 /* --- templates --- */
393 /* struct _objc_class
395 struct _objc_class *isa;
396 struct _objc_class *super_class;
401 struct _objc_ivar_list *ivars;
402 struct _objc_method_list *methods;
403 struct objc_cache *cache;
404 struct _objc_protocol_list *protocols;
406 const char *ivar_layout;
407 struct _objc_class_ext *ext;
410 void *gc_object_type;
414 /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT
415 runtime. We generate them for ABI==0 to maintain backward binary
419 build_v1_class_template (void)
421 tree ptype
, decls
, *chain
= NULL
;
423 objc_class_template
= objc_start_struct (get_identifier (UTAG_CLASS
));
425 /* struct _objc_class *isa; */
426 decls
= add_field_decl (build_pointer_type (objc_class_template
),
429 /* struct _objc_class *super_class; */
430 add_field_decl (build_pointer_type (objc_class_template
),
431 "super_class", &chain
);
434 add_field_decl (string_type_node
, "name", &chain
);
437 add_field_decl (long_integer_type_node
, "version", &chain
);
440 add_field_decl (long_integer_type_node
, "info", &chain
);
442 /* long instance_size; */
443 add_field_decl (long_integer_type_node
, "instance_size", &chain
);
445 /* struct _objc_ivar_list *ivars; */
446 add_field_decl (objc_ivar_list_ptr
,"ivars", &chain
);
448 /* struct _objc_method_list *methods; */
449 add_field_decl (objc_method_list_ptr
, "methods", &chain
);
451 /* struct objc_cache *cache; */
452 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
453 get_identifier ("objc_cache")));
454 add_field_decl (ptype
, "cache", &chain
);
456 /* struct _objc_protocol **protocol_list; */
457 ptype
= build_pointer_type (build_pointer_type
458 (xref_tag (RECORD_TYPE
,
459 get_identifier (UTAG_PROTOCOL
))));
460 add_field_decl (ptype
, "protocol_list", &chain
);
462 if (flag_objc_abi
>= 1)
464 /* const char *ivar_layout; */
465 add_field_decl (const_string_type_node
, "ivar_layout", &chain
);
467 /* struct _objc_class_ext *ext; */
468 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
469 get_identifier (UTAG_CLASS_EXT
)));
470 add_field_decl (ptype
, "ext", &chain
);
475 add_field_decl (build_pointer_type (void_type_node
), "sel_id", &chain
);
476 /* void *gc_object_type; */
477 add_field_decl (build_pointer_type (void_type_node
), "gc_object_type",
481 objc_finish_struct (objc_class_template
, decls
);
484 /* struct _objc_category
488 struct _objc_method_list *instance_methods;
489 struct _objc_method_list *class_methods;
490 struct _objc_protocol_list *protocols;
492 uint32_t size; // sizeof (struct _objc_category)
493 struct _objc_property_list *instance_properties; // category's own @property decl.
498 build_v1_category_template (void)
500 tree ptype
, decls
, *chain
= NULL
;
502 objc_category_template
= objc_start_struct (get_identifier (UTAG_CATEGORY
));
504 /* char *category_name; */
505 decls
= add_field_decl (string_type_node
, "category_name", &chain
);
507 /* char *class_name; */
508 add_field_decl (string_type_node
, "class_name", &chain
);
510 /* struct _objc_method_list *instance_methods; */
511 add_field_decl (objc_method_list_ptr
, "instance_methods", &chain
);
513 /* struct _objc_method_list *class_methods; */
514 add_field_decl (objc_method_list_ptr
, "class_methods", &chain
);
516 /* struct _objc_protocol **protocol_list; */
517 ptype
= build_pointer_type (build_pointer_type (objc_protocol_template
));
518 add_field_decl (ptype
, "protocol_list", &chain
);
520 if (flag_objc_abi
>= 1)
522 add_field_decl (integer_type_node
, "size", &chain
);
524 /* struct _objc_property_list *instance_properties;
525 This field describes a category's @property declarations.
526 Properties from inherited protocols are not included. */
527 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
528 get_identifier (UTAG_PROPERTY_LIST
)));
529 add_field_decl (ptype
, "instance_properties", &chain
);
531 objc_finish_struct (objc_category_template
, decls
);
534 /* Begin code generation for protocols...
535 Modified for ObjC #1 extensions. */
537 /* struct _objc_protocol
540 struct _objc_protocol_extension *isa;
542 struct _objc_class *isa;
546 struct _objc_protocol **protocol_list;
547 struct _objc__method_prototype_list *instance_methods;
548 struct _objc__method_prototype_list *class_methods;
552 build_v1_protocol_template (void)
554 tree ptype
, decls
, *chain
= NULL
;
556 objc_protocol_template
= objc_start_struct (get_identifier (UTAG_PROTOCOL
));
558 if (flag_objc_abi
>= 1)
559 /* struct _objc_protocol_extension *isa; */
560 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
561 get_identifier (UTAG_PROTOCOL_EXT
)));
563 /* struct _objc_class *isa; */
564 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
565 get_identifier (UTAG_CLASS
)));
567 decls
= add_field_decl (ptype
, "isa", &chain
);
569 /* char *protocol_name; */
570 add_field_decl (string_type_node
, "protocol_name", &chain
);
572 /* struct _objc_protocol **protocol_list; */
573 ptype
= build_pointer_type (build_pointer_type (objc_protocol_template
));
574 add_field_decl (ptype
, "protocol_list", &chain
);
576 /* struct _objc__method_prototype_list *instance_methods; */
577 add_field_decl (objc_method_proto_list_ptr
, "instance_methods", &chain
);
579 /* struct _objc__method_prototype_list *class_methods; */
580 add_field_decl (objc_method_proto_list_ptr
, "class_methods", &chain
);
582 objc_finish_struct (objc_protocol_template
, decls
);
585 /* --- names, decls identifers --- */
588 next_runtime_abi_01_super_superclassfield_id (void)
590 if (!super_superclassfield_id
)
591 super_superclassfield_id
= get_identifier ("super_class");
592 return super_superclassfield_id
;
596 next_runtime_abi_01_class_decl (tree klass
)
600 snprintf (buf
, BUFSIZE
, "_OBJC_Class_%s",
601 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
602 decl
= start_var_decl (objc_class_template
, buf
);
603 OBJCMETA (decl
, objc_meta
, meta_class
);
608 next_runtime_abi_01_metaclass_decl (tree klass
)
612 snprintf (buf
, BUFSIZE
, "_OBJC_MetaClass_%s",
613 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
614 decl
= start_var_decl (objc_class_template
, buf
);
615 OBJCMETA (decl
, objc_meta
, meta_metaclass
);
620 next_runtime_abi_01_category_decl (tree klass
)
624 snprintf (buf
, BUFSIZE
, "_OBJC_Category_%s_on_%s",
625 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass
)),
626 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
627 decl
= start_var_decl (objc_category_template
, buf
);
628 OBJCMETA (decl
, objc_meta
, meta_category
);
633 next_runtime_abi_01_protocol_decl (tree p
)
638 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
640 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
641 IDENTIFIER_POINTER (PROTOCOL_NAME (p
)));
642 decl
= start_var_decl (objc_protocol_template
, buf
);
643 OBJCMETA (decl
, objc_meta
, meta_protocol
);
648 next_runtime_abi_01_string_decl (tree type
, const char *name
, string_section where
)
650 tree var
= start_var_decl (type
, name
);
654 OBJCMETA (var
, objc_meta
, meta_class_name
);
657 OBJCMETA (var
, objc_meta
, meta_meth_name
);
660 OBJCMETA (var
, objc_meta
, meta_meth_type
);
662 case prop_names_attr
:
663 OBJCMETA (var
, objc_meta
, meta_prop_name_attr
);
666 OBJCMETA (var
, objc_meta
, meta_base
);
674 static GTY(()) int class_reference_idx
;
677 build_class_reference_decl (void)
682 sprintf (buf
, "_OBJC_ClassRefs_%d", class_reference_idx
++);
683 decl
= start_var_decl (objc_class_type
, buf
);
689 next_runtime_abi_01_get_class_reference (tree ident
)
696 for (chain
= &cls_ref_chain
; *chain
; chain
= &TREE_CHAIN (*chain
))
697 if (TREE_VALUE (*chain
) == ident
)
699 if (! TREE_PURPOSE (*chain
))
700 TREE_PURPOSE (*chain
) = build_class_reference_decl ();
702 return TREE_PURPOSE (*chain
);
705 decl
= build_class_reference_decl ();
706 *chain
= tree_cons (decl
, ident
, NULL_TREE
);
713 add_class_reference (ident
);
715 params
= build_tree_list (NULL_TREE
,
716 my_build_string_pointer
717 (IDENTIFIER_LENGTH (ident
) + 1,
718 IDENTIFIER_POINTER (ident
)));
720 return build_function_call (input_location
, objc_get_class_decl
, params
);
724 /* Used by get_arg_type_list.
725 Return the types for receiver & _cmd at the start of a method argument list.
726 context is either METHOD_DEF or METHOD_REF, saying whether we are trying
727 to define a method or call one. superflag says this is for a send to super.
728 meth may be NULL, in the case that there is no prototype. */
731 next_runtime_abi_01_get_arg_type_list_base (tree meth
, int context
, int superflag
)
737 arglist
= build_tree_list (NULL_TREE
, objc_super_type
);
738 else if (context
== METHOD_DEF
&& TREE_CODE (meth
) == INSTANCE_METHOD_DECL
)
739 arglist
= build_tree_list (NULL_TREE
, objc_instance_type
);
741 arglist
= build_tree_list (NULL_TREE
, objc_object_type
);
743 /* Selector type - will eventually change to `int'. */
744 chainon (arglist
, build_tree_list (NULL_TREE
, objc_selector_type
));
749 next_runtime_abi_01_receiver_is_class_object (tree receiver
)
751 if (TREE_CODE (receiver
) == VAR_DECL
752 && IS_CLASS (TREE_TYPE (receiver
)))
754 /* The receiver is a variable created by build_class_reference_decl. */
755 tree chain
= cls_ref_chain
;
756 /* Look up the identifier in the relevant chain. */
757 for (; chain
; chain
= TREE_CHAIN (chain
))
758 if (TREE_PURPOSE (chain
) == receiver
)
759 return TREE_VALUE (chain
);
765 build_selector_reference_decl (tree ident
)
768 char *t
, buf
[BUFSIZE
];
770 snprintf (buf
, BUFSIZE
, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident
));
775 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
778 decl
= start_var_decl (objc_selector_type
, buf
);
779 OBJCMETA (decl
, objc_meta
, meta_sel_refs
);
784 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED
,
786 tree proto ATTRIBUTE_UNUSED
)
788 tree
*chain
= &sel_ref_chain
;
793 if (TREE_VALUE (*chain
) == ident
)
794 return TREE_PURPOSE (*chain
);
796 chain
= &TREE_CHAIN (*chain
);
799 expr
= build_selector_reference_decl (ident
);
801 *chain
= tree_cons (expr
, ident
, NULL_TREE
);
806 /* Build a tree expression to send OBJECT the operation SELECTOR,
807 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
808 assuming the method has prototype METHOD_PROTOTYPE.
809 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
810 LOC is the location of the expression to build.
811 Use METHOD_PARAMS as list of args to pass to the method.
812 If SUPER_FLAG is nonzero, we look up the superclass's method. */
815 build_objc_method_call (location_t loc
, int super_flag
, tree method_prototype
,
816 tree lookup_object
, tree selector
,
819 tree sender
, sender_cast
, method
, t
;
820 tree rcv_p
= (super_flag
? objc_super_type
: objc_object_type
);
821 VEC(tree
, gc
) *parms
;
822 unsigned nparm
= (method_params
? list_length (method_params
) : 0);
824 /* If a prototype for the method to be called exists, then cast
825 the sender's return type and arguments to match that of the method.
826 Otherwise, leave sender as is. */
829 ? TREE_VALUE (TREE_TYPE (method_prototype
))
832 tree method_param_types
=
833 get_arg_type_list (method_prototype
, METHOD_REF
, super_flag
);
834 tree ftype
= build_function_type (ret_type
, method_param_types
);
836 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
837 ftype
= build_type_attribute_variant (ftype
,
838 METHOD_TYPE_ATTRIBUTES
841 sender_cast
= build_pointer_type (ftype
);
843 lookup_object
= build_c_cast (loc
, rcv_p
, lookup_object
);
845 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
846 lookup_object
= save_expr (lookup_object
);
848 /* Param list + 2 slots for object and selector. */
849 parms
= VEC_alloc (tree
, gc
, nparm
+ 2);
851 /* If we are returning a struct in memory, and the address
852 of that memory location is passed as a hidden first
853 argument, then change which messenger entry point this
854 expr will call. NB: Note that sender_cast remains
855 unchanged (it already has a struct return type). */
856 if (!targetm
.calls
.struct_value_rtx (0, 0)
857 && (TREE_CODE (ret_type
) == RECORD_TYPE
858 || TREE_CODE (ret_type
) == UNION_TYPE
)
859 && targetm
.calls
.return_in_memory (ret_type
, 0))
860 sender
= (super_flag
? umsg_super_stret_decl
861 : flag_nil_receivers
? umsg_stret_decl
862 : umsg_nonnil_stret_decl
);
864 sender
= (super_flag
? umsg_super_decl
865 : (flag_nil_receivers
? (flag_objc_direct_dispatch
868 : umsg_nonnil_decl
));
869 method
= build_fold_addr_expr_loc (loc
, sender
);
871 /* Pass the object to the method. */
872 VEC_quick_push (tree
, parms
, lookup_object
);
873 /* Pass the selector to the method. */
874 VEC_quick_push (tree
, parms
, selector
);
875 /* Now append the remainder of the parms. */
877 for (; method_params
; method_params
= TREE_CHAIN (method_params
))
878 VEC_quick_push (tree
, parms
, TREE_VALUE (method_params
));
880 /* Build an obj_type_ref, with the correct cast for the method call. */
881 t
= build3 (OBJ_TYPE_REF
, sender_cast
, method
,
882 lookup_object
, size_zero_node
);
883 t
= build_function_call_vec (loc
, t
, parms
, NULL
);
884 VEC_free (tree
, gc
, parms
);
889 next_runtime_abi_01_build_objc_method_call (location_t loc
,
890 tree method_prototype
,
892 tree rtype ATTRIBUTE_UNUSED
,
897 tree selector
= next_runtime_abi_01_build_selector_reference (loc
, sel_name
,
900 return build_objc_method_call (loc
, super
, method_prototype
,
901 receiver
, selector
, method_params
);
905 next_runtime_abi_01_get_protocol_reference (location_t loc
, tree p
)
909 if (!PROTOCOL_FORWARD_DECL (p
))
910 PROTOCOL_FORWARD_DECL (p
) = next_runtime_abi_01_protocol_decl (p
);
912 expr
= build_unary_op (loc
, ADDR_EXPR
, PROTOCOL_FORWARD_DECL (p
), 0);
913 return convert (objc_protocol_type
, expr
);
916 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
919 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED
,
922 return objc_build_component_ref (base
, id
);
925 /* We build super class references as we need them (but keep them once
926 built for the sake of efficiency). */
929 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED
,
930 struct imp_entry
*imp
, bool inst_meth
)
936 objc_build_component_ref (imp
->class_decl
,
937 get_identifier ("super_class"));
938 return ucls_super_ref
;
942 if (!uucls_super_ref
)
944 objc_build_component_ref (imp
->meta_decl
,
945 get_identifier ("super_class"));
946 return uucls_super_ref
;
951 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED
,
952 struct imp_entry
*imp
, bool inst_meth
)
954 tree super_name
= CLASS_SUPER_NAME (imp
->imp_template
);
959 super_class
= objc_get_class_reference (super_name
);
963 /* If we are in a class method, we must retrieve the
964 _metaclass_ for the current class, pointed at by
965 the class's "isa" pointer. The following assumes that
966 "isa" is the first ivar in a class (which it must be). */
968 build_indirect_ref (input_location
,
969 build_c_cast (input_location
,
970 build_pointer_type (objc_class_type
),
976 /* else do it the slow way. */
977 add_class_reference (super_name
);
978 super_class
= (inst_meth
? objc_get_class_decl
: objc_get_meta_class_decl
);
979 /* assemble_external (super_class);*/
980 super_name
= my_build_string_pointer (IDENTIFIER_LENGTH (super_name
) + 1,
981 IDENTIFIER_POINTER (super_name
));
982 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
983 return build_function_call (input_location
,
985 build_tree_list (NULL_TREE
, super_name
));
989 next_runtime_abi_01_setup_const_string_class_decl (void)
991 if (!constant_string_global_id
)
993 /* Hopefully, this should not represent a serious limitation. */
995 snprintf (buf
, BUFSIZE
, "_%sClassReference", constant_string_class_name
);
996 constant_string_global_id
= get_identifier (buf
);
999 string_class_decl
= lookup_name (constant_string_global_id
);
1001 return (string_class_decl
!= NULL_TREE
);
1005 next_runtime_abi_01_build_const_string_constructor (location_t loc
, tree string
,
1008 tree constructor
, fields
, var
;
1009 VEC(constructor_elt
,gc
) *v
= NULL
;
1011 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1012 fields
= TYPE_FIELDS (internal_const_str_type
);
1013 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1014 build_unary_op (loc
, ADDR_EXPR
, string_class_decl
, 0));
1016 fields
= DECL_CHAIN (fields
);
1017 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1018 build_unary_op (loc
, ADDR_EXPR
, string
, 1));
1020 /* ??? check if this should be long. */
1021 fields
= DECL_CHAIN (fields
);
1022 CONSTRUCTOR_APPEND_ELT (v
, fields
, build_int_cst (NULL_TREE
, length
));
1023 constructor
= objc_build_constructor (internal_const_str_type
, v
);
1025 var
= build_decl (input_location
, CONST_DECL
, NULL
, TREE_TYPE (constructor
));
1026 DECL_INITIAL (var
) = constructor
;
1027 TREE_STATIC (var
) = 1;
1028 DECL_CONTEXT (var
) = NULL
;
1029 OBJCMETA (var
, objc_meta
, meta_const_str
);
1033 /* --- metadata templates --- */
1035 /* This routine builds the following type:
1037 const char * const name; // property name
1038 const char * const attributes; // comma-delimited, encoded,
1039 // property attributes
1043 static GTY(()) tree objc_v1_property_template
;
1046 build_v1_property_template (void)
1049 tree decls
, *chain
= NULL
;
1051 prop_record
= objc_start_struct (get_identifier ("_prop_t"));
1052 /* const char * name */
1053 decls
= add_field_decl (string_type_node
, "name", &chain
);
1055 /* const char * attribute */
1056 add_field_decl (string_type_node
, "attribute", &chain
);
1058 objc_finish_struct (prop_record
, decls
);
1062 /* Build the following type:
1064 struct _objc_protocol_extension
1066 uint32_t size; // sizeof (struct _objc_protocol_extension)
1067 struct objc_method_list *optional_instance_methods;
1068 struct objc_method_list *optional_class_methods;
1069 struct objc_prop_list *instance_properties;
1073 static GTY(()) tree objc_protocol_extension_template
;
1076 build_v1_objc_protocol_extension_template (void)
1078 tree decls
, *chain
= NULL
;
1080 objc_protocol_extension_template
=
1081 objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT
));
1083 /* uint32_t size; */
1084 decls
= add_field_decl (integer_type_node
, "size", &chain
);
1086 /* struct objc_method_list *optional_instance_methods; */
1087 add_field_decl (objc_method_list_ptr
, "optional_instance_methods", &chain
);
1089 /* struct objc_method_list *optional_class_methods; */
1090 add_field_decl (objc_method_list_ptr
, "optional_class_methods", &chain
);
1092 /* struct objc_prop_list *instance_properties; */
1093 add_field_decl (objc_prop_list_ptr
, "instance_properties", &chain
);
1095 objc_finish_struct (objc_protocol_extension_template
, decls
);
1098 /* This routine build following struct type:
1099 struct _objc_class_ext
1101 uint32_t size; // sizeof(struct _objc_class_ext)
1102 const char *weak_ivar_layout;
1103 struct _prop_list_t *properties;
1107 static GTY(()) tree objc_class_ext_template
;
1110 build_objc_class_ext_template (void)
1112 tree ptrt
, decls
, *chain
= NULL
;
1114 objc_class_ext_template
= objc_start_struct (get_identifier (UTAG_CLASS_EXT
));
1116 /* uint32_t size; */
1117 decls
= add_field_decl (integer_type_node
, "size", &chain
);
1119 /* const char *weak_ivar_layout; */
1120 add_field_decl (const_string_type_node
, "weak_ivar_layout", &chain
);
1122 /* struct _prop_list_t *properties; */
1123 ptrt
= build_pointer_type (xref_tag (RECORD_TYPE
,
1124 get_identifier(UTAG_PROPERTY_LIST
)));
1125 add_field_decl (ptrt
, "properties", &chain
);
1127 objc_finish_struct (objc_class_ext_template
, decls
);
1131 build_metadata_templates (void)
1134 if (!objc_method_template
)
1135 objc_method_template
= build_method_template ();
1141 /* --- emit metadata --- */
1144 generate_v1_meth_descriptor_table (tree chain
, tree protocol
,
1145 const char *prefix
, tree attr
)
1147 tree method_list_template
, initlist
, decl
;
1149 VEC(constructor_elt
,gc
) *v
= NULL
;
1152 if (!chain
|| !prefix
)
1155 if (!objc_method_prototype_template
)
1156 objc_method_prototype_template
= build_method_prototype_template ();
1158 size
= list_length (chain
);
1159 method_list_template
=
1160 build_method_prototype_list_template (objc_method_prototype_template
,
1162 snprintf (buf
, BUFSIZE
, "%s_%s", prefix
,
1163 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
1165 decl
= start_var_decl (method_list_template
, buf
);
1167 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1169 build_descriptor_table_initializer (objc_method_prototype_template
,
1171 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
1172 /* Get into the right section. */
1173 OBJCMETA (decl
, objc_meta
, attr
);
1174 finish_var_decl (decl
, objc_build_constructor (method_list_template
, v
));
1178 /* Build protocol ext =
1179 {size, opt_instance_meth, opt_class_meth, instance_props};
1180 or NULL_TREE if none are present. */
1183 generate_v1_objc_protocol_extension (tree proto_interface
,
1184 tree opt_instance_meth
,
1185 tree opt_class_meth
,
1186 tree instance_props
)
1190 VEC(constructor_elt
,gc
) *v
= NULL
;
1194 /* If there are no extensions, then don't bother... */
1195 if (!opt_instance_meth
&& !opt_class_meth
&& !instance_props
)
1198 if (!objc_protocol_extension_template
)
1199 build_v1_objc_protocol_extension_template ();
1202 size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template
));
1203 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1205 /* Try for meaningful diagnostics. */
1206 loc
= DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface
));
1208 /* struct objc_method_list *optional_instance_methods; */
1209 if (opt_instance_meth
)
1210 expr
= convert (objc_method_list_ptr
,
1211 build_unary_op (loc
, ADDR_EXPR
, opt_instance_meth
, 0));
1213 expr
= convert (objc_method_list_ptr
, null_pointer_node
);
1215 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1217 /* struct objc_method_list *optional_class_methods; */
1219 expr
= convert (objc_method_list_ptr
,
1220 build_unary_op (loc
, ADDR_EXPR
, opt_class_meth
, 0));
1222 expr
= convert (objc_method_list_ptr
, null_pointer_node
);
1224 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1225 /* struct objc_prop_list *instance_properties; */
1227 expr
= convert (objc_prop_list_ptr
,
1228 build_unary_op (loc
, ADDR_EXPR
, instance_props
, 0));
1230 expr
= convert (objc_prop_list_ptr
, null_pointer_node
);
1232 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1233 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolExt_%s",
1234 IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface
)));
1236 decl
= start_var_decl (objc_protocol_extension_template
, buf
);
1237 expr
= objc_build_constructor (TREE_TYPE (decl
), v
);
1238 OBJCMETA (decl
, objc_meta
, meta_protocol_extension
);
1239 finish_var_decl (decl
, expr
);
1243 /* This routine builds the following type:
1244 struct _prop_list_t {
1245 uint32_t entsize; // sizeof (struct _prop_t)
1246 uint32_t prop_count;
1247 struct _prop_t prop_list [prop_count];
1252 build_v1_property_list_template (tree list_type
, int size
)
1254 tree property_list_t_record
;
1255 tree array_type
, decls
, *chain
= NULL
;
1258 property_list_t_record
= objc_start_struct (NULL_TREE
);
1260 /* uint32_t const entsize */
1261 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
1263 /* int prop_count */
1264 add_field_decl (integer_type_node
, "prop_count", &chain
);
1266 /* struct _prop_t prop_list[]; */
1267 array_type
= build_sized_array_type (list_type
, size
);
1268 add_field_decl (array_type
, "prop_list", &chain
);
1270 objc_finish_struct (property_list_t_record
, decls
);
1271 return property_list_t_record
;
1274 /* This routine builds the initializer list to initialize the
1275 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
1278 build_v1_property_table_initializer (tree type
, tree context
)
1281 VEC(constructor_elt
,gc
) *inits
= NULL
;
1283 if (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
)
1284 x
= CLASS_PROPERTY_DECL (context
);
1286 x
= IMPL_PROPERTY_DECL (context
);
1288 for (; x
; x
= TREE_CHAIN (x
))
1290 VEC(constructor_elt
,gc
) *elemlist
= NULL
;
1291 tree attribute
, name_ident
= PROPERTY_NAME (x
);
1293 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
1294 add_objc_string (name_ident
, prop_names_attr
));
1296 attribute
= objc_v2_encode_prop_attr (x
);
1297 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
1298 add_objc_string (attribute
, prop_names_attr
));
1300 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
1301 objc_build_constructor (type
, elemlist
));
1304 return objc_build_constructor (build_array_type (type
, 0),inits
);
1307 /* This routine builds the 'struct _prop_list_t' variable declaration and
1308 initializes it with its initializer list. TYPE is 'struct _prop_list_t',
1309 NAME is the internal name of this variable, SIZE is number of properties
1310 for this class and LIST is the initializer list for its 'prop_list' field. */
1313 generate_v1_property_table (tree context
, tree klass_ctxt
)
1315 tree x
, decl
, initlist
, property_list_template
;
1316 bool is_proto
= false;
1317 VEC(constructor_elt
,gc
) *inits
= NULL
;
1318 int init_val
, size
= 0;
1323 gcc_assert (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
);
1324 x
= CLASS_PROPERTY_DECL (context
);
1328 x
= IMPL_PROPERTY_DECL (klass_ctxt
);
1330 for (; x
; x
= TREE_CHAIN (x
))
1336 if (!objc_v1_property_template
)
1337 objc_v1_property_template
= build_v1_property_template ();
1339 property_list_template
=
1340 build_v1_property_list_template (objc_v1_property_template
,
1342 initlist
= build_v1_property_table_initializer (objc_v1_property_template
,
1346 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template
));
1348 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolPropList_%s",
1349 IDENTIFIER_POINTER (PROTOCOL_NAME (context
)));
1351 snprintf (buf
, BUFSIZE
, "_OBJC_ClassPropList_%s",
1352 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)));
1354 decl
= start_var_decl (property_list_template
, buf
);
1355 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, init_val
));
1356 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1357 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
1358 x
= objc_build_constructor (TREE_TYPE (decl
), inits
);
1359 OBJCMETA (decl
, objc_meta
, meta_proplist
);
1360 finish_var_decl (decl
, x
);
1365 generate_v1_protocol_list (tree i_or_p
, tree klass_ctxt
)
1367 tree array_type
, ptype
, refs_decl
, lproto
, e
, plist
, attr
;
1369 VEC(constructor_elt
,gc
) *v
= NULL
;
1372 switch (TREE_CODE (i_or_p
))
1374 case CLASS_INTERFACE_TYPE
:
1375 case CATEGORY_INTERFACE_TYPE
:
1376 plist
= CLASS_PROTOCOL_LIST (i_or_p
);
1378 case PROTOCOL_INTERFACE_TYPE
:
1379 plist
= PROTOCOL_LIST (i_or_p
);
1386 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
1387 if (TREE_CODE (TREE_VALUE (lproto
)) == PROTOCOL_INTERFACE_TYPE
1388 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto
)))
1391 /* Build initializer. */
1392 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, 0));
1393 e
= build_int_cst (build_pointer_type (objc_protocol_template
), size
);
1394 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, e
);
1396 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
1398 tree pval
= TREE_VALUE (lproto
);
1400 if (TREE_CODE (pval
) == PROTOCOL_INTERFACE_TYPE
1401 && PROTOCOL_FORWARD_DECL (pval
))
1403 tree fwref
= PROTOCOL_FORWARD_DECL (pval
);
1404 location_t loc
= DECL_SOURCE_LOCATION (fwref
) ;
1405 e
= build_unary_op (loc
, ADDR_EXPR
, fwref
, 0);
1406 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, e
);
1410 /* static struct objc_protocol *refs[n]; */
1411 switch (TREE_CODE (i_or_p
))
1413 case PROTOCOL_INTERFACE_TYPE
:
1414 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRefs_%s",
1415 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p
)));
1416 attr
= meta_proto_ref
;
1418 case CLASS_INTERFACE_TYPE
:
1419 snprintf (buf
, BUFSIZE
, "_OBJC_ClassProtocols_%s",
1420 IDENTIFIER_POINTER (CLASS_NAME (i_or_p
)));
1421 attr
= meta_clas_prot
;
1423 case CATEGORY_INTERFACE_TYPE
:
1424 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryProtocols_%s_%s",
1425 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)),
1426 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt
)));
1427 attr
= meta_catg_prot
;
1433 ptype
= build_pointer_type (objc_protocol_template
);
1434 array_type
= build_sized_array_type (ptype
, size
+ 3);
1435 refs_decl
= start_var_decl (array_type
, buf
);
1437 OBJCMETA (refs_decl
, objc_meta
, attr
);
1438 finish_var_decl (refs_decl
,
1439 objc_build_constructor (TREE_TYPE (refs_decl
), v
));
1445 build_v1_protocol_initializer (tree type
, tree protocol_name
, tree protocol_list
,
1446 tree inst_methods
, tree class_methods
,
1451 VEC(constructor_elt
,gc
) *inits
= NULL
;
1453 if (!objc_protocol_extension_template
)
1454 build_v1_objc_protocol_extension_template ();
1456 /* TODO: find a better representation of location from the inputs. */
1457 loc
= UNKNOWN_LOCATION
;
1458 ttyp
= build_pointer_type (objc_protocol_extension_template
);
1459 /* Instead of jamming the protocol version number into the isa, we pass
1460 either a pointer to the protocol extension - or NULL. */
1462 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_ext
, 0));
1464 expr
= convert (ttyp
, null_pointer_node
);
1466 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1467 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_name
);
1468 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_list
);
1470 ttyp
= objc_method_proto_list_ptr
;
1472 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
1474 expr
= convert (ttyp
, null_pointer_node
);
1475 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1478 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
1480 expr
= convert (ttyp
, null_pointer_node
);
1481 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1483 return objc_build_constructor (type
, inits
);
1486 /* An updated version of generate_protocols () that emit the protocol
1487 extension for ABI=1. */
1489 /* For each protocol which was referenced either from a @protocol()
1490 expression, or because a class/category implements it (then a
1491 pointer to the protocol is stored in the struct describing the
1492 class/category), we create a statically allocated instance of the
1493 Protocol class. The code is written in such a way as to generate
1494 as few Protocol objects as possible; we generate a unique Protocol
1495 instance for each protocol, and we don't generate a Protocol
1496 instance if the protocol is never referenced (either from a
1497 @protocol() or from a class/category implementation). These
1498 statically allocated objects can be referred to via the static
1499 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1501 The statically allocated Protocol objects that we generate here
1502 need to be fixed up at runtime in order to be used: the 'isa'
1503 pointer of the objects need to be set up to point to the 'Protocol'
1504 class, as known at runtime.
1506 The NeXT runtime fixes up all protocols at program startup time,
1507 before main() is entered. It uses a low-level trick to look up all
1508 those symbols, then loops on them and fixes them up. */
1510 /* TODO: finish getting rid of passing stuff around in globals. */
1512 static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl
;
1513 static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl
;
1514 static GTY(()) tree V1_ProtocolExt_decl
;
1515 static GTY(()) tree V1_Property_decl
;
1518 generate_v1_protocols (void)
1522 /* If a protocol was directly referenced, pull in indirect references. */
1523 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
1524 if (PROTOCOL_FORWARD_DECL (p
) && PROTOCOL_LIST (p
))
1525 generate_protocol_references (PROTOCOL_LIST (p
));
1527 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
1529 tree decl
, encoding
, initlist
, protocol_name_expr
;
1530 tree refs_type
, refs_decl
, refs_expr
;
1532 tree nst_methods
= PROTOCOL_NST_METHODS (p
);
1533 tree cls_methods
= PROTOCOL_CLS_METHODS (p
);
1535 /* If protocol wasn't referenced, don't generate any code. */
1536 decl
= PROTOCOL_FORWARD_DECL (p
);
1541 /* Make sure we link in the Protocol class. */
1542 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME
));
1546 if (! METHOD_ENCODING (nst_methods
))
1548 encoding
= encode_method_prototype (nst_methods
);
1549 METHOD_ENCODING (nst_methods
) = encoding
;
1551 nst_methods
= TREE_CHAIN (nst_methods
);
1554 UOBJC_INSTANCE_METHODS_decl
=
1555 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p
), p
,
1556 "_OBJC_ProtocolInstanceMethods",
1557 meta_proto_nst_meth
);
1561 if (! METHOD_ENCODING (cls_methods
))
1563 encoding
= encode_method_prototype (cls_methods
);
1564 METHOD_ENCODING (cls_methods
) = encoding
;
1567 cls_methods
= TREE_CHAIN (cls_methods
);
1570 UOBJC_CLASS_METHODS_decl
=
1571 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p
), p
,
1572 "_OBJC_ProtocolClassMethods",
1573 meta_proto_cls_meth
);
1575 /* There should be no optional methods for ABI-0 - but we need to
1576 check all this here before the lists are made. */
1577 nst_methods
= PROTOCOL_OPTIONAL_NST_METHODS (p
);
1580 if (! METHOD_ENCODING (nst_methods
))
1582 encoding
= encode_method_prototype (nst_methods
);
1583 METHOD_ENCODING (nst_methods
) = encoding
;
1585 nst_methods
= TREE_CHAIN (nst_methods
);
1588 V1_Protocol_OPT_NST_METHODS_decl
=
1589 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p
), p
,
1590 "_OBJC_OptionalProtocolInstanceMethods",
1591 meta_proto_nst_meth
);
1593 cls_methods
= PROTOCOL_OPTIONAL_CLS_METHODS (p
);
1596 if (! METHOD_ENCODING (cls_methods
))
1598 encoding
= encode_method_prototype (cls_methods
);
1599 METHOD_ENCODING (cls_methods
) = encoding
;
1602 cls_methods
= TREE_CHAIN (cls_methods
);
1605 V1_Protocol_OPT_CLS_METHODS_decl
=
1606 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p
), p
,
1607 "_OBJC_OptionalProtocolClassMethods",
1608 meta_proto_cls_meth
);
1610 if (PROTOCOL_LIST (p
))
1611 refs_decl
= generate_v1_protocol_list (p
, objc_implementation_context
);
1615 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1616 protocol_name_expr
= add_objc_string (PROTOCOL_NAME (p
), class_names
);
1617 /* TODO: more locations to be fixed up... */
1618 loc
= UNKNOWN_LOCATION
;
1620 build_pointer_type (build_pointer_type (objc_protocol_template
));
1622 refs_expr
= convert (refs_type
,
1623 build_unary_op (loc
, ADDR_EXPR
, refs_decl
, 0));
1625 refs_expr
= convert (refs_type
, null_pointer_node
);
1627 if (flag_objc_abi
< 1)
1631 build_protocol_initializer (TREE_TYPE (decl
),
1632 protocol_name_expr
, refs_expr
,
1633 UOBJC_INSTANCE_METHODS_decl
,
1634 UOBJC_CLASS_METHODS_decl
);
1635 finish_var_decl (decl
, initlist
);
1639 /* else - V1 extensions. */
1642 generate_v1_property_table (p
, NULL_TREE
);
1644 V1_ProtocolExt_decl
=
1645 generate_v1_objc_protocol_extension (p
,
1646 V1_Protocol_OPT_NST_METHODS_decl
,
1647 V1_Protocol_OPT_CLS_METHODS_decl
,
1650 initlist
= build_v1_protocol_initializer (TREE_TYPE (decl
),
1651 protocol_name_expr
, refs_expr
,
1652 UOBJC_INSTANCE_METHODS_decl
,
1653 UOBJC_CLASS_METHODS_decl
,
1654 V1_ProtocolExt_decl
);
1655 finish_var_decl (decl
, initlist
);
1660 generate_dispatch_table (tree chain
, const char *name
, tree attr
)
1662 tree decl
, method_list_template
, initlist
;
1663 VEC(constructor_elt
,gc
) *v
= NULL
;
1666 if (!chain
|| !name
|| !(size
= list_length (chain
)))
1669 if (!objc_method_template
)
1670 objc_method_template
= build_method_template ();
1672 method_list_template
= build_method_list_template (objc_method_template
,
1674 initlist
= build_dispatch_table_initializer (objc_method_template
, chain
);
1676 decl
= start_var_decl (method_list_template
, name
);
1678 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, integer_zero_node
);
1679 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1680 build_int_cst (integer_type_node
, size
));
1681 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
1683 OBJCMETA (decl
, objc_meta
, attr
);
1684 finish_var_decl (decl
,
1685 objc_build_constructor (TREE_TYPE (decl
), v
));
1690 /* Init a category. */
1692 build_v1_category_initializer (tree type
, tree cat_name
, tree class_name
,
1693 tree inst_methods
, tree class_methods
,
1694 tree protocol_list
, tree property_list
,
1698 VEC(constructor_elt
,gc
) *v
= NULL
;
1700 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, cat_name
);
1701 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, class_name
);
1703 ltyp
= objc_method_list_ptr
;
1705 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
1707 expr
= convert (ltyp
, null_pointer_node
);
1708 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1711 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
1713 expr
= convert (ltyp
, null_pointer_node
);
1714 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1716 /* protocol_list = */
1717 ltyp
= build_pointer_type (build_pointer_type (objc_protocol_template
));
1719 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
1721 expr
= convert (ltyp
, null_pointer_node
);
1722 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1724 if (flag_objc_abi
>= 1)
1726 int val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template
));
1727 expr
= build_int_cst (NULL_TREE
, val
);
1728 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1729 ltyp
= objc_prop_list_ptr
;
1731 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
1733 expr
= convert (ltyp
, null_pointer_node
);
1734 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1737 return objc_build_constructor (type
, v
);
1740 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1741 /* TODO: get rid of passing stuff around in globals. */
1743 generate_v1_category (struct imp_entry
*impent
)
1745 tree initlist
, cat_name_expr
, class_name_expr
;
1746 tree protocol_decl
, category
, cat_decl
;
1747 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
1748 tree cat
= impent
->imp_context
;
1752 cat_decl
= impent
->class_decl
;
1753 loc
= DECL_SOURCE_LOCATION (cat_decl
);
1755 add_class_reference (CLASS_NAME (cat
));
1756 cat_name_expr
= add_objc_string (CLASS_SUPER_NAME (cat
), class_names
);
1757 class_name_expr
= add_objc_string (CLASS_NAME (cat
), class_names
);
1759 category
= lookup_category (impent
->imp_template
, CLASS_SUPER_NAME (cat
));
1761 if (category
&& CLASS_PROTOCOL_LIST (category
))
1763 generate_protocol_references (CLASS_PROTOCOL_LIST (category
));
1764 protocol_decl
= generate_v1_protocol_list (category
, cat
);
1769 if (flag_objc_abi
>= 1)
1770 V1_Property_decl
= generate_v1_property_table (NULL_TREE
, cat
);
1772 V1_Property_decl
= NULL_TREE
;
1774 if (CLASS_NST_METHODS (cat
))
1776 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryInstanceMethods_%s_%s",
1777 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
1778 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
1779 inst_methods
= generate_dispatch_table (CLASS_NST_METHODS (cat
), buf
,
1783 if (CLASS_CLS_METHODS (cat
))
1785 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryClassMethods_%s_%s",
1786 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
1787 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
1788 class_methods
= generate_dispatch_table (CLASS_CLS_METHODS (cat
), buf
,
1792 initlist
= build_v1_category_initializer (TREE_TYPE (cat_decl
),
1793 cat_name_expr
, class_name_expr
,
1794 inst_methods
, class_methods
,
1795 protocol_decl
, V1_Property_decl
,
1798 finish_var_decl (cat_decl
, initlist
);
1799 impent
->class_decl
= cat_decl
;
1802 /* This routine builds the class extension used by v1 NeXT. */
1805 generate_objc_class_ext (tree property_list
, tree context
)
1807 tree decl
, expr
, ltyp
;
1808 tree weak_ivar_layout_tree
;
1811 VEC(constructor_elt
,gc
) *v
= NULL
;
1814 /* TODO: pass the loc in or find it from args. */
1815 loc
= UNKNOWN_LOCATION
;
1817 /* const char *weak_ivar_layout
1818 TODO: Figure the ivar layouts out... */
1819 weak_ivar_layout_tree
= NULL_TREE
;
1821 if (!property_list
&& !weak_ivar_layout_tree
)
1824 if (!objc_class_ext_template
)
1825 build_objc_class_ext_template ();
1828 size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template
));
1829 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1831 ltyp
= const_string_type_node
;
1832 if (weak_ivar_layout_tree
)
1833 expr
= convert (ltyp
, weak_ivar_layout_tree
);
1835 expr
= convert (ltyp
, null_pointer_node
);
1836 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1838 /* struct _prop_list_t *properties; */
1839 ltyp
= objc_prop_list_ptr
;
1841 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
1843 expr
= convert (ltyp
, null_pointer_node
);
1844 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1846 snprintf (buf
, BUFSIZE
, "_OBJC_ClassExt_%s",
1847 IDENTIFIER_POINTER (CLASS_NAME (context
)));
1848 decl
= start_var_decl (objc_class_ext_template
, buf
);
1849 expr
= objc_build_constructor (TREE_TYPE (decl
), v
);
1850 OBJCMETA (decl
, objc_meta
, meta_class_extension
);
1851 finish_var_decl (decl
, expr
);
1855 /* struct _objc_class {
1856 struct objc_class *isa;
1857 struct objc_class *super_class;
1862 struct objc_ivar_list *ivars;
1863 struct objc_method_list *methods;
1864 struct objc_cache *cache;
1865 struct objc_protocol_list *protocols;
1867 const char *ivar_layout;
1868 struct _objc_class_ext *ext;
1871 void *gc_object_type;
1876 build_v1_shared_structure_initializer (tree type
, tree isa
, tree super
,
1877 tree name
, tree size
, int status
,
1878 tree dispatch_table
, tree ivar_list
,
1879 tree protocol_list
, tree class_ext
)
1883 VEC(constructor_elt
,gc
) *v
= NULL
;
1885 /* TODO: fish the location out of the input data. */
1886 loc
= UNKNOWN_LOCATION
;
1889 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, isa
);
1892 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, super
);
1895 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, default_conversion (name
));
1898 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1899 build_int_cst (long_integer_type_node
, 0));
1902 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1903 build_int_cst (long_integer_type_node
, status
));
1905 /* instance_size = */
1906 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1907 convert (long_integer_type_node
, size
));
1909 /* objc_ivar_list = */
1910 ltyp
= objc_ivar_list_ptr
;
1912 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, ivar_list
, 0));
1914 expr
= convert (ltyp
, null_pointer_node
);
1915 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1917 /* objc_method_list = */
1918 ltyp
= objc_method_list_ptr
;
1920 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, dispatch_table
, 0));
1922 expr
= convert (ltyp
, null_pointer_node
);
1923 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1925 ltyp
= build_pointer_type (xref_tag (RECORD_TYPE
,
1926 get_identifier ("objc_cache")));
1927 /* method_cache = */
1928 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, convert (ltyp
, null_pointer_node
));
1930 /* protocol_list = */
1931 ltyp
= build_pointer_type (build_pointer_type (objc_protocol_template
));
1933 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
1935 expr
= convert (ltyp
, null_pointer_node
);
1936 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1938 if (flag_objc_abi
>= 1)
1940 /* TODO: figure out the ivar_layout stuff. */
1941 expr
= convert (const_string_type_node
, null_pointer_node
);
1942 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1943 if (!objc_class_ext_template
)
1944 build_objc_class_ext_template ();
1945 ltyp
= build_pointer_type (objc_class_ext_template
);
1947 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_ext
, 0));
1949 expr
= convert (ltyp
, null_pointer_node
);
1950 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1955 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, null_pointer_node
);
1957 /* gc_object_type = NULL */
1958 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, null_pointer_node
);
1960 return objc_build_constructor (type
, v
);
1964 generate_ivars_list (tree chain
, const char *name
, tree attr
)
1966 tree initlist
, ivar_list_template
, decl
;
1968 VEC(constructor_elt
,gc
) *inits
= NULL
;
1973 if (!objc_ivar_template
)
1974 objc_ivar_template
= build_ivar_template ();
1976 size
= ivar_list_length (chain
);
1978 generating_instance_variables
= 1;
1979 ivar_list_template
= build_ivar_list_template (objc_ivar_template
, size
);
1980 initlist
= build_ivar_list_initializer (objc_ivar_template
, chain
);
1981 generating_instance_variables
= 0;
1983 decl
= start_var_decl (ivar_list_template
, name
);
1985 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1986 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
1988 OBJCMETA (decl
, objc_meta
, attr
);
1989 finish_var_decl (decl
,
1990 objc_build_constructor (TREE_TYPE (decl
), inits
));
1995 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1996 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1999 generate_v1_class_structs (struct imp_entry
*impent
)
2001 tree name_expr
, super_expr
, root_expr
, class_decl
, meta_decl
;
2002 tree my_root_id
, my_super_id
;
2003 tree cast_type
, initlist
, protocol_decl
;
2004 tree class_ext_decl
= NULL_TREE
, props
= NULL_TREE
;
2005 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
2006 tree chain
, inst_ivars
= NULL_TREE
, class_ivars
= NULL_TREE
;
2011 /* objc_implementation_context = impent->imp_context;
2012 implementation_template = impent->imp_template;*/
2013 class_decl
= impent
->class_decl
;
2014 meta_decl
= impent
->meta_decl
;
2015 cls_flags
= impent
->has_cxx_cdtors
? CLS_HAS_CXX_STRUCTORS
: 0 ;
2017 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2019 if (flag_objc_abi
>= 1)
2021 /* ABI=1 additions. */
2022 props
= generate_v1_property_table (NULL_TREE
, impent
->imp_context
);
2023 class_ext_decl
= generate_objc_class_ext (props
, impent
->imp_context
);
2026 my_super_id
= CLASS_SUPER_NAME (impent
->imp_template
);
2029 add_class_reference (my_super_id
);
2031 /* Compute "my_root_id" - this is required for code generation.
2032 the "isa" for all meta class structures points to the root of
2033 the inheritance hierarchy (e.g. "__Object")... */
2034 my_root_id
= my_super_id
;
2037 tree my_root_int
= lookup_interface (my_root_id
);
2039 if (my_root_int
&& CLASS_SUPER_NAME (my_root_int
))
2040 my_root_id
= CLASS_SUPER_NAME (my_root_int
);
2045 super_expr
= add_objc_string (my_super_id
, class_names
);
2049 /* No super class. */
2050 my_root_id
= CLASS_NAME (impent
->imp_template
);
2051 super_expr
= null_pointer_node
;
2054 /* Install class `isa' and `super' pointers at runtime. */
2055 cast_type
= build_pointer_type (objc_class_template
);
2056 super_expr
= build_c_cast (loc
, cast_type
, super_expr
);
2058 root_expr
= add_objc_string (my_root_id
, class_names
);
2059 root_expr
= build_c_cast (loc
, cast_type
, root_expr
);
2061 if (CLASS_PROTOCOL_LIST (impent
->imp_template
))
2063 generate_protocol_references (CLASS_PROTOCOL_LIST (impent
->imp_template
));
2064 protocol_decl
= generate_v1_protocol_list (impent
->imp_template
,
2065 impent
->imp_context
);
2068 protocol_decl
= NULL_TREE
;
2070 if (CLASS_CLS_METHODS (impent
->imp_context
))
2072 snprintf (buf
, BUFSIZE
, "_OBJC_ClassMethods_%s",
2073 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2074 class_methods
= generate_dispatch_table (CLASS_CLS_METHODS (impent
->imp_context
),
2075 buf
, meta_clac_meth
);
2078 if (CLASS_SUPER_NAME (impent
->imp_template
) == NULL_TREE
2079 && (chain
= TYPE_FIELDS (objc_class_template
)))
2081 snprintf (buf
, BUFSIZE
, "_OBJC_ClassIvars_%s",
2082 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2083 class_ivars
= generate_ivars_list (chain
, buf
, meta_clac_vars
);
2085 /* TODO: get rid of hidden passing of stuff in globals. */
2086 /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */
2088 name_expr
= add_objc_string (CLASS_NAME (impent
->imp_template
), class_names
);
2090 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2092 initlist
= build_v1_shared_structure_initializer
2093 (TREE_TYPE (meta_decl
),
2094 root_expr
, super_expr
, name_expr
,
2095 convert (integer_type_node
, TYPE_SIZE_UNIT (objc_class_template
)),
2096 CLS_META
, class_methods
, class_ivars
,
2097 protocol_decl
, NULL_TREE
);
2099 finish_var_decl (meta_decl
, initlist
);
2100 impent
->meta_decl
= meta_decl
;
2102 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2103 if (CLASS_NST_METHODS (impent
->imp_context
))
2105 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceMethods_%s",
2106 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2107 inst_methods
= generate_dispatch_table (CLASS_NST_METHODS (impent
->imp_context
),
2108 buf
, meta_clai_meth
);
2111 if ((chain
= CLASS_IVARS (impent
->imp_template
)))
2113 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceIvars_%s",
2114 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2115 inst_ivars
= generate_ivars_list (chain
, buf
, meta_clai_vars
);
2118 initlist
= build_v1_shared_structure_initializer
2119 (TREE_TYPE (class_decl
),
2120 build_unary_op (loc
, ADDR_EXPR
, meta_decl
, 0),
2121 super_expr
, name_expr
,
2122 convert (integer_type_node
,
2123 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent
->imp_template
))),
2124 CLS_FACTORY
| cls_flags
, inst_methods
, inst_ivars
,
2125 protocol_decl
, class_ext_decl
);
2127 finish_var_decl (class_decl
, initlist
);
2128 impent
->class_decl
= class_decl
;
2131 /* --- Output NeXT V1 Metadata --- */
2133 /* Create the initial value for the `defs' field of _objc_symtab.
2134 This is a CONSTRUCTOR. */
2137 init_def_list (tree type
)
2141 struct imp_entry
*impent
;
2142 VEC(constructor_elt
,gc
) *v
= NULL
;
2145 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2147 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
2149 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2150 expr
= build_unary_op (loc
,
2151 ADDR_EXPR
, impent
->class_decl
, 0);
2152 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2157 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2159 if (TREE_CODE (impent
->imp_context
) == CATEGORY_IMPLEMENTATION_TYPE
)
2161 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2162 expr
= build_unary_op (loc
,
2163 ADDR_EXPR
, impent
->class_decl
, 0);
2164 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2168 return objc_build_constructor (type
, v
);
2171 /* Take care of defining and initializing _OBJC_SYMBOLS. */
2173 /* Predefine the following data type:
2181 void *defs[cls_def_cnt + cat_def_cnt];
2185 build_objc_symtab_template (void)
2187 tree fields
, *chain
= NULL
;
2189 objc_symtab_template
= objc_start_struct (get_identifier (UTAG_SYMTAB
));
2191 /* long sel_ref_cnt; */
2192 fields
= add_field_decl (long_integer_type_node
, "sel_ref_cnt", &chain
);
2195 add_field_decl (build_pointer_type (objc_selector_type
), "refs", &chain
);
2197 /* short cls_def_cnt; */
2198 add_field_decl (short_integer_type_node
, "cls_def_cnt", &chain
);
2200 /* short cat_def_cnt; */
2201 add_field_decl (short_integer_type_node
, "cat_def_cnt", &chain
);
2203 if (imp_count
|| cat_count
)
2205 /* void *defs[imp_count + cat_count (+ 1)]; */
2206 /* NB: The index is one less than the size of the array. */
2207 int index
= imp_count
+ cat_count
;
2208 tree array_type
= build_sized_array_type (ptr_type_node
, index
);
2209 add_field_decl (array_type
, "defs", &chain
);
2212 objc_finish_struct (objc_symtab_template
, fields
);
2214 /* Construct the initial value for all of _objc_symtab. */
2217 init_objc_symtab (tree type
)
2219 VEC(constructor_elt
,gc
) *v
= NULL
;
2221 /* sel_ref_cnt = { ..., 5, ... } */
2223 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2224 build_int_cst (long_integer_type_node
, 0));
2226 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2228 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2229 convert (build_pointer_type (objc_selector_type
),
2230 integer_zero_node
));
2232 /* cls_def_cnt = { ..., 5, ... } */
2234 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2235 build_int_cst (short_integer_type_node
, imp_count
));
2237 /* cat_def_cnt = { ..., 5, ... } */
2239 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2240 build_int_cst (short_integer_type_node
, cat_count
));
2242 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2244 if (imp_count
|| cat_count
)
2246 tree field
= TYPE_FIELDS (type
);
2247 field
= DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field
))));
2249 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, init_def_list (TREE_TYPE (field
)));
2252 return objc_build_constructor (type
, v
);
2255 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2256 and initialized appropriately. */
2259 generate_objc_symtab_decl (void)
2261 build_objc_symtab_template ();
2262 UOBJC_SYMBOLS_decl
= start_var_decl (objc_symtab_template
, "_OBJC_Symbols");
2263 /* Allow the runtime to mark meta-data such that it can be assigned to target
2264 specific sections by the back-end. */
2265 OBJCMETA (UOBJC_SYMBOLS_decl
, objc_meta
, meta_symtab
);
2266 finish_var_decl (UOBJC_SYMBOLS_decl
,
2267 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl
)));
2272 handle_next_class_ref (tree chain
)
2274 const char *name
= IDENTIFIER_POINTER (TREE_VALUE (chain
));
2275 char *string
= (char *) alloca (strlen (name
) + 30);
2277 sprintf (string
, ".objc_class_name_%s", name
);
2279 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
2280 ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file
, string
);
2282 return ; /* NULL build for targets other than Darwin. */
2287 handle_next_impent (struct imp_entry
*impent
)
2291 switch (TREE_CODE (impent
->imp_context
))
2293 case CLASS_IMPLEMENTATION_TYPE
:
2294 snprintf (buf
, BUFSIZE
, ".objc_class_name_%s",
2295 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2297 case CATEGORY_IMPLEMENTATION_TYPE
:
2298 snprintf (buf
, BUFSIZE
, "*.objc_category_name_%s_%s",
2299 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)),
2300 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent
->imp_context
)));
2306 #ifdef ASM_DECLARE_CLASS_REFERENCE
2307 ASM_DECLARE_CLASS_REFERENCE (asm_out_file
, buf
);
2309 return ; /* NULL build for targets other than Darwin. */
2314 generate_classref_translation_entry (tree chain
)
2316 tree expr
, decl
, type
;
2318 decl
= TREE_PURPOSE (chain
);
2319 type
= TREE_TYPE (decl
);
2321 expr
= add_objc_string (TREE_VALUE (chain
), class_names
);
2322 expr
= convert (type
, expr
); /* cast! */
2324 /* This is a class reference. It is re-written by the runtime,
2325 but will be optimized away unless we force it. */
2326 DECL_PRESERVE_P (decl
) = 1;
2327 OBJCMETA (decl
, objc_meta
, meta_class_reference
);
2328 finish_var_decl (decl
, expr
);
2333 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
2334 later requires that ObjC translation units participating in F&C be
2335 specially marked. The following routine accomplishes this. */
2337 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
2340 generate_objc_image_info (void)
2344 = ((flag_replace_objc_classes
&& imp_count
? 1 : 0)
2345 | (flag_objc_gc
? 2 : 0));
2346 VEC(constructor_elt
,gc
) *v
= NULL
;
2349 array_type
= build_sized_array_type (integer_type_node
, 2);
2351 decl
= start_var_decl (array_type
, "_OBJC_ImageInfo");
2353 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, integer_zero_node
);
2354 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (integer_type_node
, flags
));
2355 /* The runtime wants this and refers to it in a manner hidden from the compiler.
2356 So we must force the output. */
2357 DECL_PRESERVE_P (decl
) = 1;
2358 OBJCMETA (decl
, objc_meta
, meta_info
);
2359 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), v
));
2363 objc_generate_v1_next_metadata (void)
2365 struct imp_entry
*impent
;
2369 /* FIXME: Make sure that we generate no metadata if there is nothing
2372 if (objc_static_instances
)
2373 gcc_unreachable (); /* Not for NeXT */
2375 build_metadata_templates ();
2376 objc_implementation_context
=
2377 implementation_template
=
2379 UOBJC_METACLASS_decl
= NULL_TREE
;
2381 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2384 /* If -gen-decls is present, Dump the @interface of each class.
2385 TODO: Dump the classes in the order they were found, rather than in
2386 reverse order as we are doing now. */
2387 if (flag_gen_declaration
)
2388 dump_interface (gen_declaration_file
, impent
->imp_context
);
2390 /* all of the following reference the string pool... */
2391 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
2392 generate_v1_class_structs (impent
);
2394 generate_v1_category (impent
);
2397 /* If we are using an array of selectors, we must always
2398 finish up the array decl even if no selectors were used. */
2399 build_next_selector_translation_table ();
2402 generate_v1_protocols ();
2404 /* Pass summary information to the runtime. */
2405 if (imp_count
|| cat_count
)
2406 generate_objc_symtab_decl ();
2408 vers
= OBJC_VERSION
;
2409 attr
= build_tree_list (objc_meta
, meta_modules
);
2410 build_module_descriptor (vers
, attr
);
2412 /* This conveys information on GC usage and zero-link. */
2413 generate_objc_image_info ();
2415 /* Dump the class references. This forces the appropriate classes
2416 to be linked into the executable image, preserving unix archive
2417 semantics. This can be removed when we move to a more dynamically
2418 linked environment. */
2420 for (chain
= cls_ref_chain
; chain
; chain
= TREE_CHAIN (chain
))
2422 handle_next_class_ref (chain
);
2423 if (TREE_PURPOSE (chain
))
2424 generate_classref_translation_entry (chain
);
2427 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2428 handle_next_impent (impent
);
2430 /* Emit the strings tables. */
2431 generate_strings ();
2434 /* --- exceptions stuff --- */
2436 /* Predefine the following data type:
2438 struct _objc_exception_data
2440 int buf[OBJC_JBLEN];
2444 /* The following yuckiness should prevent users from having to #include
2445 <setjmp.h> in their code... */
2447 /* Define to a harmless positive value so the below code doesn't die. */
2449 #define OBJC_JBLEN 18
2453 build_next_objc_exception_stuff (void)
2455 tree decls
, temp_type
, *chain
= NULL
;
2457 objc_exception_data_template
2458 = objc_start_struct (get_identifier (UTAG_EXCDATA
));
2460 /* int buf[OBJC_JBLEN]; */
2462 temp_type
= build_sized_array_type (integer_type_node
, OBJC_JBLEN
);
2463 decls
= add_field_decl (temp_type
, "buf", &chain
);
2465 /* void *pointers[4]; */
2467 temp_type
= build_sized_array_type (ptr_type_node
, 4);
2468 add_field_decl (temp_type
, "pointers", &chain
);
2470 objc_finish_struct (objc_exception_data_template
, decls
);
2472 /* int _setjmp(...); */
2473 /* If the user includes <setjmp.h>, this shall be superseded by
2474 'int _setjmp(jmp_buf);' */
2475 temp_type
= build_varargs_function_type_list (integer_type_node
, NULL_TREE
);
2477 = add_builtin_function (TAG_SETJMP
, temp_type
, 0, NOT_BUILT_IN
, NULL
, NULL_TREE
);
2479 /* id objc_exception_extract(struct _objc_exception_data *); */
2481 = build_function_type_list (objc_object_type
,
2482 build_pointer_type (objc_exception_data_template
),
2484 objc_exception_extract_decl
2485 = add_builtin_function (TAG_EXCEPTIONEXTRACT
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2487 /* void objc_exception_try_enter(struct _objc_exception_data *); */
2488 /* void objc_exception_try_exit(struct _objc_exception_data *); */
2490 = build_function_type_list (void_type_node
,
2491 build_pointer_type (objc_exception_data_template
),
2493 objc_exception_try_enter_decl
2494 = add_builtin_function (TAG_EXCEPTIONTRYENTER
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2496 objc_exception_try_exit_decl
2497 = add_builtin_function (TAG_EXCEPTIONTRYEXIT
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2500 /* int objc_exception_match(id, id); */
2502 = build_function_type_list (integer_type_node
,
2503 objc_object_type
, objc_object_type
, NULL_TREE
);
2504 objc_exception_match_decl
2505 = add_builtin_function (TAG_EXCEPTIONMATCH
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2508 /* id objc_assign_ivar (id, id, unsigned int); */
2509 /* id objc_assign_ivar_Fast (id, id, unsigned int)
2510 __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2512 = build_function_type_list (objc_object_type
,
2517 objc_assign_ivar_decl
2518 = add_builtin_function (TAG_ASSIGNIVAR
, temp_type
, 0, NOT_BUILT_IN
,
2520 #ifdef OFFS_ASSIGNIVAR_FAST
2521 objc_assign_ivar_fast_decl
2522 = add_builtin_function (TAG_ASSIGNIVAR_FAST
, temp_type
, 0,
2523 NOT_BUILT_IN
, NULL
, NULL_TREE
);
2524 DECL_ATTRIBUTES (objc_assign_ivar_fast_decl
)
2525 = tree_cons (get_identifier ("hard_coded_address"),
2526 build_int_cst (NULL_TREE
, OFFS_ASSIGNIVAR_FAST
),
2529 /* Default to slower ivar method. */
2530 objc_assign_ivar_fast_decl
= objc_assign_ivar_decl
;
2533 /* id objc_assign_global (id, id *); */
2534 /* id objc_assign_strongCast (id, id *); */
2535 temp_type
= build_function_type_list (objc_object_type
,
2537 build_pointer_type (objc_object_type
),
2539 objc_assign_global_decl
2540 = add_builtin_function (TAG_ASSIGNGLOBAL
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2542 objc_assign_strong_cast_decl
2543 = add_builtin_function (TAG_ASSIGNSTRONGCAST
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2547 /* --- NeXT V1 SJLJ Exceptions --- */
2549 /* Build "objc_exception_try_exit(&_stack)". */
2552 next_sjlj_build_try_exit (struct objc_try_context
**ctcp
)
2555 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2556 t
= tree_cons (NULL
, t
, NULL
);
2557 t
= build_function_call (input_location
,
2558 objc_exception_try_exit_decl
, t
);
2563 objc_exception_try_enter (&_stack);
2564 if (_setjmp(&_stack.buf))
2568 Return the COND_EXPR. Note that the THEN and ELSE fields are left
2569 empty, ready for the caller to fill them in. */
2572 next_sjlj_build_enter_and_setjmp (struct objc_try_context
**ctcp
)
2574 tree t
, enter
, sj
, cond
;
2576 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2577 t
= tree_cons (NULL
, t
, NULL
);
2578 enter
= build_function_call (input_location
,
2579 objc_exception_try_enter_decl
, t
);
2581 t
= objc_build_component_ref ((*ctcp
)->stack_decl
,
2582 get_identifier ("buf"));
2583 t
= build_fold_addr_expr_loc (input_location
, t
);
2585 /* Convert _setjmp argument to type that is expected. */
2586 if (prototype_p (TREE_TYPE (objc_setjmp_decl
)))
2587 t
= convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl
))), t
);
2589 t
= convert (ptr_type_node
, t
);
2591 t
= convert (ptr_type_node
, t
);
2593 t
= tree_cons (NULL
, t
, NULL
);
2594 sj
= build_function_call (input_location
,
2595 objc_setjmp_decl
, t
);
2597 cond
= build2 (COMPOUND_EXPR
, TREE_TYPE (sj
), enter
, sj
);
2598 cond
= c_common_truthvalue_conversion (input_location
, cond
);
2600 return build3 (COND_EXPR
, void_type_node
, cond
, NULL
, NULL
);
2605 DECL = objc_exception_extract(&_stack); */
2608 next_sjlj_build_exc_extract (struct objc_try_context
**ctcp
, tree decl
)
2612 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2613 t
= tree_cons (NULL
, t
, NULL
);
2614 t
= build_function_call (input_location
,
2615 objc_exception_extract_decl
, t
);
2616 t
= convert (TREE_TYPE (decl
), t
);
2617 t
= build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
2623 if (objc_exception_match(obj_get_class(TYPE), _caught)
2630 objc_exception_try_exit(&_stack);
2632 from the sequence of CATCH_EXPRs in the current try context. */
2635 next_sjlj_build_catch_list (struct objc_try_context
**ctcp
)
2637 tree_stmt_iterator i
= tsi_start ((*ctcp
)->catch_list
);
2639 tree
*last
= &catch_seq
;
2640 bool saw_id
= false;
2642 for (; !tsi_end_p (i
); tsi_next (&i
))
2644 tree stmt
= tsi_stmt (i
);
2645 tree type
= CATCH_TYPES (stmt
);
2646 tree body
= CATCH_BODY (stmt
);
2648 if (type
!= error_mark_node
2649 && objc_is_object_id (TREE_TYPE (type
)))
2659 if (type
== error_mark_node
)
2660 cond
= error_mark_node
;
2663 args
= tree_cons (NULL
, (*ctcp
)->caught_decl
, NULL
);
2664 t
= objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type
)));
2665 args
= tree_cons (NULL
, t
, args
);
2666 t
= build_function_call (input_location
,
2667 objc_exception_match_decl
, args
);
2668 cond
= c_common_truthvalue_conversion (input_location
, t
);
2670 t
= build3 (COND_EXPR
, void_type_node
, cond
, body
, NULL
);
2671 SET_EXPR_LOCATION (t
, EXPR_LOCATION (stmt
));
2674 last
= &COND_EXPR_ELSE (t
);
2680 t
= build2 (MODIFY_EXPR
, void_type_node
, (*ctcp
)->rethrow_decl
,
2681 (*ctcp
)->caught_decl
);
2682 SET_EXPR_LOCATION (t
, (*ctcp
)->end_catch_locus
);
2683 append_to_statement_list (t
, last
);
2685 t
= next_sjlj_build_try_exit (ctcp
);
2686 SET_EXPR_LOCATION (t
, (*ctcp
)->end_catch_locus
);
2687 append_to_statement_list (t
, last
);
2693 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2694 exception handling. We aim to build:
2697 struct _objc_exception_data _stack;
2701 objc_exception_try_enter (&_stack);
2702 if (_setjmp(&_stack.buf))
2704 id _caught = objc_exception_extract(&_stack);
2705 objc_exception_try_enter (&_stack);
2706 if (_setjmp(&_stack.buf))
2707 _rethrow = objc_exception_extract(&_stack);
2717 objc_exception_try_exit(&_stack);
2720 objc_exception_throw(_rethrow);
2724 If CATCH-LIST is empty, we can omit all of the block containing
2725 "_caught" except for the setting of _rethrow. Note the use of
2726 a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2727 but handles goto and other exits from the block. */
2730 next_sjlj_build_try_catch_finally (struct objc_try_context
**ctcp
)
2732 tree rethrow_decl
, stack_decl
, t
;
2733 tree catch_seq
, try_fin
, bind
;
2734 struct objc_try_context
*cur_try_context
= *ctcp
;
2736 /* Create the declarations involved. */
2737 t
= xref_tag (RECORD_TYPE
, get_identifier (UTAG_EXCDATA
));
2738 stack_decl
= objc_create_temporary_var (t
, NULL
);
2739 cur_try_context
->stack_decl
= stack_decl
;
2741 rethrow_decl
= objc_create_temporary_var (objc_object_type
, NULL
);
2742 cur_try_context
->rethrow_decl
= rethrow_decl
;
2743 TREE_CHAIN (rethrow_decl
) = stack_decl
;
2745 /* Build the outermost variable binding level. */
2746 bind
= build3 (BIND_EXPR
, void_type_node
, rethrow_decl
, NULL
, NULL
);
2747 SET_EXPR_LOCATION (bind
, cur_try_context
->try_locus
);
2748 TREE_SIDE_EFFECTS (bind
) = 1;
2750 /* Initialize rethrow_decl. */
2751 t
= build2 (MODIFY_EXPR
, void_type_node
, rethrow_decl
,
2752 convert (objc_object_type
, null_pointer_node
));
2753 SET_EXPR_LOCATION (t
, cur_try_context
->try_locus
);
2754 append_to_statement_list (t
, &BIND_EXPR_BODY (bind
));
2756 /* Build the outermost TRY_FINALLY_EXPR. */
2757 try_fin
= build2 (TRY_FINALLY_EXPR
, void_type_node
, NULL
, NULL
);
2758 SET_EXPR_LOCATION (try_fin
, cur_try_context
->try_locus
);
2759 TREE_SIDE_EFFECTS (try_fin
) = 1;
2760 append_to_statement_list (try_fin
, &BIND_EXPR_BODY (bind
));
2762 /* Create the complete catch sequence. */
2763 if (cur_try_context
->catch_list
)
2765 tree caught_decl
= objc_build_exc_ptr (ctcp
);
2766 catch_seq
= build_stmt (input_location
, BIND_EXPR
, caught_decl
, NULL
, NULL
);
2767 TREE_SIDE_EFFECTS (catch_seq
) = 1;
2769 t
= next_sjlj_build_exc_extract (ctcp
, caught_decl
);
2770 append_to_statement_list (t
, &BIND_EXPR_BODY (catch_seq
));
2772 t
= next_sjlj_build_enter_and_setjmp (ctcp
);
2773 COND_EXPR_THEN (t
) = next_sjlj_build_exc_extract (ctcp
, rethrow_decl
);
2774 COND_EXPR_ELSE (t
) = next_sjlj_build_catch_list (ctcp
);
2775 append_to_statement_list (t
, &BIND_EXPR_BODY (catch_seq
));
2778 catch_seq
= next_sjlj_build_exc_extract (ctcp
, rethrow_decl
);
2779 SET_EXPR_LOCATION (catch_seq
, cur_try_context
->end_try_locus
);
2781 /* Build the main register-and-try if statement. */
2782 t
= next_sjlj_build_enter_and_setjmp (ctcp
);
2783 SET_EXPR_LOCATION (t
, cur_try_context
->try_locus
);
2784 COND_EXPR_THEN (t
) = catch_seq
;
2785 COND_EXPR_ELSE (t
) = cur_try_context
->try_body
;
2786 TREE_OPERAND (try_fin
, 0) = t
;
2788 /* Build the complete FINALLY statement list. */
2789 t
= next_sjlj_build_try_exit (ctcp
);
2790 t
= build_stmt (input_location
, COND_EXPR
,
2791 c_common_truthvalue_conversion
2792 (input_location
, rethrow_decl
),
2794 SET_EXPR_LOCATION (t
, cur_try_context
->finally_locus
);
2795 append_to_statement_list (t
, &TREE_OPERAND (try_fin
, 1));
2797 append_to_statement_list (cur_try_context
->finally_body
,
2798 &TREE_OPERAND (try_fin
, 1));
2800 t
= tree_cons (NULL
, rethrow_decl
, NULL
);
2801 t
= build_function_call (input_location
,
2802 objc_exception_throw_decl
, t
);
2803 t
= build_stmt (input_location
, COND_EXPR
,
2804 c_common_truthvalue_conversion (input_location
,
2807 SET_EXPR_LOCATION (t
, cur_try_context
->end_finally_locus
);
2808 append_to_statement_list (t
, &TREE_OPERAND (try_fin
, 1));
2813 /* We do not expect this to be used at the moment.
2814 If (a) it is possible to implement unwinder exceptions.
2815 (b) we do it... then it might be possibly useful.
2817 static GTY(()) tree objc_eh_personality_decl
;
2820 objc_eh_runtime_type (tree type
)
2822 tree ident
, eh_id
, decl
, str
;
2825 if (type
== error_mark_node
)
2827 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2828 to prevent an ICE. Note that we know that the compiler will
2829 terminate with an error and this 'ErrorMarkNode' class name will
2830 never be actually used. */
2831 ident
= get_identifier ("ErrorMarkNode");
2832 goto make_err_class
;
2835 if (POINTER_TYPE_P (type
) && objc_is_object_id (TREE_TYPE (type
)))
2837 ident
= get_identifier ("id");
2838 goto make_err_class
;
2841 if (!POINTER_TYPE_P (type
) || !TYPED_OBJECT (TREE_TYPE (type
)))
2844 /* This routine is also called for c++'s catch clause; in which case,
2845 we use c++'s typeinfo decl. */
2846 return build_eh_type_type (type
);
2848 error ("non-objective-c type '%T' cannot be caught", type
);
2849 ident
= get_identifier ("ErrorMarkNode");
2850 goto make_err_class
;
2854 ident
= OBJC_TYPE_NAME (TREE_TYPE (type
));
2857 /* If this class was already referenced, then it will be output during
2858 meta-data emission, so we don't need to do it here. */
2859 decl
= get_objc_string_decl (ident
, class_names
);
2860 eh_id
= add_objc_string (ident
, class_names
);
2863 /* Not found ... so we need to build it - from the freshly-entered id. */
2864 decl
= get_objc_string_decl (ident
, class_names
);
2865 str
= my_build_string (IDENTIFIER_LENGTH (ident
) + 1,
2866 IDENTIFIER_POINTER (ident
));
2867 /* We have to finalize this var here, because this might be called after
2868 all the other metadata strings have been emitted. */
2869 finish_var_decl (decl
, str
);
2875 objc_eh_personality (void)
2877 if (!objc_eh_personality_decl
)
2879 objc_eh_personality_decl
= build_personality_function ("objc");
2881 objc_eh_personality_decl
= build_personality_function ("gxx");
2883 return objc_eh_personality_decl
;
2886 /* --- interfaces --- */
2889 build_throw_stmt (location_t loc
, tree throw_expr
, bool rethrown ATTRIBUTE_UNUSED
)
2892 VEC(tree
, gc
) *parms
= VEC_alloc (tree
, gc
, 1);
2893 /* A throw is just a call to the runtime throw function with the
2894 object as a parameter. */
2895 VEC_quick_push (tree
, parms
, throw_expr
);
2896 t
= build_function_call_vec (loc
, objc_exception_throw_decl
, parms
, NULL
);
2897 VEC_free (tree
, gc
, parms
);
2898 return add_stmt (t
);
2901 /* Build __builtin_eh_pointer, or the moral equivalent. In the case
2902 of Darwin, we'll arrange for it to be initialized (and associated
2903 with a binding) later. */
2906 objc_build_exc_ptr (struct objc_try_context
**cur_try_context
)
2908 if (flag_objc_sjlj_exceptions
)
2910 tree var
= (*cur_try_context
)->caught_decl
;
2913 var
= objc_create_temporary_var (objc_object_type
, NULL
);
2914 (*cur_try_context
)->caught_decl
= var
;
2921 t
= built_in_decls
[BUILT_IN_EH_POINTER
];
2922 t
= build_call_expr (t
, 1, integer_zero_node
);
2923 return fold_convert (objc_object_type
, t
);
2928 begin_catch (struct objc_try_context
**cur_try_context
, tree type
,
2929 tree decl
, tree compound
, bool ellipsis ATTRIBUTE_UNUSED
)
2932 /* Record the data for the catch in the try context so that we can
2933 finalize it later. We treat ellipsis the same way as catching
2935 t
= build_stmt (input_location
, CATCH_EXPR
, type
, compound
);
2936 (*cur_try_context
)->current_catch
= t
;
2938 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
2939 t
= objc_build_exc_ptr (cur_try_context
);
2940 t
= convert (TREE_TYPE (decl
), t
);
2941 return build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
2945 finish_catch (struct objc_try_context
**cur_try_context
, tree current_catch
)
2947 append_to_statement_list (current_catch
, &((*cur_try_context
)->catch_list
));
2951 finish_try_stmt (struct objc_try_context
**cur_try_context
)
2954 struct objc_try_context
*c
= *cur_try_context
;
2955 /* If we're doing Darwin setjmp exceptions, build the big nasty. */
2956 if (flag_objc_sjlj_exceptions
)
2958 bool save
= in_late_binary_op
;
2959 in_late_binary_op
= true;
2960 if (!c
->finally_body
)
2962 c
->finally_locus
= input_location
;
2963 c
->end_finally_locus
= input_location
;
2965 stmt
= next_sjlj_build_try_catch_finally (cur_try_context
);
2966 in_late_binary_op
= save
;
2969 /* This doesn't happen at the moment... but maybe one day... */
2971 /* Otherwise, nest the CATCH inside a FINALLY. */
2974 stmt
= build_stmt (c
->try_locus
, TRY_CATCH_EXPR
, stmt
, c
->catch_list
);
2975 if (c
->finally_body
)
2976 stmt
= build_stmt (c
->try_locus
, TRY_FINALLY_EXPR
, stmt
, c
->finally_body
);
2981 #include "gt-objc-objc-next-runtime-abi-01.h"