xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/objc/objc-next-runtime-abi-01.c (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
1 /* Next Runtime (ABI-0/1) private.
2    Copyright (C) 2011-2015 Free Software Foundation, Inc.
3    Contributed by Iain Sandoe (split from objc-act.c)
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 /* This implements the original NeXT ABI (0) used for m32 code and
22    indicated by module version 6.  It also implements the small number
23    of additions made for properties and optional protocol methods as
24    ABI=1 (module version 7).  */
25 
26 #include "config.h"
27 #include "system.h"
28 #include "coretypes.h"
29 #include "hash-set.h"
30 #include "machmode.h"
31 #include "vec.h"
32 #include "double-int.h"
33 #include "input.h"
34 #include "alias.h"
35 #include "symtab.h"
36 #include "options.h"
37 #include "wide-int.h"
38 #include "inchash.h"
39 #include "tree.h"
40 #include "fold-const.h"
41 #include "stringpool.h"
42 
43 #ifdef OBJCPLUS
44 #include "cp/cp-tree.h"
45 #else
46 #include "c/c-tree.h"
47 #include "c/c-lang.h"
48 #endif
49 #include "langhooks.h"
50 #include "c-family/c-objc.h"
51 #include "objc-act.h"
52 
53 /* When building Objective-C++, we are not linking against the C
54    front-end and so need to replicate the C tree-construction
55    functions in some way.  */
56 #ifdef OBJCPLUS
57 #define OBJCP_REMAP_FUNCTIONS
58 #include "objcp-decl.h"
59 #endif  /* OBJCPLUS */
60 
61 #include "ggc.h"
62 #include "target.h"
63 #include "c-family/c-target.h"
64 #include "tree-iterator.h"
65 
66 #include "objc-runtime-hooks.h"
67 #include "objc-runtime-shared-support.h"
68 #include "objc-encoding.h"
69 
70 /* NeXT ABI 0 and 1 private definitions.  */
71 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
72 
73 #define TAG_GETCLASS			"objc_getClass"
74 #define TAG_GETMETACLASS		"objc_getMetaClass"
75 
76 #define TAG_MSGSEND			"objc_msgSend"
77 #define TAG_MSGSENDSUPER		"objc_msgSendSuper"
78 #define TAG_MSGSEND_STRET		"objc_msgSend_stret"
79 #define TAG_MSGSENDSUPER_STRET		"objc_msgSendSuper_stret"
80 
81 /* NeXT-specific tags.  */
82 
83 #define TAG_MSGSEND_NONNIL		"objc_msgSendNonNil"
84 #define TAG_MSGSEND_NONNIL_STRET	"objc_msgSendNonNil_stret"
85 #define TAG_EXCEPTIONEXTRACT		"objc_exception_extract"
86 #define TAG_EXCEPTIONTRYENTER		"objc_exception_try_enter"
87 #define TAG_EXCEPTIONTRYEXIT		"objc_exception_try_exit"
88 #define TAG_EXCEPTIONMATCH		"objc_exception_match"
89 #define TAG_SETJMP			"_setjmp"
90 
91 #define TAG_ASSIGNIVAR			"objc_assign_ivar"
92 #define TAG_ASSIGNGLOBAL		"objc_assign_global"
93 #define TAG_ASSIGNSTRONGCAST		"objc_assign_strongCast"
94 
95 /* Branch entry points.  All that matters here are the addresses;
96    functions with these names do not really exist in libobjc.  */
97 
98 #define TAG_MSGSEND_FAST		"objc_msgSend_Fast"
99 #define TAG_ASSIGNIVAR_FAST		"objc_assign_ivar_Fast"
100 
101 /* The version identifies which language generation and runtime the
102    module (file) was compiled for, and is recorded in the module
103    descriptor.  */
104 #define OBJC_VERSION			(flag_objc_abi >= 1 ? 7 : 6)
105 
106 #define UTAG_CLASS_EXT			"_objc_class_ext"
107 #define UTAG_PROPERTY_LIST		"_prop_list_t"
108 #define UTAG_PROTOCOL_EXT		"_objc_protocol_extension"
109 
110 #define CLS_HAS_CXX_STRUCTORS		0x2000L
111 
112 /* rt_trees identifiers - shared between NeXT implementations.  These
113    allow the FE to tag meta-data in a manner that survives LTO and can
114    be used when the runtime requires that certain meta-data items
115    appear in particular named sections.  */
116 
117 #include "objc-next-metadata-tags.h"
118 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
119 
120 static void next_runtime_01_initialize (void);
121 
122 static tree next_runtime_abi_01_super_superclassfield_id (void);
123 
124 static tree next_runtime_abi_01_class_decl (tree);
125 static tree next_runtime_abi_01_metaclass_decl (tree);
126 static tree next_runtime_abi_01_category_decl (tree);
127 static tree next_runtime_abi_01_protocol_decl (tree);
128 static tree next_runtime_abi_01_string_decl (tree, const char *, string_section);
129 
130 static tree next_runtime_abi_01_get_class_reference (tree);
131 static tree next_runtime_abi_01_build_selector_reference (location_t, tree, tree);
132 static tree next_runtime_abi_01_get_protocol_reference (location_t, tree);
133 static tree next_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
134 static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
135 static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
136 
137 static tree next_runtime_abi_01_receiver_is_class_object (tree);
138 static void next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **,
139 							tree, int, int);
140 static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
141 							tree, tree, tree, int);
142 static bool next_runtime_abi_01_setup_const_string_class_decl (void);
143 static tree next_runtime_abi_01_build_const_string_constructor (location_t, tree, int);
144 
145 static void objc_generate_v1_next_metadata (void);
146 
147 static void build_next_objc_exception_stuff (void);
148 static tree objc_eh_runtime_type (tree type);
149 static tree objc_eh_personality (void);
150 static tree build_throw_stmt (location_t, tree, bool);
151 static tree objc_build_exc_ptr (struct objc_try_context **);
152 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
153 static void finish_catch (struct objc_try_context **, tree);
154 static tree finish_try_stmt (struct objc_try_context **);
155 
156 bool
157 objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks)
158 {
159   if (flag_objc_exceptions
160       && !flag_objc_sjlj_exceptions)
161     {
162       warning_at (UNKNOWN_LOCATION, OPT_Wall,
163 		"%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
164 		"system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2");
165     }
166 
167   rthooks->initialize = next_runtime_01_initialize;
168   rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
169   rthooks->tag_getclass = TAG_GETCLASS;
170   rthooks->super_superclassfield_ident = next_runtime_abi_01_super_superclassfield_id;
171 
172   rthooks->class_decl = next_runtime_abi_01_class_decl;
173   rthooks->metaclass_decl = next_runtime_abi_01_metaclass_decl;
174   rthooks->category_decl = next_runtime_abi_01_category_decl;
175   rthooks->protocol_decl = next_runtime_abi_01_protocol_decl;
176   rthooks->string_decl = next_runtime_abi_01_string_decl;
177 
178   rthooks->get_class_reference = next_runtime_abi_01_get_class_reference;
179   rthooks->build_selector_reference = next_runtime_abi_01_build_selector_reference;
180   rthooks->get_protocol_reference = next_runtime_abi_01_get_protocol_reference;
181   rthooks->build_ivar_reference = next_runtime_abi_01_build_ivar_ref;
182   rthooks->get_class_super_ref = next_runtime_abi_01_get_class_super_ref;
183   rthooks->get_category_super_ref = next_runtime_abi_01_get_category_super_ref;
184 
185   rthooks->receiver_is_class_object = next_runtime_abi_01_receiver_is_class_object;
186   rthooks->get_arg_type_list_base = next_runtime_abi_01_get_arg_type_list_base;
187   rthooks->build_objc_method_call = next_runtime_abi_01_build_objc_method_call;
188 
189   rthooks->setup_const_string_class_decl =
190 				next_runtime_abi_01_setup_const_string_class_decl;
191   rthooks->build_const_string_constructor =
192 				next_runtime_abi_01_build_const_string_constructor;
193 
194   rthooks->build_throw_stmt = build_throw_stmt;
195   rthooks->build_exc_ptr = objc_build_exc_ptr;
196   rthooks->begin_catch = begin_catch;
197   rthooks->finish_catch = finish_catch;
198   rthooks->finish_try_stmt = finish_try_stmt;
199 
200   rthooks->generate_metadata = objc_generate_v1_next_metadata;
201   return true;
202 }
203 
204 /* We need a way to convey what kind of meta-data are represented by a
205    given variable, since each type is expected (by the runtime) to be
206    found in a specific named section.  The solution must be usable
207    with LTO.
208 
209    The scheme used for NeXT ABI 0/1 (partial matching of variable
210    names) is not satisfactory for LTO & ABI-2.  We now tag ObjC
211    meta-data with identification attributes in the front end.  The
212    back-end may choose to act on these as it requires.  */
213 
214 static void
215 next_runtime_abi_01_init_metadata_attributes (void)
216 {
217   if (!objc_meta)
218     objc_meta = get_identifier ("OBJC1META");
219 
220   if (!meta_base)
221     meta_base = get_identifier ("V1_BASE");
222 
223   meta_class = get_identifier ("V1_CLAS");
224   meta_metaclass = get_identifier ("V1_META");
225   meta_category = get_identifier ("V1_CATG");
226   meta_protocol = get_identifier ("V1_PROT");
227 
228   meta_clac_vars = get_identifier ("V1_CLCV");
229   meta_clai_vars = get_identifier ("V1_CLIV");
230 
231   meta_clac_meth = get_identifier ("V1_CLCM");
232   meta_clai_meth = get_identifier ("V1_CLIM");
233   meta_catc_meth = get_identifier ("V1_CACM");
234   meta_cati_meth = get_identifier ("V1_CAIM");
235   meta_proto_cls_meth = get_identifier ("V1_PCLM");
236   meta_proto_nst_meth = get_identifier ("V1_PNSM");
237 
238   meta_clas_prot = get_identifier ("V1_CLPR");
239   meta_catg_prot = get_identifier ("V1_CAPR");
240 
241   meta_class_reference = get_identifier ("V1_CLRF");
242   meta_proto_ref = get_identifier ("V1_PRFS");
243   meta_sel_refs = get_identifier ("V1_SRFS");
244 
245   meta_class_name = get_identifier ("V1_CLSN");
246   meta_meth_name = get_identifier ("V1_METN");
247   meta_meth_type = get_identifier ("V1_METT");
248   meta_prop_name_attr = get_identifier ("V1_STRG");
249 
250   meta_modules = get_identifier ("V1_MODU");
251   meta_symtab = get_identifier ("V1_SYMT");
252   meta_info = get_identifier ("V1_INFO");
253 
254   meta_proplist = get_identifier ("V1_PLST");
255   meta_protocol_extension = get_identifier ("V1_PEXT");
256   meta_class_extension = get_identifier ("V1_CEXT");
257 
258   meta_const_str = get_identifier ("V1_CSTR");
259 }
260 
261 static void build_v1_class_template (void);
262 static void build_v1_category_template (void);
263 static void build_v1_protocol_template (void);
264 
265 static void next_runtime_01_initialize (void)
266 {
267   tree type;
268 
269 #ifdef OBJCPLUS
270   /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
271      default.  */
272   if (!global_options_set.x_flag_objc_call_cxx_cdtors)
273     global_options.x_flag_objc_call_cxx_cdtors = 1;
274 #endif
275 
276   /* Set up attributes to be attached to the meta-data so that they
277      will be placed in the correct sections.  */
278   next_runtime_abi_01_init_metadata_attributes ();
279 
280   if (flag_objc_abi >= 1)
281     objc_prop_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE,
282 					     get_identifier ("_prop_list_t")));
283 
284  /* Declare type of selector-objects that represent an operation
285     name.  */
286   /* `struct objc_selector *' */
287   objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
288 					   get_identifier (TAG_SELECTOR)));
289 
290   build_v1_class_template ();
291   build_super_template ();
292   build_v1_protocol_template ();
293   build_v1_category_template ();
294 
295   /* NB: In order to call one of the ..._stret (struct-returning)
296      functions, the function *MUST* first be cast to a signature that
297      corresponds to the actual ObjC method being invoked.  This is
298      what is done by the build_objc_method_call() routine below.  */
299 
300   /* id objc_msgSend (id, SEL, ...); */
301   /* id objc_msgSendNonNil (id, SEL, ...); */
302   /* id objc_msgSend_stret (id, SEL, ...); */
303   /* id objc_msgSendNonNil_stret (id, SEL, ...); */
304   type = build_varargs_function_type_list (objc_object_type,
305 					   objc_object_type,
306 					   objc_selector_type,
307 					   NULL_TREE);
308 
309   umsg_decl = add_builtin_function (TAG_MSGSEND,
310 				    type, 0, NOT_BUILT_IN,
311 				    NULL, NULL_TREE);
312 
313   umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL,
314 					   type, 0, NOT_BUILT_IN,
315 					    NULL, NULL_TREE);
316 
317   umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET,
318 					  type, 0, NOT_BUILT_IN,
319 					  NULL, NULL_TREE);
320 
321   umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET,
322 						 type, 0, NOT_BUILT_IN,
323 						 NULL, NULL_TREE);
324 
325   /* These can throw, because the function that gets called can throw
326      in Obj-C++, or could itself call something that can throw even in
327      Obj-C.  */
328   TREE_NOTHROW (umsg_decl) = 0;
329   TREE_NOTHROW (umsg_nonnil_decl) = 0;
330   TREE_NOTHROW (umsg_stret_decl) = 0;
331   TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
332 
333  /* id objc_msgSend_Fast (id, SEL, ...)
334 	   __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
335 #ifdef OFFS_MSGSEND_FAST
336   umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST,
337 					     type, 0, NOT_BUILT_IN,
338 					     NULL, NULL_TREE);
339   TREE_NOTHROW (umsg_fast_decl) = 0;
340   DECL_ATTRIBUTES (umsg_fast_decl)
341 	= tree_cons (get_identifier ("hard_coded_address"),
342 		     build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
343 		     NULL_TREE);
344 #else
345   /* No direct dispatch available.  */
346   umsg_fast_decl = umsg_decl;
347 #endif
348 
349   /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
350   /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
351   type = build_varargs_function_type_list (objc_object_type,
352                                             objc_super_type,
353                                             objc_selector_type,
354                                             NULL_TREE);
355   umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
356 					      type, 0, NOT_BUILT_IN,
357 					      NULL, NULL_TREE);
358   umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET,
359 						    type, 0, NOT_BUILT_IN, 0,
360 						    NULL_TREE);
361   TREE_NOTHROW (umsg_super_decl) = 0;
362   TREE_NOTHROW (umsg_super_stret_decl) = 0;
363 
364   type = build_function_type_list (objc_object_type,
365                                    const_string_type_node,
366                                    NULL_TREE);
367 
368   /* id objc_getClass (const char *); */
369   objc_get_class_decl
370     = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
371 			    NULL, NULL_TREE);
372 
373   /* id objc_getMetaClass (const char *); */
374   objc_get_meta_class_decl
375     = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
376 
377   /* This is the type of all of the following functions
378      objc_copyStruct().  */
379   type = build_function_type_list (void_type_node,
380 				   ptr_type_node,
381 				   const_ptr_type_node,
382 				   ptrdiff_type_node,
383 				   boolean_type_node,
384 				   boolean_type_node,
385 				   NULL_TREE);
386   /* Declare the following function:
387 	 void
388          objc_copyStruct (void *destination, const void *source,
389 	                  ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
390   objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
391 						   type, 0, NOT_BUILT_IN,
392 						   NULL, NULL_TREE);
393   TREE_NOTHROW (objc_copyStruct_decl) = 0;
394   objc_getPropertyStruct_decl = NULL_TREE;
395   objc_setPropertyStruct_decl = NULL_TREE;
396 
397   build_next_objc_exception_stuff ();
398   if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
399     using_eh_for_cleanups ();
400   lang_hooks.eh_runtime_type = objc_eh_runtime_type;
401   lang_hooks.eh_personality = objc_eh_personality;
402 }
403 
404 /* --- templates --- */
405 
406 /* struct _objc_class
407    {
408      struct _objc_class *isa;
409      struct _objc_class *super_class;
410      char *name;
411      long version;
412      long info;
413      long instance_size;
414      struct _objc_ivar_list *ivars;
415      struct _objc_method_list *methods;
416      struct objc_cache *cache;
417      struct _objc_protocol_list *protocols;
418    #if ABI=1
419      const char *ivar_layout;
420      struct _objc_class_ext *ext;
421    #else
422      void *sel_id;
423      void *gc_object_type;
424     #endif
425    }; */
426 
427 /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT
428    runtime.  We generate them for ABI==0 to maintain backward binary
429    compatibility.  */
430 
431 static void
432 build_v1_class_template (void)
433 {
434   tree ptype, decls, *chain = NULL;
435 
436   objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
437 
438   /* struct _objc_class *isa; */
439   decls = add_field_decl (build_pointer_type (objc_class_template),
440 			  "isa", &chain);
441 
442   /* struct _objc_class *super_class; */
443   add_field_decl (build_pointer_type (objc_class_template),
444 		  "super_class", &chain);
445 
446   /* char *name; */
447   add_field_decl (string_type_node, "name", &chain);
448 
449   /* long version; */
450   add_field_decl (long_integer_type_node, "version", &chain);
451 
452   /* long info; */
453   add_field_decl (long_integer_type_node, "info", &chain);
454 
455   /* long instance_size; */
456   add_field_decl (long_integer_type_node, "instance_size", &chain);
457 
458   /* struct _objc_ivar_list *ivars; */
459   add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
460 
461   /* struct _objc_method_list *methods; */
462   add_field_decl (objc_method_list_ptr, "methods", &chain);
463 
464   /* struct objc_cache *cache; */
465   ptype = build_pointer_type (xref_tag (RECORD_TYPE,
466 					    get_identifier ("objc_cache")));
467   add_field_decl (ptype, "cache", &chain);
468 
469   /* struct _objc_protocol **protocol_list; */
470   ptype = build_pointer_type (build_pointer_type
471 			      (xref_tag (RECORD_TYPE,
472 					 get_identifier (UTAG_PROTOCOL))));
473   add_field_decl (ptype, "protocol_list", &chain);
474 
475   if (flag_objc_abi >= 1)
476     {
477       /* const char *ivar_layout; */
478       add_field_decl (const_string_type_node, "ivar_layout", &chain);
479 
480       /* struct _objc_class_ext *ext; */
481       ptype = build_pointer_type (xref_tag (RECORD_TYPE,
482 					    get_identifier (UTAG_CLASS_EXT)));
483       add_field_decl (ptype, "ext", &chain);
484     }
485   else
486     {
487       /* void *sel_id; */
488       add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain);
489       /* void *gc_object_type; */
490       add_field_decl (build_pointer_type (void_type_node), "gc_object_type",
491 		      &chain);
492     }
493 
494   objc_finish_struct (objc_class_template, decls);
495 }
496 
497 /* struct _objc_category
498    {
499      char *category_name;
500      char *class_name;
501      struct _objc_method_list *instance_methods;
502      struct _objc_method_list *class_methods;
503      struct _objc_protocol_list *protocols;
504    #if ABI=1
505      uint32_t size;	// sizeof (struct _objc_category)
506      struct _objc_property_list *instance_properties;  // category's own @property decl.
507    #endif
508    };   */
509 
510 static void
511 build_v1_category_template (void)
512 {
513   tree ptype, decls, *chain = NULL;
514 
515   objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
516 
517   /* char *category_name; */
518   decls = add_field_decl (string_type_node, "category_name", &chain);
519 
520   /* char *class_name; */
521   add_field_decl (string_type_node, "class_name", &chain);
522 
523   /* struct _objc_method_list *instance_methods; */
524   add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
525 
526   /* struct _objc_method_list *class_methods; */
527   add_field_decl (objc_method_list_ptr, "class_methods", &chain);
528 
529   /* struct _objc_protocol **protocol_list; */
530   ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
531   add_field_decl (ptype, "protocol_list", &chain);
532 
533   if (flag_objc_abi >= 1)
534     {
535       add_field_decl (integer_type_node, "size", &chain);
536 
537       /* struct _objc_property_list *instance_properties;
538          This field describes a category's @property declarations.
539          Properties from inherited protocols are not included.  */
540       ptype = build_pointer_type (xref_tag (RECORD_TYPE,
541 					    get_identifier (UTAG_PROPERTY_LIST)));
542       add_field_decl (ptype, "instance_properties", &chain);
543     }
544   objc_finish_struct (objc_category_template, decls);
545 }
546 
547 /* Begin code generation for protocols...
548    Modified for ObjC #1 extensions.  */
549 
550 /* struct _objc_protocol
551    {
552    #if ABI=1
553      struct _objc_protocol_extension *isa;
554    #else
555      struct _objc_class *isa;
556    #endif
557 
558      char *protocol_name;
559      struct _objc_protocol **protocol_list;
560      struct _objc__method_prototype_list *instance_methods;
561      struct _objc__method_prototype_list *class_methods;
562    }; */
563 
564 static void
565 build_v1_protocol_template (void)
566 {
567   tree ptype, decls, *chain = NULL;
568 
569   objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
570 
571   if (flag_objc_abi >= 1)
572     /* struct _objc_protocol_extension *isa; */
573     ptype = build_pointer_type (xref_tag (RECORD_TYPE,
574 					  get_identifier (UTAG_PROTOCOL_EXT)));
575   else
576     /* struct _objc_class *isa; */
577     ptype = build_pointer_type (xref_tag (RECORD_TYPE,
578 					get_identifier (UTAG_CLASS)));
579 
580   decls = add_field_decl (ptype, "isa", &chain);
581 
582   /* char *protocol_name; */
583   add_field_decl (string_type_node, "protocol_name", &chain);
584 
585   /* struct _objc_protocol **protocol_list; */
586   ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
587   add_field_decl (ptype, "protocol_list", &chain);
588 
589   /* struct _objc__method_prototype_list *instance_methods; */
590   add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
591 
592   /* struct _objc__method_prototype_list *class_methods; */
593   add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
594 
595   objc_finish_struct (objc_protocol_template, decls);
596 }
597 
598 /* --- names, decls identifiers --- */
599 
600 static tree
601 next_runtime_abi_01_super_superclassfield_id (void)
602 {
603   if (!super_superclassfield_id)
604     super_superclassfield_id = get_identifier ("super_class");
605   return super_superclassfield_id;
606 }
607 
608 static tree
609 next_runtime_abi_01_class_decl (tree klass)
610 {
611   tree decl;
612   char buf[BUFSIZE];
613   snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
614 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
615   decl = start_var_decl (objc_class_template, buf);
616   OBJCMETA (decl, objc_meta, meta_class);
617   return decl;
618 }
619 
620 static tree
621 next_runtime_abi_01_metaclass_decl (tree klass)
622 {
623   tree decl;
624   char buf[BUFSIZE];
625   snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
626 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
627   decl = start_var_decl (objc_class_template, buf);
628   OBJCMETA (decl, objc_meta, meta_metaclass);
629   return decl;
630 }
631 
632 static tree
633 next_runtime_abi_01_category_decl (tree klass)
634 {
635   tree decl;
636   char buf[BUFSIZE];
637   snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
638 	    IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
639 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
640   decl = start_var_decl (objc_category_template, buf);
641   OBJCMETA (decl, objc_meta, meta_category);
642   return decl;
643 }
644 
645 static tree
646 next_runtime_abi_01_protocol_decl (tree p)
647 {
648   tree decl;
649   char buf[BUFSIZE];
650 
651   /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
652 
653   snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
654 	    IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
655   decl = start_var_decl (objc_protocol_template, buf);
656   OBJCMETA (decl, objc_meta, meta_protocol);
657   return decl;
658 }
659 
660 static tree
661 next_runtime_abi_01_string_decl (tree type, const char *name,  string_section where)
662 {
663   tree var = start_var_decl (type, name);
664   switch (where)
665     {
666       case class_names:
667 	OBJCMETA (var, objc_meta, meta_class_name);
668 	break;
669       case meth_var_names:
670 	OBJCMETA (var, objc_meta, meta_meth_name);
671 	break;
672       case meth_var_types:
673 	OBJCMETA (var, objc_meta, meta_meth_type);
674 	break;
675       case prop_names_attr:
676 	OBJCMETA (var, objc_meta, meta_prop_name_attr);
677 	break;
678       default:
679 	OBJCMETA (var, objc_meta, meta_base);
680 	break;
681     }
682   return var;
683 }
684 
685 /* --- entry --- */
686 
687 static GTY(()) int class_reference_idx;
688 
689 static tree
690 build_class_reference_decl (void)
691 {
692   tree decl;
693   char buf[BUFSIZE];
694 
695   sprintf (buf, "_OBJC_ClassRefs_%d", class_reference_idx++);
696   decl = start_var_decl (objc_class_type, buf);
697 
698   return decl;
699 }
700 
701 static tree
702 next_runtime_abi_01_get_class_reference (tree ident)
703 {
704   if (!flag_zero_link)
705     {
706       tree *chain;
707       tree decl;
708 
709       for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
710 	if (TREE_VALUE (*chain) == ident)
711 	  {
712 	    if (! TREE_PURPOSE (*chain))
713 	      TREE_PURPOSE (*chain) = build_class_reference_decl ();
714 
715 	    return TREE_PURPOSE (*chain);
716 	  }
717 
718       decl = build_class_reference_decl ();
719       *chain = tree_cons (decl, ident, NULL_TREE);
720       return decl;
721     }
722   else
723     {
724       tree params;
725 
726       add_class_reference (ident);
727 
728       params = build_tree_list (NULL_TREE,
729 				my_build_string_pointer
730 				(IDENTIFIER_LENGTH (ident) + 1,
731 				 IDENTIFIER_POINTER (ident)));
732 
733       return build_function_call (input_location, objc_get_class_decl, params);
734     }
735 }
736 
737 /* Used by build_function_type_for_method.  Append the types for
738    receiver & _cmd at the start of a method argument list to ARGTYPES.
739    CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
740    trying to define a method or call one.  SUPERFLAG says this is for a
741    send to super.  METH may be NULL, in the case that there is no
742    prototype.  */
743 
744 static void
745 next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
746 					    tree meth, int context,
747 					    int superflag)
748 {
749   tree receiver_type;
750 
751   if (superflag)
752     receiver_type = objc_super_type;
753   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
754     receiver_type = objc_instance_type;
755   else
756     receiver_type = objc_object_type;
757 
758   vec_safe_push (*argtypes, receiver_type);
759   /* Selector type - will eventually change to `int'.  */
760   vec_safe_push (*argtypes, objc_selector_type);
761 }
762 
763 static tree
764 next_runtime_abi_01_receiver_is_class_object (tree receiver)
765 {
766   if (TREE_CODE (receiver) == VAR_DECL
767       && IS_CLASS (TREE_TYPE (receiver)))
768     {
769       /* The receiver is a variable created by build_class_reference_decl.  */
770       tree chain = cls_ref_chain ;
771       /* Look up the identifier in the relevant chain.  */
772       for (; chain; chain = TREE_CHAIN (chain))
773 	if (TREE_PURPOSE (chain) == receiver)
774 	  return TREE_VALUE (chain);
775     }
776   return NULL_TREE;
777 }
778 
779 static tree
780 build_selector_reference_decl (tree ident)
781 {
782   tree decl;
783   char *t, buf[BUFSIZE];
784 
785   snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
786   t = buf;
787   while (*t)
788     {
789       if (*t==':')
790         *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
791       t++;
792     }
793   decl = start_var_decl (objc_selector_type, buf);
794   OBJCMETA (decl, objc_meta, meta_sel_refs);
795   return decl;
796 }
797 
798 static tree
799 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
800 					      tree ident,
801 					      tree proto ATTRIBUTE_UNUSED)
802 {
803   tree *chain = &sel_ref_chain;
804   tree expr;
805 
806   while (*chain)
807     {
808       if (TREE_VALUE (*chain) == ident)
809 	return TREE_PURPOSE (*chain);
810 
811       chain = &TREE_CHAIN (*chain);
812     }
813 
814   expr = build_selector_reference_decl (ident);
815 
816   *chain = tree_cons (expr, ident, NULL_TREE);
817 
818   return expr;
819 }
820 
821 /* Build a tree expression to send OBJECT the operation SELECTOR,
822    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
823    assuming the method has prototype METHOD_PROTOTYPE.
824    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
825    LOC is the location of the expression to build.
826    Use METHOD_PARAMS as list of args to pass to the method.
827    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
828 
829 static tree
830 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
831 			tree lookup_object, tree selector,
832 			tree method_params)
833 {
834   tree sender, sender_cast, method, t;
835   tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
836   vec<tree, va_gc> *parms;
837   unsigned nparm = (method_params ? list_length (method_params) : 0);
838 
839   /* If a prototype for the method to be called exists, then cast
840      the sender's return type and arguments to match that of the method.
841      Otherwise, leave sender as is.  */
842   tree ret_type
843     = (method_prototype
844        ? TREE_VALUE (TREE_TYPE (method_prototype))
845        : objc_object_type);
846   tree ftype = build_function_type_for_method (ret_type, method_prototype,
847 					       METHOD_REF, super_flag);
848 
849   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
850     ftype = build_type_attribute_variant (ftype,
851 					  METHOD_TYPE_ATTRIBUTES
852 					  (method_prototype));
853 
854   sender_cast = build_pointer_type (ftype);
855 
856   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
857 
858   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
859   lookup_object = save_expr (lookup_object);
860 
861   /* Param list + 2 slots for object and selector.  */
862   vec_alloc (parms, nparm + 2);
863 
864   /* If we are returning a struct in memory, and the address
865      of that memory location is passed as a hidden first
866      argument, then change which messenger entry point this
867      expr will call.  NB: Note that sender_cast remains
868      unchanged (it already has a struct return type).  */
869   if (!targetm.calls.struct_value_rtx (0, 0)
870       && (TREE_CODE (ret_type) == RECORD_TYPE
871 	  || TREE_CODE (ret_type) == UNION_TYPE)
872       && targetm.calls.return_in_memory (ret_type, 0))
873     sender = (super_flag ? umsg_super_stret_decl
874 			 : flag_nil_receivers ? umsg_stret_decl
875 					      : umsg_nonnil_stret_decl);
876   else
877     sender = (super_flag ? umsg_super_decl
878 			 : (flag_nil_receivers  ? (flag_objc_direct_dispatch
879 							? umsg_fast_decl
880 							: umsg_decl)
881 						: umsg_nonnil_decl));
882   method = build_fold_addr_expr_loc (loc, sender);
883 
884   /* Pass the object to the method.  */
885   parms->quick_push (lookup_object);
886   /* Pass the selector to the method.  */
887   parms->quick_push (selector);
888   /* Now append the remainder of the parms.  */
889   if (nparm)
890     for (; method_params; method_params = TREE_CHAIN (method_params))
891       parms->quick_push (TREE_VALUE (method_params));
892 
893   /* Build an obj_type_ref, with the correct cast for the method call.  */
894   t = build3 (OBJ_TYPE_REF, sender_cast, method,
895 			    lookup_object, size_zero_node);
896   t = build_function_call_vec (loc, vNULL, t, parms, NULL);
897   vec_free (parms);
898   return t;
899 }
900 
901 static tree
902 next_runtime_abi_01_build_objc_method_call (location_t loc,
903 					    tree method_prototype,
904 					    tree receiver,
905 					    tree rtype ATTRIBUTE_UNUSED,
906 					    tree sel_name,
907 					    tree method_params,
908 					    int super)
909 {
910   tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name,
911 								NULL_TREE);
912 
913   return build_objc_method_call (loc, super, method_prototype,
914 				 receiver, selector, method_params);
915 }
916 
917 static tree
918 next_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
919 {
920   tree expr;
921 
922   if (!PROTOCOL_FORWARD_DECL (p))
923     PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p);
924 
925   expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
926   return convert (objc_protocol_type, expr);
927 }
928 
929 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct.  */
930 
931 static tree
932 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
933 				   tree base, tree id)
934 {
935   return objc_build_component_ref (base, id);
936 }
937 
938 /* We build super class references as we need them (but keep them once
939    built for the sake of efficiency).  */
940 
941 static tree
942 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
943 					 struct imp_entry *imp, bool inst_meth)
944 {
945   if (inst_meth)
946     {
947       if (!ucls_super_ref)
948 	ucls_super_ref =
949 		objc_build_component_ref (imp->class_decl,
950 					  get_identifier ("super_class"));
951 	return ucls_super_ref;
952     }
953   else
954     {
955       if (!uucls_super_ref)
956 	uucls_super_ref =
957 		objc_build_component_ref (imp->meta_decl,
958 					  get_identifier ("super_class"));
959 	return uucls_super_ref;
960     }
961 }
962 
963 static tree
964 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
965 					   struct imp_entry *imp, bool inst_meth)
966 {
967   tree super_name = CLASS_SUPER_NAME (imp->imp_template);
968   tree super_class;
969 
970   if (!flag_zero_link)
971     {
972       super_class = objc_get_class_reference (super_name);
973 
974       if (!inst_meth)
975 
976 	/* If we are in a class method, we must retrieve the
977 	   _metaclass_ for the current class, pointed at by
978 	   the class's "isa" pointer.  The following assumes that
979 	   "isa" is the first ivar in a class (which it must be).  */
980 	   super_class =
981 		build_indirect_ref (input_location,
982 				    build_c_cast (input_location,
983 					build_pointer_type (objc_class_type),
984 					super_class),
985 				    RO_UNARY_STAR);
986       return super_class;
987     }
988 
989   /* else do it the slow way.  */
990   add_class_reference (super_name);
991   super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
992   super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
993 					IDENTIFIER_POINTER (super_name));
994   /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
995   return build_function_call (input_location,
996 			      super_class,
997 			      build_tree_list (NULL_TREE, super_name));
998 }
999 
1000 static bool
1001 next_runtime_abi_01_setup_const_string_class_decl (void)
1002 {
1003   if (!constant_string_global_id)
1004     {
1005       /* Hopefully, this should not represent a serious limitation.  */
1006       char buf[BUFSIZE];
1007       snprintf (buf, BUFSIZE, "_%sClassReference", constant_string_class_name);
1008       constant_string_global_id = get_identifier (buf);
1009     }
1010 
1011   string_class_decl = lookup_name (constant_string_global_id);
1012 
1013   return (string_class_decl != NULL_TREE);
1014 }
1015 
1016 static tree
1017 next_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
1018 						   int length)
1019 {
1020   tree constructor, fields, var;
1021   vec<constructor_elt, va_gc> *v = NULL;
1022 
1023   /* NeXT:   (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length })   */
1024   fields = TYPE_FIELDS (internal_const_str_type);
1025   CONSTRUCTOR_APPEND_ELT (v, fields,
1026 			  build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1027 
1028   fields = DECL_CHAIN (fields);
1029   CONSTRUCTOR_APPEND_ELT (v, fields,
1030 			  build_unary_op (loc, ADDR_EXPR, string, 1));
1031 
1032   /* ??? check if this should be long.  */
1033   fields = DECL_CHAIN (fields);
1034   CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1035   constructor = objc_build_constructor (internal_const_str_type, v);
1036 
1037   var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1038   DECL_INITIAL (var) = constructor;
1039   TREE_STATIC (var) = 1;
1040   DECL_CONTEXT (var) = NULL;
1041   OBJCMETA (var, objc_meta, meta_const_str);
1042   return var;
1043 }
1044 
1045 /* ---  metadata templates --- */
1046 
1047 /* This routine builds the following type:
1048    struct _prop_t {
1049      const char * const name;			// property name
1050      const char * const attributes;		// comma-delimited, encoded,
1051 						// property attributes
1052    };
1053 */
1054 
1055 static GTY(()) tree objc_v1_property_template;
1056 
1057 static tree
1058 build_v1_property_template (void)
1059 {
1060   tree prop_record;
1061   tree decls, *chain = NULL;
1062 
1063   prop_record = objc_start_struct (get_identifier ("_prop_t"));
1064   /* const char * name */
1065   decls = add_field_decl (string_type_node, "name", &chain);
1066 
1067   /* const char * attribute */
1068   add_field_decl (string_type_node, "attribute", &chain);
1069 
1070   objc_finish_struct (prop_record, decls);
1071   return prop_record;
1072 }
1073 
1074 /* Build the following type:
1075 
1076   struct _objc_protocol_extension
1077     {
1078       uint32_t size;	// sizeof (struct _objc_protocol_extension)
1079       struct objc_method_list	*optional_instance_methods;
1080       struct objc_method_list   *optional_class_methods;
1081       struct objc_prop_list	*instance_properties;
1082     }
1083 */
1084 
1085 static GTY(()) tree objc_protocol_extension_template;
1086 
1087 static void
1088 build_v1_objc_protocol_extension_template (void)
1089 {
1090   tree decls, *chain = NULL;
1091 
1092   objc_protocol_extension_template =
1093 	objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT));
1094 
1095   /*  uint32_t size; */
1096   decls = add_field_decl (integer_type_node, "size", &chain);
1097 
1098   /* struct objc_method_list   *optional_instance_methods; */
1099   add_field_decl (objc_method_list_ptr, "optional_instance_methods", &chain);
1100 
1101   /* struct objc_method_list   *optional_class_methods; */
1102   add_field_decl (objc_method_list_ptr, "optional_class_methods", &chain);
1103 
1104   /* struct objc_prop_list     *instance_properties; */
1105   add_field_decl (objc_prop_list_ptr, "instance_properties", &chain);
1106 
1107   objc_finish_struct (objc_protocol_extension_template, decls);
1108 }
1109 
1110 /* This routine build following struct type:
1111    struct _objc_class_ext
1112      {
1113        uint32_t size;	// sizeof(struct _objc_class_ext)
1114        const char *weak_ivar_layout;
1115        struct _prop_list_t *properties;
1116      }
1117 */
1118 
1119 static GTY(()) tree objc_class_ext_template;
1120 
1121 static void
1122 build_objc_class_ext_template (void)
1123 {
1124   tree ptrt, decls, *chain = NULL;
1125 
1126   objc_class_ext_template = objc_start_struct (get_identifier (UTAG_CLASS_EXT));
1127 
1128   /* uint32_t size; */
1129   decls = add_field_decl (integer_type_node, "size", &chain);
1130 
1131   /* const char *weak_ivar_layout; */
1132   add_field_decl (const_string_type_node, "weak_ivar_layout", &chain);
1133 
1134   /* struct _prop_list_t *properties; */
1135   ptrt = build_pointer_type (xref_tag (RECORD_TYPE,
1136 			     get_identifier(UTAG_PROPERTY_LIST)));
1137   add_field_decl (ptrt, "properties", &chain);
1138 
1139   objc_finish_struct (objc_class_ext_template, decls);
1140 }
1141 
1142 static void
1143 build_metadata_templates (void)
1144 {
1145 
1146   if (!objc_method_template)
1147     objc_method_template = build_method_template ();
1148 
1149 
1150 
1151 }
1152 
1153 /* --- emit metadata --- */
1154 
1155 static tree
1156 generate_v1_meth_descriptor_table (tree chain, tree protocol,
1157 				   const char *prefix, tree attr)
1158 {
1159   tree method_list_template, initlist, decl;
1160   int size;
1161   vec<constructor_elt, va_gc> *v = NULL;
1162   char buf[BUFSIZE];
1163 
1164   if (!chain || !prefix)
1165     return NULL_TREE;
1166 
1167   if (!objc_method_prototype_template)
1168     objc_method_prototype_template = build_method_prototype_template ();
1169 
1170   size = list_length (chain);
1171   method_list_template =
1172 	build_method_prototype_list_template (objc_method_prototype_template,
1173 					      size);
1174   snprintf (buf, BUFSIZE, "%s_%s", prefix,
1175 	    IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1176 
1177   decl = start_var_decl (method_list_template, buf);
1178 
1179   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1180   initlist =
1181 	build_descriptor_table_initializer (objc_method_prototype_template,
1182 					    chain);
1183   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1184   /* Get into the right section.  */
1185   OBJCMETA (decl, objc_meta, attr);
1186   finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1187   return decl;
1188 }
1189 
1190 /* Build protocol ext =
1191    {size, opt_instance_meth, opt_class_meth, instance_props};
1192    or NULL_TREE if none are present.  */
1193 
1194 static tree
1195 generate_v1_objc_protocol_extension (tree proto_interface,
1196 				     tree opt_instance_meth,
1197 				     tree opt_class_meth,
1198 				     tree instance_props)
1199 {
1200   int size;
1201   location_t loc;
1202   vec<constructor_elt, va_gc> *v = NULL;
1203   tree decl, expr;
1204   char buf[BUFSIZE];
1205 
1206   /* If there are no extensions, then don't bother... */
1207   if (!opt_instance_meth && !opt_class_meth && !instance_props)
1208     return NULL_TREE;
1209 
1210   if (!objc_protocol_extension_template)
1211     build_v1_objc_protocol_extension_template ();
1212 
1213   /* uint32_t size */
1214   size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template));
1215   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1216 
1217   /* Try for meaningful diagnostics.  */
1218   loc = DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface));
1219 
1220   /* struct objc_method_list *optional_instance_methods; */
1221   if (opt_instance_meth)
1222     expr = convert (objc_method_list_ptr,
1223 		    build_unary_op (loc, ADDR_EXPR, opt_instance_meth, 0));
1224   else
1225     expr = convert (objc_method_list_ptr, null_pointer_node);
1226 
1227   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1228 
1229   /* struct objc_method_list *optional_class_methods; */
1230   if (opt_class_meth)
1231     expr = convert (objc_method_list_ptr,
1232 		    build_unary_op (loc, ADDR_EXPR, opt_class_meth, 0));
1233   else
1234     expr = convert (objc_method_list_ptr, null_pointer_node);
1235 
1236   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1237   /* struct objc_prop_list *instance_properties; */
1238   if (instance_props)
1239       expr = convert (objc_prop_list_ptr,
1240 		      build_unary_op (loc, ADDR_EXPR, instance_props, 0));
1241   else
1242     expr = convert (objc_prop_list_ptr, null_pointer_node);
1243 
1244   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1245   snprintf (buf, BUFSIZE, "_OBJC_ProtocolExt_%s",
1246 	    IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface)));
1247 
1248   decl = start_var_decl (objc_protocol_extension_template, buf);
1249   expr = objc_build_constructor (TREE_TYPE (decl), v);
1250   OBJCMETA (decl, objc_meta, meta_protocol_extension);
1251   finish_var_decl (decl, expr);
1252   return decl;
1253 }
1254 
1255 /* This routine builds the following type:
1256    struct _prop_list_t {
1257      uint32_t entsize;			// sizeof (struct _prop_t)
1258      uint32_t prop_count;
1259      struct _prop_t prop_list [prop_count];
1260    }
1261 */
1262 
1263 static tree
1264 build_v1_property_list_template (tree list_type, int size)
1265 {
1266   tree property_list_t_record;
1267   tree array_type, decls, *chain = NULL;
1268 
1269   /* anonymous.  */
1270   property_list_t_record = objc_start_struct (NULL_TREE);
1271 
1272   /* uint32_t const entsize */
1273   decls = add_field_decl (integer_type_node, "entsize", &chain);
1274 
1275   /* int prop_count */
1276   add_field_decl (integer_type_node, "prop_count", &chain);
1277 
1278   /* struct _prop_t prop_list[]; */
1279   array_type = build_sized_array_type (list_type, size);
1280   add_field_decl (array_type, "prop_list", &chain);
1281 
1282   objc_finish_struct (property_list_t_record, decls);
1283   return property_list_t_record;
1284 }
1285 
1286 /* This routine builds the initializer list to initialize the
1287    'struct _prop_t prop_list[]'  field of 'struct _prop_list_t' meta-data. */
1288 
1289 static tree
1290 build_v1_property_table_initializer (tree type, tree context)
1291 {
1292   tree x;
1293   vec<constructor_elt, va_gc> *inits = NULL;
1294 
1295   if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
1296     x = CLASS_PROPERTY_DECL (context);
1297   else
1298     x = IMPL_PROPERTY_DECL (context);
1299 
1300   for (; x; x = TREE_CHAIN (x))
1301     {
1302       vec<constructor_elt, va_gc> *elemlist = NULL;
1303       tree attribute, name_ident = PROPERTY_NAME (x);
1304 
1305       CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
1306 			      add_objc_string (name_ident, prop_names_attr));
1307 
1308       attribute = objc_v2_encode_prop_attr (x);
1309       CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
1310 			      add_objc_string (attribute, prop_names_attr));
1311 
1312       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
1313 			      objc_build_constructor (type, elemlist));
1314     }
1315 
1316   return objc_build_constructor (build_array_type (type, 0),inits);
1317 }
1318 
1319 /* This routine builds the 'struct _prop_list_t' variable declaration and
1320    initializes it with its initializer list. TYPE is 'struct _prop_list_t',
1321    NAME is the internal name of this variable, SIZE is number of properties
1322    for this class and LIST is the initializer list for its 'prop_list' field. */
1323 
1324 static tree
1325 generate_v1_property_table (tree context, tree klass_ctxt)
1326 {
1327   tree x, decl, initlist, property_list_template;
1328   bool is_proto = false;
1329   vec<constructor_elt, va_gc> *inits = NULL;
1330   int init_val, size = 0;
1331   char buf[BUFSIZE];
1332 
1333   if (context)
1334     {
1335       gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
1336       x = CLASS_PROPERTY_DECL (context);
1337       is_proto = true;
1338     }
1339   else
1340     x = IMPL_PROPERTY_DECL (klass_ctxt);
1341 
1342   for (; x; x = TREE_CHAIN (x))
1343     size++;
1344 
1345   if (size == 0)
1346     return NULL_TREE;
1347 
1348   if (!objc_v1_property_template)
1349     objc_v1_property_template = build_v1_property_template ();
1350 
1351   property_list_template =
1352 	build_v1_property_list_template (objc_v1_property_template,
1353 					 size);
1354   initlist = build_v1_property_table_initializer (objc_v1_property_template,
1355 						  is_proto ? context
1356 							   : klass_ctxt);
1357 
1358   init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template));
1359   if (is_proto)
1360     snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
1361 	      IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
1362   else
1363     snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
1364 	      IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
1365 
1366   decl = start_var_decl (property_list_template, buf);
1367   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, init_val));
1368   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1369   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1370   x = objc_build_constructor (TREE_TYPE (decl), inits);
1371   OBJCMETA (decl, objc_meta, meta_proplist);
1372   finish_var_decl (decl, x);
1373   return decl;
1374 }
1375 
1376 static tree
1377 generate_v1_protocol_list (tree i_or_p, tree klass_ctxt)
1378 {
1379   tree array_type, ptype, refs_decl, lproto, e, plist, attr;
1380   int size = 0;
1381   vec<constructor_elt, va_gc> *v = NULL;
1382   char buf[BUFSIZE];
1383 
1384   switch (TREE_CODE (i_or_p))
1385     {
1386     case CLASS_INTERFACE_TYPE:
1387     case CATEGORY_INTERFACE_TYPE:
1388       plist = CLASS_PROTOCOL_LIST (i_or_p);
1389       break;
1390     case PROTOCOL_INTERFACE_TYPE:
1391       plist = PROTOCOL_LIST (i_or_p);
1392       break;
1393     default:
1394       gcc_unreachable ();
1395     }
1396 
1397   /* Compute size.  */
1398   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1399     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1400 	&& PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1401       size++;
1402 
1403   /* Build initializer.  */
1404   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1405   e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1406   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1407 
1408   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1409     {
1410       tree pval = TREE_VALUE (lproto);
1411 
1412       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1413 	  && PROTOCOL_FORWARD_DECL (pval))
1414 	{
1415 	  tree fwref = PROTOCOL_FORWARD_DECL (pval);
1416 	  location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1417 	  e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1418           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1419 	}
1420     }
1421 
1422   /* static struct objc_protocol *refs[n]; */
1423   switch (TREE_CODE (i_or_p))
1424     {
1425     case PROTOCOL_INTERFACE_TYPE:
1426       snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1427 		IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1428       attr = meta_proto_ref;
1429       break;
1430     case CLASS_INTERFACE_TYPE:
1431       snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1432 		IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1433       attr = meta_clas_prot;
1434       break;
1435     case CATEGORY_INTERFACE_TYPE:
1436       snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1437 		IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1438 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1439       attr = meta_catg_prot;
1440       break;
1441     default:
1442       gcc_unreachable ();
1443     }
1444 
1445   ptype = build_pointer_type (objc_protocol_template);
1446   array_type = build_sized_array_type (ptype, size + 3);
1447   refs_decl = start_var_decl (array_type, buf);
1448 
1449   OBJCMETA (refs_decl, objc_meta, attr);
1450   finish_var_decl (refs_decl,
1451                    objc_build_constructor (TREE_TYPE (refs_decl), v));
1452 
1453   return refs_decl;
1454 }
1455 
1456 static tree
1457 build_v1_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1458 			       tree inst_methods, tree class_methods,
1459 			       tree protocol_ext)
1460 {
1461   tree expr, ttyp;
1462   location_t loc;
1463   vec<constructor_elt, va_gc> *inits = NULL;
1464 
1465   if (!objc_protocol_extension_template)
1466     build_v1_objc_protocol_extension_template ();
1467 
1468   /* TODO: find a better representation of location from the inputs.  */
1469   loc = UNKNOWN_LOCATION;
1470   ttyp = build_pointer_type (objc_protocol_extension_template);
1471   /* Instead of jamming the protocol version number into the isa, we pass
1472      either a pointer to the protocol extension - or NULL.  */
1473   if (protocol_ext)
1474     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, protocol_ext, 0));
1475   else
1476     expr = convert (ttyp, null_pointer_node);
1477 
1478   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1479   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1480   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1481 
1482   ttyp = objc_method_proto_list_ptr;
1483   if (inst_methods)
1484     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1485   else
1486     expr = convert (ttyp, null_pointer_node);
1487   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1488 
1489   if (class_methods)
1490     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1491   else
1492     expr = convert (ttyp, null_pointer_node);
1493   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1494 
1495   return objc_build_constructor (type, inits);
1496 }
1497 
1498 /* An updated version of generate_protocols () that emit the protocol
1499    extension for ABI=1.  */
1500 
1501 /* For each protocol which was referenced either from a @protocol()
1502    expression, or because a class/category implements it (then a
1503    pointer to the protocol is stored in the struct describing the
1504    class/category), we create a statically allocated instance of the
1505    Protocol class.  The code is written in such a way as to generate
1506    as few Protocol objects as possible; we generate a unique Protocol
1507    instance for each protocol, and we don't generate a Protocol
1508    instance if the protocol is never referenced (either from a
1509    @protocol() or from a class/category implementation).  These
1510    statically allocated objects can be referred to via the static
1511    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1512 
1513    The statically allocated Protocol objects that we generate here
1514    need to be fixed up at runtime in order to be used: the 'isa'
1515    pointer of the objects need to be set up to point to the 'Protocol'
1516    class, as known at runtime.
1517 
1518    The NeXT runtime fixes up all protocols at program startup time,
1519    before main() is entered.  It uses a low-level trick to look up all
1520    those symbols, then loops on them and fixes them up.  */
1521 
1522 /* TODO: finish getting rid of passing stuff around in globals.  */
1523 
1524 static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl;
1525 static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl;
1526 static GTY(()) tree V1_ProtocolExt_decl;
1527 static GTY(()) tree V1_Property_decl;
1528 
1529 static void
1530 generate_v1_protocols (void)
1531 {
1532   tree p;
1533 
1534   /* If a protocol was directly referenced, pull in indirect references.  */
1535   for (p = protocol_chain; p; p = TREE_CHAIN (p))
1536     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1537       generate_protocol_references (PROTOCOL_LIST (p));
1538 
1539   for (p = protocol_chain; p; p = TREE_CHAIN (p))
1540     {
1541       tree decl, encoding, initlist, protocol_name_expr;
1542       tree refs_type, refs_decl, refs_expr;
1543       location_t loc;
1544       tree nst_methods = PROTOCOL_NST_METHODS (p);
1545       tree cls_methods = PROTOCOL_CLS_METHODS (p);
1546 
1547       /* If protocol wasn't referenced, don't generate any code.  */
1548       decl = PROTOCOL_FORWARD_DECL (p);
1549 
1550       if (!decl)
1551 	continue;
1552 
1553       /* Make sure we link in the Protocol class.  */
1554       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1555 
1556       while (nst_methods)
1557 	{
1558 	  if (! METHOD_ENCODING (nst_methods))
1559 	    {
1560 	      encoding = encode_method_prototype (nst_methods);
1561 	      METHOD_ENCODING (nst_methods) = encoding;
1562 	    }
1563 	  nst_methods = TREE_CHAIN (nst_methods);
1564 	}
1565 
1566       UOBJC_INSTANCE_METHODS_decl =
1567 	generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1568 					   "_OBJC_ProtocolInstanceMethods",
1569 					   meta_proto_nst_meth);
1570 
1571       while (cls_methods)
1572 	{
1573 	  if (! METHOD_ENCODING (cls_methods))
1574 	    {
1575 	      encoding = encode_method_prototype (cls_methods);
1576 	      METHOD_ENCODING (cls_methods) = encoding;
1577 	    }
1578 
1579 	  cls_methods = TREE_CHAIN (cls_methods);
1580 	}
1581 
1582       UOBJC_CLASS_METHODS_decl =
1583 	generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1584 					   "_OBJC_ProtocolClassMethods",
1585 					   meta_proto_cls_meth);
1586 
1587       /* There should be no optional methods for ABI-0 - but we need to
1588          check all this here before the lists are made.  */
1589       nst_methods = PROTOCOL_OPTIONAL_NST_METHODS (p);
1590       while (nst_methods)
1591         {
1592           if (! METHOD_ENCODING (nst_methods))
1593             {
1594               encoding = encode_method_prototype (nst_methods);
1595               METHOD_ENCODING (nst_methods) = encoding;
1596             }
1597           nst_methods = TREE_CHAIN (nst_methods);
1598         }
1599 
1600       V1_Protocol_OPT_NST_METHODS_decl =
1601 	generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
1602 					   "_OBJC_OptionalProtocolInstanceMethods",
1603 					   meta_proto_nst_meth);
1604 
1605       cls_methods = PROTOCOL_OPTIONAL_CLS_METHODS (p);
1606       while (cls_methods)
1607         {
1608           if (! METHOD_ENCODING (cls_methods))
1609             {
1610               encoding = encode_method_prototype (cls_methods);
1611               METHOD_ENCODING (cls_methods) = encoding;
1612             }
1613 
1614           cls_methods = TREE_CHAIN (cls_methods);
1615         }
1616 
1617       V1_Protocol_OPT_CLS_METHODS_decl =
1618 	generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
1619 					   "_OBJC_OptionalProtocolClassMethods",
1620 					   meta_proto_cls_meth);
1621 
1622       if (PROTOCOL_LIST (p))
1623 	refs_decl = generate_v1_protocol_list (p, objc_implementation_context);
1624       else
1625 	refs_decl = 0;
1626 
1627       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1628       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1629       /* TODO: more locations to be fixed up... */
1630       loc = UNKNOWN_LOCATION;
1631       refs_type =
1632 	build_pointer_type (build_pointer_type (objc_protocol_template));
1633       if (refs_decl)
1634 	refs_expr = convert (refs_type,
1635 			     build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
1636       else
1637         refs_expr = convert (refs_type, null_pointer_node);
1638 
1639       if (flag_objc_abi < 1)
1640 	{
1641 	  /* Original ABI.  */
1642 	  initlist =
1643 		build_protocol_initializer (TREE_TYPE (decl),
1644 					    protocol_name_expr, refs_expr,
1645 					    UOBJC_INSTANCE_METHODS_decl,
1646 					    UOBJC_CLASS_METHODS_decl);
1647 	  finish_var_decl (decl, initlist);
1648           continue;
1649 	}
1650 
1651       /* else - V1 extensions.  */
1652 
1653       V1_Property_decl =
1654 		generate_v1_property_table (p, NULL_TREE);
1655 
1656       V1_ProtocolExt_decl =
1657 	generate_v1_objc_protocol_extension (p,
1658 					     V1_Protocol_OPT_NST_METHODS_decl,
1659 					     V1_Protocol_OPT_CLS_METHODS_decl,
1660 					     V1_Property_decl);
1661 
1662       initlist = build_v1_protocol_initializer (TREE_TYPE (decl),
1663 						protocol_name_expr, refs_expr,
1664 						UOBJC_INSTANCE_METHODS_decl,
1665 						UOBJC_CLASS_METHODS_decl,
1666 						V1_ProtocolExt_decl);
1667       finish_var_decl (decl, initlist);
1668     }
1669 }
1670 
1671 static tree
1672 generate_dispatch_table (tree chain, const char *name, tree attr)
1673 {
1674   tree decl, method_list_template, initlist;
1675   vec<constructor_elt, va_gc> *v = NULL;
1676   int size;;
1677 
1678   if (!chain || !name || !(size = list_length (chain)))
1679     return NULL_TREE;
1680 
1681   if (!objc_method_template)
1682     objc_method_template = build_method_template ();
1683 
1684   method_list_template = build_method_list_template (objc_method_template,
1685 						     size);
1686   initlist = build_dispatch_table_initializer (objc_method_template, chain);
1687 
1688   decl = start_var_decl (method_list_template, name);
1689 
1690   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1691   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1692 			  build_int_cst (integer_type_node, size));
1693   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1694 
1695   OBJCMETA (decl, objc_meta, attr);
1696   finish_var_decl (decl,
1697 		   objc_build_constructor (TREE_TYPE (decl), v));
1698 
1699   return decl;
1700 }
1701 
1702 /* Init a category.  */
1703 static tree
1704 build_v1_category_initializer (tree type, tree cat_name, tree class_name,
1705 				tree inst_methods, tree class_methods,
1706 				tree protocol_list, tree property_list,
1707 				location_t loc)
1708 {
1709   tree expr, ltyp;
1710   vec<constructor_elt, va_gc> *v = NULL;
1711 
1712   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1713   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1714 
1715   ltyp = objc_method_list_ptr;
1716   if (inst_methods)
1717     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1718   else
1719     expr = convert (ltyp, null_pointer_node);
1720   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1721 
1722   if (class_methods)
1723     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1724   else
1725     expr = convert (ltyp, null_pointer_node);
1726   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1727 
1728   /* protocol_list = */
1729   ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1730   if (protocol_list)
1731     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1732   else
1733     expr = convert (ltyp, null_pointer_node);
1734   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1735 
1736   if (flag_objc_abi >= 1)
1737     {
1738       int val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template));
1739       expr = build_int_cst (NULL_TREE, val);
1740       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1741       ltyp = objc_prop_list_ptr;
1742       if (property_list)
1743 	expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
1744       else
1745 	expr = convert (ltyp, null_pointer_node);
1746       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1747     }
1748 
1749   return objc_build_constructor (type, v);
1750 }
1751 
1752 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1753 /* TODO: get rid of passing stuff around in globals.  */
1754 static void
1755 generate_v1_category (struct imp_entry *impent)
1756 {
1757   tree initlist, cat_name_expr, class_name_expr;
1758   tree protocol_decl, category, cat_decl;
1759   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1760   tree cat = impent->imp_context;
1761   location_t loc;
1762   char buf[BUFSIZE];
1763 
1764   cat_decl = impent->class_decl;
1765   loc = DECL_SOURCE_LOCATION (cat_decl);
1766 
1767   add_class_reference (CLASS_NAME (cat));
1768   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1769   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1770 
1771   category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1772 
1773   if (category && CLASS_PROTOCOL_LIST (category))
1774     {
1775       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1776       protocol_decl = generate_v1_protocol_list (category, cat);
1777     }
1778   else
1779     protocol_decl = 0;
1780 
1781   if (flag_objc_abi >= 1)
1782     V1_Property_decl = generate_v1_property_table (NULL_TREE, cat);
1783   else
1784     V1_Property_decl = NULL_TREE;
1785 
1786   if (CLASS_NST_METHODS (cat))
1787     {
1788       snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1789 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
1790 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1791       inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf,
1792 					      meta_cati_meth);
1793     }
1794 
1795   if (CLASS_CLS_METHODS (cat))
1796     {
1797       snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1798 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
1799 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1800       class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf,
1801 					       meta_catc_meth);
1802     }
1803 
1804   initlist = build_v1_category_initializer (TREE_TYPE (cat_decl),
1805 					    cat_name_expr, class_name_expr,
1806 					    inst_methods, class_methods,
1807 					    protocol_decl, V1_Property_decl,
1808 					    loc);
1809 
1810   finish_var_decl (cat_decl, initlist);
1811   impent->class_decl = cat_decl;
1812 }
1813 
1814 /* This routine builds the class extension used by v1 NeXT.  */
1815 
1816 static tree
1817 generate_objc_class_ext (tree property_list, tree context)
1818 {
1819   tree decl, expr, ltyp;
1820   tree weak_ivar_layout_tree;
1821   int size;
1822   location_t loc;
1823   vec<constructor_elt, va_gc> *v = NULL;
1824   char buf[BUFSIZE];
1825 
1826   /* TODO: pass the loc in or find it from args.  */
1827   loc = UNKNOWN_LOCATION;
1828 
1829   /* const char *weak_ivar_layout
1830      TODO: Figure the ivar layouts out... */
1831   weak_ivar_layout_tree = NULL_TREE;
1832 
1833   if (!property_list && !weak_ivar_layout_tree)
1834     return NULL_TREE;
1835 
1836   if (!objc_class_ext_template)
1837     build_objc_class_ext_template ();
1838 
1839   /* uint32_t size */
1840   size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template));
1841   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1842 
1843   ltyp = const_string_type_node;
1844   if (weak_ivar_layout_tree)
1845     expr = convert (ltyp, weak_ivar_layout_tree);
1846   else
1847     expr = convert (ltyp, null_pointer_node);
1848   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1849 
1850   /* struct _prop_list_t *properties; */
1851   ltyp = objc_prop_list_ptr;
1852   if (property_list)
1853      expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
1854   else
1855     expr = convert (ltyp, null_pointer_node);
1856   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1857 
1858   snprintf (buf, BUFSIZE, "_OBJC_ClassExt_%s",
1859 	    IDENTIFIER_POINTER (CLASS_NAME (context)));
1860   decl = start_var_decl (objc_class_ext_template, buf);
1861   expr = objc_build_constructor (TREE_TYPE (decl), v);
1862   OBJCMETA (decl, objc_meta, meta_class_extension);
1863   finish_var_decl (decl, expr);
1864   return decl;
1865 }
1866 
1867 /* struct _objc_class {
1868      struct objc_class *isa;
1869      struct objc_class *super_class;
1870      char *name;
1871      long version;
1872      long info;
1873      long instance_size;
1874      struct objc_ivar_list *ivars;
1875      struct objc_method_list *methods;
1876      struct objc_cache *cache;
1877      struct objc_protocol_list *protocols;
1878   #if ABI >= 1
1879      const char *ivar_layout;
1880      struct _objc_class_ext *ext;
1881   #else
1882      void *sel_id;
1883      void *gc_object_type;
1884   #endif
1885    }; */
1886 
1887 static tree
1888 build_v1_shared_structure_initializer (tree type, tree isa, tree super,
1889 				    tree name, tree size, int status,
1890 				    tree dispatch_table, tree ivar_list,
1891 				    tree protocol_list, tree class_ext)
1892 {
1893   tree expr, ltyp;
1894   location_t loc;
1895   vec<constructor_elt, va_gc> *v = NULL;
1896 
1897   /* TODO: fish the location out of the input data.  */
1898   loc = UNKNOWN_LOCATION;
1899 
1900   /* isa = */
1901   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1902 
1903   /* super_class = */
1904   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1905 
1906   /* name = */
1907   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1908 
1909   /* version = */
1910   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1911                           build_int_cst (long_integer_type_node, 0));
1912 
1913   /* info = */
1914   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1915                           build_int_cst (long_integer_type_node, status));
1916 
1917   /* instance_size = */
1918   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1919                           convert (long_integer_type_node, size));
1920 
1921   /* objc_ivar_list = */
1922   ltyp = objc_ivar_list_ptr;
1923   if (ivar_list)
1924     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivar_list, 0));
1925   else
1926     expr = convert (ltyp, null_pointer_node);
1927   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1928 
1929   /* objc_method_list = */
1930   ltyp = objc_method_list_ptr;
1931   if (dispatch_table)
1932     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, dispatch_table, 0));
1933   else
1934     expr = convert (ltyp, null_pointer_node);
1935   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1936 
1937   ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
1938 					get_identifier ("objc_cache")));
1939   /* method_cache = */
1940   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
1941 
1942   /* protocol_list = */
1943   ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1944   if (protocol_list)
1945     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR,  protocol_list, 0));
1946   else
1947     expr = convert (ltyp, null_pointer_node);
1948   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1949 
1950   if (flag_objc_abi >= 1)
1951     {
1952       /* TODO: figure out the ivar_layout stuff.  */
1953       expr = convert (const_string_type_node, null_pointer_node);
1954       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1955       if (!objc_class_ext_template)
1956 	build_objc_class_ext_template ();
1957       ltyp = build_pointer_type (objc_class_ext_template);
1958       if (class_ext)
1959 	expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_ext, 0));
1960       else
1961 	expr = convert (ltyp, null_pointer_node);
1962       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1963     }
1964   else
1965     {
1966       /* sel_id = NULL */
1967       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
1968 
1969       /* gc_object_type = NULL */
1970       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
1971     }
1972   return objc_build_constructor (type, v);
1973 }
1974 
1975 static tree
1976 generate_ivars_list (tree chain, const char *name, tree attr)
1977 {
1978   tree initlist, ivar_list_template, decl;
1979   int size;
1980   vec<constructor_elt, va_gc> *inits = NULL;
1981 
1982   if (!chain)
1983     return NULL_TREE;
1984 
1985   if (!objc_ivar_template)
1986     objc_ivar_template = build_ivar_template ();
1987 
1988   size = ivar_list_length (chain);
1989 
1990   generating_instance_variables = 1;
1991   ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1992   initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1993   generating_instance_variables = 0;
1994 
1995   decl = start_var_decl (ivar_list_template, name);
1996 
1997   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1998   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1999 
2000   OBJCMETA (decl, objc_meta, attr);
2001   finish_var_decl (decl,
2002 		   objc_build_constructor (TREE_TYPE (decl), inits));
2003 
2004   return decl;
2005 }
2006 
2007 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
2008    static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2009 
2010 static void
2011 generate_v1_class_structs (struct imp_entry *impent)
2012 {
2013   tree name_expr, super_expr, root_expr, class_decl, meta_decl;
2014   tree my_root_id, my_super_id;
2015   tree cast_type, initlist, protocol_decl;
2016   tree class_ext_decl = NULL_TREE, props = NULL_TREE;
2017   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2018   tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
2019   int cls_flags;
2020   location_t loc;
2021   char buf[BUFSIZE];
2022 
2023 /*  objc_implementation_context = impent->imp_context;
2024   implementation_template = impent->imp_template;*/
2025   class_decl = impent->class_decl;
2026   meta_decl = impent->meta_decl;
2027   cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
2028 
2029   loc = DECL_SOURCE_LOCATION (impent->class_decl);
2030 
2031   if (flag_objc_abi >= 1)
2032     {
2033       /* ABI=1 additions.  */
2034       props = generate_v1_property_table (NULL_TREE, impent->imp_context);
2035       class_ext_decl = generate_objc_class_ext (props, impent->imp_context);
2036     }
2037 
2038   my_super_id = CLASS_SUPER_NAME (impent->imp_template);
2039   if (my_super_id)
2040     {
2041       add_class_reference (my_super_id);
2042 
2043       /* Compute "my_root_id" - this is required for code generation.
2044          the "isa" for all meta class structures points to the root of
2045          the inheritance hierarchy (e.g. "__Object")...  */
2046       my_root_id = my_super_id;
2047       do
2048 	{
2049 	  tree my_root_int = lookup_interface (my_root_id);
2050 
2051 	  if (my_root_int && CLASS_SUPER_NAME (my_root_int))
2052 	    my_root_id = CLASS_SUPER_NAME (my_root_int);
2053 	  else
2054 	    break;
2055 	}
2056       while (1);
2057       super_expr = add_objc_string (my_super_id, class_names);
2058     }
2059   else
2060     {
2061       /* No super class.  */
2062       my_root_id = CLASS_NAME (impent->imp_template);
2063       super_expr = null_pointer_node;
2064     }
2065 
2066   /* Install class `isa' and `super' pointers at runtime.  */
2067   cast_type = build_pointer_type (objc_class_template);
2068   super_expr = build_c_cast (loc, cast_type, super_expr);
2069 
2070   root_expr = add_objc_string (my_root_id, class_names);
2071   root_expr = build_c_cast (loc, cast_type, root_expr);
2072 
2073   if (CLASS_PROTOCOL_LIST (impent->imp_template))
2074     {
2075       generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
2076       protocol_decl = generate_v1_protocol_list (impent->imp_template,
2077 						 impent->imp_context);
2078     }
2079   else
2080     protocol_decl = NULL_TREE;
2081 
2082   if (CLASS_CLS_METHODS (impent->imp_context))
2083     {
2084       snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
2085 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2086       class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
2087 					       buf, meta_clac_meth);
2088     }
2089 
2090   if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
2091       && (chain = TYPE_FIELDS (objc_class_template)))
2092     {
2093       snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
2094 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2095       class_ivars = generate_ivars_list (chain, buf, meta_clac_vars);
2096     }
2097   /* TODO: get rid of hidden passing of stuff in globals.  */
2098   /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists().  */
2099 
2100   name_expr = add_objc_string (CLASS_NAME (impent->imp_template), class_names);
2101 
2102   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2103 
2104   initlist = build_v1_shared_structure_initializer
2105 		(TREE_TYPE (meta_decl),
2106 		root_expr, super_expr, name_expr,
2107 		convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
2108 		CLS_META, class_methods, class_ivars,
2109 		protocol_decl, NULL_TREE);
2110 
2111   finish_var_decl (meta_decl, initlist);
2112   impent->meta_decl = meta_decl;
2113 
2114   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2115   if (CLASS_NST_METHODS (impent->imp_context))
2116     {
2117       snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
2118 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2119       inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
2120 					      buf, meta_clai_meth);
2121     }
2122 
2123   if ((chain = CLASS_IVARS (impent->imp_template)))
2124     {
2125       snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
2126 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2127       inst_ivars = generate_ivars_list (chain, buf, meta_clai_vars);
2128     }
2129 
2130   initlist = build_v1_shared_structure_initializer
2131 		(TREE_TYPE (class_decl),
2132 		build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
2133 		super_expr, name_expr,
2134 		convert (integer_type_node,
2135 			 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent->imp_template))),
2136 		CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
2137 		protocol_decl, class_ext_decl);
2138 
2139   finish_var_decl (class_decl, initlist);
2140   impent->class_decl = class_decl;
2141 }
2142 
2143 /* --- Output NeXT V1 Metadata --- */
2144 
2145 /* Create the initial value for the `defs' field of _objc_symtab.
2146    This is a CONSTRUCTOR.  */
2147 
2148 static tree
2149 init_def_list (tree type)
2150 {
2151   tree expr;
2152   location_t loc;
2153   struct imp_entry *impent;
2154   vec<constructor_elt, va_gc> *v = NULL;
2155 
2156   if (imp_count)
2157     for (impent = imp_list; impent; impent = impent->next)
2158       {
2159 	if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2160 	  {
2161 	    loc = DECL_SOURCE_LOCATION (impent->class_decl);
2162 	    expr = build_unary_op (loc,
2163 				   ADDR_EXPR, impent->class_decl, 0);
2164 	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2165 	  }
2166       }
2167 
2168   if (cat_count)
2169     for (impent = imp_list; impent; impent = impent->next)
2170       {
2171 	if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2172 	  {
2173 	    loc = DECL_SOURCE_LOCATION (impent->class_decl);
2174 	    expr = build_unary_op (loc,
2175 				   ADDR_EXPR, impent->class_decl, 0);
2176 	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2177 	  }
2178       }
2179 
2180   return objc_build_constructor (type, v);
2181 }
2182 
2183 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
2184 
2185 /* Predefine the following data type:
2186 
2187    struct _objc_symtab
2188    {
2189      long sel_ref_cnt;
2190      SEL *refs;
2191      short cls_def_cnt;
2192      short cat_def_cnt;
2193      void *defs[cls_def_cnt + cat_def_cnt];
2194    }; */
2195 
2196 static void
2197 build_objc_symtab_template (void)
2198 {
2199   tree fields, *chain = NULL;
2200 
2201   objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
2202 
2203   /* long sel_ref_cnt; */
2204   fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
2205 
2206   /* SEL *refs; */
2207   add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
2208 
2209   /* short cls_def_cnt; */
2210   add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
2211 
2212   /* short cat_def_cnt; */
2213   add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
2214 
2215   if (imp_count || cat_count)
2216     {
2217       /* void *defs[imp_count + cat_count (+ 1)]; */
2218       /* NB: The index is one less than the size of the array.  */
2219       int index = imp_count + cat_count;
2220       tree array_type = build_sized_array_type (ptr_type_node, index);
2221       add_field_decl (array_type, "defs", &chain);
2222     }
2223 
2224   objc_finish_struct (objc_symtab_template, fields);
2225 }
2226 /* Construct the initial value for all of _objc_symtab.  */
2227 
2228 static tree
2229 init_objc_symtab (tree type)
2230 {
2231   vec<constructor_elt, va_gc> *v = NULL;
2232 
2233   /* sel_ref_cnt = { ..., 5, ... } */
2234 
2235   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2236 			  build_int_cst (long_integer_type_node, 0));
2237 
2238   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2239 
2240   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2241 			  convert (build_pointer_type (objc_selector_type),
2242 							integer_zero_node));
2243 
2244   /* cls_def_cnt = { ..., 5, ... } */
2245 
2246   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2247 			  build_int_cst (short_integer_type_node, imp_count));
2248 
2249   /* cat_def_cnt = { ..., 5, ... } */
2250 
2251   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2252 			  build_int_cst (short_integer_type_node, cat_count));
2253 
2254   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2255 
2256   if (imp_count || cat_count)
2257     {
2258       tree field = TYPE_FIELDS (type);
2259       field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2260 
2261       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2262     }
2263 
2264   return objc_build_constructor (type, v);
2265 }
2266 
2267 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2268    and initialized appropriately.  */
2269 
2270 static void
2271 generate_objc_symtab_decl (void)
2272 {
2273   build_objc_symtab_template ();
2274   UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_Symbols");
2275   /* Allow the runtime to mark meta-data such that it can be assigned to target
2276      specific sections by the back-end.  */
2277   OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_symtab);
2278   finish_var_decl (UOBJC_SYMBOLS_decl,
2279 		   init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2280 }
2281 
2282 /* Any target implementing NeXT ObjC m32 ABI has to ensure that objects
2283    refer to, and define, symbols that enforce linkage of classes into the
2284    executable image, preserving unix archive semantics.
2285 
2286    At present (4.8), the only targets implementing this are Darwin; these
2287    use top level asms to implement a scheme (see config/darwin-c.c).  The
2288    latter method is a hack, but compatible with LTO see also PR48109 for
2289    further discussion and other possible methods.  */
2290 
2291 static void
2292 handle_next_class_ref (tree chain ATTRIBUTE_UNUSED)
2293 {
2294   if (targetcm.objc_declare_unresolved_class_reference)
2295     {
2296       const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
2297       char *string = (char *) alloca (strlen (name) + 30);
2298       sprintf (string, ".objc_class_name_%s", name);
2299       targetcm.objc_declare_unresolved_class_reference (string);
2300     }
2301 }
2302 
2303 static void
2304 handle_next_impent (struct imp_entry *impent ATTRIBUTE_UNUSED)
2305 {
2306   if (targetcm.objc_declare_class_definition)
2307     {
2308       char buf[BUFSIZE];
2309 
2310       switch (TREE_CODE (impent->imp_context))
2311 	{
2312 	  case CLASS_IMPLEMENTATION_TYPE:
2313 	    snprintf (buf, BUFSIZE, ".objc_class_name_%s",
2314 		      IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2315 	    break;
2316 	  case CATEGORY_IMPLEMENTATION_TYPE:
2317 	    snprintf (buf, BUFSIZE, "*.objc_category_name_%s_%s",
2318 		      IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
2319 		      IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
2320 	    break;
2321 	  default:
2322 	    return;
2323 	}
2324       targetcm.objc_declare_class_definition (buf);
2325     }
2326 }
2327 
2328 static void
2329 generate_classref_translation_entry (tree chain)
2330 {
2331   tree expr, decl, type;
2332 
2333   decl = TREE_PURPOSE (chain);
2334   type = TREE_TYPE (decl);
2335 
2336   expr = add_objc_string (TREE_VALUE (chain), class_names);
2337   expr = convert (type, expr); /* cast! */
2338 
2339   /* This is a class reference.  It is re-written by the runtime,
2340      but will be optimized away unless we force it.  */
2341   DECL_PRESERVE_P (decl) = 1;
2342   OBJCMETA (decl, objc_meta, meta_class_reference);
2343   finish_var_decl (decl, expr);
2344   return;
2345 }
2346 
2347 static void
2348 objc_generate_v1_next_metadata (void)
2349 {
2350   struct imp_entry *impent;
2351   tree chain, attr;
2352   long vers;
2353 
2354   /* FIXME: Make sure that we generate no metadata if there is nothing
2355      to put into it.  */
2356 
2357   if (objc_static_instances)
2358     gcc_unreachable (); /* Not for NeXT */
2359 
2360   build_metadata_templates ();
2361   objc_implementation_context =
2362   implementation_template =
2363   UOBJC_CLASS_decl =
2364   UOBJC_METACLASS_decl = NULL_TREE;
2365 
2366   for (impent = imp_list; impent; impent = impent->next)
2367     {
2368 
2369       /* If -gen-decls is present, Dump the @interface of each class.
2370 	 TODO: Dump the classes in the  order they were found, rather than in
2371 	 reverse order as we are doing now.  */
2372       if (flag_gen_declaration)
2373 	dump_interface (gen_declaration_file, impent->imp_context);
2374 
2375       /* all of the following reference the string pool...  */
2376       if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2377 	generate_v1_class_structs (impent);
2378       else
2379 	generate_v1_category (impent);
2380     }
2381 
2382   /* If we are using an array of selectors, we must always
2383      finish up the array decl even if no selectors were used.  */
2384   build_next_selector_translation_table ();
2385 
2386   if (protocol_chain)
2387     generate_v1_protocols ();
2388 
2389   /* Pass summary information to the runtime.  */
2390   if (imp_count || cat_count)
2391     generate_objc_symtab_decl ();
2392 
2393   vers = OBJC_VERSION;
2394   attr = build_tree_list (objc_meta, meta_modules);
2395   build_module_descriptor (vers, attr);
2396 
2397   /* Dump the class references.  This forces the appropriate classes
2398      to be linked into the executable image, preserving unix archive
2399      semantics.  */
2400   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2401     {
2402       handle_next_class_ref (chain);
2403       if (TREE_PURPOSE (chain))
2404 	generate_classref_translation_entry (chain);
2405     }
2406 
2407   for (impent = imp_list; impent; impent = impent->next)
2408     handle_next_impent (impent);
2409 
2410   /* Emit the strings tables.  */
2411   generate_strings ();
2412 }
2413 
2414 /* --- exceptions stuff --- */
2415 
2416 /* Predefine the following data type:
2417 
2418    struct _objc_exception_data
2419    {
2420      int buf[OBJC_JBLEN];
2421      void *pointers[4];
2422    }; */
2423 
2424 /* The following yuckiness should prevent users from having to #include
2425    <setjmp.h> in their code... */
2426 
2427 /* Define to a harmless positive value so the below code doesn't die.  */
2428 #ifndef OBJC_JBLEN
2429 #define OBJC_JBLEN 18
2430 #endif
2431 
2432 static void
2433 build_next_objc_exception_stuff (void)
2434 {
2435   tree decls, temp_type, *chain = NULL;
2436 
2437   objc_exception_data_template
2438     = objc_start_struct (get_identifier (UTAG_EXCDATA));
2439 
2440   /* int buf[OBJC_JBLEN]; */
2441 
2442   temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
2443   decls = add_field_decl (temp_type, "buf", &chain);
2444 
2445   /* void *pointers[4]; */
2446 
2447   temp_type = build_sized_array_type (ptr_type_node, 4);
2448   add_field_decl (temp_type, "pointers", &chain);
2449 
2450   objc_finish_struct (objc_exception_data_template, decls);
2451 
2452   /* int _setjmp(...); */
2453   /* If the user includes <setjmp.h>, this shall be superseded by
2454      'int _setjmp(jmp_buf);' */
2455   temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
2456   objc_setjmp_decl
2457     = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
2458 
2459   /* id objc_exception_extract(struct _objc_exception_data *); */
2460   temp_type
2461     = build_function_type_list (objc_object_type,
2462                                 build_pointer_type (objc_exception_data_template),
2463                                 NULL_TREE);
2464   objc_exception_extract_decl
2465     = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
2466 			    NULL_TREE);
2467   /* void objc_exception_try_enter(struct _objc_exception_data *); */
2468   /* void objc_exception_try_exit(struct _objc_exception_data *); */
2469   temp_type
2470     = build_function_type_list (void_type_node,
2471                                 build_pointer_type (objc_exception_data_template),
2472                                 NULL_TREE);
2473   objc_exception_try_enter_decl
2474     = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
2475 			    NULL_TREE);
2476   objc_exception_try_exit_decl
2477     = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
2478 			    NULL_TREE);
2479 
2480   /* int objc_exception_match(id, id); */
2481   temp_type
2482     = build_function_type_list (integer_type_node,
2483                                 objc_object_type, objc_object_type, NULL_TREE);
2484   objc_exception_match_decl
2485     = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
2486 			    NULL_TREE);
2487 
2488   /* id objc_assign_ivar (id, id, unsigned int); */
2489   /* id objc_assign_ivar_Fast (id, id, unsigned int)
2490        __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2491   temp_type
2492     = build_function_type_list (objc_object_type,
2493                                 objc_object_type,
2494                                 objc_object_type,
2495                                 unsigned_type_node,
2496                                 NULL_TREE);
2497   objc_assign_ivar_decl
2498     = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
2499 			    NULL, NULL_TREE);
2500 #ifdef OFFS_ASSIGNIVAR_FAST
2501   objc_assign_ivar_fast_decl
2502     = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
2503 			    NOT_BUILT_IN, NULL, NULL_TREE);
2504   DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
2505     = tree_cons (get_identifier ("hard_coded_address"),
2506 		 build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
2507 		 NULL_TREE);
2508 #else
2509   /* Default to slower ivar method.  */
2510   objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
2511 #endif
2512 
2513   /* id objc_assign_global (id, id *); */
2514   /* id objc_assign_strongCast (id, id *); */
2515   temp_type = build_function_type_list (objc_object_type,
2516                                         objc_object_type,
2517                                         build_pointer_type (objc_object_type),
2518                                         NULL_TREE);
2519   objc_assign_global_decl
2520 	= add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
2521 				NULL_TREE);
2522   objc_assign_strong_cast_decl
2523 	= add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
2524 				NULL_TREE);
2525 }
2526 
2527 /* --- NeXT V1 SJLJ Exceptions --- */
2528 
2529 /* Build "objc_exception_try_exit(&_stack)".  */
2530 
2531 static tree
2532 next_sjlj_build_try_exit (struct objc_try_context **ctcp)
2533 {
2534   tree t;
2535   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2536   t = tree_cons (NULL, t, NULL);
2537   t = build_function_call (input_location,
2538 			   objc_exception_try_exit_decl, t);
2539   return t;
2540 }
2541 
2542 /* Build
2543 	objc_exception_try_enter (&_stack);
2544 	if (_setjmp(&_stack.buf))
2545 	  ;
2546 	else
2547 	  ;
2548    Return the COND_EXPR.  Note that the THEN and ELSE fields are left
2549    empty, ready for the caller to fill them in.  */
2550 
2551 static tree
2552 next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp)
2553 {
2554   tree t, enter, sj, cond;
2555 
2556   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2557   t = tree_cons (NULL, t, NULL);
2558   enter = build_function_call (input_location,
2559 			       objc_exception_try_enter_decl, t);
2560 
2561   t = objc_build_component_ref ((*ctcp)->stack_decl,
2562 				get_identifier ("buf"));
2563   t = build_fold_addr_expr_loc (input_location, t);
2564 #ifdef OBJCPLUS
2565   /* Convert _setjmp argument to type that is expected.  */
2566   if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
2567     t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
2568   else
2569     t = convert (ptr_type_node, t);
2570 #else
2571   t = convert (ptr_type_node, t);
2572 #endif
2573   t = tree_cons (NULL, t, NULL);
2574   sj = build_function_call (input_location,
2575 			    objc_setjmp_decl, t);
2576 
2577   cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
2578   cond = c_common_truthvalue_conversion (input_location, cond);
2579 
2580   return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
2581 }
2582 
2583 /* Build:
2584 
2585    DECL = objc_exception_extract(&_stack); */
2586 
2587 static tree
2588 next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl)
2589 {
2590   tree t;
2591 
2592   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2593   t = tree_cons (NULL, t, NULL);
2594   t = build_function_call (input_location,
2595 			   objc_exception_extract_decl, t);
2596   t = convert (TREE_TYPE (decl), t);
2597   t = build2 (MODIFY_EXPR, void_type_node, decl, t);
2598 
2599   return t;
2600 }
2601 
2602 /* Build
2603 	if (objc_exception_match(obj_get_class(TYPE), _caught)
2604 	  BODY
2605 	else if (...)
2606 	  ...
2607 	else
2608 	  {
2609 	    _rethrow = _caught;
2610 	    objc_exception_try_exit(&_stack);
2611 	  }
2612    from the sequence of CATCH_EXPRs in the current try context.  */
2613 
2614 static tree
2615 next_sjlj_build_catch_list (struct objc_try_context **ctcp)
2616 {
2617   tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list);
2618   tree catch_seq, t;
2619   tree *last = &catch_seq;
2620   bool saw_id = false;
2621 
2622   for (; !tsi_end_p (i); tsi_next (&i))
2623     {
2624       tree stmt = tsi_stmt (i);
2625       tree type = CATCH_TYPES (stmt);
2626       tree body = CATCH_BODY (stmt);
2627 
2628       if (type != error_mark_node
2629 	  && objc_is_object_id (TREE_TYPE (type)))
2630 	{
2631 	  *last = body;
2632 	  saw_id = true;
2633 	  break;
2634 	}
2635       else
2636 	{
2637 	  tree args, cond;
2638 
2639 	  if (type == error_mark_node)
2640 	    cond = error_mark_node;
2641 	  else
2642 	    {
2643 	      args = tree_cons (NULL, (*ctcp)->caught_decl, NULL);
2644 	      t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
2645 	      args = tree_cons (NULL, t, args);
2646 	      t = build_function_call (input_location,
2647 				       objc_exception_match_decl, args);
2648 	      cond = c_common_truthvalue_conversion (input_location, t);
2649 	    }
2650 	  t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
2651 	  SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
2652 
2653 	  *last = t;
2654 	  last = &COND_EXPR_ELSE (t);
2655 	}
2656     }
2657 
2658   if (!saw_id)
2659     {
2660       t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl,
2661 		  (*ctcp)->caught_decl);
2662       SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2663       append_to_statement_list (t, last);
2664 
2665       t = next_sjlj_build_try_exit (ctcp);
2666       SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2667       append_to_statement_list (t, last);
2668     }
2669 
2670   return catch_seq;
2671 }
2672 
2673 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2674    exception handling.  We aim to build:
2675 
2676 	{
2677 	  struct _objc_exception_data _stack;
2678 	  id _rethrow = 0;
2679 	  try
2680 	    {
2681 	      objc_exception_try_enter (&_stack);
2682 	      if (_setjmp(&_stack.buf))
2683 	        {
2684 		  id _caught = objc_exception_extract(&_stack);
2685 		  objc_exception_try_enter (&_stack);
2686 		  if (_setjmp(&_stack.buf))
2687 		    _rethrow = objc_exception_extract(&_stack);
2688 		  else
2689 		    CATCH-LIST
2690 	        }
2691 	      else
2692 		TRY-BLOCK
2693 	    }
2694 	  finally
2695 	    {
2696 	      if (!_rethrow)
2697 		objc_exception_try_exit(&_stack);
2698 	      FINALLY-BLOCK
2699 	      if (_rethrow)
2700 		objc_exception_throw(_rethrow);
2701 	    }
2702 	}
2703 
2704    If CATCH-LIST is empty, we can omit all of the block containing
2705    "_caught" except for the setting of _rethrow.  Note the use of
2706    a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2707    but handles goto and other exits from the block.  */
2708 
2709 static tree
2710 next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp)
2711 {
2712   tree rethrow_decl, stack_decl, t;
2713   tree catch_seq, try_fin, bind;
2714   struct objc_try_context *cur_try_context = *ctcp;
2715 
2716   /* Create the declarations involved.  */
2717   t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
2718   stack_decl = objc_create_temporary_var (t, NULL);
2719   cur_try_context->stack_decl = stack_decl;
2720 
2721   rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
2722   cur_try_context->rethrow_decl = rethrow_decl;
2723   TREE_CHAIN (rethrow_decl) = stack_decl;
2724 
2725   /* Build the outermost variable binding level.  */
2726   bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
2727   SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
2728   TREE_SIDE_EFFECTS (bind) = 1;
2729 
2730   /* Initialize rethrow_decl.  */
2731   t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
2732 	      convert (objc_object_type, null_pointer_node));
2733   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2734   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
2735 
2736   /* Build the outermost TRY_FINALLY_EXPR.  */
2737   try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
2738   SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
2739   TREE_SIDE_EFFECTS (try_fin) = 1;
2740   append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
2741 
2742   /* Create the complete catch sequence.  */
2743   if (cur_try_context->catch_list)
2744     {
2745       tree caught_decl = objc_build_exc_ptr (ctcp);
2746       catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
2747       TREE_SIDE_EFFECTS (catch_seq) = 1;
2748 
2749       t = next_sjlj_build_exc_extract (ctcp, caught_decl);
2750       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2751 
2752       t = next_sjlj_build_enter_and_setjmp (ctcp);
2753       COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2754       COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp);
2755       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2756     }
2757   else
2758     catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2759   SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
2760 
2761   /* Build the main register-and-try if statement.  */
2762   t = next_sjlj_build_enter_and_setjmp (ctcp);
2763   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2764   COND_EXPR_THEN (t) = catch_seq;
2765   COND_EXPR_ELSE (t) = cur_try_context->try_body;
2766   TREE_OPERAND (try_fin, 0) = t;
2767 
2768   /* Build the complete FINALLY statement list.  */
2769   t = next_sjlj_build_try_exit (ctcp);
2770   t = build_stmt (input_location, COND_EXPR,
2771 		  c_common_truthvalue_conversion
2772 		    (input_location, rethrow_decl),
2773 		  NULL, t);
2774   SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
2775   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2776 
2777   append_to_statement_list (cur_try_context->finally_body,
2778 			    &TREE_OPERAND (try_fin, 1));
2779 
2780   t = tree_cons (NULL, rethrow_decl, NULL);
2781   t = build_function_call (input_location,
2782 			   objc_exception_throw_decl, t);
2783   t = build_stmt (input_location, COND_EXPR,
2784 		  c_common_truthvalue_conversion (input_location,
2785 						  rethrow_decl),
2786 		  t, NULL);
2787   SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
2788   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2789 
2790   return bind;
2791 }
2792 
2793 /* We do not expect this to be used at the moment.
2794    If (a) it is possible to implement unwinder exceptions.
2795       (b) we do it... then it might be possibly useful.
2796 */
2797 static GTY(()) tree objc_eh_personality_decl;
2798 
2799 static tree
2800 objc_eh_runtime_type (tree type)
2801 {
2802   tree ident, eh_id, decl, str;
2803 
2804   gcc_unreachable ();
2805   if (type == error_mark_node)
2806     {
2807       /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2808 	 to prevent an ICE.  Note that we know that the compiler will
2809 	 terminate with an error and this 'ErrorMarkNode' class name will
2810 	 never be actually used.  */
2811       ident = get_identifier ("ErrorMarkNode");
2812       goto make_err_class;
2813     }
2814 
2815   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2816     {
2817       ident = get_identifier ("id");
2818       goto make_err_class;
2819     }
2820 
2821   if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2822     {
2823 #ifdef OBJCPLUS
2824       /* This routine is also called for c++'s catch clause; in which case,
2825 	 we use c++'s typeinfo decl. */
2826       return build_eh_type_type (type);
2827 #else
2828       error ("non-objective-c type '%T' cannot be caught", type);
2829       ident = get_identifier ("ErrorMarkNode");
2830       goto make_err_class;
2831 #endif
2832     }
2833   else
2834     ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2835 
2836 make_err_class:
2837   /* If this class was already referenced, then it will be output during
2838      meta-data emission, so we don't need to do it here.  */
2839   decl = get_objc_string_decl (ident, class_names);
2840   eh_id = add_objc_string (ident, class_names);
2841   if (!decl)
2842     {
2843       /* Not found ... so we need to build it - from the freshly-entered id.  */
2844       decl = get_objc_string_decl (ident, class_names);
2845       str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2846 			     IDENTIFIER_POINTER (ident));
2847       /* We have to finalize this var here, because this might be called after
2848 	 all the other metadata strings have been emitted.  */
2849       finish_var_decl (decl, str);
2850     }
2851   return eh_id;
2852 }
2853 
2854 /* For NeXT ABI 0 and 1, the personality routines are just those of the
2855    underlying language.  */
2856 
2857 static tree
2858 objc_eh_personality (void)
2859 {
2860   if (!objc_eh_personality_decl)
2861 #ifndef OBJCPLUS
2862     objc_eh_personality_decl = build_personality_function ("gcc");
2863 #else
2864     objc_eh_personality_decl = build_personality_function ("gxx");
2865 #endif
2866   return objc_eh_personality_decl;
2867 }
2868 
2869 /* --- interfaces --- */
2870 
2871 static tree
2872 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2873 {
2874   tree t;
2875   vec<tree, va_gc> *parms;
2876   vec_alloc (parms, 1);
2877   /* A throw is just a call to the runtime throw function with the
2878      object as a parameter.  */
2879   parms->quick_push (throw_expr);
2880   t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms,
2881 			       NULL);
2882   vec_free (parms);
2883   return add_stmt (t);
2884 }
2885 
2886 /* Build __builtin_eh_pointer, or the moral equivalent.  In the case
2887    of Darwin, we'll arrange for it to be initialized (and associated
2888    with a binding) later.  */
2889 
2890 static tree
2891 objc_build_exc_ptr (struct objc_try_context **cur_try_context)
2892 {
2893   if (flag_objc_sjlj_exceptions)
2894     {
2895       tree var = (*cur_try_context)->caught_decl;
2896       if (!var)
2897 	{
2898 	  var = objc_create_temporary_var (objc_object_type, NULL);
2899 	  (*cur_try_context)->caught_decl = var;
2900 	}
2901       return var;
2902     }
2903   else
2904     {
2905       tree t;
2906       t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2907       t = build_call_expr (t, 1, integer_zero_node);
2908       return fold_convert (objc_object_type, t);
2909     }
2910 }
2911 
2912 static tree
2913 begin_catch (struct objc_try_context **cur_try_context, tree type,
2914 	     tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2915 {
2916   tree t;
2917   /* Record the data for the catch in the try context so that we can
2918      finalize it later.  We treat ellipsis the same way as catching
2919      with 'id xyz'.  */
2920   t = build_stmt (input_location, CATCH_EXPR, type, compound);
2921   (*cur_try_context)->current_catch = t;
2922 
2923   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
2924   t = objc_build_exc_ptr (cur_try_context);
2925   t = convert (TREE_TYPE (decl), t);
2926   return build2 (MODIFY_EXPR, void_type_node, decl, t);
2927 }
2928 
2929 static void
2930 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2931 {
2932   append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2933 }
2934 
2935 static tree
2936 finish_try_stmt (struct objc_try_context **cur_try_context)
2937 {
2938   tree stmt;
2939   struct objc_try_context *c = *cur_try_context;
2940   /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
2941   if (flag_objc_sjlj_exceptions)
2942     {
2943       bool save = in_late_binary_op;
2944       in_late_binary_op = true;
2945       if (!c->finally_body)
2946 	{
2947 	  c->finally_locus = input_location;
2948 	  c->end_finally_locus = input_location;
2949 	}
2950       stmt = next_sjlj_build_try_catch_finally (cur_try_context);
2951       in_late_binary_op = save;
2952     }
2953   else
2954     /* This doesn't happen at the moment... but maybe one day... */
2955     {
2956       /* Otherwise, nest the CATCH inside a FINALLY.  */
2957       stmt = c->try_body;
2958       if (c->catch_list)
2959 	stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2960       if (c->finally_body)
2961 	stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2962     }
2963   return stmt;
2964 }
2965 
2966 #include "gt-objc-objc-next-runtime-abi-01.h"
2967