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