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