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