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"
57 #include "objc-encoding.h"
59 /* NeXT ABI 0 and 1 private definitions. */
60 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
62 #define TAG_GETCLASS "objc_getClass"
63 #define TAG_GETMETACLASS "objc_getMetaClass"
65 #define TAG_MSGSEND "objc_msgSend"
66 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
67 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
68 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
70 /* NeXT-specific tags. */
72 #define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
73 #define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
74 #define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
75 #define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
76 #define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
77 #define TAG_EXCEPTIONMATCH "objc_exception_match"
78 #define TAG_SETJMP "_setjmp"
80 #define TAG_ASSIGNIVAR "objc_assign_ivar"
81 #define TAG_ASSIGNGLOBAL "objc_assign_global"
82 #define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
84 /* Branch entry points. All that matters here are the addresses;
85 functions with these names do not really exist in libobjc. */
87 #define TAG_MSGSEND_FAST "objc_msgSend_Fast"
88 #define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
90 /* The version identifies which language generation and runtime the
91 module (file) was compiled for, and is recorded in the module
93 #define OBJC_VERSION (flag_objc_abi >= 1 ? 7 : 6)
95 #define UTAG_CLASS_EXT "_objc_class_ext"
96 #define UTAG_PROPERTY_LIST "_prop_list_t"
97 #define UTAG_PROTOCOL_EXT "_objc_protocol_extension"
99 #define CLS_HAS_CXX_STRUCTORS 0x2000L
101 /* rt_trees identifiers - shared between NeXT implementations. These
102 allow the FE to tag meta-data in a manner that survives LTO and can
103 be used when the runtime requires that certain meta-data items
104 appear in particular named sections. */
106 #include "objc-next-metadata-tags.h"
107 extern GTY(()) tree objc_rt_trees
[OCTI_RT_META_MAX
];
109 static void next_runtime_01_initialize (void);
111 static tree
next_runtime_abi_01_super_superclassfield_id (void);
113 static tree
next_runtime_abi_01_class_decl (tree
);
114 static tree
next_runtime_abi_01_metaclass_decl (tree
);
115 static tree
next_runtime_abi_01_category_decl (tree
);
116 static tree
next_runtime_abi_01_protocol_decl (tree
);
117 static tree
next_runtime_abi_01_string_decl (tree
, const char *, string_section
);
119 static tree
next_runtime_abi_01_get_class_reference (tree
);
120 static tree
next_runtime_abi_01_build_selector_reference (location_t
, tree
, tree
);
121 static tree
next_runtime_abi_01_get_protocol_reference (location_t
, tree
);
122 static tree
next_runtime_abi_01_build_ivar_ref (location_t
, tree
, tree
);
123 static tree
next_runtime_abi_01_get_class_super_ref (location_t
, struct imp_entry
*, bool);
124 static tree
next_runtime_abi_01_get_category_super_ref (location_t
, struct imp_entry
*, bool);
126 static tree
next_runtime_abi_01_receiver_is_class_object (tree
);
127 static void next_runtime_abi_01_get_arg_type_list_base (VEC(tree
,gc
) **, tree
,
129 static tree
next_runtime_abi_01_build_objc_method_call (location_t
, tree
, tree
,
130 tree
, tree
, tree
, int);
131 static bool next_runtime_abi_01_setup_const_string_class_decl (void);
132 static tree
next_runtime_abi_01_build_const_string_constructor (location_t
, tree
, int);
134 static void objc_generate_v1_next_metadata (void);
136 static void build_next_objc_exception_stuff (void);
137 static tree
objc_eh_runtime_type (tree type
);
138 static tree
objc_eh_personality (void);
139 static tree
build_throw_stmt (location_t
, tree
, bool);
140 static tree
objc_build_exc_ptr (struct objc_try_context
**);
141 static tree
begin_catch (struct objc_try_context
**, tree
, tree
, tree
, bool);
142 static void finish_catch (struct objc_try_context
**, tree
);
143 static tree
finish_try_stmt (struct objc_try_context
**);
146 objc_next_runtime_abi_01_init (objc_runtime_hooks
*rthooks
)
148 if (flag_objc_exceptions
149 && !flag_objc_sjlj_exceptions
)
151 warning_at (UNKNOWN_LOCATION
, OPT_Wall
,
152 "%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
153 "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2");
156 rthooks
->initialize
= next_runtime_01_initialize
;
157 rthooks
->default_constant_string_class_name
= DEF_CONSTANT_STRING_CLASS_NAME
;
158 rthooks
->tag_getclass
= TAG_GETCLASS
;
159 rthooks
->super_superclassfield_ident
= next_runtime_abi_01_super_superclassfield_id
;
161 rthooks
->class_decl
= next_runtime_abi_01_class_decl
;
162 rthooks
->metaclass_decl
= next_runtime_abi_01_metaclass_decl
;
163 rthooks
->category_decl
= next_runtime_abi_01_category_decl
;
164 rthooks
->protocol_decl
= next_runtime_abi_01_protocol_decl
;
165 rthooks
->string_decl
= next_runtime_abi_01_string_decl
;
167 rthooks
->get_class_reference
= next_runtime_abi_01_get_class_reference
;
168 rthooks
->build_selector_reference
= next_runtime_abi_01_build_selector_reference
;
169 rthooks
->get_protocol_reference
= next_runtime_abi_01_get_protocol_reference
;
170 rthooks
->build_ivar_reference
= next_runtime_abi_01_build_ivar_ref
;
171 rthooks
->get_class_super_ref
= next_runtime_abi_01_get_class_super_ref
;
172 rthooks
->get_category_super_ref
= next_runtime_abi_01_get_category_super_ref
;
174 rthooks
->receiver_is_class_object
= next_runtime_abi_01_receiver_is_class_object
;
175 rthooks
->get_arg_type_list_base
= next_runtime_abi_01_get_arg_type_list_base
;
176 rthooks
->build_objc_method_call
= next_runtime_abi_01_build_objc_method_call
;
178 rthooks
->setup_const_string_class_decl
=
179 next_runtime_abi_01_setup_const_string_class_decl
;
180 rthooks
->build_const_string_constructor
=
181 next_runtime_abi_01_build_const_string_constructor
;
183 rthooks
->build_throw_stmt
= build_throw_stmt
;
184 rthooks
->build_exc_ptr
= objc_build_exc_ptr
;
185 rthooks
->begin_catch
= begin_catch
;
186 rthooks
->finish_catch
= finish_catch
;
187 rthooks
->finish_try_stmt
= finish_try_stmt
;
189 rthooks
->generate_metadata
= objc_generate_v1_next_metadata
;
193 /* We need a way to convey what kind of meta-data are represented by a
194 given variable, since each type is expected (by the runtime) to be
195 found in a specific named section. The solution must be usable
198 The scheme used for NeXT ABI 0/1 (partial matching of variable
199 names) is not satisfactory for LTO & ABI-2. We now tag ObjC
200 meta-data with identification attributes in the front end. The
201 back-end may choose to act on these as it requires. */
204 next_runtime_abi_01_init_metadata_attributes (void)
207 objc_meta
= get_identifier ("OBJC1META");
210 meta_base
= get_identifier ("V1_BASE");
212 meta_class
= get_identifier ("V1_CLAS");
213 meta_metaclass
= get_identifier ("V1_META");
214 meta_category
= get_identifier ("V1_CATG");
215 meta_protocol
= get_identifier ("V1_PROT");
217 meta_clac_vars
= get_identifier ("V1_CLCV");
218 meta_clai_vars
= get_identifier ("V1_CLIV");
220 meta_clac_meth
= get_identifier ("V1_CLCM");
221 meta_clai_meth
= get_identifier ("V1_CLIM");
222 meta_catc_meth
= get_identifier ("V1_CACM");
223 meta_cati_meth
= get_identifier ("V1_CAIM");
224 meta_proto_cls_meth
= get_identifier ("V1_PCLM");
225 meta_proto_nst_meth
= get_identifier ("V1_PNSM");
227 meta_clas_prot
= get_identifier ("V1_CLPR");
228 meta_catg_prot
= get_identifier ("V1_CAPR");
230 meta_class_reference
= get_identifier ("V1_CLRF");
231 meta_proto_ref
= get_identifier ("V1_PRFS");
232 meta_sel_refs
= get_identifier ("V1_SRFS");
234 meta_class_name
= get_identifier ("V1_CLSN");
235 meta_meth_name
= get_identifier ("V1_METN");
236 meta_meth_type
= get_identifier ("V1_METT");
237 meta_prop_name_attr
= get_identifier ("V1_STRG");
239 meta_modules
= get_identifier ("V1_MODU");
240 meta_symtab
= get_identifier ("V1_SYMT");
241 meta_info
= get_identifier ("V1_INFO");
243 meta_proplist
= get_identifier ("V1_PLST");
244 meta_protocol_extension
= get_identifier ("V1_PEXT");
245 meta_class_extension
= get_identifier ("V1_CEXT");
247 meta_const_str
= get_identifier ("V1_CSTR");
250 static void build_v1_class_template (void);
251 static void build_v1_category_template (void);
252 static void build_v1_protocol_template (void);
254 static void next_runtime_01_initialize (void)
259 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
261 if (!global_options_set
.x_flag_objc_call_cxx_cdtors
)
262 global_options
.x_flag_objc_call_cxx_cdtors
= 1;
265 /* Set up attributes to be attached to the meta-data so that they
266 will be placed in the correct sections. */
267 next_runtime_abi_01_init_metadata_attributes ();
269 if (flag_objc_abi
>= 1)
270 objc_prop_list_ptr
= build_pointer_type (xref_tag (RECORD_TYPE
,
271 get_identifier ("_prop_list_t")));
273 /* Declare type of selector-objects that represent an operation
275 /* `struct objc_selector *' */
276 objc_selector_type
= build_pointer_type (xref_tag (RECORD_TYPE
,
277 get_identifier (TAG_SELECTOR
)));
279 build_v1_class_template ();
280 build_super_template ();
281 build_v1_protocol_template ();
282 build_v1_category_template ();
284 /* NB: In order to call one of the ..._stret (struct-returning)
285 functions, the function *MUST* first be cast to a signature that
286 corresponds to the actual ObjC method being invoked. This is
287 what is done by the build_objc_method_call() routine below. */
289 /* id objc_msgSend (id, SEL, ...); */
290 /* id objc_msgSendNonNil (id, SEL, ...); */
291 /* id objc_msgSend_stret (id, SEL, ...); */
292 /* id objc_msgSendNonNil_stret (id, SEL, ...); */
293 type
= build_varargs_function_type_list (objc_object_type
,
298 umsg_decl
= add_builtin_function (TAG_MSGSEND
,
299 type
, 0, NOT_BUILT_IN
,
302 umsg_nonnil_decl
= add_builtin_function (TAG_MSGSEND_NONNIL
,
303 type
, 0, NOT_BUILT_IN
,
306 umsg_stret_decl
= add_builtin_function (TAG_MSGSEND_STRET
,
307 type
, 0, NOT_BUILT_IN
,
310 umsg_nonnil_stret_decl
= add_builtin_function (TAG_MSGSEND_NONNIL_STRET
,
311 type
, 0, NOT_BUILT_IN
,
314 /* These can throw, because the function that gets called can throw
315 in Obj-C++, or could itself call something that can throw even in
317 TREE_NOTHROW (umsg_decl
) = 0;
318 TREE_NOTHROW (umsg_nonnil_decl
) = 0;
319 TREE_NOTHROW (umsg_stret_decl
) = 0;
320 TREE_NOTHROW (umsg_nonnil_stret_decl
) = 0;
322 /* id objc_msgSend_Fast (id, SEL, ...)
323 __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
324 #ifdef OFFS_MSGSEND_FAST
325 umsg_fast_decl
= add_builtin_function (TAG_MSGSEND_FAST
,
326 type
, 0, NOT_BUILT_IN
,
328 TREE_NOTHROW (umsg_fast_decl
) = 0;
329 DECL_ATTRIBUTES (umsg_fast_decl
)
330 = tree_cons (get_identifier ("hard_coded_address"),
331 build_int_cst (NULL_TREE
, OFFS_MSGSEND_FAST
),
334 /* No direct dispatch available. */
335 umsg_fast_decl
= umsg_decl
;
338 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
339 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
340 type
= build_varargs_function_type_list (objc_object_type
,
344 umsg_super_decl
= add_builtin_function (TAG_MSGSENDSUPER
,
345 type
, 0, NOT_BUILT_IN
,
347 umsg_super_stret_decl
= add_builtin_function (TAG_MSGSENDSUPER_STRET
,
348 type
, 0, NOT_BUILT_IN
, 0,
350 TREE_NOTHROW (umsg_super_decl
) = 0;
351 TREE_NOTHROW (umsg_super_stret_decl
) = 0;
353 type
= build_function_type_list (objc_object_type
,
354 const_string_type_node
,
357 /* id objc_getClass (const char *); */
359 = add_builtin_function (TAG_GETCLASS
, type
, 0, NOT_BUILT_IN
,
362 /* id objc_getMetaClass (const char *); */
363 objc_get_meta_class_decl
364 = add_builtin_function (TAG_GETMETACLASS
, type
, 0, NOT_BUILT_IN
, NULL
, NULL_TREE
);
366 /* This is the type of all of the following functions
367 objc_copyStruct(). */
368 type
= build_function_type_list (void_type_node
,
375 /* Declare the following function:
377 objc_copyStruct (void *destination, const void *source,
378 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
379 objc_copyStruct_decl
= add_builtin_function ("objc_copyStruct",
380 type
, 0, NOT_BUILT_IN
,
382 TREE_NOTHROW (objc_copyStruct_decl
) = 0;
383 objc_getPropertyStruct_decl
= NULL_TREE
;
384 objc_setPropertyStruct_decl
= NULL_TREE
;
386 build_next_objc_exception_stuff ();
387 if (flag_objc_exceptions
&& !flag_objc_sjlj_exceptions
)
388 using_eh_for_cleanups ();
389 lang_hooks
.eh_runtime_type
= objc_eh_runtime_type
;
390 lang_hooks
.eh_personality
= objc_eh_personality
;
393 /* --- templates --- */
395 /* struct _objc_class
397 struct _objc_class *isa;
398 struct _objc_class *super_class;
403 struct _objc_ivar_list *ivars;
404 struct _objc_method_list *methods;
405 struct objc_cache *cache;
406 struct _objc_protocol_list *protocols;
408 const char *ivar_layout;
409 struct _objc_class_ext *ext;
412 void *gc_object_type;
416 /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT
417 runtime. We generate them for ABI==0 to maintain backward binary
421 build_v1_class_template (void)
423 tree ptype
, decls
, *chain
= NULL
;
425 objc_class_template
= objc_start_struct (get_identifier (UTAG_CLASS
));
427 /* struct _objc_class *isa; */
428 decls
= add_field_decl (build_pointer_type (objc_class_template
),
431 /* struct _objc_class *super_class; */
432 add_field_decl (build_pointer_type (objc_class_template
),
433 "super_class", &chain
);
436 add_field_decl (string_type_node
, "name", &chain
);
439 add_field_decl (long_integer_type_node
, "version", &chain
);
442 add_field_decl (long_integer_type_node
, "info", &chain
);
444 /* long instance_size; */
445 add_field_decl (long_integer_type_node
, "instance_size", &chain
);
447 /* struct _objc_ivar_list *ivars; */
448 add_field_decl (objc_ivar_list_ptr
,"ivars", &chain
);
450 /* struct _objc_method_list *methods; */
451 add_field_decl (objc_method_list_ptr
, "methods", &chain
);
453 /* struct objc_cache *cache; */
454 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
455 get_identifier ("objc_cache")));
456 add_field_decl (ptype
, "cache", &chain
);
458 /* struct _objc_protocol **protocol_list; */
459 ptype
= build_pointer_type (build_pointer_type
460 (xref_tag (RECORD_TYPE
,
461 get_identifier (UTAG_PROTOCOL
))));
462 add_field_decl (ptype
, "protocol_list", &chain
);
464 if (flag_objc_abi
>= 1)
466 /* const char *ivar_layout; */
467 add_field_decl (const_string_type_node
, "ivar_layout", &chain
);
469 /* struct _objc_class_ext *ext; */
470 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
471 get_identifier (UTAG_CLASS_EXT
)));
472 add_field_decl (ptype
, "ext", &chain
);
477 add_field_decl (build_pointer_type (void_type_node
), "sel_id", &chain
);
478 /* void *gc_object_type; */
479 add_field_decl (build_pointer_type (void_type_node
), "gc_object_type",
483 objc_finish_struct (objc_class_template
, decls
);
486 /* struct _objc_category
490 struct _objc_method_list *instance_methods;
491 struct _objc_method_list *class_methods;
492 struct _objc_protocol_list *protocols;
494 uint32_t size; // sizeof (struct _objc_category)
495 struct _objc_property_list *instance_properties; // category's own @property decl.
500 build_v1_category_template (void)
502 tree ptype
, decls
, *chain
= NULL
;
504 objc_category_template
= objc_start_struct (get_identifier (UTAG_CATEGORY
));
506 /* char *category_name; */
507 decls
= add_field_decl (string_type_node
, "category_name", &chain
);
509 /* char *class_name; */
510 add_field_decl (string_type_node
, "class_name", &chain
);
512 /* struct _objc_method_list *instance_methods; */
513 add_field_decl (objc_method_list_ptr
, "instance_methods", &chain
);
515 /* struct _objc_method_list *class_methods; */
516 add_field_decl (objc_method_list_ptr
, "class_methods", &chain
);
518 /* struct _objc_protocol **protocol_list; */
519 ptype
= build_pointer_type (build_pointer_type (objc_protocol_template
));
520 add_field_decl (ptype
, "protocol_list", &chain
);
522 if (flag_objc_abi
>= 1)
524 add_field_decl (integer_type_node
, "size", &chain
);
526 /* struct _objc_property_list *instance_properties;
527 This field describes a category's @property declarations.
528 Properties from inherited protocols are not included. */
529 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
530 get_identifier (UTAG_PROPERTY_LIST
)));
531 add_field_decl (ptype
, "instance_properties", &chain
);
533 objc_finish_struct (objc_category_template
, decls
);
536 /* Begin code generation for protocols...
537 Modified for ObjC #1 extensions. */
539 /* struct _objc_protocol
542 struct _objc_protocol_extension *isa;
544 struct _objc_class *isa;
548 struct _objc_protocol **protocol_list;
549 struct _objc__method_prototype_list *instance_methods;
550 struct _objc__method_prototype_list *class_methods;
554 build_v1_protocol_template (void)
556 tree ptype
, decls
, *chain
= NULL
;
558 objc_protocol_template
= objc_start_struct (get_identifier (UTAG_PROTOCOL
));
560 if (flag_objc_abi
>= 1)
561 /* struct _objc_protocol_extension *isa; */
562 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
563 get_identifier (UTAG_PROTOCOL_EXT
)));
565 /* struct _objc_class *isa; */
566 ptype
= build_pointer_type (xref_tag (RECORD_TYPE
,
567 get_identifier (UTAG_CLASS
)));
569 decls
= add_field_decl (ptype
, "isa", &chain
);
571 /* char *protocol_name; */
572 add_field_decl (string_type_node
, "protocol_name", &chain
);
574 /* struct _objc_protocol **protocol_list; */
575 ptype
= build_pointer_type (build_pointer_type (objc_protocol_template
));
576 add_field_decl (ptype
, "protocol_list", &chain
);
578 /* struct _objc__method_prototype_list *instance_methods; */
579 add_field_decl (objc_method_proto_list_ptr
, "instance_methods", &chain
);
581 /* struct _objc__method_prototype_list *class_methods; */
582 add_field_decl (objc_method_proto_list_ptr
, "class_methods", &chain
);
584 objc_finish_struct (objc_protocol_template
, decls
);
587 /* --- names, decls identifers --- */
590 next_runtime_abi_01_super_superclassfield_id (void)
592 if (!super_superclassfield_id
)
593 super_superclassfield_id
= get_identifier ("super_class");
594 return super_superclassfield_id
;
598 next_runtime_abi_01_class_decl (tree klass
)
602 snprintf (buf
, BUFSIZE
, "_OBJC_Class_%s",
603 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
604 decl
= start_var_decl (objc_class_template
, buf
);
605 OBJCMETA (decl
, objc_meta
, meta_class
);
610 next_runtime_abi_01_metaclass_decl (tree klass
)
614 snprintf (buf
, BUFSIZE
, "_OBJC_MetaClass_%s",
615 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
616 decl
= start_var_decl (objc_class_template
, buf
);
617 OBJCMETA (decl
, objc_meta
, meta_metaclass
);
622 next_runtime_abi_01_category_decl (tree klass
)
626 snprintf (buf
, BUFSIZE
, "_OBJC_Category_%s_on_%s",
627 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass
)),
628 IDENTIFIER_POINTER (CLASS_NAME (klass
)));
629 decl
= start_var_decl (objc_category_template
, buf
);
630 OBJCMETA (decl
, objc_meta
, meta_category
);
635 next_runtime_abi_01_protocol_decl (tree p
)
640 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
642 snprintf (buf
, BUFSIZE
, "_OBJC_Protocol_%s",
643 IDENTIFIER_POINTER (PROTOCOL_NAME (p
)));
644 decl
= start_var_decl (objc_protocol_template
, buf
);
645 OBJCMETA (decl
, objc_meta
, meta_protocol
);
650 next_runtime_abi_01_string_decl (tree type
, const char *name
, string_section where
)
652 tree var
= start_var_decl (type
, name
);
656 OBJCMETA (var
, objc_meta
, meta_class_name
);
659 OBJCMETA (var
, objc_meta
, meta_meth_name
);
662 OBJCMETA (var
, objc_meta
, meta_meth_type
);
664 case prop_names_attr
:
665 OBJCMETA (var
, objc_meta
, meta_prop_name_attr
);
668 OBJCMETA (var
, objc_meta
, meta_base
);
676 static GTY(()) int class_reference_idx
;
679 build_class_reference_decl (void)
684 sprintf (buf
, "_OBJC_ClassRefs_%d", class_reference_idx
++);
685 decl
= start_var_decl (objc_class_type
, buf
);
691 next_runtime_abi_01_get_class_reference (tree ident
)
698 for (chain
= &cls_ref_chain
; *chain
; chain
= &TREE_CHAIN (*chain
))
699 if (TREE_VALUE (*chain
) == ident
)
701 if (! TREE_PURPOSE (*chain
))
702 TREE_PURPOSE (*chain
) = build_class_reference_decl ();
704 return TREE_PURPOSE (*chain
);
707 decl
= build_class_reference_decl ();
708 *chain
= tree_cons (decl
, ident
, NULL_TREE
);
715 add_class_reference (ident
);
717 params
= build_tree_list (NULL_TREE
,
718 my_build_string_pointer
719 (IDENTIFIER_LENGTH (ident
) + 1,
720 IDENTIFIER_POINTER (ident
)));
722 return build_function_call (input_location
, objc_get_class_decl
, params
);
726 /* Used by build_function_type_for_method. Append the types for
727 receiver & _cmd at the start of a method argument list to ARGTYPES.
728 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
729 trying to define a method or call one. SUPERFLAG says this is for a
730 send to super. METH may be NULL, in the case that there is no
734 next_runtime_abi_01_get_arg_type_list_base (VEC(tree
,gc
) **argtypes
, tree meth
,
735 int context
, int superflag
)
740 receiver_type
= objc_super_type
;
741 else if (context
== METHOD_DEF
&& TREE_CODE (meth
) == INSTANCE_METHOD_DECL
)
742 receiver_type
= objc_instance_type
;
744 receiver_type
= objc_object_type
;
746 VEC_safe_push (tree
, gc
, *argtypes
, receiver_type
);
747 /* Selector type - will eventually change to `int'. */
748 VEC_safe_push (tree
, gc
, *argtypes
, objc_selector_type
);
752 next_runtime_abi_01_receiver_is_class_object (tree receiver
)
754 if (TREE_CODE (receiver
) == VAR_DECL
755 && IS_CLASS (TREE_TYPE (receiver
)))
757 /* The receiver is a variable created by build_class_reference_decl. */
758 tree chain
= cls_ref_chain
;
759 /* Look up the identifier in the relevant chain. */
760 for (; chain
; chain
= TREE_CHAIN (chain
))
761 if (TREE_PURPOSE (chain
) == receiver
)
762 return TREE_VALUE (chain
);
768 build_selector_reference_decl (tree ident
)
771 char *t
, buf
[BUFSIZE
];
773 snprintf (buf
, BUFSIZE
, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident
));
778 *t
= '$'; /* Underscore would clash between foo:bar and foo_bar. */
781 decl
= start_var_decl (objc_selector_type
, buf
);
782 OBJCMETA (decl
, objc_meta
, meta_sel_refs
);
787 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED
,
789 tree proto ATTRIBUTE_UNUSED
)
791 tree
*chain
= &sel_ref_chain
;
796 if (TREE_VALUE (*chain
) == ident
)
797 return TREE_PURPOSE (*chain
);
799 chain
= &TREE_CHAIN (*chain
);
802 expr
= build_selector_reference_decl (ident
);
804 *chain
= tree_cons (expr
, ident
, NULL_TREE
);
809 /* Build a tree expression to send OBJECT the operation SELECTOR,
810 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
811 assuming the method has prototype METHOD_PROTOTYPE.
812 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
813 LOC is the location of the expression to build.
814 Use METHOD_PARAMS as list of args to pass to the method.
815 If SUPER_FLAG is nonzero, we look up the superclass's method. */
818 build_objc_method_call (location_t loc
, int super_flag
, tree method_prototype
,
819 tree lookup_object
, tree selector
,
822 tree sender
, sender_cast
, method
, t
;
823 tree rcv_p
= (super_flag
? objc_super_type
: objc_object_type
);
824 VEC(tree
, gc
) *parms
;
825 unsigned nparm
= (method_params
? list_length (method_params
) : 0);
827 /* If a prototype for the method to be called exists, then cast
828 the sender's return type and arguments to match that of the method.
829 Otherwise, leave sender as is. */
832 ? TREE_VALUE (TREE_TYPE (method_prototype
))
834 tree ftype
= build_function_type_for_method (ret_type
, method_prototype
,
835 METHOD_REF
, super_flag
);
837 if (method_prototype
&& METHOD_TYPE_ATTRIBUTES (method_prototype
))
838 ftype
= build_type_attribute_variant (ftype
,
839 METHOD_TYPE_ATTRIBUTES
842 sender_cast
= build_pointer_type (ftype
);
844 lookup_object
= build_c_cast (loc
, rcv_p
, lookup_object
);
846 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
847 lookup_object
= save_expr (lookup_object
);
849 /* Param list + 2 slots for object and selector. */
850 parms
= VEC_alloc (tree
, gc
, nparm
+ 2);
852 /* If we are returning a struct in memory, and the address
853 of that memory location is passed as a hidden first
854 argument, then change which messenger entry point this
855 expr will call. NB: Note that sender_cast remains
856 unchanged (it already has a struct return type). */
857 if (!targetm
.calls
.struct_value_rtx (0, 0)
858 && (TREE_CODE (ret_type
) == RECORD_TYPE
859 || TREE_CODE (ret_type
) == UNION_TYPE
)
860 && targetm
.calls
.return_in_memory (ret_type
, 0))
861 sender
= (super_flag
? umsg_super_stret_decl
862 : flag_nil_receivers
? umsg_stret_decl
863 : umsg_nonnil_stret_decl
);
865 sender
= (super_flag
? umsg_super_decl
866 : (flag_nil_receivers
? (flag_objc_direct_dispatch
869 : umsg_nonnil_decl
));
870 method
= build_fold_addr_expr_loc (loc
, sender
);
872 /* Pass the object to the method. */
873 VEC_quick_push (tree
, parms
, lookup_object
);
874 /* Pass the selector to the method. */
875 VEC_quick_push (tree
, parms
, selector
);
876 /* Now append the remainder of the parms. */
878 for (; method_params
; method_params
= TREE_CHAIN (method_params
))
879 VEC_quick_push (tree
, parms
, TREE_VALUE (method_params
));
881 /* Build an obj_type_ref, with the correct cast for the method call. */
882 t
= build3 (OBJ_TYPE_REF
, sender_cast
, method
,
883 lookup_object
, size_zero_node
);
884 t
= build_function_call_vec (loc
, t
, parms
, NULL
);
885 VEC_free (tree
, gc
, parms
);
890 next_runtime_abi_01_build_objc_method_call (location_t loc
,
891 tree method_prototype
,
893 tree rtype ATTRIBUTE_UNUSED
,
898 tree selector
= next_runtime_abi_01_build_selector_reference (loc
, sel_name
,
901 return build_objc_method_call (loc
, super
, method_prototype
,
902 receiver
, selector
, method_params
);
906 next_runtime_abi_01_get_protocol_reference (location_t loc
, tree p
)
910 if (!PROTOCOL_FORWARD_DECL (p
))
911 PROTOCOL_FORWARD_DECL (p
) = next_runtime_abi_01_protocol_decl (p
);
913 expr
= build_unary_op (loc
, ADDR_EXPR
, PROTOCOL_FORWARD_DECL (p
), 0);
914 return convert (objc_protocol_type
, expr
);
917 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
920 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED
,
923 return objc_build_component_ref (base
, id
);
926 /* We build super class references as we need them (but keep them once
927 built for the sake of efficiency). */
930 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED
,
931 struct imp_entry
*imp
, bool inst_meth
)
937 objc_build_component_ref (imp
->class_decl
,
938 get_identifier ("super_class"));
939 return ucls_super_ref
;
943 if (!uucls_super_ref
)
945 objc_build_component_ref (imp
->meta_decl
,
946 get_identifier ("super_class"));
947 return uucls_super_ref
;
952 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED
,
953 struct imp_entry
*imp
, bool inst_meth
)
955 tree super_name
= CLASS_SUPER_NAME (imp
->imp_template
);
960 super_class
= objc_get_class_reference (super_name
);
964 /* If we are in a class method, we must retrieve the
965 _metaclass_ for the current class, pointed at by
966 the class's "isa" pointer. The following assumes that
967 "isa" is the first ivar in a class (which it must be). */
969 build_indirect_ref (input_location
,
970 build_c_cast (input_location
,
971 build_pointer_type (objc_class_type
),
977 /* else do it the slow way. */
978 add_class_reference (super_name
);
979 super_class
= (inst_meth
? objc_get_class_decl
: objc_get_meta_class_decl
);
980 /* assemble_external (super_class);*/
981 super_name
= my_build_string_pointer (IDENTIFIER_LENGTH (super_name
) + 1,
982 IDENTIFIER_POINTER (super_name
));
983 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
984 return build_function_call (input_location
,
986 build_tree_list (NULL_TREE
, super_name
));
990 next_runtime_abi_01_setup_const_string_class_decl (void)
992 if (!constant_string_global_id
)
994 /* Hopefully, this should not represent a serious limitation. */
996 snprintf (buf
, BUFSIZE
, "_%sClassReference", constant_string_class_name
);
997 constant_string_global_id
= get_identifier (buf
);
1000 string_class_decl
= lookup_name (constant_string_global_id
);
1002 return (string_class_decl
!= NULL_TREE
);
1006 next_runtime_abi_01_build_const_string_constructor (location_t loc
, tree string
,
1009 tree constructor
, fields
, var
;
1010 VEC(constructor_elt
,gc
) *v
= NULL
;
1012 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1013 fields
= TYPE_FIELDS (internal_const_str_type
);
1014 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1015 build_unary_op (loc
, ADDR_EXPR
, string_class_decl
, 0));
1017 fields
= DECL_CHAIN (fields
);
1018 CONSTRUCTOR_APPEND_ELT (v
, fields
,
1019 build_unary_op (loc
, ADDR_EXPR
, string
, 1));
1021 /* ??? check if this should be long. */
1022 fields
= DECL_CHAIN (fields
);
1023 CONSTRUCTOR_APPEND_ELT (v
, fields
, build_int_cst (NULL_TREE
, length
));
1024 constructor
= objc_build_constructor (internal_const_str_type
, v
);
1026 var
= build_decl (input_location
, CONST_DECL
, NULL
, TREE_TYPE (constructor
));
1027 DECL_INITIAL (var
) = constructor
;
1028 TREE_STATIC (var
) = 1;
1029 DECL_CONTEXT (var
) = NULL
;
1030 OBJCMETA (var
, objc_meta
, meta_const_str
);
1034 /* --- metadata templates --- */
1036 /* This routine builds the following type:
1038 const char * const name; // property name
1039 const char * const attributes; // comma-delimited, encoded,
1040 // property attributes
1044 static GTY(()) tree objc_v1_property_template
;
1047 build_v1_property_template (void)
1050 tree decls
, *chain
= NULL
;
1052 prop_record
= objc_start_struct (get_identifier ("_prop_t"));
1053 /* const char * name */
1054 decls
= add_field_decl (string_type_node
, "name", &chain
);
1056 /* const char * attribute */
1057 add_field_decl (string_type_node
, "attribute", &chain
);
1059 objc_finish_struct (prop_record
, decls
);
1063 /* Build the following type:
1065 struct _objc_protocol_extension
1067 uint32_t size; // sizeof (struct _objc_protocol_extension)
1068 struct objc_method_list *optional_instance_methods;
1069 struct objc_method_list *optional_class_methods;
1070 struct objc_prop_list *instance_properties;
1074 static GTY(()) tree objc_protocol_extension_template
;
1077 build_v1_objc_protocol_extension_template (void)
1079 tree decls
, *chain
= NULL
;
1081 objc_protocol_extension_template
=
1082 objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT
));
1084 /* uint32_t size; */
1085 decls
= add_field_decl (integer_type_node
, "size", &chain
);
1087 /* struct objc_method_list *optional_instance_methods; */
1088 add_field_decl (objc_method_list_ptr
, "optional_instance_methods", &chain
);
1090 /* struct objc_method_list *optional_class_methods; */
1091 add_field_decl (objc_method_list_ptr
, "optional_class_methods", &chain
);
1093 /* struct objc_prop_list *instance_properties; */
1094 add_field_decl (objc_prop_list_ptr
, "instance_properties", &chain
);
1096 objc_finish_struct (objc_protocol_extension_template
, decls
);
1099 /* This routine build following struct type:
1100 struct _objc_class_ext
1102 uint32_t size; // sizeof(struct _objc_class_ext)
1103 const char *weak_ivar_layout;
1104 struct _prop_list_t *properties;
1108 static GTY(()) tree objc_class_ext_template
;
1111 build_objc_class_ext_template (void)
1113 tree ptrt
, decls
, *chain
= NULL
;
1115 objc_class_ext_template
= objc_start_struct (get_identifier (UTAG_CLASS_EXT
));
1117 /* uint32_t size; */
1118 decls
= add_field_decl (integer_type_node
, "size", &chain
);
1120 /* const char *weak_ivar_layout; */
1121 add_field_decl (const_string_type_node
, "weak_ivar_layout", &chain
);
1123 /* struct _prop_list_t *properties; */
1124 ptrt
= build_pointer_type (xref_tag (RECORD_TYPE
,
1125 get_identifier(UTAG_PROPERTY_LIST
)));
1126 add_field_decl (ptrt
, "properties", &chain
);
1128 objc_finish_struct (objc_class_ext_template
, decls
);
1132 build_metadata_templates (void)
1135 if (!objc_method_template
)
1136 objc_method_template
= build_method_template ();
1142 /* --- emit metadata --- */
1145 generate_v1_meth_descriptor_table (tree chain
, tree protocol
,
1146 const char *prefix
, tree attr
)
1148 tree method_list_template
, initlist
, decl
;
1150 VEC(constructor_elt
,gc
) *v
= NULL
;
1153 if (!chain
|| !prefix
)
1156 if (!objc_method_prototype_template
)
1157 objc_method_prototype_template
= build_method_prototype_template ();
1159 size
= list_length (chain
);
1160 method_list_template
=
1161 build_method_prototype_list_template (objc_method_prototype_template
,
1163 snprintf (buf
, BUFSIZE
, "%s_%s", prefix
,
1164 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol
)));
1166 decl
= start_var_decl (method_list_template
, buf
);
1168 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1170 build_descriptor_table_initializer (objc_method_prototype_template
,
1172 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
1173 /* Get into the right section. */
1174 OBJCMETA (decl
, objc_meta
, attr
);
1175 finish_var_decl (decl
, objc_build_constructor (method_list_template
, v
));
1179 /* Build protocol ext =
1180 {size, opt_instance_meth, opt_class_meth, instance_props};
1181 or NULL_TREE if none are present. */
1184 generate_v1_objc_protocol_extension (tree proto_interface
,
1185 tree opt_instance_meth
,
1186 tree opt_class_meth
,
1187 tree instance_props
)
1191 VEC(constructor_elt
,gc
) *v
= NULL
;
1195 /* If there are no extensions, then don't bother... */
1196 if (!opt_instance_meth
&& !opt_class_meth
&& !instance_props
)
1199 if (!objc_protocol_extension_template
)
1200 build_v1_objc_protocol_extension_template ();
1203 size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template
));
1204 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1206 /* Try for meaningful diagnostics. */
1207 loc
= DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface
));
1209 /* struct objc_method_list *optional_instance_methods; */
1210 if (opt_instance_meth
)
1211 expr
= convert (objc_method_list_ptr
,
1212 build_unary_op (loc
, ADDR_EXPR
, opt_instance_meth
, 0));
1214 expr
= convert (objc_method_list_ptr
, null_pointer_node
);
1216 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1218 /* struct objc_method_list *optional_class_methods; */
1220 expr
= convert (objc_method_list_ptr
,
1221 build_unary_op (loc
, ADDR_EXPR
, opt_class_meth
, 0));
1223 expr
= convert (objc_method_list_ptr
, null_pointer_node
);
1225 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1226 /* struct objc_prop_list *instance_properties; */
1228 expr
= convert (objc_prop_list_ptr
,
1229 build_unary_op (loc
, ADDR_EXPR
, instance_props
, 0));
1231 expr
= convert (objc_prop_list_ptr
, null_pointer_node
);
1233 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1234 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolExt_%s",
1235 IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface
)));
1237 decl
= start_var_decl (objc_protocol_extension_template
, buf
);
1238 expr
= objc_build_constructor (TREE_TYPE (decl
), v
);
1239 OBJCMETA (decl
, objc_meta
, meta_protocol_extension
);
1240 finish_var_decl (decl
, expr
);
1244 /* This routine builds the following type:
1245 struct _prop_list_t {
1246 uint32_t entsize; // sizeof (struct _prop_t)
1247 uint32_t prop_count;
1248 struct _prop_t prop_list [prop_count];
1253 build_v1_property_list_template (tree list_type
, int size
)
1255 tree property_list_t_record
;
1256 tree array_type
, decls
, *chain
= NULL
;
1259 property_list_t_record
= objc_start_struct (NULL_TREE
);
1261 /* uint32_t const entsize */
1262 decls
= add_field_decl (integer_type_node
, "entsize", &chain
);
1264 /* int prop_count */
1265 add_field_decl (integer_type_node
, "prop_count", &chain
);
1267 /* struct _prop_t prop_list[]; */
1268 array_type
= build_sized_array_type (list_type
, size
);
1269 add_field_decl (array_type
, "prop_list", &chain
);
1271 objc_finish_struct (property_list_t_record
, decls
);
1272 return property_list_t_record
;
1275 /* This routine builds the initializer list to initialize the
1276 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
1279 build_v1_property_table_initializer (tree type
, tree context
)
1282 VEC(constructor_elt
,gc
) *inits
= NULL
;
1284 if (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
)
1285 x
= CLASS_PROPERTY_DECL (context
);
1287 x
= IMPL_PROPERTY_DECL (context
);
1289 for (; x
; x
= TREE_CHAIN (x
))
1291 VEC(constructor_elt
,gc
) *elemlist
= NULL
;
1292 tree attribute
, name_ident
= PROPERTY_NAME (x
);
1294 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
1295 add_objc_string (name_ident
, prop_names_attr
));
1297 attribute
= objc_v2_encode_prop_attr (x
);
1298 CONSTRUCTOR_APPEND_ELT (elemlist
, NULL_TREE
,
1299 add_objc_string (attribute
, prop_names_attr
));
1301 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
,
1302 objc_build_constructor (type
, elemlist
));
1305 return objc_build_constructor (build_array_type (type
, 0),inits
);
1308 /* This routine builds the 'struct _prop_list_t' variable declaration and
1309 initializes it with its initializer list. TYPE is 'struct _prop_list_t',
1310 NAME is the internal name of this variable, SIZE is number of properties
1311 for this class and LIST is the initializer list for its 'prop_list' field. */
1314 generate_v1_property_table (tree context
, tree klass_ctxt
)
1316 tree x
, decl
, initlist
, property_list_template
;
1317 bool is_proto
= false;
1318 VEC(constructor_elt
,gc
) *inits
= NULL
;
1319 int init_val
, size
= 0;
1324 gcc_assert (TREE_CODE (context
) == PROTOCOL_INTERFACE_TYPE
);
1325 x
= CLASS_PROPERTY_DECL (context
);
1329 x
= IMPL_PROPERTY_DECL (klass_ctxt
);
1331 for (; x
; x
= TREE_CHAIN (x
))
1337 if (!objc_v1_property_template
)
1338 objc_v1_property_template
= build_v1_property_template ();
1340 property_list_template
=
1341 build_v1_property_list_template (objc_v1_property_template
,
1343 initlist
= build_v1_property_table_initializer (objc_v1_property_template
,
1347 init_val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template
));
1349 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolPropList_%s",
1350 IDENTIFIER_POINTER (PROTOCOL_NAME (context
)));
1352 snprintf (buf
, BUFSIZE
, "_OBJC_ClassPropList_%s",
1353 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)));
1355 decl
= start_var_decl (property_list_template
, buf
);
1356 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, init_val
));
1357 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1358 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
1359 x
= objc_build_constructor (TREE_TYPE (decl
), inits
);
1360 OBJCMETA (decl
, objc_meta
, meta_proplist
);
1361 finish_var_decl (decl
, x
);
1366 generate_v1_protocol_list (tree i_or_p
, tree klass_ctxt
)
1368 tree array_type
, ptype
, refs_decl
, lproto
, e
, plist
, attr
;
1370 VEC(constructor_elt
,gc
) *v
= NULL
;
1373 switch (TREE_CODE (i_or_p
))
1375 case CLASS_INTERFACE_TYPE
:
1376 case CATEGORY_INTERFACE_TYPE
:
1377 plist
= CLASS_PROTOCOL_LIST (i_or_p
);
1379 case PROTOCOL_INTERFACE_TYPE
:
1380 plist
= PROTOCOL_LIST (i_or_p
);
1387 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
1388 if (TREE_CODE (TREE_VALUE (lproto
)) == PROTOCOL_INTERFACE_TYPE
1389 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto
)))
1392 /* Build initializer. */
1393 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, 0));
1394 e
= build_int_cst (build_pointer_type (objc_protocol_template
), size
);
1395 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, e
);
1397 for (lproto
= plist
; lproto
; lproto
= TREE_CHAIN (lproto
))
1399 tree pval
= TREE_VALUE (lproto
);
1401 if (TREE_CODE (pval
) == PROTOCOL_INTERFACE_TYPE
1402 && PROTOCOL_FORWARD_DECL (pval
))
1404 tree fwref
= PROTOCOL_FORWARD_DECL (pval
);
1405 location_t loc
= DECL_SOURCE_LOCATION (fwref
) ;
1406 e
= build_unary_op (loc
, ADDR_EXPR
, fwref
, 0);
1407 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, e
);
1411 /* static struct objc_protocol *refs[n]; */
1412 switch (TREE_CODE (i_or_p
))
1414 case PROTOCOL_INTERFACE_TYPE
:
1415 snprintf (buf
, BUFSIZE
, "_OBJC_ProtocolRefs_%s",
1416 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p
)));
1417 attr
= meta_proto_ref
;
1419 case CLASS_INTERFACE_TYPE
:
1420 snprintf (buf
, BUFSIZE
, "_OBJC_ClassProtocols_%s",
1421 IDENTIFIER_POINTER (CLASS_NAME (i_or_p
)));
1422 attr
= meta_clas_prot
;
1424 case CATEGORY_INTERFACE_TYPE
:
1425 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryProtocols_%s_%s",
1426 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt
)),
1427 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt
)));
1428 attr
= meta_catg_prot
;
1434 ptype
= build_pointer_type (objc_protocol_template
);
1435 array_type
= build_sized_array_type (ptype
, size
+ 3);
1436 refs_decl
= start_var_decl (array_type
, buf
);
1438 OBJCMETA (refs_decl
, objc_meta
, attr
);
1439 finish_var_decl (refs_decl
,
1440 objc_build_constructor (TREE_TYPE (refs_decl
), v
));
1446 build_v1_protocol_initializer (tree type
, tree protocol_name
, tree protocol_list
,
1447 tree inst_methods
, tree class_methods
,
1452 VEC(constructor_elt
,gc
) *inits
= NULL
;
1454 if (!objc_protocol_extension_template
)
1455 build_v1_objc_protocol_extension_template ();
1457 /* TODO: find a better representation of location from the inputs. */
1458 loc
= UNKNOWN_LOCATION
;
1459 ttyp
= build_pointer_type (objc_protocol_extension_template
);
1460 /* Instead of jamming the protocol version number into the isa, we pass
1461 either a pointer to the protocol extension - or NULL. */
1463 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_ext
, 0));
1465 expr
= convert (ttyp
, null_pointer_node
);
1467 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1468 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_name
);
1469 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, protocol_list
);
1471 ttyp
= objc_method_proto_list_ptr
;
1473 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
1475 expr
= convert (ttyp
, null_pointer_node
);
1476 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1479 expr
= convert (ttyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
1481 expr
= convert (ttyp
, null_pointer_node
);
1482 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, expr
);
1484 return objc_build_constructor (type
, inits
);
1487 /* An updated version of generate_protocols () that emit the protocol
1488 extension for ABI=1. */
1490 /* For each protocol which was referenced either from a @protocol()
1491 expression, or because a class/category implements it (then a
1492 pointer to the protocol is stored in the struct describing the
1493 class/category), we create a statically allocated instance of the
1494 Protocol class. The code is written in such a way as to generate
1495 as few Protocol objects as possible; we generate a unique Protocol
1496 instance for each protocol, and we don't generate a Protocol
1497 instance if the protocol is never referenced (either from a
1498 @protocol() or from a class/category implementation). These
1499 statically allocated objects can be referred to via the static
1500 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1502 The statically allocated Protocol objects that we generate here
1503 need to be fixed up at runtime in order to be used: the 'isa'
1504 pointer of the objects need to be set up to point to the 'Protocol'
1505 class, as known at runtime.
1507 The NeXT runtime fixes up all protocols at program startup time,
1508 before main() is entered. It uses a low-level trick to look up all
1509 those symbols, then loops on them and fixes them up. */
1511 /* TODO: finish getting rid of passing stuff around in globals. */
1513 static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl
;
1514 static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl
;
1515 static GTY(()) tree V1_ProtocolExt_decl
;
1516 static GTY(()) tree V1_Property_decl
;
1519 generate_v1_protocols (void)
1523 /* If a protocol was directly referenced, pull in indirect references. */
1524 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
1525 if (PROTOCOL_FORWARD_DECL (p
) && PROTOCOL_LIST (p
))
1526 generate_protocol_references (PROTOCOL_LIST (p
));
1528 for (p
= protocol_chain
; p
; p
= TREE_CHAIN (p
))
1530 tree decl
, encoding
, initlist
, protocol_name_expr
;
1531 tree refs_type
, refs_decl
, refs_expr
;
1533 tree nst_methods
= PROTOCOL_NST_METHODS (p
);
1534 tree cls_methods
= PROTOCOL_CLS_METHODS (p
);
1536 /* If protocol wasn't referenced, don't generate any code. */
1537 decl
= PROTOCOL_FORWARD_DECL (p
);
1542 /* Make sure we link in the Protocol class. */
1543 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME
));
1547 if (! METHOD_ENCODING (nst_methods
))
1549 encoding
= encode_method_prototype (nst_methods
);
1550 METHOD_ENCODING (nst_methods
) = encoding
;
1552 nst_methods
= TREE_CHAIN (nst_methods
);
1555 UOBJC_INSTANCE_METHODS_decl
=
1556 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p
), p
,
1557 "_OBJC_ProtocolInstanceMethods",
1558 meta_proto_nst_meth
);
1562 if (! METHOD_ENCODING (cls_methods
))
1564 encoding
= encode_method_prototype (cls_methods
);
1565 METHOD_ENCODING (cls_methods
) = encoding
;
1568 cls_methods
= TREE_CHAIN (cls_methods
);
1571 UOBJC_CLASS_METHODS_decl
=
1572 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p
), p
,
1573 "_OBJC_ProtocolClassMethods",
1574 meta_proto_cls_meth
);
1576 /* There should be no optional methods for ABI-0 - but we need to
1577 check all this here before the lists are made. */
1578 nst_methods
= PROTOCOL_OPTIONAL_NST_METHODS (p
);
1581 if (! METHOD_ENCODING (nst_methods
))
1583 encoding
= encode_method_prototype (nst_methods
);
1584 METHOD_ENCODING (nst_methods
) = encoding
;
1586 nst_methods
= TREE_CHAIN (nst_methods
);
1589 V1_Protocol_OPT_NST_METHODS_decl
=
1590 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p
), p
,
1591 "_OBJC_OptionalProtocolInstanceMethods",
1592 meta_proto_nst_meth
);
1594 cls_methods
= PROTOCOL_OPTIONAL_CLS_METHODS (p
);
1597 if (! METHOD_ENCODING (cls_methods
))
1599 encoding
= encode_method_prototype (cls_methods
);
1600 METHOD_ENCODING (cls_methods
) = encoding
;
1603 cls_methods
= TREE_CHAIN (cls_methods
);
1606 V1_Protocol_OPT_CLS_METHODS_decl
=
1607 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p
), p
,
1608 "_OBJC_OptionalProtocolClassMethods",
1609 meta_proto_cls_meth
);
1611 if (PROTOCOL_LIST (p
))
1612 refs_decl
= generate_v1_protocol_list (p
, objc_implementation_context
);
1616 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1617 protocol_name_expr
= add_objc_string (PROTOCOL_NAME (p
), class_names
);
1618 /* TODO: more locations to be fixed up... */
1619 loc
= UNKNOWN_LOCATION
;
1621 build_pointer_type (build_pointer_type (objc_protocol_template
));
1623 refs_expr
= convert (refs_type
,
1624 build_unary_op (loc
, ADDR_EXPR
, refs_decl
, 0));
1626 refs_expr
= convert (refs_type
, null_pointer_node
);
1628 if (flag_objc_abi
< 1)
1632 build_protocol_initializer (TREE_TYPE (decl
),
1633 protocol_name_expr
, refs_expr
,
1634 UOBJC_INSTANCE_METHODS_decl
,
1635 UOBJC_CLASS_METHODS_decl
);
1636 finish_var_decl (decl
, initlist
);
1640 /* else - V1 extensions. */
1643 generate_v1_property_table (p
, NULL_TREE
);
1645 V1_ProtocolExt_decl
=
1646 generate_v1_objc_protocol_extension (p
,
1647 V1_Protocol_OPT_NST_METHODS_decl
,
1648 V1_Protocol_OPT_CLS_METHODS_decl
,
1651 initlist
= build_v1_protocol_initializer (TREE_TYPE (decl
),
1652 protocol_name_expr
, refs_expr
,
1653 UOBJC_INSTANCE_METHODS_decl
,
1654 UOBJC_CLASS_METHODS_decl
,
1655 V1_ProtocolExt_decl
);
1656 finish_var_decl (decl
, initlist
);
1661 generate_dispatch_table (tree chain
, const char *name
, tree attr
)
1663 tree decl
, method_list_template
, initlist
;
1664 VEC(constructor_elt
,gc
) *v
= NULL
;
1667 if (!chain
|| !name
|| !(size
= list_length (chain
)))
1670 if (!objc_method_template
)
1671 objc_method_template
= build_method_template ();
1673 method_list_template
= build_method_list_template (objc_method_template
,
1675 initlist
= build_dispatch_table_initializer (objc_method_template
, chain
);
1677 decl
= start_var_decl (method_list_template
, name
);
1679 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, integer_zero_node
);
1680 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1681 build_int_cst (integer_type_node
, size
));
1682 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, initlist
);
1684 OBJCMETA (decl
, objc_meta
, attr
);
1685 finish_var_decl (decl
,
1686 objc_build_constructor (TREE_TYPE (decl
), v
));
1691 /* Init a category. */
1693 build_v1_category_initializer (tree type
, tree cat_name
, tree class_name
,
1694 tree inst_methods
, tree class_methods
,
1695 tree protocol_list
, tree property_list
,
1699 VEC(constructor_elt
,gc
) *v
= NULL
;
1701 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, cat_name
);
1702 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, class_name
);
1704 ltyp
= objc_method_list_ptr
;
1706 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, inst_methods
, 0));
1708 expr
= convert (ltyp
, null_pointer_node
);
1709 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1712 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_methods
, 0));
1714 expr
= convert (ltyp
, null_pointer_node
);
1715 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1717 /* protocol_list = */
1718 ltyp
= build_pointer_type (build_pointer_type (objc_protocol_template
));
1720 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
1722 expr
= convert (ltyp
, null_pointer_node
);
1723 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1725 if (flag_objc_abi
>= 1)
1727 int val
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template
));
1728 expr
= build_int_cst (NULL_TREE
, val
);
1729 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1730 ltyp
= objc_prop_list_ptr
;
1732 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
1734 expr
= convert (ltyp
, null_pointer_node
);
1735 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1738 return objc_build_constructor (type
, v
);
1741 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1742 /* TODO: get rid of passing stuff around in globals. */
1744 generate_v1_category (struct imp_entry
*impent
)
1746 tree initlist
, cat_name_expr
, class_name_expr
;
1747 tree protocol_decl
, category
, cat_decl
;
1748 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
1749 tree cat
= impent
->imp_context
;
1753 cat_decl
= impent
->class_decl
;
1754 loc
= DECL_SOURCE_LOCATION (cat_decl
);
1756 add_class_reference (CLASS_NAME (cat
));
1757 cat_name_expr
= add_objc_string (CLASS_SUPER_NAME (cat
), class_names
);
1758 class_name_expr
= add_objc_string (CLASS_NAME (cat
), class_names
);
1760 category
= lookup_category (impent
->imp_template
, CLASS_SUPER_NAME (cat
));
1762 if (category
&& CLASS_PROTOCOL_LIST (category
))
1764 generate_protocol_references (CLASS_PROTOCOL_LIST (category
));
1765 protocol_decl
= generate_v1_protocol_list (category
, cat
);
1770 if (flag_objc_abi
>= 1)
1771 V1_Property_decl
= generate_v1_property_table (NULL_TREE
, cat
);
1773 V1_Property_decl
= NULL_TREE
;
1775 if (CLASS_NST_METHODS (cat
))
1777 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryInstanceMethods_%s_%s",
1778 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
1779 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
1780 inst_methods
= generate_dispatch_table (CLASS_NST_METHODS (cat
), buf
,
1784 if (CLASS_CLS_METHODS (cat
))
1786 snprintf (buf
, BUFSIZE
, "_OBJC_CategoryClassMethods_%s_%s",
1787 IDENTIFIER_POINTER (CLASS_NAME (cat
)),
1788 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat
)));
1789 class_methods
= generate_dispatch_table (CLASS_CLS_METHODS (cat
), buf
,
1793 initlist
= build_v1_category_initializer (TREE_TYPE (cat_decl
),
1794 cat_name_expr
, class_name_expr
,
1795 inst_methods
, class_methods
,
1796 protocol_decl
, V1_Property_decl
,
1799 finish_var_decl (cat_decl
, initlist
);
1800 impent
->class_decl
= cat_decl
;
1803 /* This routine builds the class extension used by v1 NeXT. */
1806 generate_objc_class_ext (tree property_list
, tree context
)
1808 tree decl
, expr
, ltyp
;
1809 tree weak_ivar_layout_tree
;
1812 VEC(constructor_elt
,gc
) *v
= NULL
;
1815 /* TODO: pass the loc in or find it from args. */
1816 loc
= UNKNOWN_LOCATION
;
1818 /* const char *weak_ivar_layout
1819 TODO: Figure the ivar layouts out... */
1820 weak_ivar_layout_tree
= NULL_TREE
;
1822 if (!property_list
&& !weak_ivar_layout_tree
)
1825 if (!objc_class_ext_template
)
1826 build_objc_class_ext_template ();
1829 size
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template
));
1830 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1832 ltyp
= const_string_type_node
;
1833 if (weak_ivar_layout_tree
)
1834 expr
= convert (ltyp
, weak_ivar_layout_tree
);
1836 expr
= convert (ltyp
, null_pointer_node
);
1837 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1839 /* struct _prop_list_t *properties; */
1840 ltyp
= objc_prop_list_ptr
;
1842 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, property_list
, 0));
1844 expr
= convert (ltyp
, null_pointer_node
);
1845 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1847 snprintf (buf
, BUFSIZE
, "_OBJC_ClassExt_%s",
1848 IDENTIFIER_POINTER (CLASS_NAME (context
)));
1849 decl
= start_var_decl (objc_class_ext_template
, buf
);
1850 expr
= objc_build_constructor (TREE_TYPE (decl
), v
);
1851 OBJCMETA (decl
, objc_meta
, meta_class_extension
);
1852 finish_var_decl (decl
, expr
);
1856 /* struct _objc_class {
1857 struct objc_class *isa;
1858 struct objc_class *super_class;
1863 struct objc_ivar_list *ivars;
1864 struct objc_method_list *methods;
1865 struct objc_cache *cache;
1866 struct objc_protocol_list *protocols;
1868 const char *ivar_layout;
1869 struct _objc_class_ext *ext;
1872 void *gc_object_type;
1877 build_v1_shared_structure_initializer (tree type
, tree isa
, tree super
,
1878 tree name
, tree size
, int status
,
1879 tree dispatch_table
, tree ivar_list
,
1880 tree protocol_list
, tree class_ext
)
1884 VEC(constructor_elt
,gc
) *v
= NULL
;
1886 /* TODO: fish the location out of the input data. */
1887 loc
= UNKNOWN_LOCATION
;
1890 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, isa
);
1893 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, super
);
1896 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, default_conversion (name
));
1899 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1900 build_int_cst (long_integer_type_node
, 0));
1903 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1904 build_int_cst (long_integer_type_node
, status
));
1906 /* instance_size = */
1907 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
1908 convert (long_integer_type_node
, size
));
1910 /* objc_ivar_list = */
1911 ltyp
= objc_ivar_list_ptr
;
1913 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, ivar_list
, 0));
1915 expr
= convert (ltyp
, null_pointer_node
);
1916 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1918 /* objc_method_list = */
1919 ltyp
= objc_method_list_ptr
;
1921 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, dispatch_table
, 0));
1923 expr
= convert (ltyp
, null_pointer_node
);
1924 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1926 ltyp
= build_pointer_type (xref_tag (RECORD_TYPE
,
1927 get_identifier ("objc_cache")));
1928 /* method_cache = */
1929 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, convert (ltyp
, null_pointer_node
));
1931 /* protocol_list = */
1932 ltyp
= build_pointer_type (build_pointer_type (objc_protocol_template
));
1934 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, protocol_list
, 0));
1936 expr
= convert (ltyp
, null_pointer_node
);
1937 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1939 if (flag_objc_abi
>= 1)
1941 /* TODO: figure out the ivar_layout stuff. */
1942 expr
= convert (const_string_type_node
, null_pointer_node
);
1943 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1944 if (!objc_class_ext_template
)
1945 build_objc_class_ext_template ();
1946 ltyp
= build_pointer_type (objc_class_ext_template
);
1948 expr
= convert (ltyp
, build_unary_op (loc
, ADDR_EXPR
, class_ext
, 0));
1950 expr
= convert (ltyp
, null_pointer_node
);
1951 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
1956 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, null_pointer_node
);
1958 /* gc_object_type = NULL */
1959 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, null_pointer_node
);
1961 return objc_build_constructor (type
, v
);
1965 generate_ivars_list (tree chain
, const char *name
, tree attr
)
1967 tree initlist
, ivar_list_template
, decl
;
1969 VEC(constructor_elt
,gc
) *inits
= NULL
;
1974 if (!objc_ivar_template
)
1975 objc_ivar_template
= build_ivar_template ();
1977 size
= ivar_list_length (chain
);
1979 generating_instance_variables
= 1;
1980 ivar_list_template
= build_ivar_list_template (objc_ivar_template
, size
);
1981 initlist
= build_ivar_list_initializer (objc_ivar_template
, chain
);
1982 generating_instance_variables
= 0;
1984 decl
= start_var_decl (ivar_list_template
, name
);
1986 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, build_int_cst (NULL_TREE
, size
));
1987 CONSTRUCTOR_APPEND_ELT (inits
, NULL_TREE
, initlist
);
1989 OBJCMETA (decl
, objc_meta
, attr
);
1990 finish_var_decl (decl
,
1991 objc_build_constructor (TREE_TYPE (decl
), inits
));
1996 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1997 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2000 generate_v1_class_structs (struct imp_entry
*impent
)
2002 tree name_expr
, super_expr
, root_expr
, class_decl
, meta_decl
;
2003 tree my_root_id
, my_super_id
;
2004 tree cast_type
, initlist
, protocol_decl
;
2005 tree class_ext_decl
= NULL_TREE
, props
= NULL_TREE
;
2006 tree inst_methods
= NULL_TREE
, class_methods
= NULL_TREE
;
2007 tree chain
, inst_ivars
= NULL_TREE
, class_ivars
= NULL_TREE
;
2012 /* objc_implementation_context = impent->imp_context;
2013 implementation_template = impent->imp_template;*/
2014 class_decl
= impent
->class_decl
;
2015 meta_decl
= impent
->meta_decl
;
2016 cls_flags
= impent
->has_cxx_cdtors
? CLS_HAS_CXX_STRUCTORS
: 0 ;
2018 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2020 if (flag_objc_abi
>= 1)
2022 /* ABI=1 additions. */
2023 props
= generate_v1_property_table (NULL_TREE
, impent
->imp_context
);
2024 class_ext_decl
= generate_objc_class_ext (props
, impent
->imp_context
);
2027 my_super_id
= CLASS_SUPER_NAME (impent
->imp_template
);
2030 add_class_reference (my_super_id
);
2032 /* Compute "my_root_id" - this is required for code generation.
2033 the "isa" for all meta class structures points to the root of
2034 the inheritance hierarchy (e.g. "__Object")... */
2035 my_root_id
= my_super_id
;
2038 tree my_root_int
= lookup_interface (my_root_id
);
2040 if (my_root_int
&& CLASS_SUPER_NAME (my_root_int
))
2041 my_root_id
= CLASS_SUPER_NAME (my_root_int
);
2046 super_expr
= add_objc_string (my_super_id
, class_names
);
2050 /* No super class. */
2051 my_root_id
= CLASS_NAME (impent
->imp_template
);
2052 super_expr
= null_pointer_node
;
2055 /* Install class `isa' and `super' pointers at runtime. */
2056 cast_type
= build_pointer_type (objc_class_template
);
2057 super_expr
= build_c_cast (loc
, cast_type
, super_expr
);
2059 root_expr
= add_objc_string (my_root_id
, class_names
);
2060 root_expr
= build_c_cast (loc
, cast_type
, root_expr
);
2062 if (CLASS_PROTOCOL_LIST (impent
->imp_template
))
2064 generate_protocol_references (CLASS_PROTOCOL_LIST (impent
->imp_template
));
2065 protocol_decl
= generate_v1_protocol_list (impent
->imp_template
,
2066 impent
->imp_context
);
2069 protocol_decl
= NULL_TREE
;
2071 if (CLASS_CLS_METHODS (impent
->imp_context
))
2073 snprintf (buf
, BUFSIZE
, "_OBJC_ClassMethods_%s",
2074 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2075 class_methods
= generate_dispatch_table (CLASS_CLS_METHODS (impent
->imp_context
),
2076 buf
, meta_clac_meth
);
2079 if (CLASS_SUPER_NAME (impent
->imp_template
) == NULL_TREE
2080 && (chain
= TYPE_FIELDS (objc_class_template
)))
2082 snprintf (buf
, BUFSIZE
, "_OBJC_ClassIvars_%s",
2083 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2084 class_ivars
= generate_ivars_list (chain
, buf
, meta_clac_vars
);
2086 /* TODO: get rid of hidden passing of stuff in globals. */
2087 /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */
2089 name_expr
= add_objc_string (CLASS_NAME (impent
->imp_template
), class_names
);
2091 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2093 initlist
= build_v1_shared_structure_initializer
2094 (TREE_TYPE (meta_decl
),
2095 root_expr
, super_expr
, name_expr
,
2096 convert (integer_type_node
, TYPE_SIZE_UNIT (objc_class_template
)),
2097 CLS_META
, class_methods
, class_ivars
,
2098 protocol_decl
, NULL_TREE
);
2100 finish_var_decl (meta_decl
, initlist
);
2101 impent
->meta_decl
= meta_decl
;
2103 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2104 if (CLASS_NST_METHODS (impent
->imp_context
))
2106 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceMethods_%s",
2107 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2108 inst_methods
= generate_dispatch_table (CLASS_NST_METHODS (impent
->imp_context
),
2109 buf
, meta_clai_meth
);
2112 if ((chain
= CLASS_IVARS (impent
->imp_template
)))
2114 snprintf (buf
, BUFSIZE
, "_OBJC_InstanceIvars_%s",
2115 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2116 inst_ivars
= generate_ivars_list (chain
, buf
, meta_clai_vars
);
2119 initlist
= build_v1_shared_structure_initializer
2120 (TREE_TYPE (class_decl
),
2121 build_unary_op (loc
, ADDR_EXPR
, meta_decl
, 0),
2122 super_expr
, name_expr
,
2123 convert (integer_type_node
,
2124 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent
->imp_template
))),
2125 CLS_FACTORY
| cls_flags
, inst_methods
, inst_ivars
,
2126 protocol_decl
, class_ext_decl
);
2128 finish_var_decl (class_decl
, initlist
);
2129 impent
->class_decl
= class_decl
;
2132 /* --- Output NeXT V1 Metadata --- */
2134 /* Create the initial value for the `defs' field of _objc_symtab.
2135 This is a CONSTRUCTOR. */
2138 init_def_list (tree type
)
2142 struct imp_entry
*impent
;
2143 VEC(constructor_elt
,gc
) *v
= NULL
;
2146 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2148 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
2150 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2151 expr
= build_unary_op (loc
,
2152 ADDR_EXPR
, impent
->class_decl
, 0);
2153 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2158 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2160 if (TREE_CODE (impent
->imp_context
) == CATEGORY_IMPLEMENTATION_TYPE
)
2162 loc
= DECL_SOURCE_LOCATION (impent
->class_decl
);
2163 expr
= build_unary_op (loc
,
2164 ADDR_EXPR
, impent
->class_decl
, 0);
2165 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, expr
);
2169 return objc_build_constructor (type
, v
);
2172 /* Take care of defining and initializing _OBJC_SYMBOLS. */
2174 /* Predefine the following data type:
2182 void *defs[cls_def_cnt + cat_def_cnt];
2186 build_objc_symtab_template (void)
2188 tree fields
, *chain
= NULL
;
2190 objc_symtab_template
= objc_start_struct (get_identifier (UTAG_SYMTAB
));
2192 /* long sel_ref_cnt; */
2193 fields
= add_field_decl (long_integer_type_node
, "sel_ref_cnt", &chain
);
2196 add_field_decl (build_pointer_type (objc_selector_type
), "refs", &chain
);
2198 /* short cls_def_cnt; */
2199 add_field_decl (short_integer_type_node
, "cls_def_cnt", &chain
);
2201 /* short cat_def_cnt; */
2202 add_field_decl (short_integer_type_node
, "cat_def_cnt", &chain
);
2204 if (imp_count
|| cat_count
)
2206 /* void *defs[imp_count + cat_count (+ 1)]; */
2207 /* NB: The index is one less than the size of the array. */
2208 int index
= imp_count
+ cat_count
;
2209 tree array_type
= build_sized_array_type (ptr_type_node
, index
);
2210 add_field_decl (array_type
, "defs", &chain
);
2213 objc_finish_struct (objc_symtab_template
, fields
);
2215 /* Construct the initial value for all of _objc_symtab. */
2218 init_objc_symtab (tree type
)
2220 VEC(constructor_elt
,gc
) *v
= NULL
;
2222 /* sel_ref_cnt = { ..., 5, ... } */
2224 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2225 build_int_cst (long_integer_type_node
, 0));
2227 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2229 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2230 convert (build_pointer_type (objc_selector_type
),
2231 integer_zero_node
));
2233 /* cls_def_cnt = { ..., 5, ... } */
2235 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2236 build_int_cst (short_integer_type_node
, imp_count
));
2238 /* cat_def_cnt = { ..., 5, ... } */
2240 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
,
2241 build_int_cst (short_integer_type_node
, cat_count
));
2243 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2245 if (imp_count
|| cat_count
)
2247 tree field
= TYPE_FIELDS (type
);
2248 field
= DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field
))));
2250 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, init_def_list (TREE_TYPE (field
)));
2253 return objc_build_constructor (type
, v
);
2256 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2257 and initialized appropriately. */
2260 generate_objc_symtab_decl (void)
2262 build_objc_symtab_template ();
2263 UOBJC_SYMBOLS_decl
= start_var_decl (objc_symtab_template
, "_OBJC_Symbols");
2264 /* Allow the runtime to mark meta-data such that it can be assigned to target
2265 specific sections by the back-end. */
2266 OBJCMETA (UOBJC_SYMBOLS_decl
, objc_meta
, meta_symtab
);
2267 finish_var_decl (UOBJC_SYMBOLS_decl
,
2268 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl
)));
2273 handle_next_class_ref (tree chain
)
2275 const char *name
= IDENTIFIER_POINTER (TREE_VALUE (chain
));
2276 char *string
= (char *) alloca (strlen (name
) + 30);
2278 sprintf (string
, ".objc_class_name_%s", name
);
2280 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
2281 ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file
, string
);
2283 return ; /* NULL build for targets other than Darwin. */
2288 handle_next_impent (struct imp_entry
*impent
)
2292 switch (TREE_CODE (impent
->imp_context
))
2294 case CLASS_IMPLEMENTATION_TYPE
:
2295 snprintf (buf
, BUFSIZE
, ".objc_class_name_%s",
2296 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)));
2298 case CATEGORY_IMPLEMENTATION_TYPE
:
2299 snprintf (buf
, BUFSIZE
, "*.objc_category_name_%s_%s",
2300 IDENTIFIER_POINTER (CLASS_NAME (impent
->imp_context
)),
2301 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent
->imp_context
)));
2307 #ifdef ASM_DECLARE_CLASS_REFERENCE
2308 ASM_DECLARE_CLASS_REFERENCE (asm_out_file
, buf
);
2310 return ; /* NULL build for targets other than Darwin. */
2315 generate_classref_translation_entry (tree chain
)
2317 tree expr
, decl
, type
;
2319 decl
= TREE_PURPOSE (chain
);
2320 type
= TREE_TYPE (decl
);
2322 expr
= add_objc_string (TREE_VALUE (chain
), class_names
);
2323 expr
= convert (type
, expr
); /* cast! */
2325 /* This is a class reference. It is re-written by the runtime,
2326 but will be optimized away unless we force it. */
2327 DECL_PRESERVE_P (decl
) = 1;
2328 OBJCMETA (decl
, objc_meta
, meta_class_reference
);
2329 finish_var_decl (decl
, expr
);
2334 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
2335 later requires that ObjC translation units participating in F&C be
2336 specially marked. The following routine accomplishes this. */
2338 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
2341 generate_objc_image_info (void)
2345 = ((flag_replace_objc_classes
&& imp_count
? 1 : 0)
2346 | (flag_objc_gc
? 2 : 0));
2347 VEC(constructor_elt
,gc
) *v
= NULL
;
2350 array_type
= build_sized_array_type (integer_type_node
, 2);
2352 decl
= start_var_decl (array_type
, "_OBJC_ImageInfo");
2354 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, integer_zero_node
);
2355 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, build_int_cst (integer_type_node
, flags
));
2356 /* The runtime wants this and refers to it in a manner hidden from the compiler.
2357 So we must force the output. */
2358 DECL_PRESERVE_P (decl
) = 1;
2359 OBJCMETA (decl
, objc_meta
, meta_info
);
2360 finish_var_decl (decl
, objc_build_constructor (TREE_TYPE (decl
), v
));
2364 objc_generate_v1_next_metadata (void)
2366 struct imp_entry
*impent
;
2370 /* FIXME: Make sure that we generate no metadata if there is nothing
2373 if (objc_static_instances
)
2374 gcc_unreachable (); /* Not for NeXT */
2376 build_metadata_templates ();
2377 objc_implementation_context
=
2378 implementation_template
=
2380 UOBJC_METACLASS_decl
= NULL_TREE
;
2382 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2385 /* If -gen-decls is present, Dump the @interface of each class.
2386 TODO: Dump the classes in the order they were found, rather than in
2387 reverse order as we are doing now. */
2388 if (flag_gen_declaration
)
2389 dump_interface (gen_declaration_file
, impent
->imp_context
);
2391 /* all of the following reference the string pool... */
2392 if (TREE_CODE (impent
->imp_context
) == CLASS_IMPLEMENTATION_TYPE
)
2393 generate_v1_class_structs (impent
);
2395 generate_v1_category (impent
);
2398 /* If we are using an array of selectors, we must always
2399 finish up the array decl even if no selectors were used. */
2400 build_next_selector_translation_table ();
2403 generate_v1_protocols ();
2405 /* Pass summary information to the runtime. */
2406 if (imp_count
|| cat_count
)
2407 generate_objc_symtab_decl ();
2409 vers
= OBJC_VERSION
;
2410 attr
= build_tree_list (objc_meta
, meta_modules
);
2411 build_module_descriptor (vers
, attr
);
2413 /* This conveys information on GC usage and zero-link. */
2414 generate_objc_image_info ();
2416 /* Dump the class references. This forces the appropriate classes
2417 to be linked into the executable image, preserving unix archive
2418 semantics. This can be removed when we move to a more dynamically
2419 linked environment. */
2421 for (chain
= cls_ref_chain
; chain
; chain
= TREE_CHAIN (chain
))
2423 handle_next_class_ref (chain
);
2424 if (TREE_PURPOSE (chain
))
2425 generate_classref_translation_entry (chain
);
2428 for (impent
= imp_list
; impent
; impent
= impent
->next
)
2429 handle_next_impent (impent
);
2431 /* Emit the strings tables. */
2432 generate_strings ();
2435 /* --- exceptions stuff --- */
2437 /* Predefine the following data type:
2439 struct _objc_exception_data
2441 int buf[OBJC_JBLEN];
2445 /* The following yuckiness should prevent users from having to #include
2446 <setjmp.h> in their code... */
2448 /* Define to a harmless positive value so the below code doesn't die. */
2450 #define OBJC_JBLEN 18
2454 build_next_objc_exception_stuff (void)
2456 tree decls
, temp_type
, *chain
= NULL
;
2458 objc_exception_data_template
2459 = objc_start_struct (get_identifier (UTAG_EXCDATA
));
2461 /* int buf[OBJC_JBLEN]; */
2463 temp_type
= build_sized_array_type (integer_type_node
, OBJC_JBLEN
);
2464 decls
= add_field_decl (temp_type
, "buf", &chain
);
2466 /* void *pointers[4]; */
2468 temp_type
= build_sized_array_type (ptr_type_node
, 4);
2469 add_field_decl (temp_type
, "pointers", &chain
);
2471 objc_finish_struct (objc_exception_data_template
, decls
);
2473 /* int _setjmp(...); */
2474 /* If the user includes <setjmp.h>, this shall be superseded by
2475 'int _setjmp(jmp_buf);' */
2476 temp_type
= build_varargs_function_type_list (integer_type_node
, NULL_TREE
);
2478 = add_builtin_function (TAG_SETJMP
, temp_type
, 0, NOT_BUILT_IN
, NULL
, NULL_TREE
);
2480 /* id objc_exception_extract(struct _objc_exception_data *); */
2482 = build_function_type_list (objc_object_type
,
2483 build_pointer_type (objc_exception_data_template
),
2485 objc_exception_extract_decl
2486 = add_builtin_function (TAG_EXCEPTIONEXTRACT
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2488 /* void objc_exception_try_enter(struct _objc_exception_data *); */
2489 /* void objc_exception_try_exit(struct _objc_exception_data *); */
2491 = build_function_type_list (void_type_node
,
2492 build_pointer_type (objc_exception_data_template
),
2494 objc_exception_try_enter_decl
2495 = add_builtin_function (TAG_EXCEPTIONTRYENTER
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2497 objc_exception_try_exit_decl
2498 = add_builtin_function (TAG_EXCEPTIONTRYEXIT
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2501 /* int objc_exception_match(id, id); */
2503 = build_function_type_list (integer_type_node
,
2504 objc_object_type
, objc_object_type
, NULL_TREE
);
2505 objc_exception_match_decl
2506 = add_builtin_function (TAG_EXCEPTIONMATCH
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2509 /* id objc_assign_ivar (id, id, unsigned int); */
2510 /* id objc_assign_ivar_Fast (id, id, unsigned int)
2511 __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2513 = build_function_type_list (objc_object_type
,
2518 objc_assign_ivar_decl
2519 = add_builtin_function (TAG_ASSIGNIVAR
, temp_type
, 0, NOT_BUILT_IN
,
2521 #ifdef OFFS_ASSIGNIVAR_FAST
2522 objc_assign_ivar_fast_decl
2523 = add_builtin_function (TAG_ASSIGNIVAR_FAST
, temp_type
, 0,
2524 NOT_BUILT_IN
, NULL
, NULL_TREE
);
2525 DECL_ATTRIBUTES (objc_assign_ivar_fast_decl
)
2526 = tree_cons (get_identifier ("hard_coded_address"),
2527 build_int_cst (NULL_TREE
, OFFS_ASSIGNIVAR_FAST
),
2530 /* Default to slower ivar method. */
2531 objc_assign_ivar_fast_decl
= objc_assign_ivar_decl
;
2534 /* id objc_assign_global (id, id *); */
2535 /* id objc_assign_strongCast (id, id *); */
2536 temp_type
= build_function_type_list (objc_object_type
,
2538 build_pointer_type (objc_object_type
),
2540 objc_assign_global_decl
2541 = add_builtin_function (TAG_ASSIGNGLOBAL
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2543 objc_assign_strong_cast_decl
2544 = add_builtin_function (TAG_ASSIGNSTRONGCAST
, temp_type
, 0, NOT_BUILT_IN
, NULL
,
2548 /* --- NeXT V1 SJLJ Exceptions --- */
2550 /* Build "objc_exception_try_exit(&_stack)". */
2553 next_sjlj_build_try_exit (struct objc_try_context
**ctcp
)
2556 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2557 t
= tree_cons (NULL
, t
, NULL
);
2558 t
= build_function_call (input_location
,
2559 objc_exception_try_exit_decl
, t
);
2564 objc_exception_try_enter (&_stack);
2565 if (_setjmp(&_stack.buf))
2569 Return the COND_EXPR. Note that the THEN and ELSE fields are left
2570 empty, ready for the caller to fill them in. */
2573 next_sjlj_build_enter_and_setjmp (struct objc_try_context
**ctcp
)
2575 tree t
, enter
, sj
, cond
;
2577 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2578 t
= tree_cons (NULL
, t
, NULL
);
2579 enter
= build_function_call (input_location
,
2580 objc_exception_try_enter_decl
, t
);
2582 t
= objc_build_component_ref ((*ctcp
)->stack_decl
,
2583 get_identifier ("buf"));
2584 t
= build_fold_addr_expr_loc (input_location
, t
);
2586 /* Convert _setjmp argument to type that is expected. */
2587 if (prototype_p (TREE_TYPE (objc_setjmp_decl
)))
2588 t
= convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl
))), t
);
2590 t
= convert (ptr_type_node
, t
);
2592 t
= convert (ptr_type_node
, t
);
2594 t
= tree_cons (NULL
, t
, NULL
);
2595 sj
= build_function_call (input_location
,
2596 objc_setjmp_decl
, t
);
2598 cond
= build2 (COMPOUND_EXPR
, TREE_TYPE (sj
), enter
, sj
);
2599 cond
= c_common_truthvalue_conversion (input_location
, cond
);
2601 return build3 (COND_EXPR
, void_type_node
, cond
, NULL
, NULL
);
2606 DECL = objc_exception_extract(&_stack); */
2609 next_sjlj_build_exc_extract (struct objc_try_context
**ctcp
, tree decl
)
2613 t
= build_fold_addr_expr_loc (input_location
, (*ctcp
)->stack_decl
);
2614 t
= tree_cons (NULL
, t
, NULL
);
2615 t
= build_function_call (input_location
,
2616 objc_exception_extract_decl
, t
);
2617 t
= convert (TREE_TYPE (decl
), t
);
2618 t
= build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
2624 if (objc_exception_match(obj_get_class(TYPE), _caught)
2631 objc_exception_try_exit(&_stack);
2633 from the sequence of CATCH_EXPRs in the current try context. */
2636 next_sjlj_build_catch_list (struct objc_try_context
**ctcp
)
2638 tree_stmt_iterator i
= tsi_start ((*ctcp
)->catch_list
);
2640 tree
*last
= &catch_seq
;
2641 bool saw_id
= false;
2643 for (; !tsi_end_p (i
); tsi_next (&i
))
2645 tree stmt
= tsi_stmt (i
);
2646 tree type
= CATCH_TYPES (stmt
);
2647 tree body
= CATCH_BODY (stmt
);
2649 if (type
!= error_mark_node
2650 && objc_is_object_id (TREE_TYPE (type
)))
2660 if (type
== error_mark_node
)
2661 cond
= error_mark_node
;
2664 args
= tree_cons (NULL
, (*ctcp
)->caught_decl
, NULL
);
2665 t
= objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type
)));
2666 args
= tree_cons (NULL
, t
, args
);
2667 t
= build_function_call (input_location
,
2668 objc_exception_match_decl
, args
);
2669 cond
= c_common_truthvalue_conversion (input_location
, t
);
2671 t
= build3 (COND_EXPR
, void_type_node
, cond
, body
, NULL
);
2672 SET_EXPR_LOCATION (t
, EXPR_LOCATION (stmt
));
2675 last
= &COND_EXPR_ELSE (t
);
2681 t
= build2 (MODIFY_EXPR
, void_type_node
, (*ctcp
)->rethrow_decl
,
2682 (*ctcp
)->caught_decl
);
2683 SET_EXPR_LOCATION (t
, (*ctcp
)->end_catch_locus
);
2684 append_to_statement_list (t
, last
);
2686 t
= next_sjlj_build_try_exit (ctcp
);
2687 SET_EXPR_LOCATION (t
, (*ctcp
)->end_catch_locus
);
2688 append_to_statement_list (t
, last
);
2694 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2695 exception handling. We aim to build:
2698 struct _objc_exception_data _stack;
2702 objc_exception_try_enter (&_stack);
2703 if (_setjmp(&_stack.buf))
2705 id _caught = objc_exception_extract(&_stack);
2706 objc_exception_try_enter (&_stack);
2707 if (_setjmp(&_stack.buf))
2708 _rethrow = objc_exception_extract(&_stack);
2718 objc_exception_try_exit(&_stack);
2721 objc_exception_throw(_rethrow);
2725 If CATCH-LIST is empty, we can omit all of the block containing
2726 "_caught" except for the setting of _rethrow. Note the use of
2727 a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2728 but handles goto and other exits from the block. */
2731 next_sjlj_build_try_catch_finally (struct objc_try_context
**ctcp
)
2733 tree rethrow_decl
, stack_decl
, t
;
2734 tree catch_seq
, try_fin
, bind
;
2735 struct objc_try_context
*cur_try_context
= *ctcp
;
2737 /* Create the declarations involved. */
2738 t
= xref_tag (RECORD_TYPE
, get_identifier (UTAG_EXCDATA
));
2739 stack_decl
= objc_create_temporary_var (t
, NULL
);
2740 cur_try_context
->stack_decl
= stack_decl
;
2742 rethrow_decl
= objc_create_temporary_var (objc_object_type
, NULL
);
2743 cur_try_context
->rethrow_decl
= rethrow_decl
;
2744 TREE_CHAIN (rethrow_decl
) = stack_decl
;
2746 /* Build the outermost variable binding level. */
2747 bind
= build3 (BIND_EXPR
, void_type_node
, rethrow_decl
, NULL
, NULL
);
2748 SET_EXPR_LOCATION (bind
, cur_try_context
->try_locus
);
2749 TREE_SIDE_EFFECTS (bind
) = 1;
2751 /* Initialize rethrow_decl. */
2752 t
= build2 (MODIFY_EXPR
, void_type_node
, rethrow_decl
,
2753 convert (objc_object_type
, null_pointer_node
));
2754 SET_EXPR_LOCATION (t
, cur_try_context
->try_locus
);
2755 append_to_statement_list (t
, &BIND_EXPR_BODY (bind
));
2757 /* Build the outermost TRY_FINALLY_EXPR. */
2758 try_fin
= build2 (TRY_FINALLY_EXPR
, void_type_node
, NULL
, NULL
);
2759 SET_EXPR_LOCATION (try_fin
, cur_try_context
->try_locus
);
2760 TREE_SIDE_EFFECTS (try_fin
) = 1;
2761 append_to_statement_list (try_fin
, &BIND_EXPR_BODY (bind
));
2763 /* Create the complete catch sequence. */
2764 if (cur_try_context
->catch_list
)
2766 tree caught_decl
= objc_build_exc_ptr (ctcp
);
2767 catch_seq
= build_stmt (input_location
, BIND_EXPR
, caught_decl
, NULL
, NULL
);
2768 TREE_SIDE_EFFECTS (catch_seq
) = 1;
2770 t
= next_sjlj_build_exc_extract (ctcp
, caught_decl
);
2771 append_to_statement_list (t
, &BIND_EXPR_BODY (catch_seq
));
2773 t
= next_sjlj_build_enter_and_setjmp (ctcp
);
2774 COND_EXPR_THEN (t
) = next_sjlj_build_exc_extract (ctcp
, rethrow_decl
);
2775 COND_EXPR_ELSE (t
) = next_sjlj_build_catch_list (ctcp
);
2776 append_to_statement_list (t
, &BIND_EXPR_BODY (catch_seq
));
2779 catch_seq
= next_sjlj_build_exc_extract (ctcp
, rethrow_decl
);
2780 SET_EXPR_LOCATION (catch_seq
, cur_try_context
->end_try_locus
);
2782 /* Build the main register-and-try if statement. */
2783 t
= next_sjlj_build_enter_and_setjmp (ctcp
);
2784 SET_EXPR_LOCATION (t
, cur_try_context
->try_locus
);
2785 COND_EXPR_THEN (t
) = catch_seq
;
2786 COND_EXPR_ELSE (t
) = cur_try_context
->try_body
;
2787 TREE_OPERAND (try_fin
, 0) = t
;
2789 /* Build the complete FINALLY statement list. */
2790 t
= next_sjlj_build_try_exit (ctcp
);
2791 t
= build_stmt (input_location
, COND_EXPR
,
2792 c_common_truthvalue_conversion
2793 (input_location
, rethrow_decl
),
2795 SET_EXPR_LOCATION (t
, cur_try_context
->finally_locus
);
2796 append_to_statement_list (t
, &TREE_OPERAND (try_fin
, 1));
2798 append_to_statement_list (cur_try_context
->finally_body
,
2799 &TREE_OPERAND (try_fin
, 1));
2801 t
= tree_cons (NULL
, rethrow_decl
, NULL
);
2802 t
= build_function_call (input_location
,
2803 objc_exception_throw_decl
, t
);
2804 t
= build_stmt (input_location
, COND_EXPR
,
2805 c_common_truthvalue_conversion (input_location
,
2808 SET_EXPR_LOCATION (t
, cur_try_context
->end_finally_locus
);
2809 append_to_statement_list (t
, &TREE_OPERAND (try_fin
, 1));
2814 /* We do not expect this to be used at the moment.
2815 If (a) it is possible to implement unwinder exceptions.
2816 (b) we do it... then it might be possibly useful.
2818 static GTY(()) tree objc_eh_personality_decl
;
2821 objc_eh_runtime_type (tree type
)
2823 tree ident
, eh_id
, decl
, str
;
2826 if (type
== error_mark_node
)
2828 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2829 to prevent an ICE. Note that we know that the compiler will
2830 terminate with an error and this 'ErrorMarkNode' class name will
2831 never be actually used. */
2832 ident
= get_identifier ("ErrorMarkNode");
2833 goto make_err_class
;
2836 if (POINTER_TYPE_P (type
) && objc_is_object_id (TREE_TYPE (type
)))
2838 ident
= get_identifier ("id");
2839 goto make_err_class
;
2842 if (!POINTER_TYPE_P (type
) || !TYPED_OBJECT (TREE_TYPE (type
)))
2845 /* This routine is also called for c++'s catch clause; in which case,
2846 we use c++'s typeinfo decl. */
2847 return build_eh_type_type (type
);
2849 error ("non-objective-c type '%T' cannot be caught", type
);
2850 ident
= get_identifier ("ErrorMarkNode");
2851 goto make_err_class
;
2855 ident
= OBJC_TYPE_NAME (TREE_TYPE (type
));
2858 /* If this class was already referenced, then it will be output during
2859 meta-data emission, so we don't need to do it here. */
2860 decl
= get_objc_string_decl (ident
, class_names
);
2861 eh_id
= add_objc_string (ident
, class_names
);
2864 /* Not found ... so we need to build it - from the freshly-entered id. */
2865 decl
= get_objc_string_decl (ident
, class_names
);
2866 str
= my_build_string (IDENTIFIER_LENGTH (ident
) + 1,
2867 IDENTIFIER_POINTER (ident
));
2868 /* We have to finalize this var here, because this might be called after
2869 all the other metadata strings have been emitted. */
2870 finish_var_decl (decl
, str
);
2875 /* For NeXT ABI 0 and 1, the personality routines are just those of the
2876 underlying language. */
2879 objc_eh_personality (void)
2881 if (!objc_eh_personality_decl
)
2883 objc_eh_personality_decl
= build_personality_function ("gcc");
2885 objc_eh_personality_decl
= build_personality_function ("gxx");
2887 return objc_eh_personality_decl
;
2890 /* --- interfaces --- */
2893 build_throw_stmt (location_t loc
, tree throw_expr
, bool rethrown ATTRIBUTE_UNUSED
)
2896 VEC(tree
, gc
) *parms
= VEC_alloc (tree
, gc
, 1);
2897 /* A throw is just a call to the runtime throw function with the
2898 object as a parameter. */
2899 VEC_quick_push (tree
, parms
, throw_expr
);
2900 t
= build_function_call_vec (loc
, objc_exception_throw_decl
, parms
, NULL
);
2901 VEC_free (tree
, gc
, parms
);
2902 return add_stmt (t
);
2905 /* Build __builtin_eh_pointer, or the moral equivalent. In the case
2906 of Darwin, we'll arrange for it to be initialized (and associated
2907 with a binding) later. */
2910 objc_build_exc_ptr (struct objc_try_context
**cur_try_context
)
2912 if (flag_objc_sjlj_exceptions
)
2914 tree var
= (*cur_try_context
)->caught_decl
;
2917 var
= objc_create_temporary_var (objc_object_type
, NULL
);
2918 (*cur_try_context
)->caught_decl
= var
;
2925 t
= builtin_decl_explicit (BUILT_IN_EH_POINTER
);
2926 t
= build_call_expr (t
, 1, integer_zero_node
);
2927 return fold_convert (objc_object_type
, t
);
2932 begin_catch (struct objc_try_context
**cur_try_context
, tree type
,
2933 tree decl
, tree compound
, bool ellipsis ATTRIBUTE_UNUSED
)
2936 /* Record the data for the catch in the try context so that we can
2937 finalize it later. We treat ellipsis the same way as catching
2939 t
= build_stmt (input_location
, CATCH_EXPR
, type
, compound
);
2940 (*cur_try_context
)->current_catch
= t
;
2942 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
2943 t
= objc_build_exc_ptr (cur_try_context
);
2944 t
= convert (TREE_TYPE (decl
), t
);
2945 return build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
2949 finish_catch (struct objc_try_context
**cur_try_context
, tree current_catch
)
2951 append_to_statement_list (current_catch
, &((*cur_try_context
)->catch_list
));
2955 finish_try_stmt (struct objc_try_context
**cur_try_context
)
2958 struct objc_try_context
*c
= *cur_try_context
;
2959 /* If we're doing Darwin setjmp exceptions, build the big nasty. */
2960 if (flag_objc_sjlj_exceptions
)
2962 bool save
= in_late_binary_op
;
2963 in_late_binary_op
= true;
2964 if (!c
->finally_body
)
2966 c
->finally_locus
= input_location
;
2967 c
->end_finally_locus
= input_location
;
2969 stmt
= next_sjlj_build_try_catch_finally (cur_try_context
);
2970 in_late_binary_op
= save
;
2973 /* This doesn't happen at the moment... but maybe one day... */
2975 /* Otherwise, nest the CATCH inside a FINALLY. */
2978 stmt
= build_stmt (c
->try_locus
, TRY_CATCH_EXPR
, stmt
, c
->catch_list
);
2979 if (c
->finally_body
)
2980 stmt
= build_stmt (c
->try_locus
, TRY_FINALLY_EXPR
, stmt
, c
->finally_body
);
2985 #include "gt-objc-objc-next-runtime-abi-01.h"