xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/objc/objc-gnu-runtime-abi-01.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* GNU Runtime ABI version 8
2    Copyright (C) 2011-2015 Free Software Foundation, Inc.
3    Contributed by Iain Sandoe (split from objc-act.c)
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "hash-set.h"
25 #include "machmode.h"
26 #include "vec.h"
27 #include "double-int.h"
28 #include "input.h"
29 #include "alias.h"
30 #include "symtab.h"
31 #include "options.h"
32 #include "wide-int.h"
33 #include "inchash.h"
34 #include "tree.h"
35 #include "fold-const.h"
36 #include "stringpool.h"
37 
38 #ifdef OBJCPLUS
39 #include "cp/cp-tree.h"
40 #else
41 #include "c/c-tree.h"
42 #include "c/c-lang.h"
43 #endif
44 
45 #include "langhooks.h"
46 #include "c-family/c-objc.h"
47 #include "objc-act.h"
48 
49 /* When building Objective-C++, we are not linking against the C front-end
50    and so need to replicate the C tree-construction functions in some way.  */
51 #ifdef OBJCPLUS
52 #define OBJCP_REMAP_FUNCTIONS
53 #include "objcp-decl.h"
54 #endif  /* OBJCPLUS */
55 
56 #include "toplev.h"
57 #include "ggc.h"
58 #include "tree-iterator.h"
59 
60 #include "objc-runtime-hooks.h"
61 #include "objc-runtime-shared-support.h"
62 #include "objc-encoding.h"
63 
64 /* GNU runtime private definitions.  */
65 #define DEF_CONSTANT_STRING_CLASS_NAME "NXConstantString"
66 
67 #define TAG_GETCLASS		"objc_get_class"
68 #define TAG_GETMETACLASS	"objc_get_meta_class"
69 
70 #define TAG_MSGSEND		"objc_msg_lookup"
71 #define TAG_MSGSENDSUPER	"objc_msg_lookup_super"
72 
73 /* GNU-specific tags.  */
74 
75 #define TAG_EXECCLASS		"__objc_exec_class"
76 #define TAG_GNUINIT		"__objc_gnu_init"
77 
78 /* The version identifies which language generation and runtime
79    the module (file) was compiled for, and is recorded in the
80    module descriptor.  */
81 #define OBJC_VERSION		8
82 
83 #define PROTOCOL_VERSION	2
84 
85 /* This macro provides a method of removing ambiguity between runtimes
86    when LTO is in use on targets supporting multiple runtimes.
87 
88    For example, at present, any target that includes an implementation of
89    the NeXT runtime needs to place Objective-C meta-data into specific
90    named sections.  This should _not_ be done for the GNU runtime, and the
91    following macro is used to attach Objective-C private attributes that may
92    be used to identify the runtime for which the meta-data are intended.  */
93 
94 #define OBJCMETA(DECL,VERS,KIND)					\
95   if (VERS)								\
96     DECL_ATTRIBUTES (DECL) = build_tree_list ((VERS), (KIND));
97 
98 static void gnu_runtime_01_initialize (void);
99 
100 static void build_selector_template (void);
101 
102 static tree gnu_runtime_abi_01_super_superclassfield_id (void);
103 
104 static tree gnu_runtime_abi_01_class_decl (tree);
105 static tree gnu_runtime_abi_01_metaclass_decl (tree);
106 static tree gnu_runtime_abi_01_category_decl (tree);
107 static tree gnu_runtime_abi_01_protocol_decl (tree);
108 static tree gnu_runtime_abi_01_string_decl (tree, const char *, string_section);
109 
110 static tree gnu_runtime_abi_01_get_class_reference (tree);
111 static tree gnu_runtime_abi_01_build_typed_selector_reference (location_t, tree,
112 								tree);
113 static tree gnu_runtime_abi_01_get_protocol_reference (location_t, tree);
114 static tree gnu_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
115 static tree gnu_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
116 static tree gnu_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
117 
118 static tree gnu_runtime_abi_01_receiver_is_class_object (tree);
119 static void gnu_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **,
120 						       tree, int, int);
121 static tree gnu_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
122 							tree, tree, tree, int);
123 
124 static bool gnu_runtime_abi_01_setup_const_string_class_decl (void);
125 static tree gnu_runtime_abi_01_build_const_string_constructor (location_t, tree,int);
126 
127 static void objc_generate_v1_gnu_metadata (void);
128 
129 static tree objc_eh_runtime_type (tree type);
130 static tree objc_eh_personality (void);
131 static tree objc_build_exc_ptr (struct objc_try_context **);
132 static tree build_throw_stmt (location_t, tree, bool);
133 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
134 static void finish_catch (struct objc_try_context **, tree);
135 static tree finish_try_stmt (struct objc_try_context **);
136 
137 bool
138 objc_gnu_runtime_abi_01_init (objc_runtime_hooks *rthooks)
139 {
140   /* GNU runtime does not need the compiler to change code in order to do GC. */
141   if (flag_objc_gc)
142     {
143       warning_at (0, 0, "%<-fobjc-gc%> is ignored for %<-fgnu-runtime%>");
144       flag_objc_gc = 0;
145     }
146 
147   /* Although I guess we could, we don't currently support SJLJ exceptions for the
148      GNU runtime.  */
149   if (flag_objc_sjlj_exceptions)
150     {
151       inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for %<-fgnu-runtime%>");
152       flag_objc_sjlj_exceptions = 0;
153     }
154 
155   /* TODO: Complain if -fobjc-abi-version=N was used.  */
156 
157   /* TODO: Complain if -fobj-nilcheck was used.  */
158 
159   rthooks->initialize = gnu_runtime_01_initialize;
160   rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
161   rthooks->tag_getclass = TAG_GETCLASS;
162   rthooks->super_superclassfield_ident = gnu_runtime_abi_01_super_superclassfield_id;
163 
164   rthooks->class_decl = gnu_runtime_abi_01_class_decl;
165   rthooks->metaclass_decl = gnu_runtime_abi_01_metaclass_decl;
166   rthooks->category_decl = gnu_runtime_abi_01_category_decl;
167   rthooks->protocol_decl = gnu_runtime_abi_01_protocol_decl;
168   rthooks->string_decl = gnu_runtime_abi_01_string_decl;
169 
170   rthooks->get_class_reference = gnu_runtime_abi_01_get_class_reference;
171   rthooks->build_selector_reference = gnu_runtime_abi_01_build_typed_selector_reference;
172   rthooks->get_protocol_reference = gnu_runtime_abi_01_get_protocol_reference;
173   rthooks->build_ivar_reference = gnu_runtime_abi_01_build_ivar_ref;
174   rthooks->get_class_super_ref = gnu_runtime_abi_01_get_class_super_ref;
175   rthooks->get_category_super_ref = gnu_runtime_abi_01_get_category_super_ref;
176 
177   rthooks->receiver_is_class_object = gnu_runtime_abi_01_receiver_is_class_object;
178   rthooks->get_arg_type_list_base = gnu_runtime_abi_01_get_arg_type_list_base;
179   rthooks->build_objc_method_call = gnu_runtime_abi_01_build_objc_method_call;
180 
181   rthooks->setup_const_string_class_decl =
182 				gnu_runtime_abi_01_setup_const_string_class_decl;
183   rthooks->build_const_string_constructor =
184 				gnu_runtime_abi_01_build_const_string_constructor;
185 
186   rthooks->build_throw_stmt = build_throw_stmt;
187   rthooks->build_exc_ptr = objc_build_exc_ptr;
188   rthooks->begin_catch = begin_catch;
189   rthooks->finish_catch = finish_catch;
190   rthooks->finish_try_stmt = finish_try_stmt;
191 
192   rthooks->generate_metadata = objc_generate_v1_gnu_metadata;
193   return true;
194 }
195 
196 static void build_selector_table_decl (void);
197 static void build_class_template (void);
198 static void build_category_template (void);
199 static void build_protocol_template (void);
200 
201 static GTY(()) tree objc_meta;
202 static GTY(()) tree meta_base;
203 
204 static void gnu_runtime_01_initialize (void)
205 {
206   tree type, ftype, IMP_type;
207 
208   /* We do not need to mark GNU ObjC metadata for different sections,
209      however, we do need to make sure that it is not mistaken for NeXT
210      metadata.  */
211   objc_meta = get_identifier ("OBJC1METG");
212   meta_base = get_identifier ("NONE");
213 
214   /* Declare type of selector-objects that represent an operation name.  */
215   /* `const struct objc_selector *' */
216   type = xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR));
217   type = build_qualified_type (type, TYPE_QUAL_CONST);
218   objc_selector_type = build_pointer_type (type);
219 
220   /* typedef id (*IMP)(id, SEL, ...); */
221   ftype = build_varargs_function_type_list (objc_object_type,
222 					    objc_object_type,
223 					    objc_selector_type,
224 					    NULL_TREE);
225 
226   IMP_type = build_pointer_type (ftype);
227 
228   build_class_template ();
229   build_super_template ();
230   build_protocol_template ();
231   build_category_template ();
232 
233   /* GNU runtime messenger entry points.  */
234   /* TREE_NOTHROW is cleared for the message-sending functions,
235      because the function that gets called can throw in Obj-C++, or
236      could itself call something that can throw even in Obj-C.  */
237 
238   /* IMP objc_msg_lookup (id, SEL); */
239   type = build_function_type_list (IMP_type,
240 				   objc_object_type,
241 				   objc_selector_type,
242 				   NULL_TREE);
243 
244   umsg_decl = add_builtin_function (TAG_MSGSEND,
245 				    type, 0, NOT_BUILT_IN,
246 				    NULL, NULL_TREE);
247   TREE_NOTHROW (umsg_decl) = 0;
248 
249   /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
250   type = build_function_type_list (IMP_type,
251 				   objc_super_type,
252 				   objc_selector_type,
253 				   NULL_TREE);
254 
255   umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
256 					  type, 0, NOT_BUILT_IN,
257 					  NULL, NULL_TREE);
258   TREE_NOTHROW (umsg_super_decl) = 0;
259 
260   /* The following GNU runtime entry point is called to initialize
261 	 each module:
262 
263 	 __objc_exec_class (void *); */
264   type = build_function_type_list (void_type_node,
265 				   ptr_type_node,
266 				   NULL_TREE);
267 
268   execclass_decl = add_builtin_function (TAG_EXECCLASS,
269 					 type, 0, NOT_BUILT_IN,
270 					 NULL, NULL_TREE);
271 
272   type = build_function_type_list (objc_object_type,
273 				   const_string_type_node,
274 				   NULL_TREE);
275 
276   /* id objc_getClass (const char *); */
277   objc_get_class_decl
278     = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
279 			    NULL, NULL_TREE);
280 
281   /* id objc_getMetaClass (const char *); */
282   objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS, type,
283 						   0, NOT_BUILT_IN, NULL,
284 						   NULL_TREE);
285 
286   /* static SEL _OBJC_SELECTOR_TABLE[]; */
287   build_selector_table_decl ();
288 
289   /* Stuff for properties.
290      The codegen relies on this being NULL for GNU.  */
291   objc_copyStruct_decl = NULL_TREE;
292 
293   /* This is the type of all of the following functions
294      bjc_getPropertyStruct() and objc_setPropertyStruct().  */
295   type = build_function_type_list (void_type_node,
296 				   ptr_type_node,
297 				   const_ptr_type_node,
298 				   ptrdiff_type_node,
299 				   boolean_type_node,
300 				   boolean_type_node,
301 				   NULL_TREE);
302 
303   /* Declare the following function:
304 	 void
305 	 objc_getPropertyStruct (void *destination, const void *source,
306                                  ptrdiff_t size, BOOL is_atomic, BOOL has_strong);  */
307   objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct",
308 							  type, 0, NOT_BUILT_IN,
309 							  NULL, NULL_TREE);
310   TREE_NOTHROW (objc_getPropertyStruct_decl) = 0;
311   /* Declare the following function:
312 	 void
313 	 objc_setPropertyStruct (void *destination, const void *source,
314 	                         ptrdiff_t size, BOOL is_atomic, BOOL has_strong);  */
315   objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct",
316 							  type, 0, NOT_BUILT_IN,
317 							  NULL, NULL_TREE);
318   TREE_NOTHROW (objc_setPropertyStruct_decl) = 0;
319 
320   using_eh_for_cleanups ();
321   lang_hooks.eh_runtime_type = objc_eh_runtime_type;
322   lang_hooks.eh_personality = objc_eh_personality;
323 }
324 
325 /* --- templates --- */
326 /* struct _objc_selector {
327      SEL sel_id;
328      char *sel_type;
329    }; */
330 
331 static void
332 build_selector_template (void)
333 {
334   tree decls, *chain = NULL;
335 
336   objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
337 
338   /* SEL sel_id; */
339   decls = add_field_decl (objc_selector_type, "sel_id", &chain);
340 
341   /* char *sel_type; */
342   add_field_decl (string_type_node, "sel_type", &chain);
343 
344   objc_finish_struct (objc_selector_template, decls);
345 }
346 
347 /* struct _objc_class {
348      struct _objc_class *isa;
349      struct _objc_class *super_class;
350      char *name;
351      long version;
352      long info;
353      long instance_size;
354      struct _objc_ivar_list *ivars;
355      struct _objc_method_list *methods;
356      struct sarray *dtable;
357      struct _objc_class *subclass_list;
358      struct _objc_class *sibling_class;
359      struct _objc_protocol_list *protocols;
360      void *gc_object_type;
361    };  */
362 
363 static void
364 build_class_template (void)
365 {
366   tree ptype, decls, *chain = NULL;
367 
368   objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
369 
370   /* struct _objc_class *isa; */
371   decls = add_field_decl (build_pointer_type (objc_class_template),
372 			  "isa", &chain);
373 
374   /* struct _objc_class *super_class; */
375   add_field_decl (build_pointer_type (objc_class_template),
376 		  "super_class", &chain);
377 
378   /* char *name; */
379   add_field_decl (string_type_node, "name", &chain);
380 
381   /* long version; */
382   add_field_decl (long_integer_type_node, "version", &chain);
383 
384   /* long info; */
385   add_field_decl (long_integer_type_node, "info", &chain);
386 
387   /* long instance_size; */
388   add_field_decl (long_integer_type_node, "instance_size", &chain);
389 
390   /* struct _objc_ivar_list *ivars; */
391   add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
392 
393   /* struct _objc_method_list *methods; */
394   add_field_decl (objc_method_list_ptr, "methods", &chain);
395 
396   /* struct sarray *dtable; */
397   ptype = build_pointer_type(xref_tag (RECORD_TYPE,
398 					   get_identifier ("sarray")));
399   add_field_decl (ptype, "dtable", &chain);
400 
401   /* struct objc_class *subclass_list; */
402   ptype = build_pointer_type (objc_class_template);
403   add_field_decl (ptype, "subclass_list", &chain);
404 
405   /* struct objc_class *sibling_class; */
406   ptype = build_pointer_type (objc_class_template);
407   add_field_decl (ptype, "sibling_class", &chain);
408 
409   /* struct _objc_protocol **protocol_list; */
410   ptype = build_pointer_type (build_pointer_type
411 			      (xref_tag (RECORD_TYPE,
412 					 get_identifier (UTAG_PROTOCOL))));
413   add_field_decl (ptype, "protocol_list", &chain);
414 
415   /* void *gc_object_type; */
416   add_field_decl (build_pointer_type (void_type_node),
417 		    "gc_object_type", &chain);
418 
419   objc_finish_struct (objc_class_template, decls);
420 }
421 
422 /* struct _objc_category {
423      char *category_name;
424      char *class_name;
425      struct _objc_method_list *instance_methods;
426      struct _objc_method_list *class_methods;
427      struct _objc_protocol_list *protocols;
428    };   */
429 
430 static void
431 build_category_template (void)
432 {
433   tree ptype, decls, *chain = NULL;
434 
435   objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
436 
437   /* char *category_name; */
438   decls = add_field_decl (string_type_node, "category_name", &chain);
439 
440   /* char *class_name; */
441   add_field_decl (string_type_node, "class_name", &chain);
442 
443   /* struct _objc_method_list *instance_methods; */
444   add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
445 
446   /* struct _objc_method_list *class_methods; */
447   add_field_decl (objc_method_list_ptr, "class_methods", &chain);
448 
449   /* struct _objc_protocol **protocol_list; */
450   ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
451   add_field_decl (ptype, "protocol_list", &chain);
452 
453   objc_finish_struct (objc_category_template, decls);
454 }
455 
456 /* struct _objc_protocol {
457      struct _objc_class *isa;
458      char *protocol_name;
459      struct _objc_protocol **protocol_list;
460      struct _objc__method_prototype_list *instance_methods;
461      struct _objc__method_prototype_list *class_methods;
462    };  */
463 
464 static void
465 build_protocol_template (void)
466 {
467   tree ptype, decls, *chain = NULL;
468 
469   objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
470 
471   /* struct _objc_class *isa; */
472   ptype = build_pointer_type (xref_tag (RECORD_TYPE,
473 					get_identifier (UTAG_CLASS)));
474   decls = add_field_decl (ptype, "isa", &chain);
475 
476   /* char *protocol_name; */
477   add_field_decl (string_type_node, "protocol_name", &chain);
478 
479   /* struct _objc_protocol **protocol_list; */
480   ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
481   add_field_decl (ptype, "protocol_list", &chain);
482 
483   /* struct _objc__method_prototype_list *instance_methods; */
484   add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
485 
486   /* struct _objc__method_prototype_list *class_methods; */
487   add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
488 
489   objc_finish_struct (objc_protocol_template, decls);
490 }
491 
492 /* --- names, decls + identifiers --- */
493 
494 static void
495 build_selector_table_decl (void)
496 {
497   tree temp;
498 
499   build_selector_template ();
500   temp = build_array_type (objc_selector_template, NULL_TREE);
501 
502   UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
503   OBJCMETA (UOBJC_SELECTOR_TABLE_decl, objc_meta, meta_base);
504 }
505 
506 
507 static tree
508 gnu_runtime_abi_01_super_superclassfield_id (void)
509 {
510   if (!super_superclassfield_id)
511     super_superclassfield_id = get_identifier ("super_class");
512   return super_superclassfield_id;
513 }
514 
515 
516 static tree
517 gnu_runtime_abi_01_class_decl (tree klass)
518 {
519   tree decl;
520   char buf[BUFSIZE];
521   snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
522 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
523   decl = start_var_decl (objc_class_template, buf);
524   OBJCMETA (decl, objc_meta, meta_base);
525   return decl;
526 }
527 
528 static tree
529 gnu_runtime_abi_01_metaclass_decl (tree klass)
530 {
531   tree decl;
532   char buf[BUFSIZE];
533   snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
534 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
535   decl = start_var_decl (objc_class_template, buf);
536   OBJCMETA (decl, objc_meta, meta_base);
537   return decl;
538 }
539 
540 static tree
541 gnu_runtime_abi_01_category_decl (tree klass)
542 {
543   tree decl;
544   char buf[BUFSIZE];
545   snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
546 	    IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
547 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
548   decl = start_var_decl (objc_category_template, buf);
549   OBJCMETA (decl, objc_meta, meta_base);
550   return decl;
551 }
552 
553 static tree
554 gnu_runtime_abi_01_protocol_decl (tree p)
555 {
556   tree decl;
557   char buf[BUFSIZE];
558 
559   /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
560   snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
561 	    IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
562   decl = start_var_decl (objc_protocol_template, buf);
563   OBJCMETA (decl, objc_meta, meta_base);
564   return decl;
565 }
566 
567 static tree
568 gnu_runtime_abi_01_string_decl (tree type, const char *name,
569 				string_section where ATTRIBUTE_UNUSED)
570 {
571   tree decl = start_var_decl (type, name);
572   OBJCMETA (decl, objc_meta, meta_base);
573   return decl;
574 }
575 
576 /* --- entry --- */
577 
578 static tree
579 gnu_runtime_abi_01_get_class_reference (tree ident)
580 {
581   tree params;
582 
583   add_class_reference (ident);
584 
585   params = build_tree_list (NULL_TREE, my_build_string_pointer
586 						(IDENTIFIER_LENGTH (ident) + 1,
587 						 IDENTIFIER_POINTER (ident)));
588 
589   return build_function_call (input_location, objc_get_class_decl, params);
590 }
591 
592 /* Used by build_function_type_for_method.  Append the types for
593    receiver & _cmd at the start of a method argument list to ARGTYPES.
594    CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
595    trying to define a method or call one.  SUPERFLAG says this is for a
596    send to super.  METH may be NULL, in the case that there is no
597    prototype.  */
598 
599 static void
600 gnu_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
601 					   tree meth, int context,
602 					   int superflag ATTRIBUTE_UNUSED)
603 {
604   tree receiver_type;
605 
606   if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
607     receiver_type = objc_instance_type;
608   else
609     receiver_type = objc_object_type;
610 
611   vec_safe_push (*argtypes, receiver_type);
612   /* Selector type - will eventually change to `int'.  */
613   vec_safe_push (*argtypes, objc_selector_type);
614 }
615 
616 /* Unused for GNU runtime.  */
617 static tree
618 gnu_runtime_abi_01_receiver_is_class_object (tree a ATTRIBUTE_UNUSED)
619 {
620   return NULL_TREE;
621 }
622 
623 /* sel_ref_chain is a list whose "value" fields will be instances of
624    identifier_node that represent the selector.  LOC is the location of
625    the @selector.  */
626 
627 static tree
628 gnu_runtime_abi_01_build_typed_selector_reference (location_t loc, tree ident,
629 						   tree prototype)
630 {
631   tree *chain = &sel_ref_chain;
632   tree expr;
633   int index = 0;
634 
635   while (*chain)
636     {
637       /* When we do a lookup for @selector () we have no idea of the
638          prototype - so match the first we find.  */
639       if (TREE_VALUE (*chain) == ident
640           && (!prototype || TREE_PURPOSE (*chain) == prototype))
641 	goto return_at_index;
642 
643       index++;
644       chain = &TREE_CHAIN (*chain);
645     }
646 
647   *chain = tree_cons (prototype, ident, NULL_TREE);
648 
649   /* TODO: Use a vec and keep this in it to (a) avoid re-creating and
650      (b) provide better diagnostics for the first time an undefined
651      selector is used.  */
652  return_at_index:
653   expr = build_unary_op (loc, ADDR_EXPR,
654 			 build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
655 					  build_int_cst (NULL_TREE, index)),
656 			 1);
657   return convert (objc_selector_type, expr);
658 }
659 
660 /* Build a tree expression to send OBJECT the operation SELECTOR,
661    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
662    assuming the method has prototype METHOD_PROTOTYPE.
663    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
664    LOC is the location of the expression to build.
665    Use METHOD_PARAMS as list of args to pass to the method.
666    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
667 
668 static tree
669 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
670 			tree lookup_object, tree selector,
671 			tree method_params)
672 {
673   tree sender = (super_flag ? umsg_super_decl
674 			    : (flag_objc_direct_dispatch ? umsg_fast_decl
675 							 : umsg_decl));
676   tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
677   vec<tree, va_gc> *parms;
678   vec<tree, va_gc> *tv;
679   unsigned nparm = (method_params ? list_length (method_params) : 0);
680 
681   /* If a prototype for the method to be called exists, then cast
682      the sender's return type and arguments to match that of the method.
683      Otherwise, leave sender as is.  */
684   tree ret_type
685     = (method_prototype
686        ? TREE_VALUE (TREE_TYPE (method_prototype))
687        : objc_object_type);
688   tree ftype
689     = build_function_type_for_method (ret_type, method_prototype,
690 				      METHOD_REF, super_flag);
691   tree sender_cast;
692   tree method, t;
693 
694   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
695     ftype = build_type_attribute_variant (ftype,
696 					  METHOD_TYPE_ATTRIBUTES
697 					  (method_prototype));
698 
699   sender_cast = build_pointer_type (ftype);
700 
701   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
702 
703   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
704   lookup_object = save_expr (lookup_object);
705 
706   /* Param list + 2 slots for object and selector.  */
707   vec_alloc (parms, nparm + 2);
708   vec_alloc (tv, 2);
709 
710   /* First, call the lookup function to get a pointer to the method,
711      then cast the pointer, then call it with the method arguments.  */
712   tv->quick_push (lookup_object);
713   tv->quick_push (selector);
714   method = build_function_call_vec (loc, vNULL, sender, tv, NULL);
715   vec_free (tv);
716 
717   /* Pass the appropriate object to the method.  */
718   parms->quick_push ((super_flag ? self_decl : lookup_object));
719 
720   /* Pass the selector to the method.  */
721   parms->quick_push (selector);
722   /* Now append the remainder of the parms.  */
723   if (nparm)
724     for (; method_params; method_params = TREE_CHAIN (method_params))
725       parms->quick_push (TREE_VALUE (method_params));
726 
727   /* Build an obj_type_ref, with the correct cast for the method call.  */
728   t = build3 (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
729   t = build_function_call_vec (loc, vNULL, t, parms, NULL);
730   vec_free (parms);
731   return t;
732 }
733 
734 static tree
735 gnu_runtime_abi_01_build_objc_method_call (location_t loc,
736 					   tree method_prototype,
737 					   tree receiver,
738 					   tree rtype ATTRIBUTE_UNUSED,
739 					   tree sel_name,
740 					   tree method_params,
741 					   int super ATTRIBUTE_UNUSED)
742 {
743   tree selector =
744 	gnu_runtime_abi_01_build_typed_selector_reference (loc,
745 							  sel_name,
746 							  method_prototype);
747 
748   return build_objc_method_call (loc, super, method_prototype, receiver,
749 				 selector, method_params);
750 }
751 
752 static tree
753 gnu_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
754 {
755   tree expr, protocol_struct_type, *chain;
756   if (!PROTOCOL_FORWARD_DECL (p))
757     PROTOCOL_FORWARD_DECL (p) = gnu_runtime_abi_01_protocol_decl (p);
758 
759   expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
760 
761   /* ??? Ideally we'd build the reference with objc_protocol_type directly,
762      if we have it, rather than converting it here.  */
763   expr = convert (objc_protocol_type, expr);
764 
765   /* The @protocol() expression is being compiled into a pointer to a
766      statically allocated instance of the Protocol class.  To become
767      usable at runtime, the 'isa' pointer of the instance need to be
768      fixed up at runtime by the runtime library, to point to the
769      actual 'Protocol' class.  */
770 
771   /* For the GNU runtime, put the static Protocol instance in the list
772      of statically allocated instances, so that we make sure that its
773      'isa' pointer is fixed up at runtime by the GNU runtime library
774      to point to the Protocol class (at runtime, when loading the
775      module, the GNU runtime library loops on the statically allocated
776      instances (as found in the defs field in objc_symtab) and fixups
777      all the 'isa' pointers of those objects).  */
778 
779   /* This type is a struct containing the fields of a Protocol
780      object.  (Cfr. objc_protocol_type instead is the type of a pointer
781      to such a struct).  */
782   protocol_struct_type = xref_tag (RECORD_TYPE,
783 				   get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
784 
785   /* Look for the list of Protocol statically allocated instances
786      to fixup at runtime.  Create a new list to hold Protocol
787      statically allocated instances, if the list is not found.  At
788      present there is only another list, holding NSConstantString
789      static instances to be fixed up at runtime.  */
790 
791   for (chain = &objc_static_instances;
792 	*chain && TREE_VALUE (*chain) != protocol_struct_type;
793 	chain = &TREE_CHAIN (*chain));
794 
795   if (!*chain)
796     {
797        *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
798        add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
799                           class_names);
800     }
801 
802   /* Add this statically allocated instance to the Protocol list.  */
803   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
804 				     PROTOCOL_FORWARD_DECL (p),
805 				     TREE_PURPOSE (*chain));
806   return expr;
807 }
808 
809 /* For ABI 8 an IVAR is just a fixed offset in the class struct.  */
810 
811 static tree
812 gnu_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
813 				   tree base, tree id)
814 {
815   return objc_build_component_ref (base, id);
816 }
817 
818 /* We build super class references as we need them (but keep them once
819    built for the sake of efficiency).  */
820 
821 static tree
822 gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
823 					struct imp_entry *imp, bool inst_meth)
824 {
825   if (inst_meth)
826     {
827       if (!ucls_super_ref)
828 	ucls_super_ref =
829 		objc_build_component_ref (imp->class_decl,
830 					  get_identifier ("super_class"));
831 	return ucls_super_ref;
832     }
833   else
834     {
835       if (!uucls_super_ref)
836 	uucls_super_ref =
837 		objc_build_component_ref (imp->meta_decl,
838 					  get_identifier ("super_class"));
839 	return uucls_super_ref;
840     }
841 }
842 
843 static tree
844 gnu_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
845 					   struct imp_entry *imp, bool inst_meth)
846 {
847   tree super_name = CLASS_SUPER_NAME (imp->imp_template);
848   tree super_class;
849 
850   add_class_reference (super_name);
851   super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
852   super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
853 					IDENTIFIER_POINTER (super_name));
854   /* super_class = get_{meta_}class("CLASS_SUPER_NAME");  */
855   return build_function_call (input_location,
856 			      super_class,
857 			      build_tree_list (NULL_TREE, super_name));
858 }
859 
860 static bool
861 gnu_runtime_abi_01_setup_const_string_class_decl (void)
862 {
863   /* Do nothing, and create no error.  */
864   return true;
865 }
866 
867 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
868 
869 static GTY(()) int num_static_inst;
870 
871 static tree
872 objc_add_static_instance (tree constructor, tree class_decl)
873 {
874   tree *chain, decl;
875   char buf[BUFSIZE];
876 
877   /* Find the list of static instances for the CLASS_DECL.  Create one if
878      not found.  */
879   for (chain = &objc_static_instances;
880        *chain && TREE_VALUE (*chain) != class_decl;
881        chain = &TREE_CHAIN (*chain));
882   if (!*chain)
883     {
884       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
885       add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
886     }
887 
888   snprintf (buf, BUFSIZE, "_OBJC_INSTANCE_%d", num_static_inst++);
889   decl = build_decl (input_location,
890 		     VAR_DECL, get_identifier (buf), class_decl);
891   TREE_STATIC (decl) = 1;
892   DECL_ARTIFICIAL (decl) = 1;
893   TREE_USED (decl) = 1;
894   DECL_INITIAL (decl) = constructor;
895   DECL_CONTEXT (decl) = NULL;
896   OBJCMETA (decl, objc_meta, meta_base);
897 
898   /* We may be writing something else just now.
899      Postpone till end of input. */
900   DECL_DEFER_OUTPUT (decl) = 1;
901   pushdecl_top_level (decl);
902   rest_of_decl_compilation (decl, 1, 0);
903 
904   /* Add the DECL to the head of this CLASS' list.  */
905   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
906 
907   return decl;
908 }
909 
910 static tree
911 gnu_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
912 						   int length)
913 {
914   tree constructor, fields;
915   vec<constructor_elt, va_gc> *v = NULL;
916 
917   /* GNU:    (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length })  */
918   fields = TYPE_FIELDS (internal_const_str_type);
919   CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, 0));
920 
921   fields = DECL_CHAIN (fields);
922   CONSTRUCTOR_APPEND_ELT (v, fields, build_unary_op (loc,
923 						     ADDR_EXPR, string, 1));
924 
925   fields = DECL_CHAIN (fields);
926   CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
927   constructor = objc_build_constructor (internal_const_str_type, v);
928 
929   constructor = objc_add_static_instance (constructor, constant_string_type);
930   return constructor;
931 }
932 
933 /* --- metadata - module initializer --- */
934 
935 /* The GNU runtime requires us to provide a static initializer function
936    for each module:
937 
938    static void __objc_gnu_init (void) {
939      __objc_exec_class (&L_OBJC_MODULES);
940    }  */
941 
942 
943 static void
944 build_module_initializer_routine (void)
945 {
946   tree body;
947 
948 #ifdef OBJCPLUS
949   push_lang_context (lang_name_c); /* extern "C" */
950 #endif
951 
952   objc_push_parm (build_decl (input_location,
953 			      PARM_DECL, NULL_TREE, void_type_node));
954 #ifdef OBJCPLUS
955   objc_start_function (get_identifier (TAG_GNUINIT),
956 		       build_function_type_list (void_type_node, NULL_TREE),
957 		       NULL_TREE, NULL_TREE);
958 #else
959   objc_start_function (get_identifier (TAG_GNUINIT),
960 		       build_function_type_list (void_type_node, NULL_TREE),
961 		       NULL_TREE, objc_get_parm_info (0, NULL_TREE));
962 #endif
963   body = c_begin_compound_stmt (true);
964   add_stmt (build_function_call
965 	    (input_location,
966 	     execclass_decl,
967 	     build_tree_list
968 	     (NULL_TREE,
969 	      build_unary_op (input_location, ADDR_EXPR,
970 			      UOBJC_MODULES_decl, 0))));
971   add_stmt (c_end_compound_stmt (input_location, body, true));
972 
973   TREE_PUBLIC (current_function_decl) = 0;
974 
975 #ifndef OBJCPLUS
976   /* For Objective-C++, we will need to call __objc_gnu_init
977      from objc_generate_static_init_call() below.  */
978   DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
979 #endif
980 
981   GNU_INIT_decl = current_function_decl;
982   finish_function ();
983 
984 #ifdef OBJCPLUS
985     pop_lang_context ();
986 #endif
987 }
988 
989 #ifdef OBJCPLUS
990 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
991    to be called by the module initializer routine.  */
992 
993 int
994 objc_static_init_needed_p (void)
995 {
996   return (GNU_INIT_decl != NULL_TREE);
997 }
998 
999 /* Generate a call to the __objc_gnu_init initializer function.  */
1000 
1001 tree
1002 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
1003 {
1004   add_stmt (build_stmt (input_location, EXPR_STMT,
1005 			build_function_call (input_location,
1006 					     GNU_INIT_decl, NULL_TREE)));
1007 
1008   return ctors;
1009 }
1010 #endif /* OBJCPLUS */
1011 
1012 /* --- Output GNU Meta-data --- */
1013 
1014 static void
1015 generate_classref_translation_entry (tree chain)
1016 {
1017   tree expr, decl, type;
1018 
1019   decl = TREE_PURPOSE (chain);
1020   type = TREE_TYPE (decl);
1021 
1022   expr = add_objc_string (TREE_VALUE (chain), class_names);
1023   expr = convert (type, expr); /* cast! */
1024 
1025   /* This is a class reference.  It is re-written by the runtime,
1026      but will be optimized away unless we force it.  */
1027   DECL_PRESERVE_P (decl) = 1;
1028   OBJCMETA (decl, objc_meta, meta_base);
1029   finish_var_decl (decl, expr);
1030   return;
1031 }
1032 
1033 
1034 static void
1035 handle_impent (struct imp_entry *impent)
1036 {
1037   char *string;
1038 
1039 /*  objc_implementation_context = impent->imp_context;
1040   implementation_template = impent->imp_template;*/
1041 
1042   switch (TREE_CODE (impent->imp_context))
1043     {
1044     case CLASS_IMPLEMENTATION_TYPE:
1045       {
1046 	const char *const class_name =
1047 	  IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1048 
1049 	string = (char *) alloca (strlen (class_name) + 30);
1050 
1051 	sprintf (string, "__objc_class_name_%s", class_name);
1052 	break;
1053       }
1054     case CATEGORY_IMPLEMENTATION_TYPE:
1055       {
1056 	const char *const class_name =
1057 	  IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1058 	const char *const class_super_name =
1059 	  IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
1060 
1061 	string = (char *) alloca (strlen (class_name)
1062 				  + strlen (class_super_name) + 30);
1063 
1064 	/* Do the same for categories.  Even though no references to
1065 	   these symbols are generated automatically by the compiler,
1066 	   it gives you a handle to pull them into an archive by
1067 	   hand.  */
1068 	sprintf (string, "*__objc_category_name_%s_%s", class_name, class_super_name);
1069 	break;
1070       }
1071     default:
1072       return;
1073     }
1074 
1075     {
1076       tree decl, init;
1077 
1078       init = integer_zero_node;
1079       decl = build_decl (input_location,
1080 			 VAR_DECL, get_identifier (string), TREE_TYPE (init));
1081       TREE_PUBLIC (decl) = 1;
1082       TREE_READONLY (decl) = 1;
1083       TREE_USED (decl) = 1;
1084       TREE_CONSTANT (decl) = 1;
1085       DECL_CONTEXT (decl) = NULL_TREE;
1086       DECL_ARTIFICIAL (decl) = 1;
1087       TREE_STATIC (decl) = 1;
1088       DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
1089       /* We must force the reference.  */
1090       DECL_PRESERVE_P (decl) = 1;
1091 
1092       finish_var_decl(decl, init) ;
1093     }
1094 }
1095 
1096 tree
1097 build_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1098 			    tree inst_methods, tree class_methods)
1099 {
1100   tree expr, ttyp;
1101   location_t loc;
1102   vec<constructor_elt, va_gc> *inits = NULL;
1103 
1104   /* TODO: pass the loc in or find it from args.  */
1105   loc = input_location;
1106   ttyp = build_pointer_type (xref_tag (RECORD_TYPE,
1107 				       get_identifier (UTAG_CLASS)));
1108   /* Filling the "isa" in with a version allows the runtime system to
1109      detect this ...   */
1110   expr = build_int_cst (ttyp, PROTOCOL_VERSION);
1111 
1112   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1113 
1114   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1115   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1116 
1117   ttyp = objc_method_proto_list_ptr;
1118   if (inst_methods)
1119     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1120   else
1121     expr = convert (ttyp, null_pointer_node);
1122   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1123 
1124   if (class_methods)
1125     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1126   else
1127     expr = convert (ttyp, null_pointer_node);
1128   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1129 
1130   return objc_build_constructor (type, inits);
1131 }
1132 
1133 static tree
1134 generate_protocol_list (tree i_or_p, tree klass_ctxt)
1135 {
1136   tree array_type, ptype, refs_decl, lproto, e, plist;
1137   vec<constructor_elt, va_gc> *v = NULL;
1138   char buf[BUFSIZE];
1139   int size = 0;
1140 
1141   switch (TREE_CODE (i_or_p))
1142     {
1143     case CLASS_INTERFACE_TYPE:
1144     case CATEGORY_INTERFACE_TYPE:
1145       plist = CLASS_PROTOCOL_LIST (i_or_p);
1146       break;
1147     case PROTOCOL_INTERFACE_TYPE:
1148       plist = PROTOCOL_LIST (i_or_p);
1149       break;
1150     default:
1151       gcc_unreachable ();
1152     }
1153 
1154   /* Compute size.  */
1155   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1156     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1157 	&& PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1158       size++;
1159 
1160   /* Build initializer.  */
1161   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1162   e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1163   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1164 
1165   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1166     {
1167       tree pval = TREE_VALUE (lproto);
1168 
1169       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1170 	  && PROTOCOL_FORWARD_DECL (pval))
1171 	{
1172 	  tree fwref = PROTOCOL_FORWARD_DECL (pval);
1173 	  location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1174 	  e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1175           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1176 	}
1177     }
1178 
1179   /* static struct objc_protocol *refs[n]; */
1180 
1181   switch (TREE_CODE (i_or_p))
1182     {
1183     case PROTOCOL_INTERFACE_TYPE:
1184       snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1185 		IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1186       break;
1187     case CLASS_INTERFACE_TYPE:
1188       snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1189 		IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1190       break;
1191     case CATEGORY_INTERFACE_TYPE:
1192       snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1193 		IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1194 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1195       break;
1196     default:
1197       gcc_unreachable ();
1198     }
1199 
1200   ptype = build_pointer_type (objc_protocol_template);
1201   array_type = build_sized_array_type (ptype, size + 3);
1202   refs_decl = start_var_decl (array_type, buf);
1203   OBJCMETA (refs_decl, objc_meta, meta_base);
1204   finish_var_decl (refs_decl,
1205                    objc_build_constructor (TREE_TYPE (refs_decl), v));
1206 
1207   return refs_decl;
1208 }
1209 
1210 static tree
1211 generate_v1_meth_descriptor_table (tree chain, tree protocol, const char *prefix)
1212 {
1213   tree method_list_template, initlist, decl;
1214   int size;
1215   vec<constructor_elt, va_gc> *v = NULL;
1216   char buf[BUFSIZE];
1217 
1218   if (!chain || !prefix)
1219     return NULL_TREE;
1220 
1221   if (!objc_method_prototype_template)
1222     objc_method_prototype_template = build_method_prototype_template ();
1223 
1224   size = list_length (chain);
1225   method_list_template =
1226 	build_method_prototype_list_template (objc_method_prototype_template,
1227 					      size);
1228   snprintf (buf, BUFSIZE, "%s_%s", prefix,
1229 	    IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1230 
1231   decl = start_var_decl (method_list_template, buf);
1232 
1233   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1234   initlist =
1235 	build_descriptor_table_initializer (objc_method_prototype_template,
1236 					    chain);
1237   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1238   OBJCMETA (decl, objc_meta, meta_base);
1239   finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1240   return decl;
1241 }
1242 
1243 /* For each protocol which was referenced either from a @protocol()
1244    expression, or because a class/category implements it (then a
1245    pointer to the protocol is stored in the struct describing the
1246    class/category), we create a statically allocated instance of the
1247    Protocol class.  The code is written in such a way as to generate
1248    as few Protocol objects as possible; we generate a unique Protocol
1249    instance for each protocol, and we don't generate a Protocol
1250    instance if the protocol is never referenced (either from a
1251    @protocol() or from a class/category implementation).  These
1252    statically allocated objects can be referred to via the static
1253    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1254 
1255    The statically allocated Protocol objects that we generate here
1256    need to be fixed up at runtime in order to be used: the 'isa'
1257    pointer of the objects need to be set up to point to the 'Protocol'
1258    class, as known at runtime.
1259 
1260    The GNU runtime fixes up all protocols before user code from the module
1261    is executed; it requires pointers to those symbols
1262    to be put in the objc_symtab (which is then passed as argument to
1263    the function __objc_exec_class() which the compiler sets up to be
1264    executed automatically when the module is loaded); setup of those
1265    Protocol objects happen in two ways in the GNU runtime: all
1266    Protocol objects referred to by a class or category implementation
1267    are fixed up when the class/category is loaded; all Protocol
1268    objects referred to by a @protocol() expression are added by the
1269    compiler to the list of statically allocated instances to fixup
1270    (the same list holding the statically allocated constant string
1271    objects).  Because, as explained above, the compiler generates as
1272    few Protocol objects as possible, some Protocol object might end up
1273    being referenced multiple times when compiled with the GNU runtime,
1274    and end up being fixed up multiple times at runtime initialization.
1275    But that doesn't hurt, it's just a little inefficient.  */
1276 
1277 static void
1278 generate_protocols (void)
1279 {
1280   tree p, encoding;
1281   tree decl;
1282   tree initlist, protocol_name_expr, refs_decl, refs_expr;
1283 
1284   /* If a protocol was directly referenced, pull in indirect references.  */
1285   for (p = protocol_chain; p; p = TREE_CHAIN (p))
1286     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1287       generate_protocol_references (PROTOCOL_LIST (p));
1288 
1289   for (p = protocol_chain; p; p = TREE_CHAIN (p))
1290     {
1291       tree nst_methods = PROTOCOL_NST_METHODS (p);
1292       tree cls_methods = PROTOCOL_CLS_METHODS (p);
1293 
1294       /* If protocol wasn't referenced, don't generate any code.  */
1295       decl = PROTOCOL_FORWARD_DECL (p);
1296 
1297       if (!decl)
1298 	continue;
1299 
1300       /* Make sure we link in the Protocol class.  */
1301       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1302 
1303       while (nst_methods)
1304 	{
1305 	  if (! METHOD_ENCODING (nst_methods))
1306 	    {
1307 	      encoding = encode_method_prototype (nst_methods);
1308 	      METHOD_ENCODING (nst_methods) = encoding;
1309 	    }
1310 	  nst_methods = DECL_CHAIN (nst_methods);
1311 	}
1312 
1313       UOBJC_INSTANCE_METHODS_decl =
1314 	generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1315 					   "_OBJC_PROTOCOL_INSTANCE_METHODS");
1316 
1317       while (cls_methods)
1318 	{
1319 	  if (! METHOD_ENCODING (cls_methods))
1320 	    {
1321 	      encoding = encode_method_prototype (cls_methods);
1322 	      METHOD_ENCODING (cls_methods) = encoding;
1323 	    }
1324 
1325 	  cls_methods = DECL_CHAIN (cls_methods);
1326 	}
1327 
1328       UOBJC_CLASS_METHODS_decl =
1329 	generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1330 					   "_OBJC_PROTOCOL_CLASS_METHODS");
1331 /*      generate_method_descriptors (p);*/
1332 
1333       if (PROTOCOL_LIST (p))
1334 	refs_decl = generate_protocol_list (p, NULL_TREE);
1335       else
1336 	refs_decl = 0;
1337 
1338       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1339       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1340 
1341       if (refs_decl)
1342 	refs_expr = convert (build_pointer_type (build_pointer_type
1343 						 (objc_protocol_template)),
1344 			     build_unary_op (input_location,
1345 					     ADDR_EXPR, refs_decl, 0));
1346       else
1347 	refs_expr = build_int_cst (NULL_TREE, 0);
1348 
1349       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
1350 	 by generate_method_descriptors, which is called above.  */
1351       initlist = build_protocol_initializer (TREE_TYPE (decl),
1352 					     protocol_name_expr, refs_expr,
1353 					     UOBJC_INSTANCE_METHODS_decl,
1354 					     UOBJC_CLASS_METHODS_decl);
1355       finish_var_decl (decl, initlist);
1356     }
1357 }
1358 
1359 static tree
1360 generate_dispatch_table (tree chain, const char *name)
1361 {
1362   tree decl, method_list_template, initlist;
1363   vec<constructor_elt, va_gc> *v = NULL;
1364   int size = list_length (chain);
1365 
1366   if (!objc_method_template)
1367     objc_method_template = build_method_template ();
1368 
1369   method_list_template = build_method_list_template (objc_method_template,
1370 						     size);
1371   initlist = build_dispatch_table_initializer (objc_method_template, chain);
1372 
1373   decl = start_var_decl (method_list_template, name);
1374 
1375   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1376   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1377 			  build_int_cst (integer_type_node, size));
1378   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1379 
1380   OBJCMETA (decl, objc_meta, meta_base);
1381   finish_var_decl (decl,
1382 		   objc_build_constructor (TREE_TYPE (decl), v));
1383 
1384   return decl;
1385 }
1386 
1387 /* Init a category.  */
1388 static tree
1389 build_category_initializer (tree type, tree cat_name, tree class_name,
1390 			    tree inst_methods, tree class_methods,
1391 			    tree protocol_list)
1392 {
1393   tree expr, ltyp;
1394   location_t loc;
1395   vec<constructor_elt, va_gc> *v = NULL;
1396 
1397   /* TODO: pass the loc in or find it from args.  */
1398   /* TODO: pass the loc in or find it from args.  */
1399   loc = UNKNOWN_LOCATION;
1400   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1401   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1402 
1403   ltyp = objc_method_list_ptr;
1404   if (inst_methods)
1405     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1406   else
1407     expr = convert (ltyp, null_pointer_node);
1408   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1409 
1410   if (class_methods)
1411     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1412   else
1413     expr = convert (ltyp, null_pointer_node);
1414   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1415 
1416   /* protocol_list = */
1417   ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1418   if (protocol_list)
1419     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1420   else
1421     expr = convert (ltyp, null_pointer_node);
1422   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1423 
1424   return objc_build_constructor (type, v);
1425 }
1426 
1427 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
1428 
1429 static void
1430 generate_category (struct imp_entry *impent)
1431 {
1432   tree initlist, cat_name_expr, class_name_expr;
1433   tree protocol_decl, category, cat_decl;
1434   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1435   tree cat = impent->imp_context;
1436   char buf[BUFSIZE];
1437 
1438   cat_decl = impent->class_decl;
1439 
1440   add_class_reference (CLASS_NAME (cat));
1441   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1442 
1443   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1444 
1445   category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1446 
1447   if (category && CLASS_PROTOCOL_LIST (category))
1448     {
1449       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1450       protocol_decl = generate_protocol_list (category, cat);
1451     }
1452   else
1453     protocol_decl = 0;
1454 
1455   if (CLASS_NST_METHODS (cat))
1456     {
1457       snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1458 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
1459 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1460       inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf);
1461     }
1462 
1463   if (CLASS_CLS_METHODS (cat))
1464     {
1465       snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1466 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
1467 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1468       class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf);
1469     }
1470 
1471   initlist = build_category_initializer (TREE_TYPE (cat_decl),
1472 					 cat_name_expr, class_name_expr,
1473 					 inst_methods, class_methods,
1474 					 protocol_decl);
1475   /* Finish and initialize the forward decl.  */
1476   finish_var_decl (cat_decl, initlist);
1477   impent->class_decl = cat_decl;
1478 }
1479 
1480 /* struct _objc_class {
1481      struct objc_class *isa;
1482      struct objc_class *super_class;
1483      char *name;
1484      long version;
1485      long info;
1486      long instance_size;
1487      struct objc_ivar_list *ivars;
1488      struct objc_method_list *methods;
1489      struct sarray *dtable;
1490      struct objc_class *subclass_list;
1491      struct objc_class *sibling_class;
1492      struct objc_protocol_list *protocols;
1493      void *gc_object_type;
1494    };  */
1495 
1496 static tree
1497 build_shared_structure_initializer (tree type, tree isa, tree super,
1498 				    tree name, tree size, int status,
1499 				    tree dispatch_table, tree ivar_list,
1500 				    tree protocol_list)
1501 {
1502   tree expr, ltyp;
1503   vec<constructor_elt, va_gc> *v = NULL;
1504 
1505   /* isa = */
1506   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1507 
1508   /* super_class = */
1509   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1510 
1511   /* name = */
1512   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1513 
1514   /* version = */
1515   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1516                           build_int_cst (long_integer_type_node, 0));
1517 
1518   /* info = */
1519   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1520                           build_int_cst (long_integer_type_node, status));
1521 
1522   /* instance_size = */
1523   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1524                           convert (long_integer_type_node, size));
1525 
1526   /* objc_ivar_list = */
1527   if (!ivar_list)
1528     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1529 			    build_int_cst (objc_ivar_list_ptr, 0));
1530   else
1531     {
1532       expr = convert (objc_ivar_list_ptr,
1533 		      build_unary_op (input_location, ADDR_EXPR,
1534 				      ivar_list, 0));
1535       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1536     }
1537 
1538   /* objc_method_list = */
1539   if (!dispatch_table)
1540     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1541 			   convert (objc_method_list_ptr, null_pointer_node));
1542   else
1543     {
1544       expr = convert (objc_method_list_ptr,
1545 		      build_unary_op (input_location, ADDR_EXPR,
1546 				      dispatch_table, 0));
1547       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1548     }
1549 
1550   /* FIXME: Remove NeXT runtime code.  */
1551   if (flag_next_runtime)
1552     {
1553       ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
1554 					   get_identifier ("objc_cache")));
1555       /* method_cache = */
1556       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
1557     }
1558   else
1559     {
1560       /* dtable = */
1561       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1562 
1563       /* subclass_list = */
1564       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1565 
1566       /* sibling_class = */
1567       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1568     }
1569 
1570   /* protocol_list = */
1571   ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1572   if (! protocol_list)
1573     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (ltyp, 0));
1574   else
1575     {
1576       expr = convert (ltyp,
1577 		      build_unary_op (input_location, ADDR_EXPR,
1578 				      protocol_list, 0));
1579       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1580     }
1581 
1582   /* FIXME: Remove NeXT runtime code.  */
1583   if (flag_next_runtime)
1584     /* sel_id = NULL */
1585     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1586 
1587   /* gc_object_type = NULL */
1588   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1589 
1590   return objc_build_constructor (type, v);
1591 }
1592 
1593 
1594 static tree
1595 generate_ivars_list (tree chain, const char *name)
1596 {
1597   tree initlist, ivar_list_template, decl;
1598   int size;
1599   vec<constructor_elt, va_gc> *inits = NULL;
1600 
1601   if (!chain)
1602     return NULL_TREE;
1603 
1604   if (!objc_ivar_template)
1605     objc_ivar_template = build_ivar_template ();
1606 
1607   size = ivar_list_length (chain);
1608 
1609   generating_instance_variables = 1;
1610   ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1611   initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1612   generating_instance_variables = 0;
1613 
1614   decl = start_var_decl (ivar_list_template, name);
1615 
1616   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1617   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1618 
1619   OBJCMETA (decl, objc_meta, meta_base);
1620   finish_var_decl (decl,
1621 		   objc_build_constructor (TREE_TYPE (decl), inits));
1622 
1623   return decl;
1624 }
1625 
1626 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1627    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
1628 
1629 static void
1630 generate_class_structures (struct imp_entry *impent)
1631 {
1632   tree name_expr, super_expr, root_expr, class_decl, meta_decl;
1633   tree my_root_id, my_super_id;
1634   tree cast_type, initlist, protocol_decl;
1635   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1636   tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
1637   location_t loc;
1638   char buf[BUFSIZE];
1639   int cls_flags = 0 ;
1640 
1641 /*  objc_implementation_context = impent->imp_context;
1642   implementation_template = impent->imp_template;*/
1643   class_decl = impent->class_decl;
1644   meta_decl = impent->meta_decl;
1645 /*  UOBJC_CLASS_decl = impent->class_decl;
1646   UOBJC_METACLASS_decl = impent->meta_decl;*/
1647 
1648   loc = DECL_SOURCE_LOCATION (impent->class_decl);
1649 
1650   my_super_id = CLASS_SUPER_NAME (impent->imp_template);
1651   if (my_super_id)
1652     {
1653       add_class_reference (my_super_id);
1654 
1655       /* Compute "my_root_id" - this is required for code generation.
1656          the "isa" for all meta class structures points to the root of
1657          the inheritance hierarchy (e.g. "__Object")...  */
1658       my_root_id = my_super_id;
1659       do
1660 	{
1661 	  tree my_root_int = lookup_interface (my_root_id);
1662 
1663 	  if (my_root_int && CLASS_SUPER_NAME (my_root_int))
1664 	    my_root_id = CLASS_SUPER_NAME (my_root_int);
1665 	  else
1666 	    break;
1667 	}
1668       while (1);
1669     }
1670   else
1671     /* No super class.  */
1672     my_root_id = CLASS_NAME (impent->imp_template);
1673 
1674   cast_type = build_pointer_type (objc_class_template);
1675   name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
1676 			       class_names);
1677 
1678   /* Install class `isa' and `super' pointers at runtime.  */
1679   if (my_super_id)
1680     super_expr = add_objc_string (my_super_id, class_names);
1681   else
1682     super_expr = null_pointer_node;
1683 
1684   super_expr = build_c_cast (loc, cast_type, super_expr);
1685 
1686   root_expr = add_objc_string (my_root_id, class_names);
1687   root_expr = build_c_cast (loc, cast_type, root_expr);
1688 
1689   if (CLASS_PROTOCOL_LIST (impent->imp_template))
1690     {
1691       generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
1692       protocol_decl = generate_protocol_list (impent->imp_template,
1693 					      impent->imp_context);
1694     }
1695   else
1696     protocol_decl = NULL_TREE;
1697 
1698   if (CLASS_CLS_METHODS (impent->imp_context))
1699     {
1700       snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
1701 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1702       class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
1703 					       buf);
1704     }
1705 
1706   if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
1707       && (chain = TYPE_FIELDS (objc_class_template)))
1708     {
1709       snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
1710 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1711       class_ivars = generate_ivars_list (chain, buf);
1712     }
1713 
1714   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
1715 
1716   initlist =
1717 	build_shared_structure_initializer
1718 			(TREE_TYPE (meta_decl),
1719 			root_expr, super_expr, name_expr,
1720 			convert (integer_type_node,
1721 				TYPE_SIZE_UNIT (objc_class_template)),
1722 			CLS_META, class_methods, class_ivars,
1723 			protocol_decl);
1724 
1725   finish_var_decl (meta_decl, initlist);
1726   impent->meta_decl = meta_decl;
1727 
1728   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1729   if (CLASS_NST_METHODS (impent->imp_context))
1730     {
1731       snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
1732 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1733       inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
1734 					      buf);
1735     }
1736 
1737   if ((chain = CLASS_IVARS (impent->imp_template)))
1738     {
1739       snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
1740 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1741       inst_ivars = generate_ivars_list (chain, buf);
1742     }
1743 
1744   initlist =
1745 	build_shared_structure_initializer
1746 		(TREE_TYPE (class_decl),
1747 		build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
1748 		super_expr, name_expr,
1749 		convert (integer_type_node,
1750 			 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
1751 					(impent->imp_template))),
1752 		CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
1753 		protocol_decl);
1754 
1755   finish_var_decl (class_decl, initlist);
1756   impent->class_decl = class_decl;
1757 }
1758 
1759 /* --- Output GNU Metadata --- */
1760 
1761 /* TODO: Make this into an array of refs.  */
1762 static void
1763 handle_class_ref (tree chain)
1764 {
1765   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
1766   char *string = (char *) alloca (strlen (name) + 30);
1767   tree decl;
1768   tree exp;
1769 
1770   sprintf (string, "__objc_class_name_%s", name);
1771 
1772   /* Make a decl for this name, so we can use its address in a tree.  */
1773   decl = build_decl (input_location,
1774 		     VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
1775   DECL_EXTERNAL (decl) = 1;
1776   TREE_PUBLIC (decl) = 1;
1777   DECL_CONTEXT (decl) = NULL_TREE;
1778   finish_var_decl (decl, 0);
1779 
1780   /* Make a decl for the address.  */
1781   sprintf (string, "__objc_class_ref_%s", name);
1782   exp = build1 (ADDR_EXPR, string_type_node, decl);
1783   decl = build_decl (input_location,
1784 		     VAR_DECL, get_identifier (string), string_type_node);
1785   TREE_STATIC (decl) = 1;
1786   TREE_USED (decl) = 1;
1787   DECL_READ_P (decl) = 1;
1788   DECL_ARTIFICIAL (decl) = 1;
1789   DECL_INITIAL (decl) = error_mark_node;
1790 
1791   /* We must force the reference.  */
1792   DECL_PRESERVE_P (decl) = 1;
1793 
1794   DECL_CONTEXT (decl) = NULL_TREE;
1795   finish_var_decl (decl, exp);
1796 }
1797 
1798 static tree
1799 get_proto_encoding (tree proto)
1800 {
1801   tree encoding;
1802   if (proto)
1803     {
1804       if (! METHOD_ENCODING (proto))
1805 	{
1806 	  encoding = encode_method_prototype (proto);
1807 	  METHOD_ENCODING (proto) = encoding;
1808 	}
1809       else
1810 	encoding = METHOD_ENCODING (proto);
1811 
1812       return add_objc_string (encoding, meth_var_types);
1813     }
1814   else
1815     return build_int_cst (NULL_TREE, 0);
1816 }
1817 
1818 static void
1819 build_gnu_selector_translation_table (void)
1820 {
1821   tree chain, expr;
1822   vec<constructor_elt, va_gc> *inits = NULL;
1823   vec<constructor_elt, va_gc> *v ;
1824 
1825   /* Cause the selector table (previously forward-declared)
1826      to be actually output.  */
1827 
1828   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1829     {
1830       tree encoding;
1831       if (warn_selector)
1832 	{
1833 	  /* TODO: improve on the location for the diagnostic.  */
1834 	  location_t loc = input_location;
1835 	  diagnose_missing_method (TREE_VALUE (chain), loc);
1836 	}
1837 
1838       v = NULL;
1839       expr = build_selector (TREE_VALUE (chain));
1840       encoding = get_proto_encoding (TREE_PURPOSE (chain));
1841       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1842       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, encoding);
1843       expr = objc_build_constructor (objc_selector_template, v);
1844 
1845       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1846     } /* each element in the chain */
1847 
1848   /* List terminator.  */
1849   v = NULL;
1850   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1851   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1852   expr = objc_build_constructor (objc_selector_template, v);
1853 
1854   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1855   expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
1856 				     inits);
1857   finish_var_decl (UOBJC_SELECTOR_TABLE_decl, expr);
1858 }
1859 
1860 /* Output references to all statically allocated objects.  Return the DECL
1861    for the array built.  */
1862 
1863 static void
1864 generate_static_references (void)
1865 {
1866   tree expr = NULL_TREE;
1867   tree class_name, klass, decl;
1868   tree cl_chain, in_chain, type
1869     = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
1870   int num_inst, num_class;
1871   char buf[BUFSIZE];
1872   vec<constructor_elt, va_gc> *decls = NULL;
1873 
1874   /* FIXME: Remove NeXT runtime code.  */
1875   if (flag_next_runtime)
1876     gcc_unreachable ();
1877 
1878   for (cl_chain = objc_static_instances, num_class = 0;
1879        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1880     {
1881       vec<constructor_elt, va_gc> *v = NULL;
1882 
1883       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1884 	   in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1885 
1886       snprintf (buf, BUFSIZE, "_OBJC_STATIC_INSTANCES_%d", num_class);
1887       decl = start_var_decl (type, buf);
1888 
1889       /* Output {class_name, ...}.  */
1890       klass = TREE_VALUE (cl_chain);
1891       class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
1892       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1893 			      build_unary_op (input_location,
1894 					      ADDR_EXPR, class_name, 1));
1895 
1896       /* Output {..., instance, ...}.  */
1897       for (in_chain = TREE_PURPOSE (cl_chain);
1898 	   in_chain; in_chain = TREE_CHAIN (in_chain))
1899 	{
1900 	  expr = build_unary_op (input_location,
1901 				 ADDR_EXPR, TREE_VALUE (in_chain), 1);
1902 	  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1903 	}
1904 
1905       /* Output {..., NULL}.  */
1906       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1907 
1908       expr = objc_build_constructor (TREE_TYPE (decl), v);
1909       OBJCMETA (decl, objc_meta, meta_base);
1910       finish_var_decl (decl, expr);
1911       CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
1912 			      build_unary_op (input_location,
1913 					      ADDR_EXPR, decl, 1));
1914     }
1915 
1916   CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
1917   expr = objc_build_constructor (type, decls);
1918   static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
1919   OBJCMETA (static_instances_decl, objc_meta, meta_base);
1920   finish_var_decl (static_instances_decl, expr);
1921 }
1922 
1923 /* Create the initial value for the `defs' field of _objc_symtab.
1924    This is a CONSTRUCTOR.  */
1925 
1926 static tree
1927 init_def_list (tree type)
1928 {
1929   tree expr;
1930   struct imp_entry *impent;
1931   location_t loc;
1932   vec<constructor_elt, va_gc> *v = NULL;
1933 
1934   if (imp_count)
1935     for (impent = imp_list; impent; impent = impent->next)
1936       {
1937 	if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1938 	  {
1939 	    loc = DECL_SOURCE_LOCATION (impent->class_decl);
1940 	    expr = build_unary_op (loc,
1941 				   ADDR_EXPR, impent->class_decl, 0);
1942 	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1943 	  }
1944       }
1945 
1946   if (cat_count)
1947     for (impent = imp_list; impent; impent = impent->next)
1948       {
1949 	if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1950 	  {
1951 	    loc = DECL_SOURCE_LOCATION (impent->class_decl);
1952 	    expr = build_unary_op (loc,
1953 				   ADDR_EXPR, impent->class_decl, 0);
1954 	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1955 	  }
1956       }
1957 
1958   loc = UNKNOWN_LOCATION;
1959   /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
1960   if (static_instances_decl)
1961     expr = build_unary_op (loc, ADDR_EXPR, static_instances_decl, 0);
1962   else
1963     expr = integer_zero_node;
1964   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1965 
1966   return objc_build_constructor (type, v);
1967 }
1968 
1969 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
1970 
1971 /* Predefine the following data type:
1972 
1973    struct _objc_symtab
1974    {
1975      long sel_ref_cnt;
1976      SEL *refs;
1977      short cls_def_cnt;
1978      short cat_def_cnt;
1979      void *defs[cls_def_cnt + cat_def_cnt];
1980    }; */
1981 
1982 static void
1983 build_objc_symtab_template (void)
1984 {
1985   tree fields, array_type, *chain = NULL;
1986   int index;
1987 
1988   objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
1989 
1990   /* long sel_ref_cnt; */
1991   fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
1992 
1993   /* SEL *refs; */
1994   add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
1995 
1996   /* short cls_def_cnt; */
1997   add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
1998 
1999   /* short cat_def_cnt; */
2000   add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
2001 
2002   /* Note that padding will be added here on LP64.  */
2003 
2004   /* void *defs[imp_count + cat_count (+ 1)]; */
2005   /* NB: The index is one less than the size of the array.  */
2006   index = imp_count + cat_count;
2007   array_type = build_sized_array_type (ptr_type_node, index + 1);
2008   add_field_decl (array_type, "defs", &chain);
2009 
2010   objc_finish_struct (objc_symtab_template, fields);
2011 }
2012 /* Construct the initial value for all of _objc_symtab.  */
2013 
2014 static tree
2015 init_objc_symtab (tree type)
2016 {
2017   tree field, expr, ltyp;
2018   location_t loc;
2019   vec<constructor_elt, va_gc> *v = NULL;
2020 
2021   loc = UNKNOWN_LOCATION;
2022 
2023   /* sel_ref_cnt = { ..., 5, ... } */
2024 
2025   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2026 			  build_int_cst (long_integer_type_node, 0));
2027 
2028   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2029 
2030   ltyp = build_pointer_type (objc_selector_type);
2031   if (sel_ref_chain)
2032     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR,
2033 					  UOBJC_SELECTOR_TABLE_decl, 1));
2034   else
2035     expr = convert (ltyp, null_pointer_node);
2036   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2037 
2038   /* cls_def_cnt = { ..., 5, ... } */
2039 
2040   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2041 			  build_int_cst (short_integer_type_node, imp_count));
2042 
2043   /* cat_def_cnt = { ..., 5, ... } */
2044 
2045   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2046 			  build_int_cst (short_integer_type_node, cat_count));
2047 
2048   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2049 
2050   field = TYPE_FIELDS (type);
2051   field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2052 
2053   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2054 
2055   return objc_build_constructor (type, v);
2056 }
2057 
2058 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2059    and initialized appropriately.  */
2060 
2061 static void
2062 generate_objc_symtab_decl (void)
2063 {
2064   build_objc_symtab_template ();
2065   UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2066   OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_base);
2067   finish_var_decl (UOBJC_SYMBOLS_decl,
2068 		   init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2069 }
2070 
2071 static void
2072 objc_generate_v1_gnu_metadata (void)
2073 {
2074   struct imp_entry *impent;
2075   tree chain;
2076 
2077   /* Process the static instances here because initialization of objc_symtab
2078      depends on them.  */
2079   if (objc_static_instances)
2080     generate_static_references ();
2081 
2082   objc_implementation_context =
2083   implementation_template =
2084   UOBJC_CLASS_decl =
2085   UOBJC_METACLASS_decl = NULL_TREE;
2086 
2087   for (impent = imp_list; impent; impent = impent->next)
2088     {
2089       /* If -gen-decls is present, Dump the @interface of each class.
2090 	 TODO: Dump the classes in the  order they were found, rather than in
2091 	 reverse order as we are doing now.  */
2092       if (flag_gen_declaration)
2093 	dump_interface (gen_declaration_file, impent->imp_context);
2094 
2095       /* all of the following reference the string pool...  */
2096       if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2097 	generate_class_structures (impent);
2098       else
2099 	generate_category (impent);
2100     }
2101 
2102   /* If we are using an array of selectors, we must always
2103      finish up the array decl even if no selectors were used.  */
2104   build_gnu_selector_translation_table ();
2105 
2106   if (protocol_chain)
2107     generate_protocols ();
2108 
2109   /* Arrange for ObjC data structures to be initialized at run time.  */
2110   /* FIXME: Have some more elegant way to determine if we need to
2111      generate objc_symtab_decl or not, instead of checking these
2112      global symbols.  */
2113   if (imp_list || class_names_chain
2114       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain
2115       || prop_names_attr_chain)
2116     generate_objc_symtab_decl ();
2117 
2118   if (imp_list || class_names_chain || objc_static_instances
2119       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
2120     {
2121       /* Make sure that the meta-data are identified as being
2122 	 GNU-runtime.  */
2123       build_module_descriptor (OBJC_VERSION,
2124 			       build_tree_list (objc_meta, meta_base));
2125       build_module_initializer_routine ();
2126     }
2127 
2128   /* Dump the class references.  This forces the appropriate classes
2129      to be linked into the executable image, preserving unix archive
2130      semantics.  This can be removed when we move to a more dynamically
2131      linked environment.  */
2132 
2133   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2134     {
2135       handle_class_ref (chain);
2136       if (TREE_PURPOSE (chain))
2137 	generate_classref_translation_entry (chain);
2138     }
2139 
2140   for (impent = imp_list; impent; impent = impent->next)
2141     handle_impent (impent);
2142 
2143   generate_strings ();
2144 }
2145 
2146 /* --- exceptions --- */
2147 
2148 static GTY(()) tree objc_eh_personality_decl;
2149 
2150 static tree
2151 objc_eh_runtime_type (tree type)
2152 {
2153   tree ident, eh_id, decl, str;
2154 
2155   if (type == error_mark_node
2156       || errorcount || sorrycount)
2157     {
2158       /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2159 	 to prevent an ICE.  Note that we know that the compiler will
2160 	 terminate with an error and this 'ErrorMarkNode' class name will
2161 	 never be actually used.  */
2162       ident = get_identifier ("ErrorMarkNode");
2163       goto make_err_class;
2164     }
2165 
2166   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2167     /* We don't want to identify 'id' for GNU. Instead, build a 0
2168        entry in the exceptions table.  */
2169     return null_pointer_node;
2170 
2171   if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2172     {
2173 #ifdef OBJCPLUS
2174       /* This routine is also called for c++ catch clauses; in which case,
2175 	 we use the c++ typeinfo decl. */
2176       return build_eh_type_type (type);
2177 #else
2178       error ("non-objective-c type '%T' cannot be caught", type);
2179       ident = get_identifier ("ErrorMarkNode");
2180       goto make_err_class;
2181 #endif
2182     }
2183   else
2184     ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2185 
2186 make_err_class:
2187   /* If this class was already referenced, then it will be output during
2188      meta-data emission, so we don't need to do it here.  */
2189   decl = get_objc_string_decl (ident, class_names);
2190   eh_id = add_objc_string (ident, class_names);
2191   if (!decl)
2192     {
2193       /* Not found ... so we need to build it - from the freshly-entered id.  */
2194       decl = get_objc_string_decl (ident, class_names);
2195       str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2196 			     IDENTIFIER_POINTER (ident));
2197       /* We have to finalize this var here, because this might be called after
2198 	 all the other metadata strings have been emitted.  */
2199       finish_var_decl (decl, str);
2200     }
2201   return eh_id;
2202 }
2203 
2204 static tree
2205 objc_eh_personality (void)
2206 {
2207   if (!objc_eh_personality_decl)
2208 #ifndef OBJCPLUS
2209     objc_eh_personality_decl = build_personality_function  ("gnu_objc");
2210 #else
2211     objc_eh_personality_decl = build_personality_function  ("gxx");
2212 #endif
2213   return objc_eh_personality_decl;
2214 }
2215 
2216 /* -- interfaces --- */
2217 
2218 static tree
2219 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2220 {
2221   tree t;
2222   vec<tree, va_gc> *parms;
2223   vec_alloc (parms, 1);
2224   /* A throw is just a call to the runtime throw function with the
2225      object as a parameter.  */
2226   parms->quick_push (throw_expr);
2227   t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms,
2228 			       NULL);
2229   vec_free (parms);
2230   return add_stmt (t);
2231 }
2232 
2233 /* Build __builtin_eh_pointer.  */
2234 
2235 static tree
2236 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
2237 {
2238   tree t;
2239   t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2240   t = build_call_expr (t, 1, integer_zero_node);
2241   return fold_convert (objc_object_type, t);
2242 }
2243 
2244 static tree
2245 begin_catch (struct objc_try_context **cur_try_context, tree type,
2246 	     tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2247 {
2248   tree t;
2249   /* Record the data for the catch in the try context so that we can
2250      finalize it later.  */
2251   if (ellipsis)
2252     t = build_stmt (input_location, CATCH_EXPR, NULL, compound);
2253   else
2254     t = build_stmt (input_location, CATCH_EXPR, type, compound);
2255   (*cur_try_context)->current_catch = t;
2256 
2257   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
2258   t = objc_build_exc_ptr (cur_try_context);
2259   t = convert (TREE_TYPE (decl), t);
2260   return build2 (MODIFY_EXPR, void_type_node, decl, t);
2261 }
2262 
2263 static void
2264 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2265 {
2266   append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2267 }
2268 
2269 static tree
2270 finish_try_stmt (struct objc_try_context **cur_try_context)
2271 {
2272   struct objc_try_context *c = *cur_try_context;
2273   tree stmt = c->try_body;
2274   if (c->catch_list)
2275     stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2276   if (c->finally_body)
2277     stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2278   return stmt;
2279 }
2280 
2281 #include "gt-objc-objc-gnu-runtime-abi-01.h"
2282