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