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