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