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