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