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