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