xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/objc/objc-next-runtime-abi-02.c (revision d909946ca08dceb44d7d0f22ec9488679695d976)
1 /* Next Runtime (ABI-2) private.
2    Copyright (C) 2011-2013 Free Software Foundation, Inc.
3 
4    Contributed by Iain Sandoe and based, in part, on an implementation in
5    'branches/apple/trunk' contributed by Apple Computer Inc.
6 
7 This file is part of GCC.
8 
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13 
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22 
23 /* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
24 
25    This version is intended to match (logically) the output of Apple's
26    4.2.1 compiler.  */
27 
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "tree.h"
33 
34 #ifdef OBJCPLUS
35 #include "cp/cp-tree.h"
36 #else
37 #include "c/c-tree.h"
38 #include "c/c-lang.h"
39 #endif
40 #include "langhooks.h"
41 #include "c-family/c-objc.h"
42 #include "objc-act.h"
43 
44 /* When building Objective-C++, we are not linking against the C front-end
45    and so need to replicate the C tree-construction functions in some way.  */
46 #ifdef OBJCPLUS
47 #define OBJCP_REMAP_FUNCTIONS
48 #include "objcp-decl.h"
49 #endif  /* OBJCPLUS */
50 
51 #include "ggc.h"
52 #include "target.h"
53 #include "tree-iterator.h"
54 
55 #include "objc-runtime-hooks.h"
56 #include "objc-runtime-shared-support.h"
57 #include "objc-encoding.h"
58 
59 /* ABI 2 Private definitions. */
60 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
61 
62 #define TAG_GETCLASS		"objc_getClass"
63 #define TAG_GETMETACLASS	"objc_getMetaClass"
64 
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"
69 
70 #define TAG_NEXT_EHVTABLE_NAME	"objc_ehtype_vtable"
71 #define TAG_V2_EH_TYPE		"objc_ehtype_t"
72 
73 #define UTAG_V2_CLASS		"_class_t"
74 #define UTAG_V2_CLASS_RO	"_class_ro_t"
75 #define UTAG_V2_PROTOCOL	"_protocol_t"
76 #define UTAG_V2_PROTOCOL_LIST	"_protocol_list_t"
77 
78 #define UTAG_V2_EH_TYPE		"_objc_ehtype_t"
79 
80 #define OBJC2_CLS_HAS_CXX_STRUCTORS	0x0004L
81 
82 enum objc_v2_tree_index
83 {
84   /* Templates.  */
85   OCTI_V2_CLS_TEMPL,
86   OCTI_V2_CAT_TEMPL,
87   OCTI_V2_CLS_RO_TEMPL,
88   OCTI_V2_PROTO_TEMPL,
89   OCTI_V2_IVAR_TEMPL,
90   OCTI_V2_IVAR_LIST_TEMPL,
91   OCTI_V2_MESSAGE_REF_TEMPL,
92   OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
93 
94   OCTI_V2_MESSAGE_SELECTOR_TYPE,
95   OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
96   OCTI_V2_IMP_TYPE,
97   OCTI_V2_SUPER_IMP_TYPE,
98 
99   OCTI_V2_CACHE_DECL,
100   OCTI_V2_VTABLE_DECL,
101 
102   OCTI_V2_PROPERTY_TEMPL,
103 
104   /* V2 messaging.  */
105   OCTI_V2_UMSG_FIXUP_DECL,
106   OCTI_V2_UMSG_STRET_FIXUP_DECL,
107   OCTI_V2_UMSG_ID_FIXUP_DECL,
108   OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
109   OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
110   OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
111 
112   /* Exceptions - related.  */
113   OCTI_V2_BEGIN_CATCH_DECL,
114   OCTI_V2_END_CATCH_DECL,
115   OCTI_V2_RETHROW_DECL,
116 
117   OCTI_V2_MAX
118 };
119 
120 #define objc_v2_class_template	objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
121 #define objc_v2_class_ro_template \
122 				objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
123 #define objc_v2_category_template \
124 				objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
125 #define objc_v2_protocol_template \
126 				objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
127 
128 /* struct message_ref_t */
129 #define objc_v2_message_ref_template \
130 				objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
131 
132 #define objc_v2_ivar_list_ptr	objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
133 
134 /* struct super_message_ref_t */
135 #define objc_v2_super_message_ref_template \
136 				objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
137 
138 /* struct message_ref_t* */
139 #define objc_v2_selector_type	objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
140 /* struct super_super_message_ref_t */
141 #define objc_v2_super_selector_type \
142 				objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
143 #define objc_v2_imp_type	objc_v2_global_trees[OCTI_V2_IMP_TYPE]
144 #define objc_v2_super_imp_type	objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
145 
146 #define UOBJC_V2_CACHE_decl	objc_v2_global_trees[OCTI_V2_CACHE_DECL]
147 #define UOBJC_V2_VTABLE_decl	objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
148 
149 #define objc_v2_ivar_template	objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
150 #define objc_v2_property_template \
151 				objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
152 
153 /* V2 Messaging */
154 
155 /* objc_msgSend_fixup_rtp */
156 #define umsg_fixup_decl		objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
157 /* objc_msgSend_stret_fixup_rtp */
158 #define umsg_stret_fixup_decl	objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
159 /* objc_msgSendId_fixup_rtp */
160 #define umsg_id_fixup_decl	objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
161 /* objc_msgSendId_stret_fixup_rtp */
162 #define umsg_id_stret_fixup_decl \
163 				objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
164 /* objc_msgSendSuper2_fixup_rtp */
165 #define umsg_id_super2_fixup_decl \
166 				objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
167 /* objc_msgSendSuper2_stret_fixup_rtp */
168 #define umsg_id_super2_stret_fixup_decl \
169 				objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
170 
171 #define objc2_begin_catch_decl	objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
172 #define objc2_end_catch_decl	objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
173 #define objc_rethrow_exception_decl \
174 				objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
175 
176 /* rt_trees identifiers - shared between NeXT implementations.  These allow
177    the FE to tag meta-data in a manner that survives LTO and can be used when
178    the  runtime requires that certain meta-data items appear in particular
179    named sections.  */
180 
181 #include "objc-next-metadata-tags.h"
182 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
183 
184 /* The OCTI_V2_... enumeration itself is in above.  */
185 static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
186 
187 static void next_runtime_02_initialize (void);
188 
189 static void build_v2_message_ref_templates (void);
190 static void build_v2_class_templates (void);
191 static void build_v2_super_template (void);
192 static void build_v2_category_template (void);
193 static void build_v2_protocol_template (void);
194 
195 static tree next_runtime_abi_02_super_superclassfield_id (void);
196 
197 static tree next_runtime_abi_02_class_decl (tree);
198 static tree next_runtime_abi_02_metaclass_decl (tree);
199 static tree next_runtime_abi_02_category_decl (tree);
200 static tree next_runtime_abi_02_protocol_decl (tree);
201 static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
202 
203 static tree next_runtime_abi_02_get_class_reference (tree);
204 static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
205 static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
206 static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
207 static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
208 static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
209 
210 static tree next_runtime_abi_02_receiver_is_class_object (tree);
211 static void next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **,
212 							tree, int, int);
213 static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
214 							tree, tree, tree, int);
215 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
216 static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
217 
218 static tree create_extern_decl (tree, const char *);
219 
220 static void objc_generate_v2_next_metadata (void);
221 static bool objc2_objc_exception_attr (tree);
222 
223 /* void build_v2_protocol_reference (tree);*/
224 static void build_v2_ehtype_template (void);
225 static void build_v2_eh_catch_objects (void);
226 static tree next_runtime_02_eh_type (tree);
227 static tree objc_eh_personality (void);
228 static tree build_throw_stmt (location_t, tree, bool);
229 static tree objc_build_exc_ptr (struct objc_try_context **);
230 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
231 static void finish_catch (struct objc_try_context **, tree);
232 static tree finish_try_stmt (struct objc_try_context **);
233 
234 /* TODO: Use an objc-map.  */
235 static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
236 
237 bool
238 objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
239 {
240   extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
241 
242   if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
243     {
244       inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for "
245 				"%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
246       flag_objc_sjlj_exceptions = 0;
247     }
248 
249   rthooks->initialize = next_runtime_02_initialize;
250   rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
251   rthooks->tag_getclass = TAG_GETCLASS;
252   rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
253 
254   rthooks->class_decl = next_runtime_abi_02_class_decl;
255   rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
256   rthooks->category_decl = next_runtime_abi_02_category_decl;
257   rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
258   rthooks->string_decl = next_runtime_abi_02_string_decl;
259 
260   rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
261   rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
262   rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
263   rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
264   rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
265   rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
266 
267   rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
268   rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
269   rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
270 
271   rthooks->setup_const_string_class_decl =
272 				next_runtime_abi_02_setup_const_string_class_decl;
273   rthooks->build_const_string_constructor =
274 				next_runtime_abi_02_build_const_string_constructor;
275 
276   rthooks->build_throw_stmt = build_throw_stmt;
277   rthooks->build_exc_ptr = objc_build_exc_ptr;
278   rthooks->begin_catch = begin_catch;
279   rthooks->finish_catch = finish_catch;
280   rthooks->finish_try_stmt = finish_try_stmt;
281 
282   rthooks->generate_metadata = objc_generate_v2_next_metadata;
283   return true;
284 }
285 
286 /* We need a way to convey what kind of meta-data are represented by a given
287    variable, since each type is expected (by the runtime) to be found in a
288    specific named section.  The solution must be usable with LTO.
289 
290    The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
291    satisfactory when LTO is used with ABI-2.  We now tag ObjC meta-data with
292    identification attributes in the front end.  The back-end may choose to act
293    on these as it requires.  */
294 
295 static void
296 next_runtime_abi_02_init_metadata_attributes (void)
297 {
298   if (!objc_meta)
299     objc_meta = get_identifier ("OBJC2META");
300 
301   if (!meta_base)
302     meta_base = get_identifier ("V2_BASE");
303 
304   meta_class = get_identifier ("G2_CLAS");
305   meta_metaclass = get_identifier ("G2_META");
306   meta_category =
307   meta_protocol = meta_base;
308 
309   meta_clac_vars =
310   meta_clai_vars = meta_base;
311 
312   meta_clac_meth =
313   meta_clai_meth =
314   meta_catc_meth =
315   meta_cati_meth =
316   meta_proto_cls_meth =
317   meta_proto_nst_meth = meta_base;
318 
319   meta_clas_prot =
320   meta_catg_prot = meta_base;
321 
322   meta_sel_refs = get_identifier ("V2_SRFS");
323 
324   meta_class_name =
325   meta_meth_name =
326   meta_meth_type =
327   meta_prop_name_attr = get_identifier ("V2_STRG");
328 
329   meta_mref = get_identifier ("V2_MREF");
330   meta_class_ref = get_identifier ("V2_CLRF");
331   meta_superclass_ref = get_identifier ("V2_SURF");
332 
333   meta_label_classlist = get_identifier ("V2_CLAB");
334   meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
335   meta_label_categorylist = get_identifier ("V2_CALA");
336   meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
337 
338   meta_label_protocollist = get_identifier ("V2_PLST");
339   meta_proto_ref = get_identifier ("V2_PRFS");
340 
341   meta_info = get_identifier ("V2_INFO");
342 
343   meta_ehtype = get_identifier ("V2_EHTY");
344 
345   meta_const_str = get_identifier ("V2_CSTR");
346 }
347 
348 static void next_runtime_02_initialize (void)
349 {
350   tree type;
351 #ifdef OBJCPLUS
352   /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
353      default.  */
354   if (!global_options_set.x_flag_objc_call_cxx_cdtors)
355     global_options.x_flag_objc_call_cxx_cdtors = 1;
356 #endif
357 
358   /* Set up attributes to be attached to the meta-data so that they
359      will be placed in the correct sections.  */
360   next_runtime_abi_02_init_metadata_attributes ();
361 
362   /* `struct objc_selector *' */
363   objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
364 					   get_identifier (TAG_SELECTOR)));
365 
366   /* IMP : id (*) (id, _message_ref_t*, ...)
367      SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
368      objc_v2_selector_type.  */
369   build_v2_message_ref_templates ();
370 
371   objc_v2_ivar_list_ptr =
372 		build_pointer_type (xref_tag (RECORD_TYPE,
373 				    get_identifier ("_ivar_list_t")));
374 
375   objc_prop_list_ptr =
376 		build_pointer_type (xref_tag (RECORD_TYPE,
377 				    get_identifier ("_prop_list_t")));
378 
379   build_v2_class_templates ();
380   build_v2_super_template ();
381   build_v2_protocol_template ();
382   build_v2_category_template ();
383 
384   /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
385   type = build_varargs_function_type_list (objc_object_type,
386 						   objc_object_type,
387 						   objc_v2_selector_type,
388 						   NULL_TREE);
389   umsg_fixup_decl =  add_builtin_function ("objc_msgSend_fixup",
390 					   type, 0, NOT_BUILT_IN,
391 					   NULL, NULL_TREE);
392   TREE_NOTHROW (umsg_fixup_decl) = 0;
393 
394   /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
395   umsg_stret_fixup_decl = add_builtin_function ("objc_msgSend_stret_fixup",
396 						type, 0, NOT_BUILT_IN,
397 						NULL, NULL_TREE);
398   TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
399 
400   /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
401   umsg_id_fixup_decl = add_builtin_function ("objc_msgSendId_fixup",
402 					     type, 0, NOT_BUILT_IN,
403 					     NULL, NULL_TREE);
404   TREE_NOTHROW (umsg_id_fixup_decl) = 0;
405 
406   /* id objc_msgSendId_stret_fixup_rtp
407 			(id, struct message_ref_t*, ...); */
408   umsg_id_stret_fixup_decl = add_builtin_function ("objc_msgSendId_stret_fixup",
409 						   type, 0, NOT_BUILT_IN,
410 						   NULL, NULL_TREE);
411   TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
412 
413  /* id objc_msgSendSuper2_fixup_rtp
414 			(struct objc_super *, struct message_ref_t*, ...); */
415   type = build_varargs_function_type_list (objc_object_type,
416 					   objc_super_type,
417 					   objc_v2_super_selector_type,
418 					   NULL_TREE);
419   umsg_id_super2_fixup_decl = add_builtin_function ("objc_msgSendSuper2_fixup",
420 						    type, 0, NOT_BUILT_IN,
421 						    NULL, NULL_TREE);
422   TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
423 
424   /* id objc_msgSendSuper2_stret_fixup_rtp
425 			(struct objc_super *, struct message_ref_t*, ...); */
426   umsg_id_super2_stret_fixup_decl =
427 			add_builtin_function ("objc_msgSendSuper2_stret_fixup",
428 					      type, 0, NOT_BUILT_IN,
429 					      NULL, NULL_TREE);
430   TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
431 
432   /* Present in the library, but unused by the FE.  */
433   /* Protocol *objc_getProtocol (const char *)
434   type = build_function_type_list (objc_protocol_type,
435 				   const_string_type_node,
436 				   NULL_TREE);
437   objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
438 						    type, 0, NOT_BUILT_IN,
439 						    NULL, NULL_TREE);
440   TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
441 
442   UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
443 					    "_objc_empty_cache");
444 
445   UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
446 					     "_objc_empty_vtable");
447 
448   /* id objc_getClass (const char *); */
449   type = build_function_type_list (objc_object_type,
450                                    const_string_type_node,
451                                    NULL_TREE);
452   objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
453 					      type, 0, NOT_BUILT_IN,
454 					      NULL, NULL_TREE);
455 
456   /* id objc_getMetaClass (const char *); */
457   objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
458 						   type, 0, NOT_BUILT_IN,
459 						   NULL, NULL_TREE);
460 
461   /* This is the type of all of the following functions
462      objc_copyStruct().  */
463   type = build_function_type_list (void_type_node,
464 				   ptr_type_node,
465 				   const_ptr_type_node,
466 				   ptrdiff_type_node,
467 				   boolean_type_node,
468 				   boolean_type_node,
469 				   NULL_TREE);
470   /* Declare the following function:
471 	 void
472          objc_copyStruct (void *destination, const void *source,
473 	                  ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
474   objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
475 						   type, 0, NOT_BUILT_IN,
476 						   NULL, NULL_TREE);
477   TREE_NOTHROW (objc_copyStruct_decl) = 0;
478   objc_getPropertyStruct_decl = NULL_TREE;
479   objc_setPropertyStruct_decl = NULL_TREE;
480 
481   gcc_assert (!flag_objc_sjlj_exceptions);
482 
483   /* Although we warn that fobjc-exceptions is required for exceptions
484      code, we carry on and create it anyway.  */
485 
486   /* This can be required, even when exceptions code is not present,
487      when an __attribute__((objc_exception)) is applied to a
488      class.  */
489   build_v2_ehtype_template ();
490 
491   /* void * objc_begin_catch (void *) */
492   type = build_function_type_list (ptr_type_node,
493 				   ptr_type_node, NULL_TREE);
494 
495   objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
496 						 type, 0, NOT_BUILT_IN,
497 						 NULL, NULL_TREE);
498   TREE_NOTHROW (objc2_begin_catch_decl) = 0;
499 
500   /* void objc_end_catch () */
501   type = build_function_type_list (void_type_node, NULL_TREE);
502   objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
503 						type, 0, NOT_BUILT_IN,
504 						NULL, NULL_TREE);
505   TREE_NOTHROW (objc2_end_catch_decl) = 0;
506 
507   /* void objc_exception_rethrow (void) */
508   objc_rethrow_exception_decl =
509 			add_builtin_function ("objc_exception_rethrow",
510 					      type, 0, NOT_BUILT_IN,
511 					      NULL, NULL_TREE);
512   TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
513   using_eh_for_cleanups ();
514   lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
515   lang_hooks.eh_personality = objc_eh_personality;
516 }
517 
518 /* NOTE --- templates --- */
519 
520 /* Set 'objc_v2_message_ref_template' to the data type node for
521    'struct _message_ref_t'.  This needs to be done just once per
522    compilation.  Also Set 'objc_v2_super_message_ref_template' to data
523    type node for 'struct _super_message_ref_t'.  */
524 
525 /* struct _message_ref_t
526    {
527      IMP messenger;
528      SEL name;
529    };
530    where IMP is: id (*) (id, _message_ref_t*, ...)
531 */
532 
533 /* struct _super_message_ref_t
534    {
535      SUPER_IMP messenger;
536      SEL name;
537    };
538    where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
539 */
540 
541 static void
542 build_v2_message_ref_templates (void)
543 {
544   tree ptr_message_ref_t;
545   tree decls, *chain = NULL;
546 
547   /* struct _message_ref_t {...} */
548   objc_v2_message_ref_template =
549 		objc_start_struct (get_identifier ("_message_ref_t"));
550 
551   /* IMP messenger; */
552   ptr_message_ref_t =
553 		build_pointer_type (xref_tag (RECORD_TYPE,
554 				    get_identifier ("_message_ref_t")));
555 
556   objc_v2_imp_type =
557 		build_pointer_type (build_function_type_list
558 					(objc_object_type,
559 					 objc_object_type,
560 					 ptr_message_ref_t,
561 					 NULL_TREE));
562 
563   decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
564 
565   /* SEL name; */
566   add_field_decl (objc_selector_type, "name", &chain);
567 
568   objc_finish_struct (objc_v2_message_ref_template, decls);
569 
570   objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
571 
572   chain = NULL;
573   /* struct _super_message_ref_t {...} */
574   objc_v2_super_message_ref_template =
575 		objc_start_struct (get_identifier ("_super_message_ref_t"));
576 
577   /* SUPER_IMP messenger; */
578   ptr_message_ref_t = build_pointer_type
579 			(xref_tag (RECORD_TYPE,
580 				   get_identifier ("_super_message_ref_t")));
581 
582   objc_v2_super_imp_type =
583 		build_pointer_type (build_function_type_list
584 					(objc_object_type,
585 					 objc_super_type,
586 					 ptr_message_ref_t,
587 					 NULL_TREE));
588 
589   add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
590 
591   /* SEL name; */
592   add_field_decl (objc_selector_type, "name", &chain);
593 
594   objc_finish_struct (objc_v2_super_message_ref_template, decls);
595   objc_v2_super_selector_type =
596 		build_pointer_type (objc_v2_super_message_ref_template);
597 }
598 
599 /* Build following types which represent each class implementation.
600 
601 struct class_ro_t
602 {
603     uint32_t const flags;
604     uint32_t const instanceStart;
605     uint32_t const instanceSize;
606 #ifdef __LP64__
607     uint32_t const reserved;
608 #endif
609     const uint8_t * const ivarLayout;
610     const char *const name;
611     const struct method_list_t * const baseMethods;
612     const struct objc_protocol_list *const baseProtocols;
613     const struct ivar_list_t *const ivars;
614     const uint8_t * const weakIvarLayout;
615     const struct _prop_list_t * const properties;
616 };
617 
618 struct class_t
619 {
620     struct class_t *isa;
621     struct class_t *superclass;
622     void *cache;
623     IMP *vtable;
624 
625     ...When this is active - it will point to a rw version, but
626        when we build the meta-data we point it to the ro...
627     struct class_ro_t *data;
628 };
629 
630 */
631 
632 static void
633 build_v2_class_templates (void)
634 {
635   tree cnst_strg_type;
636   tree decls, *chain = NULL;
637 
638   /* struct class_ro_t {...} */
639   objc_v2_class_ro_template =
640 	objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
641 
642   /* uint32_t const flags; */
643   decls = add_field_decl (integer_type_node, "flags", &chain);
644 
645   /* uint32_t const instanceStart; */
646   add_field_decl (integer_type_node, "instanceStart", &chain);
647 
648   /* uint32_t const instanceSize; */
649   add_field_decl (integer_type_node, "instanceSize", &chain);
650 
651   /* This ABI is currently only used on m64 NeXT.  We always
652      explicitly declare the alignment padding.  */
653   /* uint32_t const reserved; */
654   add_field_decl (integer_type_node, "reserved", &chain);
655 
656   /* const uint8_t * const ivarLayout; */
657   cnst_strg_type = build_pointer_type (unsigned_char_type_node);
658   add_field_decl (cnst_strg_type, "ivarLayout", &chain);
659 
660   /* const char *const name; */
661   add_field_decl (string_type_node, "name", &chain);
662 
663   /* const struct method_list_t * const baseMethods; */
664   add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
665 
666   /* const struct objc_protocol_list *const baseProtocols; */
667   add_field_decl (build_pointer_type
668 			(xref_tag (RECORD_TYPE,
669 				   get_identifier (UTAG_V2_PROTOCOL_LIST))),
670 				  "baseProtocols", &chain);
671 
672   /* const struct ivar_list_t *const ivars; */
673   add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
674 
675   /* const uint8_t * const weakIvarLayout; */
676   add_field_decl (cnst_strg_type, "weakIvarLayout",  &chain);
677 
678   /* struct _prop_list_t * baseProperties; */
679   add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
680 
681   objc_finish_struct (objc_v2_class_ro_template, decls);
682 
683   chain = NULL;
684   /* struct class_t {...} */
685   objc_v2_class_template =
686 	objc_start_struct (get_identifier (UTAG_V2_CLASS));
687 
688   /* struct class_t *isa; */
689   decls = add_field_decl (build_pointer_type (objc_v2_class_template),
690 			  "isa", &chain);
691 
692   /* struct class_t * const superclass; */
693   add_field_decl (build_pointer_type (objc_v2_class_template),
694 				      "superclass", &chain);
695 
696   /* void *cache; */
697   add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
698 
699   /* IMP *vtable; */
700   add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
701 
702   /* struct class_ro_t *ro; */
703   add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
704 
705   objc_finish_struct (objc_v2_class_template, decls);
706 }
707 
708 /* struct _objc_super
709    {
710      struct _objc_object *self;
711      Class cls;
712    }; */
713 void
714 build_v2_super_template (void)
715 {
716   tree decls, *chain = NULL;
717 
718   objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
719 
720   /* struct _objc_object *self; */
721   decls = add_field_decl (objc_object_type, "self", &chain);
722 
723   /* Class cls; */
724   add_field_decl (objc_class_type, "cls", &chain);
725 
726   objc_finish_struct (objc_super_template, decls);
727 }
728 
729 /* struct protocol_t
730   {
731      Class isa;
732      const char * const protocol_name;
733      const struct protocol_list_t * const protocol_list;
734      const struct method_list_t * const instance_methods;
735      const struct method_list_t * const class_methods;
736      const struct method_list_t * optionalInstanceMethods;
737      const struct method_list_t * optionalClassMethod
738      const struct _prop_list_t * const properties;
739      const uint32_t size;
740      const uint32_t flags;
741    }
742 */
743 static void
744 build_v2_protocol_template (void)
745 {
746   tree decls, *chain = NULL;
747 
748   objc_v2_protocol_template =
749 	objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
750 
751   /* Class isa; */
752   decls = add_field_decl (objc_object_type, "isa", &chain);
753 
754   /* char *protocol_name; */
755   add_field_decl (string_type_node, "protocol_name", &chain);
756 
757   /* const struct protocol_list_t * const protocol_list; */
758   add_field_decl (build_pointer_type (objc_v2_protocol_template),
759 		  "protocol_list", &chain);
760 
761   /* const struct method_list_t * const instance_methods; */
762   add_field_decl (objc_method_proto_list_ptr,  "instance_methods", &chain);
763 
764   /* const struct method_list_t * const class_methods; */
765   add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
766 
767   /* const struct method_list_t * optionalInstanceMethods; */
768   add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
769 
770   /* const struct method_list_t * optionalClassMethods; */
771   add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
772 
773   /* struct _prop_list_t * properties; */
774   add_field_decl (objc_prop_list_ptr, "properties", &chain);
775 
776   /* const uint32_t size; */
777   add_field_decl (integer_type_node, "size", &chain);
778 
779   /* const uint32_t flags; */
780   add_field_decl (integer_type_node, "flags", &chain);
781 
782   objc_finish_struct (objc_v2_protocol_template, decls);
783 }
784 
785 /* Build type for a category:
786    struct category_t
787    {
788      const char * const name;
789      struct class_t *const cls;
790      const struct method_list_t * const instance_methods;
791      const struct method_list_t * const class_methods;
792      const struct protocol_list_t * const protocols;
793      const struct _prop_list_t * const properties;
794    }
795 */
796 
797 static void
798 build_v2_category_template (void)
799 {
800   tree decls, *chain = NULL;
801 
802   objc_v2_category_template =
803 	objc_start_struct (get_identifier ("_category_t"));
804 
805   /* char *name; */
806   decls = add_field_decl (string_type_node, "name", &chain);
807 
808   /* struct class_t *const cls; */
809   add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
810 
811   /* struct method_list_t *instance_methods; */
812   add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
813 
814   /* struct method_list_t *class_methods; */
815   add_field_decl (objc_method_list_ptr, "class_methods", &chain);
816 
817   /* struct protocol_list_t *protocol_list; */
818   add_field_decl (build_pointer_type (objc_v2_protocol_template),
819                   "protocol_list", &chain );
820 
821   /* struct _prop_list_t * properties; */
822   add_field_decl (objc_prop_list_ptr, "properties", &chain);
823 
824   objc_finish_struct (objc_v2_category_template, decls);
825 }
826 
827 /* NOTE --- Decls, Identifiers, Names etc. --- */
828 
829 /* This routine is given a name and returns a matching extern variable
830    if one is found.  */
831 
832 static tree
833 hash_name_lookup (hash *hashlist, tree name)
834 {
835   hash target;
836 
837   target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
838 
839   while (target)
840     {
841       if (name == DECL_NAME (target->key))
842 	return target->key;
843 
844       target = target->next;
845     }
846   return 0;
847 }
848 
849 /* This routine is given an extern variable and enters it in its hash
850    table.  Note that hashing is done on its inner IDENTIFIER_NODE
851    node.  */
852 
853 static void
854 hash_name_enter (hash *hashlist, tree id)
855 {
856   hash obj;
857   int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
858 
859   obj = ggc_alloc_hashed_entry ();
860   obj->list = 0;
861   obj->next = hashlist[slot];
862   obj->key = id;
863 
864   hashlist[slot] = obj;		/* append to front */
865 }
866 
867 /* Create a declaration "extern <type> <name>;"
868    The var will need to be finalized (e.g. by calling finish_var_decl()).  */
869 
870 static tree
871 create_extern_decl (tree type, const char *name)
872 {
873   tree id = get_identifier (name);
874   tree var = hash_name_lookup (extern_names, id);
875   if (var)
876       return var;
877   /* New name. */
878   var = start_var_decl (type, name);
879   TREE_STATIC (var) = 0;
880   DECL_EXTERNAL (var) = 1;
881   TREE_PUBLIC (var) = 1;
882   hash_name_enter (extern_names, var);
883   return var;
884 }
885 
886 /* Create a globally visible definition for variable NAME of a given TYPE. The
887    finish_var_decl() routine will need to be called on it afterwards.  */
888 
889 static tree
890 create_global_decl (tree type, const char *name)
891 {
892   tree id = get_identifier (name);
893   tree var = hash_name_lookup (extern_names, id);
894   if (var)
895     {
896       DECL_EXTERNAL (var) = 0;
897       TREE_STATIC (var) = 1;
898     }
899   else
900     {
901       var = start_var_decl (type, name);
902       hash_name_enter (extern_names, var);
903     }
904   TREE_PUBLIC (var) = 1;
905   return var;
906 }
907 
908 /* Create a symbol with __attribute__ ((visibility ("hidden")))
909    attribute (private extern).  */
910 
911 static tree
912 create_hidden_decl (tree type, const char *name)
913 {
914     tree decl = create_global_decl (type, name);
915     DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
916     DECL_VISIBILITY_SPECIFIED (decl) = 1;
917     return decl;
918 }
919 
920 /* Irritatingly, we have a different superclass field name for ABI=2.  */
921 /* PS/TODO: The field name does not matter, it is only used internally
922    by the compiler.  We can rename it to whatever we want. ;-) */
923 
924 static tree
925 next_runtime_abi_02_super_superclassfield_id (void)
926 {
927   /* TODO: Simplify.  Just always return get_identifier ("cls"), or at
928      most look it once at startup then always return it.  */
929   if (!super_superclassfield_id)
930     super_superclassfield_id = get_identifier ("cls");
931   return super_superclassfield_id;
932 }
933 
934 static tree
935 next_runtime_abi_02_class_decl (tree klass)
936 {
937   tree decl;
938   char buf[BUFSIZE];
939   snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
940 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
941   /* ObjC2 classes are extern visible.  */
942   decl = create_global_decl (objc_v2_class_template, buf);
943   OBJCMETA (decl, objc_meta, meta_class);
944   return decl;
945 }
946 
947 static tree
948 next_runtime_abi_02_metaclass_decl (tree klass)
949 {
950   tree decl;
951   char buf[BUFSIZE];
952   snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
953 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
954   /* ObjC2 classes are extern visible.  */
955   decl = create_global_decl (objc_v2_class_template, buf);
956   OBJCMETA (decl, objc_meta, meta_metaclass);
957   return decl;
958 }
959 
960 static tree
961 next_runtime_abi_02_category_decl (tree klass)
962 {
963   tree decl;
964   char buf[BUFSIZE];
965   snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
966 	    IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
967 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
968   decl = start_var_decl (objc_v2_category_template, buf);
969   OBJCMETA (decl, objc_meta, meta_category);
970   return decl;
971 }
972 
973 static tree
974 next_runtime_abi_02_protocol_decl (tree p)
975 {
976   tree decl;
977   char buf[BUFSIZE];
978 
979   /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
980   snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
981 	    IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
982   decl = start_var_decl (objc_v2_protocol_template, buf);
983   OBJCMETA (decl, objc_meta, meta_protocol);
984   return decl;
985 }
986 
987 static tree
988 next_runtime_abi_02_string_decl (tree type, const char *name,  string_section where)
989 {
990   tree var = start_var_decl (type, name);
991   switch (where)
992     {
993       case class_names:
994 	OBJCMETA (var, objc_meta, meta_class_name);
995 	break;
996       case meth_var_names:
997 	OBJCMETA (var, objc_meta, meta_meth_name);
998 	break;
999       case meth_var_types:
1000 	OBJCMETA (var, objc_meta, meta_meth_type);
1001 	break;
1002       case prop_names_attr:
1003 	OBJCMETA (var, objc_meta, meta_prop_name_attr);
1004 	break;
1005       default:
1006 	OBJCMETA (var, objc_meta, meta_base);
1007 	break;
1008     }
1009   return var;
1010 }
1011 
1012 /* NOTE --- entry --- */
1013 
1014 typedef struct GTY(()) ident_data_tuple {
1015   tree ident;
1016   tree data;
1017 } ident_data_tuple ;
1018 
1019 /* This routine creates a file scope static variable of type 'Class'
1020    to hold the address of a class.  */
1021 
1022 static tree
1023 build_v2_class_reference_decl (tree ident)
1024 {
1025   tree decl;
1026   char buf[BUFSIZE];
1027 
1028   snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1029   decl = start_var_decl (objc_class_type, buf);
1030   OBJCMETA (decl, objc_meta, meta_class_ref);
1031   return decl;
1032 }
1033 
1034 /* This routine builds a class refs entry for each class name used.
1035    Initially, a (static-ref, IDENT) tuple is added to the list.  The
1036    ident is replaced with address of the class metadata (of type
1037    'Class') in the output routine.  */
1038 
1039 static GTY (()) vec<ident_data_tuple, va_gc> *classrefs;
1040 
1041 static tree
1042 objc_v2_get_class_reference (tree ident)
1043 {
1044   tree decl;
1045   ident_data_tuple e;
1046   if (classrefs)
1047     {
1048       int count;
1049       ident_data_tuple *ref;
1050       FOR_EACH_VEC_ELT (*classrefs, count, ref)
1051 	{
1052 	  if (ref->ident == ident)
1053 	    {
1054 	      if (!ref->data)
1055 		ref->data = build_v2_class_reference_decl (ident);
1056 	      return ref->data;
1057 	    }
1058 	}
1059     }
1060   else
1061     /* Somewhat arbitrary initial provision.  */
1062     vec_alloc (classrefs, 16);
1063 
1064   /* We come here if we don't find the entry - or if the table was yet
1065      to be created.  */
1066   decl = build_v2_class_reference_decl (ident);
1067   e.ident = ident;
1068   e.data = decl;
1069   vec_safe_push (classrefs, e);
1070   return decl;
1071 }
1072 
1073 static tree
1074 next_runtime_abi_02_get_class_reference (tree ident)
1075 {
1076   if (!flag_zero_link)
1077     return objc_v2_get_class_reference (ident);
1078   else
1079     {
1080       /* We fall back to using objc_getClass ().  */
1081       vec<tree, va_gc> *v;
1082       vec_alloc (v, 1);
1083       tree t;
1084       /* ??? add_class_reference (ident); - is pointless, since the
1085          system lib does not export the equivalent symbols.  Maybe we
1086          need to build a class ref anyway.  */
1087       t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1088 				   IDENTIFIER_POINTER (ident));
1089       v->quick_push (t);
1090       t = build_function_call_vec (input_location, objc_get_class_decl, v, 0);
1091       vec_free (v);
1092       return t;
1093     }
1094 }
1095 
1096 /* Used by build_function_type_for_method.  Append the types for
1097    receiver & _cmd at the start of a method argument list to ARGTYPES.
1098    CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1099    trying to define a method or call one.  SUPERFLAG says this is for a
1100    send to super.  METH may be NULL, in the case that there is no
1101    prototype.  */
1102 
1103 static void
1104 next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1105 					    tree meth, int context,
1106 					    int superflag)
1107 {
1108   tree receiver_type;
1109 
1110   if (superflag)
1111     receiver_type = objc_super_type;
1112   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1113     receiver_type = objc_instance_type;
1114   else
1115     receiver_type = objc_object_type;
1116 
1117   vec_safe_push (*argtypes, receiver_type);
1118   /* Selector type - will eventually change to `int'.  */
1119   vec_safe_push (*argtypes,
1120 		 superflag ? objc_v2_super_selector_type
1121 		           : objc_v2_selector_type);
1122 }
1123 
1124 /* TODO: Merge this with the message refs.  */
1125 static tree
1126 build_selector_reference_decl (tree ident)
1127 {
1128   tree decl;
1129   char *t, buf[BUFSIZE];
1130 
1131   snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1132   t = buf;
1133   while (*t)
1134     {
1135       if (*t==':')
1136         *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
1137       t++;
1138     }
1139   decl = start_var_decl (objc_selector_type, buf);
1140   OBJCMETA (decl, objc_meta, meta_sel_refs);
1141   return decl;
1142 }
1143 
1144 static tree
1145 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1146 					      tree ident,
1147 					      tree proto ATTRIBUTE_UNUSED)
1148 {
1149   tree *chain = &sel_ref_chain;
1150   tree expr;
1151 
1152   while (*chain)
1153     {
1154       if (TREE_VALUE (*chain) == ident)
1155 	return TREE_PURPOSE (*chain);
1156 
1157       chain = &TREE_CHAIN (*chain);
1158     }
1159 
1160   expr = build_selector_reference_decl (ident);
1161   *chain = tree_cons (expr, ident, NULL_TREE);
1162 
1163   return expr;
1164 }
1165 
1166 /* Declare a variable of type 'struct message_ref_t'. */
1167 /* This will be finished in build_v2_message_ref_translation_table ().
1168    We take an idea from LLVM in making the names a bit more connected
1169    and thus the asm more readable.  */
1170 
1171 static tree
1172 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1173 {
1174   tree decl;
1175   char buf[BUFSIZE], *t;
1176   int offset = 12;
1177 
1178   /* Skip past the objc_msgSend it's the same for all...  */
1179   if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1180     offset++;
1181 
1182   snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1183 	    &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1184 	    IDENTIFIER_POINTER (sel_name));
1185   t = buf;
1186   while (*t)
1187     {
1188       if (*t==':')
1189         *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
1190       t++;
1191     }
1192   decl = start_var_decl (objc_v2_message_ref_template, buf);
1193   OBJCMETA (decl, objc_meta, meta_mref);
1194   return decl;
1195 }
1196 
1197 typedef struct GTY(()) msgref_entry {
1198   tree func;
1199   tree selname;
1200   tree refdecl;
1201 } msgref_entry;
1202 
1203 static GTY (()) vec<msgref_entry, va_gc> *msgrefs;
1204 
1205 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1206    later on to initialize the table of 'struct message_ref_t'
1207    elements.  */
1208 
1209 static tree
1210 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1211 {
1212   tree decl;
1213   msgref_entry e;
1214   if (msgrefs)
1215     {
1216       int count;
1217       msgref_entry *ref;
1218       FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1219 	if (ref->func == message_func_decl && ref->selname == sel_name)
1220 	  return ref->refdecl;
1221     }
1222   else
1223     /* Somewhat arbitrary initial provision.  */
1224     vec_alloc (msgrefs, 32);
1225 
1226   /* We come here if we don't find a match or at the start.  */
1227   decl = build_v2_message_reference_decl (sel_name,
1228 					  DECL_NAME (message_func_decl));
1229   e.func = message_func_decl;
1230   e.selname = sel_name;
1231   e.refdecl = decl;
1232   vec_safe_push (msgrefs, e);
1233   return decl;
1234 }
1235 
1236 static tree
1237 build_v2_protocollist_ref_decl (tree protocol)
1238 {
1239   tree decl;
1240   tree protocol_ident = PROTOCOL_NAME (protocol);
1241   char buf[BUFSIZE];
1242 
1243   snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1244 	    IDENTIFIER_POINTER (protocol_ident));
1245   /* TODO: other compiler versions make these hidden & weak.  */
1246   decl = create_global_decl (objc_protocol_type, buf);
1247   /* Let optimizer know that this decl is not removable.  */
1248   DECL_PRESERVE_P (decl) = 1;
1249   OBJCMETA (decl, objc_meta, meta_proto_ref);
1250   return decl;
1251 }
1252 
1253 typedef struct GTY(()) prot_list_entry {
1254   tree id;
1255   tree refdecl;
1256 } prot_list_entry;
1257 static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
1258 
1259 static tree
1260 objc_v2_get_protocol_reference (tree ident)
1261 {
1262   tree decl;
1263   prot_list_entry e;
1264   if (protrefs)
1265     {
1266       int count;
1267       prot_list_entry *ref;
1268       FOR_EACH_VEC_ELT (*protrefs, count, ref)
1269 	{
1270 	  if (ref->id == ident)
1271 	    {
1272 	      if (!ref->refdecl)
1273 		ref->refdecl = build_v2_protocollist_ref_decl (ident);
1274 	      return ref->refdecl;
1275 	    }
1276 	}
1277     }
1278   else
1279     /* Somewhat arbitrary initial provision.  */
1280     vec_alloc (protrefs, 32);
1281 
1282   /* We come here if we don't find the entry - or if the table was yet
1283      to be created.  */
1284   decl = build_v2_protocollist_ref_decl (ident);
1285   e.id = ident;
1286   e.refdecl = decl;
1287   vec_safe_push (protrefs, e);
1288   return decl;
1289 }
1290 
1291 static tree
1292 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1293 					    tree p)
1294 {
1295   if (!PROTOCOL_FORWARD_DECL (p))
1296     PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1297 
1298   return objc_v2_get_protocol_reference (p);
1299 }
1300 
1301 /* This routine returns the ivar declaration, if component is a valid
1302    ivar field; NULL_TREE otherwise. On finding an ivar, it also
1303    returns the class name in CLASS.  */
1304 
1305 static tree
1306 objc_is_ivar (tree expr, tree component, tree *klass)
1307 {
1308   tree field = NULL_TREE;
1309   tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1310 
1311   if (TREE_CODE (basetype) == RECORD_TYPE
1312       && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1313     {
1314       *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1315       if (*klass)
1316 	{
1317 	  do
1318 	    {
1319 	      tree ivar_chain = CLASS_RAW_IVARS (*klass);
1320 	      if (ivar_chain)
1321 		{
1322 		  field = is_ivar (ivar_chain, component);
1323 		  if (field != NULL_TREE)
1324 		    break;
1325 	        }
1326 	      *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1327 	    }
1328 	  while (*klass);
1329 	}
1330     }
1331   return field;
1332 }
1333 
1334 static void
1335 create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1336 {
1337   tree fname = DECL_NAME (field_decl);
1338 
1339   sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1340 	   IDENTIFIER_POINTER (fname));
1341   return;
1342 }
1343 
1344 /* This routine generates new abi's ivar reference tree.  It amounts
1345    to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1346    generate pObj->IVAR.  OFFSET_IVAR is an 'extern' variable holding
1347    the offset for 'IVAR' field.  TYPE is type of IVAR field.  */
1348 
1349 static tree
1350 objc_v2_build_ivar_ref (tree datum, tree component)
1351 {
1352   tree field, ref, class_name, offset, ftype, expr;
1353   char var_offset_name[512];
1354 
1355   field = objc_is_ivar (datum, component, &class_name);
1356   if (!field)
1357     return NULL_TREE;
1358 
1359   /* This routine only handles non-bitfield fields */
1360   /* DECL_INITIAL macro is set to width of bitfield and can be relied
1361      on to check for bitfield ivars.  Note that I cannot rely on
1362      DECL_BIT_FIELD macro because it is only set when the whole struct
1363      is seen (at finish_struct) and not when the ivar chain is
1364      built.  */
1365   if (DECL_INITIAL (field))
1366     return NULL_TREE;
1367 
1368   create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name),  field);
1369 
1370   offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1371 
1372   ftype = TREE_TYPE (field);
1373 
1374   /* (char*)datum */
1375   expr = build_c_cast (input_location,
1376 		       string_type_node, build_fold_addr_expr (datum));
1377 
1378   /* (char*)datum + offset */
1379   expr = fold_build_pointer_plus_loc (input_location, expr, offset);
1380 
1381   /* (ftype*)((char*)datum + offset) */
1382   expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1383 
1384   /* Finally: *(ftype*)((char*)datum + offset) */
1385   ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1386 
1387   /* We must set type of the resulting expression to be the same as
1388      the field type. This is because, build_indirect_ref (...)
1389      rebuilds the type which may result in lost information; as in the
1390      case of protocol-qualified types (id <protocol> ).  */
1391   TREE_TYPE (ref) = ftype;
1392 
1393   if (TREE_READONLY (datum) || TREE_READONLY (field))
1394     TREE_READONLY (ref) = 1;
1395 
1396   if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1397     TREE_THIS_VOLATILE (ref) = 1;
1398 
1399   if (TREE_DEPRECATED (field))
1400     warn_deprecated_use (field, NULL_TREE);
1401 
1402   return ref;
1403 }
1404 
1405 /* IVAR refs are made via an externally referenceable offset and built
1406    on the fly.  That is, unless they refer to (private) fields in  the
1407    class stucture.  */
1408 static tree
1409 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1410 				   tree base, tree id)
1411 {
1412   tree ivar;
1413   if ((ivar = objc_v2_build_ivar_ref (base, id)))
1414     return ivar;
1415   return objc_build_component_ref (base, id);
1416 }
1417 
1418 /* [super ...] references are listed here (and built into a table at
1419    meta -data emit time).  */
1420 static tree
1421 build_v2_superclass_ref_decl (tree ident, bool inst)
1422 {
1423   tree decl;
1424   char buf[BUFSIZE];
1425 
1426   snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1427 	    IDENTIFIER_POINTER (ident));
1428   decl = start_var_decl (objc_class_type, buf);
1429   OBJCMETA (decl, objc_meta, meta_superclass_ref);
1430   return decl;
1431 }
1432 
1433 static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs;
1434 static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs;
1435 
1436 static tree
1437 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1438 					 struct imp_entry *imp, bool inst_meth)
1439 {
1440   tree decl;
1441   ident_data_tuple e;
1442   tree id = CLASS_NAME (imp->imp_context);
1443   vec<ident_data_tuple, va_gc> *list = inst_meth  ? class_super_refs
1444 						: metaclass_super_refs;
1445 
1446   if (list)
1447     {
1448       int count;
1449       ident_data_tuple *ref;
1450       FOR_EACH_VEC_ELT (*list, count, ref)
1451 	{
1452 	  if (ref->ident == id)
1453 	    {
1454 	      if (!ref->data)
1455 		ref->data = build_v2_superclass_ref_decl (id, inst_meth);
1456 	      return ref->data;
1457 	    }
1458 	}
1459     }
1460   else
1461     {
1462       /* Somewhat arbitrary initial provision.  */
1463       if (inst_meth)
1464 	{
1465 	  vec_alloc (class_super_refs, 16);
1466 	  list = class_super_refs;
1467 	}
1468       else
1469 	{
1470 	  vec_alloc (metaclass_super_refs, 16);
1471 	  list = metaclass_super_refs;
1472 	}
1473     }
1474   /* We come here if we don't find the entry - or if the table was yet
1475      to be created.  */
1476   decl = build_v2_superclass_ref_decl (id, inst_meth);
1477   e.ident = id;
1478   e.data = decl;
1479   vec_safe_push (list, e);
1480   return decl;
1481 }
1482 
1483 static tree
1484 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1485 					   struct imp_entry *imp, bool inst_meth)
1486 {
1487   /* ??? is this OK when zero-link = true?  */
1488   tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1489   tree super_class;
1490 
1491   if (!flag_zero_link)
1492     {
1493       super_class = objc_get_class_reference (CLASS_NAME (imp->imp_template));
1494 
1495       if (!inst_meth)
1496 
1497 	/* If we are in a class method, we must retrieve the
1498 	   _metaclass_ for the current class, pointed at by the
1499 	   class's "isa" pointer.  The following assumes that "isa" is
1500 	   the first ivar in a class (which it must be).  */
1501 	   super_class =
1502 		build_indirect_ref (input_location,
1503 				    build_c_cast (input_location,
1504 					build_pointer_type (objc_class_type),
1505 					super_class),
1506 				    RO_UNARY_STAR);
1507       return super_class;
1508     }
1509   /* ??? Do we need to add the class ref anway for zero-link?  */
1510   /* else do it the slow way.  */
1511   super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
1512   super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1513 					IDENTIFIER_POINTER (super_name));
1514   /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1515   return build_function_call (input_location,
1516 			      super_class,
1517 			      build_tree_list (NULL_TREE, super_name));
1518 }
1519 
1520 static tree
1521 next_runtime_abi_02_receiver_is_class_object (tree receiver)
1522 {
1523   if (TREE_CODE (receiver) == VAR_DECL
1524       && IS_CLASS (TREE_TYPE (receiver))
1525       && vec_safe_length (classrefs))
1526     {
1527       int count;
1528       ident_data_tuple *ref;
1529       /* The receiver is a variable created by build_class_reference_decl.  */
1530       FOR_EACH_VEC_ELT (*classrefs, count, ref)
1531 	if (ref->data == receiver)
1532 	  return ref->ident;
1533     }
1534   return NULL_TREE;
1535 }
1536 
1537 /* Assign all arguments in VALUES which have side-effect to a temporary
1538    and replaced that argument in VALUES list with the temporary. The
1539    arguments will be passed to a function with FNTYPE.  */
1540 
1541 static tree
1542 objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1543 {
1544   tree valtail;
1545   function_args_iterator iter;
1546 
1547   /* Skip over receiver and the &_msf_ref types.  */
1548   function_args_iter_init (&iter, fntype);
1549   function_args_iter_next (&iter);
1550   function_args_iter_next (&iter);
1551 
1552   for (valtail = values; valtail;
1553        valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
1554     {
1555       tree value = TREE_VALUE (valtail);
1556       tree type = function_args_iter_cond (&iter);
1557       if (type == NULL_TREE)
1558 	break;
1559       if (!TREE_SIDE_EFFECTS (value))
1560 	continue;
1561       /* To prevent re-evaluation.  */
1562       value = save_expr (value);
1563       add_stmt (value);
1564       TREE_VALUE (valtail) = value;
1565     }
1566   return values;
1567 }
1568 
1569 /* Build the new abi's messaging library call. It looks like:
1570    (*_msg.messenger) (receiver, &_msg, ...) */
1571 
1572 static tree
1573 build_v2_build_objc_method_call (int super_flag, tree method_prototype,
1574 				 tree lookup_object, tree selector,
1575 				 tree method_params,
1576 				 bool check_for_nil)
1577 {
1578   tree ret_val;
1579   tree sender, rcv_p, t;
1580   tree ret_type
1581     = (method_prototype
1582        ? TREE_VALUE (TREE_TYPE (method_prototype))
1583        : objc_object_type);
1584   tree ftype = build_function_type_for_method (ret_type, method_prototype,
1585 					       METHOD_REF, super_flag);
1586   tree sender_cast;
1587 
1588   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1589     ftype = build_type_attribute_variant (
1590 	      ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1591 
1592   sender_cast = build_pointer_type (ftype);
1593 
1594   if (check_for_nil)
1595     method_params = objc_copy_to_temp_side_effect_params (ftype,
1596 							  method_params);
1597 
1598   /* Get &message_ref_t.messenger.  */
1599   sender = build_c_cast (input_location,
1600 			 build_pointer_type (super_flag
1601 					     ? objc_v2_super_imp_type
1602 					     : objc_v2_imp_type),
1603 			 selector);
1604 
1605   sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1606 
1607   rcv_p = (super_flag ? objc_super_type : objc_object_type);
1608 
1609   lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1610 
1611   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
1612   lookup_object = save_expr (lookup_object);
1613 
1614   method_params = tree_cons (NULL_TREE, lookup_object,
1615                              tree_cons (NULL_TREE, selector,
1616                                         method_params));
1617   t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
1618   ret_val =  build_function_call (input_location, t, method_params);
1619   if (check_for_nil)
1620     {
1621       /* receiver != nil ? ret_val : 0 */
1622       tree ftree;
1623       tree ifexp;
1624 
1625       if (TREE_CODE (ret_type) == RECORD_TYPE
1626 	  || TREE_CODE (ret_type) == UNION_TYPE)
1627 	{
1628 	  vec<constructor_elt, va_gc> *rtt = NULL;
1629 	  /* ??? CHECKME. hmmm..... think we need something more
1630 	     here.  */
1631 	  CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE);
1632 	  ftree = objc_build_constructor (ret_type, rtt);
1633 	}
1634       else
1635 	ftree = fold_convert (ret_type, integer_zero_node);
1636 
1637       ifexp = build_binary_op (input_location, NE_EXPR,
1638 			       lookup_object,
1639 			       fold_convert (rcv_p, integer_zero_node), 1);
1640 
1641 #ifdef OBJCPLUS
1642       ret_val = build_conditional_expr (ifexp, ret_val, ftree, tf_warning_or_error);
1643 #else
1644      /* ??? CHECKME.   */
1645       ret_val = build_conditional_expr (input_location,
1646 					ifexp, 1,
1647 					ret_val, NULL_TREE,
1648 					ftree, NULL_TREE);
1649 #endif
1650     }
1651   return ret_val;
1652 }
1653 
1654 static tree
1655 next_runtime_abi_02_build_objc_method_call (location_t loc,
1656 					    tree method_prototype,
1657 					    tree receiver,
1658 					    tree rtype,
1659 					    tree sel_name,
1660 					    tree method_params,
1661 					    int super)
1662 {
1663   tree ret_type, selector;
1664   tree message_func_decl;
1665   bool check_for_nil = flag_objc_nilcheck;
1666 
1667   ret_type = method_prototype
1668 	     ? TREE_VALUE (TREE_TYPE (method_prototype))
1669 	     : objc_object_type;
1670 
1671   /* Do we need to check for nil receivers ? */
1672   /* For now, message sent to classes need no nil check.  In the
1673       future, class declaration marked as weak_import must be nil
1674       checked.  */
1675   if (super
1676       || (TREE_CODE (receiver) == VAR_DECL
1677 	  && TREE_TYPE (receiver) == objc_class_type))
1678     check_for_nil = false;
1679 
1680   if (!targetm.calls.struct_value_rtx (0, 0)
1681           && (TREE_CODE (ret_type) == RECORD_TYPE
1682 	      || TREE_CODE (ret_type) == UNION_TYPE)
1683           && targetm.calls.return_in_memory (ret_type, 0))
1684     {
1685       if (super)
1686 	message_func_decl = umsg_id_super2_stret_fixup_decl;
1687       else
1688 	message_func_decl = objc_is_id (rtype)
1689 			    ? umsg_id_stret_fixup_decl
1690 			    : umsg_stret_fixup_decl;
1691     }
1692   else
1693     {
1694       if (super)
1695 	message_func_decl = umsg_id_super2_fixup_decl;
1696       else
1697 	message_func_decl = objc_is_id (rtype)
1698 			    ? umsg_id_fixup_decl
1699 			    : umsg_fixup_decl;
1700     }
1701 
1702   selector = build_v2_selector_messenger_reference (sel_name,
1703 						      message_func_decl);
1704 
1705   /* selector = &_msg; */
1706   selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1707 
1708   selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1709 				       : objc_v2_selector_type),
1710 			   selector);
1711 
1712   /* (*_msg.messenger) (receiver, &_msg, ...); */
1713   return build_v2_build_objc_method_call (super, method_prototype,
1714 					  receiver, selector,
1715 					  method_params, check_for_nil);
1716 }
1717 
1718 /* NOTE --- Constant String Class Stuff --- */
1719 
1720 static bool
1721 next_runtime_abi_02_setup_const_string_class_decl (void)
1722 {
1723   if (!constant_string_global_id)
1724     {
1725       /* Hopefully, this should not represent a serious limitation.  */
1726       char buf[BUFSIZE];
1727       snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1728       constant_string_global_id = get_identifier (buf);
1729     }
1730 
1731   string_class_decl = lookup_name (constant_string_global_id);
1732 
1733   /* In OBJC2 abi, constant string class reference refers to class
1734      name for NSConstantString class.  This declaration may not be
1735      available yet (in fact it is not in most cases).  So, declare an
1736      extern OBJC_CLASS_$_NSConstantString in its place. */
1737   if (!string_class_decl)
1738     string_class_decl =
1739 	create_extern_decl (objc_v2_class_template,
1740 			    IDENTIFIER_POINTER (constant_string_global_id));
1741 
1742   return (string_class_decl != NULL_TREE);
1743 }
1744 
1745 static tree
1746 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1747 						   int length)
1748 {
1749   tree constructor, fields, var;
1750   vec<constructor_elt, va_gc> *v = NULL;
1751 
1752   /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1753   fields = TYPE_FIELDS (internal_const_str_type);
1754   CONSTRUCTOR_APPEND_ELT (v, fields,
1755 			  build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1756 
1757   fields = DECL_CHAIN (fields);
1758   CONSTRUCTOR_APPEND_ELT (v, fields,
1759 			  build_unary_op (loc, ADDR_EXPR, string, 1));
1760 
1761   /* ??? check if this should be long.  */
1762   fields = DECL_CHAIN (fields);
1763   CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1764   constructor = objc_build_constructor (internal_const_str_type, v);
1765 
1766   var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1767   DECL_INITIAL (var) = constructor;
1768   TREE_STATIC (var) = 1;
1769   DECL_CONTEXT (var) = NULL;
1770   OBJCMETA (var, objc_meta, meta_const_str);
1771   return var;
1772 }
1773 
1774 /* NOTE --- NeXT V2 Metadata templates --- */
1775 
1776 /* This routine builds the following type:
1777    struct _prop_t
1778    {
1779      const char * const name;			// property name
1780      const char * const attributes;		// comma-delimited, encoded,
1781 						// property attributes
1782    };
1783 */
1784 
1785 static tree
1786 build_v2_property_template (void)
1787 {
1788   tree prop_record;
1789   tree decls, *chain = NULL;
1790 
1791   prop_record = objc_start_struct (get_identifier ("_prop_t"));
1792   /* const char * name */
1793   decls = add_field_decl (string_type_node, "name", &chain);
1794 
1795   /* const char * attribute */
1796   add_field_decl (string_type_node, "attribute", &chain);
1797 
1798   objc_finish_struct (prop_record, decls);
1799   return prop_record;
1800 }
1801 
1802 /* struct ivar_t
1803    {
1804      unsigned long int *offset;
1805      char *name;
1806      char *type;
1807      uint32_t alignment;
1808      uint32_t size;
1809    };
1810 */
1811 
1812 static tree
1813 build_v2_ivar_t_template (void)
1814 {
1815   tree objc_ivar_id, objc_ivar_record;
1816   tree decls, *chain = NULL;
1817 
1818   objc_ivar_id = get_identifier ("_ivar_t");
1819   objc_ivar_record = objc_start_struct (objc_ivar_id);
1820 
1821   /* unsigned long int *offset; */
1822   decls = add_field_decl (build_pointer_type
1823 			   (TREE_TYPE (size_zero_node)), "offset", &chain);
1824 
1825   /* char *name; */
1826   add_field_decl (string_type_node, "name", &chain);
1827 
1828   /* char *type; */
1829   add_field_decl (string_type_node, "type", &chain);
1830 
1831   /* uint32_t alignment; */
1832   add_field_decl (integer_type_node, "alignment", &chain);
1833 
1834   /* uint32_t size; */
1835   add_field_decl (integer_type_node, "size", &chain);
1836 
1837   objc_finish_struct (objc_ivar_record, decls);
1838   return objc_ivar_record;
1839 }
1840 
1841 static void
1842 build_metadata_templates (void)
1843 {
1844 
1845   if (!objc_method_template)
1846     objc_method_template = build_method_template ();
1847 
1848   if (!objc_v2_property_template)
1849     objc_v2_property_template = build_v2_property_template ();
1850 
1851   if (!objc_v2_ivar_template)
1852     objc_v2_ivar_template = build_v2_ivar_t_template ();
1853 
1854 }
1855 
1856 /* NOTE --- Output NeXT V2 Metadata --- */
1857 
1858 /* Routine builds name of Interface's main meta-data of type class_t. */
1859 
1860 static char *
1861 objc_build_internal_classname (tree ident, bool metaclass)
1862 {
1863   static char string[512];
1864   snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
1865 					    : "OBJC_CLASS_$",
1866 	    IDENTIFIER_POINTER (ident));
1867   return string;
1868 }
1869 
1870 /* Build the name for object of type struct class_ro_t */
1871 
1872 static const char *
1873 newabi_append_ro (const char *name)
1874 {
1875   const char *dollar;
1876   char *p;
1877   static char string[BUFSIZE];
1878   dollar = strchr (name, '$');
1879   gcc_assert (dollar);
1880   p = string;
1881   *p = '_'; p++;
1882   strncpy (p, name, (int)(dollar - name));
1883   p += (int)(dollar - name);
1884   sprintf (p, "RO_%s", dollar);
1885   return string;
1886 }
1887 
1888 /* Build the struct message_ref_t msg =
1889 	       {objc_msgSend_fixup_xxx, @selector(func)}
1890    table.  */
1891 
1892 static
1893 void build_v2_message_ref_translation_table (void)
1894 {
1895   int count;
1896   msgref_entry *ref;
1897 
1898   if (!vec_safe_length (msgrefs))
1899     return;
1900 
1901   FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1902     {
1903       vec<constructor_elt, va_gc> *initializer;
1904       tree expr, constructor;
1905       tree struct_type = TREE_TYPE (ref->refdecl);
1906       location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
1907 
1908       initializer = NULL;
1909       /* First 'IMP messenger' field...  */
1910       expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
1911       expr = convert (objc_v2_imp_type, expr);
1912       CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1913 
1914       /* ... then 'SEL name' field.  */
1915       expr = build_selector (ref->selname);
1916       CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
1917       constructor = objc_build_constructor (struct_type, initializer);
1918       finish_var_decl (ref->refdecl, constructor);
1919     }
1920 }
1921 
1922 /* Build decl = initializer; for each externally visible class
1923    reference.  */
1924 
1925 static void
1926 build_v2_classrefs_table (void)
1927 {
1928   int count;
1929   ident_data_tuple *ref;
1930 
1931   if (!vec_safe_length (classrefs))
1932     return;
1933 
1934   FOR_EACH_VEC_ELT (*classrefs, count, ref)
1935     {
1936       tree expr = ref->ident;
1937       tree decl = ref->data;
1938       /* Interface with no implementation and yet one of its messages
1939 	 has been used. Need to generate a full address-of tree for it
1940 	 here.  */
1941       if (TREE_CODE (expr) == IDENTIFIER_NODE)
1942         {
1943           const char *name = objc_build_internal_classname (expr, false);
1944           expr = create_extern_decl (objc_v2_class_template, name);
1945 	  expr = convert (objc_class_type, build_fold_addr_expr (expr));
1946 	}
1947       /* The runtime wants this, even if it appears unused, so we must force the
1948 	 output.
1949       DECL_PRESERVE_P (decl) = 1; */
1950       finish_var_decl (decl, expr);
1951     }
1952 }
1953 
1954 /* Build decl = initializer; for each externally visible super class
1955    reference.  */
1956 
1957 static void
1958 build_v2_super_classrefs_table (bool metaclass)
1959 {
1960   int count;
1961   ident_data_tuple *ref;
1962   vec<ident_data_tuple, va_gc> *list = metaclass  ? metaclass_super_refs
1963 						: class_super_refs;
1964 
1965   if (!vec_safe_length (list))
1966     return;
1967 
1968   FOR_EACH_VEC_ELT (*list, count, ref)
1969     {
1970       tree expr = ref->ident;
1971       tree decl = ref->data;
1972       /* Interface with no implementation and yet one of its messages
1973 	 has been used. Need to generate a full address-of tree for it
1974 	 here.  */
1975       if (TREE_CODE (expr) == IDENTIFIER_NODE)
1976 	{
1977 	  const char * name = objc_build_internal_classname (expr, metaclass);
1978           expr = create_extern_decl (objc_v2_class_template, name);
1979 	  expr = convert (objc_class_type, build_fold_addr_expr (expr));
1980 	}
1981       finish_var_decl (decl, expr);
1982     }
1983 }
1984 
1985 /* Add the global class meta-data declaration to the list which later
1986    on ends up in the __class_list section.  */
1987 
1988 static GTY(()) vec<tree, va_gc> *class_list;
1989 
1990 static void
1991 objc_v2_add_to_class_list (tree global_class_decl)
1992 {
1993   vec_safe_push (class_list, global_class_decl);
1994 }
1995 
1996 static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
1997 
1998 /* Add the global class meta-data declaration to the list which later
1999    on ends up in the __nonlazy_class section.  */
2000 
2001 static void
2002 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2003 {
2004   vec_safe_push (nonlazy_class_list, global_class_decl);
2005 }
2006 
2007 static GTY(()) vec<tree, va_gc> *category_list;
2008 
2009 /* Add the category meta-data declaration to the list which later on
2010    ends up in the __nonlazy_category section.  */
2011 
2012 static void
2013 objc_v2_add_to_category_list (tree decl)
2014 {
2015   vec_safe_push (category_list, decl);
2016 }
2017 
2018 static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
2019 
2020 /* Add the category meta-data declaration to the list which later on
2021    ends up in the __category_list section.  */
2022 
2023 static void
2024 objc_v2_add_to_nonlazy_category_list (tree decl)
2025 {
2026   vec_safe_push (nonlazy_category_list, decl);
2027 }
2028 
2029 static bool
2030 has_load_impl (tree clsmeth)
2031 {
2032   while (clsmeth)
2033     {
2034       tree id = METHOD_SEL_NAME (clsmeth);
2035       if (IDENTIFIER_LENGTH (id) == 4
2036 	  && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
2037         return true;
2038       clsmeth = DECL_CHAIN (clsmeth);
2039     }
2040 
2041   return false;
2042 }
2043 
2044 /* Build a __{class,category}_list section table containing address of
2045    all @implemented {class,category} meta-data.  */
2046 
2047 static void
2048 build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
2049 {
2050   int count=0;
2051   tree type, decl, expr;
2052   vec<constructor_elt, va_gc> *initlist = NULL;
2053 
2054   if (!vec_safe_length (src))
2055     return;
2056 
2057   FOR_EACH_VEC_ELT (*src, count, decl)
2058     {
2059 #ifndef OBJCPLUS
2060       tree purpose = build_int_cst (NULL_TREE, count);
2061 #else
2062       tree purpose = NULL_TREE;
2063 #endif
2064       expr = convert (objc_class_type, build_fold_addr_expr (decl));
2065       CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2066     }
2067   gcc_assert (count > 0);
2068   type = build_array_type (objc_class_type,
2069 			   build_index_type (build_int_cst (NULL_TREE, count - 1)));
2070   decl = start_var_decl (type, nam);
2071   /* The runtime wants this, even if it appears unused, so we must
2072      force the output.  */
2073   DECL_PRESERVE_P (decl) = 1;
2074   expr = objc_build_constructor (type, initlist);
2075   OBJCMETA (decl, objc_meta, attr);
2076   finish_var_decl (decl, expr);
2077 }
2078 
2079 /* Build decl = initializer; for each protocol referenced in
2080    @protocol(MyProt) expression.  Refs as built in the entry section
2081    above.  */
2082 
2083 static void
2084 build_v2_protocol_list_translation_table (void)
2085 {
2086   int count;
2087   prot_list_entry *ref;
2088 
2089   if (!protrefs)
2090     return;
2091 
2092   FOR_EACH_VEC_ELT (*protrefs, count, ref)
2093     {
2094       char buf[BUFSIZE];
2095       tree expr;
2096       gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2097       snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2098 		IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2099       expr = start_var_decl (objc_v2_protocol_template, buf);
2100       expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2101       finish_var_decl (ref->refdecl, expr);
2102     }
2103   /* TODO: Maybe we could explicitly delete the vec. now?  */
2104 }
2105 
2106 static GTY (()) vec<prot_list_entry, va_gc> *protlist;
2107 
2108 /* Add the local protocol meta-data declaration to the list which
2109    later on ends up in the __protocol_list section.  */
2110 
2111 static void
2112 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2113 {
2114   prot_list_entry e;
2115   if (!protlist)
2116     /* Arbitrary init count.  */
2117     vec_alloc (protlist, 32);
2118   e.id = protocol_interface_decl;
2119   e.refdecl = protocol_decl;
2120   vec_safe_push (protlist, e);
2121 }
2122 
2123 /* Build the __protocol_list section table containing address of all
2124    generate protocol_t meta-data.  */
2125 
2126 static void
2127 build_v2_protocol_list_address_table (void)
2128 {
2129   int count;
2130   prot_list_entry *ref;
2131   if (!vec_safe_length (protlist))
2132     return;
2133 
2134   FOR_EACH_VEC_ELT (*protlist, count, ref)
2135     {
2136       tree decl, expr;
2137       char buf[BUFSIZE];
2138       gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2139       snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2140 		IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2141       decl = create_global_decl (objc_protocol_type, buf);
2142       expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2143       OBJCMETA (decl, objc_meta, meta_label_protocollist);
2144       finish_var_decl (decl, expr);
2145     }
2146 
2147     /* TODO: delete the vec.  */
2148     /* TODO: upgrade to the clang/llvm hidden version.  */
2149 }
2150 
2151 /* This routine declares a variable to hold meta data for 'struct
2152    protocol_list_t'.  */
2153 
2154 static tree
2155 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2156 {
2157   tree refs_decl, lproto, e, plist, ptempl_p_t;
2158   int size = 0;
2159   vec<constructor_elt, va_gc> *initlist = NULL;
2160   char buf[BUFSIZE];
2161 
2162   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2163       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2164     plist = CLASS_PROTOCOL_LIST (i_or_p);
2165   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2166     plist = PROTOCOL_LIST (i_or_p);
2167   else
2168     gcc_unreachable ();
2169 
2170   /* Compute size.  */
2171   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2172     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2173 	&& PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2174       size++;
2175 
2176   /* Build initializer.  */
2177 
2178   ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2179   e = build_int_cst (ptempl_p_t, size);
2180   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2181 
2182   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2183     {
2184       tree pval = TREE_VALUE (lproto);
2185 
2186       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2187 	  && PROTOCOL_FORWARD_DECL (pval))
2188 	{
2189 	  tree fwref = PROTOCOL_FORWARD_DECL (pval);
2190 	  location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2191 	  e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2192 	  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2193 	}
2194     }
2195 
2196   /* static struct protocol_list_t *list[size]; */
2197 
2198   switch (TREE_CODE (i_or_p))
2199     {
2200     case PROTOCOL_INTERFACE_TYPE:
2201       snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2202 		IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2203       break;
2204     case CLASS_INTERFACE_TYPE:
2205       snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2206 		IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2207       break;
2208     case CATEGORY_INTERFACE_TYPE:
2209       snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2210 		IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2211 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2212       break;
2213       default:
2214 	gcc_unreachable ();
2215     }
2216 
2217   refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2218 			      buf);
2219   /* ObjC2 puts all these in the base section.  */
2220   OBJCMETA (refs_decl, objc_meta, meta_base);
2221   DECL_PRESERVE_P (refs_decl) = 1;
2222   finish_var_decl (refs_decl,
2223 		   objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2224   return refs_decl;
2225 }
2226 
2227 /* This routine builds one 'struct method_t' initializer list. Note
2228    that the old ABI is supposed to build 'struct objc_method' which
2229    has 3 fields, but it does not build the initialization expression
2230    for 'method_imp' which for protocols is NULL any way.  To be
2231    consistant with declaration of 'struct method_t', in the new ABI we
2232    set the method_t.imp to NULL.  */
2233 
2234 static tree
2235 build_v2_descriptor_table_initializer (tree type, tree entries)
2236 {
2237   vec<constructor_elt, va_gc> *initlist = NULL;
2238   do
2239     {
2240       vec<constructor_elt, va_gc> *eltlist = NULL;
2241       CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2242 			      build_selector (METHOD_SEL_NAME (entries)));
2243       CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2244 			      add_objc_string (METHOD_ENCODING (entries),
2245 						meth_var_types));
2246       CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2247 
2248       CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2249 			      objc_build_constructor (type, eltlist));
2250       entries = TREE_CHAIN (entries);
2251     }
2252   while (entries);
2253 
2254   return objc_build_constructor (build_array_type (type, 0), initlist);
2255 }
2256 
2257 /* struct method_list_t
2258   {
2259      uint32_t entsize;
2260      uint32_t method_count;
2261      struct objc_method method_list[method_count];
2262    }; */
2263 
2264 static tree
2265 build_v2_method_list_template (tree list_type, int size)
2266 {
2267   tree method_list_t_record;
2268   tree array_type, decls, *chain = NULL;
2269 
2270   method_list_t_record = objc_start_struct (NULL_TREE);
2271 
2272   /* uint32_t const entsize; */
2273   decls = add_field_decl (integer_type_node, "entsize", &chain);
2274 
2275   /* int method_count; */
2276   add_field_decl (integer_type_node, "method_count", &chain);
2277 
2278   /* struct objc_method method_list[]; */
2279   array_type = build_sized_array_type (list_type, size);
2280   add_field_decl (array_type, "method_list", &chain);
2281 
2282   objc_finish_struct (method_list_t_record, decls);
2283   return method_list_t_record;
2284 }
2285 
2286 /* Note, as above that we are building to the objc_method_template
2287    which has the *imp field.  ABI0/1 build with
2288    objc_method_prototype_template which is missing this field.  */
2289 static tree
2290 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2291 				   const char *prefix, tree attr)
2292 {
2293   tree method_list_template, initlist, decl, methods;
2294   int size, entsize;
2295   vec<constructor_elt, va_gc> *v = NULL;
2296   char buf[BUFSIZE];
2297 
2298   if (!chain || !prefix)
2299     return NULL_TREE;
2300 
2301   methods = chain;
2302   size = 0;
2303   while (methods)
2304     {
2305       if (! METHOD_ENCODING (methods))
2306 	METHOD_ENCODING (methods) = encode_method_prototype (methods);
2307       methods = TREE_CHAIN (methods);
2308       size++;
2309     }
2310 
2311   gcc_assert (size);
2312   method_list_template = build_v2_method_list_template (objc_method_template,
2313 							size);
2314   snprintf (buf, BUFSIZE, "%s_%s", prefix,
2315 	    IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2316 
2317   decl = start_var_decl (method_list_template, buf);
2318 
2319   entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2320   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2321   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2322   initlist =
2323 	build_v2_descriptor_table_initializer (objc_method_template,
2324 					    chain);
2325   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2326   /* Get into the right section.  */
2327   OBJCMETA (decl, objc_meta, attr);
2328   finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2329   return decl;
2330 }
2331 
2332 /* This routine builds the initializer list to initialize the 'struct
2333    _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data.  */
2334 
2335 static tree
2336 build_v2_property_table_initializer (tree type, tree context)
2337 {
2338   tree x;
2339   vec<constructor_elt, va_gc> *inits = NULL;
2340   if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2341     x = CLASS_PROPERTY_DECL (context);
2342   else
2343     x = IMPL_PROPERTY_DECL (context);
2344 
2345   for (; x; x = TREE_CHAIN (x))
2346     {
2347       vec<constructor_elt, va_gc> *elemlist = NULL;
2348       /* NOTE! sections where property name/attribute go MUST change
2349 	 later.  */
2350       tree attribute, name_ident = PROPERTY_NAME (x);
2351 
2352       CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2353 			      add_objc_string (name_ident, prop_names_attr));
2354 
2355       attribute = objc_v2_encode_prop_attr (x);
2356       CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2357 			      add_objc_string (attribute, prop_names_attr));
2358 
2359       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2360 			      objc_build_constructor (type, elemlist));
2361     }
2362 
2363   return objc_build_constructor (build_array_type (type, 0),inits);
2364 }
2365 
2366 /* This routine builds the following type:
2367    struct _prop_list_t
2368    {
2369      uint32_t entsize;			// sizeof (struct _prop_t)
2370      uint32_t prop_count;
2371      struct _prop_t prop_list [prop_count];
2372    }
2373 */
2374 
2375 static tree
2376 build_v2_property_list_template (tree list_type, int size)
2377 {
2378   tree property_list_t_record;
2379   tree array_type, decls, *chain = NULL;
2380 
2381   /* anonymous.  */
2382   property_list_t_record = objc_start_struct (NULL_TREE);
2383 
2384   /* uint32_t const entsize; */
2385   decls = add_field_decl (integer_type_node, "entsize", &chain);
2386 
2387   /* int prop_count; */
2388   add_field_decl (integer_type_node, "prop_count", &chain);
2389 
2390   /* struct _prop_t prop_list[]; */
2391   array_type = build_sized_array_type (list_type, size);
2392   add_field_decl (array_type, "prop_list", &chain);
2393 
2394   objc_finish_struct (property_list_t_record, decls);
2395   return property_list_t_record;
2396 }
2397 
2398 /* Top-level routine to generate property tables for each
2399    implementation.  */
2400 
2401 static tree
2402 generate_v2_property_table (tree context, tree klass_ctxt)
2403 {
2404   tree x, decl, initlist, property_list_template;
2405   bool is_proto = false;
2406   vec<constructor_elt, va_gc> *inits = NULL;
2407   int init_val, size = 0;
2408   char buf[BUFSIZE];
2409 
2410   if (context)
2411     {
2412       gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2413       x = CLASS_PROPERTY_DECL (context);
2414       is_proto = true;
2415     }
2416   else
2417     x = IMPL_PROPERTY_DECL (klass_ctxt);
2418 
2419   for (; x; x = TREE_CHAIN (x))
2420     size++;
2421 
2422   if (size == 0)
2423     return NULL_TREE;
2424 
2425   property_list_template =
2426 	build_v2_property_list_template (objc_v2_property_template,
2427 					 size);
2428 
2429   initlist = build_v2_property_table_initializer (objc_v2_property_template,
2430 						  is_proto ? context
2431 							   : klass_ctxt);
2432 
2433   init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2434   if (is_proto)
2435     snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2436 	      IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2437   else
2438     snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2439 	      IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2440 
2441   decl = start_var_decl (property_list_template, buf);
2442 
2443   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2444 			  build_int_cst (NULL_TREE, init_val));
2445   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2446 			  build_int_cst (NULL_TREE, size));
2447   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2448 
2449   OBJCMETA (decl, objc_meta, meta_base);
2450   finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2451   return decl;
2452 }
2453 
2454 static tree
2455 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2456 			      tree inst_methods, tree class_methods,
2457 			      tree opt_ins_meth, tree opt_cls_meth,
2458 			      tree property_list)
2459 {
2460   tree expr, ttyp;
2461   location_t loc;
2462   vec<constructor_elt, va_gc> *inits = NULL;
2463 
2464   /* TODO: find a better representation of location from the inputs.  */
2465   loc = UNKNOWN_LOCATION;
2466 
2467   /*  This is NULL for the new ABI.  */
2468   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2469 			      convert (objc_object_type, null_pointer_node));
2470 
2471   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2472   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2473 
2474   ttyp = objc_method_proto_list_ptr;
2475   if (inst_methods)
2476     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2477   else
2478     expr = convert (ttyp, null_pointer_node);
2479   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2480 
2481   if (class_methods)
2482     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2483   else
2484     expr = convert (ttyp, null_pointer_node);
2485   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2486 
2487   if (opt_ins_meth)
2488     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2489   else
2490     expr = convert (ttyp, null_pointer_node);
2491   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2492 
2493   if (opt_cls_meth)
2494     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2495   else
2496     expr = convert (ttyp, null_pointer_node);
2497   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2498 
2499   ttyp = objc_prop_list_ptr;
2500   if (property_list)
2501     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2502   else
2503     expr = convert (ttyp, null_pointer_node);
2504   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2505 
2506   /* const uint32_t size;  = sizeof(struct protocol_t) */
2507   expr = build_int_cst (integer_type_node,
2508 	      TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2509   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2510   /* const uint32_t flags; = 0 */
2511   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2512 
2513   return objc_build_constructor (type, inits);
2514 }
2515 
2516 /* Main routine to build all meta data for all protocols used in a
2517    translation unit.  */
2518 
2519 static void
2520 generate_v2_protocols (void)
2521 {
2522   tree p ;
2523   bool some = false;
2524 
2525   if (!protocol_chain)
2526     return ;
2527 
2528   /* If a protocol was directly referenced, pull in indirect
2529      references.  */
2530   for (p = protocol_chain; p; p = TREE_CHAIN (p))
2531     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2532       generate_protocol_references (PROTOCOL_LIST (p));
2533 
2534   for (p = protocol_chain; p; p = TREE_CHAIN (p))
2535     {
2536       location_t loc;
2537       tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2538       tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2539 
2540       /* If protocol wasn't referenced, don't generate any code.  */
2541       decl = PROTOCOL_FORWARD_DECL (p);
2542 
2543       if (!decl)
2544 	continue;
2545 
2546       loc = DECL_SOURCE_LOCATION (decl);
2547       some = true;
2548 
2549       inst_meth =
2550 	generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2551 					   "_OBJC_ProtocolInstanceMethods",
2552 					   meta_proto_nst_meth);
2553 
2554       class_meth =
2555 	generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2556 					   "_OBJC_ProtocolClassMethods",
2557 					   meta_proto_cls_meth);
2558 
2559       opt_inst_meth =
2560 	generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2561 					   "_OBJC_OptProtocolInstMethods",
2562 					   meta_proto_nst_meth);
2563 
2564       opt_class_meth =
2565 	generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2566 					   "_OBJC_OptProtocolClassMethods",
2567 					   meta_proto_cls_meth);
2568 
2569       if (PROTOCOL_LIST (p))
2570 	refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2571       else
2572 	refs_decl = 0;
2573 
2574       /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2575       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2576 
2577       if (refs_decl)
2578 	refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2579 			     build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2580       else
2581 	refs_expr = build_int_cst (NULL_TREE, 0);
2582 
2583       props = generate_v2_property_table (p, NULL_TREE);
2584 
2585       initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2586 						protocol_name_expr, refs_expr,
2587 						inst_meth, class_meth,
2588 						opt_inst_meth, opt_class_meth,
2589 						props);
2590       finish_var_decl (decl, initlist);
2591       objc_add_to_protocol_list (p, decl);
2592     }
2593 
2594   if (some)
2595     {
2596       /* Make sure we get the Protocol class linked in - reference
2597 	 it...  */
2598       p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2599       /* ... but since we don't specifically use the reference...  we
2600          need to force it.  */
2601       DECL_PRESERVE_P (p) = 1;
2602     }
2603 }
2604 
2605 static tree
2606 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2607 {
2608   tree decl, method_list_template, initlist;
2609   vec<constructor_elt, va_gc> *v = NULL;
2610   int size, init_val;
2611 
2612   if (!chain || !name || !(size = list_length (chain)))
2613     return NULL_TREE;
2614 
2615   method_list_template
2616 	= build_v2_method_list_template (objc_method_template, size);
2617   initlist
2618 	= build_dispatch_table_initializer (objc_method_template, chain);
2619 
2620   decl = start_var_decl  (method_list_template, name);
2621 
2622   init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2623   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2624 			  build_int_cst (integer_type_node, init_val));
2625   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2626 			  build_int_cst (integer_type_node, size));
2627   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2628 
2629   OBJCMETA (decl, objc_meta, attr);
2630   finish_var_decl (decl,
2631 		   objc_build_constructor (TREE_TYPE (decl), v));
2632   return decl;
2633 }
2634 
2635 /* Init a category.  */
2636 static tree
2637 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2638 				tree inst_methods, tree class_methods,
2639 				tree protocol_list, tree property_list,
2640 				location_t loc)
2641 {
2642   tree expr, ltyp;
2643   vec<constructor_elt, va_gc> *v = NULL;
2644 
2645   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2646   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2647 
2648   ltyp = objc_method_list_ptr;
2649   if (inst_methods)
2650     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2651   else
2652     expr = convert (ltyp, null_pointer_node);
2653   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2654 
2655   if (class_methods)
2656     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2657   else
2658     expr = convert (ltyp, null_pointer_node);
2659   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2660 
2661   /* protocol_list = */
2662   ltyp = build_pointer_type (objc_v2_protocol_template);
2663   if (protocol_list)
2664     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2665   else
2666     expr = convert (ltyp, null_pointer_node);
2667   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2668 
2669   ltyp = objc_prop_list_ptr;
2670   if (property_list)
2671     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2672   else
2673     expr = convert (ltyp, null_pointer_node);
2674   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2675 
2676   return objc_build_constructor (type, v);
2677 }
2678 
2679 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2680 
2681 static void
2682 generate_v2_category (struct imp_entry *impent)
2683 {
2684   tree initlist, cat_name_expr, class_name_expr;
2685   tree protocol_decl, category, props, t;
2686   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2687   tree cat = impent->imp_context;
2688   tree cat_decl = impent->class_decl;
2689   location_t loc;
2690   char buf[BUFSIZE];
2691 
2692   loc = DECL_SOURCE_LOCATION (cat_decl);
2693 
2694   /* ??? not sure this is really necessary, the following references should
2695      force appropriate linkage linkage...
2696      -- but ... ensure a reference to the class...  */
2697   t = objc_v2_get_class_reference (CLASS_NAME (cat));
2698   /* ... which we ignore so force it out.. */
2699   DECL_PRESERVE_P (t) = 1;
2700 
2701   snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2702   class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2703   class_name_expr = build_fold_addr_expr (class_name_expr);
2704 
2705   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2706   category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2707 
2708   if (category && CLASS_PROTOCOL_LIST (category))
2709     {
2710       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2711       protocol_decl = generate_v2_protocol_list (category, cat);
2712     }
2713   else
2714     protocol_decl = NULL_TREE;
2715 
2716 /* decl = update_var_decl(impent->class_decl); */
2717 
2718   props = generate_v2_property_table (NULL_TREE, cat);
2719 
2720   if (CLASS_NST_METHODS (cat))
2721     {
2722       snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2723 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
2724 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2725       inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2726 						 meta_cati_meth);
2727     }
2728 
2729   if (CLASS_CLS_METHODS (cat))
2730     {
2731       snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2732 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
2733 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2734       class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2735 						  meta_catc_meth);
2736     }
2737 
2738   initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2739 					    cat_name_expr, class_name_expr,
2740 					    inst_methods, class_methods,
2741 					    protocol_decl, props, loc);
2742 
2743   finish_var_decl (cat_decl, initlist);
2744   impent->class_decl = cat_decl;
2745 
2746   /* Add to list of pointers in __category_list section.  */
2747   objc_v2_add_to_category_list (cat_decl);
2748   if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2749     objc_v2_add_to_nonlazy_category_list (cat_decl);
2750 }
2751 
2752 /* This routine declares a variable to hold the offset for ivar
2753    FIELD_DECL.  Variable name is .objc_ivar.ClassName.IvarName.  */
2754 
2755 typedef struct GTY(()) ivarref_entry
2756 {
2757   tree decl;
2758   tree offset;
2759 } ivarref_entry;
2760 
2761 static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
2762 
2763 static tree
2764 ivar_offset_ref (tree class_name, tree field_decl)
2765 {
2766   tree decl, field_decl_id;
2767   ivarref_entry e;
2768   bool global_var;
2769   char buf[512];
2770 
2771   create_ivar_offset_name (buf, class_name, field_decl);
2772   field_decl_id = get_identifier (buf);
2773 
2774   if (ivar_offset_refs)
2775     {
2776       int count;
2777       ivarref_entry *ref;
2778       FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
2779 	if (DECL_NAME (ref->decl) == field_decl_id)
2780 	  return ref->decl;
2781     }
2782   else
2783     /* Somewhat arbitrary initial provision.  */
2784     vec_alloc (ivar_offset_refs, 32);
2785 
2786   /* We come here if we don't find a match or at the start.  */
2787   global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
2788   if (global_var)
2789     decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
2790   else
2791     decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
2792 
2793   /* Make sure it ends up in an ObjC section.  */
2794   OBJCMETA (decl, objc_meta, meta_base);
2795 
2796   e.decl = decl;
2797   e.offset = byte_position (field_decl);
2798   vec_safe_push (ivar_offset_refs, e);
2799   return decl;
2800 }
2801 
2802 /* This routine builds initializer-list needed to initialize 'struct
2803    ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
2804    'struct ivar_t' and FIELD_DECL is list of ivars for the target
2805    class.  */
2806 
2807 static tree
2808 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
2809 {
2810   vec<constructor_elt, va_gc> *inits = NULL;
2811 
2812   do
2813     {
2814       vec<constructor_elt, va_gc> *ivar = NULL;
2815       int val;
2816       tree id;
2817 
2818       /* Unnamed bitfields are ignored.  */
2819       if (!DECL_NAME (field_decl))
2820 	{
2821 	  field_decl = DECL_CHAIN (field_decl);
2822 	  continue;
2823 	}
2824 
2825       /* Set offset.  */
2826       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2827 			      build_unary_op (input_location,
2828 					      ADDR_EXPR,
2829 					      ivar_offset_ref (class_name,
2830 							       field_decl), 0));
2831 
2832       /* Set name.  */
2833       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2834 			      add_objc_string (DECL_NAME (field_decl),
2835 						meth_var_names));
2836 
2837       /* Set type.  */
2838       id = add_objc_string (encode_field_decl (field_decl),
2839                             meth_var_types);
2840       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
2841 
2842       /* Set alignment.  */
2843       val = DECL_ALIGN_UNIT (field_decl);
2844       val = exact_log2 (val);
2845       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2846 			      build_int_cst (integer_type_node, val));
2847 
2848       /* Set size.  */
2849       val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
2850       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
2851 			      build_int_cst (integer_type_node, val));
2852 
2853       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2854 			      objc_build_constructor (type, ivar));
2855 
2856       do
2857 	field_decl = DECL_CHAIN (field_decl);
2858       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
2859     }
2860   while (field_decl);
2861 
2862   return objc_build_constructor (build_array_type (type, 0), inits);
2863 }
2864 
2865 /*
2866   struct ivar_list_t
2867   {
2868     uint32 entsize;
2869     uint32 count;
2870     struct iver_t list[count];
2871   };
2872 */
2873 
2874 static tree
2875 build_v2_ivar_list_t_template (tree list_type, int size)
2876 {
2877   tree objc_ivar_list_record;
2878   tree decls, *chain = NULL;
2879 
2880   /* Anonymous.  */
2881   objc_ivar_list_record = objc_start_struct (NULL_TREE);
2882 
2883   /* uint32 entsize; */
2884   decls = add_field_decl (integer_type_node, "entsize", &chain);
2885 
2886   /* uint32 count; */
2887   add_field_decl (integer_type_node, "count", &chain);
2888 
2889   /* struct objc_ivar ivar_list[]; */
2890   add_field_decl (build_sized_array_type (list_type, size),
2891 			  "list", &chain);
2892 
2893   objc_finish_struct (objc_ivar_list_record, decls);
2894   return objc_ivar_list_record;
2895 }
2896 
2897 /* This routine declares a static variable of type 'struct
2898    ivar_list_t' and initializes it.  chain is the source of the data,
2899    name is the name for the var.  attr is the meta-data section tag
2900    attribute.  templ is the implementation template for the class.  */
2901 
2902 static tree
2903 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
2904 {
2905   tree decl, initlist, ivar_list_template;
2906   vec<constructor_elt, va_gc> *inits = NULL;
2907   int size, ivar_t_size;
2908 
2909   if (!chain || !name || !(size = ivar_list_length (chain)))
2910     return NULL_TREE;
2911 
2912   generating_instance_variables = 1;
2913   ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
2914 						      size);
2915 
2916   initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
2917 					     objc_v2_ivar_template, chain);
2918   ivar_t_size = TREE_INT_CST_LOW  (TYPE_SIZE_UNIT (objc_v2_ivar_template));
2919 
2920   decl = start_var_decl (ivar_list_template, name);
2921   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2922 			  build_int_cst (integer_type_node, ivar_t_size));
2923   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2924 			  build_int_cst (integer_type_node, size));
2925   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2926   OBJCMETA (decl, objc_meta, attr);
2927   finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2928   generating_instance_variables = 0;
2929   return decl;
2930 }
2931 
2932 /* Routine to build initializer list to initialize objects of type
2933    struct class_t; */
2934 
2935 static tree
2936 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
2937 			      tree ro, tree cache, tree vtable)
2938 {
2939   vec<constructor_elt, va_gc> *initlist = NULL;
2940 
2941   /* isa */
2942   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
2943 
2944   /* superclass */
2945   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
2946 
2947   /* cache */
2948   if (cache)
2949     CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
2950   else
2951     CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2952 
2953   /* vtable */
2954   if (vtable)
2955     CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
2956   else
2957     CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
2958 
2959   /* ro */
2960   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
2961 
2962   return objc_build_constructor (type, initlist);
2963 }
2964 
2965 /* Routine to build object of struct class_ro_t { ... }; */
2966 
2967 static tree
2968 build_v2_class_ro_t_initializer (tree type, tree name,
2969 			       unsigned int flags, unsigned int instanceStart,
2970 			       unsigned int instanceSize,
2971 			       tree ivarLayout,
2972 			       tree baseMethods, tree baseProtocols,
2973 			       tree ivars, tree property_list)
2974 {
2975   tree expr, unsigned_char_star, ltyp;
2976   location_t loc;
2977   vec<constructor_elt, va_gc> *initlist = NULL;
2978 
2979   /* TODO: fish out the real location from somewhere.  */
2980   loc = UNKNOWN_LOCATION;
2981 
2982   /* flags */
2983   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2984 			  build_int_cst (integer_type_node, flags));
2985 
2986   /* instanceStart */
2987   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2988 			  build_int_cst (integer_type_node, instanceStart));
2989 
2990   /* instanceSize */
2991   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2992 			  build_int_cst (integer_type_node, instanceSize));
2993 
2994   /* This ABI is currently only used on m64 NeXT.  We always
2995      explicitly declare the alignment padding.  */
2996   /* reserved, pads alignment.  */
2997   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2998 			    build_int_cst (integer_type_node, 0));
2999 
3000   /* ivarLayout */
3001   unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3002   if (ivarLayout)
3003     expr = ivarLayout;
3004   else
3005     expr = convert (unsigned_char_star, null_pointer_node);
3006   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3007 
3008   /* name */
3009   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3010 
3011   /* baseMethods */
3012   ltyp = objc_method_list_ptr;
3013   if (baseMethods)
3014     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3015   else
3016     expr = convert (ltyp, null_pointer_node);
3017   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3018 
3019   /* baseProtocols */
3020   ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3021 			               get_identifier (UTAG_V2_PROTOCOL_LIST)));
3022   if (baseProtocols)
3023     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3024   else
3025     expr = convert (ltyp, null_pointer_node);
3026   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3027 
3028   /* ivars */
3029   ltyp = objc_v2_ivar_list_ptr;
3030   if (ivars)
3031     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3032   else
3033     expr = convert (ltyp, null_pointer_node);
3034   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3035 
3036   /* TODO: We don't yet have the weak/strong stuff...  */
3037   /* weakIvarLayout */
3038   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3039 			  convert (unsigned_char_star, null_pointer_node));
3040 
3041   /* property list */
3042   ltyp = objc_prop_list_ptr;
3043   if (property_list)
3044     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3045   else
3046     expr = convert (ltyp, null_pointer_node);
3047   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3048   return objc_build_constructor (type, initlist);
3049 }
3050 
3051 static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
3052 
3053 /* Record a name as needing a catcher.  */
3054 static void
3055 objc_v2_add_to_ehtype_list (tree name)
3056 {
3057   ident_data_tuple e;
3058   if (ehtype_list)
3059     {
3060       int count = 0;
3061       ident_data_tuple *ref;
3062 
3063       FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3064 	if (ref->ident == name)
3065 	  return; /* Already entered.  */
3066      }
3067   else
3068     /* Arbitrary initial count.  */
3069     vec_alloc (ehtype_list, 8);
3070 
3071   /* Not found, or new list.  */
3072   e.ident = name;
3073   e.data = NULL_TREE;
3074   vec_safe_push (ehtype_list, e);
3075 }
3076 
3077 static void
3078 generate_v2_class_structs (struct imp_entry *impent)
3079 {
3080   tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3081   tree field, firstIvar, chain;
3082   tree class_superclass_expr, metaclass_superclass_expr, props;
3083   /* TODO: figure out how to compute this.  */
3084   tree ivarLayout = NULL_TREE;
3085   tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3086   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3087   tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3088   location_t loc;
3089   char buf[BUFSIZE];
3090   unsigned int instanceStart, instanceSize;
3091   unsigned int flags = 0x01; /* RO_META */
3092   int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3093 					 : 0 ;
3094 
3095   class_decl = impent->class_decl;
3096   metaclass_decl = impent->meta_decl;
3097   loc = DECL_SOURCE_LOCATION (class_decl);
3098 
3099   DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3100   TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3101 #ifdef OBJCPLUS
3102   gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3103   gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3104 #endif
3105 
3106   /* Generation of data for meta class.  */
3107   my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3108   if (my_super_id)
3109     {
3110       /* Compute reference to root's name.  For a meta class, "isa" is
3111 	 a reference to the root class name. */
3112       tree my_root_id = my_super_id;
3113       tree my_root_int, interface;
3114       do
3115         {
3116           my_root_int = lookup_interface (my_root_id);
3117 
3118           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3119             my_root_id = CLASS_SUPER_NAME (my_root_int);
3120           else
3121             break;
3122         }
3123       while (1);
3124 
3125       /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3126          create extern if not already declared.  */
3127       snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3128 		IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3129       root_expr = create_extern_decl (objc_v2_class_template, buf);
3130       root_expr = build_fold_addr_expr (root_expr);
3131 
3132       /* Install class `isa' and `super' pointers at runtime.  */
3133       interface = lookup_interface (my_super_id);
3134       gcc_assert (interface);
3135       /* Similarly, for OBJC_CLASS_$_<interface>...  */
3136       snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3137 		IDENTIFIER_POINTER (CLASS_NAME (interface)));
3138       class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3139       class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3140       /* ... and for OBJC_METACLASS_$_<interface>.  */
3141       snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3142 		IDENTIFIER_POINTER (CLASS_NAME (interface)));
3143       metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3144       metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3145     }
3146   else
3147     {
3148       /* Root class.  */
3149       root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3150       metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3151       class_superclass_expr = build_int_cst (NULL_TREE, 0);
3152       flags |= 0x02; /* RO_ROOT: it is also a root meta class.  */
3153     }
3154 
3155   if (CLASS_PROTOCOL_LIST (impent->imp_template))
3156     {
3157       generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3158       protocol_decl = generate_v2_protocol_list (impent->imp_template,
3159 						 impent->imp_context);
3160     }
3161   else
3162     protocol_decl = 0;
3163 
3164   name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3165                                class_names);
3166 
3167   if (CLASS_CLS_METHODS (impent->imp_context))
3168     {
3169       snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3170 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3171       class_methods =
3172 	generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3173 				    buf, meta_clac_meth);
3174     }
3175 
3176   instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3177 
3178   /* Currently there are no class ivars and generation of class
3179      variables for the root of the inheritance has been removed.  It
3180      causes multiple defines if there are two root classes in the
3181      link, because each will define its own identically-named offset
3182      variable.  */
3183 
3184   class_ivars = NULL_TREE;
3185   /* TODO: Add total size of class variables when implemented. */
3186   instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3187 
3188   /* So now build the META CLASS structs.  */
3189   /* static struct class_ro_t  _OBJC_METACLASS_Foo = { ... }; */
3190 
3191   decl = start_var_decl (objc_v2_class_ro_template,
3192 			 newabi_append_ro (IDENTIFIER_POINTER
3193 						(DECL_NAME (metaclass_decl))));
3194 
3195   /* TODO: ivarLayout needs t be built.  */
3196   initlist =
3197 	build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3198 					(flags | cls_flags), instanceStart,
3199 					instanceSize, ivarLayout,
3200 					class_methods, protocol_decl,
3201 					class_ivars, NULL_TREE);
3202   /* The ROs sit in the default const section.  */
3203   OBJCMETA (decl, objc_meta, meta_base);
3204   finish_var_decl (decl, initlist);
3205 
3206   /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3207   initlist =
3208 	build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3209 				      root_expr,
3210 				      metaclass_superclass_expr,
3211 				      build_fold_addr_expr (decl),
3212 				      build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3213 				      build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3214   /* The class section attributes are set when they are created.  */
3215   finish_var_decl (metaclass_decl, initlist);
3216   impent->meta_decl = metaclass_decl;
3217 
3218   /* So now build the CLASS structs.  */
3219 
3220   flags = 0x0;		/* ... */
3221   if (!my_super_id)
3222     flags |= 0x02;	/* RO_ROOT: this is a root class */
3223 
3224   if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3225     flags |= 0x10;	/* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3226 
3227   if (objc2_objc_exception_attr (impent->imp_template))
3228     flags |= 0x20;	/* RO_EXCEPTION */
3229 
3230   if (CLASS_NST_METHODS (impent->imp_context))
3231     {
3232       snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3233 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3234       inst_methods =
3235 	generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3236 				    buf, meta_clai_meth);
3237     }
3238 
3239   /* Sort out the ivars before we try to compute the class sizes.  */
3240   if ((chain = CLASS_IVARS (impent->imp_template)))
3241     {
3242       snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3243 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3244       inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3245 					   impent->imp_template);
3246     }
3247 
3248   /* Compute instanceStart.  */
3249   gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3250   field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3251   if (my_super_id && field && TREE_CHAIN (field))
3252     field = TREE_CHAIN (field);
3253 
3254   firstIvar = field;
3255 
3256   while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3257     firstIvar = TREE_CHAIN (firstIvar);
3258 
3259   gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3260 
3261   /* Compute instanceSize.  */
3262   while (field && TREE_CHAIN (field)
3263          && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3264     field = TREE_CHAIN (field);
3265 
3266   if (field && TREE_CODE (field) == FIELD_DECL)
3267     instanceSize = int_byte_position (field) * BITS_PER_UNIT
3268 		   + tree_low_cst (DECL_SIZE (field), 0);
3269   else
3270     instanceSize = 0;
3271   instanceSize /= BITS_PER_UNIT;
3272 
3273   props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3274 
3275   /* If the class has no ivars, instanceStart should be set to the
3276      superclass's instanceSize.  */
3277   instanceStart =
3278 	(inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3279 				  : instanceSize;
3280 
3281   /* static struct class_ro_t  _OBJC_CLASS_Foo = { ... }; */
3282   decl = start_var_decl (objc_v2_class_ro_template,
3283 			 newabi_append_ro (IDENTIFIER_POINTER
3284 						(DECL_NAME (class_decl))));
3285 
3286   initlist =
3287 	build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3288 					 (flags | cls_flags), instanceStart,
3289 					 instanceSize, ivarLayout,
3290 					 inst_methods, protocol_decl,
3291 					 inst_ivars, props);
3292   /* The ROs sit in the default const section.  */
3293   OBJCMETA (decl, objc_meta, meta_base);
3294   finish_var_decl (decl, initlist);
3295 
3296   /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3297   initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3298 					build_fold_addr_expr (metaclass_decl),
3299 					class_superclass_expr,
3300 					build_fold_addr_expr (decl),
3301 					build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3302 					build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3303 
3304   /* The class section attributes are set when they are created.  */
3305   finish_var_decl (class_decl, initlist);
3306   impent->class_decl = class_decl;
3307 
3308   objc_v2_add_to_class_list (class_decl);
3309   if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3310     objc_v2_add_to_nonlazy_class_list (class_decl);
3311 
3312   if (flags & 0x20) /* RO_EXCEPTION */
3313     objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3314 }
3315 
3316 /* This routine outputs the (ivar_reference_offset, offset)
3317    tuples.  */
3318 
3319 static void
3320 build_v2_ivar_offset_ref_table (void)
3321 {
3322   int count;
3323   ivarref_entry *ref;
3324 
3325   if (!vec_safe_length (ivar_offset_refs))
3326     return;
3327 
3328   FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3329     finish_var_decl (ref->decl, ref->offset);
3330 }
3331 
3332 static void
3333 objc_generate_v2_next_metadata (void)
3334 {
3335   struct imp_entry *impent;
3336 
3337   /* FIXME: Make sure that we generate no metadata if there is nothing
3338      to put into it.  */
3339 
3340   gcc_assert (!objc_static_instances); /* Not for NeXT */
3341 
3342   build_metadata_templates ();
3343 
3344   for (impent = imp_list; impent; impent = impent->next)
3345     {
3346       /* If -gen-decls is present, Dump the @interface of each class.
3347 	 TODO: Dump the classes in the order they were found, rather
3348 	 than in reverse order as we are doing now.  */
3349       if (flag_gen_declaration)
3350 	dump_interface (gen_declaration_file, impent->imp_context);
3351 
3352       /* all of the following reference the string pool...  */
3353       if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3354 	generate_v2_class_structs (impent);
3355       else
3356 	generate_v2_category (impent);
3357     }
3358 
3359   build_next_selector_translation_table ();
3360   build_v2_message_ref_translation_table ();
3361 
3362   /* This will add "Protocol" to the class refs.  */
3363   generate_v2_protocols ();
3364 
3365   build_v2_classrefs_table ();
3366   build_v2_super_classrefs_table (/*metaclass= */false);
3367   build_v2_super_classrefs_table (/*metaclass= */true);
3368 
3369   build_v2_ivar_offset_ref_table ();
3370 
3371   build_v2_protocol_list_translation_table ();
3372   build_v2_protocol_list_address_table ();
3373 
3374   build_v2_address_table (class_list, "_OBJC_ClassList$",
3375 			  meta_label_classlist);
3376   build_v2_address_table (category_list, "_OBJC_CategoryList$",
3377 			  meta_label_categorylist);
3378   build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3379 			  meta_label_nonlazy_classlist);
3380   build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3381 			  meta_label_nonlazy_categorylist);
3382 
3383   /* Generate catch objects for eh, if any are needed.  */
3384   build_v2_eh_catch_objects ();
3385 
3386   /* Emit the string table last.  */
3387   generate_strings ();
3388 }
3389 
3390 /* NOTE --- Output NeXT V2 Exceptions --- */
3391 
3392 static GTY(()) tree objc_v2_ehtype_template;
3393 static GTY(()) tree next_v2_ehvtable_decl;
3394 static GTY(()) tree next_v2_EHTYPE_id_decl;
3395 
3396 static void
3397 build_v2_ehtype_template (void)
3398 {
3399   tree decls, *chain = NULL;
3400   objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3401 
3402   /* void *_objc_ehtype_vtable; */
3403   decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3404 
3405   /* const char *className; */
3406   add_field_decl (string_type_node, "className", &chain);
3407 
3408   /* struct class_t *const cls; */
3409   add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3410 
3411   objc_finish_struct (objc_v2_ehtype_template, decls);
3412 }
3413 
3414 /* Template for the Objective-C family typeinfo type for ABI=2.  This
3415    starts off the same as the gxx/cxx eh typeinfo.
3416 
3417    struct _objc_ehtype_t
3418    {
3419      void *_objc_ehtype_vtable_ptr;	- as per c++
3420      const char *className;		- as per c++
3421      struct class_t *const cls;
3422    }
3423 */
3424 
3425 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3426 */
3427 
3428 static tree
3429 objc2_build_ehtype_initializer (tree name, tree cls)
3430 {
3431   vec<constructor_elt, va_gc> *initlist = NULL;
3432   tree addr, offs;
3433 
3434   /* This is done the same way as c++, missing the two first entries
3435      in the parent vtable.  NOTE: there is a fix-me in the Apple/NeXT
3436      runtime source about this so, perhaps, this will change at some
3437      point.  */
3438   /* _objc_ehtype_vtable + 2*sizeof(void*)  */
3439   if (!next_v2_ehvtable_decl)
3440     {
3441       next_v2_ehvtable_decl =
3442 			start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3443       TREE_STATIC (next_v2_ehvtable_decl) = 0;
3444       DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3445       TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3446     }
3447   addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3448   offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3449   addr = fold_build_pointer_plus (addr, offs);
3450 
3451   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3452 
3453   /* className */
3454   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3455 
3456   /* cls */
3457   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3458 
3459   return objc_build_constructor (objc_v2_ehtype_template, initlist);
3460 }
3461 
3462 static tree
3463 build_ehtype (tree name, const char *eh_name, bool weak)
3464 {
3465   tree name_expr, class_name_expr, ehtype_decl, inits;
3466 
3467   name_expr = add_objc_string (name, class_names);
3468   /* Extern ref. for the class. ???  Maybe we can look this up
3469      somewhere.  */
3470   class_name_expr =
3471 	create_extern_decl (objc_v2_class_template,
3472 			    objc_build_internal_classname (name, false));
3473   class_name_expr = build_fold_addr_expr (class_name_expr);
3474   ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3475   if (weak)
3476     DECL_WEAK (ehtype_decl) = 1;
3477   inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3478   OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3479   finish_var_decl (ehtype_decl, inits);
3480   return ehtype_decl;
3481 }
3482 
3483 /* This routine returns TRUE if CLS or any of its super classes has
3484    __attribute__ ((objc_exception)).  */
3485 
3486 static bool
3487 objc2_objc_exception_attr (tree cls)
3488 {
3489   while (cls)
3490     {
3491       if (CLASS_HAS_EXCEPTION_ATTR (cls))
3492 	return true;
3493       cls = lookup_interface (CLASS_SUPER_NAME (cls));
3494     }
3495 
3496   return false;
3497 }
3498 
3499 static bool
3500 is_implemented (tree name)
3501 {
3502   struct imp_entry *t;
3503   for (t = imp_list; t; t = t->next)
3504     if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3505 	&& CLASS_NAME (t->imp_template) == name)
3506       return true;
3507 
3508   return false;
3509 }
3510 
3511 /* We will build catch objects:
3512      for any type  implemented here.
3513      for any type used in a catch that has no exception attribute.  */
3514 static void build_v2_eh_catch_objects (void)
3515 {
3516   int count=0;
3517   ident_data_tuple *ref;
3518 
3519   if (!vec_safe_length (ehtype_list))
3520     return;
3521 
3522   FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3523     {
3524       char buf[BUFSIZE];
3525       bool impl = is_implemented (ref->ident);
3526       bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3527       snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3528       if (!impl && excpt)
3529 	/* The User says this class has a catcher already.  */
3530 	ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3531       else
3532 	/* Create a catcher, weak if it wasn't marked.  */
3533 	ref->data = build_ehtype (ref->ident, buf, !excpt);
3534     }
3535 }
3536 
3537 static tree
3538 lookup_ehtype_ref (tree id)
3539 {
3540   int count=0;
3541   ident_data_tuple *ref;
3542 
3543   if (!vec_safe_length (ehtype_list))
3544     return NULL_TREE;
3545 
3546   FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3547     if (ref->ident == id)
3548       return ref->data;
3549   return NULL_TREE;
3550 }
3551 
3552 /* This hook, called via lang_eh_runtime_type, generates a runtime
3553    object which is either the address of the 'OBJC_EHTYPE_$_class'
3554    object or address of external OBJC_EHTYPE_id object.  */
3555 static tree
3556 next_runtime_02_eh_type (tree type)
3557 {
3558   tree t;
3559 
3560   if (type == error_mark_node
3561       /*|| errorcount || sorrycount*/)
3562     goto err_mark_in;
3563 
3564   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3565     {
3566       if (!next_v2_EHTYPE_id_decl)
3567 	{
3568 	  /* This is provided by the Apple/NeXT libobjc.dylib so we
3569 	     need only to reference it.  */
3570 	  next_v2_EHTYPE_id_decl =
3571 		start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3572 	  DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3573 	  TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3574 	  TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3575 	}
3576       return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3577     }
3578 
3579   if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3580     {
3581 #ifdef OBJCPLUS
3582       /* This routine is also called for c++'s catch clause; in which
3583 	 case, we use c++'s typeinfo decl.  */
3584       return build_eh_type_type (type);
3585 #else
3586       error ("non-objective-c type '%T' cannot be caught", type);
3587       goto err_mark_in;
3588 #endif
3589     }
3590   else
3591     t = OBJC_TYPE_NAME (TREE_TYPE (type));
3592 
3593   /* We have to build a reference to the OBJC_EHTYPE_<Class>.  */
3594   t = lookup_ehtype_ref (t);
3595   if (!t)
3596     goto err_mark_in;
3597 
3598   return build_fold_addr_expr (t);
3599 
3600 err_mark_in:
3601   return error_mark_node;
3602 }
3603 
3604 static GTY(()) tree objc_eh_personality_decl;
3605 
3606 static tree
3607 objc_eh_personality (void)
3608 {
3609   if (!objc_eh_personality_decl)
3610     objc_eh_personality_decl = build_personality_function  ("objc");
3611   return objc_eh_personality_decl;
3612 }
3613 
3614 /* NOTE --- interfaces --- */
3615 
3616 static tree
3617 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3618 {
3619   tree t;
3620   if (rethrown)
3621     /* We have a separate re-throw entry.  */
3622     t = build_function_call_vec (loc, objc_rethrow_exception_decl, NULL, NULL);
3623   else
3624     {
3625       /* Throw like the others...  */
3626       vec<tree, va_gc> *parms;
3627       vec_alloc (parms, 1);
3628       parms->quick_push (throw_expr);
3629       t = build_function_call_vec (loc, objc_exception_throw_decl, parms, 0);
3630       vec_free (parms);
3631     }
3632   return add_stmt (t);
3633 }
3634 
3635 /* Build __builtin_eh_pointer.  */
3636 
3637 static tree
3638 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3639 {
3640   tree t;
3641   t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3642   t = build_call_expr (t, 1, integer_zero_node);
3643   return fold_convert (objc_object_type, t);
3644 }
3645 
3646 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3647 			 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3648 {
3649   tree t;
3650 
3651   /* Record the data for the catch in the try context so that we can
3652      finalize it later.  Ellipsis is signalled by a NULL entry.  */
3653   if (ellipsis)
3654     t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3655   else
3656     t = build_stmt (input_location, CATCH_EXPR, type, compound);
3657   (*cur_try_context)->current_catch = t;
3658 
3659   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
3660   t = objc_build_exc_ptr (cur_try_context);
3661   t = convert (TREE_TYPE (decl), t);
3662   /* FIXME: location.  */
3663   if (type && type != error_mark_node)
3664     {
3665       t = build1(NOP_EXPR, ptr_type_node, t);
3666       t = build_function_call (input_location, objc2_begin_catch_decl,
3667 			      tree_cons (NULL_TREE, t, NULL_TREE));
3668 
3669       /* We might want to build a catch object for this (if it's not
3670 	 id).  */
3671       if (POINTER_TYPE_P (type)
3672 	  && !objc_is_object_id (TREE_TYPE (type))
3673 	  && TYPED_OBJECT (TREE_TYPE (type)))
3674 	objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3675     }
3676   return build2 (MODIFY_EXPR, void_type_node, decl, t);
3677 }
3678 
3679 /* try { catch-body } finally { objc_end_catch (); } */
3680 static void
3681 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3682 {
3683   struct objc_try_context *ct;
3684   tree try_exp, func, *l, t ;
3685   location_t loc = (*cur_try_context)->try_locus;
3686 
3687   if (!curr_catch || curr_catch == error_mark_node)
3688     return;
3689 
3690   t = CATCH_BODY (curr_catch);
3691   if (TREE_CODE (t) == BIND_EXPR)
3692     {
3693       /* Usual case of @catch (objc-expr).  */
3694       objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3695       BIND_EXPR_BODY (t) = NULL_TREE;
3696       l = &BIND_EXPR_BODY (t);
3697     }
3698   else
3699     {
3700       /* NULL entry, meaning @catch (...).  */
3701       objc_begin_try_stmt (loc, t);
3702       CATCH_BODY (curr_catch) = NULL_TREE;
3703       l = &CATCH_BODY (curr_catch);
3704     }
3705 
3706   /* Pick up the new context we made in begin_try above...  */
3707   ct = *cur_try_context;
3708   func = build_function_call_vec (loc, objc2_end_catch_decl, NULL, NULL);
3709   append_to_statement_list (func, &ct->finally_body);
3710   try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3711   *cur_try_context = ct->outer;
3712   free (ct);
3713   append_to_statement_list (try_exp, l);
3714   append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3715 }
3716 
3717 static tree
3718 finish_try_stmt (struct objc_try_context **cur_try_context)
3719 {
3720   struct objc_try_context *c = *cur_try_context;
3721   tree stmt = c->try_body;
3722   if (c->catch_list)
3723     stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3724   if (c->finally_body)
3725     stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3726   return stmt;
3727 }
3728 
3729 #include "gt-objc-objc-next-runtime-abi-02.h"
3730