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