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