xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/objc/objc-next-runtime-abi-01.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /* Next Runtime (ABI-0/1) private.
2    Copyright (C) 2011-2013 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/cp-tree.h"
33 #else
34 #include "c/c-tree.h"
35 #include "c/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, va_gc> **,
127 							tree, 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, va_gc> **argtypes,
734 					    tree meth, int context,
735 					    int superflag)
736 {
737   tree receiver_type;
738 
739   if (superflag)
740     receiver_type = objc_super_type;
741   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
742     receiver_type = objc_instance_type;
743   else
744     receiver_type = objc_object_type;
745 
746   vec_safe_push (*argtypes, receiver_type);
747   /* Selector type - will eventually change to `int'.  */
748   vec_safe_push (*argtypes, objc_selector_type);
749 }
750 
751 static tree
752 next_runtime_abi_01_receiver_is_class_object (tree receiver)
753 {
754   if (TREE_CODE (receiver) == VAR_DECL
755       && IS_CLASS (TREE_TYPE (receiver)))
756     {
757       /* The receiver is a variable created by build_class_reference_decl.  */
758       tree chain = cls_ref_chain ;
759       /* Look up the identifier in the relevant chain.  */
760       for (; chain; chain = TREE_CHAIN (chain))
761 	if (TREE_PURPOSE (chain) == receiver)
762 	  return TREE_VALUE (chain);
763     }
764   return NULL_TREE;
765 }
766 
767 static tree
768 build_selector_reference_decl (tree ident)
769 {
770   tree decl;
771   char *t, buf[BUFSIZE];
772 
773   snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
774   t = buf;
775   while (*t)
776     {
777       if (*t==':')
778         *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
779       t++;
780     }
781   decl = start_var_decl (objc_selector_type, buf);
782   OBJCMETA (decl, objc_meta, meta_sel_refs);
783   return decl;
784 }
785 
786 static tree
787 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
788 					      tree ident,
789 					      tree proto ATTRIBUTE_UNUSED)
790 {
791   tree *chain = &sel_ref_chain;
792   tree expr;
793 
794   while (*chain)
795     {
796       if (TREE_VALUE (*chain) == ident)
797 	return TREE_PURPOSE (*chain);
798 
799       chain = &TREE_CHAIN (*chain);
800     }
801 
802   expr = build_selector_reference_decl (ident);
803 
804   *chain = tree_cons (expr, ident, NULL_TREE);
805 
806   return expr;
807 }
808 
809 /* Build a tree expression to send OBJECT the operation SELECTOR,
810    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
811    assuming the method has prototype METHOD_PROTOTYPE.
812    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
813    LOC is the location of the expression to build.
814    Use METHOD_PARAMS as list of args to pass to the method.
815    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
816 
817 static tree
818 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
819 			tree lookup_object, tree selector,
820 			tree method_params)
821 {
822   tree sender, sender_cast, method, t;
823   tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
824   vec<tree, va_gc> *parms;
825   unsigned nparm = (method_params ? list_length (method_params) : 0);
826 
827   /* If a prototype for the method to be called exists, then cast
828      the sender's return type and arguments to match that of the method.
829      Otherwise, leave sender as is.  */
830   tree ret_type
831     = (method_prototype
832        ? TREE_VALUE (TREE_TYPE (method_prototype))
833        : objc_object_type);
834   tree ftype = build_function_type_for_method (ret_type, method_prototype,
835 					       METHOD_REF, super_flag);
836 
837   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
838     ftype = build_type_attribute_variant (ftype,
839 					  METHOD_TYPE_ATTRIBUTES
840 					  (method_prototype));
841 
842   sender_cast = build_pointer_type (ftype);
843 
844   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
845 
846   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
847   lookup_object = save_expr (lookup_object);
848 
849   /* Param list + 2 slots for object and selector.  */
850   vec_alloc (parms, nparm + 2);
851 
852   /* If we are returning a struct in memory, and the address
853      of that memory location is passed as a hidden first
854      argument, then change which messenger entry point this
855      expr will call.  NB: Note that sender_cast remains
856      unchanged (it already has a struct return type).  */
857   if (!targetm.calls.struct_value_rtx (0, 0)
858       && (TREE_CODE (ret_type) == RECORD_TYPE
859 	  || TREE_CODE (ret_type) == UNION_TYPE)
860       && targetm.calls.return_in_memory (ret_type, 0))
861     sender = (super_flag ? umsg_super_stret_decl
862 			 : flag_nil_receivers ? umsg_stret_decl
863 					      : umsg_nonnil_stret_decl);
864   else
865     sender = (super_flag ? umsg_super_decl
866 			 : (flag_nil_receivers  ? (flag_objc_direct_dispatch
867 							? umsg_fast_decl
868 							: umsg_decl)
869 						: umsg_nonnil_decl));
870   method = build_fold_addr_expr_loc (loc, sender);
871 
872   /* Pass the object to the method.  */
873   parms->quick_push (lookup_object);
874   /* Pass the selector to the method.  */
875   parms->quick_push (selector);
876   /* Now append the remainder of the parms.  */
877   if (nparm)
878     for (; method_params; method_params = TREE_CHAIN (method_params))
879       parms->quick_push (TREE_VALUE (method_params));
880 
881   /* Build an obj_type_ref, with the correct cast for the method call.  */
882   t = build3 (OBJ_TYPE_REF, sender_cast, method,
883 			    lookup_object, size_zero_node);
884   t = build_function_call_vec (loc, t, parms, NULL);
885   vec_free (parms);
886   return t;
887 }
888 
889 static tree
890 next_runtime_abi_01_build_objc_method_call (location_t loc,
891 					    tree method_prototype,
892 					    tree receiver,
893 					    tree rtype ATTRIBUTE_UNUSED,
894 					    tree sel_name,
895 					    tree method_params,
896 					    int super)
897 {
898   tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name,
899 								NULL_TREE);
900 
901   return build_objc_method_call (loc, super, method_prototype,
902 				 receiver, selector, method_params);
903 }
904 
905 static tree
906 next_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
907 {
908   tree expr;
909 
910   if (!PROTOCOL_FORWARD_DECL (p))
911     PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p);
912 
913   expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
914   return convert (objc_protocol_type, expr);
915 }
916 
917 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct.  */
918 
919 static tree
920 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
921 				   tree base, tree id)
922 {
923   return objc_build_component_ref (base, id);
924 }
925 
926 /* We build super class references as we need them (but keep them once
927    built for the sake of efficiency).  */
928 
929 static tree
930 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
931 					 struct imp_entry *imp, bool inst_meth)
932 {
933   if (inst_meth)
934     {
935       if (!ucls_super_ref)
936 	ucls_super_ref =
937 		objc_build_component_ref (imp->class_decl,
938 					  get_identifier ("super_class"));
939 	return ucls_super_ref;
940     }
941   else
942     {
943       if (!uucls_super_ref)
944 	uucls_super_ref =
945 		objc_build_component_ref (imp->meta_decl,
946 					  get_identifier ("super_class"));
947 	return uucls_super_ref;
948     }
949 }
950 
951 static tree
952 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
953 					   struct imp_entry *imp, bool inst_meth)
954 {
955   tree super_name = CLASS_SUPER_NAME (imp->imp_template);
956   tree super_class;
957 
958   if (!flag_zero_link)
959     {
960       super_class = objc_get_class_reference (super_name);
961 
962       if (!inst_meth)
963 
964 	/* If we are in a class method, we must retrieve the
965 	   _metaclass_ for the current class, pointed at by
966 	   the class's "isa" pointer.  The following assumes that
967 	   "isa" is the first ivar in a class (which it must be).  */
968 	   super_class =
969 		build_indirect_ref (input_location,
970 				    build_c_cast (input_location,
971 					build_pointer_type (objc_class_type),
972 					super_class),
973 				    RO_UNARY_STAR);
974       return super_class;
975     }
976 
977   /* else do it the slow way.  */
978   add_class_reference (super_name);
979   super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
980   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, va_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, va_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, va_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, va_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, va_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, va_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, va_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, va_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, va_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, va_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, va_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, va_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, va_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, va_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, va_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 static void
2336 objc_generate_v1_next_metadata (void)
2337 {
2338   struct imp_entry *impent;
2339   tree chain, attr;
2340   long vers;
2341 
2342   /* FIXME: Make sure that we generate no metadata if there is nothing
2343      to put into it.  */
2344 
2345   if (objc_static_instances)
2346     gcc_unreachable (); /* Not for NeXT */
2347 
2348   build_metadata_templates ();
2349   objc_implementation_context =
2350   implementation_template =
2351   UOBJC_CLASS_decl =
2352   UOBJC_METACLASS_decl = NULL_TREE;
2353 
2354   for (impent = imp_list; impent; impent = impent->next)
2355     {
2356 
2357       /* If -gen-decls is present, Dump the @interface of each class.
2358 	 TODO: Dump the classes in the  order they were found, rather than in
2359 	 reverse order as we are doing now.  */
2360       if (flag_gen_declaration)
2361 	dump_interface (gen_declaration_file, impent->imp_context);
2362 
2363       /* all of the following reference the string pool...  */
2364       if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2365 	generate_v1_class_structs (impent);
2366       else
2367 	generate_v1_category (impent);
2368     }
2369 
2370   /* If we are using an array of selectors, we must always
2371      finish up the array decl even if no selectors were used.  */
2372   build_next_selector_translation_table ();
2373 
2374   if (protocol_chain)
2375     generate_v1_protocols ();
2376 
2377   /* Pass summary information to the runtime.  */
2378   if (imp_count || cat_count)
2379     generate_objc_symtab_decl ();
2380 
2381   vers = OBJC_VERSION;
2382   attr = build_tree_list (objc_meta, meta_modules);
2383   build_module_descriptor (vers, attr);
2384 
2385   /* Dump the class references.  This forces the appropriate classes
2386      to be linked into the executable image, preserving unix archive
2387      semantics.  */
2388   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2389     {
2390       handle_next_class_ref (chain);
2391       if (TREE_PURPOSE (chain))
2392 	generate_classref_translation_entry (chain);
2393     }
2394 
2395   for (impent = imp_list; impent; impent = impent->next)
2396     handle_next_impent (impent);
2397 
2398   /* Emit the strings tables.  */
2399   generate_strings ();
2400 }
2401 
2402 /* --- exceptions stuff --- */
2403 
2404 /* Predefine the following data type:
2405 
2406    struct _objc_exception_data
2407    {
2408      int buf[OBJC_JBLEN];
2409      void *pointers[4];
2410    }; */
2411 
2412 /* The following yuckiness should prevent users from having to #include
2413    <setjmp.h> in their code... */
2414 
2415 /* Define to a harmless positive value so the below code doesn't die.  */
2416 #ifndef OBJC_JBLEN
2417 #define OBJC_JBLEN 18
2418 #endif
2419 
2420 static void
2421 build_next_objc_exception_stuff (void)
2422 {
2423   tree decls, temp_type, *chain = NULL;
2424 
2425   objc_exception_data_template
2426     = objc_start_struct (get_identifier (UTAG_EXCDATA));
2427 
2428   /* int buf[OBJC_JBLEN]; */
2429 
2430   temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
2431   decls = add_field_decl (temp_type, "buf", &chain);
2432 
2433   /* void *pointers[4]; */
2434 
2435   temp_type = build_sized_array_type (ptr_type_node, 4);
2436   add_field_decl (temp_type, "pointers", &chain);
2437 
2438   objc_finish_struct (objc_exception_data_template, decls);
2439 
2440   /* int _setjmp(...); */
2441   /* If the user includes <setjmp.h>, this shall be superseded by
2442      'int _setjmp(jmp_buf);' */
2443   temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
2444   objc_setjmp_decl
2445     = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
2446 
2447   /* id objc_exception_extract(struct _objc_exception_data *); */
2448   temp_type
2449     = build_function_type_list (objc_object_type,
2450                                 build_pointer_type (objc_exception_data_template),
2451                                 NULL_TREE);
2452   objc_exception_extract_decl
2453     = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
2454 			    NULL_TREE);
2455   /* void objc_exception_try_enter(struct _objc_exception_data *); */
2456   /* void objc_exception_try_exit(struct _objc_exception_data *); */
2457   temp_type
2458     = build_function_type_list (void_type_node,
2459                                 build_pointer_type (objc_exception_data_template),
2460                                 NULL_TREE);
2461   objc_exception_try_enter_decl
2462     = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
2463 			    NULL_TREE);
2464   objc_exception_try_exit_decl
2465     = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
2466 			    NULL_TREE);
2467 
2468   /* int objc_exception_match(id, id); */
2469   temp_type
2470     = build_function_type_list (integer_type_node,
2471                                 objc_object_type, objc_object_type, NULL_TREE);
2472   objc_exception_match_decl
2473     = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
2474 			    NULL_TREE);
2475 
2476   /* id objc_assign_ivar (id, id, unsigned int); */
2477   /* id objc_assign_ivar_Fast (id, id, unsigned int)
2478        __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2479   temp_type
2480     = build_function_type_list (objc_object_type,
2481                                 objc_object_type,
2482                                 objc_object_type,
2483                                 unsigned_type_node,
2484                                 NULL_TREE);
2485   objc_assign_ivar_decl
2486     = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
2487 			    NULL, NULL_TREE);
2488 #ifdef OFFS_ASSIGNIVAR_FAST
2489   objc_assign_ivar_fast_decl
2490     = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
2491 			    NOT_BUILT_IN, NULL, NULL_TREE);
2492   DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
2493     = tree_cons (get_identifier ("hard_coded_address"),
2494 		 build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
2495 		 NULL_TREE);
2496 #else
2497   /* Default to slower ivar method.  */
2498   objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
2499 #endif
2500 
2501   /* id objc_assign_global (id, id *); */
2502   /* id objc_assign_strongCast (id, id *); */
2503   temp_type = build_function_type_list (objc_object_type,
2504                                         objc_object_type,
2505                                         build_pointer_type (objc_object_type),
2506                                         NULL_TREE);
2507   objc_assign_global_decl
2508 	= add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
2509 				NULL_TREE);
2510   objc_assign_strong_cast_decl
2511 	= add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
2512 				NULL_TREE);
2513 }
2514 
2515 /* --- NeXT V1 SJLJ Exceptions --- */
2516 
2517 /* Build "objc_exception_try_exit(&_stack)".  */
2518 
2519 static tree
2520 next_sjlj_build_try_exit (struct objc_try_context **ctcp)
2521 {
2522   tree t;
2523   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2524   t = tree_cons (NULL, t, NULL);
2525   t = build_function_call (input_location,
2526 			   objc_exception_try_exit_decl, t);
2527   return t;
2528 }
2529 
2530 /* Build
2531 	objc_exception_try_enter (&_stack);
2532 	if (_setjmp(&_stack.buf))
2533 	  ;
2534 	else
2535 	  ;
2536    Return the COND_EXPR.  Note that the THEN and ELSE fields are left
2537    empty, ready for the caller to fill them in.  */
2538 
2539 static tree
2540 next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp)
2541 {
2542   tree t, enter, sj, cond;
2543 
2544   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2545   t = tree_cons (NULL, t, NULL);
2546   enter = build_function_call (input_location,
2547 			       objc_exception_try_enter_decl, t);
2548 
2549   t = objc_build_component_ref ((*ctcp)->stack_decl,
2550 				get_identifier ("buf"));
2551   t = build_fold_addr_expr_loc (input_location, t);
2552 #ifdef OBJCPLUS
2553   /* Convert _setjmp argument to type that is expected.  */
2554   if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
2555     t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
2556   else
2557     t = convert (ptr_type_node, t);
2558 #else
2559   t = convert (ptr_type_node, t);
2560 #endif
2561   t = tree_cons (NULL, t, NULL);
2562   sj = build_function_call (input_location,
2563 			    objc_setjmp_decl, t);
2564 
2565   cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
2566   cond = c_common_truthvalue_conversion (input_location, cond);
2567 
2568   return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
2569 }
2570 
2571 /* Build:
2572 
2573    DECL = objc_exception_extract(&_stack); */
2574 
2575 static tree
2576 next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl)
2577 {
2578   tree t;
2579 
2580   t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2581   t = tree_cons (NULL, t, NULL);
2582   t = build_function_call (input_location,
2583 			   objc_exception_extract_decl, t);
2584   t = convert (TREE_TYPE (decl), t);
2585   t = build2 (MODIFY_EXPR, void_type_node, decl, t);
2586 
2587   return t;
2588 }
2589 
2590 /* Build
2591 	if (objc_exception_match(obj_get_class(TYPE), _caught)
2592 	  BODY
2593 	else if (...)
2594 	  ...
2595 	else
2596 	  {
2597 	    _rethrow = _caught;
2598 	    objc_exception_try_exit(&_stack);
2599 	  }
2600    from the sequence of CATCH_EXPRs in the current try context.  */
2601 
2602 static tree
2603 next_sjlj_build_catch_list (struct objc_try_context **ctcp)
2604 {
2605   tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list);
2606   tree catch_seq, t;
2607   tree *last = &catch_seq;
2608   bool saw_id = false;
2609 
2610   for (; !tsi_end_p (i); tsi_next (&i))
2611     {
2612       tree stmt = tsi_stmt (i);
2613       tree type = CATCH_TYPES (stmt);
2614       tree body = CATCH_BODY (stmt);
2615 
2616       if (type != error_mark_node
2617 	  && objc_is_object_id (TREE_TYPE (type)))
2618 	{
2619 	  *last = body;
2620 	  saw_id = true;
2621 	  break;
2622 	}
2623       else
2624 	{
2625 	  tree args, cond;
2626 
2627 	  if (type == error_mark_node)
2628 	    cond = error_mark_node;
2629 	  else
2630 	    {
2631 	      args = tree_cons (NULL, (*ctcp)->caught_decl, NULL);
2632 	      t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
2633 	      args = tree_cons (NULL, t, args);
2634 	      t = build_function_call (input_location,
2635 				       objc_exception_match_decl, args);
2636 	      cond = c_common_truthvalue_conversion (input_location, t);
2637 	    }
2638 	  t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
2639 	  SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
2640 
2641 	  *last = t;
2642 	  last = &COND_EXPR_ELSE (t);
2643 	}
2644     }
2645 
2646   if (!saw_id)
2647     {
2648       t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl,
2649 		  (*ctcp)->caught_decl);
2650       SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2651       append_to_statement_list (t, last);
2652 
2653       t = next_sjlj_build_try_exit (ctcp);
2654       SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2655       append_to_statement_list (t, last);
2656     }
2657 
2658   return catch_seq;
2659 }
2660 
2661 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2662    exception handling.  We aim to build:
2663 
2664 	{
2665 	  struct _objc_exception_data _stack;
2666 	  id _rethrow = 0;
2667 	  try
2668 	    {
2669 	      objc_exception_try_enter (&_stack);
2670 	      if (_setjmp(&_stack.buf))
2671 	        {
2672 		  id _caught = objc_exception_extract(&_stack);
2673 		  objc_exception_try_enter (&_stack);
2674 		  if (_setjmp(&_stack.buf))
2675 		    _rethrow = objc_exception_extract(&_stack);
2676 		  else
2677 		    CATCH-LIST
2678 	        }
2679 	      else
2680 		TRY-BLOCK
2681 	    }
2682 	  finally
2683 	    {
2684 	      if (!_rethrow)
2685 		objc_exception_try_exit(&_stack);
2686 	      FINALLY-BLOCK
2687 	      if (_rethrow)
2688 		objc_exception_throw(_rethrow);
2689 	    }
2690 	}
2691 
2692    If CATCH-LIST is empty, we can omit all of the block containing
2693    "_caught" except for the setting of _rethrow.  Note the use of
2694    a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2695    but handles goto and other exits from the block.  */
2696 
2697 static tree
2698 next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp)
2699 {
2700   tree rethrow_decl, stack_decl, t;
2701   tree catch_seq, try_fin, bind;
2702   struct objc_try_context *cur_try_context = *ctcp;
2703 
2704   /* Create the declarations involved.  */
2705   t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
2706   stack_decl = objc_create_temporary_var (t, NULL);
2707   cur_try_context->stack_decl = stack_decl;
2708 
2709   rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
2710   cur_try_context->rethrow_decl = rethrow_decl;
2711   TREE_CHAIN (rethrow_decl) = stack_decl;
2712 
2713   /* Build the outermost variable binding level.  */
2714   bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
2715   SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
2716   TREE_SIDE_EFFECTS (bind) = 1;
2717 
2718   /* Initialize rethrow_decl.  */
2719   t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
2720 	      convert (objc_object_type, null_pointer_node));
2721   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2722   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
2723 
2724   /* Build the outermost TRY_FINALLY_EXPR.  */
2725   try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
2726   SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
2727   TREE_SIDE_EFFECTS (try_fin) = 1;
2728   append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
2729 
2730   /* Create the complete catch sequence.  */
2731   if (cur_try_context->catch_list)
2732     {
2733       tree caught_decl = objc_build_exc_ptr (ctcp);
2734       catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
2735       TREE_SIDE_EFFECTS (catch_seq) = 1;
2736 
2737       t = next_sjlj_build_exc_extract (ctcp, caught_decl);
2738       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2739 
2740       t = next_sjlj_build_enter_and_setjmp (ctcp);
2741       COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2742       COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp);
2743       append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2744     }
2745   else
2746     catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2747   SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
2748 
2749   /* Build the main register-and-try if statement.  */
2750   t = next_sjlj_build_enter_and_setjmp (ctcp);
2751   SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2752   COND_EXPR_THEN (t) = catch_seq;
2753   COND_EXPR_ELSE (t) = cur_try_context->try_body;
2754   TREE_OPERAND (try_fin, 0) = t;
2755 
2756   /* Build the complete FINALLY statement list.  */
2757   t = next_sjlj_build_try_exit (ctcp);
2758   t = build_stmt (input_location, COND_EXPR,
2759 		  c_common_truthvalue_conversion
2760 		    (input_location, rethrow_decl),
2761 		  NULL, t);
2762   SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
2763   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2764 
2765   append_to_statement_list (cur_try_context->finally_body,
2766 			    &TREE_OPERAND (try_fin, 1));
2767 
2768   t = tree_cons (NULL, rethrow_decl, NULL);
2769   t = build_function_call (input_location,
2770 			   objc_exception_throw_decl, t);
2771   t = build_stmt (input_location, COND_EXPR,
2772 		  c_common_truthvalue_conversion (input_location,
2773 						  rethrow_decl),
2774 		  t, NULL);
2775   SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
2776   append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2777 
2778   return bind;
2779 }
2780 
2781 /* We do not expect this to be used at the moment.
2782    If (a) it is possible to implement unwinder exceptions.
2783       (b) we do it... then it might be possibly useful.
2784 */
2785 static GTY(()) tree objc_eh_personality_decl;
2786 
2787 static tree
2788 objc_eh_runtime_type (tree type)
2789 {
2790   tree ident, eh_id, decl, str;
2791 
2792   gcc_unreachable ();
2793   if (type == error_mark_node)
2794     {
2795       /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2796 	 to prevent an ICE.  Note that we know that the compiler will
2797 	 terminate with an error and this 'ErrorMarkNode' class name will
2798 	 never be actually used.  */
2799       ident = get_identifier ("ErrorMarkNode");
2800       goto make_err_class;
2801     }
2802 
2803   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2804     {
2805       ident = get_identifier ("id");
2806       goto make_err_class;
2807     }
2808 
2809   if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2810     {
2811 #ifdef OBJCPLUS
2812       /* This routine is also called for c++'s catch clause; in which case,
2813 	 we use c++'s typeinfo decl. */
2814       return build_eh_type_type (type);
2815 #else
2816       error ("non-objective-c type '%T' cannot be caught", type);
2817       ident = get_identifier ("ErrorMarkNode");
2818       goto make_err_class;
2819 #endif
2820     }
2821   else
2822     ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2823 
2824 make_err_class:
2825   /* If this class was already referenced, then it will be output during
2826      meta-data emission, so we don't need to do it here.  */
2827   decl = get_objc_string_decl (ident, class_names);
2828   eh_id = add_objc_string (ident, class_names);
2829   if (!decl)
2830     {
2831       /* Not found ... so we need to build it - from the freshly-entered id.  */
2832       decl = get_objc_string_decl (ident, class_names);
2833       str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2834 			     IDENTIFIER_POINTER (ident));
2835       /* We have to finalize this var here, because this might be called after
2836 	 all the other metadata strings have been emitted.  */
2837       finish_var_decl (decl, str);
2838     }
2839   return eh_id;
2840 }
2841 
2842 /* For NeXT ABI 0 and 1, the personality routines are just those of the
2843    underlying language.  */
2844 
2845 static tree
2846 objc_eh_personality (void)
2847 {
2848   if (!objc_eh_personality_decl)
2849 #ifndef OBJCPLUS
2850     objc_eh_personality_decl = build_personality_function ("gcc");
2851 #else
2852     objc_eh_personality_decl = build_personality_function ("gxx");
2853 #endif
2854   return objc_eh_personality_decl;
2855 }
2856 
2857 /* --- interfaces --- */
2858 
2859 static tree
2860 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2861 {
2862   tree t;
2863   vec<tree, va_gc> *parms;
2864   vec_alloc (parms, 1);
2865   /* A throw is just a call to the runtime throw function with the
2866      object as a parameter.  */
2867   parms->quick_push (throw_expr);
2868   t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
2869   vec_free (parms);
2870   return add_stmt (t);
2871 }
2872 
2873 /* Build __builtin_eh_pointer, or the moral equivalent.  In the case
2874    of Darwin, we'll arrange for it to be initialized (and associated
2875    with a binding) later.  */
2876 
2877 static tree
2878 objc_build_exc_ptr (struct objc_try_context **cur_try_context)
2879 {
2880   if (flag_objc_sjlj_exceptions)
2881     {
2882       tree var = (*cur_try_context)->caught_decl;
2883       if (!var)
2884 	{
2885 	  var = objc_create_temporary_var (objc_object_type, NULL);
2886 	  (*cur_try_context)->caught_decl = var;
2887 	}
2888       return var;
2889     }
2890   else
2891     {
2892       tree t;
2893       t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2894       t = build_call_expr (t, 1, integer_zero_node);
2895       return fold_convert (objc_object_type, t);
2896     }
2897 }
2898 
2899 static tree
2900 begin_catch (struct objc_try_context **cur_try_context, tree type,
2901 	     tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2902 {
2903   tree t;
2904   /* Record the data for the catch in the try context so that we can
2905      finalize it later.  We treat ellipsis the same way as catching
2906      with 'id xyz'.  */
2907   t = build_stmt (input_location, CATCH_EXPR, type, compound);
2908   (*cur_try_context)->current_catch = t;
2909 
2910   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
2911   t = objc_build_exc_ptr (cur_try_context);
2912   t = convert (TREE_TYPE (decl), t);
2913   return build2 (MODIFY_EXPR, void_type_node, decl, t);
2914 }
2915 
2916 static void
2917 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2918 {
2919   append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2920 }
2921 
2922 static tree
2923 finish_try_stmt (struct objc_try_context **cur_try_context)
2924 {
2925   tree stmt;
2926   struct objc_try_context *c = *cur_try_context;
2927   /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
2928   if (flag_objc_sjlj_exceptions)
2929     {
2930       bool save = in_late_binary_op;
2931       in_late_binary_op = true;
2932       if (!c->finally_body)
2933 	{
2934 	  c->finally_locus = input_location;
2935 	  c->end_finally_locus = input_location;
2936 	}
2937       stmt = next_sjlj_build_try_catch_finally (cur_try_context);
2938       in_late_binary_op = save;
2939     }
2940   else
2941     /* This doesn't happen at the moment... but maybe one day... */
2942     {
2943       /* Otherwise, nest the CATCH inside a FINALLY.  */
2944       stmt = c->try_body;
2945       if (c->catch_list)
2946 	stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2947       if (c->finally_body)
2948 	stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2949     }
2950   return stmt;
2951 }
2952 
2953 #include "gt-objc-objc-next-runtime-abi-01.h"
2954