1 /* Next Runtime (ABI-2) private.
2    Copyright (C) 2011-2020 Free Software Foundation, Inc.
3 
4    Contributed by Iain Sandoe and based, in part, on an implementation in
5    'branches/apple/trunk' contributed by Apple Computer Inc.
6 
7 This file is part of GCC.
8 
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13 
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22 
23 /* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
24 
25    This version is intended to match (logically) the output of Apple's
26    4.2.1 compiler.  */
27 
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tree.h"
32 #include "stringpool.h"
33 #include "attribs.h"
34 
35 #ifdef OBJCPLUS
36 #include "cp/cp-tree.h"
37 #else
38 #include "c/c-tree.h"
39 #include "c/c-lang.h"
40 #endif
41 #include "langhooks.h"
42 #include "c-family/c-objc.h"
43 #include "objc-act.h"
44 
45 /* When building Objective-C++, we are not linking against the C front-end
46    and so need to replicate the C tree-construction functions in some way.  */
47 #ifdef OBJCPLUS
48 #define OBJCP_REMAP_FUNCTIONS
49 #include "objcp-decl.h"
50 #endif  /* OBJCPLUS */
51 
52 #include "target.h"
53 #include "tree-iterator.h"
54 
55 #include "objc-runtime-hooks.h"
56 #include "objc-runtime-shared-support.h"
57 #include "objc-next-metadata-tags.h"
58 #include "objc-encoding.h"
59 
60 /* ABI 2 Private definitions. */
61 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
62 
63 #define TAG_GETCLASS		"objc_getClass"
64 #define TAG_GETMETACLASS	"objc_getMetaClass"
65 
66 #define TAG_MSGSEND		"objc_msgSend"
67 #define TAG_MSGSENDID		"objc_msgSendId"
68 #define TAG_MSGSENDSUPER	"objc_msgSendSuper2"
69 #define TAG_MSGSEND_STRET	"objc_msgSend_stret"
70 #define TAG_MSGSENDID_STRET	"objc_msgSendId_stret"
71 #define TAG_MSGSENDSUPER_STRET	"objc_msgSendSuper2_stret"
72 
73 #define USE_FIXUP_BEFORE	100600
74 #define TAG_FIXUP		"_fixup"
75 
76 
77 #define TAG_NEXT_EHVTABLE_NAME	"objc_ehtype_vtable"
78 #define TAG_V2_EH_TYPE		"objc_ehtype_t"
79 
80 #define UTAG_V2_CLASS		"_class_t"
81 #define UTAG_V2_CLASS_RO	"_class_ro_t"
82 #define UTAG_V2_PROTOCOL	"_protocol_t"
83 #define UTAG_V2_PROTOCOL_LIST	"_protocol_list_t"
84 
85 #define UTAG_V2_EH_TYPE		"_objc_ehtype_t"
86 
87 #define OBJC2_CLS_HAS_CXX_STRUCTORS	0x0004L
88 
89 enum objc_v2_tree_index
90 {
91   /* Templates.  */
92   OCTI_V2_CLS_TEMPL,
93   OCTI_V2_CAT_TEMPL,
94   OCTI_V2_CLS_RO_TEMPL,
95   OCTI_V2_PROTO_TEMPL,
96   OCTI_V2_IVAR_TEMPL,
97   OCTI_V2_IVAR_LIST_TEMPL,
98   OCTI_V2_MESSAGE_REF_TEMPL,
99   OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
100 
101   OCTI_V2_MESSAGE_SELECTOR_TYPE,
102   OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
103   OCTI_V2_IMP_TYPE,
104   OCTI_V2_SUPER_IMP_TYPE,
105 
106   OCTI_V2_CACHE_DECL,
107   OCTI_V2_VTABLE_DECL,
108 
109   OCTI_V2_PROPERTY_TEMPL,
110 
111   /* V2 messaging.  */
112   OCTI_V2_UMSG_FIXUP_DECL,
113   OCTI_V2_UMSG_STRET_FIXUP_DECL,
114   OCTI_V2_UMSG_ID_FIXUP_DECL,
115   OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
116   OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
117   OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
118 
119   /* Exceptions - related.  */
120   OCTI_V2_BEGIN_CATCH_DECL,
121   OCTI_V2_END_CATCH_DECL,
122   OCTI_V2_RETHROW_DECL,
123 
124   OCTI_V2_MAX
125 };
126 
127 #define objc_v2_class_template	objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
128 #define objc_v2_class_ro_template \
129 				objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
130 #define objc_v2_category_template \
131 				objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
132 #define objc_v2_protocol_template \
133 				objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
134 
135 /* struct message_ref_t */
136 #define objc_v2_message_ref_template \
137 				objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
138 
139 #define objc_v2_ivar_list_ptr	objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
140 
141 /* struct super_message_ref_t */
142 #define objc_v2_super_message_ref_template \
143 				objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
144 
145 /* struct message_ref_t* */
146 #define objc_v2_selector_type	objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
147 /* struct super_super_message_ref_t */
148 #define objc_v2_super_selector_type \
149 				objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
150 #define objc_v2_imp_type	objc_v2_global_trees[OCTI_V2_IMP_TYPE]
151 #define objc_v2_super_imp_type	objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
152 
153 #define UOBJC_V2_CACHE_decl	objc_v2_global_trees[OCTI_V2_CACHE_DECL]
154 #define UOBJC_V2_VTABLE_decl	objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
155 
156 #define objc_v2_ivar_template	objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
157 #define objc_v2_property_template \
158 				objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
159 
160 /* V2 Messaging */
161 
162 /* objc_msgSend_fixup_rtp */
163 #define umsg_fixup_decl		objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
164 /* objc_msgSend_stret_fixup_rtp */
165 #define umsg_stret_fixup_decl	objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
166 /* objc_msgSendId_fixup_rtp */
167 #define umsg_id_fixup_decl	objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
168 /* objc_msgSendId_stret_fixup_rtp */
169 #define umsg_id_stret_fixup_decl \
170 				objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
171 /* objc_msgSendSuper2_fixup_rtp */
172 #define umsg_id_super2_fixup_decl \
173 				objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
174 /* objc_msgSendSuper2_stret_fixup_rtp */
175 #define umsg_id_super2_stret_fixup_decl \
176 				objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
177 
178 #define objc2_begin_catch_decl	objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
179 #define objc2_end_catch_decl	objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
180 #define objc_rethrow_exception_decl \
181 				objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
182 
183 /* The OCTI_V2_... enumeration itself is in above.  */
184 static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
185 
186 static void next_runtime_02_initialize (void);
187 
188 static void build_v2_message_ref_templates (void);
189 static void build_v2_class_templates (void);
190 static void build_v2_super_template (void);
191 static void build_v2_category_template (void);
192 static void build_v2_protocol_template (void);
193 
194 static tree next_runtime_abi_02_super_superclassfield_id (void);
195 
196 static tree next_runtime_abi_02_class_decl (tree);
197 static tree next_runtime_abi_02_metaclass_decl (tree);
198 static tree next_runtime_abi_02_category_decl (tree);
199 static tree next_runtime_abi_02_protocol_decl (tree);
200 static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
201 
202 static tree next_runtime_abi_02_get_class_reference (tree);
203 static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
204 static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
205 static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
206 static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
207 static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
208 
209 static tree next_runtime_abi_02_receiver_is_class_object (tree);
210 static void next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **,
211 							tree, int, int);
212 static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
213 							tree, tree, tree, int);
214 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
215 static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
216 
217 static tree create_extern_decl (tree, const char *);
218 
219 static void objc_generate_v2_next_metadata (void);
220 static bool objc2_objc_exception_attr (tree);
221 
222 /* void build_v2_protocol_reference (tree);*/
223 static void build_v2_ehtype_template (void);
224 static void build_v2_eh_catch_objects (void);
225 static tree next_runtime_02_eh_type (tree);
226 static tree objc_eh_personality (void);
227 static tree build_throw_stmt (location_t, tree, bool);
228 static tree objc_build_exc_ptr (struct objc_try_context **);
229 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
230 static void finish_catch (struct objc_try_context **, tree);
231 static tree finish_try_stmt (struct objc_try_context **);
232 
233 /* TODO: Use an objc-map.  */
234 static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
235 
236 bool
objc_next_runtime_abi_02_init(objc_runtime_hooks * rthooks)237 objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
238 {
239   extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
240 
241   if (flag_objc_sjlj_exceptions)
242     {
243       inform (UNKNOWN_LOCATION,
244 	      "%<-fobjc-sjlj-exceptions%> is ignored for "
245 	      "%<-fnext-runtime%> when %<-fobjc-abi-version%> "
246 	      "greater than 1");
247       flag_objc_sjlj_exceptions = 0;
248     }
249 
250   /* NeXT ABI 2 is intended to default to checking for nil receivers.  */
251   if (! global_options_set.x_flag_objc_nilcheck)
252     flag_objc_nilcheck = 1;
253 
254   rthooks->initialize = next_runtime_02_initialize;
255   rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
256   rthooks->tag_getclass = TAG_GETCLASS;
257   rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
258 
259   rthooks->class_decl = next_runtime_abi_02_class_decl;
260   rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
261   rthooks->category_decl = next_runtime_abi_02_category_decl;
262   rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
263   rthooks->string_decl = next_runtime_abi_02_string_decl;
264 
265   rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
266   rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
267   rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
268   rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
269   rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
270   rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
271 
272   rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
273   rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
274   rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
275 
276   rthooks->setup_const_string_class_decl =
277 				next_runtime_abi_02_setup_const_string_class_decl;
278   rthooks->build_const_string_constructor =
279 				next_runtime_abi_02_build_const_string_constructor;
280 
281   rthooks->build_throw_stmt = build_throw_stmt;
282   rthooks->build_exc_ptr = objc_build_exc_ptr;
283   rthooks->begin_catch = begin_catch;
284   rthooks->finish_catch = finish_catch;
285   rthooks->finish_try_stmt = finish_try_stmt;
286 
287   rthooks->generate_metadata = objc_generate_v2_next_metadata;
288   return true;
289 }
290 
291 /* We need a way to convey what kind of meta-data are represented by a given
292    variable, since each type is expected (by the runtime) to be found in a
293    specific named section.  The solution must be usable with LTO.
294 
295    The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
296    satisfactory when LTO is used with ABI-2.  We now tag ObjC meta-data with
297    identification attributes in the front end.  The back-end may choose to act
298    on these as it requires.  */
299 
300 static void
next_runtime_abi_02_init_metadata_attributes(void)301 next_runtime_abi_02_init_metadata_attributes (void)
302 {
303   if (!objc_meta)
304     objc_meta = get_identifier ("OBJC2META");
305 
306   if (!meta_base)
307     meta_base = get_identifier ("V2_BASE");
308 
309   meta_class = get_identifier ("G2_CLAS");
310   meta_metaclass = get_identifier ("G2_META");
311   meta_category = meta_base;
312   meta_protocol = get_identifier ("V2_PCOL");
313 
314   meta_clac_vars =
315   meta_clai_vars = meta_base;
316 
317   meta_clac_meth =
318   meta_clai_meth =
319   meta_catc_meth =
320   meta_cati_meth =
321   meta_proto_cls_meth =
322   meta_proto_nst_meth = meta_base;
323 
324   meta_clas_prot =
325   meta_catg_prot = meta_base;
326 
327   meta_sel_refs = get_identifier ("V2_SRFS");
328 
329   meta_class_name = get_identifier ("V2_CNAM");
330   meta_meth_name = get_identifier ("V2_MNAM");
331 
332   meta_meth_type = get_identifier ("V2_MTYP");
333   meta_prop_name_attr = get_identifier ("V2_STRG");
334 
335   meta_mref = get_identifier ("V2_MREF");
336   meta_class_ref = get_identifier ("V2_CLRF");
337   meta_superclass_ref = get_identifier ("V2_SURF");
338 
339   meta_label_classlist = get_identifier ("V2_CLAB");
340   meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
341   meta_label_categorylist = get_identifier ("V2_CALA");
342   meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
343 
344   meta_label_protocollist = get_identifier ("V2_PLST");
345   meta_proto_ref = get_identifier ("V2_PRFS");
346 
347   meta_info = get_identifier ("V2_INFO");
348 
349   meta_ehtype = get_identifier ("V2_EHTY");
350 
351   meta_const_str = get_identifier ("V2_CSTR");
352 
353   meta_ivar_ref = get_identifier ("V2_IVRF");
354 }
355 
next_runtime_02_initialize(void)356 static void next_runtime_02_initialize (void)
357 {
358   tree type;
359 #ifdef OBJCPLUS
360   /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
361      default.  */
362   if (!global_options_set.x_flag_objc_call_cxx_cdtors)
363     global_options.x_flag_objc_call_cxx_cdtors = 1;
364 #endif
365 
366   /* Set up attributes to be attached to the meta-data so that they
367      will be placed in the correct sections.  */
368   next_runtime_abi_02_init_metadata_attributes ();
369 
370   /* `struct objc_selector *' */
371   objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
372 					   get_identifier (TAG_SELECTOR)));
373 
374   /* SEL typedef.  */
375   type = lang_hooks.decls.pushdecl (build_decl (input_location,
376 						TYPE_DECL,
377 						objc_selector_name,
378 						objc_selector_type));
379   TREE_NO_WARNING (type) = 1;
380 
381   /* IMP : id (*) (id, _message_ref_t*, ...)
382      SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
383      objc_v2_selector_type.  */
384   build_v2_message_ref_templates ();
385 
386   objc_v2_ivar_list_ptr =
387 		build_pointer_type (xref_tag (RECORD_TYPE,
388 				    get_identifier ("_ivar_list_t")));
389 
390   objc_prop_list_ptr =
391 		build_pointer_type (xref_tag (RECORD_TYPE,
392 				    get_identifier ("_prop_list_t")));
393 
394   build_v2_class_templates ();
395   build_v2_super_template ();
396   build_v2_protocol_template ();
397   build_v2_category_template ();
398 
399   bool fixup_p = flag_next_runtime < USE_FIXUP_BEFORE;
400   if (fixup_p)
401     {
402       /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
403       type = build_varargs_function_type_list (objc_object_type,
404 					       objc_object_type,
405 					       objc_v2_selector_type,
406 					       NULL_TREE);
407     }
408   else
409     {
410       /* id objc_msgSendXXXX (id, SEL, ...); */
411       type = build_varargs_function_type_list (objc_object_type,
412 					       objc_object_type,
413 					       objc_selector_type,
414 					       NULL_TREE);
415     }
416   const char *fnam = fixup_p ? TAG_MSGSEND TAG_FIXUP : TAG_MSGSEND;
417   umsg_fixup_decl =  add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
418 					   NULL, NULL_TREE);
419   TREE_NOTHROW (umsg_fixup_decl) = 0;
420 
421   /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
422   fnam = fixup_p ? TAG_MSGSEND_STRET TAG_FIXUP : TAG_MSGSEND_STRET;
423   umsg_stret_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
424 						NULL, NULL_TREE);
425   TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
426 
427   /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
428   fnam = fixup_p ? TAG_MSGSENDID TAG_FIXUP : TAG_MSGSENDID;
429   umsg_id_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
430 					     NULL, NULL_TREE);
431   TREE_NOTHROW (umsg_id_fixup_decl) = 0;
432 
433   /* id objc_msgSendId_stret_fixup_rtp (id, struct message_ref_t*, ...); */
434   fnam = fixup_p ? TAG_MSGSENDID_STRET TAG_FIXUP : TAG_MSGSENDID_STRET;
435   umsg_id_stret_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
436 						   NULL, NULL_TREE);
437   TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
438 
439  /* id objc_msgSendSuper2_fixup_rtp
440 			(struct objc_super *, struct message_ref_t*, ...); */
441   type = build_varargs_function_type_list (objc_object_type,
442 					   objc_super_type,
443 					   objc_v2_super_selector_type,
444 					   NULL_TREE);
445   fnam = fixup_p ? TAG_MSGSENDSUPER TAG_FIXUP : TAG_MSGSENDSUPER;
446   umsg_id_super2_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
447 						    NULL, NULL_TREE);
448   TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
449 
450   /* id objc_msgSendSuper2_stret_fixup_rtp
451 			(struct objc_super *, struct message_ref_t*, ...); */
452   fnam = fixup_p ? TAG_MSGSENDSUPER_STRET TAG_FIXUP : TAG_MSGSENDSUPER_STRET;
453   umsg_id_super2_stret_fixup_decl = add_builtin_function (fnam, type, 0,
454 							  NOT_BUILT_IN,  NULL,
455 							  NULL_TREE);
456   TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
457 
458   /* Present in the library, but unused by the FE.  */
459   /* Protocol *objc_getProtocol (const char *)
460   type = build_function_type_list (objc_protocol_type,
461 				   const_string_type_node,
462 				   NULL_TREE);
463   objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
464 						    type, 0, NOT_BUILT_IN,
465 						    NULL, NULL_TREE);
466   TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
467 
468   UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
469 					    "_objc_empty_cache");
470 
471   UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
472 					     "_objc_empty_vtable");
473 
474   /* id objc_getClass (const char *); */
475   type = build_function_type_list (objc_object_type,
476                                    const_string_type_node,
477                                    NULL_TREE);
478   objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
479 					      type, 0, NOT_BUILT_IN,
480 					      NULL, NULL_TREE);
481 
482   /* id objc_getMetaClass (const char *); */
483   objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
484 						   type, 0, NOT_BUILT_IN,
485 						   NULL, NULL_TREE);
486 
487   /* This is the type of all of the following functions
488      objc_copyStruct().  */
489   type = build_function_type_list (void_type_node,
490 				   ptr_type_node,
491 				   const_ptr_type_node,
492 				   ptrdiff_type_node,
493 				   boolean_type_node,
494 				   boolean_type_node,
495 				   NULL_TREE);
496   /* Declare the following function:
497 	 void
498          objc_copyStruct (void *destination, const void *source,
499 	                  ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
500   objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
501 						   type, 0, NOT_BUILT_IN,
502 						   NULL, NULL_TREE);
503   TREE_NOTHROW (objc_copyStruct_decl) = 0;
504   objc_getPropertyStruct_decl = NULL_TREE;
505   objc_setPropertyStruct_decl = NULL_TREE;
506 
507   gcc_checking_assert (!flag_objc_sjlj_exceptions);
508 
509   /* Although we warn that fobjc-exceptions is required for exceptions
510      code, we carry on and create it anyway.  */
511 
512   /* This can be required, even when exceptions code is not present,
513      when an __attribute__((objc_exception)) is applied to a
514      class.  */
515   build_v2_ehtype_template ();
516 
517   /* void * objc_begin_catch (void *) */
518   type = build_function_type_list (ptr_type_node,
519 				   ptr_type_node, NULL_TREE);
520 
521   objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
522 						 type, 0, NOT_BUILT_IN,
523 						 NULL, NULL_TREE);
524   TREE_NOTHROW (objc2_begin_catch_decl) = 0;
525 
526   /* void objc_end_catch () */
527   type = build_function_type_list (void_type_node, NULL_TREE);
528   objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
529 						type, 0, NOT_BUILT_IN,
530 						NULL, NULL_TREE);
531   TREE_NOTHROW (objc2_end_catch_decl) = 0;
532 
533   /* void objc_exception_rethrow (void) */
534   objc_rethrow_exception_decl =
535 			add_builtin_function ("objc_exception_rethrow",
536 					      type, 0, NOT_BUILT_IN,
537 					      NULL, NULL_TREE);
538   TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
539   using_eh_for_cleanups ();
540   lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
541   lang_hooks.eh_personality = objc_eh_personality;
542 }
543 
544 /* NOTE --- templates --- */
545 
546 /* Set 'objc_v2_message_ref_template' to the data type node for
547    'struct _message_ref_t'.  This needs to be done just once per
548    compilation.  Also Set 'objc_v2_super_message_ref_template' to data
549    type node for 'struct _super_message_ref_t'.  */
550 
551 /* struct _message_ref_t
552    {
553      IMP messenger;
554      SEL name;
555    };
556    where IMP is: id (*) (id, _message_ref_t*, ...)
557 */
558 
559 /* struct _super_message_ref_t
560    {
561      SUPER_IMP messenger;
562      SEL name;
563    };
564    where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
565 */
566 
567 static void
build_v2_message_ref_templates(void)568 build_v2_message_ref_templates (void)
569 {
570   tree ptr_message_ref_t;
571   tree decls, *chain = NULL;
572 
573   /* struct _message_ref_t {...} */
574   objc_v2_message_ref_template =
575 		objc_start_struct (get_identifier ("_message_ref_t"));
576 
577   /* IMP messenger; */
578   ptr_message_ref_t =
579 		build_pointer_type (xref_tag (RECORD_TYPE,
580 				    get_identifier ("_message_ref_t")));
581 
582   objc_v2_imp_type =
583 		build_pointer_type (build_function_type_list
584 					(objc_object_type,
585 					 objc_object_type,
586 					 ptr_message_ref_t,
587 					 NULL_TREE));
588 
589   decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
590 
591   /* SEL name; */
592   add_field_decl (objc_selector_type, "name", &chain);
593 
594   objc_finish_struct (objc_v2_message_ref_template, decls);
595 
596   objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
597 
598   chain = NULL;
599   /* struct _super_message_ref_t {...} */
600   objc_v2_super_message_ref_template =
601 		objc_start_struct (get_identifier ("_super_message_ref_t"));
602 
603   /* SUPER_IMP messenger; */
604   ptr_message_ref_t = build_pointer_type
605 			(xref_tag (RECORD_TYPE,
606 				   get_identifier ("_super_message_ref_t")));
607 
608   objc_v2_super_imp_type =
609 		build_pointer_type (build_function_type_list
610 					(objc_object_type,
611 					 objc_super_type,
612 					 ptr_message_ref_t,
613 					 NULL_TREE));
614 
615   add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
616 
617   /* SEL name; */
618   add_field_decl (objc_selector_type, "name", &chain);
619 
620   objc_finish_struct (objc_v2_super_message_ref_template, decls);
621   objc_v2_super_selector_type =
622 		build_pointer_type (objc_v2_super_message_ref_template);
623 }
624 
625 /* Build following types which represent each class implementation.
626 
627 struct class_ro_t
628 {
629     uint32_t const flags;
630     uint32_t const instanceStart;
631     uint32_t const instanceSize;
632 #ifdef __LP64__
633     uint32_t const reserved;
634 #endif
635     const uint8_t * const ivarLayout;
636     const char *const name;
637     const struct method_list_t * const baseMethods;
638     const struct objc_protocol_list *const baseProtocols;
639     const struct ivar_list_t *const ivars;
640     const uint8_t * const weakIvarLayout;
641     const struct _prop_list_t * const properties;
642 };
643 
644 struct class_t
645 {
646     struct class_t *isa;
647     struct class_t *superclass;
648     void *cache;
649     IMP *vtable;
650 
651     ...When this is active - it will point to a rw version, but
652        when we build the meta-data we point it to the ro...
653     struct class_ro_t *data;
654 };
655 
656 */
657 
658 static void
build_v2_class_templates(void)659 build_v2_class_templates (void)
660 {
661   tree cnst_strg_type;
662   tree decls, *chain = NULL;
663 
664   /* struct class_ro_t {...} */
665   objc_v2_class_ro_template =
666 	objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
667 
668   /* uint32_t const flags; */
669   decls = add_field_decl (integer_type_node, "flags", &chain);
670 
671   /* uint32_t const instanceStart; */
672   add_field_decl (integer_type_node, "instanceStart", &chain);
673 
674   /* uint32_t const instanceSize; */
675   add_field_decl (integer_type_node, "instanceSize", &chain);
676 
677   /* This ABI is currently only used on m64 NeXT.  We always
678      explicitly declare the alignment padding.  */
679   /* uint32_t const reserved; */
680   add_field_decl (integer_type_node, "reserved", &chain);
681 
682   /* const uint8_t * const ivarLayout; */
683   cnst_strg_type = build_pointer_type (unsigned_char_type_node);
684   add_field_decl (cnst_strg_type, "ivarLayout", &chain);
685 
686   /* const char *const name; */
687   add_field_decl (string_type_node, "name", &chain);
688 
689   /* const struct method_list_t * const baseMethods; */
690   add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
691 
692   /* const struct objc_protocol_list *const baseProtocols; */
693   add_field_decl (build_pointer_type
694 			(xref_tag (RECORD_TYPE,
695 				   get_identifier (UTAG_V2_PROTOCOL_LIST))),
696 				  "baseProtocols", &chain);
697 
698   /* const struct ivar_list_t *const ivars; */
699   add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
700 
701   /* const uint8_t * const weakIvarLayout; */
702   add_field_decl (cnst_strg_type, "weakIvarLayout",  &chain);
703 
704   /* struct _prop_list_t * baseProperties; */
705   add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
706 
707   objc_finish_struct (objc_v2_class_ro_template, decls);
708 
709   chain = NULL;
710   /* struct class_t {...} */
711   objc_v2_class_template =
712 	objc_start_struct (get_identifier (UTAG_V2_CLASS));
713 
714   /* struct class_t *isa; */
715   decls = add_field_decl (build_pointer_type (objc_v2_class_template),
716 			  "isa", &chain);
717 
718   /* struct class_t * const superclass; */
719   add_field_decl (build_pointer_type (objc_v2_class_template),
720 				      "superclass", &chain);
721 
722   /* void *cache; */
723   add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
724 
725   /* IMP *vtable; */
726   add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
727 
728   /* struct class_ro_t *ro; */
729   add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
730 
731   objc_finish_struct (objc_v2_class_template, decls);
732 }
733 
734 /* struct _objc_super
735    {
736      struct _objc_object *self;
737      Class cls;
738    }; */
739 void
build_v2_super_template(void)740 build_v2_super_template (void)
741 {
742   tree decls, *chain = NULL;
743 
744   objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
745 
746   /* struct _objc_object *self; */
747   decls = add_field_decl (objc_object_type, "self", &chain);
748 
749   /* Class cls; */
750   add_field_decl (objc_class_type, "cls", &chain);
751 
752   objc_finish_struct (objc_super_template, decls);
753 }
754 
755 /* struct protocol_t
756   {
757      Class isa;
758      const char * const protocol_name;
759      const struct protocol_list_t * const protocol_list;
760      const struct method_list_t * const instance_methods;
761      const struct method_list_t * const class_methods;
762      const struct method_list_t * optionalInstanceMethods;
763      const struct method_list_t * optionalClassMethod
764      const struct _prop_list_t * const properties;
765      const uint32_t size;
766      const uint32_t flags;
767      const char ** extended_method_types;
768      const char * demangled_name;
769      const struct _prop_list_t * class_properties;
770    }
771 */
772 static void
build_v2_protocol_template(void)773 build_v2_protocol_template (void)
774 {
775   tree decls, *chain = NULL;
776 
777   objc_v2_protocol_template =
778 	objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
779 
780   /* Class isa; */
781   decls = add_field_decl (objc_object_type, "isa", &chain);
782 
783   /* char *protocol_name; */
784   add_field_decl (string_type_node, "protocol_name", &chain);
785 
786   /* const struct protocol_list_t * const protocol_list; */
787   add_field_decl (build_pointer_type (objc_v2_protocol_template),
788 		  "protocol_list", &chain);
789 
790   /* const struct method_list_t * const instance_methods; */
791   add_field_decl (objc_method_proto_list_ptr,  "instance_methods", &chain);
792 
793   /* const struct method_list_t * const class_methods; */
794   add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
795 
796   /* const struct method_list_t * optionalInstanceMethods; */
797   add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
798 
799   /* const struct method_list_t * optionalClassMethods; */
800   add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
801 
802   /* struct _prop_list_t * properties; */
803   add_field_decl (objc_prop_list_ptr, "properties", &chain);
804 
805   /* const uint32_t size; */
806   add_field_decl (integer_type_node, "size", &chain);
807 
808   /* const uint32_t flags; */
809   add_field_decl (integer_type_node, "flags", &chain);
810 
811   /* const char **extendedMethodTypes; */
812   tree ptr_to_ptr_to_char = build_pointer_type (string_type_node);
813   add_field_decl (ptr_to_ptr_to_char, "extended_method_types", &chain);
814 
815   /* const char *demangledName; */
816   add_field_decl (string_type_node, "demangled_name", &chain);
817 
818   /* const struct _prop_list_t *class_properties; */
819   add_field_decl (objc_prop_list_ptr, "class_properties", &chain);
820 
821   objc_finish_struct (objc_v2_protocol_template, decls);
822 }
823 
824 /* Build type for a category:
825    struct category_t
826    {
827      const char * const name;
828      struct class_t *const cls;
829      const struct method_list_t * const instance_methods;
830      const struct method_list_t * const class_methods;
831      const struct protocol_list_t * const protocols;
832      const struct _prop_list_t * const properties;
833    }
834 */
835 
836 static void
build_v2_category_template(void)837 build_v2_category_template (void)
838 {
839   tree decls, *chain = NULL;
840 
841   objc_v2_category_template =
842 	objc_start_struct (get_identifier ("_category_t"));
843 
844   /* char *name; */
845   decls = add_field_decl (string_type_node, "name", &chain);
846 
847   /* struct class_t *const cls; */
848   add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
849 
850   /* struct method_list_t *instance_methods; */
851   add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
852 
853   /* struct method_list_t *class_methods; */
854   add_field_decl (objc_method_list_ptr, "class_methods", &chain);
855 
856   /* struct protocol_list_t *protocol_list; */
857   add_field_decl (build_pointer_type (objc_v2_protocol_template),
858                   "protocol_list", &chain );
859 
860   /* struct _prop_list_t * properties; */
861   add_field_decl (objc_prop_list_ptr, "properties", &chain);
862 
863   objc_finish_struct (objc_v2_category_template, decls);
864 }
865 
866 /* NOTE --- Decls, Identifiers, Names etc. --- */
867 
868 /* This routine is given a name and returns a matching extern variable
869    if one is found.  */
870 
871 static tree
hash_name_lookup(hash * hashlist,tree name)872 hash_name_lookup (hash *hashlist, tree name)
873 {
874   hash target;
875 
876   target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
877 
878   while (target)
879     {
880       if (name == DECL_NAME (target->key))
881 	return target->key;
882 
883       target = target->next;
884     }
885   return 0;
886 }
887 
888 /* This routine is given an extern variable and enters it in its hash
889    table.  Note that hashing is done on its inner IDENTIFIER_NODE
890    node.  */
891 
892 static void
hash_name_enter(hash * hashlist,tree id)893 hash_name_enter (hash *hashlist, tree id)
894 {
895   hash obj;
896   int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
897 
898   obj = ggc_alloc<hashed_entry> ();
899   obj->list = 0;
900   obj->next = hashlist[slot];
901   obj->key = id;
902 
903   hashlist[slot] = obj;		/* append to front */
904 }
905 
906 /* Create a declaration "extern <type> <name>;"
907    The var will need to be finalized (e.g. by calling finish_var_decl()).  */
908 
909 static tree
create_extern_decl(tree type,const char * name)910 create_extern_decl (tree type, const char *name)
911 {
912   tree id = get_identifier (name);
913   tree var = hash_name_lookup (extern_names, id);
914   if (var)
915       return var;
916   /* New name. */
917   var = start_var_decl (type, name);
918   TREE_STATIC (var) = 0;
919   DECL_EXTERNAL (var) = 1;
920   TREE_PUBLIC (var) = 1;
921   hash_name_enter (extern_names, var);
922   return var;
923 }
924 
925 /* Create a globally visible definition for variable NAME of a given TYPE. The
926    finish_var_decl() routine will need to be called on it afterwards.  */
927 static tree
928 create_global_decl (tree type, const char *name, bool is_def = false);
929 
930 static tree
create_global_decl(tree type,const char * name,bool is_def)931 create_global_decl (tree type, const char *name, bool is_def)
932 {
933   tree id = get_identifier (name);
934   tree var = hash_name_lookup (extern_names, id);
935   if (var)
936     is_def = true;
937   else
938     {
939       var = start_var_decl (type, name);
940       hash_name_enter (extern_names, var);
941     }
942   if (is_def)
943     {
944       DECL_EXTERNAL (var) = 0;
945       TREE_STATIC (var) = 1;
946     }
947   TREE_PUBLIC (var) = 1;
948   return var;
949 }
950 
951 /* Create a symbol with __attribute__ ((visibility ("hidden")))
952    attribute (private extern).  */
953 static tree
954 create_hidden_decl (tree type, const char *name, bool is_def = false);
955 
956 static tree
create_hidden_decl(tree type,const char * name,bool is_def)957 create_hidden_decl (tree type, const char *name, bool is_def)
958 {
959     tree decl = create_global_decl (type, name, is_def);
960     DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
961     DECL_VISIBILITY_SPECIFIED (decl) = 1;
962     return decl;
963 }
964 
965 /* Irritatingly, we have a different superclass field name for ABI=2.  */
966 /* PS/TODO: The field name does not matter, it is only used internally
967    by the compiler.  We can rename it to whatever we want. ;-) */
968 
969 static tree
next_runtime_abi_02_super_superclassfield_id(void)970 next_runtime_abi_02_super_superclassfield_id (void)
971 {
972   /* TODO: Simplify.  Just always return get_identifier ("cls"), or at
973      most look it once at startup then always return it.  */
974   if (!super_superclassfield_id)
975     super_superclassfield_id = get_identifier ("cls");
976   return super_superclassfield_id;
977 }
978 
979 static tree
next_runtime_abi_02_class_decl(tree klass)980 next_runtime_abi_02_class_decl (tree klass)
981 {
982   tree decl;
983   char buf[BUFSIZE];
984   snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
985 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
986   /* ObjC2 classes are extern visible.  */
987   decl = create_global_decl (objc_v2_class_template, buf);
988   OBJCMETA (decl, objc_meta, meta_class);
989   return decl;
990 }
991 
992 static tree
next_runtime_abi_02_metaclass_decl(tree klass)993 next_runtime_abi_02_metaclass_decl (tree klass)
994 {
995   tree decl;
996   char buf[BUFSIZE];
997   snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
998 	    IDENTIFIER_POINTER (CLASS_NAME (klass)));
999   /* ObjC2 classes are extern visible.  */
1000   decl = create_global_decl (objc_v2_class_template, buf);
1001   OBJCMETA (decl, objc_meta, meta_metaclass);
1002   return decl;
1003 }
1004 
1005 static tree
next_runtime_abi_02_category_decl(tree klass)1006 next_runtime_abi_02_category_decl (tree klass)
1007 {
1008   tree decl;
1009   char buf[BUFSIZE];
1010   snprintf (buf, BUFSIZE, "_OBJC_Category_%s_%s",
1011 	    IDENTIFIER_POINTER (CLASS_NAME (klass)),
1012 	    IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)));
1013   decl = start_var_decl (objc_v2_category_template, buf);
1014   OBJCMETA (decl, objc_meta, meta_category);
1015   return decl;
1016 }
1017 
1018 static tree
next_runtime_abi_02_protocol_decl(tree p)1019 next_runtime_abi_02_protocol_decl (tree p)
1020 {
1021   tree decl;
1022   char buf[BUFSIZE];
1023 
1024   /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
1025   snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
1026 	    IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
1027   if (flag_next_runtime >= USE_FIXUP_BEFORE)
1028     {
1029       decl = create_hidden_decl (objc_v2_protocol_template, buf);
1030       DECL_WEAK (decl) = true;
1031     }
1032   else
1033     decl = start_var_decl (objc_v2_protocol_template, buf);
1034   OBJCMETA (decl, objc_meta, meta_protocol);
1035   DECL_PRESERVE_P (decl) = 1;
1036   return decl;
1037 }
1038 
1039 static tree
next_runtime_abi_02_string_decl(tree type,const char * name,string_section where)1040 next_runtime_abi_02_string_decl (tree type, const char *name,  string_section where)
1041 {
1042   tree var = start_var_decl (type, name);
1043   switch (where)
1044     {
1045       case class_names:
1046 	OBJCMETA (var, objc_meta, meta_class_name);
1047 	break;
1048       case meth_var_names:
1049 	OBJCMETA (var, objc_meta, meta_meth_name);
1050 	break;
1051       case meth_var_types:
1052 	OBJCMETA (var, objc_meta, meta_meth_type);
1053 	break;
1054       case prop_names_attr:
1055 	OBJCMETA (var, objc_meta, meta_prop_name_attr);
1056 	break;
1057       default:
1058 	OBJCMETA (var, objc_meta, meta_base);
1059 	break;
1060     }
1061   return var;
1062 }
1063 
1064 /* NOTE --- entry --- */
1065 
1066 struct GTY(()) ident_data_tuple {
1067   tree ident;
1068   tree data;
1069 };
1070 
1071 /* This routine creates a file scope static variable of type 'Class'
1072    to hold the address of a class.  */
1073 
1074 static tree
build_v2_class_reference_decl(tree ident)1075 build_v2_class_reference_decl (tree ident)
1076 {
1077   tree decl;
1078   char buf[BUFSIZE];
1079 
1080   snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1081   decl = start_var_decl (objc_class_type, buf);
1082   OBJCMETA (decl, objc_meta, meta_class_ref);
1083   return decl;
1084 }
1085 
1086 /* This routine builds a class refs entry for each class name used.
1087    Initially, a (static-ref, IDENT) tuple is added to the list.  The
1088    ident is replaced with address of the class metadata (of type
1089    'Class') in the output routine.  */
1090 
1091 static GTY (()) vec<ident_data_tuple, va_gc> *classrefs;
1092 
1093 static tree
objc_v2_get_class_reference(tree ident)1094 objc_v2_get_class_reference (tree ident)
1095 {
1096   tree decl;
1097   ident_data_tuple e;
1098   if (classrefs)
1099     {
1100       int count;
1101       ident_data_tuple *ref;
1102       FOR_EACH_VEC_ELT (*classrefs, count, ref)
1103 	{
1104 	  if (ref->ident == ident)
1105 	    {
1106 	      if (!ref->data)
1107 		ref->data = build_v2_class_reference_decl (ident);
1108 	      return ref->data;
1109 	    }
1110 	}
1111     }
1112   else
1113     /* Somewhat arbitrary initial provision.  */
1114     vec_alloc (classrefs, 16);
1115 
1116   /* We come here if we don't find the entry - or if the table was yet
1117      to be created.  */
1118   decl = build_v2_class_reference_decl (ident);
1119   e.ident = ident;
1120   e.data = decl;
1121   vec_safe_push (classrefs, e);
1122   return decl;
1123 }
1124 
1125 static tree
next_runtime_abi_02_get_class_reference(tree ident)1126 next_runtime_abi_02_get_class_reference (tree ident)
1127 {
1128   if (!flag_zero_link)
1129     return objc_v2_get_class_reference (ident);
1130   else
1131     {
1132       /* We fall back to using objc_getClass ().  */
1133       vec<tree, va_gc> *v;
1134       vec_alloc (v, 1);
1135       tree t;
1136       /* ??? add_class_reference (ident); - is pointless, since the
1137          system lib does not export the equivalent symbols.  Maybe we
1138          need to build a class ref anyway.  */
1139       t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1140 				   IDENTIFIER_POINTER (ident));
1141       v->quick_push (t);
1142       t = build_function_call_vec (input_location, vNULL, objc_get_class_decl,
1143 				   v, 0);
1144       vec_free (v);
1145       return t;
1146     }
1147 }
1148 
1149 /* Used by build_function_type_for_method.  Append the types for
1150    receiver & _cmd at the start of a method argument list to ARGTYPES.
1151    CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1152    trying to define a method or call one.  SUPERFLAG says this is for a
1153    send to super.  METH may be NULL, in the case that there is no
1154    prototype.  */
1155 
1156 static void
next_runtime_abi_02_get_arg_type_list_base(vec<tree,va_gc> ** argtypes,tree meth,int context,int superflag)1157 next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1158 					    tree meth, int context,
1159 					    int superflag)
1160 {
1161   tree receiver_type;
1162 
1163   if (superflag)
1164     receiver_type = objc_super_type;
1165   else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1166     receiver_type = objc_instance_type;
1167   else
1168     receiver_type = objc_object_type;
1169 
1170   vec_safe_push (*argtypes, receiver_type);
1171   if (flag_next_runtime < USE_FIXUP_BEFORE)
1172     /* Selector type - will eventually change to `int'.  */
1173     vec_safe_push (*argtypes, superflag ? objc_v2_super_selector_type
1174 					: objc_v2_selector_type);
1175   else
1176     vec_safe_push (*argtypes, objc_selector_type);
1177 }
1178 
1179 /* TODO: Merge this with the message refs.  */
1180 static tree
build_selector_reference_decl(tree ident)1181 build_selector_reference_decl (tree ident)
1182 {
1183   tree decl;
1184   char *t, buf[BUFSIZE];
1185 
1186   snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1187   t = buf;
1188   while (*t)
1189     {
1190       if (*t==':')
1191         *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
1192       t++;
1193     }
1194   decl = start_var_decl (objc_selector_type, buf);
1195   OBJCMETA (decl, objc_meta, meta_sel_refs);
1196   return decl;
1197 }
1198 
1199 static tree
next_runtime_abi_02_build_selector_reference(location_t loc ATTRIBUTE_UNUSED,tree ident,tree proto ATTRIBUTE_UNUSED)1200 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1201 					      tree ident,
1202 					      tree proto ATTRIBUTE_UNUSED)
1203 {
1204   tree *chain = &sel_ref_chain;
1205   tree expr;
1206 
1207   while (*chain)
1208     {
1209       if (TREE_VALUE (*chain) == ident)
1210 	return TREE_PURPOSE (*chain);
1211 
1212       chain = &TREE_CHAIN (*chain);
1213     }
1214 
1215   expr = build_selector_reference_decl (ident);
1216   *chain = tree_cons (expr, ident, NULL_TREE);
1217 
1218   return expr;
1219 }
1220 
1221 /* Declare a variable of type 'struct message_ref_t'. */
1222 /* This will be finished in build_v2_message_ref_translation_table ().
1223    We take an idea from LLVM in making the names a bit more connected
1224    and thus the asm more readable.  */
1225 
1226 static tree
build_v2_message_reference_decl(tree sel_name,tree message_func_ident)1227 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1228 {
1229   tree decl;
1230   char buf[BUFSIZE], *t;
1231   int offset = 12;
1232 
1233   /* Skip past the objc_msgSend it's the same for all...  */
1234   if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1235     offset++;
1236 
1237   snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1238 	    &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1239 	    IDENTIFIER_POINTER (sel_name));
1240   t = buf;
1241   while (*t)
1242     {
1243       if (*t==':')
1244         *t = '$'; /* Underscore would clash between foo:bar and foo_bar.  */
1245       t++;
1246     }
1247   decl = start_var_decl (objc_v2_message_ref_template, buf);
1248   OBJCMETA (decl, objc_meta, meta_mref);
1249   return decl;
1250 }
1251 
1252 struct GTY(()) msgref_entry {
1253   tree func;
1254   tree selname;
1255   tree refdecl;
1256 };
1257 
1258 static GTY (()) vec<msgref_entry, va_gc> *msgrefs;
1259 
1260 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1261    later on to initialize the table of 'struct message_ref_t'
1262    elements.  */
1263 
1264 static tree
build_v2_selector_messenger_reference(tree sel_name,tree message_func_decl)1265 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1266 {
1267   tree decl;
1268   msgref_entry e;
1269   if (msgrefs)
1270     {
1271       int count;
1272       msgref_entry *ref;
1273       FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1274 	if (ref->func == message_func_decl && ref->selname == sel_name)
1275 	  return ref->refdecl;
1276     }
1277   else
1278     /* Somewhat arbitrary initial provision.  */
1279     vec_alloc (msgrefs, 32);
1280 
1281   /* We come here if we don't find a match or at the start.  */
1282   decl = build_v2_message_reference_decl (sel_name,
1283 					  DECL_NAME (message_func_decl));
1284   e.func = message_func_decl;
1285   e.selname = sel_name;
1286   e.refdecl = decl;
1287   vec_safe_push (msgrefs, e);
1288   return decl;
1289 }
1290 
1291 static tree
build_v2_protocollist_ref_decl(tree protocol)1292 build_v2_protocollist_ref_decl (tree protocol)
1293 {
1294   tree decl;
1295   tree protocol_ident = PROTOCOL_NAME (protocol);
1296   char buf[BUFSIZE];
1297 
1298   snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1299 	    IDENTIFIER_POINTER (protocol_ident));
1300   /* TODO: other compiler versions make these hidden & weak.  */
1301   decl = create_global_decl (objc_protocol_type, buf);
1302   /* Let optimizer know that this decl is not removable.  */
1303   DECL_PRESERVE_P (decl) = 1;
1304   OBJCMETA (decl, objc_meta, meta_proto_ref);
1305   return decl;
1306 }
1307 
1308 struct GTY(()) prot_list_entry {
1309   tree id;
1310   tree refdecl;
1311 };
1312 static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
1313 
1314 static tree
objc_v2_get_protocol_reference(tree ident)1315 objc_v2_get_protocol_reference (tree ident)
1316 {
1317   tree decl;
1318   prot_list_entry e;
1319   if (protrefs)
1320     {
1321       int count;
1322       prot_list_entry *ref;
1323       FOR_EACH_VEC_ELT (*protrefs, count, ref)
1324 	{
1325 	  if (ref->id == ident)
1326 	    {
1327 	      if (!ref->refdecl)
1328 		ref->refdecl = build_v2_protocollist_ref_decl (ident);
1329 	      return ref->refdecl;
1330 	    }
1331 	}
1332     }
1333   else
1334     /* Somewhat arbitrary initial provision.  */
1335     vec_alloc (protrefs, 32);
1336 
1337   /* We come here if we don't find the entry - or if the table was yet
1338      to be created.  */
1339   decl = build_v2_protocollist_ref_decl (ident);
1340   e.id = ident;
1341   e.refdecl = decl;
1342   vec_safe_push (protrefs, e);
1343   return decl;
1344 }
1345 
1346 static tree
next_runtime_abi_02_get_protocol_reference(location_t loc ATTRIBUTE_UNUSED,tree p)1347 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1348 					    tree p)
1349 {
1350   if (!PROTOCOL_FORWARD_DECL (p))
1351     PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1352 
1353   return objc_v2_get_protocol_reference (p);
1354 }
1355 
1356 /* This routine returns the ivar declaration, if component is a valid
1357    ivar field; NULL_TREE otherwise. On finding an ivar, it also
1358    returns the class name in CLASS.  */
1359 
1360 static tree
objc_is_ivar(tree expr,tree component,tree * klass)1361 objc_is_ivar (tree expr, tree component, tree *klass)
1362 {
1363   tree field = NULL_TREE;
1364   tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1365 
1366   if (TREE_CODE (basetype) == RECORD_TYPE
1367       && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1368     {
1369       *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1370       if (*klass)
1371 	{
1372 	  do
1373 	    {
1374 	      tree ivar_chain = CLASS_RAW_IVARS (*klass);
1375 	      if (ivar_chain)
1376 		{
1377 		  field = is_ivar (ivar_chain, component);
1378 		  if (field != NULL_TREE)
1379 		    break;
1380 	        }
1381 	      *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1382 	    }
1383 	  while (*klass);
1384 	}
1385     }
1386   return field;
1387 }
1388 
1389 static void
create_ivar_offset_name(char * buf,tree class_name,tree field_decl)1390 create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1391 {
1392   tree fname = DECL_NAME (field_decl);
1393 
1394   sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1395 	   IDENTIFIER_POINTER (fname));
1396   return;
1397 }
1398 
1399 /* This routine generates new abi's ivar reference tree.  It amounts
1400    to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1401    generate pObj->IVAR.  OFFSET_IVAR is an 'extern' variable holding
1402    the offset for 'IVAR' field.  TYPE is type of IVAR field.  */
1403 
1404 static tree
objc_v2_build_ivar_ref(tree datum,tree component)1405 objc_v2_build_ivar_ref (tree datum, tree component)
1406 {
1407   tree field, ref, class_name, offset, ftype, expr;
1408   char var_offset_name[512];
1409 
1410   field = objc_is_ivar (datum, component, &class_name);
1411   if (!field)
1412     return NULL_TREE;
1413 
1414   /* This routine only handles non-bitfield fields */
1415   if (DECL_C_BIT_FIELD (field))
1416     return NULL_TREE;
1417 
1418   create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name),  field);
1419 
1420   offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1421 
1422   ftype = TREE_TYPE (field);
1423 
1424   /* (char*)datum */
1425   expr = build_c_cast (input_location,
1426 		       string_type_node, build_fold_addr_expr (datum));
1427 
1428   /* (char*)datum + offset */
1429   expr = fold_build_pointer_plus_loc (input_location, expr, offset);
1430 
1431   /* (ftype*)((char*)datum + offset) */
1432   expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1433 
1434   /* Finally: *(ftype*)((char*)datum + offset) */
1435   ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1436 
1437   /* We must set type of the resulting expression to be the same as
1438      the field type. This is because, build_indirect_ref (...)
1439      rebuilds the type which may result in lost information; as in the
1440      case of protocol-qualified types (id <protocol> ).  */
1441   TREE_TYPE (ref) = ftype;
1442 
1443   if (TREE_READONLY (datum) || TREE_READONLY (field))
1444     TREE_READONLY (ref) = 1;
1445 
1446   if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1447     TREE_THIS_VOLATILE (ref) = 1;
1448 
1449   if (TREE_DEPRECATED (field))
1450     warn_deprecated_use (field, NULL_TREE);
1451 
1452   return ref;
1453 }
1454 
1455 /* IVAR refs are made via an externally referenceable offset and built
1456    on the fly.  That is, unless they refer to (private) fields in  the
1457    class structure.  */
1458 static tree
next_runtime_abi_02_build_ivar_ref(location_t loc ATTRIBUTE_UNUSED,tree base,tree id)1459 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1460 				   tree base, tree id)
1461 {
1462   tree ivar;
1463   if ((ivar = objc_v2_build_ivar_ref (base, id)))
1464     return ivar;
1465   return objc_build_component_ref (base, id);
1466 }
1467 
1468 /* [super ...] references are listed here (and built into a table at
1469    meta -data emit time).  */
1470 static tree
build_v2_superclass_ref_decl(tree ident,bool inst)1471 build_v2_superclass_ref_decl (tree ident, bool inst)
1472 {
1473   tree decl;
1474   char buf[BUFSIZE];
1475 
1476   snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1477 	    IDENTIFIER_POINTER (ident));
1478   decl = start_var_decl (objc_class_type, buf);
1479   OBJCMETA (decl, objc_meta, meta_superclass_ref);
1480   return decl;
1481 }
1482 
1483 static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs;
1484 static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs;
1485 
1486 /* Find or build a superclass reference decl for class NAME.  */
1487 
1488 static tree
objc_get_superclass_ref_decl(tree name,bool inst_meth)1489 objc_get_superclass_ref_decl (tree name, bool inst_meth)
1490 {
1491   tree decl;
1492   vec<ident_data_tuple, va_gc> *list = inst_meth  ? class_super_refs
1493 						: metaclass_super_refs;
1494 
1495   if (list)
1496     {
1497       int count;
1498       ident_data_tuple *ref;
1499       FOR_EACH_VEC_ELT (*list, count, ref)
1500 	{
1501 	  if (ref->ident == name)
1502 	    {
1503 	      if (!ref->data)
1504 		ref->data = build_v2_superclass_ref_decl (name, inst_meth);
1505 	      return ref->data;
1506 	    }
1507 	}
1508     }
1509   else
1510     {
1511       /* Somewhat arbitrary initial provision.  */
1512       if (inst_meth)
1513 	{
1514 	  vec_alloc (class_super_refs, 16);
1515 	  list = class_super_refs;
1516 	}
1517       else
1518 	{
1519 	  vec_alloc (metaclass_super_refs, 16);
1520 	  list = metaclass_super_refs;
1521 	}
1522     }
1523   /* We come here if we don't find the entry - or if the table was yet
1524      to be created.  */
1525   decl = build_v2_superclass_ref_decl (name, inst_meth);
1526   ident_data_tuple e;
1527   e.ident = name;
1528   e.data = decl;
1529   vec_safe_push (list, e);
1530   return decl;
1531 }
1532 
1533 /* Get a reference to the superclass for IMP.  */
1534 
1535 static tree
next_runtime_abi_02_get_class_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)1536 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1537 					 struct imp_entry *imp, bool inst_meth)
1538 {
1539   tree name = CLASS_NAME (imp->imp_context);
1540   return objc_get_superclass_ref_decl (name, inst_meth);
1541 }
1542 
1543 /* Get a reference to the superclass for category IMP.  */
1544 
1545 static tree
next_runtime_abi_02_get_category_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)1546 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1547 					    struct imp_entry *imp,
1548 					    bool inst_meth)
1549 {
1550   if (flag_zero_link)
1551     {
1552       /* Do it the slow way.  */
1553       tree get_cl_fn = inst_meth ? objc_get_class_decl
1554 				 : objc_get_meta_class_decl;
1555       tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1556       super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1557 					    IDENTIFIER_POINTER (super_name));
1558       /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1559       return build_function_call (input_location, get_cl_fn,
1560 				  build_tree_list (NULL_TREE, super_name));
1561     }
1562 
1563   /* This is the 'usual' path.  */
1564   tree cls_name = CLASS_NAME (imp->imp_template);
1565   if (!inst_meth)
1566     return objc_get_superclass_ref_decl (cls_name, inst_meth);
1567   return objc_get_class_reference (cls_name);
1568 }
1569 
1570 static tree
next_runtime_abi_02_receiver_is_class_object(tree receiver)1571 next_runtime_abi_02_receiver_is_class_object (tree receiver)
1572 {
1573   if (TREE_CODE (receiver) == VAR_DECL
1574       && IS_CLASS (TREE_TYPE (receiver))
1575       && vec_safe_length (classrefs))
1576     {
1577       int count;
1578       ident_data_tuple *ref;
1579       /* The receiver is a variable created by build_class_reference_decl.  */
1580       FOR_EACH_VEC_ELT (*classrefs, count, ref)
1581 	if (ref->data == receiver)
1582 	  return ref->ident;
1583     }
1584   return NULL_TREE;
1585 }
1586 
1587 /* Assign all arguments in VALUES which have side-effect to a temporary
1588    and replaced that argument in VALUES list with the temporary. The
1589    arguments will be passed to a function with FNTYPE.  */
1590 
1591 static tree
objc_copy_to_temp_side_effect_params(tree fntype,tree values)1592 objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1593 {
1594   tree valtail;
1595   function_args_iterator iter;
1596 
1597   /* Skip over receiver and the &_msf_ref types.  */
1598   function_args_iter_init (&iter, fntype);
1599   function_args_iter_next (&iter);
1600   function_args_iter_next (&iter);
1601 
1602   for (valtail = values; valtail;
1603        valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
1604     {
1605       tree value = TREE_VALUE (valtail);
1606       tree type = function_args_iter_cond (&iter);
1607       if (type == NULL_TREE)
1608 	break;
1609       if (!TREE_SIDE_EFFECTS (value))
1610 	continue;
1611       /* To prevent re-evaluation.  */
1612       value = save_expr (value);
1613       add_stmt (value);
1614       TREE_VALUE (valtail) = value;
1615     }
1616   return values;
1617 }
1618 
1619 /* Build the new abi's messaging library call. It looks like:
1620    (*_msg.messenger) (receiver, &_msg, ...) */
1621 
1622 static tree
build_v2_objc_method_fixup_call(int super_flag,tree method_prototype,tree lookup_object,tree selector,tree method_params,bool check_for_nil)1623 build_v2_objc_method_fixup_call (int super_flag, tree method_prototype,
1624 				tree lookup_object, tree selector,
1625 				tree method_params, bool check_for_nil)
1626 {
1627   tree ret_val;
1628   tree sender, rcv_p, t;
1629   tree ret_type
1630     = (method_prototype
1631        ? TREE_VALUE (TREE_TYPE (method_prototype))
1632        : objc_object_type);
1633   tree ftype = build_function_type_for_method (ret_type, method_prototype,
1634 					       METHOD_REF, super_flag);
1635   tree sender_cast;
1636 
1637   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1638     ftype = build_type_attribute_variant (
1639 	      ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1640 
1641   sender_cast = build_pointer_type (ftype);
1642 
1643   if (check_for_nil)
1644     method_params = objc_copy_to_temp_side_effect_params (ftype,
1645 							  method_params);
1646 
1647   /* Get &message_ref_t.messenger.  */
1648   sender = build_c_cast (input_location,
1649 			 build_pointer_type (super_flag
1650 					     ? objc_v2_super_imp_type
1651 					     : objc_v2_imp_type),
1652 			 selector);
1653 
1654   sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1655 
1656   rcv_p = (super_flag ? objc_super_type : objc_object_type);
1657 
1658   lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1659 
1660   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
1661   lookup_object = save_expr (lookup_object);
1662 
1663   method_params = tree_cons (NULL_TREE, lookup_object,
1664                              tree_cons (NULL_TREE, selector,
1665                                         method_params));
1666   t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
1667   ret_val =  build_function_call (input_location, t, method_params);
1668   if (check_for_nil)
1669     {
1670       /* receiver != nil ? ret_val : 0 */
1671       tree ftree;
1672       tree ifexp;
1673 
1674       if (TREE_CODE (ret_type) == RECORD_TYPE
1675 	  || TREE_CODE (ret_type) == UNION_TYPE)
1676 	/* An empty constructor is zero-filled by the middle end.  */
1677 	ftree = objc_build_constructor (ret_type, NULL);
1678       else
1679 	ftree = fold_convert (ret_type, integer_zero_node);
1680 
1681       ifexp = build_binary_op (input_location, NE_EXPR,
1682 			       lookup_object,
1683 			       fold_convert (rcv_p, integer_zero_node), 1);
1684 
1685 #ifdef OBJCPLUS
1686       ret_val = build_conditional_expr (input_location,
1687 					ifexp, ret_val, ftree,
1688 					tf_warning_or_error);
1689 #else
1690       ret_val = build_conditional_expr (input_location,
1691 					ifexp, 0,
1692 					ret_val, NULL_TREE, input_location,
1693 					ftree, NULL_TREE, input_location);
1694       ret_val = fold_convert (ret_type, ret_val);
1695 #endif
1696     }
1697   return ret_val;
1698 }
1699 
1700 static tree
build_v2_build_objc_method_call(int super,tree method_prototype,tree lookup_object,tree selector,tree method_params,location_t loc,bool check_for_nil,bool rx_is_id)1701 build_v2_build_objc_method_call (int super, tree method_prototype,
1702 				 tree lookup_object, tree selector,
1703 				 tree method_params, location_t loc,
1704 				 bool check_for_nil, bool rx_is_id)
1705 {
1706   tree sender, sender_cast, method, t;
1707   tree rcv_p = (super ? objc_super_type : objc_object_type);
1708   vec<tree, va_gc> *parms;
1709   unsigned nparm = (method_params ? list_length (method_params) : 0);
1710 
1711   /* If a prototype for the method to be called exists, then cast
1712      the sender's return type and arguments to match that of the method.
1713      Otherwise, leave sender as is.  */
1714   tree ret_type
1715     = (method_prototype
1716        ? TREE_VALUE (TREE_TYPE (method_prototype))
1717        : objc_object_type);
1718   tree ftype = build_function_type_for_method (ret_type, method_prototype,
1719 					       METHOD_REF, super);
1720 
1721   if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1722     ftype = build_type_attribute_variant (ftype,
1723 					  METHOD_TYPE_ATTRIBUTES
1724 					  (method_prototype));
1725 
1726   sender_cast = build_pointer_type (ftype);
1727 
1728   lookup_object = build_c_cast (loc, rcv_p, lookup_object);
1729 
1730   /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
1731   lookup_object = save_expr (lookup_object);
1732 
1733   /* Param list + 2 slots for object and selector.  */
1734   vec_alloc (parms, nparm + 2);
1735 
1736   /* If we are returning an item that must be returned in memory, and the
1737      target ABI does this by an invisible pointer provided as the first arg,
1738      we need to adjust the message signature to include this.  The second
1739      part of this excludes targets that provide some alternate scheme for
1740      structure returns.  */
1741   if (ret_type && !VOID_TYPE_P (ret_type)
1742       && targetm.calls.return_in_memory (ret_type, 0)
1743       && !(targetm.calls.struct_value_rtx (0, 0)
1744 	   && (TREE_CODE (ret_type) == RECORD_TYPE
1745 	       || TREE_CODE (ret_type) == UNION_TYPE)))
1746     {
1747       if (super)
1748 	sender = umsg_id_super2_stret_fixup_decl;
1749       else
1750 	sender = rx_is_id ? umsg_id_stret_fixup_decl
1751 			  : umsg_stret_fixup_decl;
1752     }
1753   else
1754     {
1755       if (super)
1756 	sender = umsg_id_super2_fixup_decl;
1757       else
1758 	sender = rx_is_id ? umsg_id_fixup_decl
1759 			  : umsg_fixup_decl;
1760     }
1761 
1762   method = build_fold_addr_expr_loc (loc, sender);
1763 
1764   /* Pass the object to the method.  */
1765   parms->quick_push (lookup_object);
1766   /* Pass the selector to the method.  */
1767   parms->quick_push (selector);
1768   /* Now append the remainder of the parms.  */
1769   if (nparm)
1770     for (; method_params; method_params = TREE_CHAIN (method_params))
1771       parms->quick_push (TREE_VALUE (method_params));
1772 
1773   /* Build an obj_type_ref, with the correct cast for the method call.  */
1774   t = build3 (OBJ_TYPE_REF, sender_cast, method,
1775 			    lookup_object, size_zero_node);
1776   tree ret_val = build_function_call_vec (loc, vNULL, t, parms, NULL);
1777   vec_free (parms);
1778   if (check_for_nil)
1779     {
1780       /* receiver != nil ? ret_val : 0 */
1781       tree ftree;
1782       tree ifexp;
1783 
1784       if (TREE_CODE (ret_type) == RECORD_TYPE
1785 	  || TREE_CODE (ret_type) == UNION_TYPE)
1786 	{
1787 	/* An empty constructor is zero-filled by the middle end.  */
1788 	  ftree = objc_build_constructor (ret_type, NULL);
1789 	}
1790       else
1791 	ftree = fold_convert (ret_type, integer_zero_node);
1792 
1793       ifexp = build_binary_op (loc, NE_EXPR,
1794 			       lookup_object,
1795 			       fold_convert (rcv_p, integer_zero_node), 1);
1796 
1797 #ifdef OBJCPLUS
1798       ret_val = build_conditional_expr (loc, ifexp, ret_val, ftree,
1799 					tf_warning_or_error);
1800 #else
1801       ret_val = build_conditional_expr (loc, ifexp, 1,
1802 					ret_val, NULL_TREE, loc,
1803 					ftree, NULL_TREE, loc);
1804       ret_val = fold_convert (ret_type, ret_val);
1805 #endif
1806     }
1807   return ret_val;
1808 }
1809 
1810 static tree
next_runtime_abi_02_build_objc_method_call(location_t loc,tree method_prototype,tree receiver,tree rtype,tree sel_name,tree method_params,int super)1811 next_runtime_abi_02_build_objc_method_call (location_t loc,
1812 					    tree method_prototype,
1813 					    tree receiver,
1814 					    tree rtype,
1815 					    tree sel_name,
1816 					    tree method_params,
1817 					    int super)
1818 {
1819   /* Do we need to check for nil receivers ? */
1820   /* For now, message sent to classes need no nil check.  In the
1821       future, class declaration marked as weak_import must be nil
1822       checked.  */
1823   bool check_for_nil = flag_objc_nilcheck;
1824   if (super
1825       || (TREE_CODE (receiver) == VAR_DECL
1826 	  && TREE_TYPE (receiver) == objc_class_type))
1827     check_for_nil = false;
1828 
1829   if (flag_next_runtime >= USE_FIXUP_BEFORE)
1830     {
1831       tree selector
1832 	= next_runtime_abi_02_build_selector_reference (loc, sel_name,
1833 						    method_prototype);
1834       return build_v2_build_objc_method_call (super, method_prototype,
1835 					      receiver, selector,
1836 					      method_params, loc,
1837 					      check_for_nil,
1838 					      objc_is_id (rtype));
1839     }
1840 
1841   /* else we have to build a pair of the function and selector.  */
1842   tree message_func_decl;
1843   tree  ret_type = method_prototype
1844 	     ? TREE_VALUE (TREE_TYPE (method_prototype))
1845 	     : objc_object_type;
1846 
1847   /* See comment for the fixup version above.  */
1848   if (ret_type && !VOID_TYPE_P (ret_type)
1849       && targetm.calls.return_in_memory (ret_type, 0)
1850       && !(targetm.calls.struct_value_rtx (0, 0)
1851 	   && (TREE_CODE (ret_type) == RECORD_TYPE
1852 	       || TREE_CODE (ret_type) == UNION_TYPE)))
1853     {
1854       if (super)
1855 	message_func_decl = umsg_id_super2_stret_fixup_decl;
1856       else
1857 	message_func_decl = objc_is_id (rtype)
1858 			    ? umsg_id_stret_fixup_decl
1859 			    : umsg_stret_fixup_decl;
1860     }
1861   else
1862     {
1863       if (super)
1864 	message_func_decl = umsg_id_super2_fixup_decl;
1865       else
1866 	message_func_decl = objc_is_id (rtype)
1867 			    ? umsg_id_fixup_decl
1868 			    : umsg_fixup_decl;
1869     }
1870 
1871   tree selector = build_v2_selector_messenger_reference (sel_name,
1872 						      message_func_decl);
1873 
1874   /* selector = &_msg; */
1875   selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1876 
1877   selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1878 				       : objc_v2_selector_type),
1879 			   selector);
1880 
1881   /* (*_msg.messenger) (receiver, &_msg, ...); */
1882   return build_v2_objc_method_fixup_call (super, method_prototype, receiver,
1883 					  selector, method_params,
1884 					  check_for_nil);
1885 }
1886 
1887 /* NOTE --- Constant String Class Stuff --- */
1888 
1889 static bool
next_runtime_abi_02_setup_const_string_class_decl(void)1890 next_runtime_abi_02_setup_const_string_class_decl (void)
1891 {
1892   if (!constant_string_global_id)
1893     {
1894       /* Hopefully, this should not represent a serious limitation.  */
1895       char buf[BUFSIZE];
1896       snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1897       constant_string_global_id = get_identifier (buf);
1898     }
1899 
1900   string_class_decl = lookup_name (constant_string_global_id);
1901 
1902   /* In OBJC2 abi, constant string class reference refers to class
1903      name for NSConstantString class.  This declaration may not be
1904      available yet (in fact it is not in most cases).  So, declare an
1905      extern OBJC_CLASS_$_NSConstantString in its place. */
1906   if (!string_class_decl)
1907     string_class_decl =
1908 	create_extern_decl (objc_v2_class_template,
1909 			    IDENTIFIER_POINTER (constant_string_global_id));
1910 
1911   return (string_class_decl != NULL_TREE);
1912 }
1913 
1914 static tree
next_runtime_abi_02_build_const_string_constructor(location_t loc,tree string,int length)1915 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1916 						   int length)
1917 {
1918   tree constructor, fields, var;
1919   vec<constructor_elt, va_gc> *v = NULL;
1920 
1921   /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1922   fields = TYPE_FIELDS (internal_const_str_type);
1923   CONSTRUCTOR_APPEND_ELT (v, fields,
1924 			  build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1925 
1926   fields = DECL_CHAIN (fields);
1927   CONSTRUCTOR_APPEND_ELT (v, fields,
1928 			  build_unary_op (loc, ADDR_EXPR, string, 1));
1929 
1930   /* ??? check if this should be long.  */
1931   fields = DECL_CHAIN (fields);
1932   CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1933   constructor = objc_build_constructor (internal_const_str_type, v);
1934 
1935   var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1936   DECL_INITIAL (var) = constructor;
1937   TREE_STATIC (var) = 1;
1938   DECL_CONTEXT (var) = NULL;
1939   OBJCMETA (var, objc_meta, meta_const_str);
1940   return var;
1941 }
1942 
1943 /* NOTE --- NeXT V2 Metadata templates --- */
1944 
1945 /* This routine builds the following type:
1946    struct _prop_t
1947    {
1948      const char * const name;			// property name
1949      const char * const attributes;		// comma-delimited, encoded,
1950 						// property attributes
1951    };
1952 */
1953 
1954 static tree
build_v2_property_template(void)1955 build_v2_property_template (void)
1956 {
1957   tree prop_record;
1958   tree decls, *chain = NULL;
1959 
1960   prop_record = objc_start_struct (get_identifier ("_prop_t"));
1961   /* const char * name */
1962   decls = add_field_decl (string_type_node, "name", &chain);
1963 
1964   /* const char * attribute */
1965   add_field_decl (string_type_node, "attribute", &chain);
1966 
1967   objc_finish_struct (prop_record, decls);
1968   return prop_record;
1969 }
1970 
1971 /* struct ivar_t
1972    {
1973      unsigned long int *offset;
1974      char *name;
1975      char *type;
1976      uint32_t alignment;
1977      uint32_t size;
1978    };
1979 */
1980 
1981 static tree
build_v2_ivar_t_template(void)1982 build_v2_ivar_t_template (void)
1983 {
1984   tree objc_ivar_id, objc_ivar_record;
1985   tree decls, *chain = NULL;
1986 
1987   objc_ivar_id = get_identifier ("_ivar_t");
1988   objc_ivar_record = objc_start_struct (objc_ivar_id);
1989 
1990   /* unsigned long int *offset; */
1991   decls = add_field_decl (build_pointer_type
1992 			   (TREE_TYPE (size_zero_node)), "offset", &chain);
1993 
1994   /* char *name; */
1995   add_field_decl (string_type_node, "name", &chain);
1996 
1997   /* char *type; */
1998   add_field_decl (string_type_node, "type", &chain);
1999 
2000   /* uint32_t alignment; */
2001   add_field_decl (integer_type_node, "alignment", &chain);
2002 
2003   /* uint32_t size; */
2004   add_field_decl (integer_type_node, "size", &chain);
2005 
2006   objc_finish_struct (objc_ivar_record, decls);
2007   return objc_ivar_record;
2008 }
2009 
2010 static void
build_metadata_templates(void)2011 build_metadata_templates (void)
2012 {
2013 
2014   if (!objc_method_template)
2015     objc_method_template = build_method_template ();
2016 
2017   if (!objc_v2_property_template)
2018     objc_v2_property_template = build_v2_property_template ();
2019 
2020   if (!objc_v2_ivar_template)
2021     objc_v2_ivar_template = build_v2_ivar_t_template ();
2022 
2023 }
2024 
2025 /* NOTE --- Output NeXT V2 Metadata --- */
2026 
2027 /* Routine builds name of Interface's main meta-data of type class_t. */
2028 
2029 static char *
objc_build_internal_classname(tree ident,bool metaclass)2030 objc_build_internal_classname (tree ident, bool metaclass)
2031 {
2032   static char string[512];
2033   snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
2034 					    : "OBJC_CLASS_$",
2035 	    IDENTIFIER_POINTER (ident));
2036   return string;
2037 }
2038 
2039 /* Build the name for object of type struct class_ro_t */
2040 
2041 static const char *
newabi_append_ro(const char * name)2042 newabi_append_ro (const char *name)
2043 {
2044   const char *dollar;
2045   char *p;
2046   static char string[BUFSIZE];
2047   dollar = strchr (name, '$');
2048   gcc_assert (dollar);
2049   p = string;
2050   *p = '_'; p++;
2051   strncpy (p, name, (int)(dollar - name));
2052   p += (int)(dollar - name);
2053   sprintf (p, "RO_%s", dollar);
2054   return string;
2055 }
2056 
2057 /* Build the struct message_ref_t msg =
2058 	       {objc_msgSend_fixup_xxx, @selector(func)}
2059    table.  */
2060 
2061 static
build_v2_message_ref_translation_table(void)2062 void build_v2_message_ref_translation_table (void)
2063 {
2064   int count;
2065   msgref_entry *ref;
2066 
2067   if (!vec_safe_length (msgrefs))
2068     return;
2069 
2070   FOR_EACH_VEC_ELT (*msgrefs, count, ref)
2071     {
2072       vec<constructor_elt, va_gc> *initializer;
2073       tree expr, constructor;
2074       tree struct_type = TREE_TYPE (ref->refdecl);
2075       location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
2076 
2077       initializer = NULL;
2078       /* First 'IMP messenger' field...  */
2079       expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
2080       expr = convert (objc_v2_imp_type, expr);
2081       CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2082 
2083       /* ... then 'SEL name' field.  */
2084       expr = build_selector (ref->selname);
2085       CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2086       constructor = objc_build_constructor (struct_type, initializer);
2087       finish_var_decl (ref->refdecl, constructor);
2088     }
2089 }
2090 
2091 /* Build decl = initializer; for each externally visible class
2092    reference.  */
2093 
2094 static void
build_v2_classrefs_table(void)2095 build_v2_classrefs_table (void)
2096 {
2097   int count;
2098   ident_data_tuple *ref;
2099 
2100   if (!vec_safe_length (classrefs))
2101     return;
2102 
2103   FOR_EACH_VEC_ELT (*classrefs, count, ref)
2104     {
2105       tree expr = ref->ident;
2106       tree decl = ref->data;
2107       /* Interface with no implementation and yet one of its messages
2108 	 has been used. Need to generate a full address-of tree for it
2109 	 here.  */
2110       if (TREE_CODE (expr) == IDENTIFIER_NODE)
2111         {
2112           const char *name = objc_build_internal_classname (expr, false);
2113           expr = create_extern_decl (objc_v2_class_template, name);
2114 	  expr = convert (objc_class_type, build_fold_addr_expr (expr));
2115 	}
2116       /* The runtime wants this, even if it appears unused, so we must force the
2117 	 output.  */
2118       DECL_PRESERVE_P (decl) = 1;
2119       finish_var_decl (decl, expr);
2120     }
2121 }
2122 
2123 /* Build decl = initializer; for each externally visible super class
2124    reference.  */
2125 
2126 static void
build_v2_super_classrefs_table(bool metaclass)2127 build_v2_super_classrefs_table (bool metaclass)
2128 {
2129   int count;
2130   ident_data_tuple *ref;
2131   vec<ident_data_tuple, va_gc> *list = metaclass  ? metaclass_super_refs
2132 						: class_super_refs;
2133 
2134   if (!vec_safe_length (list))
2135     return;
2136 
2137   FOR_EACH_VEC_ELT (*list, count, ref)
2138     {
2139       tree expr = ref->ident;
2140       tree decl = ref->data;
2141       /* Interface with no implementation and yet one of its messages
2142 	 has been used. Need to generate a full address-of tree for it
2143 	 here.  */
2144       if (TREE_CODE (expr) == IDENTIFIER_NODE)
2145 	{
2146 	  const char * name = objc_build_internal_classname (expr, metaclass);
2147           expr = create_extern_decl (objc_v2_class_template, name);
2148 	  expr = convert (objc_class_type, build_fold_addr_expr (expr));
2149 	}
2150       finish_var_decl (decl, expr);
2151     }
2152 }
2153 
2154 /* Add the global class meta-data declaration to the list which later
2155    on ends up in the __class_list section.  */
2156 
2157 static GTY(()) vec<tree, va_gc> *class_list;
2158 
2159 static void
objc_v2_add_to_class_list(tree global_class_decl)2160 objc_v2_add_to_class_list (tree global_class_decl)
2161 {
2162   vec_safe_push (class_list, global_class_decl);
2163 }
2164 
2165 static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
2166 
2167 /* Add the global class meta-data declaration to the list which later
2168    on ends up in the __nonlazy_class section.  */
2169 
2170 static void
objc_v2_add_to_nonlazy_class_list(tree global_class_decl)2171 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2172 {
2173   vec_safe_push (nonlazy_class_list, global_class_decl);
2174 }
2175 
2176 static GTY(()) vec<tree, va_gc> *category_list;
2177 
2178 /* Add the category meta-data declaration to the list which later on
2179    ends up in the __nonlazy_category section.  */
2180 
2181 static void
objc_v2_add_to_category_list(tree decl)2182 objc_v2_add_to_category_list (tree decl)
2183 {
2184   vec_safe_push (category_list, decl);
2185 }
2186 
2187 static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
2188 
2189 /* Add the category meta-data declaration to the list which later on
2190    ends up in the __category_list section.  */
2191 
2192 static void
objc_v2_add_to_nonlazy_category_list(tree decl)2193 objc_v2_add_to_nonlazy_category_list (tree decl)
2194 {
2195   vec_safe_push (nonlazy_category_list, decl);
2196 }
2197 
2198 static bool
has_load_impl(tree clsmeth)2199 has_load_impl (tree clsmeth)
2200 {
2201   while (clsmeth)
2202     {
2203       tree id = METHOD_SEL_NAME (clsmeth);
2204       if (IDENTIFIER_LENGTH (id) == 4
2205 	  && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
2206         return true;
2207       clsmeth = DECL_CHAIN (clsmeth);
2208     }
2209 
2210   return false;
2211 }
2212 
2213 /* Build a __{class,category}_list section table containing address of
2214    all @implemented {class,category} meta-data.  */
2215 
2216 static void
build_v2_address_table(vec<tree,va_gc> * src,const char * nam,tree attr)2217 build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
2218 {
2219   int count=0;
2220   tree type, decl, expr;
2221   vec<constructor_elt, va_gc> *initlist = NULL;
2222 
2223   if (!vec_safe_length (src))
2224     return;
2225 
2226   FOR_EACH_VEC_ELT (*src, count, decl)
2227     {
2228 #ifndef OBJCPLUS
2229       tree purpose = build_int_cst (NULL_TREE, count);
2230 #else
2231       tree purpose = NULL_TREE;
2232 #endif
2233       expr = convert (objc_class_type, build_fold_addr_expr (decl));
2234       CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2235     }
2236   gcc_assert (count > 0);
2237   type = build_array_type (objc_class_type,
2238 			   build_index_type (build_int_cst (NULL_TREE, count - 1)));
2239   decl = start_var_decl (type, nam);
2240   /* The runtime wants this, even if it appears unused, so we must
2241      force the output.  */
2242   DECL_PRESERVE_P (decl) = 1;
2243   expr = objc_build_constructor (type, initlist);
2244   OBJCMETA (decl, objc_meta, attr);
2245   finish_var_decl (decl, expr);
2246 }
2247 
2248 /* Build decl = initializer; for each protocol referenced in
2249    @protocol(MyProt) expression.  Refs as built in the entry section
2250    above.  */
2251 
2252 static void
build_v2_protocol_list_translation_table(void)2253 build_v2_protocol_list_translation_table (void)
2254 {
2255   int count;
2256   prot_list_entry *ref;
2257 
2258   if (!protrefs)
2259     return;
2260 
2261   FOR_EACH_VEC_ELT (*protrefs, count, ref)
2262     {
2263       char buf[BUFSIZE];
2264       tree expr;
2265       gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2266       snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2267 		IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2268       expr = start_var_decl (objc_v2_protocol_template, buf);
2269       expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2270       finish_var_decl (ref->refdecl, expr);
2271     }
2272   /* TODO: Maybe we could explicitly delete the vec. now?  */
2273 }
2274 
2275 static GTY (()) vec<prot_list_entry, va_gc> *protlist;
2276 
2277 /* Add the local protocol meta-data declaration to the list which
2278    later on ends up in the __protocol_list section.  */
2279 
2280 static void
objc_add_to_protocol_list(tree protocol_interface_decl,tree protocol_decl)2281 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2282 {
2283   prot_list_entry e;
2284   if (!protlist)
2285     /* Arbitrary init count.  */
2286     vec_alloc (protlist, 32);
2287   e.id = protocol_interface_decl;
2288   e.refdecl = protocol_decl;
2289   vec_safe_push (protlist, e);
2290 }
2291 
2292 /* Build the __protocol_list section table containing address of all
2293    generate protocol_t meta-data.  */
2294 
2295 static void
build_v2_protocol_list_address_table(void)2296 build_v2_protocol_list_address_table (void)
2297 {
2298   int count;
2299   prot_list_entry *ref;
2300   if (!vec_safe_length (protlist))
2301     return;
2302 
2303   FOR_EACH_VEC_ELT (*protlist, count, ref)
2304     {
2305       tree decl, expr;
2306       char buf[BUFSIZE];
2307       gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2308       snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2309 		IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2310       if (flag_next_runtime >= USE_FIXUP_BEFORE)
2311 	{
2312 	  decl = create_hidden_decl (objc_protocol_type, buf, /*is def=*/true);
2313 	  DECL_WEAK (decl) = true;
2314 	}
2315       else
2316 	decl = create_global_decl (objc_protocol_type, buf, /*is def=*/true);
2317       expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2318       OBJCMETA (decl, objc_meta, meta_label_protocollist);
2319       finish_var_decl (decl, expr);
2320       DECL_PRESERVE_P (decl) = 1;
2321     }
2322 
2323     /* TODO: delete the vec.  */
2324     /* TODO: upgrade to the clang/llvm hidden version.  */
2325 }
2326 
2327 /* This routine declares a variable to hold meta data for 'struct
2328    protocol_list_t'.  */
2329 
2330 static tree
generate_v2_protocol_list(tree i_or_p,tree klass_ctxt)2331 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2332 {
2333   tree refs_decl, lproto, e, plist, ptempl_p_t;
2334   int size = 0;
2335   vec<constructor_elt, va_gc> *initlist = NULL;
2336   char buf[BUFSIZE];
2337 
2338   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2339       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2340     plist = CLASS_PROTOCOL_LIST (i_or_p);
2341   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2342     plist = PROTOCOL_LIST (i_or_p);
2343   else
2344     gcc_unreachable ();
2345 
2346   /* Compute size.  */
2347   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2348     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2349 	&& PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2350       size++;
2351 
2352   /* Build initializer.  */
2353 
2354   ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2355   e = build_int_cst (ptempl_p_t, size);
2356   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2357 
2358   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2359     {
2360       tree pval = TREE_VALUE (lproto);
2361 
2362       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2363 	  && PROTOCOL_FORWARD_DECL (pval))
2364 	{
2365 	  tree fwref = PROTOCOL_FORWARD_DECL (pval);
2366 	  location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2367 	  e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2368 	  CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2369 	}
2370     }
2371 
2372   /* static struct protocol_list_t *list[size]; */
2373 
2374   switch (TREE_CODE (i_or_p))
2375     {
2376     case PROTOCOL_INTERFACE_TYPE:
2377       snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2378 		IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2379       break;
2380     case CLASS_INTERFACE_TYPE:
2381       snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2382 		IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2383       break;
2384     case CATEGORY_INTERFACE_TYPE:
2385       snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2386 		IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2387 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2388       break;
2389       default:
2390 	gcc_unreachable ();
2391     }
2392 
2393   refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2394 			      buf);
2395   /* ObjC2 puts all these in the base section.  */
2396   OBJCMETA (refs_decl, objc_meta, meta_base);
2397   DECL_PRESERVE_P (refs_decl) = 1;
2398   finish_var_decl (refs_decl,
2399 		   objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2400   return refs_decl;
2401 }
2402 
2403 /* This routine builds one 'struct method_t' initializer list. Note
2404    that the old ABI is supposed to build 'struct objc_method' which
2405    has 3 fields, but it does not build the initialization expression
2406    for 'method_imp' which for protocols is NULL any way.  To be
2407    consistent with declaration of 'struct method_t', in the new ABI we
2408    set the method_t.imp to NULL.  */
2409 
2410 static tree
build_v2_descriptor_table_initializer(tree type,tree entries)2411 build_v2_descriptor_table_initializer (tree type, tree entries)
2412 {
2413   vec<constructor_elt, va_gc> *initlist = NULL;
2414   do
2415     {
2416       vec<constructor_elt, va_gc> *eltlist = NULL;
2417       CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2418 			      build_selector (METHOD_SEL_NAME (entries)));
2419       CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2420 			      add_objc_string (METHOD_ENCODING (entries),
2421 						meth_var_types));
2422       CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2423 
2424       CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2425 			      objc_build_constructor (type, eltlist));
2426       entries = TREE_CHAIN (entries);
2427     }
2428   while (entries);
2429 
2430   return objc_build_constructor (build_array_type (type, 0), initlist);
2431 }
2432 
2433 /* struct method_list_t
2434   {
2435      uint32_t entsize;
2436      uint32_t method_count;
2437      struct objc_method method_list[method_count];
2438    }; */
2439 
2440 static tree
build_v2_method_list_template(tree list_type,int size)2441 build_v2_method_list_template (tree list_type, int size)
2442 {
2443   tree method_list_t_record;
2444   tree array_type, decls, *chain = NULL;
2445 
2446   method_list_t_record = objc_start_struct (NULL_TREE);
2447 
2448   /* uint32_t const entsize; */
2449   decls = add_field_decl (integer_type_node, "entsize", &chain);
2450 
2451   /* int method_count; */
2452   add_field_decl (integer_type_node, "method_count", &chain);
2453 
2454   /* struct objc_method method_list[]; */
2455   array_type = build_sized_array_type (list_type, size);
2456   add_field_decl (array_type, "method_list", &chain);
2457 
2458   objc_finish_struct (method_list_t_record, decls);
2459   return method_list_t_record;
2460 }
2461 
2462 /* Note, as above that we are building to the objc_method_template
2463    which has the *imp field.  ABI0/1 build with
2464    objc_method_prototype_template which is missing this field.  */
2465 static tree
generate_v2_meth_descriptor_table(tree chain,tree protocol,const char * prefix,tree attr,vec<tree> & all_meths)2466 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2467 				   const char *prefix, tree attr,
2468 				   vec<tree>& all_meths)
2469 {
2470   tree method_list_template, initlist, decl;
2471   int size, entsize;
2472   vec<constructor_elt, va_gc> *v = NULL;
2473   char buf[BUFSIZE];
2474 
2475   if (!chain || !prefix)
2476     return NULL_TREE;
2477 
2478   tree method = chain;
2479   size = 0;
2480   while (method)
2481     {
2482       if (! METHOD_ENCODING (method))
2483 	METHOD_ENCODING (method) = encode_method_prototype (method);
2484       all_meths.safe_push (method);
2485       method = TREE_CHAIN (method);
2486       size++;
2487     }
2488 
2489   gcc_assert (size);
2490   method_list_template = build_v2_method_list_template (objc_method_template,
2491 							size);
2492   snprintf (buf, BUFSIZE, "%s_%s", prefix,
2493 	    IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2494 
2495   decl = start_var_decl (method_list_template, buf);
2496 
2497   entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2498   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2499   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2500   initlist =
2501 	build_v2_descriptor_table_initializer (objc_method_template,
2502 					    chain);
2503   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2504   /* Get into the right section.  */
2505   OBJCMETA (decl, objc_meta, attr);
2506   finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2507   return decl;
2508 }
2509 
2510 static tree
generate_v2_meth_type_list(vec<tree> & all_meths,tree protocol,const char * prefix)2511 generate_v2_meth_type_list (vec<tree>& all_meths, tree protocol,
2512 			    const char *prefix)
2513 {
2514   if (all_meths.is_empty () || !prefix)
2515     return NULL_TREE;
2516 
2517   unsigned size = all_meths.length ();
2518   tree list_type = build_sized_array_type (string_type_node, size);
2519   char *nam;
2520   asprintf (&nam, "%s_%s", prefix,
2521 	    IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2522   tree decl = start_var_decl (list_type, nam);
2523   free (nam);
2524   OBJCMETA (decl, objc_meta, meta_base);
2525   vec<constructor_elt, va_gc> *v = NULL;
2526 
2527   for (unsigned i = 0; i < size; ++i)
2528     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2529 			    add_objc_string (METHOD_ENCODING (all_meths[i]),
2530 					     meth_var_types));
2531   finish_var_decl (decl, objc_build_constructor (list_type, v));
2532   return decl;
2533 }
2534 
2535 /* This routine builds the initializer list to initialize the 'struct
2536    _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data.  */
2537 
2538 static tree
build_v2_property_table_initializer(tree type,tree context)2539 build_v2_property_table_initializer (tree type, tree context)
2540 {
2541   tree x;
2542   vec<constructor_elt, va_gc> *inits = NULL;
2543   if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2544     x = CLASS_PROPERTY_DECL (context);
2545   else
2546     x = IMPL_PROPERTY_DECL (context);
2547 
2548   for (; x; x = TREE_CHAIN (x))
2549     {
2550       vec<constructor_elt, va_gc> *elemlist = NULL;
2551       /* NOTE! sections where property name/attribute go MUST change
2552 	 later.  */
2553       tree attribute, name_ident = PROPERTY_NAME (x);
2554 
2555       CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2556 			      add_objc_string (name_ident, prop_names_attr));
2557 
2558       attribute = objc_v2_encode_prop_attr (x);
2559       CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2560 			      add_objc_string (attribute, prop_names_attr));
2561 
2562       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2563 			      objc_build_constructor (type, elemlist));
2564     }
2565 
2566   return objc_build_constructor (build_array_type (type, 0),inits);
2567 }
2568 
2569 /* This routine builds the following type:
2570    struct _prop_list_t
2571    {
2572      uint32_t entsize;			// sizeof (struct _prop_t)
2573      uint32_t prop_count;
2574      struct _prop_t prop_list [prop_count];
2575    }
2576 */
2577 
2578 static tree
build_v2_property_list_template(tree list_type,int size)2579 build_v2_property_list_template (tree list_type, int size)
2580 {
2581   tree property_list_t_record;
2582   tree array_type, decls, *chain = NULL;
2583 
2584   /* anonymous.  */
2585   property_list_t_record = objc_start_struct (NULL_TREE);
2586 
2587   /* uint32_t const entsize; */
2588   decls = add_field_decl (integer_type_node, "entsize", &chain);
2589 
2590   /* int prop_count; */
2591   add_field_decl (integer_type_node, "prop_count", &chain);
2592 
2593   /* struct _prop_t prop_list[]; */
2594   array_type = build_sized_array_type (list_type, size);
2595   add_field_decl (array_type, "prop_list", &chain);
2596 
2597   objc_finish_struct (property_list_t_record, decls);
2598   return property_list_t_record;
2599 }
2600 
2601 /* Top-level routine to generate property tables for each
2602    implementation.  */
2603 
2604 static tree
generate_v2_property_table(tree context,tree klass_ctxt)2605 generate_v2_property_table (tree context, tree klass_ctxt)
2606 {
2607   tree x, decl, initlist, property_list_template;
2608   bool is_proto = false;
2609   vec<constructor_elt, va_gc> *inits = NULL;
2610   int init_val, size = 0;
2611   char buf[BUFSIZE];
2612 
2613   if (context)
2614     {
2615       gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2616       x = CLASS_PROPERTY_DECL (context);
2617       is_proto = true;
2618     }
2619   else
2620     x = IMPL_PROPERTY_DECL (klass_ctxt);
2621 
2622   for (; x; x = TREE_CHAIN (x))
2623     size++;
2624 
2625   if (size == 0)
2626     return NULL_TREE;
2627 
2628   property_list_template =
2629 	build_v2_property_list_template (objc_v2_property_template,
2630 					 size);
2631 
2632   initlist = build_v2_property_table_initializer (objc_v2_property_template,
2633 						  is_proto ? context
2634 							   : klass_ctxt);
2635 
2636   init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2637   if (is_proto)
2638     snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2639 	      IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2640   else
2641     snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2642 	      IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2643 
2644   decl = start_var_decl (property_list_template, buf);
2645 
2646   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2647 			  build_int_cst (NULL_TREE, init_val));
2648   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2649 			  build_int_cst (NULL_TREE, size));
2650   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2651 
2652   OBJCMETA (decl, objc_meta, meta_base);
2653   finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2654   return decl;
2655 }
2656 
2657 static tree
build_v2_protocol_initializer(tree type,tree protocol_name,tree protocol_list,tree inst_methods,tree class_methods,tree opt_ins_meth,tree opt_cls_meth,tree property_list,tree ext_meth_types,tree demangled_name,tree class_prop_list)2658 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2659 			      tree inst_methods, tree class_methods,
2660 			      tree opt_ins_meth, tree opt_cls_meth,
2661 			      tree property_list, tree ext_meth_types,
2662 			      tree demangled_name, tree class_prop_list)
2663 {
2664   tree expr, ttyp;
2665   location_t loc;
2666   vec<constructor_elt, va_gc> *inits = NULL;
2667 
2668   /* TODO: find a better representation of location from the inputs.  */
2669   loc = UNKNOWN_LOCATION;
2670 
2671   /*  This is NULL for the new ABI.  */
2672   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2673 			      convert (objc_object_type, null_pointer_node));
2674 
2675   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2676   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2677 
2678   ttyp = objc_method_proto_list_ptr;
2679   if (inst_methods)
2680     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2681   else
2682     expr = convert (ttyp, null_pointer_node);
2683   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2684 
2685   if (class_methods)
2686     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2687   else
2688     expr = convert (ttyp, null_pointer_node);
2689   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2690 
2691   if (opt_ins_meth)
2692     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2693   else
2694     expr = convert (ttyp, null_pointer_node);
2695   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2696 
2697   if (opt_cls_meth)
2698     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2699   else
2700     expr = convert (ttyp, null_pointer_node);
2701   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2702 
2703   ttyp = objc_prop_list_ptr;
2704   if (property_list)
2705     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2706   else
2707     expr = convert (ttyp, null_pointer_node);
2708   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2709 
2710   /* const uint32_t size;  = sizeof(struct protocol_t) */
2711   expr = build_int_cst (integer_type_node,
2712 	      TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2713   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2714   /* const uint32_t flags; = 0 */
2715   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2716 
2717   ttyp = build_pointer_type (string_type_node);
2718   if (ext_meth_types)
2719     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, ext_meth_types, 0));
2720   else
2721     expr = convert (ttyp, null_pointer_node);
2722   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2723 
2724   ttyp = string_type_node;
2725    if (demangled_name)
2726     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, demangled_name, 0));
2727   else
2728     expr = convert (ttyp, null_pointer_node);
2729   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2730 
2731   ttyp = objc_prop_list_ptr;
2732    if (class_prop_list)
2733     expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_prop_list, 0));
2734   else
2735     expr = convert (ttyp, null_pointer_node);
2736   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2737 
2738  return objc_build_constructor (type, inits);
2739 }
2740 
2741 /* Main routine to build all meta data for all protocols used in a
2742    translation unit.  */
2743 
2744 static void
generate_v2_protocols(void)2745 generate_v2_protocols (void)
2746 {
2747   tree p ;
2748   bool some = false;
2749 
2750   if (!protocol_chain)
2751     return ;
2752 
2753   /* If a protocol was directly referenced, pull in indirect
2754      references.  */
2755   for (p = protocol_chain; p; p = TREE_CHAIN (p))
2756     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2757       generate_protocol_references (PROTOCOL_LIST (p));
2758 
2759   for (p = protocol_chain; p; p = TREE_CHAIN (p))
2760     {
2761       location_t loc;
2762       tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2763       tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2764 
2765       /* If protocol wasn't referenced, don't generate any code.  */
2766       decl = PROTOCOL_FORWARD_DECL (p);
2767 
2768       if (!decl)
2769 	continue;
2770 
2771       loc = DECL_SOURCE_LOCATION (decl);
2772       some = true;
2773 
2774       vec<tree> all_meths = vNULL;
2775       inst_meth =
2776 	generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2777 					   "_OBJC_ProtocolInstanceMethods",
2778 					   meta_proto_nst_meth, all_meths);
2779 
2780       class_meth =
2781 	generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2782 					   "_OBJC_ProtocolClassMethods",
2783 					   meta_proto_cls_meth, all_meths);
2784 
2785       opt_inst_meth =
2786 	generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2787 					   "_OBJC_ProtocolOptInstMethods",
2788 					   meta_proto_nst_meth, all_meths);
2789 
2790       opt_class_meth =
2791 	generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2792 					   "_OBJC_ProtocolOptClassMethods",
2793 					   meta_proto_cls_meth, all_meths);
2794 
2795       if (PROTOCOL_LIST (p))
2796 	refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2797       else
2798 	refs_decl = 0;
2799 
2800       /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2801       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2802 
2803       if (refs_decl)
2804 	refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2805 			     build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2806       else
2807 	refs_expr = build_int_cst (NULL_TREE, 0);
2808 
2809       props = generate_v2_property_table (p, NULL_TREE);
2810 
2811       tree ext_meth_types
2812 	= generate_v2_meth_type_list (all_meths, p,
2813 				      "_OBJC_ProtocolMethodTypes");
2814       tree demangled_name = NULL_TREE;
2815       tree class_prop_list = NULL_TREE;
2816 
2817       initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2818 						protocol_name_expr, refs_expr,
2819 						inst_meth, class_meth,
2820 						opt_inst_meth, opt_class_meth,
2821 						props, ext_meth_types,
2822 						demangled_name,class_prop_list);
2823       finish_var_decl (decl, initlist);
2824       objc_add_to_protocol_list (p, decl);
2825       all_meths.truncate (0);
2826     }
2827 
2828   if (some)
2829     {
2830       /* Make sure we get the Protocol class linked in - reference
2831 	 it...  */
2832       p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2833       /* ... but since we don't specifically use the reference...  we
2834          need to force it.  */
2835       DECL_PRESERVE_P (p) = 1;
2836     }
2837 }
2838 
2839 static tree
generate_v2_dispatch_table(tree chain,const char * name,tree attr)2840 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2841 {
2842   tree decl, method_list_template, initlist;
2843   vec<constructor_elt, va_gc> *v = NULL;
2844   int size, init_val;
2845 
2846   if (!chain || !name || !(size = list_length (chain)))
2847     return NULL_TREE;
2848 
2849   method_list_template
2850 	= build_v2_method_list_template (objc_method_template, size);
2851   initlist
2852 	= build_dispatch_table_initializer (objc_method_template, chain);
2853 
2854   decl = start_var_decl  (method_list_template, name);
2855 
2856   init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2857   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2858 			  build_int_cst (integer_type_node, init_val));
2859   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2860 			  build_int_cst (integer_type_node, size));
2861   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2862 
2863   OBJCMETA (decl, objc_meta, attr);
2864   finish_var_decl (decl,
2865 		   objc_build_constructor (TREE_TYPE (decl), v));
2866   return decl;
2867 }
2868 
2869 /* Init a category.  */
2870 static tree
build_v2_category_initializer(tree type,tree cat_name,tree class_name,tree inst_methods,tree class_methods,tree protocol_list,tree property_list,location_t loc)2871 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2872 				tree inst_methods, tree class_methods,
2873 				tree protocol_list, tree property_list,
2874 				location_t loc)
2875 {
2876   tree expr, ltyp;
2877   vec<constructor_elt, va_gc> *v = NULL;
2878 
2879   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2880   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2881 
2882   ltyp = objc_method_list_ptr;
2883   if (inst_methods)
2884     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2885   else
2886     expr = convert (ltyp, null_pointer_node);
2887   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2888 
2889   if (class_methods)
2890     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2891   else
2892     expr = convert (ltyp, null_pointer_node);
2893   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2894 
2895   /* protocol_list = */
2896   ltyp = build_pointer_type (objc_v2_protocol_template);
2897   if (protocol_list)
2898     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2899   else
2900     expr = convert (ltyp, null_pointer_node);
2901   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2902 
2903   ltyp = objc_prop_list_ptr;
2904   if (property_list)
2905     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2906   else
2907     expr = convert (ltyp, null_pointer_node);
2908   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2909 
2910   return objc_build_constructor (type, v);
2911 }
2912 
2913 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2914 
2915 static void
generate_v2_category(struct imp_entry * impent)2916 generate_v2_category (struct imp_entry *impent)
2917 {
2918   tree initlist, cat_name_expr, class_name_expr;
2919   tree protocol_decl, category, props, t;
2920   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2921   tree cat = impent->imp_context;
2922   tree cat_decl = impent->class_decl;
2923   location_t loc;
2924   char buf[BUFSIZE];
2925 
2926   loc = DECL_SOURCE_LOCATION (cat_decl);
2927 
2928   /* ??? not sure this is really necessary, the following references should
2929      force appropriate linkage linkage...
2930      -- but ... ensure a reference to the class...  */
2931   t = objc_v2_get_class_reference (CLASS_NAME (cat));
2932   /* ... which we ignore so force it out.. */
2933   DECL_PRESERVE_P (t) = 1;
2934 
2935   snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2936   class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2937   class_name_expr = build_fold_addr_expr (class_name_expr);
2938 
2939   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2940   category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2941 
2942   if (category && CLASS_PROTOCOL_LIST (category))
2943     {
2944       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2945       protocol_decl = generate_v2_protocol_list (category, cat);
2946     }
2947   else
2948     protocol_decl = NULL_TREE;
2949 
2950 /* decl = update_var_decl(impent->class_decl); */
2951 
2952   props = generate_v2_property_table (NULL_TREE, cat);
2953 
2954   if (CLASS_NST_METHODS (cat))
2955     {
2956       snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2957 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
2958 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2959       inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2960 						 meta_cati_meth);
2961     }
2962 
2963   if (CLASS_CLS_METHODS (cat))
2964     {
2965       snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2966 		IDENTIFIER_POINTER (CLASS_NAME (cat)),
2967 		IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2968       class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2969 						  meta_catc_meth);
2970     }
2971 
2972   initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2973 					    cat_name_expr, class_name_expr,
2974 					    inst_methods, class_methods,
2975 					    protocol_decl, props, loc);
2976 
2977   finish_var_decl (cat_decl, initlist);
2978   impent->class_decl = cat_decl;
2979 
2980   /* Add to list of pointers in __category_list section.  */
2981   objc_v2_add_to_category_list (cat_decl);
2982   if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2983     objc_v2_add_to_nonlazy_category_list (cat_decl);
2984 }
2985 
2986 /* This routine declares a variable to hold the offset for ivar
2987    FIELD_DECL.  Variable name is .objc_ivar.ClassName.IvarName.  */
2988 
2989 struct GTY(()) ivarref_entry
2990 {
2991   tree decl;
2992   tree offset;
2993 };
2994 
2995 static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
2996 
2997 static tree
ivar_offset_ref(tree class_name,tree field_decl)2998 ivar_offset_ref (tree class_name, tree field_decl)
2999 {
3000   tree decl, field_decl_id;
3001   ivarref_entry e;
3002   bool global_var;
3003   char buf[512];
3004 
3005   create_ivar_offset_name (buf, class_name, field_decl);
3006   field_decl_id = get_identifier (buf);
3007 
3008   if (ivar_offset_refs)
3009     {
3010       int count;
3011       ivarref_entry *ref;
3012       FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3013 	if (DECL_NAME (ref->decl) == field_decl_id)
3014 	  return ref->decl;
3015     }
3016   else
3017     /* Somewhat arbitrary initial provision.  */
3018     vec_alloc (ivar_offset_refs, 32);
3019 
3020   /* We come here if we don't find a match or at the start.  */
3021   global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
3022   if (global_var)
3023     decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
3024   else
3025     decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
3026 
3027   /* Identify so that we can indirect these where the ABI requires.  */
3028   OBJCMETA (decl, objc_meta, meta_ivar_ref);
3029 
3030   e.decl = decl;
3031   e.offset = byte_position (field_decl);
3032   vec_safe_push (ivar_offset_refs, e);
3033   return decl;
3034 }
3035 
3036 /* This routine builds initializer-list needed to initialize 'struct
3037    ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
3038    'struct ivar_t' and FIELD_DECL is list of ivars for the target
3039    class.  */
3040 
3041 static tree
build_v2_ivar_list_initializer(tree class_name,tree type,tree field_decl)3042 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
3043 {
3044   vec<constructor_elt, va_gc> *inits = NULL;
3045 
3046   do
3047     {
3048       vec<constructor_elt, va_gc> *ivar = NULL;
3049       int val;
3050       tree id;
3051 
3052       /* Unnamed bitfields are ignored.  */
3053       if (!DECL_NAME (field_decl))
3054 	{
3055 	  field_decl = DECL_CHAIN (field_decl);
3056 	  continue;
3057 	}
3058 
3059       /* Set offset.  */
3060       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3061 			      build_unary_op (input_location,
3062 					      ADDR_EXPR,
3063 					      ivar_offset_ref (class_name,
3064 							       field_decl), 0));
3065 
3066       /* Set name.  */
3067       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3068 			      add_objc_string (DECL_NAME (field_decl),
3069 						meth_var_names));
3070 
3071       /* Set type.  */
3072       id = add_objc_string (encode_field_decl (field_decl),
3073                             meth_var_types);
3074       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
3075 
3076       /* Set alignment.  */
3077       val = DECL_ALIGN_UNIT (field_decl);
3078       val = exact_log2 (val);
3079       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3080 			      build_int_cst (integer_type_node, val));
3081 
3082       /* Set size.  */
3083       val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
3084       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3085 			      build_int_cst (integer_type_node, val));
3086 
3087       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3088 			      objc_build_constructor (type, ivar));
3089 
3090       do
3091 	field_decl = DECL_CHAIN (field_decl);
3092       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
3093     }
3094   while (field_decl);
3095 
3096   return objc_build_constructor (build_array_type (type, 0), inits);
3097 }
3098 
3099 /*
3100   struct ivar_list_t
3101   {
3102     uint32 entsize;
3103     uint32 count;
3104     struct iver_t list[count];
3105   };
3106 */
3107 
3108 static tree
build_v2_ivar_list_t_template(tree list_type,int size)3109 build_v2_ivar_list_t_template (tree list_type, int size)
3110 {
3111   tree objc_ivar_list_record;
3112   tree decls, *chain = NULL;
3113 
3114   /* Anonymous.  */
3115   objc_ivar_list_record = objc_start_struct (NULL_TREE);
3116 
3117   /* uint32 entsize; */
3118   decls = add_field_decl (integer_type_node, "entsize", &chain);
3119 
3120   /* uint32 count; */
3121   add_field_decl (integer_type_node, "count", &chain);
3122 
3123   /* struct objc_ivar ivar_list[]; */
3124   add_field_decl (build_sized_array_type (list_type, size),
3125 			  "list", &chain);
3126 
3127   objc_finish_struct (objc_ivar_list_record, decls);
3128   return objc_ivar_list_record;
3129 }
3130 
3131 /* This routine declares a static variable of type 'struct
3132    ivar_list_t' and initializes it.  chain is the source of the data,
3133    name is the name for the var.  attr is the meta-data section tag
3134    attribute.  templ is the implementation template for the class.  */
3135 
3136 static tree
generate_v2_ivars_list(tree chain,const char * name,tree attr,tree templ)3137 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
3138 {
3139   tree decl, initlist, ivar_list_template;
3140   vec<constructor_elt, va_gc> *inits = NULL;
3141   int size, ivar_t_size;
3142 
3143   if (!chain || !name || !(size = ivar_list_length (chain)))
3144     return NULL_TREE;
3145 
3146   generating_instance_variables = 1;
3147   ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
3148 						      size);
3149 
3150   initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
3151 					     objc_v2_ivar_template, chain);
3152   ivar_t_size = TREE_INT_CST_LOW  (TYPE_SIZE_UNIT (objc_v2_ivar_template));
3153 
3154   decl = start_var_decl (ivar_list_template, name);
3155   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3156 			  build_int_cst (integer_type_node, ivar_t_size));
3157   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3158 			  build_int_cst (integer_type_node, size));
3159   CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
3160   OBJCMETA (decl, objc_meta, attr);
3161   finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
3162   generating_instance_variables = 0;
3163   return decl;
3164 }
3165 
3166 /* Routine to build initializer list to initialize objects of type
3167    struct class_t; */
3168 
3169 static tree
build_v2_class_t_initializer(tree type,tree isa,tree superclass,tree ro,tree cache,tree vtable)3170 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
3171 			      tree ro, tree cache, tree vtable)
3172 {
3173   vec<constructor_elt, va_gc> *initlist = NULL;
3174 
3175   /* isa */
3176   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
3177 
3178   /* superclass */
3179   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
3180 
3181   /* cache */
3182   if (cache)
3183     CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
3184   else
3185     CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3186 
3187   /* vtable */
3188   if (vtable)
3189     CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
3190   else
3191     CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3192 
3193   /* ro */
3194   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
3195 
3196   return objc_build_constructor (type, initlist);
3197 }
3198 
3199 /* Routine to build object of struct class_ro_t { ... }; */
3200 
3201 static tree
build_v2_class_ro_t_initializer(tree type,tree name,unsigned int flags,unsigned int instanceStart,unsigned int instanceSize,tree ivarLayout,tree baseMethods,tree baseProtocols,tree ivars,tree property_list)3202 build_v2_class_ro_t_initializer (tree type, tree name,
3203 			       unsigned int flags, unsigned int instanceStart,
3204 			       unsigned int instanceSize,
3205 			       tree ivarLayout,
3206 			       tree baseMethods, tree baseProtocols,
3207 			       tree ivars, tree property_list)
3208 {
3209   tree expr, unsigned_char_star, ltyp;
3210   location_t loc;
3211   vec<constructor_elt, va_gc> *initlist = NULL;
3212 
3213   /* TODO: fish out the real location from somewhere.  */
3214   loc = UNKNOWN_LOCATION;
3215 
3216   /* flags */
3217   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3218 			  build_int_cst (integer_type_node, flags));
3219 
3220   /* instanceStart */
3221   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3222 			  build_int_cst (integer_type_node, instanceStart));
3223 
3224   /* instanceSize */
3225   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3226 			  build_int_cst (integer_type_node, instanceSize));
3227 
3228   /* This ABI is currently only used on m64 NeXT.  We always
3229      explicitly declare the alignment padding.  */
3230   /* reserved, pads alignment.  */
3231   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3232 			    build_int_cst (integer_type_node, 0));
3233 
3234   /* ivarLayout */
3235   unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3236   if (ivarLayout)
3237     expr = ivarLayout;
3238   else
3239     expr = convert (unsigned_char_star, null_pointer_node);
3240   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3241 
3242   /* name */
3243   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3244 
3245   /* baseMethods */
3246   ltyp = objc_method_list_ptr;
3247   if (baseMethods)
3248     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3249   else
3250     expr = convert (ltyp, null_pointer_node);
3251   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3252 
3253   /* baseProtocols */
3254   ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3255 			               get_identifier (UTAG_V2_PROTOCOL_LIST)));
3256   if (baseProtocols)
3257     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3258   else
3259     expr = convert (ltyp, null_pointer_node);
3260   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3261 
3262   /* ivars */
3263   ltyp = objc_v2_ivar_list_ptr;
3264   if (ivars)
3265     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3266   else
3267     expr = convert (ltyp, null_pointer_node);
3268   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3269 
3270   /* TODO: We don't yet have the weak/strong stuff...  */
3271   /* weakIvarLayout */
3272   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3273 			  convert (unsigned_char_star, null_pointer_node));
3274 
3275   /* property list */
3276   ltyp = objc_prop_list_ptr;
3277   if (property_list)
3278     expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3279   else
3280     expr = convert (ltyp, null_pointer_node);
3281   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3282   return objc_build_constructor (type, initlist);
3283 }
3284 
3285 static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
3286 
3287 /* Record a name as needing a catcher.  */
3288 static void
objc_v2_add_to_ehtype_list(tree name)3289 objc_v2_add_to_ehtype_list (tree name)
3290 {
3291   ident_data_tuple e;
3292   if (ehtype_list)
3293     {
3294       int count = 0;
3295       ident_data_tuple *ref;
3296 
3297       FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3298 	if (ref->ident == name)
3299 	  return; /* Already entered.  */
3300      }
3301   else
3302     /* Arbitrary initial count.  */
3303     vec_alloc (ehtype_list, 8);
3304 
3305   /* Not found, or new list.  */
3306   e.ident = name;
3307   e.data = NULL_TREE;
3308   vec_safe_push (ehtype_list, e);
3309 }
3310 
3311 static void
generate_v2_class_structs(struct imp_entry * impent)3312 generate_v2_class_structs (struct imp_entry *impent)
3313 {
3314   tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3315   tree field, firstIvar, chain;
3316   tree class_superclass_expr, metaclass_superclass_expr, props;
3317   /* TODO: figure out how to compute this.  */
3318   tree ivarLayout = NULL_TREE;
3319   tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3320   tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3321   tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3322   location_t loc;
3323   char buf[BUFSIZE];
3324   unsigned int instanceStart, instanceSize;
3325   unsigned int flags = 0x01; /* RO_META */
3326   int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3327 					 : 0 ;
3328 
3329   class_decl = impent->class_decl;
3330   metaclass_decl = impent->meta_decl;
3331   loc = DECL_SOURCE_LOCATION (class_decl);
3332 
3333   DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3334   TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3335 #ifdef OBJCPLUS
3336   gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3337   gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3338 #endif
3339 
3340   /* Generation of data for meta class.  */
3341   my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3342   if (my_super_id)
3343     {
3344       /* Compute reference to root's name.  For a meta class, "isa" is
3345 	 a reference to the root class name. */
3346       tree my_root_id = my_super_id;
3347       tree my_root_int, interface;
3348       do
3349         {
3350           my_root_int = lookup_interface (my_root_id);
3351 
3352           if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3353             my_root_id = CLASS_SUPER_NAME (my_root_int);
3354           else
3355             break;
3356         }
3357       while (1);
3358 
3359       /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3360          create extern if not already declared.  */
3361       snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3362 		IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3363       root_expr = create_extern_decl (objc_v2_class_template, buf);
3364       root_expr = build_fold_addr_expr (root_expr);
3365 
3366       /* Install class `isa' and `super' pointers at runtime.  */
3367       interface = lookup_interface (my_super_id);
3368       gcc_assert (interface);
3369       /* Similarly, for OBJC_CLASS_$_<interface>...  */
3370       snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3371 		IDENTIFIER_POINTER (CLASS_NAME (interface)));
3372       class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3373       class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3374       /* ... and for OBJC_METACLASS_$_<interface>.  */
3375       snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3376 		IDENTIFIER_POINTER (CLASS_NAME (interface)));
3377       metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3378       metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3379     }
3380   else
3381     {
3382       /* Root class.  */
3383       root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3384       metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3385       class_superclass_expr = build_int_cst (NULL_TREE, 0);
3386       flags |= 0x02; /* RO_ROOT: it is also a root meta class.  */
3387     }
3388 
3389   if (CLASS_PROTOCOL_LIST (impent->imp_template))
3390     {
3391       generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3392       protocol_decl = generate_v2_protocol_list (impent->imp_template,
3393 						 impent->imp_context);
3394     }
3395   else
3396     protocol_decl = 0;
3397 
3398   name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3399                                class_names);
3400 
3401   if (CLASS_CLS_METHODS (impent->imp_context))
3402     {
3403       snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3404 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3405       class_methods =
3406 	generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3407 				    buf, meta_clac_meth);
3408     }
3409 
3410   instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3411 
3412   /* Currently there are no class ivars and generation of class
3413      variables for the root of the inheritance has been removed.  It
3414      causes multiple defines if there are two root classes in the
3415      link, because each will define its own identically-named offset
3416      variable.  */
3417 
3418   class_ivars = NULL_TREE;
3419   /* TODO: Add total size of class variables when implemented. */
3420   instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3421 
3422   /* So now build the META CLASS structs.  */
3423   /* static struct class_ro_t  _OBJC_METACLASS_Foo = { ... }; */
3424 
3425   decl = start_var_decl (objc_v2_class_ro_template,
3426 			 newabi_append_ro (IDENTIFIER_POINTER
3427 						(DECL_NAME (metaclass_decl))));
3428 
3429   /* TODO: ivarLayout needs t be built.  */
3430   initlist =
3431 	build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3432 					(flags | cls_flags), instanceStart,
3433 					instanceSize, ivarLayout,
3434 					class_methods, protocol_decl,
3435 					class_ivars, NULL_TREE);
3436   /* The ROs sit in the default const section.  */
3437   OBJCMETA (decl, objc_meta, meta_base);
3438   finish_var_decl (decl, initlist);
3439 
3440   /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3441   initlist =
3442 	build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3443 				      root_expr,
3444 				      metaclass_superclass_expr,
3445 				      build_fold_addr_expr (decl),
3446 				      build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3447 				      build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3448   /* The class section attributes are set when they are created.  */
3449   finish_var_decl (metaclass_decl, initlist);
3450   impent->meta_decl = metaclass_decl;
3451 
3452   /* So now build the CLASS structs.  */
3453 
3454   flags = 0x0;		/* ... */
3455   if (!my_super_id)
3456     flags |= 0x02;	/* RO_ROOT: this is a root class */
3457 
3458   if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3459     flags |= 0x10;	/* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3460 
3461   if (objc2_objc_exception_attr (impent->imp_template))
3462     flags |= 0x20;	/* RO_EXCEPTION */
3463 
3464   if (CLASS_NST_METHODS (impent->imp_context))
3465     {
3466       snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3467 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3468       inst_methods =
3469 	generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3470 				    buf, meta_clai_meth);
3471     }
3472 
3473   /* Sort out the ivars before we try to compute the class sizes.  */
3474   if ((chain = CLASS_IVARS (impent->imp_template)))
3475     {
3476       snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3477 		IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3478       inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3479 					   impent->imp_template);
3480     }
3481 
3482   /* Compute instanceStart.  */
3483   gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3484   field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3485   if (my_super_id && field && TREE_CHAIN (field))
3486     field = TREE_CHAIN (field);
3487 
3488   firstIvar = field;
3489 
3490   while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3491     firstIvar = TREE_CHAIN (firstIvar);
3492 
3493   gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3494 
3495   /* Compute instanceSize.  */
3496   while (field && TREE_CHAIN (field)
3497          && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3498     field = TREE_CHAIN (field);
3499 
3500   if (field && TREE_CODE (field) == FIELD_DECL)
3501     instanceSize = int_byte_position (field) * BITS_PER_UNIT
3502 		   + tree_to_shwi (DECL_SIZE (field));
3503   else
3504     instanceSize = 0;
3505   instanceSize /= BITS_PER_UNIT;
3506 
3507   props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3508 
3509   /* If the class has no ivars, instanceStart should be set to the
3510      superclass's instanceSize.  */
3511   instanceStart =
3512 	(inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3513 				  : instanceSize;
3514 
3515   /* static struct class_ro_t  _OBJC_CLASS_Foo = { ... }; */
3516   decl = start_var_decl (objc_v2_class_ro_template,
3517 			 newabi_append_ro (IDENTIFIER_POINTER
3518 						(DECL_NAME (class_decl))));
3519 
3520   initlist =
3521 	build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3522 					 (flags | cls_flags), instanceStart,
3523 					 instanceSize, ivarLayout,
3524 					 inst_methods, protocol_decl,
3525 					 inst_ivars, props);
3526   /* The ROs sit in the default const section.  */
3527   OBJCMETA (decl, objc_meta, meta_base);
3528   finish_var_decl (decl, initlist);
3529 
3530   /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3531   initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3532 					build_fold_addr_expr (metaclass_decl),
3533 					class_superclass_expr,
3534 					build_fold_addr_expr (decl),
3535 					build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3536 					build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3537 
3538   /* The class section attributes are set when they are created.  */
3539   finish_var_decl (class_decl, initlist);
3540   impent->class_decl = class_decl;
3541 
3542   objc_v2_add_to_class_list (class_decl);
3543   if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3544     objc_v2_add_to_nonlazy_class_list (class_decl);
3545 
3546   if (flags & 0x20) /* RO_EXCEPTION */
3547     objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3548 }
3549 
3550 /* This routine outputs the (ivar_reference_offset, offset)
3551    tuples.  */
3552 
3553 static void
build_v2_ivar_offset_ref_table(void)3554 build_v2_ivar_offset_ref_table (void)
3555 {
3556   int count;
3557   ivarref_entry *ref;
3558 
3559   if (!vec_safe_length (ivar_offset_refs))
3560     return;
3561 
3562   FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3563     finish_var_decl (ref->decl, ref->offset);
3564 }
3565 
3566 static void
objc_generate_v2_next_metadata(void)3567 objc_generate_v2_next_metadata (void)
3568 {
3569   struct imp_entry *impent;
3570 
3571   /* FIXME: Make sure that we generate no metadata if there is nothing
3572      to put into it.  */
3573 
3574   gcc_assert (!objc_static_instances); /* Not for NeXT */
3575 
3576   build_metadata_templates ();
3577 
3578   for (impent = imp_list; impent; impent = impent->next)
3579     {
3580       /* If -gen-decls is present, Dump the @interface of each class.
3581 	 TODO: Dump the classes in the order they were found, rather
3582 	 than in reverse order as we are doing now.  */
3583       if (flag_gen_declaration)
3584 	dump_interface (gen_declaration_file, impent->imp_context);
3585 
3586       /* all of the following reference the string pool...  */
3587       if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3588 	generate_v2_class_structs (impent);
3589       else
3590 	generate_v2_category (impent);
3591     }
3592 
3593   build_next_selector_translation_table ();
3594   build_v2_message_ref_translation_table ();
3595 
3596   /* This will add "Protocol" to the class refs.  */
3597   generate_v2_protocols ();
3598 
3599   build_v2_classrefs_table ();
3600   build_v2_super_classrefs_table (/*metaclass= */false);
3601   build_v2_super_classrefs_table (/*metaclass= */true);
3602 
3603   build_v2_ivar_offset_ref_table ();
3604 
3605   build_v2_protocol_list_translation_table ();
3606   build_v2_protocol_list_address_table ();
3607 
3608   build_v2_address_table (class_list, "_OBJC_ClassList$",
3609 			  meta_label_classlist);
3610   build_v2_address_table (category_list, "_OBJC_CategoryList$",
3611 			  meta_label_categorylist);
3612   build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3613 			  meta_label_nonlazy_classlist);
3614   build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3615 			  meta_label_nonlazy_categorylist);
3616 
3617   /* Generate catch objects for eh, if any are needed.  */
3618   build_v2_eh_catch_objects ();
3619 
3620   /* Emit the string table last.  */
3621   generate_strings ();
3622 }
3623 
3624 /* NOTE --- Output NeXT V2 Exceptions --- */
3625 
3626 static GTY(()) tree objc_v2_ehtype_template;
3627 static GTY(()) tree next_v2_ehvtable_decl;
3628 static GTY(()) tree next_v2_EHTYPE_id_decl;
3629 
3630 static void
build_v2_ehtype_template(void)3631 build_v2_ehtype_template (void)
3632 {
3633   tree decls, *chain = NULL;
3634   objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3635 
3636   /* void *_objc_ehtype_vtable; */
3637   decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3638 
3639   /* const char *className; */
3640   add_field_decl (string_type_node, "className", &chain);
3641 
3642   /* struct class_t *const cls; */
3643   add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3644 
3645   objc_finish_struct (objc_v2_ehtype_template, decls);
3646 }
3647 
3648 /* Template for the Objective-C family typeinfo type for ABI=2.  This
3649    starts off the same as the gxx/cxx eh typeinfo.
3650 
3651    struct _objc_ehtype_t
3652    {
3653      void *_objc_ehtype_vtable_ptr;	- as per c++
3654      const char *className;		- as per c++
3655      struct class_t *const cls;
3656    }
3657 */
3658 
3659 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3660 */
3661 
3662 static tree
objc2_build_ehtype_initializer(tree name,tree cls)3663 objc2_build_ehtype_initializer (tree name, tree cls)
3664 {
3665   vec<constructor_elt, va_gc> *initlist = NULL;
3666   tree addr, offs;
3667 
3668   /* This is done the same way as c++, missing the two first entries
3669      in the parent vtable.  NOTE: there is a fix-me in the Apple/NeXT
3670      runtime source about this so, perhaps, this will change at some
3671      point.  */
3672   /* _objc_ehtype_vtable + 2*sizeof(void*)  */
3673   if (!next_v2_ehvtable_decl)
3674     {
3675       next_v2_ehvtable_decl =
3676 			start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3677       TREE_STATIC (next_v2_ehvtable_decl) = 0;
3678       DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3679       TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3680     }
3681   addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3682   offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3683   addr = fold_build_pointer_plus (addr, offs);
3684 
3685   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3686 
3687   /* className */
3688   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3689 
3690   /* cls */
3691   CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3692 
3693   return objc_build_constructor (objc_v2_ehtype_template, initlist);
3694 }
3695 
3696 static tree
build_ehtype(tree name,const char * eh_name,bool weak)3697 build_ehtype (tree name, const char *eh_name, bool weak)
3698 {
3699   tree name_expr, class_name_expr, ehtype_decl, inits;
3700 
3701   name_expr = add_objc_string (name, class_names);
3702   /* Extern ref. for the class. ???  Maybe we can look this up
3703      somewhere.  */
3704   class_name_expr =
3705 	create_extern_decl (objc_v2_class_template,
3706 			    objc_build_internal_classname (name, false));
3707   class_name_expr = build_fold_addr_expr (class_name_expr);
3708   ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3709   if (weak)
3710     DECL_WEAK (ehtype_decl) = 1;
3711   inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3712   OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3713   finish_var_decl (ehtype_decl, inits);
3714   return ehtype_decl;
3715 }
3716 
3717 /* This routine returns TRUE if CLS or any of its super classes has
3718    __attribute__ ((objc_exception)).  */
3719 
3720 static bool
objc2_objc_exception_attr(tree cls)3721 objc2_objc_exception_attr (tree cls)
3722 {
3723   while (cls)
3724     {
3725       if (CLASS_HAS_EXCEPTION_ATTR (cls))
3726 	return true;
3727       cls = lookup_interface (CLASS_SUPER_NAME (cls));
3728     }
3729 
3730   return false;
3731 }
3732 
3733 static bool
is_implemented(tree name)3734 is_implemented (tree name)
3735 {
3736   struct imp_entry *t;
3737   for (t = imp_list; t; t = t->next)
3738     if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3739 	&& CLASS_NAME (t->imp_template) == name)
3740       return true;
3741 
3742   return false;
3743 }
3744 
3745 /* We will build catch objects:
3746      for any type  implemented here.
3747      for any type used in a catch that has no exception attribute.  */
build_v2_eh_catch_objects(void)3748 static void build_v2_eh_catch_objects (void)
3749 {
3750   int count=0;
3751   ident_data_tuple *ref;
3752 
3753   if (!vec_safe_length (ehtype_list))
3754     return;
3755 
3756   FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3757     {
3758       char buf[BUFSIZE];
3759       bool impl = is_implemented (ref->ident);
3760       bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3761       snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3762       if (!impl && excpt)
3763 	/* The User says this class has a catcher already.  */
3764 	ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3765       else
3766 	/* Create a catcher, weak if it wasn't marked.  */
3767 	ref->data = build_ehtype (ref->ident, buf, !excpt);
3768     }
3769 }
3770 
3771 static tree
lookup_ehtype_ref(tree id)3772 lookup_ehtype_ref (tree id)
3773 {
3774   int count=0;
3775   ident_data_tuple *ref;
3776 
3777   if (!vec_safe_length (ehtype_list))
3778     return NULL_TREE;
3779 
3780   FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3781     if (ref->ident == id)
3782       return ref->data;
3783   return NULL_TREE;
3784 }
3785 
3786 /* This hook, called via lang_eh_runtime_type, generates a runtime
3787    object which is either the address of the 'OBJC_EHTYPE_$_class'
3788    object or address of external OBJC_EHTYPE_id object.  */
3789 static tree
next_runtime_02_eh_type(tree type)3790 next_runtime_02_eh_type (tree type)
3791 {
3792   tree t;
3793 
3794   if (type == error_mark_node
3795       /*|| errorcount || sorrycount*/)
3796     goto err_mark_in;
3797 
3798   if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3799     {
3800       if (!next_v2_EHTYPE_id_decl)
3801 	{
3802 	  /* This is provided by the Apple/NeXT libobjc.dylib so we
3803 	     need only to reference it.  */
3804 	  next_v2_EHTYPE_id_decl =
3805 		start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3806 	  DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3807 	  TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3808 	  TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3809 	}
3810       return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3811     }
3812 
3813   if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3814     {
3815 #ifdef OBJCPLUS
3816       /* This routine is also called for c++'s catch clause; in which
3817 	 case, we use c++'s typeinfo decl.  */
3818       return build_eh_type_type (type);
3819 #else
3820       error ("non-objective-c type %qT cannot be caught", type);
3821       goto err_mark_in;
3822 #endif
3823     }
3824   else
3825     t = OBJC_TYPE_NAME (TREE_TYPE (type));
3826 
3827   /* We have to build a reference to the OBJC_EHTYPE_<Class>.  */
3828   t = lookup_ehtype_ref (t);
3829   if (!t)
3830     goto err_mark_in;
3831 
3832   return build_fold_addr_expr (t);
3833 
3834 err_mark_in:
3835   return error_mark_node;
3836 }
3837 
3838 static GTY(()) tree objc_eh_personality_decl;
3839 
3840 static tree
objc_eh_personality(void)3841 objc_eh_personality (void)
3842 {
3843   if (!objc_eh_personality_decl)
3844     objc_eh_personality_decl = build_personality_function  ("objc");
3845   return objc_eh_personality_decl;
3846 }
3847 
3848 /* NOTE --- interfaces --- */
3849 
3850 static tree
build_throw_stmt(location_t loc,tree throw_expr,bool rethrown)3851 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3852 {
3853   tree t;
3854   if (rethrown)
3855     /* We have a separate re-throw entry.  */
3856     t = build_function_call_vec (loc, vNULL, objc_rethrow_exception_decl,
3857 				 NULL, NULL);
3858   else
3859     {
3860       /* Throw like the others...  */
3861       vec<tree, va_gc> *parms;
3862       vec_alloc (parms, 1);
3863       parms->quick_push (throw_expr);
3864       t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl,
3865 				   parms, 0);
3866       vec_free (parms);
3867     }
3868   return add_stmt (t);
3869 }
3870 
3871 /* Build __builtin_eh_pointer.  */
3872 
3873 static tree
objc_build_exc_ptr(struct objc_try_context ** x ATTRIBUTE_UNUSED)3874 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3875 {
3876   tree t;
3877   t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3878   t = build_call_expr (t, 1, integer_zero_node);
3879   return fold_convert (objc_object_type, t);
3880 }
3881 
begin_catch(struct objc_try_context ** cur_try_context,tree type,tree decl,tree compound,bool ellipsis ATTRIBUTE_UNUSED)3882 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3883 			 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3884 {
3885   tree t;
3886 
3887   /* Record the data for the catch in the try context so that we can
3888      finalize it later.  Ellipsis is signalled by a NULL entry.  */
3889   if (ellipsis)
3890     t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3891   else
3892     t = build_stmt (input_location, CATCH_EXPR, type, compound);
3893   (*cur_try_context)->current_catch = t;
3894 
3895   /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
3896   t = objc_build_exc_ptr (cur_try_context);
3897   t = convert (TREE_TYPE (decl), t);
3898   /* FIXME: location.  */
3899   if (type && type != error_mark_node)
3900     {
3901       t = build1(NOP_EXPR, ptr_type_node, t);
3902       t = build_function_call (input_location, objc2_begin_catch_decl,
3903 			      tree_cons (NULL_TREE, t, NULL_TREE));
3904 
3905       /* We might want to build a catch object for this (if it's not
3906 	 id).  */
3907       if (POINTER_TYPE_P (type)
3908 	  && !objc_is_object_id (TREE_TYPE (type))
3909 	  && TYPED_OBJECT (TREE_TYPE (type)))
3910 	objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3911     }
3912   return build2 (MODIFY_EXPR, void_type_node, decl, t);
3913 }
3914 
3915 /* try { catch-body } finally { objc_end_catch (); } */
3916 static void
finish_catch(struct objc_try_context ** cur_try_context,tree curr_catch)3917 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3918 {
3919   struct objc_try_context *ct;
3920   tree try_exp, func, *l, t ;
3921   location_t loc = (*cur_try_context)->try_locus;
3922 
3923   if (!curr_catch || curr_catch == error_mark_node)
3924     return;
3925 
3926   t = CATCH_BODY (curr_catch);
3927   if (TREE_CODE (t) == BIND_EXPR)
3928     {
3929       /* Usual case of @catch (objc-expr).  */
3930       objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3931       BIND_EXPR_BODY (t) = NULL_TREE;
3932       l = &BIND_EXPR_BODY (t);
3933     }
3934   else
3935     {
3936       /* NULL entry, meaning @catch (...).  */
3937       objc_begin_try_stmt (loc, t);
3938       CATCH_BODY (curr_catch) = NULL_TREE;
3939       l = &CATCH_BODY (curr_catch);
3940     }
3941 
3942   /* Pick up the new context we made in begin_try above...  */
3943   ct = *cur_try_context;
3944   func = build_function_call_vec (loc, vNULL, objc2_end_catch_decl, NULL,
3945 				  NULL);
3946   append_to_statement_list (func, &ct->finally_body);
3947   try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3948   *cur_try_context = ct->outer;
3949   free (ct);
3950   append_to_statement_list (try_exp, l);
3951   append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3952 }
3953 
3954 static tree
finish_try_stmt(struct objc_try_context ** cur_try_context)3955 finish_try_stmt (struct objc_try_context **cur_try_context)
3956 {
3957   struct objc_try_context *c = *cur_try_context;
3958   tree stmt = c->try_body;
3959   if (c->catch_list)
3960     stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3961   if (c->finally_body)
3962     stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3963   return stmt;
3964 }
3965 
3966 #include "gt-objc-objc-next-runtime-abi-02.h"
3967