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