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