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