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