xref: /netbsd-src/external/gpl3/gcc/dist/gcc/objc/objc-gnu-runtime-abi-01.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* GNU Runtime ABI version 8
2    Copyright (C) 2011-2022 Free Software Foundation, Inc.
3    Contributed by Iain Sandoe (split from objc-act.cc)
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   suppress_warning (type);
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,
729 	      build_int_cst (TREE_TYPE (lookup_object), 0));
730   t = build_function_call_vec (loc, vNULL, t, parms, NULL);
731   vec_free (parms);
732   return t;
733 }
734 
735 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)736 gnu_runtime_abi_01_build_objc_method_call (location_t loc,
737 					   tree method_prototype,
738 					   tree receiver,
739 					   tree rtype ATTRIBUTE_UNUSED,
740 					   tree sel_name,
741 					   tree method_params,
742 					   int super ATTRIBUTE_UNUSED)
743 {
744   tree selector =
745 	gnu_runtime_abi_01_build_typed_selector_reference (loc,
746 							  sel_name,
747 							  method_prototype);
748 
749   return build_objc_method_call (loc, super, method_prototype, receiver,
750 				 selector, method_params);
751 }
752 
753 static tree
gnu_runtime_abi_01_get_protocol_reference(location_t loc,tree p)754 gnu_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
755 {
756   tree expr, protocol_struct_type, *chain;
757   if (!PROTOCOL_FORWARD_DECL (p))
758     PROTOCOL_FORWARD_DECL (p) = gnu_runtime_abi_01_protocol_decl (p);
759 
760   expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
761 
762   /* ??? Ideally we'd build the reference with objc_protocol_type directly,
763      if we have it, rather than converting it here.  */
764   expr = convert (objc_protocol_type, expr);
765 
766   /* The @protocol() expression is being compiled into a pointer to a
767      statically allocated instance of the Protocol class.  To become
768      usable at runtime, the 'isa' pointer of the instance need to be
769      fixed up at runtime by the runtime library, to point to the
770      actual 'Protocol' class.  */
771 
772   /* For the GNU runtime, put the static Protocol instance in the list
773      of statically allocated instances, so that we make sure that its
774      'isa' pointer is fixed up at runtime by the GNU runtime library
775      to point to the Protocol class (at runtime, when loading the
776      module, the GNU runtime library loops on the statically allocated
777      instances (as found in the defs field in objc_symtab) and fixups
778      all the 'isa' pointers of those objects).  */
779 
780   /* This type is a struct containing the fields of a Protocol
781      object.  (Cfr. objc_protocol_type instead is the type of a pointer
782      to such a struct).  */
783   protocol_struct_type = xref_tag (RECORD_TYPE,
784 				   get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
785 
786   /* Look for the list of Protocol statically allocated instances
787      to fixup at runtime.  Create a new list to hold Protocol
788      statically allocated instances, if the list is not found.  At
789      present there is only another list, holding NSConstantString
790      static instances to be fixed up at runtime.  */
791 
792   for (chain = &objc_static_instances;
793 	*chain && TREE_VALUE (*chain) != protocol_struct_type;
794 	chain = &TREE_CHAIN (*chain));
795 
796   if (!*chain)
797     {
798        *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
799        add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
800                           class_names);
801     }
802 
803   /* Add this statically allocated instance to the Protocol list.  */
804   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
805 				     PROTOCOL_FORWARD_DECL (p),
806 				     TREE_PURPOSE (*chain));
807   return expr;
808 }
809 
810 /* For ABI 8 an IVAR is just a fixed offset in the class struct.  */
811 
812 static tree
gnu_runtime_abi_01_build_ivar_ref(location_t loc ATTRIBUTE_UNUSED,tree base,tree id)813 gnu_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
814 				   tree base, tree id)
815 {
816   return objc_build_component_ref (base, id);
817 }
818 
819 /* We build super class references as we need them (but keep them once
820    built for the sake of efficiency).  */
821 
822 static tree
gnu_runtime_abi_01_get_class_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)823 gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
824 					struct imp_entry *imp, bool inst_meth)
825 {
826   if (inst_meth)
827     {
828       if (!ucls_super_ref)
829 	ucls_super_ref =
830 		objc_build_component_ref (imp->class_decl,
831 					  get_identifier ("super_class"));
832       return ucls_super_ref;
833     }
834   else
835     {
836       if (!uucls_super_ref)
837 	uucls_super_ref =
838 		objc_build_component_ref (imp->meta_decl,
839 					  get_identifier ("super_class"));
840       return uucls_super_ref;
841     }
842 }
843 
844 static tree
gnu_runtime_abi_01_get_category_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)845 gnu_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
846 					   struct imp_entry *imp, bool inst_meth)
847 {
848   tree super_name = CLASS_SUPER_NAME (imp->imp_template);
849   tree super_class;
850 
851   add_class_reference (super_name);
852   super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
853   super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
854 					IDENTIFIER_POINTER (super_name));
855   /* super_class = get_{meta_}class("CLASS_SUPER_NAME");  */
856   return build_function_call (input_location,
857 			      super_class,
858 			      build_tree_list (NULL_TREE, super_name));
859 }
860 
861 static bool
gnu_runtime_abi_01_setup_const_string_class_decl(void)862 gnu_runtime_abi_01_setup_const_string_class_decl (void)
863 {
864   /* Do nothing, and create no error.  */
865   return true;
866 }
867 
868 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
869 
870 static GTY(()) int num_static_inst;
871 
872 static tree
objc_add_static_instance(tree constructor,tree class_decl)873 objc_add_static_instance (tree constructor, tree class_decl)
874 {
875   tree *chain, decl;
876   char buf[BUFSIZE];
877 
878   /* Find the list of static instances for the CLASS_DECL.  Create one if
879      not found.  */
880   for (chain = &objc_static_instances;
881        *chain && TREE_VALUE (*chain) != class_decl;
882        chain = &TREE_CHAIN (*chain));
883   if (!*chain)
884     {
885       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
886       add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
887     }
888 
889   snprintf (buf, BUFSIZE, "_OBJC_INSTANCE_%d", num_static_inst++);
890   decl = build_decl (input_location,
891 		     VAR_DECL, get_identifier (buf), class_decl);
892   TREE_STATIC (decl) = 1;
893   DECL_ARTIFICIAL (decl) = 1;
894   TREE_USED (decl) = 1;
895   DECL_INITIAL (decl) = constructor;
896   DECL_CONTEXT (decl) = NULL;
897   OBJCMETA (decl, objc_meta, meta_base);
898 
899   /* We may be writing something else just now.
900      Postpone till end of input. */
901   DECL_DEFER_OUTPUT (decl) = 1;
902   lang_hooks.decls.pushdecl (decl);
903   rest_of_decl_compilation (decl, 1, 0);
904 
905   /* Add the DECL to the head of this CLASS' list.  */
906   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
907 
908   return decl;
909 }
910 
911 static tree
gnu_runtime_abi_01_build_const_string_constructor(location_t loc,tree string,int length)912 gnu_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
913 						   int length)
914 {
915   tree constructor, fields;
916   vec<constructor_elt, va_gc> *v = NULL;
917 
918   /* GNU:    (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length })  */
919   fields = TYPE_FIELDS (internal_const_str_type);
920   CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, 0));
921 
922   fields = DECL_CHAIN (fields);
923   CONSTRUCTOR_APPEND_ELT (v, fields, build_unary_op (loc,
924 						     ADDR_EXPR, string, 1));
925 
926   fields = DECL_CHAIN (fields);
927   CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
928   constructor = objc_build_constructor (internal_const_str_type, v);
929 
930   constructor = objc_add_static_instance (constructor, constant_string_type);
931   return constructor;
932 }
933 
934 /* --- metadata - module initializer --- */
935 
936 /* The GNU runtime requires us to provide a static initializer function
937    for each module:
938 
939    static void __objc_gnu_init (void) {
940      __objc_exec_class (&L_OBJC_MODULES);
941    }  */
942 
943 
944 static void
build_module_initializer_routine(void)945 build_module_initializer_routine (void)
946 {
947   tree body;
948 
949 #ifdef OBJCPLUS
950   push_lang_context (lang_name_c); /* extern "C" */
951 #endif
952 
953   objc_push_parm (build_decl (input_location,
954 			      PARM_DECL, NULL_TREE, void_type_node));
955 #ifdef OBJCPLUS
956   objc_start_function (get_identifier (TAG_GNUINIT),
957 		       build_function_type_list (void_type_node, NULL_TREE),
958 		       NULL_TREE, NULL_TREE);
959 #else
960   objc_start_function (get_identifier (TAG_GNUINIT),
961 		       build_function_type_list (void_type_node, NULL_TREE),
962 		       NULL_TREE, objc_get_parm_info (0, NULL_TREE));
963 #endif
964   body = c_begin_compound_stmt (true);
965   add_stmt (build_function_call
966 	    (input_location,
967 	     execclass_decl,
968 	     build_tree_list
969 	     (NULL_TREE,
970 	      build_unary_op (input_location, ADDR_EXPR,
971 			      UOBJC_MODULES_decl, 0))));
972   add_stmt (c_end_compound_stmt (input_location, body, true));
973 
974   TREE_PUBLIC (current_function_decl) = 0;
975 
976 #ifndef OBJCPLUS
977   /* For Objective-C++, we will need to call __objc_gnu_init
978      from objc_generate_static_init_call() below.  */
979   DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
980 #endif
981 
982   GNU_INIT_decl = current_function_decl;
983   finish_function ();
984 
985 #ifdef OBJCPLUS
986     pop_lang_context ();
987 #endif
988 }
989 
990 #ifdef OBJCPLUS
991 /* Return 1 if the __objc_gnu_init function has been synthesized and needs
992    to be called by the module initializer routine.  */
993 
994 int
objc_static_init_needed_p(void)995 objc_static_init_needed_p (void)
996 {
997   return (GNU_INIT_decl != NULL_TREE);
998 }
999 
1000 /* Generate a call to the __objc_gnu_init initializer function.  */
1001 
1002 tree
objc_generate_static_init_call(tree ctors ATTRIBUTE_UNUSED)1003 objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
1004 {
1005   add_stmt (build_stmt (input_location, EXPR_STMT,
1006 			build_function_call (input_location,
1007 					     GNU_INIT_decl, NULL_TREE)));
1008 
1009   return ctors;
1010 }
1011 #endif /* OBJCPLUS */
1012 
1013 /* --- Output GNU Meta-data --- */
1014 
1015 static void
generate_classref_translation_entry(tree chain)1016 generate_classref_translation_entry (tree chain)
1017 {
1018   tree expr, decl, type;
1019 
1020   decl = TREE_PURPOSE (chain);
1021   type = TREE_TYPE (decl);
1022 
1023   expr = add_objc_string (TREE_VALUE (chain), class_names);
1024   expr = convert (type, expr); /* cast! */
1025 
1026   /* This is a class reference.  It is re-written by the runtime,
1027      but will be optimized away unless we force it.  */
1028   DECL_PRESERVE_P (decl) = 1;
1029   OBJCMETA (decl, objc_meta, meta_base);
1030   finish_var_decl (decl, expr);
1031   return;
1032 }
1033 
1034 
1035 static void
handle_impent(struct imp_entry * impent)1036 handle_impent (struct imp_entry *impent)
1037 {
1038   char *string;
1039 
1040 /*  objc_implementation_context = impent->imp_context;
1041   implementation_template = impent->imp_template;*/
1042 
1043   switch (TREE_CODE (impent->imp_context))
1044     {
1045     case CLASS_IMPLEMENTATION_TYPE:
1046       {
1047 	const char *const class_name =
1048 	  IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1049 
1050 	string = (char *) alloca (strlen (class_name) + 30);
1051 
1052 	sprintf (string, "__objc_class_name_%s", class_name);
1053 	break;
1054       }
1055     case CATEGORY_IMPLEMENTATION_TYPE:
1056       {
1057 	const char *const class_name =
1058 	  IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
1059 	const char *const class_super_name =
1060 	  IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
1061 
1062 	string = (char *) alloca (strlen (class_name)
1063 				  + strlen (class_super_name) + 30);
1064 
1065 	/* Do the same for categories.  Even though no references to
1066 	   these symbols are generated automatically by the compiler,
1067 	   it gives you a handle to pull them into an archive by
1068 	   hand.  */
1069 	sprintf (string, "*__objc_category_name_%s_%s", class_name, class_super_name);
1070 	break;
1071       }
1072     default:
1073       return;
1074     }
1075 
1076     {
1077       tree decl, init;
1078 
1079       init = integer_zero_node;
1080       decl = build_decl (input_location,
1081 			 VAR_DECL, get_identifier (string), TREE_TYPE (init));
1082       TREE_PUBLIC (decl) = 1;
1083       TREE_READONLY (decl) = 1;
1084       TREE_USED (decl) = 1;
1085       TREE_CONSTANT (decl) = 1;
1086       DECL_CONTEXT (decl) = NULL_TREE;
1087       DECL_ARTIFICIAL (decl) = 1;
1088       TREE_STATIC (decl) = 1;
1089       DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
1090       /* We must force the reference.  */
1091       DECL_PRESERVE_P (decl) = 1;
1092 
1093       finish_var_decl(decl, init) ;
1094     }
1095 }
1096 
1097 tree
build_protocol_initializer(tree type,tree protocol_name,tree protocol_list,tree inst_methods,tree class_methods)1098 build_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1099 			    tree inst_methods, tree class_methods)
1100 {
1101   tree expr, ttyp;
1102   location_t loc;
1103   vec<constructor_elt, va_gc> *inits = NULL;
1104 
1105   /* TODO: pass the loc in or find it from args.  */
1106   loc = input_location;
1107   ttyp = build_pointer_type (xref_tag (RECORD_TYPE,
1108 				       get_identifier (UTAG_CLASS)));
1109   /* Filling the "isa" in with a version allows the runtime system to
1110      detect this ...   */
1111   expr = build_int_cst (ttyp, PROTOCOL_VERSION);
1112 
1113   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1114 
1115   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1116   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1117 
1118   ttyp = objc_method_proto_list_ptr;
1119   if (inst_methods)
1120     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1121   else
1122     expr = convert (ttyp, null_pointer_node);
1123   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1124 
1125   if (class_methods)
1126     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1127   else
1128     expr = convert (ttyp, null_pointer_node);
1129   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1130 
1131   return objc_build_constructor (type, inits);
1132 }
1133 
1134 static tree
generate_protocol_list(tree i_or_p,tree klass_ctxt)1135 generate_protocol_list (tree i_or_p, tree klass_ctxt)
1136 {
1137   tree array_type, ptype, refs_decl, lproto, e, plist;
1138   vec<constructor_elt, va_gc> *v = NULL;
1139   char buf[BUFSIZE];
1140   int size = 0;
1141 
1142   switch (TREE_CODE (i_or_p))
1143     {
1144     case CLASS_INTERFACE_TYPE:
1145     case CATEGORY_INTERFACE_TYPE:
1146       plist = CLASS_PROTOCOL_LIST (i_or_p);
1147       break;
1148     case PROTOCOL_INTERFACE_TYPE:
1149       plist = PROTOCOL_LIST (i_or_p);
1150       break;
1151     default:
1152       gcc_unreachable ();
1153     }
1154 
1155   /* Compute size.  */
1156   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1157     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1158 	&& PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1159       size++;
1160 
1161   /* Build initializer.  */
1162   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1163   e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1164   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1165 
1166   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1167     {
1168       tree pval = TREE_VALUE (lproto);
1169 
1170       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1171 	  && PROTOCOL_FORWARD_DECL (pval))
1172 	{
1173 	  tree fwref = PROTOCOL_FORWARD_DECL (pval);
1174 	  location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1175 	  e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1176           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1177 	}
1178     }
1179 
1180   /* static struct objc_protocol *refs[n]; */
1181 
1182   switch (TREE_CODE (i_or_p))
1183     {
1184     case PROTOCOL_INTERFACE_TYPE:
1185       snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1186 		IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1187       break;
1188     case CLASS_INTERFACE_TYPE:
1189       snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1190 		IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1191       break;
1192     case CATEGORY_INTERFACE_TYPE:
1193       snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1194 		IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1195 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1196       break;
1197     default:
1198       gcc_unreachable ();
1199     }
1200 
1201   ptype = build_pointer_type (objc_protocol_template);
1202   array_type = build_sized_array_type (ptype, size + 3);
1203   refs_decl = start_var_decl (array_type, buf);
1204   OBJCMETA (refs_decl, objc_meta, meta_base);
1205   finish_var_decl (refs_decl,
1206                    objc_build_constructor (TREE_TYPE (refs_decl), v));
1207 
1208   return refs_decl;
1209 }
1210 
1211 static tree
generate_v1_meth_descriptor_table(tree chain,tree protocol,const char * prefix)1212 generate_v1_meth_descriptor_table (tree chain, tree protocol, const char *prefix)
1213 {
1214   tree method_list_template, initlist, decl;
1215   int size;
1216   vec<constructor_elt, va_gc> *v = NULL;
1217   char buf[BUFSIZE];
1218 
1219   if (!chain || !prefix)
1220     return NULL_TREE;
1221 
1222   if (!objc_method_prototype_template)
1223     objc_method_prototype_template = build_method_prototype_template ();
1224 
1225   size = list_length (chain);
1226   method_list_template =
1227 	build_method_prototype_list_template (objc_method_prototype_template,
1228 					      size);
1229   snprintf (buf, BUFSIZE, "%s_%s", prefix,
1230 	    IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1231 
1232   decl = start_var_decl (method_list_template, buf);
1233 
1234   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1235   initlist =
1236 	build_descriptor_table_initializer (objc_method_prototype_template,
1237 					    chain);
1238   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1239   OBJCMETA (decl, objc_meta, meta_base);
1240   finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1241   return decl;
1242 }
1243 
1244 /* For each protocol which was referenced either from a @protocol()
1245    expression, or because a class/category implements it (then a
1246    pointer to the protocol is stored in the struct describing the
1247    class/category), we create a statically allocated instance of the
1248    Protocol class.  The code is written in such a way as to generate
1249    as few Protocol objects as possible; we generate a unique Protocol
1250    instance for each protocol, and we don't generate a Protocol
1251    instance if the protocol is never referenced (either from a
1252    @protocol() or from a class/category implementation).  These
1253    statically allocated objects can be referred to via the static
1254    (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1255 
1256    The statically allocated Protocol objects that we generate here
1257    need to be fixed up at runtime in order to be used: the 'isa'
1258    pointer of the objects need to be set up to point to the 'Protocol'
1259    class, as known at runtime.
1260 
1261    The GNU runtime fixes up all protocols before user code from the module
1262    is executed; it requires pointers to those symbols
1263    to be put in the objc_symtab (which is then passed as argument to
1264    the function __objc_exec_class() which the compiler sets up to be
1265    executed automatically when the module is loaded); setup of those
1266    Protocol objects happen in two ways in the GNU runtime: all
1267    Protocol objects referred to by a class or category implementation
1268    are fixed up when the class/category is loaded; all Protocol
1269    objects referred to by a @protocol() expression are added by the
1270    compiler to the list of statically allocated instances to fixup
1271    (the same list holding the statically allocated constant string
1272    objects).  Because, as explained above, the compiler generates as
1273    few Protocol objects as possible, some Protocol object might end up
1274    being referenced multiple times when compiled with the GNU runtime,
1275    and end up being fixed up multiple times at runtime initialization.
1276    But that doesn't hurt, it's just a little inefficient.  */
1277 
1278 static void
generate_protocols(void)1279 generate_protocols (void)
1280 {
1281   tree p, encoding;
1282   tree decl;
1283   tree initlist, protocol_name_expr, refs_decl, refs_expr;
1284 
1285   /* If a protocol was directly referenced, pull in indirect references.  */
1286   for (p = protocol_chain; p; p = TREE_CHAIN (p))
1287     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1288       generate_protocol_references (PROTOCOL_LIST (p));
1289 
1290   for (p = protocol_chain; p; p = TREE_CHAIN (p))
1291     {
1292       tree nst_methods = PROTOCOL_NST_METHODS (p);
1293       tree cls_methods = PROTOCOL_CLS_METHODS (p);
1294 
1295       /* If protocol wasn't referenced, don't generate any code.  */
1296       decl = PROTOCOL_FORWARD_DECL (p);
1297 
1298       if (!decl)
1299 	continue;
1300 
1301       /* Make sure we link in the Protocol class.  */
1302       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1303 
1304       while (nst_methods)
1305 	{
1306 	  if (! METHOD_ENCODING (nst_methods))
1307 	    {
1308 	      encoding = encode_method_prototype (nst_methods);
1309 	      METHOD_ENCODING (nst_methods) = encoding;
1310 	    }
1311 	  nst_methods = DECL_CHAIN (nst_methods);
1312 	}
1313 
1314       UOBJC_INSTANCE_METHODS_decl =
1315 	generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1316 					   "_OBJC_PROTOCOL_INSTANCE_METHODS");
1317 
1318       while (cls_methods)
1319 	{
1320 	  if (! METHOD_ENCODING (cls_methods))
1321 	    {
1322 	      encoding = encode_method_prototype (cls_methods);
1323 	      METHOD_ENCODING (cls_methods) = encoding;
1324 	    }
1325 
1326 	  cls_methods = DECL_CHAIN (cls_methods);
1327 	}
1328 
1329       UOBJC_CLASS_METHODS_decl =
1330 	generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1331 					   "_OBJC_PROTOCOL_CLASS_METHODS");
1332 /*      generate_method_descriptors (p);*/
1333 
1334       if (PROTOCOL_LIST (p))
1335 	refs_decl = generate_protocol_list (p, NULL_TREE);
1336       else
1337 	refs_decl = 0;
1338 
1339       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1340       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1341 
1342       if (refs_decl)
1343 	refs_expr = convert (build_pointer_type (build_pointer_type
1344 						 (objc_protocol_template)),
1345 			     build_unary_op (input_location,
1346 					     ADDR_EXPR, refs_decl, 0));
1347       else
1348 	refs_expr = build_int_cst (NULL_TREE, 0);
1349 
1350       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
1351 	 by generate_method_descriptors, which is called above.  */
1352       initlist = build_protocol_initializer (TREE_TYPE (decl),
1353 					     protocol_name_expr, refs_expr,
1354 					     UOBJC_INSTANCE_METHODS_decl,
1355 					     UOBJC_CLASS_METHODS_decl);
1356       finish_var_decl (decl, initlist);
1357     }
1358 }
1359 
1360 static tree
generate_dispatch_table(tree chain,const char * name)1361 generate_dispatch_table (tree chain, const char *name)
1362 {
1363   tree decl, method_list_template, initlist;
1364   vec<constructor_elt, va_gc> *v = NULL;
1365   int size = list_length (chain);
1366 
1367   if (!objc_method_template)
1368     objc_method_template = build_method_template ();
1369 
1370   method_list_template = build_method_list_template (objc_method_template,
1371 						     size);
1372   initlist = build_dispatch_table_initializer (objc_method_template, chain);
1373 
1374   decl = start_var_decl (method_list_template, name);
1375 
1376   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1377   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1378 			  build_int_cst (integer_type_node, size));
1379   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1380 
1381   OBJCMETA (decl, objc_meta, meta_base);
1382   finish_var_decl (decl,
1383 		   objc_build_constructor (TREE_TYPE (decl), v));
1384 
1385   return decl;
1386 }
1387 
1388 /* Init a category.  */
1389 static tree
build_category_initializer(tree type,tree cat_name,tree class_name,tree inst_methods,tree class_methods,tree protocol_list)1390 build_category_initializer (tree type, tree cat_name, tree class_name,
1391 			    tree inst_methods, tree class_methods,
1392 			    tree protocol_list)
1393 {
1394   tree expr, ltyp;
1395   location_t loc;
1396   vec<constructor_elt, va_gc> *v = NULL;
1397 
1398   /* TODO: pass the loc in or find it from args.  */
1399   /* TODO: pass the loc in or find it from args.  */
1400   loc = UNKNOWN_LOCATION;
1401   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1402   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1403 
1404   ltyp = objc_method_list_ptr;
1405   if (inst_methods)
1406     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1407   else
1408     expr = convert (ltyp, null_pointer_node);
1409   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1410 
1411   if (class_methods)
1412     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1413   else
1414     expr = convert (ltyp, null_pointer_node);
1415   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1416 
1417   /* protocol_list = */
1418   ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1419   if (protocol_list)
1420     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1421   else
1422     expr = convert (ltyp, null_pointer_node);
1423   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1424 
1425   return objc_build_constructor (type, v);
1426 }
1427 
1428 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
1429 
1430 static void
generate_category(struct imp_entry * impent)1431 generate_category (struct imp_entry *impent)
1432 {
1433   tree initlist, cat_name_expr, class_name_expr;
1434   tree protocol_decl, category, cat_decl;
1435   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1436   tree cat = impent->imp_context;
1437   char buf[BUFSIZE];
1438 
1439   cat_decl = impent->class_decl;
1440 
1441   add_class_reference (CLASS_NAME (cat));
1442   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1443 
1444   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1445 
1446   category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1447 
1448   if (category && CLASS_PROTOCOL_LIST (category))
1449     {
1450       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1451       protocol_decl = generate_protocol_list (category, cat);
1452     }
1453   else
1454     protocol_decl = 0;
1455 
1456   if (CLASS_NST_METHODS (cat))
1457     {
1458       snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1459 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
1460 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1461       inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf);
1462     }
1463 
1464   if (CLASS_CLS_METHODS (cat))
1465     {
1466       snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1467 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
1468 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1469       class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf);
1470     }
1471 
1472   initlist = build_category_initializer (TREE_TYPE (cat_decl),
1473 					 cat_name_expr, class_name_expr,
1474 					 inst_methods, class_methods,
1475 					 protocol_decl);
1476   /* Finish and initialize the forward decl.  */
1477   finish_var_decl (cat_decl, initlist);
1478   impent->class_decl = cat_decl;
1479 }
1480 
1481 /* struct _objc_class {
1482      struct objc_class *isa;
1483      struct objc_class *super_class;
1484      char *name;
1485      long version;
1486      long info;
1487      long instance_size;
1488      struct objc_ivar_list *ivars;
1489      struct objc_method_list *methods;
1490      struct sarray *dtable;
1491      struct objc_class *subclass_list;
1492      struct objc_class *sibling_class;
1493      struct objc_protocol_list *protocols;
1494      void *gc_object_type;
1495    };  */
1496 
1497 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)1498 build_shared_structure_initializer (tree type, tree isa, tree super,
1499 				    tree name, tree size, int status,
1500 				    tree dispatch_table, tree ivar_list,
1501 				    tree protocol_list)
1502 {
1503   tree expr, ltyp;
1504   vec<constructor_elt, va_gc> *v = NULL;
1505 
1506   /* isa = */
1507   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1508 
1509   /* super_class = */
1510   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1511 
1512   /* name = */
1513   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1514 
1515   /* version = */
1516   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1517                           build_int_cst (long_integer_type_node, 0));
1518 
1519   /* info = */
1520   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1521                           build_int_cst (long_integer_type_node, status));
1522 
1523   /* instance_size = */
1524   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1525                           convert (long_integer_type_node, size));
1526 
1527   /* objc_ivar_list = */
1528   if (!ivar_list)
1529     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1530 			    build_int_cst (objc_ivar_list_ptr, 0));
1531   else
1532     {
1533       expr = convert (objc_ivar_list_ptr,
1534 		      build_unary_op (input_location, ADDR_EXPR,
1535 				      ivar_list, 0));
1536       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1537     }
1538 
1539   /* objc_method_list = */
1540   if (!dispatch_table)
1541     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1542 			   convert (objc_method_list_ptr, null_pointer_node));
1543   else
1544     {
1545       expr = convert (objc_method_list_ptr,
1546 		      build_unary_op (input_location, ADDR_EXPR,
1547 				      dispatch_table, 0));
1548       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1549     }
1550 
1551   /* dtable = */
1552   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1553 
1554   /* subclass_list = */
1555   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1556 
1557   /* sibling_class = */
1558   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1559 
1560   /* protocol_list = */
1561   ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1562   if (! protocol_list)
1563     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (ltyp, 0));
1564   else
1565     {
1566       expr = convert (ltyp,
1567 		      build_unary_op (input_location, ADDR_EXPR,
1568 				      protocol_list, 0));
1569       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1570     }
1571 
1572   /* gc_object_type = NULL */
1573   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1574 
1575   return objc_build_constructor (type, v);
1576 }
1577 
1578 
1579 static tree
generate_ivars_list(tree chain,const char * name)1580 generate_ivars_list (tree chain, const char *name)
1581 {
1582   tree initlist, ivar_list_template, decl;
1583   int size;
1584   vec<constructor_elt, va_gc> *inits = NULL;
1585 
1586   if (!chain)
1587     return NULL_TREE;
1588 
1589   if (!objc_ivar_template)
1590     objc_ivar_template = build_ivar_template ();
1591 
1592   size = ivar_list_length (chain);
1593 
1594   generating_instance_variables = 1;
1595   ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1596   initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1597   generating_instance_variables = 0;
1598 
1599   decl = start_var_decl (ivar_list_template, name);
1600 
1601   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1602   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1603 
1604   OBJCMETA (decl, objc_meta, meta_base);
1605   finish_var_decl (decl,
1606 		   objc_build_constructor (TREE_TYPE (decl), inits));
1607 
1608   return decl;
1609 }
1610 
1611 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1612    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
1613 
1614 static void
generate_class_structures(struct imp_entry * impent)1615 generate_class_structures (struct imp_entry *impent)
1616 {
1617   tree name_expr, super_expr, root_expr, class_decl, meta_decl;
1618   tree my_root_id, my_super_id;
1619   tree cast_type, initlist, protocol_decl;
1620   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1621   tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
1622   location_t loc;
1623   char buf[BUFSIZE];
1624   int cls_flags = 0 ;
1625 
1626 /*  objc_implementation_context = impent->imp_context;
1627   implementation_template = impent->imp_template;*/
1628   class_decl = impent->class_decl;
1629   meta_decl = impent->meta_decl;
1630 /*  UOBJC_CLASS_decl = impent->class_decl;
1631   UOBJC_METACLASS_decl = impent->meta_decl;*/
1632 
1633   loc = DECL_SOURCE_LOCATION (impent->class_decl);
1634 
1635   my_super_id = CLASS_SUPER_NAME (impent->imp_template);
1636   if (my_super_id)
1637     {
1638       add_class_reference (my_super_id);
1639 
1640       /* Compute "my_root_id" - this is required for code generation.
1641          the "isa" for all meta class structures points to the root of
1642          the inheritance hierarchy (e.g. "__Object")...  */
1643       my_root_id = my_super_id;
1644       do
1645 	{
1646 	  tree my_root_int = lookup_interface (my_root_id);
1647 
1648 	  if (my_root_int && CLASS_SUPER_NAME (my_root_int))
1649 	    my_root_id = CLASS_SUPER_NAME (my_root_int);
1650 	  else
1651 	    break;
1652 	}
1653       while (1);
1654     }
1655   else
1656     /* No super class.  */
1657     my_root_id = CLASS_NAME (impent->imp_template);
1658 
1659   cast_type = build_pointer_type (objc_class_template);
1660   name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
1661 			       class_names);
1662 
1663   /* Install class `isa' and `super' pointers at runtime.  */
1664   if (my_super_id)
1665     super_expr = add_objc_string (my_super_id, class_names);
1666   else
1667     super_expr = null_pointer_node;
1668 
1669   super_expr = build_c_cast (loc, cast_type, super_expr);
1670 
1671   root_expr = add_objc_string (my_root_id, class_names);
1672   root_expr = build_c_cast (loc, cast_type, root_expr);
1673 
1674   if (CLASS_PROTOCOL_LIST (impent->imp_template))
1675     {
1676       generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
1677       protocol_decl = generate_protocol_list (impent->imp_template,
1678 					      impent->imp_context);
1679     }
1680   else
1681     protocol_decl = NULL_TREE;
1682 
1683   if (CLASS_CLS_METHODS (impent->imp_context))
1684     {
1685       snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
1686 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1687       class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
1688 					       buf);
1689     }
1690 
1691   if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
1692       && (chain = TYPE_FIELDS (objc_class_template)))
1693     {
1694       snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
1695 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1696       class_ivars = generate_ivars_list (chain, buf);
1697     }
1698 
1699   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
1700 
1701   initlist =
1702 	build_shared_structure_initializer
1703 			(TREE_TYPE (meta_decl),
1704 			root_expr, super_expr, name_expr,
1705 			convert (integer_type_node,
1706 				TYPE_SIZE_UNIT (objc_class_template)),
1707 			CLS_META, class_methods, class_ivars,
1708 			protocol_decl);
1709 
1710   finish_var_decl (meta_decl, initlist);
1711   impent->meta_decl = meta_decl;
1712 
1713   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1714   if (CLASS_NST_METHODS (impent->imp_context))
1715     {
1716       snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
1717 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1718       inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
1719 					      buf);
1720     }
1721 
1722   if ((chain = CLASS_IVARS (impent->imp_template)))
1723     {
1724       snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
1725 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
1726       inst_ivars = generate_ivars_list (chain, buf);
1727     }
1728 
1729   initlist =
1730 	build_shared_structure_initializer
1731 		(TREE_TYPE (class_decl),
1732 		build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
1733 		super_expr, name_expr,
1734 		convert (integer_type_node,
1735 			 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
1736 					(impent->imp_template))),
1737 		CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
1738 		protocol_decl);
1739 
1740   finish_var_decl (class_decl, initlist);
1741   impent->class_decl = class_decl;
1742 }
1743 
1744 /* --- Output GNU Metadata --- */
1745 
1746 /* TODO: Make this into an array of refs.  */
1747 static void
handle_class_ref(tree chain)1748 handle_class_ref (tree chain)
1749 {
1750   const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
1751   char *string = (char *) alloca (strlen (name) + 30);
1752   tree decl;
1753   tree exp;
1754 
1755   sprintf (string, "__objc_class_name_%s", name);
1756 
1757   /* Make a decl for this name, so we can use its address in a tree.  */
1758   decl = build_decl (input_location,
1759 		     VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
1760   DECL_EXTERNAL (decl) = 1;
1761   TREE_PUBLIC (decl) = 1;
1762   DECL_CONTEXT (decl) = NULL_TREE;
1763   finish_var_decl (decl, 0);
1764 
1765   /* Make a decl for the address.  */
1766   sprintf (string, "__objc_class_ref_%s", name);
1767   exp = build1 (ADDR_EXPR, string_type_node, decl);
1768   decl = build_decl (input_location,
1769 		     VAR_DECL, get_identifier (string), string_type_node);
1770   TREE_STATIC (decl) = 1;
1771   TREE_USED (decl) = 1;
1772   DECL_READ_P (decl) = 1;
1773   DECL_ARTIFICIAL (decl) = 1;
1774   DECL_INITIAL (decl) = error_mark_node;
1775 
1776   /* We must force the reference.  */
1777   DECL_PRESERVE_P (decl) = 1;
1778 
1779   DECL_CONTEXT (decl) = NULL_TREE;
1780   finish_var_decl (decl, exp);
1781 }
1782 
1783 static tree
get_proto_encoding(tree proto)1784 get_proto_encoding (tree proto)
1785 {
1786   tree encoding;
1787   if (proto)
1788     {
1789       if (! METHOD_ENCODING (proto))
1790 	{
1791 	  encoding = encode_method_prototype (proto);
1792 	  METHOD_ENCODING (proto) = encoding;
1793 	}
1794       else
1795 	encoding = METHOD_ENCODING (proto);
1796 
1797       return add_objc_string (encoding, meth_var_types);
1798     }
1799   else
1800     return build_int_cst (NULL_TREE, 0);
1801 }
1802 
1803 static void
build_gnu_selector_translation_table(void)1804 build_gnu_selector_translation_table (void)
1805 {
1806   tree chain, expr;
1807   vec<constructor_elt, va_gc> *inits = NULL;
1808   vec<constructor_elt, va_gc> *v ;
1809 
1810   /* Cause the selector table (previously forward-declared)
1811      to be actually output.  */
1812 
1813   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
1814     {
1815       tree encoding;
1816       if (warn_selector)
1817 	{
1818 	  /* TODO: improve on the location for the diagnostic.  */
1819 	  location_t loc = input_location;
1820 	  diagnose_missing_method (TREE_VALUE (chain), loc);
1821 	}
1822 
1823       v = NULL;
1824       expr = build_selector (TREE_VALUE (chain));
1825       encoding = get_proto_encoding (TREE_PURPOSE (chain));
1826       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1827       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, encoding);
1828       expr = objc_build_constructor (objc_selector_template, v);
1829 
1830       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1831     } /* each element in the chain */
1832 
1833   /* List terminator.  */
1834   v = NULL;
1835   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1836   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1837   expr = objc_build_constructor (objc_selector_template, v);
1838 
1839   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1840   expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
1841 				     inits);
1842   finish_var_decl (UOBJC_SELECTOR_TABLE_decl, expr);
1843 }
1844 
1845 /* Output references to all statically allocated objects.  Return the DECL
1846    for the array built.  */
1847 
1848 static void
generate_static_references(void)1849 generate_static_references (void)
1850 {
1851   tree expr = NULL_TREE;
1852   tree class_name, klass, decl;
1853   tree cl_chain, in_chain, type
1854     = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
1855   int num_inst, num_class;
1856   char buf[BUFSIZE];
1857   vec<constructor_elt, va_gc> *decls = NULL;
1858 
1859   for (cl_chain = objc_static_instances, num_class = 0;
1860        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1861     {
1862       vec<constructor_elt, va_gc> *v = NULL;
1863 
1864       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1865 	   in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1866 
1867       snprintf (buf, BUFSIZE, "_OBJC_STATIC_INSTANCES_%d", num_class);
1868       decl = start_var_decl (type, buf);
1869 
1870       /* Output {class_name, ...}.  */
1871       klass = TREE_VALUE (cl_chain);
1872       class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
1873       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1874 			      build_unary_op (input_location,
1875 					      ADDR_EXPR, class_name, 1));
1876 
1877       /* Output {..., instance, ...}.  */
1878       for (in_chain = TREE_PURPOSE (cl_chain);
1879 	   in_chain; in_chain = TREE_CHAIN (in_chain))
1880 	{
1881 	  expr = build_unary_op (input_location,
1882 				 ADDR_EXPR, TREE_VALUE (in_chain), 1);
1883 	  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1884 	}
1885 
1886       /* Output {..., NULL}.  */
1887       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1888 
1889       expr = objc_build_constructor (TREE_TYPE (decl), v);
1890       OBJCMETA (decl, objc_meta, meta_base);
1891       finish_var_decl (decl, expr);
1892       CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
1893 			      build_unary_op (input_location,
1894 					      ADDR_EXPR, decl, 1));
1895     }
1896 
1897   CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
1898   expr = objc_build_constructor (type, decls);
1899   static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
1900   OBJCMETA (static_instances_decl, objc_meta, meta_base);
1901   finish_var_decl (static_instances_decl, expr);
1902 }
1903 
1904 /* Create the initial value for the `defs' field of _objc_symtab.
1905    This is a CONSTRUCTOR.  */
1906 
1907 static tree
init_def_list(tree type)1908 init_def_list (tree type)
1909 {
1910   tree expr;
1911   struct imp_entry *impent;
1912   location_t loc;
1913   vec<constructor_elt, va_gc> *v = NULL;
1914 
1915   if (imp_count)
1916     for (impent = imp_list; impent; impent = impent->next)
1917       {
1918 	if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1919 	  {
1920 	    loc = DECL_SOURCE_LOCATION (impent->class_decl);
1921 	    expr = build_unary_op (loc,
1922 				   ADDR_EXPR, impent->class_decl, 0);
1923 	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1924 	  }
1925       }
1926 
1927   if (cat_count)
1928     for (impent = imp_list; impent; impent = impent->next)
1929       {
1930 	if (TREE_CODE (impent->imp_context) == CATEGORY_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   loc = UNKNOWN_LOCATION;
1940   /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
1941   if (static_instances_decl)
1942     expr = build_unary_op (loc, ADDR_EXPR, static_instances_decl, 0);
1943   else
1944     expr = integer_zero_node;
1945   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1946 
1947   return objc_build_constructor (type, v);
1948 }
1949 
1950 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
1951 
1952 /* Predefine the following data type:
1953 
1954    struct _objc_symtab
1955    {
1956      long sel_ref_cnt;
1957      SEL *refs;
1958      short cls_def_cnt;
1959      short cat_def_cnt;
1960      void *defs[cls_def_cnt + cat_def_cnt];
1961    }; */
1962 
1963 static void
build_objc_symtab_template(void)1964 build_objc_symtab_template (void)
1965 {
1966   tree fields, array_type, *chain = NULL;
1967   int index;
1968 
1969   objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
1970 
1971   /* long sel_ref_cnt; */
1972   fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
1973 
1974   /* SEL *refs; */
1975   add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
1976 
1977   /* short cls_def_cnt; */
1978   add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
1979 
1980   /* short cat_def_cnt; */
1981   add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
1982 
1983   /* Note that padding will be added here on LP64.  */
1984 
1985   /* void *defs[imp_count + cat_count (+ 1)]; */
1986   /* NB: The index is one less than the size of the array.  */
1987   index = imp_count + cat_count;
1988   array_type = build_sized_array_type (ptr_type_node, index + 1);
1989   add_field_decl (array_type, "defs", &chain);
1990 
1991   objc_finish_struct (objc_symtab_template, fields);
1992 }
1993 /* Construct the initial value for all of _objc_symtab.  */
1994 
1995 static tree
init_objc_symtab(tree type)1996 init_objc_symtab (tree type)
1997 {
1998   tree field, expr, ltyp;
1999   location_t loc;
2000   vec<constructor_elt, va_gc> *v = NULL;
2001 
2002   loc = UNKNOWN_LOCATION;
2003 
2004   /* sel_ref_cnt = { ..., 5, ... } */
2005 
2006   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2007 			  build_int_cst (long_integer_type_node, 0));
2008 
2009   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2010 
2011   ltyp = build_pointer_type (objc_selector_type);
2012   if (sel_ref_chain)
2013     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR,
2014 					  UOBJC_SELECTOR_TABLE_decl, 1));
2015   else
2016     expr = convert (ltyp, null_pointer_node);
2017   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2018 
2019   /* cls_def_cnt = { ..., 5, ... } */
2020 
2021   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2022 			  build_int_cst (short_integer_type_node, imp_count));
2023 
2024   /* cat_def_cnt = { ..., 5, ... } */
2025 
2026   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2027 			  build_int_cst (short_integer_type_node, cat_count));
2028 
2029   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2030 
2031   field = TYPE_FIELDS (type);
2032   field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2033 
2034   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2035 
2036   return objc_build_constructor (type, v);
2037 }
2038 
2039 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2040    and initialized appropriately.  */
2041 
2042 static void
generate_objc_symtab_decl(void)2043 generate_objc_symtab_decl (void)
2044 {
2045   build_objc_symtab_template ();
2046   UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
2047   OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_base);
2048   finish_var_decl (UOBJC_SYMBOLS_decl,
2049 		   init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2050 }
2051 
2052 static void
objc_generate_v1_gnu_metadata(void)2053 objc_generate_v1_gnu_metadata (void)
2054 {
2055   struct imp_entry *impent;
2056   tree chain;
2057 
2058   /* Process the static instances here because initialization of objc_symtab
2059      depends on them.  */
2060   if (objc_static_instances)
2061     generate_static_references ();
2062 
2063   objc_implementation_context =
2064   implementation_template =
2065   UOBJC_CLASS_decl =
2066   UOBJC_METACLASS_decl = NULL_TREE;
2067 
2068   for (impent = imp_list; impent; impent = impent->next)
2069     {
2070       /* If -gen-decls is present, Dump the @interface of each class.
2071 	 TODO: Dump the classes in the  order they were found, rather than in
2072 	 reverse order as we are doing now.  */
2073       if (flag_gen_declaration)
2074 	dump_interface (gen_declaration_file, impent->imp_context);
2075 
2076       /* all of the following reference the string pool...  */
2077       if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2078 	generate_class_structures (impent);
2079       else
2080 	generate_category (impent);
2081     }
2082 
2083   /* If we are using an array of selectors, we must always
2084      finish up the array decl even if no selectors were used.  */
2085   build_gnu_selector_translation_table ();
2086 
2087   if (protocol_chain)
2088     generate_protocols ();
2089 
2090   /* Arrange for ObjC data structures to be initialized at run time.  */
2091   /* FIXME: Have some more elegant way to determine if we need to
2092      generate objc_symtab_decl or not, instead of checking these
2093      global symbols.  */
2094   if (imp_list || class_names_chain
2095       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain
2096       || prop_names_attr_chain)
2097     generate_objc_symtab_decl ();
2098 
2099   if (imp_list || class_names_chain || objc_static_instances
2100       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
2101     {
2102       /* Make sure that the meta-data are identified as being
2103 	 GNU-runtime.  */
2104       build_module_descriptor (OBJC_VERSION,
2105 			       build_tree_list (objc_meta, meta_base));
2106       build_module_initializer_routine ();
2107     }
2108 
2109   /* Dump the class references.  This forces the appropriate classes
2110      to be linked into the executable image, preserving unix archive
2111      semantics.  This can be removed when we move to a more dynamically
2112      linked environment.  */
2113 
2114   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2115     {
2116       handle_class_ref (chain);
2117       if (TREE_PURPOSE (chain))
2118 	generate_classref_translation_entry (chain);
2119     }
2120 
2121   for (impent = imp_list; impent; impent = impent->next)
2122     handle_impent (impent);
2123 
2124   generate_strings ();
2125 }
2126 
2127 /* --- exceptions --- */
2128 
2129 static GTY(()) tree objc_eh_personality_decl;
2130 
2131 static tree
objc_eh_runtime_type(tree type)2132 objc_eh_runtime_type (tree type)
2133 {
2134   tree ident, eh_id, decl, str;
2135 
2136   if (type == error_mark_node
2137       || errorcount || sorrycount)
2138     {
2139       /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2140 	 to prevent an ICE.  Note that we know that the compiler will
2141 	 terminate with an error and this 'ErrorMarkNode' class name will
2142 	 never be actually used.  */
2143       ident = get_identifier ("ErrorMarkNode");
2144       goto make_err_class;
2145     }
2146 
2147   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2148     /* We don't want to identify 'id' for GNU. Instead, build a 0
2149        entry in the exceptions table.  */
2150     return null_pointer_node;
2151 
2152   if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2153     {
2154 #ifdef OBJCPLUS
2155       /* This routine is also called for c++ catch clauses; in which case,
2156 	 we use the c++ typeinfo decl. */
2157       return build_eh_type_type (type);
2158 #else
2159       error ("non-objective-c type %qT cannot be caught", type);
2160       ident = get_identifier ("ErrorMarkNode");
2161       goto make_err_class;
2162 #endif
2163     }
2164   else
2165     ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2166 
2167 make_err_class:
2168   /* If this class was already referenced, then it will be output during
2169      meta-data emission, so we don't need to do it here.  */
2170   decl = get_objc_string_decl (ident, class_names);
2171   eh_id = add_objc_string (ident, class_names);
2172   if (!decl)
2173     {
2174       /* Not found ... so we need to build it - from the freshly-entered id.  */
2175       decl = get_objc_string_decl (ident, class_names);
2176       str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2177 			     IDENTIFIER_POINTER (ident));
2178       /* We have to finalize this var here, because this might be called after
2179 	 all the other metadata strings have been emitted.  */
2180       finish_var_decl (decl, str);
2181     }
2182   return eh_id;
2183 }
2184 
2185 static tree
objc_eh_personality(void)2186 objc_eh_personality (void)
2187 {
2188   if (!objc_eh_personality_decl)
2189 #ifndef OBJCPLUS
2190     objc_eh_personality_decl = build_personality_function  ("gnu_objc");
2191 #else
2192     objc_eh_personality_decl = build_personality_function  ("gxx");
2193 #endif
2194   return objc_eh_personality_decl;
2195 }
2196 
2197 /* -- interfaces --- */
2198 
2199 static tree
build_throw_stmt(location_t loc,tree throw_expr,bool rethrown ATTRIBUTE_UNUSED)2200 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2201 {
2202   tree t;
2203   vec<tree, va_gc> *parms;
2204   vec_alloc (parms, 1);
2205   /* A throw is just a call to the runtime throw function with the
2206      object as a parameter.  */
2207   parms->quick_push (throw_expr);
2208   t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms,
2209 			       NULL);
2210   vec_free (parms);
2211   return add_stmt (t);
2212 }
2213 
2214 /* Build __builtin_eh_pointer.  */
2215 
2216 static tree
objc_build_exc_ptr(struct objc_try_context ** x ATTRIBUTE_UNUSED)2217 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
2218 {
2219   tree t;
2220   t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2221   t = build_call_expr (t, 1, integer_zero_node);
2222   return fold_convert (objc_object_type, t);
2223 }
2224 
2225 static tree
begin_catch(struct objc_try_context ** cur_try_context,tree type,tree decl,tree compound,bool ellipsis ATTRIBUTE_UNUSED)2226 begin_catch (struct objc_try_context **cur_try_context, tree type,
2227 	     tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2228 {
2229   tree t;
2230   /* Record the data for the catch in the try context so that we can
2231      finalize it later.  */
2232   if (ellipsis)
2233     t = build_stmt (input_location, CATCH_EXPR, NULL, compound);
2234   else
2235     t = build_stmt (input_location, CATCH_EXPR, type, compound);
2236   (*cur_try_context)->current_catch = t;
2237 
2238   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
2239   t = objc_build_exc_ptr (cur_try_context);
2240   t = convert (TREE_TYPE (decl), t);
2241   return build2 (MODIFY_EXPR, void_type_node, decl, t);
2242 }
2243 
2244 static void
finish_catch(struct objc_try_context ** cur_try_context,tree current_catch)2245 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2246 {
2247   append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2248 }
2249 
2250 static tree
finish_try_stmt(struct objc_try_context ** cur_try_context)2251 finish_try_stmt (struct objc_try_context **cur_try_context)
2252 {
2253   struct objc_try_context *c = *cur_try_context;
2254   tree stmt = c->try_body;
2255   if (c->catch_list)
2256     stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2257   if (c->finally_body)
2258     stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2259   return stmt;
2260 }
2261 
2262 #include "gt-objc-objc-gnu-runtime-abi-01.h"
2263